Skip to content

Is CMN safe when the subtraction is nsw? #141822

Open
@AZero13

Description

@AZero13

In C,

bool cmp(int a, int b) {
return a > -b;
}

yeilds

define i1 @cmn_nsw(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: neg w8, w1
; CHECK-NEXT: cmp w0, w8
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%sub = sub nsw i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}

Now, because no fwrapv, the sub is assumed to be nsw.

However, this would mean no signed wrap.

For 0 - b to be signed wrap, b would have to be a value that fits in the realm of possible signed integers, and cause a wrap.

The only value for b that fits is 0x80000000, and therefore:
Iff b is 0x80000000, then 0 - b is signed wrap.

Therefore,
if 0 - b is not signed wrap, or nsw, b is not 0x80000000

Which means in theory I could do this:
define i1 @cmn_nsw(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: cmn w0, w1
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%sub = sub nsw i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}

However, alive2 says:

define i1 @src(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: cmn w0, w1
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%sub = sub nsw i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}

define i1 @tgt(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: cmn w0, w1
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%isNotMin = icmp ne i32 %b, -2147483648
call void @llvm.assume(i1 %isNotMin)
%sub = sub i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}

ERROR: Source is more defined than target

Example:
i32 %a = #x00000003 (3)
i32 %b = #x80000000 (2147483648, -2147483648)

Source:
i32 %sub = poison
i1 %cmp = poison

Target:
i1 %isNotMin = #x0 (0)
void = UB triggered!

I know I am thinking of multiple levels at once, but the question is, if I am checking if it is safe to turn cmp into cmn, is it safe to just look at the no signed wrap flag?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions