[llvm-dev] load instruction erroneously removed by GVN

Mikael Holmén via llvm-dev llvm-dev at lists.llvm.org
Tue Aug 11 04:08:32 PDT 2015


I filed a TR for this problem:

https://llvm.org/bugs/show_bug.cgi?id=24426

/Mikael

On 08/10/2015 10:39 AM, Mikael Holmén via llvm-dev wrote:
> 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
>
> _______________________________________________
> 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