setOnlyReadsMemory / setDoesNotAccessMemory

Hello,

I'm in a situation where my code is calling many native functions.
Sometimes, these calls are simply calls to static "accessor" methods that
read a variable in some class object (object pointer as input, member
variable value returned as output). I was wondering if using the
setOnlyReadsMemory method on the native function objects could help LLVM
generate optimized code (because it would then know the function has no side
effects), and say, eliminating redundant calls to the same accessor
function.

Also, I would like to know what setDoesNotAccessMemory means exactly. Is it
used to mean that a function accesses no memory (neither read nor write)
outside of its stack frame? I'm just puzzled as to the meaning of the flags
these two methods set on a function, and whether they are useful or not for
LLVM to perform optimizations (and if they are, what optimization pass makes
use of them).

Thank you for your help,

- Maxime

Nyx wrote:

Hello,

I'm in a situation where my code is calling many native functions.
Sometimes, these calls are simply calls to static "accessor" methods that
read a variable in some class object (object pointer as input, member
variable value returned as output). I was wondering if using the
setOnlyReadsMemory method on the native function objects could help LLVM
generate optimized code (because it would then know the function has no side
effects), and say, eliminating redundant calls to the same accessor
function.

Also, I would like to know what setDoesNotAccessMemory means exactly. Is it
used to mean that a function accesses no memory (neither read nor write)
outside of its stack frame? I'm just puzzled as to the meaning of the flags
these two methods set on a function, and whether they are useful or not for
LLVM to perform optimizations (and if they are, what optimization pass makes
use of them).
  
If you think of there being a "world" of state and recorded side-effects, a readnone
function completely ignores the world, whereas a readonly function can depend on
the current state of the world, but can't modify it. Calls to readnone functions are arbitrarily
re-orderable (and hence redundant calls can always be joined), but calls to readonly functions
can't be re-ordered around operations which might modify state.

The precise meaning of this is kindof up to you. If you only access immutable memory, that's
legitimate in a readnone function. If you allocate new memory, but your program's semantics
can't distinguish between separate allocations, that's legitimate, too.

Last time I checked, the optimizers don't consider the possibility of readonly/readnone
functions unwinding, and hence will happily eliminate calls to readonly/readnone functions,
even when they aren't marked nounwind. So if your function can unwind, don't mark it
readonly/readnone.

John.

But, which optimization pass will take advantage of those flags?

As for nounwind, that means "can't throw an exception"?

- Maxime

John McCall-2 wrote:

But, which optimization pass will take advantage of those flags?

GVN, DSE, misc passes which erase dead instructions, LICM,
instcombine, possibly some others.

As for nounwind, that means "can't throw an exception"?

Yes. It's orthogonal in theory, but readonly exception-throwing
methods are rare, so I think there are a few lurking bugs.

-Eli

Hi,

Last time I checked, the optimizers don't consider the possibility of readonly/readnone
functions unwinding, and hence will happily eliminate calls to readonly/readnone functions,
even when they aren't marked nounwind. So if your function can unwind, don't mark it
readonly/readnone.

the situation has improved in svn. For example, an unused call to a
readonly function is not be removed unless the function is also marked
nounwind.

Ciao,

Duncan.