x.with.overflow semantics question

Philip Reames and I are debating the semantics of x.with.overflow and I wanted to see if I could get a ruling here:

My read of the langref is that the overflow bit and the result of the operation are independent of each other. In other words, we can count on the result of add.with.overflow being the same as the result of a (non-nsw) add, even in the case where an overflow occurs. Is that right?

Thanks!

John

Hi John

That matches my understanding. Otherwise I guess you'd be talking about a saturating operation.

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?

Cheers
Pete

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

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

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."

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

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

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 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

Please. :slight_smile: