John Regehr via llvm-dev
2016-May-08 20:57 UTC
[llvm-dev] x.with.overflow semantics question
Hi Pete, > 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. John
Nuno Lopes via llvm-dev
2016-May-08 21:14 UTC
[llvm-dev] x.with.overflow semantics question
>> 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
David Majnemer via llvm-dev
2016-May-08 22:19 UTC
[llvm-dev] x.with.overflow semantics question
On Sun, May 8, 2016 at 2:14 PM, Nuno Lopes via llvm-dev < llvm-dev at lists.llvm.org> 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?Yes, they were introduced to implement clang's __builtin_foo_overflow intrinsics which are explicitly documented to provide the two's complement behavior: http://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins "Otherwise, the builtin will return 1 and the result will be equal to the unique value that is equivalent to the mathematically-correct result modulo two raised to the k power, where k is the number of bits in the result type. The behavior of these builtins is well-defined for all argument values."> 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 >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160508/21f1ed5a/attachment.html>
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