[llvm-commits] [PATCH] Fix llvm.invariant support

Dan Gohman gohman at apple.com
Mon Nov 29 11:20:55 PST 2010


On Nov 22, 2010, at 7:14 PM, Kenneth Uildriks wrote:

> Ping.
> 
> On Sat, Nov 13, 2010 at 7:00 PM, Kenneth Uildriks <kennethuil at gmail.com> wrote:
>> A less drastic attempt to fix issues with support for
>> llvm.invariant.start and llvm.invariant.end.  It involves adding
>> invariant tracking by block to MemoryDependenceAnalysis.  When a load
>> is analyzed, the invariant information for that block and its
>> predecessors is lazily computed and consulted.  If the load's target
>> is not invariant anywhere in the block, there is no need to look for
>> invariant markers during the scan.  If it is invariant throughout the
>> block, no def or clobber can be in that block, so we can skip
>> backwards to the block(s) that began the invariance.  If it is
>> invariant through part of the block, we need to continue scanning
>> backwards past clobbers until we find the def or an invariant marker -
>> we can't assume that the scan starts after the invariant end, but
>> instead assume that we *might* have started scanning in the middle of
>> an invariant region until we can prove otherwise.

How do @llvm.invariant.start and @llvm.invariant.end work?

There are at least two interesting situations.

First, is this valid?

define void @callee(i8* %p) {
 call void @llvm.invariant.end(i8* %p)
 ret void
}

If so, then any call can call @llvm.invariant.end on any pointer it has
access to, which substantially weakens what MemDep can do. If not, then
it seems to violate high-level IR design principles -- it should always
be valid to out-line code regions.

Next, what about this?

  %a = alloca i32
  %b = bitcast i32* %a to i8*
  %c = call {}* @llvm.invariant.begin(i8* %b)
  %d = bitcast {}* %c to i8*
  call void @llvm.invariant.end(i8* %d)

If I read your patch correctly, it won't notice that the invariant
region for %b is ended here, because it's ended with a different
pointer. The results for subsequent getPointerDependencyFrom queries
will depend on which pointer happens to land first in the std::map.
Or did I miss something?

Here are a few specific comments on the patch:

> +  struct InvariantInfo {
> +    unsigned Size;

AliasAnalysis uses uint64_t for sizes now.

> +      else if (F->getName() == "llvm.invariant.start"

> +      else if (F->getName() == "llvm.invariant.end"

These should use F->getIntrinsicID().

> @@ -321,8 +367,11 @@
> 
>        if (R == AliasAnalysis::NoAlias)
>          continue;
> -      if (R == AliasAnalysis::MayAlias)
> -        return MemDepResult::getClobber(Inst);
> +      if (R == AliasAnalysis::MayAlias) {
> +        if (!InvariantInside)
> +          return MemDepResult::getClobber(Inst);
> +        MayBeClobbered = true;
> +      }
>        return MemDepResult::getDef(Inst);
>      }

It's not obvious what's happening here. If the pointer is
invariant inside the block, why is it marked MayBeClobbered?

And, a testcase demonstrating the basic functionality would
be helpful.

Dan






More information about the llvm-commits mailing list