llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-webassembly Author: Julius Alexandre (wizardengineer) <details> <summary>Changes</summary> --- Patch is 79.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/166709.diff 5 Files Affected: - (added) llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll (+376) - (added) llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll (+641) - (added) llvm/test/CodeGen/WebAssembly/ctselect-fallback-vector.ll (+714) - (added) llvm/test/CodeGen/WebAssembly/ctselect-fallback.ll (+552) - (added) llvm/test/CodeGen/WebAssembly/ctselect-side-effects.ll (+226) ``````````diff diff --git a/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll new file mode 100644 index 0000000000000..b0f7f2807debd --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll @@ -0,0 +1,376 @@ +; 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 with small integer types +define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) { +; W32-LABEL: test_ctselect_i1: +; W32: .functype test_ctselect_i1 (i32, i32, i32) -> (i32) +; W32-NEXT: # %bb.0: +; W32-NEXT: local.get 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 2 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_i1: +; W64: .functype test_ctselect_i1 (i32, i32, i32) -> (i32) +; W64-NEXT: # %bb.0: +; W64-NEXT: local.get 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i32.and +; W64-NEXT: local.get 0 +; W64-NEXT: i32.const 1 +; W64-NEXT: i32.xor +; W64-NEXT: local.get 2 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; W64-NEXT: # fallthrough-return + %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b) + ret i1 %result +} + +; Test with extremal values +define i32 @test_ctselect_extremal_values(i1 %cond) { +; W32-LABEL: test_ctselect_extremal_values: +; W32: .functype test_ctselect_extremal_values (i32) -> (i32) +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 0 +; W32-NEXT: i32.sub +; W32-NEXT: i32.const 2147483647 +; W32-NEXT: i32.and +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: i32.const -2147483648 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_extremal_values: +; W64: .functype test_ctselect_extremal_values (i32) -> (i32) +; W64-NEXT: # %bb.0: +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: i32.const 1 +; W64-NEXT: i32.and +; W64-NEXT: local.tee 0 +; W64-NEXT: i32.sub +; W64-NEXT: i32.const 2147483647 +; W64-NEXT: i32.and +; W64-NEXT: local.get 0 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.add +; W64-NEXT: i32.const -2147483648 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; W64-NEXT: # fallthrough-return + %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 -2147483648) + ret i32 %result +} + +; Test with null pointers +define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) { +; W32-LABEL: test_ctselect_null_ptr: +; W32: .functype test_ctselect_null_ptr (i32, i32) -> (i32) +; W32-NEXT: # %bb.0: +; 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: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_null_ptr: +; W64: .functype test_ctselect_null_ptr (i32, i64) -> (i64) +; W64-NEXT: # %bb.0: +; W64-NEXT: i64.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: i64.extend_i32_u +; W64-NEXT: i64.const 1 +; W64-NEXT: i64.and +; W64-NEXT: i64.sub +; W64-NEXT: local.get 1 +; W64-NEXT: i64.and +; W64-NEXT: # fallthrough-return + %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null) + ret ptr %result +} + +; Test with function pointers +define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) { +; W32-LABEL: test_ctselect_function_ptr: +; W32: .functype test_ctselect_function_ptr (i32, i32, i32) -> (i32) +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 0 +; W32-NEXT: i32.sub +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: local.get 2 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_function_ptr: +; W64: .functype test_ctselect_function_ptr (i32, i64, i64) -> (i64) +; W64-NEXT: .local i64 +; W64-NEXT: # %bb.0: +; W64-NEXT: i64.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: i64.extend_i32_u +; W64-NEXT: i64.const 1 +; W64-NEXT: i64.and +; W64-NEXT: local.tee 3 +; W64-NEXT: i64.sub +; W64-NEXT: local.get 1 +; W64-NEXT: i64.and +; W64-NEXT: local.get 3 +; W64-NEXT: i64.const -1 +; W64-NEXT: i64.add +; W64-NEXT: local.get 2 +; W64-NEXT: i64.and +; W64-NEXT: i64.or +; W64-NEXT: # fallthrough-return + %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2) + ret ptr %result +} + +; Test with condition from icmp on pointers +define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) { +; W32-LABEL: test_ctselect_ptr_cmp: +; W32: .functype test_ctselect_ptr_cmp (i32, i32, i32, i32) -> (i32) +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.eq +; W32-NEXT: i32.select +; W32-NEXT: local.tee 1 +; W32-NEXT: local.get 2 +; W32-NEXT: i32.and +; W32-NEXT: local.get 1 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 3 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_ptr_cmp: +; W64: .functype test_ctselect_ptr_cmp (i64, i64, i64, i64) -> (i64) +; W64-NEXT: # %bb.0: +; W64-NEXT: i64.const -1 +; W64-NEXT: i64.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i64.eq +; W64-NEXT: i64.select +; W64-NEXT: local.tee 1 +; W64-NEXT: local.get 2 +; W64-NEXT: i64.and +; W64-NEXT: local.get 1 +; W64-NEXT: i64.const -1 +; W64-NEXT: i64.xor +; W64-NEXT: local.get 3 +; W64-NEXT: i64.and +; W64-NEXT: i64.or +; W64-NEXT: # fallthrough-return + %cmp = icmp eq ptr %p1, %p2 + %result = call ptr @llvm.ct.select.p0(i1 %cmp, ptr %a, ptr %b) + ret ptr %result +} + +; Test with struct pointer types +%struct.pair = type { i32, i32 } + +define ptr @test_ctselect_struct_ptr(i1 %cond, ptr %a, ptr %b) { +; W32-LABEL: test_ctselect_struct_ptr: +; W32: .functype test_ctselect_struct_ptr (i32, i32, i32) -> (i32) +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 0 +; W32-NEXT: i32.sub +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: local.get 2 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_struct_ptr: +; W64: .functype test_ctselect_struct_ptr (i32, i64, i64) -> (i64) +; W64-NEXT: .local i64 +; W64-NEXT: # %bb.0: +; W64-NEXT: i64.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: i64.extend_i32_u +; W64-NEXT: i64.const 1 +; W64-NEXT: i64.and +; W64-NEXT: local.tee 3 +; W64-NEXT: i64.sub +; W64-NEXT: local.get 1 +; W64-NEXT: i64.and +; W64-NEXT: local.get 3 +; W64-NEXT: i64.const -1 +; W64-NEXT: i64.add +; W64-NEXT: local.get 2 +; W64-NEXT: i64.and +; W64-NEXT: i64.or +; W64-NEXT: # fallthrough-return + %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %a, ptr %b) + ret ptr %result +} + +; Test with deeply nested conditions +define i32 @test_ctselect_deeply_nested(i1 %c1, i1 %c2, i1 %c3, i1 %c4, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) { +; W32-LABEL: test_ctselect_deeply_nested: +; W32: .functype test_ctselect_deeply_nested (i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32) +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 3 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 3 +; W32-NEXT: i32.sub +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 2 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 2 +; W32-NEXT: i32.sub +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 1 +; W32-NEXT: i32.sub +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const 1 +; W32-NEXT: i32.and +; W32-NEXT: local.tee 0 +; W32-NEXT: i32.sub +; W32-NEXT: local.get 4 +; W32-NEXT: i32.and +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: local.get 5 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: i32.and +; W32-NEXT: local.get 1 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: local.get 6 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: i32.and +; W32-NEXT: local.get 2 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: local.get 7 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: i32.and +; W32-NEXT: local.get 3 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.add +; W32-NEXT: local.get 8 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_deeply_nested: +; W64: .functype test_ctselect_deeply_nested (i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32) +; W64-NEXT: # %bb.0: +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 3 +; W64-NEXT: i32.const 1 +; W64-NEXT: i32.and +; W64-NEXT: local.tee 3 +; W64-NEXT: i32.sub +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 2 +; W64-NEXT: i32.const 1 +; W64-NEXT: i32.and +; W64-NEXT: local.tee 2 +; W64-NEXT: i32.sub +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i32.const 1 +; W64-NEXT: i32.and +; W64-NEXT: local.tee 1 +; W64-NEXT: i32.sub +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: i32.const 1 +; W64-NEXT: i32.and +; W64-NEXT: local.tee 0 +; W64-NEXT: i32.sub +; W64-NEXT: local.get 4 +; W64-NEXT: i32.and +; W64-NEXT: local.get 0 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.add +; W64-NEXT: local.get 5 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; W64-NEXT: i32.and +; W64-NEXT: local.get 1 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.add +; W64-NEXT: local.get 6 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; W64-NEXT: i32.and +; W64-NEXT: local.get 2 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.add +; W64-NEXT: local.get 7 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; W64-NEXT: i32.and +; W64-NEXT: local.get 3 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.add +; W64-NEXT: local.get 8 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; 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) + %sel4 = call i32 @llvm.ct.select.i32(i1 %c4, i32 %sel3, i32 %e) + ret i32 %sel4 +} + +; Declare the intrinsics +declare i1 @llvm.ct.select.i1(i1, i1, i1) +declare i32 @llvm.ct.select.i32(i1, i32, i32) +declare ptr @llvm.ct.select.p0(i1, ptr, ptr) diff --git a/llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll new file mode 100644 index 0000000000000..040ee44addb69 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll @@ -0,0 +1,641 @@ +; 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 31 +; W32-NEXT: i32.shr_s +; W32-NEXT: local.get 0 +; 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 31 +; W64-NEXT: i32.shr_s +; W64-NEXT: local.get 0 +; 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.select +; 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.select +; 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: .local i32 +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.lt_s +; W32-NEXT: i32.select +; W32-NEXT: local.tee 2 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.and +; W32-NEXT: local.get 2 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_smin_generic: +; W64: .functype test_ctselect_smin_generic (i32, i32) -> (i32) +; W64-NEXT: .local i32 +; W64-NEXT: # %bb.0: +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i32.lt_s +; W64-NEXT: i32.select +; W64-NEXT: local.tee 2 +; W64-NEXT: local.get 0 +; W64-NEXT: i32.and +; W64-NEXT: local.get 2 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.xor +; W64-NEXT: local.get 1 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; 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: .local i32 +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.gt_s +; W32-NEXT: i32.select +; W32-NEXT: local.tee 2 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.and +; W32-NEXT: local.get 2 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_smax_generic: +; W64: .functype test_ctselect_smax_generic (i32, i32) -> (i32) +; W64-NEXT: .local i32 +; W64-NEXT: # %bb.0: +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i32.gt_s +; W64-NEXT: i32.select +; W64-NEXT: local.tee 2 +; W64-NEXT: local.get 0 +; W64-NEXT: i32.and +; W64-NEXT: local.get 2 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.xor +; W64-NEXT: local.get 1 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; 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: .local i32 +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.lt_u +; W32-NEXT: i32.select +; W32-NEXT: local.tee 2 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.and +; W32-NEXT: local.get 2 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_umin_generic: +; W64: .functype test_ctselect_umin_generic (i32, i32) -> (i32) +; W64-NEXT: .local i32 +; W64-NEXT: # %bb.0: +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i32.lt_u +; W64-NEXT: i32.select +; W64-NEXT: local.tee 2 +; W64-NEXT: local.get 0 +; W64-NEXT: i32.and +; W64-NEXT: local.get 2 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.xor +; W64-NEXT: local.get 1 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; 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: .local i32 +; W32-NEXT: # %bb.0: +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: local.get 1 +; W32-NEXT: i32.gt_u +; W32-NEXT: i32.select +; W32-NEXT: local.tee 2 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.and +; W32-NEXT: local.get 2 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 1 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_umax_generic: +; W64: .functype test_ctselect_umax_generic (i32, i32) -> (i32) +; W64-NEXT: .local i32 +; W64-NEXT: # %bb.0: +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.const 0 +; W64-NEXT: local.get 0 +; W64-NEXT: local.get 1 +; W64-NEXT: i32.gt_u +; W64-NEXT: i32.select +; W64-NEXT: local.tee 2 +; W64-NEXT: local.get 0 +; W64-NEXT: i32.and +; W64-NEXT: local.get 2 +; W64-NEXT: i32.const -1 +; W64-NEXT: i32.xor +; W64-NEXT: local.get 1 +; W64-NEXT: i32.and +; W64-NEXT: i32.or +; 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: .local i32 +; W32-NEXT: # %bb.0: +; W32-NEXT: local.get 0 +; W32-NEXT: i32.const 31 +; W32-NEXT: i32.shr_s +; W32-NEXT: local.tee 1 +; W32-NEXT: i32.const 0 +; W32-NEXT: local.get 0 +; W32-NEXT: i32.sub +; W32-NEXT: i32.and +; W32-NEXT: local.get 1 +; W32-NEXT: i32.const -1 +; W32-NEXT: i32.xor +; W32-NEXT: local.get 0 +; W32-NEXT: i32.and +; W32-NEXT: i32.or +; W32-NEXT: # fallthrough-return +; +; W64-LABEL: test_ctselect_abs: +; W64: .functype test_ctselect_abs (i32) -> (i32) +; W64-NEXT: .local i32 +; W64-NEXT: # %bb.0: +; W64-NEXT: local.get 0 +; W64-NEXT: i32.const 31 +; W64-NEXT: i32.shr_s +; W6... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/166709 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
