Add x86 legalization for SIMD ineg

This commit is contained in:
Andrew Brown
2019-09-18 10:50:01 -07:00
parent ca1df499a0
commit ba393afd4d
5 changed files with 77 additions and 4 deletions

View File

@@ -36,6 +36,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
let iadd = insts.by_name("iadd"); let iadd = insts.by_name("iadd");
let iconst = insts.by_name("iconst"); let iconst = insts.by_name("iconst");
let imul = insts.by_name("imul"); let imul = insts.by_name("imul");
let ineg = insts.by_name("ineg");
let insertlane = insts.by_name("insertlane"); let insertlane = insts.by_name("insertlane");
let isub = insts.by_name("isub"); let isub = insts.by_name("isub");
let popcnt = insts.by_name("popcnt"); 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(shuffle, "convert_shuffle");
narrow.custom_legalize(extractlane, "convert_extractlane"); narrow.custom_legalize(extractlane, "convert_extractlane");
narrow.custom_legalize(insertlane, "convert_insertlane"); narrow.custom_legalize(insertlane, "convert_insertlane");
narrow.custom_legalize(ineg, "convert_ineg");
narrow.build_and_add_to(&mut shared.transform_groups); narrow.build_and_add_to(&mut shared.transform_groups);
} }

View File

@@ -1704,6 +1704,17 @@ pub(crate) fn define(
.operands_out(vec![a]), .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( ig.push(
Inst::new( Inst::new(
"imul", "imul",

View File

@@ -5,6 +5,7 @@ use crate::bitset::BitSet;
use crate::cursor::{Cursor, FuncCursor}; use crate::cursor::{Cursor, FuncCursor};
use crate::flowgraph::ControlFlowGraph; use crate::flowgraph::ControlFlowGraph;
use crate::ir::condcodes::{FloatCC, IntCC}; use crate::ir::condcodes::{FloatCC, IntCC};
use crate::ir::immediates::V128Imm;
use crate::ir::types::*; use crate::ir::types::*;
use crate::ir::{self, Function, Inst, InstBuilder}; use crate::ir::{self, Function, Inst, InstBuilder};
use crate::isa::constraints::*; 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);
}
}
}

View File

@@ -1,5 +1,6 @@
test run test run
test binemit test binemit
test legalizer
set enable_simd set enable_simd
target x86_64 skylake 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 [-, %xmm3] v2 = isub v0, v1 ; bin: 66 0f f8 dc
return v2 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
}

View File

@@ -1004,6 +1004,10 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
let (a, b) = state.pop2(); let (a, b) = state.pop2();
state.push1(builder.ins().isub(a, b)) 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::I8x16Eq
| Operator::I8x16Ne | Operator::I8x16Ne
| Operator::I8x16LtS | Operator::I8x16LtS
@@ -1051,7 +1055,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
| Operator::V128Or | Operator::V128Or
| Operator::V128Xor | Operator::V128Xor
| Operator::V128Bitselect | Operator::V128Bitselect
| Operator::I8x16Neg
| Operator::I8x16AnyTrue | Operator::I8x16AnyTrue
| Operator::I8x16AllTrue | Operator::I8x16AllTrue
| Operator::I8x16Shl | Operator::I8x16Shl
@@ -1062,7 +1065,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
| Operator::I8x16SubSaturateS | Operator::I8x16SubSaturateS
| Operator::I8x16SubSaturateU | Operator::I8x16SubSaturateU
| Operator::I8x16Mul | Operator::I8x16Mul
| Operator::I16x8Neg
| Operator::I16x8AnyTrue | Operator::I16x8AnyTrue
| Operator::I16x8AllTrue | Operator::I16x8AllTrue
| Operator::I16x8Shl | Operator::I16x8Shl
@@ -1073,14 +1075,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
| Operator::I16x8SubSaturateS | Operator::I16x8SubSaturateS
| Operator::I16x8SubSaturateU | Operator::I16x8SubSaturateU
| Operator::I16x8Mul | Operator::I16x8Mul
| Operator::I32x4Neg
| Operator::I32x4AnyTrue | Operator::I32x4AnyTrue
| Operator::I32x4AllTrue | Operator::I32x4AllTrue
| Operator::I32x4Shl | Operator::I32x4Shl
| Operator::I32x4ShrS | Operator::I32x4ShrS
| Operator::I32x4ShrU | Operator::I32x4ShrU
| Operator::I32x4Mul | Operator::I32x4Mul
| Operator::I64x2Neg
| Operator::I64x2AnyTrue | Operator::I64x2AnyTrue
| Operator::I64x2AllTrue | Operator::I64x2AllTrue
| Operator::I64x2Shl | Operator::I64x2Shl