| ; 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, mi |
| ; 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 |
| } |