diff --git a/cranelift/codegen/src/opts/icmp.isle b/cranelift/codegen/src/opts/icmp.isle index b726b89acb39..f0db4153042e 100644 --- a/cranelift/codegen/src/opts/icmp.isle +++ b/cranelift/codegen/src/opts/icmp.isle @@ -376,3 +376,37 @@ (simplify (band ty (ult ty x y) (ne ty (iconst_s _ -1) x))) (ult ty x y)) +;; icmp on select with two constant inputs compared with one of the two +;; constants can directly use the inner select condition. +;; See: https://github.com/bytecodealliance/wasmtime/issues/11578 +(rule (simplify (eq _ + (select select_ty inner_cond + (iconst_u _ k1) + (iconst_u _ k2)) + (iconst_u _ k1))) + (if-let false (u64_eq k1 k2)) + (ne select_ty inner_cond (iconst_u select_ty 0))) + +(rule (simplify (eq _ + (select select_ty inner_cond + (iconst_u _ k1) + (iconst_u _ k2)) + (iconst_u _ k2))) + (if-let false (u64_eq k1 k2)) + (eq select_ty inner_cond (iconst_u select_ty 0))) + +(rule (simplify (ne _ + (select select_ty inner_cond + (iconst_u _ k1) + (iconst_u _ k2)) + (iconst_u _ k1))) + (if-let false (u64_eq k1 k2)) + (eq select_ty inner_cond (iconst_u select_ty 0))) + +(rule (simplify (ne _ + (select select_ty inner_cond + (iconst_u _ k1) + (iconst_u _ k2)) + (iconst_u _ k2))) + (if-let false (u64_eq k1 k2)) + (ne select_ty inner_cond (iconst_u select_ty 0))) diff --git a/cranelift/filetests/filetests/egraph/issue-11578-opt.clif b/cranelift/filetests/filetests/egraph/issue-11578-opt.clif new file mode 100644 index 000000000000..0d59c41048aa --- /dev/null +++ b/cranelift/filetests/filetests/egraph/issue-11578-opt.clif @@ -0,0 +1,127 @@ +test optimize +set opt_level=speed +target x86_64 +target aarch64 + +function %eq_k1(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp eq v7, v5 + return v8 +} + +; check: function %eq_k1(i64) -> i8 fast { +; check: block0(v2: i64): +; nextln: v14 = iconst.i64 -562949953421310 +; nextln: v3 = band v2, v14 +; nextln: v16 = iconst.i64 0 +; nextln: v4 = icmp eq v3, v16 +; nextln: return v4 +; nextln: } + +function %eq_k2(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp eq v7, v6 + return v8 +} + +; check: function %eq_k2(i64) -> i8 fast { +; check: block0(v2: i64): +; nextln: v14 = iconst.i64 -562949953421310 +; nextln: v3 = band v2, v14 ; v14 = -562949953421310 +; nextln: v16 = iconst.i64 0 +; nextln: v18 = icmp ne v3, v16 ; v16 = 0 +; nextln: return v18 +; nextln: } + +function %ne_k1(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp ne v7, v5 + return v8 +} + +; check: function %ne_k1(i64) -> i8 fast { +; check: block0(v2: i64): +; nextln: v14 = iconst.i64 -562949953421310 +; nextln: v3 = band v2, v14 ; v14 = -562949953421310 +; nextln: v16 = iconst.i64 0 +; nextln: v18 = icmp ne v3, v16 ; v16 = 0 +; nextln: return v18 +; nextln: } + +function %ne_k2(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp ne v7, v6 + return v8 +} + +; check: function %ne_k2(i64) -> i8 fast { +; check: block0(v2: i64): +; nextln: v14 = iconst.i64 -562949953421310 +; nextln: v3 = band v2, v14 +; nextln: v16 = iconst.i64 0 +; nextln: v4 = icmp eq v3, v16 +; nextln: return v4 +; nextln: } + +; select x, k1, k1 should be constant propagated +function %constant_propagated(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = select v4, v5, v5 + v7 = icmp eq v6, v5 + return v7 +} + +; check: function %constant_propagated(i64) -> i8 fast { +; check: block0(v2: i64): +; nextln: v17 = iconst.i8 1 +; nextln: return v17 +; nextln: } + +function %a(i64) -> i8 { +block0(v0: i64): + v1 = iconst.i64 6 + v3 = iconst.i64 7 + v4 = select v0, v1, v3 + v5 = icmp eq v4, v1 + return v5 +} + +; check: function %a(i64) -> i8 fast { +; check: block0(v0: i64): +; nextln: v6 = iconst.i64 0 +; nextln: v7 = icmp ne v0, v6 ; v6 = 0 +; nextln: return v7 +; nextln: } diff --git a/cranelift/filetests/filetests/egraph/issue-11578-semantics.clif b/cranelift/filetests/filetests/egraph/issue-11578-semantics.clif new file mode 100644 index 000000000000..7aa5ec4e8be8 --- /dev/null +++ b/cranelift/filetests/filetests/egraph/issue-11578-semantics.clif @@ -0,0 +1,96 @@ +test interpret +test run +set opt_level=none +target x86_64 +target aarch64 +set opt_level=speed +target x86_64 +target aarch64 + +function %eq_k1(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp eq v7, v5 + return v8 +} + +; run: %eq_k1(0) == 1 + +function %eq_k2(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp eq v7, v6 + return v8 +} + +; run: %eq_k2(0) == 0 + +function %ne_k1(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp ne v7, v5 + return v8 +} + +; run: %ne_k1(0) == 0 + +function %ne_k2(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = iconst.i64 7 + v7 = select v4, v5, v6 + v8 = icmp ne v7, v6 + return v8 +} + +; run: %ne_k2(0) == 1 + +; select x, k1, k1 should be constant propagated +function %constant_propagated(i64) -> i8 { +block0(v2: i64): + v14 = iconst.i64 -562949953421310 + v3 = band v2, v14 + v16 = iconst.i64 0 + v4 = icmp eq v3, v16 + v5 = iconst.i64 6 + v6 = select v4, v5, v5 + v7 = icmp eq v6, v5 + return v7 +} + +; run: %constant_propagated(0) == 1 + +function %non_icmp_inner(i64) -> i8 { +block0(v0: i64): + v1 = iconst.i64 6 + v3 = iconst.i64 7 + v4 = select v0, v1, v3 + v5 = icmp eq v4, v1 + return v5 +} + +; run: %non_icmp_inner(0) == 0 +; run: %non_icmp_inner(1) == 1 +; run: %non_icmp_inner(5) == 1