| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: llc < %s -mtriple=wasm32-unknown-unknown -O3 -filetype=asm | FileCheck %s --check-prefix=W32 |
| ; RUN: llc < %s -mtriple=wasm64-unknown-unknown -O3 -filetype=asm | FileCheck %s --check-prefix=W64 |
| |
| ; Test smin(x, 0) pattern |
| define i32 @test_ctselect_smin_zero(i32 %x) { |
| ; W32-LABEL: test_ctselect_smin_zero: |
| ; W32: .functype test_ctselect_smin_zero (i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.lt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_smin_zero: |
| ; W64: .functype test_ctselect_smin_zero (i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.lt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp slt i32 %x, 0 |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 0) |
| ret i32 %result |
| } |
| |
| ; Test smax(x, 0) pattern |
| define i32 @test_ctselect_smax_zero(i32 %x) { |
| ; W32-LABEL: test_ctselect_smax_zero: |
| ; W32: .functype test_ctselect_smax_zero (i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.gt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_smax_zero: |
| ; W64: .functype test_ctselect_smax_zero (i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.gt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp sgt i32 %x, 0 |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 0) |
| ret i32 %result |
| } |
| |
| ; Test generic smin pattern |
| define i32 @test_ctselect_smin_generic(i32 %x, i32 %y) { |
| ; W32-LABEL: test_ctselect_smin_generic: |
| ; W32: .functype test_ctselect_smin_generic (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.lt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_smin_generic: |
| ; W64: .functype test_ctselect_smin_generic (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.lt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp slt i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y) |
| ret i32 %result |
| } |
| |
| ; Test generic smax pattern |
| define i32 @test_ctselect_smax_generic(i32 %x, i32 %y) { |
| ; W32-LABEL: test_ctselect_smax_generic: |
| ; W32: .functype test_ctselect_smax_generic (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.gt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_smax_generic: |
| ; W64: .functype test_ctselect_smax_generic (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.gt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp sgt i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y) |
| ret i32 %result |
| } |
| |
| ; Test umin pattern |
| define i32 @test_ctselect_umin_generic(i32 %x, i32 %y) { |
| ; W32-LABEL: test_ctselect_umin_generic: |
| ; W32: .functype test_ctselect_umin_generic (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.lt_u |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_umin_generic: |
| ; W64: .functype test_ctselect_umin_generic (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.lt_u |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp ult i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y) |
| ret i32 %result |
| } |
| |
| ; Test umax pattern |
| define i32 @test_ctselect_umax_generic(i32 %x, i32 %y) { |
| ; W32-LABEL: test_ctselect_umax_generic: |
| ; W32: .functype test_ctselect_umax_generic (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.gt_u |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_umax_generic: |
| ; W64: .functype test_ctselect_umax_generic (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.gt_u |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp ugt i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y) |
| ret i32 %result |
| } |
| |
| ; Test abs pattern |
| define i32 @test_ctselect_abs(i32 %x) { |
| ; W32-LABEL: test_ctselect_abs: |
| ; W32: .functype test_ctselect_abs (i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.lt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_abs: |
| ; W64: .functype test_ctselect_abs (i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.lt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %neg = sub i32 0, %x |
| %cmp = icmp slt i32 %x, 0 |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %neg, i32 %x) |
| ret i32 %result |
| } |
| |
| ; Test nabs pattern (negative abs) |
| define i32 @test_ctselect_nabs(i32 %x) { |
| ; W32-LABEL: test_ctselect_nabs: |
| ; W32: .functype test_ctselect_nabs (i32) -> (i32) |
| ; W32-NEXT: .local i32 |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: local.tee 1 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.lt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_nabs: |
| ; W64: .functype test_ctselect_nabs (i32) -> (i32) |
| ; W64-NEXT: .local i32 |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: local.tee 1 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.lt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %neg = sub i32 0, %x |
| %cmp = icmp slt i32 %x, 0 |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %neg) |
| ret i32 %result |
| } |
| |
| ; Test sign extension pattern |
| define i32 @test_ctselect_sign_extend(i32 %x) { |
| ; W32-LABEL: test_ctselect_sign_extend: |
| ; W32: .functype test_ctselect_sign_extend (i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.lt_s |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_sign_extend: |
| ; W64: .functype test_ctselect_sign_extend (i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.lt_s |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp slt i32 %x, 0 |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 -1, i32 0) |
| ret i32 %result |
| } |
| |
| ; Test zero extension pattern |
| define i32 @test_ctselect_zero_extend(i32 %x) { |
| ; W32-LABEL: test_ctselect_zero_extend: |
| ; W32: .functype test_ctselect_zero_extend (i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.ne |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_zero_extend: |
| ; W64: .functype test_ctselect_zero_extend (i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.ne |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp ne i32 %x, 0 |
| %result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 1, i32 0) |
| ret i32 %result |
| } |
| |
| ; Test constant folding with known condition |
| define i32 @test_ctselect_constant_folding_true(i32 %a, i32 %b) { |
| ; W32-LABEL: test_ctselect_constant_folding_true: |
| ; W32: .functype test_ctselect_constant_folding_true (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_constant_folding_true: |
| ; W64: .functype test_ctselect_constant_folding_true (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %result = call i32 @llvm.ct.select.i32(i1 true, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| define i32 @test_ctselect_constant_folding_false(i32 %a, i32 %b) { |
| ; W32-LABEL: test_ctselect_constant_folding_false: |
| ; W32: .functype test_ctselect_constant_folding_false (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_constant_folding_false: |
| ; W64: .functype test_ctselect_constant_folding_false (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %result = call i32 @llvm.ct.select.i32(i1 false, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| ; Test with identical operands |
| define i32 @test_ctselect_identical_operands(i1 %cond, i32 %x) { |
| ; W32-LABEL: test_ctselect_identical_operands: |
| ; W32: .functype test_ctselect_identical_operands (i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_identical_operands: |
| ; W64: .functype test_ctselect_identical_operands (i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %x, i32 %x) |
| ret i32 %result |
| } |
| |
| ; Test with inverted condition |
| define i32 @test_ctselect_inverted_condition(i32 %x, i32 %y, i32 %a, i32 %b) { |
| ; W32-LABEL: test_ctselect_inverted_condition: |
| ; W32: .functype test_ctselect_inverted_condition (i32, i32, i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 2 |
| ; W32-NEXT: local.get 3 |
| ; W32-NEXT: local.get 2 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.eq |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_inverted_condition: |
| ; W64: .functype test_ctselect_inverted_condition (i32, i32, i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 2 |
| ; W64-NEXT: local.get 3 |
| ; W64-NEXT: local.get 2 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.eq |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp eq i32 %x, %y |
| %not_cmp = xor i1 %cmp, true |
| %result = call i32 @llvm.ct.select.i32(i1 %not_cmp, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| ; Test chain of ct.select operations |
| define i32 @test_ctselect_chain(i1 %c1, i1 %c2, i1 %c3, i32 %a, i32 %b, i32 %c, i32 %d) { |
| ; W32-LABEL: test_ctselect_chain: |
| ; W32: .functype test_ctselect_chain (i32, i32, i32, i32, i32, i32, i32) -> (i32) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 6 |
| ; W32-NEXT: local.get 5 |
| ; W32-NEXT: local.get 4 |
| ; W32-NEXT: local.get 3 |
| ; W32-NEXT: local.get 4 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i32.const 1 |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: local.get 5 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 1 |
| ; W32-NEXT: i32.const 1 |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: local.get 6 |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: i32.const 0 |
| ; W32-NEXT: local.get 2 |
| ; W32-NEXT: i32.const 1 |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.sub |
| ; W32-NEXT: i32.and |
| ; W32-NEXT: i32.xor |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_chain: |
| ; W64: .functype test_ctselect_chain (i32, i32, i32, i32, i32, i32, i32) -> (i32) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 6 |
| ; W64-NEXT: local.get 5 |
| ; W64-NEXT: local.get 4 |
| ; W64-NEXT: local.get 3 |
| ; W64-NEXT: local.get 4 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i32.const 1 |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: local.get 5 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 1 |
| ; W64-NEXT: i32.const 1 |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: local.get 6 |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: i32.const 0 |
| ; W64-NEXT: local.get 2 |
| ; W64-NEXT: i32.const 1 |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.sub |
| ; W64-NEXT: i32.and |
| ; W64-NEXT: i32.xor |
| ; W64-NEXT: # fallthrough-return |
| %sel1 = call i32 @llvm.ct.select.i32(i1 %c1, i32 %a, i32 %b) |
| %sel2 = call i32 @llvm.ct.select.i32(i1 %c2, i32 %sel1, i32 %c) |
| %sel3 = call i32 @llvm.ct.select.i32(i1 %c3, i32 %sel2, i32 %d) |
| ret i32 %sel3 |
| } |
| |
| ; Test for 64-bit operations (supported on all 64-bit architectures) |
| define i64 @test_ctselect_i64_smin_zero(i64 %x) { |
| ; W32-LABEL: test_ctselect_i64_smin_zero: |
| ; W32: .functype test_ctselect_i64_smin_zero (i64) -> (i64) |
| ; W32-NEXT: # %bb.0: |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: local.get 0 |
| ; W32-NEXT: i64.const 63 |
| ; W32-NEXT: i64.shr_s |
| ; W32-NEXT: i64.and |
| ; W32-NEXT: # fallthrough-return |
| ; |
| ; W64-LABEL: test_ctselect_i64_smin_zero: |
| ; W64: .functype test_ctselect_i64_smin_zero (i64) -> (i64) |
| ; W64-NEXT: # %bb.0: |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: local.get 0 |
| ; W64-NEXT: i64.const 63 |
| ; W64-NEXT: i64.shr_s |
| ; W64-NEXT: i64.and |
| ; W64-NEXT: # fallthrough-return |
| %cmp = icmp slt i64 %x, 0 |
| %result = call i64 @llvm.ct.select.i64(i1 %cmp, i64 %x, i64 0) |
| ret i64 %result |
| } |
| |
| ; Declare the intrinsics |
| declare i32 @llvm.ct.select.i32(i1, i32, i32) |
| declare i64 @llvm.ct.select.i64(i1, i64, i64) |