
This PR resolves https://github.com/llvm/llvm-project/issues/144513 The modification include five pattern : 1.vselect Cond, 0, 0 → 0 2.vselect Cond, -1, 0 → bitcast Cond 3.vselect Cond, -1, x → or Cond, x 4.vselect Cond, x, 0 → and Cond, x 5.vselect Cond, 000..., X -> andn Cond, X 1-4 have been migrated to DAGCombine. 5 still in x86 code. The reason is that you cannot use the andn instruction directly in DAGCombine, you can only use and+xor, which will introduce optimization order issues. For example, in the x86 backend, select Cond, 0, x → (~Cond) & x, the backend will first check whether the cond node of (~Cond) is a setcc node. If so, it will modify the comparison operator of the condition.So the x86 backend cannot complete the optimization of andn.In short, I think it is a better choice to keep the pattern of vselect Cond, 000..., X instead of and+xor in combineDAG. For commit, the first is code changes and x86 test(note 1), the second is tests in other backend(node 2). --------- Co-authored-by: Simon Pilgrim <llvm-dev@redking.me.uk>
467 lines
13 KiB
LLVM
467 lines
13 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=arm64-apple-iphoneos -aarch64-enable-sink-fold=true -o - %s | FileCheck %s
|
|
|
|
define i3 @sign_i3(i3 %a) {
|
|
; CHECK-LABEL: sign_i3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sbfx w8, w0, #2, #1
|
|
; CHECK-NEXT: orr w0, w8, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i3 %a, -1
|
|
%res = select i1 %c, i3 1, i3 -1
|
|
ret i3 %res
|
|
}
|
|
|
|
define i4 @sign_i4(i4 %a) {
|
|
; CHECK-LABEL: sign_i4:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sbfx w8, w0, #3, #1
|
|
; CHECK-NEXT: orr w0, w8, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i4 %a, -1
|
|
%res = select i1 %c, i4 1, i4 -1
|
|
ret i4 %res
|
|
}
|
|
|
|
define i8 @sign_i8(i8 %a) {
|
|
; CHECK-LABEL: sign_i8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sbfx w8, w0, #7, #1
|
|
; CHECK-NEXT: orr w0, w8, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i8 %a, -1
|
|
%res = select i1 %c, i8 1, i8 -1
|
|
ret i8 %res
|
|
}
|
|
|
|
define i16 @sign_i16(i16 %a) {
|
|
; CHECK-LABEL: sign_i16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sbfx w8, w0, #15, #1
|
|
; CHECK-NEXT: orr w0, w8, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i16 %a, -1
|
|
%res = select i1 %c, i16 1, i16 -1
|
|
ret i16 %res
|
|
}
|
|
|
|
define i32 @sign_i32(i32 %a) {
|
|
; CHECK-LABEL: sign_i32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: asr w8, w0, #31
|
|
; CHECK-NEXT: orr w0, w8, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i32 %a, -1
|
|
%res = select i1 %c, i32 1, i32 -1
|
|
ret i32 %res
|
|
}
|
|
|
|
define i64 @sign_i64(i64 %a) {
|
|
; CHECK-LABEL: sign_i64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: asr x8, x0, #63
|
|
; CHECK-NEXT: orr x0, x8, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i64 %a, -1
|
|
%res = select i1 %c, i64 1, i64 -1
|
|
ret i64 %res
|
|
}
|
|
|
|
|
|
define i64 @not_sign_i64(i64 %a) {
|
|
; CHECK-LABEL: not_sign_i64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #1 // =0x1
|
|
; CHECK-NEXT: cmp x0, #0
|
|
; CHECK-NEXT: cneg x0, x8, le
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i64 %a, 0
|
|
%res = select i1 %c, i64 1, i64 -1
|
|
ret i64 %res
|
|
}
|
|
|
|
define i64 @not_sign_i64_2(i64 %a) {
|
|
; CHECK-LABEL: not_sign_i64_2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: asr x0, x0, #63
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i64 %a, -1
|
|
%res = select i1 %c, i64 0, i64 -1
|
|
ret i64 %res
|
|
}
|
|
|
|
define i64 @not_sign_i64_3(i64 %a) {
|
|
; CHECK-LABEL: not_sign_i64_3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mvn x8, x0
|
|
; CHECK-NEXT: lsr x0, x8, #63
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt i64 %a, -1
|
|
%res = select i1 %c, i64 1, i64 0
|
|
ret i64 %res
|
|
}
|
|
|
|
define i64 @not_sign_i64_4(i64 %a) {
|
|
; CHECK-LABEL: not_sign_i64_4:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x0, #-1 // =0xffffffffffffffff
|
|
; CHECK-NEXT: ret
|
|
%c = icmp ugt i64 %a, -1
|
|
%res = select i1 %c, i64 1, i64 -1
|
|
ret i64 %res
|
|
}
|
|
|
|
define <7 x i8> @sign_7xi8(<7 x i8> %a) {
|
|
; CHECK-LABEL: sign_7xi8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8b, #1
|
|
; CHECK-NEXT: cmlt v0.8b, v0.8b, #0
|
|
; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <7 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
|
|
%res = select <7 x i1> %c, <7 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <7 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
|
|
ret <7 x i8> %res
|
|
}
|
|
|
|
define <8 x i8> @sign_8xi8(<8 x i8> %a) {
|
|
; CHECK-LABEL: sign_8xi8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8b, #1
|
|
; CHECK-NEXT: cmlt v0.8b, v0.8b, #0
|
|
; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
|
|
%res = select <8 x i1> %c, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
|
|
ret <8 x i8> %res
|
|
}
|
|
|
|
define <16 x i8> @sign_16xi8(<16 x i8> %a) {
|
|
; CHECK-LABEL: sign_16xi8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.16b, #1
|
|
; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
|
|
; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
|
|
%res = select <16 x i1> %c, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
|
|
ret <16 x i8> %res
|
|
}
|
|
|
|
define <3 x i32> @sign_3xi32(<3 x i32> %a) {
|
|
; CHECK-LABEL: sign_3xi32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
|
|
; CHECK-NEXT: orr v0.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <3 x i32> %a, <i32 -1, i32 -1, i32 -1>
|
|
%res = select <3 x i1> %c, <3 x i32> <i32 1, i32 1, i32 1>, <3 x i32> <i32 -1, i32 -1, i32 -1>
|
|
ret <3 x i32> %res
|
|
}
|
|
|
|
define <4 x i32> @sign_4xi32(<4 x i32> %a) {
|
|
; CHECK-LABEL: sign_4xi32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
|
|
; CHECK-NEXT: orr v0.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
%res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
ret <4 x i32> %res
|
|
}
|
|
|
|
define <4 x i32> @sign_4xi32_multi_use(<4 x i32> %a) {
|
|
; CHECK-LABEL: sign_4xi32_multi_use:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #32
|
|
; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 32
|
|
; CHECK-NEXT: .cfi_offset w30, -16
|
|
; CHECK-NEXT: cmlt v1.4s, v0.4s, #0
|
|
; CHECK-NEXT: cmge v0.4s, v0.4s, #0
|
|
; CHECK-NEXT: xtn v0.4h, v0.4s
|
|
; CHECK-NEXT: orr v1.4s, #1
|
|
; CHECK-NEXT: str q1, [sp] // 16-byte Folded Spill
|
|
; CHECK-NEXT: bl use_4xi1
|
|
; CHECK-NEXT: ldr q0, [sp] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
|
|
; CHECK-NEXT: add sp, sp, #32
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
%res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
call void @use_4xi1(<4 x i1> %c)
|
|
ret <4 x i32> %res
|
|
}
|
|
|
|
; Second icmp operand breaks sign pattern.
|
|
define <4 x i32> @not_sign_4xi32(<4 x i32> %a) {
|
|
; CHECK-LABEL: not_sign_4xi32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: adrp x8, .LCPI16_0
|
|
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI16_0]
|
|
; CHECK-NEXT: cmge v0.4s, v1.4s, v0.4s
|
|
; CHECK-NEXT: orr v0.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <4 x i32> %a, <i32 1, i32 -1, i32 -1, i32 -1>
|
|
%res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
ret <4 x i32> %res
|
|
}
|
|
|
|
; First select operand breaks sign pattern.
|
|
define <4 x i32> @not_sign_4xi32_2(<4 x i32> %a) {
|
|
; CHECK-LABEL: not_sign_4xi32_2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: adrp x8, .LCPI17_0
|
|
; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
|
|
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI17_0]
|
|
; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
%res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 -1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
ret <4 x i32> %res
|
|
}
|
|
|
|
; Second select operand breaks sign pattern.
|
|
define <4 x i32> @not_sign_4xi32_3(<4 x i32> %a) {
|
|
; CHECK-LABEL: not_sign_4xi32_3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: adrp x8, .LCPI18_0
|
|
; CHECK-NEXT: cmge v0.4s, v0.4s, #0
|
|
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI18_0]
|
|
; CHECK-NEXT: bic v1.16b, v1.16b, v0.16b
|
|
; CHECK-NEXT: sub v0.4s, v1.4s, v0.4s
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
|
|
%res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 1>
|
|
ret <4 x i32> %res
|
|
}
|
|
|
|
; i65 is not legal.
|
|
define <4 x i65> @sign_4xi65(<4 x i65> %a) {
|
|
; CHECK-LABEL: sign_4xi65:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sbfx x8, x5, #0, #1
|
|
; CHECK-NEXT: sbfx x9, x3, #0, #1
|
|
; CHECK-NEXT: sbfx x10, x1, #0, #1
|
|
; CHECK-NEXT: sbfx x11, x7, #0, #1
|
|
; CHECK-NEXT: lsr x1, x10, #63
|
|
; CHECK-NEXT: lsr x3, x9, #63
|
|
; CHECK-NEXT: lsr x5, x8, #63
|
|
; CHECK-NEXT: lsr x7, x11, #63
|
|
; CHECK-NEXT: orr x0, x10, #0x1
|
|
; CHECK-NEXT: orr x2, x9, #0x1
|
|
; CHECK-NEXT: orr x4, x8, #0x1
|
|
; CHECK-NEXT: orr x6, x11, #0x1
|
|
; CHECK-NEXT: ret
|
|
%c = icmp sgt <4 x i65> %a, <i65 -1, i65 -1, i65 -1, i65 -1>
|
|
%res = select <4 x i1> %c, <4 x i65> <i65 1, i65 1, i65 1, i65 1>, <4 x i65 > <i65 -1, i65 -1, i65 -1, i65 -1>
|
|
ret <4 x i65> %res
|
|
}
|
|
|
|
define i32 @or_neg(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: orr w8, w0, #0x1
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, lt
|
|
; CHECK-NEXT: ret
|
|
%3 = or i32 %x, 1
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp sgt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_ugt(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_ugt:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: orr w8, w0, #0x1
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
%3 = or i32 %x, 1
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp ugt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define i32 @or_neg_no_smin(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_no_smin:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: neg w8, w0
|
|
; CHECK-NEXT: cmp w8, w1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
%4 = sub i32 0, %x
|
|
%5 = icmp sgt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define i32 @or_neg_ult_no_zero(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_ult_no_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: neg w8, w0
|
|
; CHECK-NEXT: cmp w8, w1
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
%4 = sub i32 0, %x
|
|
%5 = icmp ult i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_no_smin_but_zero(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_no_smin_but_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: bic w8, w0, w0, asr #31
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, lt
|
|
; CHECK-NEXT: ret
|
|
%3 = call i32 @llvm.smax.i32(i32 %x, i32 0)
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp sgt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_slt_zero_but_no_smin(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_slt_zero_but_no_smin:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #9 // =0x9
|
|
; CHECK-NEXT: cmp w0, #9
|
|
; CHECK-NEXT: csel w8, w0, w8, lo
|
|
; CHECK-NEXT: neg w8, w8
|
|
; CHECK-NEXT: cmp w8, w1
|
|
; CHECK-NEXT: cset w0, hi
|
|
; CHECK-NEXT: ret
|
|
%3 = call i32 @llvm.umin.i32(i32 %x, i32 9)
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp ugt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: orr w8, w0, #0x1
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, le
|
|
; CHECK-NEXT: ret
|
|
%3 = or i32 %x, 1
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp sge i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg3(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: orr w8, w0, #0x1
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
%3 = or i32 %x, 1
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp slt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg4(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg4:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: orr w8, w0, #0x1
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, ge
|
|
; CHECK-NEXT: ret
|
|
%3 = or i32 %x, 1
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp sle i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_ult(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_ult:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: orr w8, w0, #0x1
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
%3 = or i32 %x, 1
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp ugt i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_no_smin2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_no_smin2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: neg w8, w0
|
|
; CHECK-NEXT: cmp w8, w1
|
|
; CHECK-NEXT: cset w0, ge
|
|
; CHECK-NEXT: ret
|
|
%4 = sub i32 0, %x
|
|
%5 = icmp sge i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define i32 @or_neg_ult_no_zero2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_ult_no_zero2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: neg w8, w0
|
|
; CHECK-NEXT: cmp w8, w1
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
%4 = sub i32 0, %x
|
|
%5 = icmp ult i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_no_smin_but_zero2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_no_smin_but_zero2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: bic w8, w0, w0, asr #31
|
|
; CHECK-NEXT: cmn w1, w8
|
|
; CHECK-NEXT: cset w0, ge
|
|
; CHECK-NEXT: ret
|
|
%3 = call i32 @llvm.smax.i32(i32 %x, i32 0)
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp sle i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @or_neg_slt_zero_but_no_smin2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: or_neg_slt_zero_but_no_smin2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #9 // =0x9
|
|
; CHECK-NEXT: cmp w0, #9
|
|
; CHECK-NEXT: csel w8, w0, w8, lo
|
|
; CHECK-NEXT: neg w8, w8
|
|
; CHECK-NEXT: cmp w8, w1
|
|
; CHECK-NEXT: cset w0, hs
|
|
; CHECK-NEXT: ret
|
|
%3 = call i32 @llvm.umin.i32(i32 %x, i32 9)
|
|
%4 = sub i32 0, %3
|
|
%5 = icmp uge i32 %4, %y
|
|
%6 = zext i1 %5 to i32
|
|
ret i32 %6
|
|
}
|
|
|
|
declare i32 @llvm.smax.i32(i32, i32)
|
|
declare i32 @llvm.umax.i32(i32, i32)
|
|
declare void @use_4xi1(<4 x i1>)
|