; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -debugify-and-strip-all-safe -O3 < %s | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64"
target triple = "arm64-unknown-unknown"
define i32 @foo1(i32 %b, i32 %c) nounwind readnone ssp {
; CHECK-LABEL: foo1:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: add w8, w1, w0
; CHECK-NEXT: cinc w0, w8, ne
; CHECK-NEXT: ret
entry:
%not.tobool = icmp ne i32 %c, 0
%add = zext i1 %not.tobool to i32
%b.add = add i32 %c, %b
%add1 = add i32 %b.add, %add
ret i32 %add1
}
define i32 @foo2(i32 %b, i32 %c) nounwind readnone ssp {
; CHECK-LABEL: foo2:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: cneg w8, w0, ne
; CHECK-NEXT: add w0, w8, w1
; CHECK-NEXT: ret
entry:
%mul = sub i32 0, %b
%tobool = icmp eq i32 %c, 0
%b.mul = select i1 %tobool, i32 %b, i32 %mul
%add = add nsw i32 %b.mul, %c
ret i32 %add
}
define i32 @foo3(i32 %b, i32 %c) nounwind readnone ssp {
; CHECK-LABEL: foo3:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: cinv w8, w0, ne
; CHECK-NEXT: add w0, w8, w1
; CHECK-NEXT: ret
entry:
%not.tobool = icmp ne i32 %c, 0
%xor = sext i1 %not.tobool to i32
%b.xor = xor i32 %xor, %b
%add = add nsw i32 %b.xor, %c
ret i32 %add
}
; rdar://11632325
define i32@foo4(i32 %a) nounwind ssp {
; CHECK-LABEL: foo4:
; CHECK: // %bb.0:
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: cneg w0, w0, mi
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %a, -1
%neg = sub nsw i32 0, %a
%cond = select i1 %cmp, i32 %a, i32 %neg
ret i32 %cond
}
define i32@foo5(i32 %a, i32 %b) nounwind ssp {
; CHECK-LABEL: foo5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: subs w8, w0, w1
; CHECK-NEXT: cneg w0, w8, mi
; CHECK-NEXT: ret
entry:
%sub = sub nsw i32 %a, %b
%cmp = icmp sgt i32 %sub, -1
%sub3 = sub nsw i32 0, %sub
%cond = select i1 %cmp, i32 %sub, i32 %sub3
ret i32 %cond
}
; make sure we can handle branch instruction in optimizeCompare.
define i32@foo6(i32 %a, i32 %b) nounwind ssp {
; CHECK-LABEL: foo6:
; CHECK: // %bb.0: // %common.ret
; CHECK-NEXT: subs w8, w0, w1
; CHECK-NEXT: csinc w0, w8, wzr, le
; CHECK-NEXT: ret
%sub = sub nsw i32 %a, %b
%cmp = icmp sgt i32 %sub, 0
br i1 %cmp, label %l.if, label %l.else
l.if:
ret i32 1
l.else:
ret i32 %sub
}
; If CPSR is used multiple times and V flag is used, we don't remove cmp.
define i32 @foo7(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: foo7:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: subs w8, w0, w1
; CHECK-NEXT: cneg w9, w8, mi
; CHECK-NEXT: cmn w8, #1
; CHECK-NEXT: csel w10, w9, w0, lt
; CHECK-NEXT: cmp w8, #0
; CHECK-NEXT: csel w0, w10, w9, ge
; CHECK-NEXT: ret
entry:
%sub = sub nsw i32 %a, %b
%cmp = icmp sgt i32 %sub, -1
%sub3 = sub nsw i32 0, %sub
%cond = select i1 %cmp, i32 %sub, i32 %sub3
br i1 %cmp, label %if.then, label %if.else
if.then:
%cmp2 = icmp slt i32 %sub, -1
%sel = select i1 %cmp2, i32 %cond, i32 %a
ret i32 %sel
if.else:
ret i32 %cond
}
define i32 @foo8(i32 %v, i32 %a, i32 %b) nounwind readnone ssp {
; CHECK-LABEL: foo8:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: csinv w0, w1, w2, ne
; CHECK-NEXT: ret
entry:
%tobool = icmp eq i32 %v, 0
%neg = xor i32 -1, %b
%cond = select i1 %tobool, i32 %neg, i32 %a
ret i32 %cond
}
define i32 @foo9(i32 %v) nounwind readnone optsize ssp {
; CHECK-LABEL: foo9:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #4 // =0x4
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: cinv w0, w8, eq
; CHECK-NEXT: ret
entry:
%tobool = icmp ne i32 %v, 0
%cond = select i1 %tobool, i32 4, i32 -5
ret i32 %cond
}
define i64 @foo10(i64 %v) nounwind readnone optsize ssp {
; CHECK-LABEL: foo10:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #4 // =0x4
; CHECK-NEXT: cmp x0, #0
; CHECK-NEXT: cinv x0, x8, eq
; CHECK-NEXT: ret
entry:
%tobool = icmp ne i64 %v, 0
%cond = select i1 %tobool, i64 4, i64 -5
ret i64 %cond
}
define i32 @foo11(i32 %v) nounwind readnone optsize ssp {
; CHECK-LABEL: foo11:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #4 // =0x4
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: cneg w0, w8, eq
; CHECK-NEXT: ret
entry:
%tobool = icmp ne i32 %v, 0
%cond = select i1 %tobool, i32 4, i32 -4
ret i32 %cond
}
define i64 @foo12(i64 %v) nounwind readnone optsize ssp {
; CHECK-LABEL: foo12:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #4 // =0x4
; CHECK-NEXT: cmp x0, #0
; CHECK-NEXT: cneg x0, x8, eq
; CHECK-NEXT: ret
entry:
%tobool = icmp ne i64 %v, 0
%cond = select i1 %tobool, i64 4, i64 -4
ret i64 %cond
}
define i32 @foo13(i32 %v, i32 %a, i32 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo13:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: csneg w0, w1, w2, ne
; CHECK-NEXT: ret
entry:
%tobool = icmp eq i32 %v, 0
%sub = sub i32 0, %b
%cond = select i1 %tobool, i32 %sub, i32 %a
ret i32 %cond
}
define i64 @foo14(i64 %v, i64 %a, i64 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo14:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp x0, #0
; CHECK-NEXT: csneg x0, x1, x2, ne
; CHECK-NEXT: ret
entry:
%tobool = icmp eq i64 %v, 0
%sub = sub i64 0, %b
%cond = select i1 %tobool, i64 %sub, i64 %a
ret i64 %cond
}
define i32 @foo15(i32 %a, i32 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo15:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #1 // =0x1
; CHECK-NEXT: cmp w0, w1
; CHECK-NEXT: cinc w0, w8, gt
; CHECK-NEXT: ret
entry:
%cmp = icmp sgt i32 %a, %b
%. = select i1 %cmp, i32 2, i32 1
ret i32 %.
}
define i32 @foo16(i32 %a, i32 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo16:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #1 // =0x1
; CHECK-NEXT: cmp w0, w1
; CHECK-NEXT: cinc w0, w8, le
; CHECK-NEXT: ret
entry:
%cmp = icmp sgt i32 %a, %b
%. = select i1 %cmp, i32 1, i32 2
ret i32 %.
}
define i64 @foo17(i64 %a, i64 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo17:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #1 // =0x1
; CHECK-NEXT: cmp x0, x1
; CHECK-NEXT: cinc x0, x8, gt
; CHECK-NEXT: ret
entry:
%cmp = icmp sgt i64 %a, %b
%. = select i1 %cmp, i64 2, i64 1
ret i64 %.
}
define i64 @foo18(i64 %a, i64 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo18:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #1 // =0x1
; CHECK-NEXT: cmp x0, x1
; CHECK-NEXT: cinc x0, x8, le
; CHECK-NEXT: ret
entry:
%cmp = icmp sgt i64 %a, %b
%. = select i1 %cmp, i64 1, i64 2
ret i64 %.
}
; Regression test for TrueVal + 1 overflow
define i64 @foo18_overflow1(i64 %a, i64 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo18_overflow1:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff
; CHECK-NEXT: cmp x0, x1
; CHECK-NEXT: csel x0, x8, xzr, gt
; CHECK-NEXT: ret
entry:
%cmp = icmp sgt i64 %a, %b
%. = select i1 %cmp, i64 9223372036854775807, i64 0
ret i64 %.
}
; Regression test for FalseVal + 1 overflow
define i64 @foo18_overflow2(i64 %a, i64 %b) nounwind readnone optsize ssp {
; CHECK-LABEL: foo18_overflow2:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff
; CHECK-NEXT: cmp x0, x1
; CHECK-NEXT: csel x0, xzr, x8, gt
; CHECK-NEXT: ret
entry:
%cmp = icmp sgt i64 %a, %b
%. = select i1 %cmp, i64 0, i64 9223372036854775807
ret i64 %.
}
; Regression test for FalseVal - TrueVal overflow
define i64 @foo18_overflow3(i1 %cmp) nounwind readnone optsize ssp {
; CHECK-LABEL: foo18_overflow3:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000
; CHECK-NEXT: tst w0, #0x1
; CHECK-NEXT: csel x0, x8, xzr, ne
; CHECK-NEXT: ret
entry:
%. = select i1 %cmp, i64 -9223372036854775808, i64 0
ret i64 %.
}
; Regression test for TrueVal - FalseVal overflow
define i64 @foo18_overflow4(i1 %cmp) nounwind readnone optsize ssp {
; CHECK-LABEL: foo18_overflow4:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000
; CHECK-NEXT: tst w0, #0x1
; CHECK-NEXT: csel x0, xzr, x8, ne
; CHECK-NEXT: ret
entry:
%. = select i1 %cmp, i64 0, i64 -9223372036854775808
ret i64 %.
}
define i64 @foo19(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: foo19:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp x0, x1
; CHECK-NEXT: cinc x0, x2, lo
; CHECK-NEXT: ret
entry:
%cmp = icmp ult i64 %a, %b
%inc = zext i1 %cmp to i64
%inc.c = add i64 %inc, %c
ret i64 %inc.c
}
define i32 @foo20(i32 %x) {
; CHECK-LABEL: foo20:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #6 // =0x6
; CHECK-NEXT: cmp w0, #5
; CHECK-NEXT: csinc w0, w8, wzr, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x, 5
%res = select i1 %cmp, i32 6, i32 1
ret i32 %res
}
define i64 @foo21(i64 %x) {
; CHECK-LABEL: foo21:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #6 // =0x6
; CHECK-NEXT: cmp x0, #5
; CHECK-NEXT: csinc x0, x8, xzr, eq
; CHECK-NEXT: ret
%cmp = icmp eq i64 %x, 5
%res = select i1 %cmp, i64 6, i64 1
ret i64 %res
}
define i32 @foo22(i32 %x) {
; CHECK-LABEL: foo22:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #6 // =0x6
; CHECK-NEXT: cmp w0, #5
; CHECK-NEXT: csinc w0, w8, wzr, ne
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x, 5
%res = select i1 %cmp, i32 1, i32 6
ret i32 %res
}
define i64 @foo23(i64 %x) {
; CHECK-LABEL: foo23:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #6 // =0x6
; CHECK-NEXT: cmp x0, #5
; CHECK-NEXT: csinc x0, x8, xzr, ne
; CHECK-NEXT: ret
%cmp = icmp eq i64 %x, 5
%res = select i1 %cmp, i64 1, i64 6
ret i64 %res
}
define i16 @foo24(ptr nocapture readonly %A, ptr nocapture readonly %B) {
; CHECK-LABEL: foo24:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ldrb w8, [x0]
; CHECK-NEXT: ldrb w9, [x1]
; CHECK-NEXT: cmp w8, #3
; CHECK-NEXT: cset w8, hi
; CHECK-NEXT: cmp w9, #33
; CHECK-NEXT: cinc w0, w8, hi
; CHECK-NEXT: ret
entry:
%0 = load i8, ptr %A, align 1
%cmp = icmp ugt i8 %0, 3
%conv1 = zext i1 %cmp to i16
%1 = load i8, ptr %B, align 1
%cmp4 = icmp ugt i8 %1, 33
%conv5 = zext i1 %cmp4 to i16
%add = add nuw nsw i16 %conv5, %conv1
ret i16 %add
}
define i64 @foo25(ptr nocapture readonly %A, ptr nocapture readonly %B) {
; CHECK-LABEL: foo25:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ldr x8, [x1]
; CHECK-NEXT: ldr x9, [x0]
; CHECK-NEXT: cmp x8, #33
; CHECK-NEXT: cset w8, hi
; CHECK-NEXT: cmp x9, #3
; CHECK-NEXT: cinc x0, x8, hi
; CHECK-NEXT: ret
entry:
%0 = load i64, ptr %A, align 1
%cmp = icmp ugt i64 %0, 3
%conv1 = zext i1 %cmp to i64
%1 = load i64, ptr %B, align 1
%cmp4 = icmp ugt i64 %1, 33
%conv5 = zext i1 %cmp4 to i64
%add = add nuw nsw i64 %conv5, %conv1
ret i64 %add
}
define i32 @or(i32 %num, i32 %x) {
; CHECK-LABEL: or:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: and w8, w0, #0xff00
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: cinc w0, w8, ne
; CHECK-NEXT: ret
entry:
%and = and i32 %num, 65280
%tobool.not = icmp ne i32 %x, 0
%cond = zext i1 %tobool.not to i32
%or = or disjoint i32 %and, %cond
ret i32 %or
}
define i64 @or64(i64 %num, i64 %x) {
; CHECK-LABEL: or64:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: and x8, x0, #0xff00
; CHECK-NEXT: cmp x1, #0
; CHECK-NEXT: cinc x0, x8, ne
; CHECK-NEXT: ret
entry:
%and = and i64 %num, 65280
%tobool.not = icmp ne i64 %x, 0
%conv = zext i1 %tobool.not to i64
%or = or disjoint i64 %and, %conv
ret i64 %or
}
define i32 @selor32(i32 %num, i32 %x) {
; CHECK-LABEL: selor32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: and w8, w0, #0xff00
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: cinc w0, w8, ne
; CHECK-NEXT: ret
entry:
%and = and i32 %num, 65280
%tobool.not = icmp ne i32 %x, 0
%or = or disjoint i32 %and, 1
%sel = select i1 %tobool.not, i32 %or, i32 %and
ret i32 %sel
}
define i32 @selor32_2(i32 %num, i32 %x) {
; CHECK-LABEL: selor32_2:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: and w8, w0, #0xff00
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: orr w9, w8, #0x2
; CHECK-NEXT: csel w0, w9, w8, ne
; CHECK-NEXT: ret
entry:
%and = and i32 %num, 65280
%tobool.not = icmp ne i32 %x, 0
%or = or disjoint i32 %and, 2
%sel = select i1 %tobool.not, i32 %or, i32 %and
ret i32 %sel
}
define i64 @selor64(i64 %num, i64 %x) {
; CHECK-LABEL: selor64:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: and x8, x0, #0xff00
; CHECK-NEXT: cmp x1, #0
; CHECK-NEXT: cinc x0, x8, ne
; CHECK-NEXT: ret
entry:
%and = and i64 %num, 65280
%tobool.not = icmp ne i64 %x, 0
%or = or disjoint i64 %and, 1
%sel = select i1 %tobool.not, i64 %or, i64 %and
ret i64 %sel
}
; Same as above with disjoint but without knowing haveNoCommonBitsSet.
define i64 @selor64_disjoint(i64 %num, i64 %x) {
; CHECK-LABEL: selor64_disjoint:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp x1, #0
; CHECK-NEXT: cinc x0, x0, ne
; CHECK-NEXT: ret
entry:
%tobool.not = icmp ne i64 %x, 0
%or = or disjoint i64 %num, 1
%sel = select i1 %tobool.not, i64 %or, i64 %num
ret i64 %sel
}