Add x86 legalization for SIMD ineg
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user