Add ineg legalization for scalar integer types (#1385)
This commit is contained in:
@@ -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);
|
group.build_and_add_to(&mut shared.transform_groups);
|
||||||
|
|
||||||
let mut narrow = TransformGroupBuilder::new(
|
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.custom_legalize(ineg, "convert_ineg");
|
||||||
|
|
||||||
narrow.build_and_add_to(&mut shared.transform_groups);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,16 +32,15 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
|||||||
let mut x86_32 = CpuMode::new("I32");
|
let mut x86_32 = CpuMode::new("I32");
|
||||||
|
|
||||||
let expand_flags = shared_defs.transform_groups.by_name("expand_flags");
|
let expand_flags = shared_defs.transform_groups.by_name("expand_flags");
|
||||||
let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags");
|
let x86_widen = shared_defs.transform_groups.by_name("x86_widen");
|
||||||
let widen = shared_defs.transform_groups.by_name("widen");
|
|
||||||
let x86_narrow = shared_defs.transform_groups.by_name("x86_narrow");
|
let x86_narrow = shared_defs.transform_groups.by_name("x86_narrow");
|
||||||
let x86_expand = shared_defs.transform_groups.by_name("x86_expand");
|
let x86_expand = shared_defs.transform_groups.by_name("x86_expand");
|
||||||
|
|
||||||
x86_32.legalize_monomorphic(expand_flags);
|
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(B1, expand_flags);
|
||||||
x86_32.legalize_type(I8, widen);
|
x86_32.legalize_type(I8, x86_widen);
|
||||||
x86_32.legalize_type(I16, widen);
|
x86_32.legalize_type(I16, x86_widen);
|
||||||
x86_32.legalize_type(I32, x86_expand);
|
x86_32.legalize_type(I32, x86_expand);
|
||||||
x86_32.legalize_value_type(ReferenceType(R32), x86_expand);
|
x86_32.legalize_value_type(ReferenceType(R32), x86_expand);
|
||||||
x86_32.legalize_type(F32, 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_monomorphic(expand_flags);
|
||||||
x86_64.legalize_default(x86_narrow);
|
x86_64.legalize_default(x86_narrow);
|
||||||
x86_64.legalize_type(B1, expand_flags);
|
x86_64.legalize_type(B1, expand_flags);
|
||||||
x86_64.legalize_type(I8, widen);
|
x86_64.legalize_type(I8, x86_widen);
|
||||||
x86_64.legalize_type(I16, widen);
|
x86_64.legalize_type(I16, x86_widen);
|
||||||
x86_64.legalize_type(I32, x86_expand);
|
x86_64.legalize_type(I32, x86_expand);
|
||||||
x86_64.legalize_type(I64, x86_expand);
|
x86_64.legalize_type(I64, x86_expand);
|
||||||
x86_64.legalize_value_type(ReferenceType(R64), x86_expand);
|
x86_64.legalize_value_type(ReferenceType(R64), x86_expand);
|
||||||
|
|||||||
@@ -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(
|
fn convert_ineg(
|
||||||
inst: ir::Inst,
|
inst: ir::Inst,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
@@ -1229,10 +1229,16 @@ fn convert_ineg(
|
|||||||
} = pos.func.dfg[inst]
|
} = pos.func.dfg[inst]
|
||||||
{
|
{
|
||||||
let value_type = pos.func.dfg.value_type(arg);
|
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_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.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);
|
pos.func.dfg.replace(inst).isub(zero_value, arg);
|
||||||
}
|
} else {
|
||||||
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,3 +90,44 @@ block0(v0: f32, v1: f32):
|
|||||||
; check: $done(v2: f32):
|
; check: $done(v2: f32):
|
||||||
; nextln: return v2
|
; 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -338,3 +338,20 @@ block0(v1: i64):
|
|||||||
; nextln: v10 = bor $b1, $c2
|
; nextln: v10 = bor $b1, $c2
|
||||||
return v10
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user