diff --git a/cranelift/codegen/meta/src/isa/x86/legalize.rs b/cranelift/codegen/meta/src/isa/x86/legalize.rs index 57057ce6bb..61389729f5 100644 --- a/cranelift/codegen/meta/src/isa/x86/legalize.rs +++ b/cranelift/codegen/meta/src/isa/x86/legalize.rs @@ -36,6 +36,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct let iadd = insts.by_name("iadd"); let iconst = insts.by_name("iconst"); let imul = insts.by_name("imul"); + let ineg = insts.by_name("ineg"); let insertlane = insts.by_name("insertlane"); let isub = insts.by_name("isub"); let popcnt = insts.by_name("popcnt"); @@ -385,6 +386,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct narrow.custom_legalize(shuffle, "convert_shuffle"); narrow.custom_legalize(extractlane, "convert_extractlane"); narrow.custom_legalize(insertlane, "convert_insertlane"); + narrow.custom_legalize(ineg, "convert_ineg"); narrow.build_and_add_to(&mut shared.transform_groups); } diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 1f0e629a2e..d8f5474c29 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -1704,6 +1704,17 @@ pub(crate) fn define( .operands_out(vec![a]), ); + ig.push( + Inst::new( + "ineg", + r#" + Integer negation: `a := -x \pmod{2^B}`. + "#, + ) + .operands_in(vec![x]) + .operands_out(vec![a]), + ); + ig.push( Inst::new( "imul", diff --git a/cranelift/codegen/src/isa/x86/enc_tables.rs b/cranelift/codegen/src/isa/x86/enc_tables.rs index 94333116e6..93adca0c25 100644 --- a/cranelift/codegen/src/isa/x86/enc_tables.rs +++ b/cranelift/codegen/src/isa/x86/enc_tables.rs @@ -5,6 +5,7 @@ use crate::bitset::BitSet; use crate::cursor::{Cursor, FuncCursor}; use crate::flowgraph::ControlFlowGraph; use crate::ir::condcodes::{FloatCC, IntCC}; +use crate::ir::immediates::V128Imm; use crate::ir::types::*; use crate::ir::{self, Function, Inst, InstBuilder}; use crate::isa::constraints::*; @@ -1090,3 +1091,27 @@ fn convert_insertlane( } } } + +/// For SIMD negation, convert an `ineg` to a `vconst + isub`. +fn convert_ineg( + inst: ir::Inst, + func: &mut ir::Function, + _cfg: &mut ControlFlowGraph, + _isa: &dyn TargetIsa, +) { + let mut pos = FuncCursor::new(func).at_inst(inst); + pos.use_srcloc(inst); + + if let ir::InstructionData::Unary { + opcode: ir::Opcode::Ineg, + arg, + } = 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_immediate = pos.func.dfg.constants.insert(V128Imm::from(0).to_vec()); + 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); + } + } +} diff --git a/cranelift/filetests/filetests/isa/x86/simd-arithmetic.clif b/cranelift/filetests/filetests/isa/x86/simd-arithmetic.clif index 64b6e854e7..8244177728 100644 --- a/cranelift/filetests/filetests/isa/x86/simd-arithmetic.clif +++ b/cranelift/filetests/filetests/isa/x86/simd-arithmetic.clif @@ -1,5 +1,6 @@ test run test binemit +test legalizer set enable_simd target x86_64 skylake @@ -85,3 +86,37 @@ ebb0(v0: i8x16 [%xmm3], v1: i8x16 [%xmm4]): [-, %xmm3] v2 = isub v0, v1 ; bin: 66 0f f8 dc return v2 } + +function %ineg_i32x4() -> b1 { +ebb0: + v0 = vconst.i32x4 [1 1 1 1] + v2 = ineg v0 + ; check: v5 = vconst.i32x4 0x00 + ; nextln: v2 = isub v5, v0 + + v3 = extractlane v2, 0 + v4 = icmp_imm eq v3, -1 + + return v4 ; bin: c3 +} +; run + +function %ineg_legalized() { +ebb0: + v0 = vconst.i8x16 0x00 + v1 = ineg v0 + ; check: v6 = vconst.i8x16 0x00 + ; nextln: v1 = isub v6, v0 + + v2 = raw_bitcast.i16x8 v0 + v3 = ineg v2 + ; check: v7 = vconst.i16x8 0x00 + ; nextln: v3 = isub v7, v2 + + v4 = raw_bitcast.i64x2 v0 + v5 = ineg v4 + ; check: v8 = vconst.i64x2 0x00 + ; nextln: v5 = isub v8, v4 + + return ; bin: c3 +} diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index 9dbd9d7463..ce2aa8dab7 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -1004,6 +1004,10 @@ pub fn translate_operator( let (a, b) = state.pop2(); state.push1(builder.ins().isub(a, b)) } + Operator::I8x16Neg | Operator::I16x8Neg | Operator::I32x4Neg | Operator::I64x2Neg => { + let a = state.pop1(); + state.push1(builder.ins().ineg(a)) + } Operator::I8x16Eq | Operator::I8x16Ne | Operator::I8x16LtS @@ -1051,7 +1055,6 @@ pub fn translate_operator( | Operator::V128Or | Operator::V128Xor | Operator::V128Bitselect - | Operator::I8x16Neg | Operator::I8x16AnyTrue | Operator::I8x16AllTrue | Operator::I8x16Shl @@ -1062,7 +1065,6 @@ pub fn translate_operator( | Operator::I8x16SubSaturateS | Operator::I8x16SubSaturateU | Operator::I8x16Mul - | Operator::I16x8Neg | Operator::I16x8AnyTrue | Operator::I16x8AllTrue | Operator::I16x8Shl @@ -1073,14 +1075,12 @@ pub fn translate_operator( | Operator::I16x8SubSaturateS | Operator::I16x8SubSaturateU | Operator::I16x8Mul - | Operator::I32x4Neg | Operator::I32x4AnyTrue | Operator::I32x4AllTrue | Operator::I32x4Shl | Operator::I32x4ShrS | Operator::I32x4ShrU | Operator::I32x4Mul - | Operator::I64x2Neg | Operator::I64x2AnyTrue | Operator::I64x2AllTrue | Operator::I64x2Shl