diff --git a/cranelift/codegen/meta/src/isa/x86/legalize.rs b/cranelift/codegen/meta/src/isa/x86/legalize.rs index c6161cf43b..0d0ab76a57 100644 --- a/cranelift/codegen/meta/src/isa/x86/legalize.rs +++ b/cranelift/codegen/meta/src/isa/x86/legalize.rs @@ -319,6 +319,8 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct ], ); + group.custom_legalize(ineg, "convert_ineg"); + group.build_and_add_to(&mut shared.transform_groups); let mut narrow = TransformGroupBuilder::new( @@ -612,4 +614,17 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct narrow.custom_legalize(ineg, "convert_ineg"); narrow.build_and_add_to(&mut shared.transform_groups); + + let mut widen = TransformGroupBuilder::new( + "x86_widen", + r#" + Legalize instructions by widening. + + Use x86-specific instructions if needed."#, + ) + .isa("x86") + .chain_with(shared.transform_groups.by_name("widen").id); + + widen.custom_legalize(ineg, "convert_ineg"); + widen.build_and_add_to(&mut shared.transform_groups); } diff --git a/cranelift/codegen/meta/src/isa/x86/mod.rs b/cranelift/codegen/meta/src/isa/x86/mod.rs index ab1b5b4053..519ad884ff 100644 --- a/cranelift/codegen/meta/src/isa/x86/mod.rs +++ b/cranelift/codegen/meta/src/isa/x86/mod.rs @@ -32,16 +32,15 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let mut x86_32 = CpuMode::new("I32"); let expand_flags = shared_defs.transform_groups.by_name("expand_flags"); - let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags"); - let widen = shared_defs.transform_groups.by_name("widen"); + let x86_widen = shared_defs.transform_groups.by_name("x86_widen"); let x86_narrow = shared_defs.transform_groups.by_name("x86_narrow"); let x86_expand = shared_defs.transform_groups.by_name("x86_expand"); x86_32.legalize_monomorphic(expand_flags); - x86_32.legalize_default(narrow_flags); + x86_32.legalize_default(x86_narrow); x86_32.legalize_type(B1, expand_flags); - x86_32.legalize_type(I8, widen); - x86_32.legalize_type(I16, widen); + x86_32.legalize_type(I8, x86_widen); + x86_32.legalize_type(I16, x86_widen); x86_32.legalize_type(I32, x86_expand); x86_32.legalize_value_type(ReferenceType(R32), x86_expand); x86_32.legalize_type(F32, x86_expand); @@ -50,8 +49,8 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { x86_64.legalize_monomorphic(expand_flags); x86_64.legalize_default(x86_narrow); x86_64.legalize_type(B1, expand_flags); - x86_64.legalize_type(I8, widen); - x86_64.legalize_type(I16, widen); + x86_64.legalize_type(I8, x86_widen); + x86_64.legalize_type(I16, x86_widen); x86_64.legalize_type(I32, x86_expand); x86_64.legalize_type(I64, x86_expand); x86_64.legalize_value_type(ReferenceType(R64), x86_expand); diff --git a/cranelift/codegen/src/isa/x86/enc_tables.rs b/cranelift/codegen/src/isa/x86/enc_tables.rs index 947b315cd2..a93be1d658 100644 --- a/cranelift/codegen/src/isa/x86/enc_tables.rs +++ b/cranelift/codegen/src/isa/x86/enc_tables.rs @@ -1213,7 +1213,7 @@ fn convert_insertlane( } } -/// For SIMD negation, convert an `ineg` to a `vconst + isub`. +/// For SIMD or scalar integer negation, convert `ineg` to `vconst + isub` or `iconst + isub`. fn convert_ineg( inst: ir::Inst, func: &mut ir::Function, @@ -1229,10 +1229,16 @@ fn convert_ineg( } = pos.func.dfg[inst] { let value_type = pos.func.dfg.value_type(arg); - if value_type.is_vector() && value_type.lane_type().is_int() { + let zero_value = if value_type.is_vector() && value_type.lane_type().is_int() { let zero_immediate = pos.func.dfg.constants.insert(vec![0; 16].into()); - let zero_value = pos.ins().vconst(value_type, zero_immediate); // this should be legalized to a PXOR - pos.func.dfg.replace(inst).isub(zero_value, arg); - } + pos.ins().vconst(value_type, zero_immediate) // this should be legalized to a PXOR + } else if value_type.is_int() { + pos.ins().iconst(value_type, 0) + } else { + panic!("Can't convert ineg of type {}", value_type) + }; + pos.func.dfg.replace(inst).isub(zero_value, arg); + } else { + unreachable!() } } diff --git a/cranelift/filetests/filetests/isa/x86/legalize-custom.clif b/cranelift/filetests/filetests/isa/x86/legalize-custom.clif index c2bc6bec19..3ee674d66a 100644 --- a/cranelift/filetests/filetests/isa/x86/legalize-custom.clif +++ b/cranelift/filetests/filetests/isa/x86/legalize-custom.clif @@ -90,3 +90,44 @@ block0(v0: f32, v1: f32): ; check: $done(v2: f32): ; nextln: return v2 } + +function %ineg_legalized_i8() { +block0: + v0 = iconst.i8 1 + v1 = ineg v0 + ; check: v2 = iconst.i32 1 + ; nextln: v0 = ireduce.i8 v2 + ; nextln: v3 = iconst.i8 0 + ; nextln: v4 = uextend.i32 v3 + ; nextln: v5 = uextend.i32 v0 + ; nextln: v6 = isub v4, v5 + ; nextln: v1 = ireduce.i8 v6 + + return +} + +function %ineg_legalized_i16() { +block0: + v0 = iconst.i16 1 + v1 = ineg v0 + ; check: v2 = iconst.i32 1 + ; nextln: v0 = ireduce.i16 v2 + ; nextln: v3 = iconst.i16 0 + ; nextln: v4 = uextend.i32 v3 + ; nextln: v5 = uextend.i32 v0 + ; nextln: v6 = isub v4, v5 + ; nextln: v1 = ireduce.i16 v6 + + return +} + +function %ineg_legalized_i32() { +block0: + v0 = iconst.i32 1 + v1 = ineg v0 + ; check: v0 = iconst.i32 1 + ; nextln: v2 = iconst.i32 0 + ; nextln: v1 = isub v2, v0 + + return +} diff --git a/cranelift/filetests/filetests/isa/x86/legalize-i64.clif b/cranelift/filetests/filetests/isa/x86/legalize-i64.clif index 0d1eea5152..94fbc82015 100644 --- a/cranelift/filetests/filetests/isa/x86/legalize-i64.clif +++ b/cranelift/filetests/filetests/isa/x86/legalize-i64.clif @@ -338,3 +338,20 @@ block0(v1: i64): ; nextln: v10 = bor $b1, $c2 return v10 } + +function %ineg_legalized_i64() { +block0: + v0 = iconst.i64 1 + v1 = ineg v0 + ; check: v2 = iconst.i32 1 + ; nextln: v3 = iconst.i32 0 + ; nextln: v0 = iconcat v2, v3 + ; nextln: v5 = iconst.i32 0 + ; nextln: v6 = iconst.i32 0 + ; nextln: v4 = iconcat v5, v6 + ; nextln: v7, v8 = isub_ifbout v5, v2 + ; nextln: v9 = isub_ifbin v6, v3, v8 + ; nextln: v1 = iconcat v7, v9 + + return +} diff --git a/cranelift/filetests/filetests/isa/x86/legalize-ineg-x86_64.clif b/cranelift/filetests/filetests/isa/x86/legalize-ineg-x86_64.clif new file mode 100644 index 0000000000..fac17d6ff1 --- /dev/null +++ b/cranelift/filetests/filetests/isa/x86/legalize-ineg-x86_64.clif @@ -0,0 +1,13 @@ +; Test the custom legalization of ineg.i64 on x86_64. +test legalizer +target x86_64 + +function %ineg_legalized_i64() { +block0: + v0 = iconst.i64 1 + v1 = ineg v0 + ; check: v0 = iconst.i64 1 + ; nextln: v2 = iconst.i64 0 + ; nextln: v1 = isub v2, v0 + return +}