Add ineg legalization for scalar integer types (#1385)

This commit is contained in:
Peter Delevoryas
2020-02-14 13:16:02 -08:00
committed by GitHub
parent 4d8cf563f3
commit 18b40d1101
6 changed files with 103 additions and 12 deletions

View File

@@ -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);
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.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);
}

View File

@@ -32,16 +32,15 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let mut x86_32 = CpuMode::new("I32");
let expand_flags = shared_defs.transform_groups.by_name("expand_flags");
let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags");
let widen = shared_defs.transform_groups.by_name("widen");
let x86_widen = shared_defs.transform_groups.by_name("x86_widen");
let x86_narrow = shared_defs.transform_groups.by_name("x86_narrow");
let x86_expand = shared_defs.transform_groups.by_name("x86_expand");
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(I8, widen);
x86_32.legalize_type(I16, widen);
x86_32.legalize_type(I8, x86_widen);
x86_32.legalize_type(I16, x86_widen);
x86_32.legalize_type(I32, x86_expand);
x86_32.legalize_value_type(ReferenceType(R32), 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_default(x86_narrow);
x86_64.legalize_type(B1, expand_flags);
x86_64.legalize_type(I8, widen);
x86_64.legalize_type(I16, widen);
x86_64.legalize_type(I8, x86_widen);
x86_64.legalize_type(I16, x86_widen);
x86_64.legalize_type(I32, x86_expand);
x86_64.legalize_type(I64, x86_expand);
x86_64.legalize_value_type(ReferenceType(R64), x86_expand);

View File

@@ -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(
inst: ir::Inst,
func: &mut ir::Function,
@@ -1229,10 +1229,16 @@ fn convert_ineg(
} = 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_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_value = pos.ins().vconst(value_type, zero_immediate); // this should be legalized to a PXOR
pos.func.dfg.replace(inst).isub(zero_value, arg);
}
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);
} else {
unreachable!()
}
}

View File

@@ -90,3 +90,44 @@ block0(v0: f32, v1: f32):
; check: $done(v2: f32):
; 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
}

View File

@@ -338,3 +338,20 @@ block0(v1: i64):
; nextln: v10 = bor $b1, $c2
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
}

View File

@@ -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
}