blob: e745326323329c9919d79af5a0ba368f5c1051e7 [file] [log] [blame]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s
declare void @use_i1(i1 %x)
declare void @use_i32(i32 %x)
; Based on the IR generated for the `last` method of the type `slice` in Rust
define ptr @test_last_elem_from_ptr(ptr noundef readnone %x0, i64 noundef %x1) {
; CHECK-LABEL: test_last_elem_from_ptr:
; CHECK: // %bb.0:
; CHECK-NEXT: subs x8, x1, #1
; CHECK-NEXT: add x8, x8, x0
; CHECK-NEXT: csel x0, xzr, x8, lo
; CHECK-NEXT: ret
%cmp = icmp eq i64 %x1, 0
%add.ptr = getelementptr inbounds nuw i8, ptr %x0, i64 %x1
%add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 -1
%retval.0 = select i1 %cmp, ptr null, ptr %add.ptr1
ret ptr %retval.0
}
define i32 @test_eq0_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #1
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_eq7_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq7_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 7
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, 7
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ule7_sub7_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ule7_sub7_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ls
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 7
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ule7_sub8_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ule7_sub8_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #8
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ule0_sub1_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ule0_sub1_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #1
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x1, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ultminus2_subminus2_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ultminus2_subminus2_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: adds w8, w1, #2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, -2
%add = add i32 %x0, %x1
%sub = sub i32 %add, -2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ultminus2_subminus3_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ultminus2_subminus3_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: adds w8, w1, #3
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ls
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, -2
%add = add i32 %x0, %x1
%sub = sub i32 %add, -3
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ne0_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ne0_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #1
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, w8, wzr, hs
; CHECK-NEXT: ret
%cmp = icmp ne i32 %x1, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 %sub, i32 0
ret i32 %ret
}
define i32 @test_ne7_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ne7_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, w8, wzr, ne
; CHECK-NEXT: ret
%cmp = icmp ne i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 7
%ret = select i1 %cmp, i32 %sub, i32 0
ret i32 %ret
}
define i32 @test_ultminus1_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ultminus1_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: adds w8, w1, #1
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ne
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, -1
%add = add i32 %x0, %x1
%sub = sub i32 %add, -1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ugt7_sub7_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ugt7_sub7_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, hi
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 7
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ugt7_sub8_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ugt7_sub8_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #8
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, hs
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sle7_sub7_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sle7_sub7_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, le
; CHECK-NEXT: ret
%cmp = icmp sle i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 7
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sle7_sub8_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sle7_sub8_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #8
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp sle i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_slt8_sub8_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_slt8_sub8_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #8
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x1, 8
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_slt8_sub7_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_slt8_sub7_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, le
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x1, 8
%add = add i32 %x0, %x1
%sub = sub i32 %add, 7
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sltminus8_subminus8_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sltminus8_subminus8_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: adds w8, w1, #8
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x1, -8
%add = add i32 %x0, %x1
%sub = sub i32 %add, -8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sgtminus8_subminus8_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sgtminus8_subminus8_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: adds w8, w1, #8
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, gt
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %x1, -8
%add = add i32 %x0, %x1
%sub = sub i32 %add, -8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sgtminus8_subminus7_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sgtminus8_subminus7_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: adds w8, w1, #7
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ge
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %x1, -8
%add = add i32 %x0, %x1
%sub = sub i32 %add, -7
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_eq0_sub_addcomm_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_sub_addcomm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #1
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add i32 %x1, %x0
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_eq0_subcomm_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_subcomm_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, #1
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add i32 %x0, %x1
%sub = add i32 -1, %add
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_eq0_multi_use_sub_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_multi_use_sub_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: subs w8, w1, #1
; CHECK-NEXT: add w0, w8, w0
; CHECK-NEXT: csel w19, wzr, w0, lo
; CHECK-NEXT: bl use_i32
; CHECK-NEXT: mov w0, w19
; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, 1
tail call void @use_i32(i32 %sub)
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_eq_nonconst_sub_add_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_eq_nonconst_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, %x2
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ne_nonconst_sub_add_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ne_nonconst_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ne
; CHECK-NEXT: ret
%cmp = icmp ne i32 %x1, %x2
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ult_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ult_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ule_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ule_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ls
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ugt_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ugt_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, hi
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_uge_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_uge_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, hs
; CHECK-NEXT: ret
%cmp = icmp uge i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_slt_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_slt_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sle_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_sle_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, le
; CHECK-NEXT: ret
%cmp = icmp sle i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sgt_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_sgt_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, gt
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sge_nonconst_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_sge_nonconst_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ge
; CHECK-NEXT: ret
%cmp = icmp sge i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i64 @test_ult_nonconst_i64(i64 %x0, i64 %x1, i64 %x2) {
; CHECK-LABEL: test_ult_nonconst_i64:
; CHECK: // %bb.0:
; CHECK-NEXT: subs x8, x1, x2
; CHECK-NEXT: add x8, x8, x0
; CHECK-NEXT: csel x0, xzr, x8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i64 %x1, %x2
%add = add i64 %x0, %x1
%sub = sub i64 %add, %x2
%ret = select i1 %cmp, i64 0, i64 %sub
ret i64 %ret
}
define i32 @test_eq_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_eq_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ne_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ne_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ne
; CHECK-NEXT: ret
%cmp = icmp ne i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ult_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ult_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, hi
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ule_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ule_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, hs
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_ugt_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ugt_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_uge_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_uge_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ls
; CHECK-NEXT: ret
%cmp = icmp uge i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_slt_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_slt_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, gt
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sle_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_sle_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, ge
; CHECK-NEXT: ret
%cmp = icmp sle i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sgt_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_sgt_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
define i32 @test_sge_nonconst_sub_add_comm_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_sge_nonconst_sub_add_comm_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: subs w8, w1, w2
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: csel w0, wzr, w8, le
; CHECK-NEXT: ret
%cmp = icmp sge i32 %x2, %x1
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_eq0_multi_use_cmp_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_multi_use_cmp_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: sub w8, w8, #1
; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: csel w19, wzr, w8, eq
; CHECK-NEXT: bl use_i1
; CHECK-NEXT: mov w0, w19
; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
tail call void @use_i1(i1 %cmp)
%add = add nuw i32 %x0, %x1
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_eq0_multi_use_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_multi_use_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill
; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w20, -16
; CHECK-NEXT: .cfi_offset w30, -32
; CHECK-NEXT: add w20, w0, w1
; CHECK-NEXT: mov w19, w1
; CHECK-NEXT: mov w0, w20
; CHECK-NEXT: bl use_i32
; CHECK-NEXT: sub w8, w20, #1
; CHECK-NEXT: cmp w19, #0
; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add nuw i32 %x0, %x1
tail call void @use_i32(i32 %add)
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_eq1_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq1_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #1
; CHECK-NEXT: sub w8, w8, #2
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 1
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ugtsmax_sub_add_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ugtsmax_sub_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000
; CHECK-NEXT: add w9, w0, w1
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: add w8, w9, w8
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x1, 2147483647
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2147483648
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_eq_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: sub w8, w8, #2
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ne_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ne_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: sub w8, w8, #2
; CHECK-NEXT: csel w0, w8, wzr, ne
; CHECK-NEXT: ret
%cmp = icmp ne i32 %x1, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2
%ret = select i1 %cmp, i32 %sub, i32 0
ret i32 %ret
}
; Negative test
define i32 @test_ult7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ult7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #7
; CHECK-NEXT: sub w8, w8, #8
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ule7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ule7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #8
; CHECK-NEXT: sub w8, w8, #6
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 6
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ugt7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ugt7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #7
; CHECK-NEXT: sub w8, w8, #6
; CHECK-NEXT: csel w0, wzr, w8, hi
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 6
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_uge7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_uge7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #6
; CHECK-NEXT: sub w8, w8, #8
; CHECK-NEXT: csel w0, wzr, w8, hi
; CHECK-NEXT: ret
%cmp = icmp uge i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_slt7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_slt7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #7
; CHECK-NEXT: sub w8, w8, #8
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_sle7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sle7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #8
; CHECK-NEXT: sub w8, w8, #6
; CHECK-NEXT: csel w0, wzr, w8, lt
; CHECK-NEXT: ret
%cmp = icmp sle i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 6
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_sgt7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sgt7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #7
; CHECK-NEXT: sub w8, w8, #6
; CHECK-NEXT: csel w0, wzr, w8, gt
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 6
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_sge7_const_mismatch_i32(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sge7_const_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, #6
; CHECK-NEXT: sub w8, w8, #8
; CHECK-NEXT: csel w0, wzr, w8, gt
; CHECK-NEXT: ret
%cmp = icmp sge i32 %x1, 7
%add = add i32 %x0, %x1
%sub = sub i32 %add, 8
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_unrelated_add_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_unrelated_add_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w2
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: sub w8, w8, #1
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i32 %x1, 0
%add = add nuw i32 %x0, %x2
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i16 @test_eq0_sub_add_i16(i16 %x0, i16 %x1) {
; CHECK-LABEL: test_eq0_sub_add_i16:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: tst w1, #0xffff
; CHECK-NEXT: sub w8, w8, #1
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%cmp = icmp eq i16 %x1, 0
%add = add nuw i16 %x0, %x1
%sub = sub i16 %add, 1
%ret = select i1 %cmp, i16 0, i16 %sub
ret i16 %ret
}
; Negative test
define i8 @test_eq_nonconst_sub_add_i8(i8 %x0, i8 %x1, i8 %x2) {
; CHECK-LABEL: test_eq_nonconst_sub_add_i8:
; CHECK: // %bb.0:
; CHECK-NEXT: and w8, w1, #0xff
; CHECK-NEXT: add w9, w0, w1
; CHECK-NEXT: sub w9, w9, w2
; CHECK-NEXT: cmp w8, w2, uxtb
; CHECK-NEXT: csel w0, wzr, w9, eq
; CHECK-NEXT: ret
%cmp = icmp eq i8 %x1, %x2
%add = add nuw i8 %x0, %x1
%sub = sub i8 %add, %x2
%ret = select i1 %cmp, i8 0, i8 %sub
ret i8 %ret
}
; Negative test
define i16 @test_eq_nonconst_sub_add_i16(i16 %x0, i16 %x1, i16 %x2) {
; CHECK-LABEL: test_eq_nonconst_sub_add_i16:
; CHECK: // %bb.0:
; CHECK-NEXT: and w8, w1, #0xffff
; CHECK-NEXT: add w9, w0, w1
; CHECK-NEXT: sub w9, w9, w2
; CHECK-NEXT: cmp w8, w2, uxth
; CHECK-NEXT: csel w0, wzr, w9, eq
; CHECK-NEXT: ret
%cmp = icmp eq i16 %x1, %x2
%add = add nuw i16 %x0, %x1
%sub = sub i16 %add, %x2
%ret = select i1 %cmp, i16 0, i16 %sub
ret i16 %ret
}
; Negative test
define i32 @test_ule_unsigned_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ule_unsigned_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
%cmp = icmp ule i32 %x1, -1
%add = add i32 %x0, %x1
%sub = sub i32 %add, 0
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ugt_unsigned_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ugt_unsigned_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: add w0, w0, w1
; CHECK-NEXT: ret
%cmp = icmp ugt i32 %x1, -1
%add = add i32 %x0, %x1
%sub = sub i32 %add, 0
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ult_unsigned_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_ult_unsigned_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: add w0, w8, #1
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, -1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_uge_unsigned_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_uge_unsigned_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
%cmp = icmp uge i32 %x1, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, -1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_slt_signed_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_slt_signed_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #-2147483647 // =0x80000001
; CHECK-NEXT: add w9, w0, w1
; CHECK-NEXT: add w0, w9, w8
; CHECK-NEXT: ret
%cmp = icmp slt i32 %x1, 2147483648
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2147483647
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_sle_signed_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sle_signed_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
%cmp = icmp sle i32 %x1, 2147483647
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2147483648
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_sgt_signed_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sgt_signed_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000
; CHECK-NEXT: add w9, w0, w1
; CHECK-NEXT: add w0, w9, w8
; CHECK-NEXT: ret
%cmp = icmp sgt i32 %x1, 2147483647
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2147483648
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_sge_signed_overflow(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_sge_signed_overflow:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
%cmp = icmp sge i32 %x1, 2147483648
%add = add i32 %x0, %x1
%sub = sub i32 %add, 2147483647
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_eq0_bitwidth_mismatch(i32 %x0, i32 %x1) {
; CHECK-LABEL: test_eq0_bitwidth_mismatch:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: tst w1, #0xffff
; CHECK-NEXT: sub w8, w8, #1
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%x1t = trunc i32 %x1 to i16
%cmp = icmp eq i16 %x1t, 0
%add = add i32 %x0, %x1
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_eq0_bitwidth_mismatch_2(i32 %x0, i64 %x1) {
; CHECK-LABEL: test_eq0_bitwidth_mismatch_2:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp x1, #0
; CHECK-NEXT: sub w8, w8, #1
; CHECK-NEXT: csel w0, wzr, w8, eq
; CHECK-NEXT: ret
%x1t = trunc i64 %x1 to i32
%cmp = icmp eq i64 %x1, 0
%add = add i32 %x0, %x1t
%sub = sub i32 %add, 1
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ult_nonconst_op_mismatch_i32(i32 %x0, i32 %x1, i32 %x2) {
; CHECK-LABEL: test_ult_nonconst_op_mismatch_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, w2
; CHECK-NEXT: add w8, w8, w2
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = add i32 %add, %x2
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ult_nonconst_unrelated_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
; CHECK-LABEL: test_ult_nonconst_unrelated_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w1, w2
; CHECK-NEXT: sub w8, w8, w3
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x1, %x2
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x3
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}
; Negative test
define i32 @test_ult_nonconst_unrelated_2_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
; CHECK-LABEL: test_ult_nonconst_unrelated_2_i32:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: cmp w2, w1
; CHECK-NEXT: sub w8, w8, w3
; CHECK-NEXT: csel w0, wzr, w8, lo
; CHECK-NEXT: ret
%cmp = icmp ult i32 %x2, %x1
%add = add i32 %x0, %x1
%sub = sub i32 %add, %x3
%ret = select i1 %cmp, i32 0, i32 %sub
ret i32 %ret
}