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 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);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1004,6 +1004,10 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
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<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::V128Or
|
||||
| Operator::V128Xor
|
||||
| Operator::V128Bitselect
|
||||
| Operator::I8x16Neg
|
||||
| Operator::I8x16AnyTrue
|
||||
| Operator::I8x16AllTrue
|
||||
| Operator::I8x16Shl
|
||||
@@ -1062,7 +1065,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::I8x16SubSaturateS
|
||||
| Operator::I8x16SubSaturateU
|
||||
| Operator::I8x16Mul
|
||||
| Operator::I16x8Neg
|
||||
| Operator::I16x8AnyTrue
|
||||
| Operator::I16x8AllTrue
|
||||
| Operator::I16x8Shl
|
||||
@@ -1073,14 +1075,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| 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
|
||||
|
||||
Reference in New Issue
Block a user