[LLVMdev] GVN incorrectly handling readnone parameter attribute?
Nick Lewycky
nlewycky at google.com
Thu May 29 19:45:15 PDT 2014
On 21 May 2014 13:40, Robert Lougher <rob.lougher at gmail.com> wrote:
> Hi,
>
> I'm investigating a bug which I have so far been able to narrow down
> to the following small testcase:
>
> ======== test.c ===========
>
> int *get_pntr(int *p) {
> return p;
> }
>
> __attribute__((noinline))
> void store(int *p) {
> int *p2 = get_pntr(p);
> *p2 = 10;
> }
>
> int test() {
> int i;
> store(&i);
> return i;
> }
> -----------------------------
>
> If this is compiled in two steps as follows:
>
> clang -O1 -emit-llvm test.c -c -o test.bc
> opt -basicaa -inline -functionattrs -gvn -S test.bc
>
> We get the following IR:
>
> --------------------------------------------------
> define i32* @get_pntr(i32* readnone %p) {
> entry:
> ret i32* %p
> }
>
> define void @store(i32* nocapture readnone %p) {
> entry:
> store i32 10, i32* %p, align 4, !tbaa !1
> ret void
> }
>
> define i32 @test() {
> entry:
> %i = alloca i32, align 4
> call void @store(i32* %i)
> ret i32 undef
> }
> --------------------------------------------------
>
> As can be seen, the load of %i in test() has been eliminated, and we
> have an undefined return value.
>
As of revision 209870 we now get:
; Function Attrs: nounwind readnone uwtable
define i32* @get_pntr(i32* readnone %p) #0 {
entry:
ret i32* %p
}
; Function Attrs: noinline nounwind uwtable
define void @store(i32* nocapture %p) #1 {
entry:
store i32 10, i32* %p, align 4, !tbaa !1
ret void
}
; Function Attrs: nounwind uwtable
define i32 @test() #2 {
entry:
%i = alloca i32, align 4
call void @store(i32* %i)
%0 = load i32* %i, align 4, !tbaa !1
ret i32 %0
}
I think that's correct, let me know if there's another bug hiding in here.
Nick
Investigating this I can see that the load is removed by the GVN pass.
> It does this because it believes that the call to store() has no
> affect on %i, and as %i has just been allocated, the loaded value is
> undefined.
>
> The reason it believes that store() has no affect is because of
> store()'s parameter attributes. Argument %p doesn't escape
> (nocapture), and it doesn't access memory (readnone). So even though
> the call aliases the load, it believes it doesn't touch it (even
> though it clearly does).
>
> The nocapture attribute is added by the functionattrs pass (and is
> correct). The readnone attribute, however, is present from the first
> compilation step (clang -O1):
>
> --------------------------------------------------
> define i32* @get_pntr(i32* readnone %p) {
> entry:
> ret i32* %p
> }
>
> define void @store(i32* readnone %p) {
> entry:
> %call = tail call i32* @get_pntr(i32* %p)
> store i32 10, i32* %call, align 4, !tbaa !1
> ret void
> }
>
> define i32 @test() {
> entry:
> %i = alloca i32, align 4
> call void @store(i32* %i)
> %0 = load i32* %i, align 4, !tbaa !1
> ret i32 %0
> }
> --------------------------------------------------
>
> Looking at the definition of readnone in the LangRef we see:
>
> "On an argument, this attribute indicates that the function does not
> dereference that pointer argument, even though it may read or write
> the memory that the pointer points to if accessed through other
> pointers."
>
> So this appears to be correct. Argument %p is marked as readnone in
> both get_pntr() and store() as it is not read or written to. Store()
> does write to it via a copy of %p, but this is also OK according to
> the definition.
>
> So the problem appears to be within GVN. The assumption based on
> store()'s parameter attributes is incorrect, as the load can be
> affected through a different pointer.
>
> So before I try to fix GVN, my question is, am I on the right track?
> Specifically, is the definition in the LangRef correct?
>
> Thanks,
> Rob.
>
> P.S. GVN's checking of the attributes is done in
> AliasAnalysis::callCapturesBefore in lib/Analysis/AliasAnalysis.cpp
>
> --
> Robert Lougher
> SN Systems - Sony Computer Entertainment Group
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140529/a1e22269/attachment.html>
More information about the llvm-dev
mailing list