diff --git a/cranelift/codegen/meta/src/isa/x86/legalize.rs b/cranelift/codegen/meta/src/isa/x86/legalize.rs index 8d9033d3a9..df0b88dc04 100644 --- a/cranelift/codegen/meta/src/isa/x86/legalize.rs +++ b/cranelift/codegen/meta/src/isa/x86/legalize.rs @@ -20,7 +20,9 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct // List of instructions. let insts = &shared.instructions; let band = insts.by_name("band"); + let band_not = insts.by_name("band_not"); let bitcast = insts.by_name("bitcast"); + let bitselect = insts.by_name("bitselect"); let bor = insts.by_name("bor"); let bnot = insts.by_name("bnot"); let bxor = insts.by_name("bxor"); @@ -431,6 +433,19 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct ); } + // SIMD select + for ty in ValueType::all_lane_types().filter(allowed_simd_type) { + let bitselect = bitselect.bind(vector(ty, sse_vector_size)); // must bind both x/y and c + narrow.legalize( + def!(d = bitselect(c, x, y)), + vec![ + def!(a = band(x, c)), + def!(b = band_not(y, c)), + def!(d = bor(a, b)), + ], + ); + } + narrow.custom_legalize(shuffle, "convert_shuffle"); narrow.custom_legalize(extractlane, "convert_extractlane"); narrow.custom_legalize(insertlane, "convert_insertlane"); diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index b9070c7f39..e13871fa3c 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -1199,6 +1199,22 @@ pub(crate) fn define( .operands_out(vec![a]), ); + let c = &operand_doc("c", Any, "Controlling value to test"); + ig.push( + Inst::new( + "bitselect", + r#" + Conditional select of bits. + + For each bit in `c`, this instruction selects the corresponding bit from `x` if the bit + in `c` is 1 and the corresponding bit from `y` if the bit in `c` is 0. See also: + `select`, `vselect`. + "#, + ) + .operands_in(vec![c, x, y]) + .operands_out(vec![a]), + ); + let x = &operand("x", Any); ig.push( diff --git a/cranelift/filetests/filetests/isa/x86/simd-bitwise-legalize.clif b/cranelift/filetests/filetests/isa/x86/simd-bitwise-legalize.clif index 9c728eb208..e8391c8a73 100644 --- a/cranelift/filetests/filetests/isa/x86/simd-bitwise-legalize.clif +++ b/cranelift/filetests/filetests/isa/x86/simd-bitwise-legalize.clif @@ -31,3 +31,15 @@ ebb0: ; nextln: v2 = x86_psra v1, v3 return v2 } + +function %bitselect_i16x8() -> i16x8 { +ebb0: + v0 = vconst.i16x8 [0 0 0 0 0 0 0 0] + v1 = vconst.i16x8 [0 0 0 0 0 0 0 0] + v2 = vconst.i16x8 [0 0 0 0 0 0 0 0] + v3 = bitselect v0, v1, v2 + ; check: v4 = band v1, v0 + ; nextln: v5 = band_not v2, v0 + ; nextln: v3 = bor v4, v5 + return v3 +} diff --git a/cranelift/filetests/filetests/isa/x86/simd-bitwise-run.clif b/cranelift/filetests/filetests/isa/x86/simd-bitwise-run.clif index 07c50bee0a..0c6eac6a10 100644 --- a/cranelift/filetests/filetests/isa/x86/simd-bitwise-run.clif +++ b/cranelift/filetests/filetests/isa/x86/simd-bitwise-run.clif @@ -105,3 +105,25 @@ ebb0: return v7 } ; run + +function %bitselect_i8x16() -> b1 { +ebb0: + v0 = vconst.i8x16 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255] ; the selector vector + v1 = vconst.i8x16 [127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42] ; for each 1-bit in v0 the bit of v1 is selected + v2 = vconst.i8x16 [42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127] ; for each 0-bit in v0 the bit of v2 is selected + v3 = bitselect v0, v1, v2 + + v4 = extractlane v3, 0 + v5 = icmp_imm eq v4, 42 + + v6 = extractlane v3, 1 + v7 = icmp_imm eq v6, 0 + + v8 = extractlane v3, 15 + v9 = icmp_imm eq v8, 42 + + v10 = band v5, v7 + v11 = band v10, v9 + return v11 +} +; run