Sanjoy Das via llvm-dev
2016-May-09 06:14 UTC
[llvm-dev] x.with.overflow semantics question
CGP also relies on the add being a simple two's complement add, since it will transform define void @test1(i64 %a, i64 %b, i64* %res_i64, i1* %res_i1) { entry: %add = add i64 %b, %a %cmp = icmp ult i64 %add, %a store i1 %cmp, i1* %res_i1 store i64 %add, i64* %res_i64 ret void } to define void @test1(i64 %a, i64 %b, i64* %res_i64, i1* %res_i1) { entry: %uadd.overflow = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %b, i64 %a) %uadd = extractvalue { i64, i1 } %uadd.overflow, 0 %overflow = extractvalue { i64, i1 } %uadd.overflow, 1 store i1 %overflow, i1* %res_i1 store i64 %uadd, i64* %res_i64 ret void } Now if we _know_ that the arithmetic result is used only if it does not overflow, then we can "pretend" that the arithmetic was nsw/nuw. This is what I tried to do in http://reviews.llvm.org/rL265912, but I had to back out the change due to an unrelated issue with SCEV. -- Sanjoy Nuno Lopes via llvm-dev wrote:>>> Or do you mean that the result of an add may not even be defined? In that case would reading it be considered UB in >>> the case where the overflow bit was set? >> >> Yeah, this is the case I'm worried about: that for example sadd.with.overflow(INT_MAX, 1) might be designed to return >> { poison, true } instead of giving a useful result in the first element of the struct. > > Any argument against that? I guess that would be the most natural definition given the motivation to have these > intrinsics (e.g., check if the 'nmemb * size' operation of calloc overflows; if so return null). > > InstCombine will remove these instrinsics if the overflow bit is unused, for example. AFAICT, InstCombine never adds > nsw/nuw to the replacements. I didn't check GVN. But I think they should unless there's some reason not to. > > Nuno > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
John Regehr via llvm-dev
2016-May-09 19:47 UTC
[llvm-dev] x.with.overflow semantics question
Ok, thanks folks. Sounds like it's clear that x.with.overflow performs two's complement operations. Should I patch the LangRef to be more explicit about this? John On 5/9/16 8:14 AM, Sanjoy Das wrote:> CGP also relies on the add being a simple two's complement add, since it > will transform > > define void @test1(i64 %a, i64 %b, i64* %res_i64, i1* %res_i1) { > entry: > %add = add i64 %b, %a > %cmp = icmp ult i64 %add, %a > store i1 %cmp, i1* %res_i1 > store i64 %add, i64* %res_i64 > ret void > } > > to > > define void @test1(i64 %a, i64 %b, i64* %res_i64, i1* %res_i1) { > entry: > %uadd.overflow = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %b, > i64 %a) > %uadd = extractvalue { i64, i1 } %uadd.overflow, 0 > %overflow = extractvalue { i64, i1 } %uadd.overflow, 1 > store i1 %overflow, i1* %res_i1 > store i64 %uadd, i64* %res_i64 > ret void > } > > > Now if we _know_ that the arithmetic result is used only if it does not > overflow, then we can "pretend" that the arithmetic was nsw/nuw. This > is what I tried to do in http://reviews.llvm.org/rL265912, but I had to > back out the change due to an unrelated issue with SCEV. > > -- Sanjoy > > Nuno Lopes via llvm-dev wrote: >>>> Or do you mean that the result of an add may not even be defined? In >>>> that case would reading it be considered UB in >>>> the case where the overflow bit was set? >>> >>> Yeah, this is the case I'm worried about: that for example >>> sadd.with.overflow(INT_MAX, 1) might be designed to return >>> { poison, true } instead of giving a useful result in the first >>> element of the struct. >> >> Any argument against that? I guess that would be the most natural >> definition given the motivation to have these >> intrinsics (e.g., check if the 'nmemb * size' operation of calloc >> overflows; if so return null). >> >> InstCombine will remove these instrinsics if the overflow bit is >> unused, for example. AFAICT, InstCombine never adds >> nsw/nuw to the replacements. I didn't check GVN. But I think they >> should unless there's some reason not to. >> >> Nuno >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >
Sanjoy Das via llvm-dev
2016-May-09 20:08 UTC
[llvm-dev] x.with.overflow semantics question
John Regehr wrote:> Ok, thanks folks. Sounds like it's clear that x.with.overflow performs > two's complement operations. Should I patch the LangRef to be more > explicit about this? >SGTM> John > > > On 5/9/16 8:14 AM, Sanjoy Das wrote: >> CGP also relies on the add being a simple two's complement add, since it >> will transform >> >> define void @test1(i64 %a, i64 %b, i64* %res_i64, i1* %res_i1) { >> entry: >> %add = add i64 %b, %a >> %cmp = icmp ult i64 %add, %a >> store i1 %cmp, i1* %res_i1 >> store i64 %add, i64* %res_i64 >> ret void >> } >> >> to >> >> define void @test1(i64 %a, i64 %b, i64* %res_i64, i1* %res_i1) { >> entry: >> %uadd.overflow = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %b, >> i64 %a) >> %uadd = extractvalue { i64, i1 } %uadd.overflow, 0 >> %overflow = extractvalue { i64, i1 } %uadd.overflow, 1 >> store i1 %overflow, i1* %res_i1 >> store i64 %uadd, i64* %res_i64 >> ret void >> } >> >> >> Now if we _know_ that the arithmetic result is used only if it does not >> overflow, then we can "pretend" that the arithmetic was nsw/nuw. This >> is what I tried to do in http://reviews.llvm.org/rL265912, but I had to >> back out the change due to an unrelated issue with SCEV. >> >> -- Sanjoy >> >> Nuno Lopes via llvm-dev wrote: >>>>> Or do you mean that the result of an add may not even be defined? In >>>>> that case would reading it be considered UB in >>>>> the case where the overflow bit was set? >>>> >>>> Yeah, this is the case I'm worried about: that for example >>>> sadd.with.overflow(INT_MAX, 1) might be designed to return >>>> { poison, true } instead of giving a useful result in the first >>>> element of the struct. >>> >>> Any argument against that? I guess that would be the most natural >>> definition given the motivation to have these >>> intrinsics (e.g., check if the 'nmemb * size' operation of calloc >>> overflows; if so return null). >>> >>> InstCombine will remove these instrinsics if the overflow bit is >>> unused, for example. AFAICT, InstCombine never adds >>> nsw/nuw to the replacements. I didn't check GVN. But I think they >>> should unless there's some reason not to. >>> >>> Nuno >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>