Safe loads

Hello,

For the Glasgow Haskell Compiler's backend, we would like to let LLVM know
that certain loads are safe to execute speculatively and hence to hoist
out of loops. At the moment, there doesn't seem to be a mechanism for
doing so. There seem to be two ways of implementing this: either allow
arbitrary instructions to be marked as safe and have
Instruction::isSafeToSpeculativelyExecute return true for those or mark
memory regions and extend Value::isDereferenceablePointer to return true
for those. Is either of these a good idea? Or is there some other way to
do this? FWIW, I quickly prototyped instruction marking using metadata and
that seemed to work well enough for us.

Roman

I think that marking the load with metadata would make sense. Is it safe to load the pointer *anywhere*, or just "ahead of the loop"? If it is safe to move it anywhere (e.g. because it is a load from constant memory, the optimizer just doesn't know it) then using metadata makes sense. If it is a region where it is safe, then we'd need to implement something like this:
http://nondot.org/sabre/LLVMNotes/MemoryUseMarkers.txt

-Chris

BTW, we already have metadata for marking a load as invariant; see
http://llvm.org/docs/LangRef.html#tbaa .

-Eli

Hello,

For the Glasgow Haskell Compiler's backend, we would like to let LLVM know
that certain loads are safe to execute speculatively and hence to hoist
out of loops. At the moment, there doesn't seem to be a mechanism for
doing so. There seem to be two ways of implementing this: either allow
arbitrary instructions to be marked as safe and have
Instruction::isSafeToSpeculativelyExecute return true for those or mark
memory regions and extend Value::isDereferenceablePointer to return true
for those. Is either of these a good idea? Or is there some other way to
do this? FWIW, I quickly prototyped instruction marking using metadata and
that seemed to work well enough for us.

I think that marking the load with metadata would make sense. Is it safe to load the pointer *anywhere*, or just "ahead of the loop"? If it is safe to move it anywhere (e.g. because it is a load from constant memory, the optimizer just doesn't know it) then using metadata makes sense. If it is a region where it is safe, then we'd need to implement something like this:
http://nondot.org/sabre/LLVMNotes/MemoryUseMarkers.txt

Just for the case of something being from a constant location but the compiler not knowing this, you can attach the "invariant.load" metadata to a load which lets the load be hoisted out of a loop. This is only currently done on reads from runtime constant globals so the address of the load is known to be valid.

The clang commit to generate it is http://llvm.org/viewvc/llvm-project?view=rev&revision=144318
The llvm commit to use it is http://llvm.org/viewvc/llvm-project?view=rev&revision=144107

Pete

For the code that GHC generates, it is safe to load the pointer anywhere in the function that contains the load and those functions don't get inlined. But that's probably too specific to GHC, a general-purpose mechanism would make more sense.

I looked at llvm.lifetime.start before but it has two problems. Firstly, isDeferenceablePointer doesn't seem to take it into account so marking the memory block in question has no effect on the loads. Secondly, the memory block is quite alive when the function is entered and we definitely don't want to replace those loads with undefs. We'd want to be able to mark memory blocks as "alive here" rather than "alive from now on and dead before" and we'd want isDereferenceablePointer to use this information. Alas, this seems somewhat more difficult to implement for someone who has never done any LLVM hacking before.

Roman

That’s right. Invariance and lifetime are definitely distinct from safety/side effects. The currently proposed memory use markers don’t address the later, yet.

-Andy