[LLVMdev] BasicAliasAnalysis: constant does not alias with noalias parameter
Nick Lewycky
nicholas at mxc.ca
Thu Nov 12 20:16:48 PST 2009
Hans Wennborg wrote:
> After discussing with Nick Lewycky in the IRC channel, here comes a less
> aggressive patch.
>
> We were worried that a constant pointer could alias with a GlobalValue.
> Also, if one pointer could be a GlobalValue and the other a GlobalAlias
> with the GlobalValue as aliasee.
> However, I was not able to produce a test where this happens wihout the
> getUnderlyingObject() returning the same value.
>
> It would be nice if someone could produce such a test case, or dismiss
> the possibility of this happening.
My bad, it seems that while I wasn't looking, someone taught
getUnderlyingObject to look through GlobalAliases and return what they
point to!
However the previous patch was wrong given code like:
@gv = global i32 0
define void @test() {
store i16 1, i16* inttoptr(i64 add(i64 ptrtoint(i32* @gv to i64),
i64 1) to i16*) ; ; Not dead
store i32 2, i32* @gv
ret void
}
> Anyway, saying that a Constant does not alias with a non-const
> isIdentifiedObject object seems safe.
Yup!
Please remove the tailing ; on the lines where they aren't needed in
your tests. Besides that, your patch looks great! Thanks!
Nick
> / Hans
>
>
> Hans Wennborg wrote:
>> Dan Gohman wrote:
>>> On Nov 4, 2009, at 6:43 AM, Hans Wennborg wrote:
>>>
>>>> Here is another change I'd like to suggest to the BasicAliasAnalysis.
>>>>
>>>> LLVM fails to remove the dead store in the following code:
>>>>
>>>> %t = type { i32 }
>>>>
>>>> define void @f(%t* noalias nocapture %stuff ) {
>>>> %p = getelementptr inbounds %t* %stuff, i32 0, i32 0
>>>>
>>>> store i32 1, i32* %p; <-- This store is dead
>>>>
>>>> %x = load i32* inttoptr (i32 12345 to i32*)
>>>> store i32 %x, i32* %p
>>>> ret void
>>>> }
>>>>
>>>>
>>>> when run through
>>>> ./llvm-as -o - test2.ll | ./opt -O3 -o - | ./llvm-dis -o -
>>>>
>>>>
>>>> The problem is that the alias analysis is unsure about whether %p
>>>> and 12345 may alias. But since %p is derived from %stuff, which has
>>>> the noalias attribute, and 12345 is a constant and therefore cannot
>>>> be derived from %stuff, they cannot alias.
>>>
>>> This sounds right. And actually, it's not limited to noalias;
>>> isIdentifiedObject objects don't alias inttoptr-casted integer
>>> literals either. I have a few comments on the patch below.
>>>
>>>> I'm attaching a patch which implements this. Please comment on
>>>> whether this is sane, and if my code is the right way of doing it.
>>>>
>>>>
>>>> / Hans
>>>> Index: lib/Analysis/BasicAliasAnalysis.cpp
>>>> ===================================================================
>>>> --- lib/Analysis/BasicAliasAnalysis.cpp (revision 86023)
>>>> +++ lib/Analysis/BasicAliasAnalysis.cpp (working copy)
>>>> @@ -643,6 +643,23 @@
>>>> if (!isa<PointerType>(V1->getType()) ||
>>>> !isa<PointerType>(V2->getType()))
>>>> return NoAlias; // Scalars cannot alias each other
>>>>
>>>> + // Constant ptr cannot alias with a noalias attribute
>>>> + if (isa<Constant>(V1) && isa<PointerType>(V2->getType())) {
>>>> + while (const GEPOperator *g = dyn_cast<GEPOperator>(V2))
>>>> + V2 = g->getOperand(0);
>>>> +
>>>> + if (const Argument *A = dyn_cast<Argument>(V2))
>>>> + if (A->hasNoAliasAttr())
>>>> + return NoAlias;
>>>> + } else if (isa<Constant>(V2) && isa<PointerType>(V1->getType())) {
>>>> + while (const GEPOperator *g = dyn_cast<GEPOperator>(V1))
>>>> + V1 = g->getOperand(0);
>>>> +
>>>> + if (const Argument *A = dyn_cast<Argument>(V1))
>>>> + if (A->hasNoAliasAttr())
>>>> + return NoAlias;
>>>> + }
>>>
>>> The GEP logic here is effectively doing (a subset of) what
>>> getUnderlyingObject does. It would be better to move these checks
>>> below the getUnderlyingObject calls just below so that they can
>>> use the results from those calls instead.
>>>
>>> And instead of checking for a no-alias argument, this code could
>>> use isIdentifiedObject instead, following my comment above.
>>
>> Thank you for the input, this certainly made things nicer. I have
>> attached a patch that does this together with a test case.
>>
>> / Hans
>>
>>>
>>> Dan
>>>
>>>> // Figure out what objects these things are pointing to if we can.
>>>> const Value *O1 = V1->getUnderlyingObject();
>>>> const Value *O2 = V2->getUnderlyingObject();
>>>> _______________________________________________
>>>> LLVM Developers mailing list
>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list