[llvm-dev] load instruction erroneously removed by GVN

Mikael Holmén via llvm-dev llvm-dev at lists.llvm.org
Mon Aug 10 01:39:56 PDT 2015


Hi again,

I've managed to reduce the code to make it easier to see what's going on.

So my input to opt is:

declare void @check(i8)

declare void @write(i8* %res)

define i8 @TEST1() {
   %buf = alloca [10 x i8]
   %_tmp30 = bitcast [10 x i8]* %buf to i8*

   call void @write(i8* %_tmp30)

   %_tmp33 = load i8, i8* %_tmp30
   call void @check(i8 %_tmp33)

   ret i8 0
}

and I run opt with
build-all/bin/opt -S -memcpyopt -mldst-motion -gvn -O3 ./f2.ll

and then the load is removed by GVN and %_tmp33 is replaced with undef.

GVN iteration: 0
GVN removed:   %_tmp33 = load i8, i8* %_tmp30


I notice that if I change TEST1 slightly, and rewrite it as

define i8 @TEST2() {
   %buf = alloca i8

   call void @write(i8* %buf)

   %_tmp33 = load i8, i8* %buf
   call void @check(i8 %_tmp33)

   ret i8 0
}

then the load is left intact

GVN iteration: 0
GVN: load i8 %_tmp33 is clobbered by   call void @write(i8* %buf.17)

In this case it seems to be the code

   if (llvm::PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true,
                                        /* StoreCaptures */ true, I, DT,
                                        /* include Object */ true,
                                        /* OrderedBasicBlock */ OBB))
     return MRI_ModRef;

in AliasAnalysis::callCapturesBefore that saves the load, which it 
doesn't in the first case.

Anything obvious that I'm doing wrong or should I write a bug report on 
this?
/Mikael


On 08/10/2015 08:30 AM, Mikael Holmén via llvm-dev wrote:
> Hi,
>
> On 08/07/2015 10:30 PM, Nick Lewycky wrote:
> [...]
>
>>         Depends.  What is the exact declaration of format_long?
>>
>>
>>     In the input .ll file it is:
>>
>>     ; Function Attrs: minsize optsize
>>     define internal i16 @format_long(i16* %res.8.par, i16 %base.9.par,
>>     i32 %x.10.par) #3 {
>>
>>     which is later changed somewhere in opt to:
>>
>>     ; Function Attrs: minsize nounwind optsize
>>     define internal fastcc i16 @format_long(i16* %res.8.par, i16
>>     %base.9.par, i32 %x.10.par) #2 {
>>
>>
>> That's part of it, but we also need to see what #3 and #2 refer to in
>> this context. Those should be grouped at the end of your .ll,
>> something like
>>
>> attributes #3 = { nobuiltin nounwind "less-precise-fpmad"="false"
>> "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"
>> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
>> "stack-protector-buffer-size"="8" "unsafe-fp-math"="false"
>> "use-soft-float"="false" }
>
> The attributes are
>
> attributes #3 = { minsize optsize "target-cpu"="phoenixIV" }
>
> and
>
> attributes #2 = { minsize nounwind optsize "target-cpu"="phoenixIV" }
>
> (I'm compiling for my out-of-tree target, thus the
> "target-cpu"="phoenixIV").
>
> So no readonly or readnone attributes.
>
> Thanks,
> Mikael
>
>>
>> or
>>
>> attributes #2 = { nounwind readonly }
>>
>> If @format_long is marked with the 'readonly' or 'readnone' attribute
>> then GVN would be justified in doing the transformation you've described.
>>
>> Nick
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org         http://llvm.cs.uiuc.edu
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



More information about the llvm-dev mailing list