cranelift: Add narrower and wider constraints to the instruction DSL (#6013)

* Add narrower and wider constraints to the instruction DSL

* Add docs to narrower/wider operands

* Update cranelift/codegen/meta/src/cdsl/instructions.rs

Co-authored-by: Jamey Sharp <jamey@minilop.net>

* Fix assertion message

* Simplify upper bounds for the wider constraint

* Remove additional unnecessary cases in the verifier

* Remove unused variables

* Remove changes to is_ctrl_typevar_candidate

These changes were only necessary when the type returned by an
instruction was a variable constrained by narrow or widen. As we have
switched to requiring that constraints must appear on argument types and
not return types, these changes were not longer necessary.

---------

Co-authored-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
Trevor Elliott
2023-03-14 09:34:17 -07:00
committed by GitHub
parent 5c1b468648
commit f5ad74e546
6 changed files with 145 additions and 111 deletions

View File

@@ -202,6 +202,32 @@ impl TypeVar {
"can't halve a scalar type"
);
}
DerivedFunc::Narrower => {
assert_eq!(
*ts.lanes.iter().max().unwrap(),
1,
"The `narrower` constraint does not apply to vectors"
);
assert!(
(!ts.ints.is_empty() || !ts.floats.is_empty())
&& ts.refs.is_empty()
&& ts.dynamic_lanes.is_empty(),
"The `narrower` constraint only applies to scalar ints or floats"
);
}
DerivedFunc::Wider => {
assert_eq!(
*ts.lanes.iter().max().unwrap(),
1,
"The `wider` constraint does not apply to vectors"
);
assert!(
(!ts.ints.is_empty() || !ts.floats.is_empty())
&& ts.refs.is_empty()
&& ts.dynamic_lanes.is_empty(),
"The `wider` constraint only applies to scalar ints or floats"
);
}
DerivedFunc::LaneOf | DerivedFunc::AsBool | DerivedFunc::DynamicToVector => {
/* no particular assertions */
}
@@ -241,6 +267,16 @@ impl TypeVar {
pub fn dynamic_to_vector(&self) -> TypeVar {
self.derived(DerivedFunc::DynamicToVector)
}
/// Make a new [TypeVar] that includes all types narrower than self.
pub fn narrower(&self) -> TypeVar {
self.derived(DerivedFunc::Narrower)
}
/// Make a new [TypeVar] that includes all types wider than self.
pub fn wider(&self) -> TypeVar {
self.derived(DerivedFunc::Wider)
}
}
impl Into<TypeVar> for &TypeVar {
@@ -302,6 +338,8 @@ pub(crate) enum DerivedFunc {
SplitLanes,
MergeLanes,
DynamicToVector,
Narrower,
Wider,
}
impl DerivedFunc {
@@ -314,6 +352,8 @@ impl DerivedFunc {
DerivedFunc::SplitLanes => "split_lanes",
DerivedFunc::MergeLanes => "merge_lanes",
DerivedFunc::DynamicToVector => "dynamic_to_vector",
DerivedFunc::Narrower => "narrower",
DerivedFunc::Wider => "wider",
}
}
}
@@ -391,6 +431,8 @@ impl TypeSet {
DerivedFunc::SplitLanes => self.half_width().double_vector(),
DerivedFunc::MergeLanes => self.double_width().half_vector(),
DerivedFunc::DynamicToVector => self.dynamic_to_vector(),
DerivedFunc::Narrower => self.clone(),
DerivedFunc::Wider => self.clone(),
}
}

View File

@@ -3064,12 +3064,6 @@ pub(crate) fn define(
TypeSetBuilder::new().ints(Interval::All).build(),
);
let IntTo = &TypeVar::new(
"IntTo",
"A smaller integer type",
TypeSetBuilder::new().ints(Interval::All).build(),
);
ig.push(
Inst::new(
"ireduce",
@@ -3081,8 +3075,9 @@ pub(crate) fn define(
"#,
&formats.unary,
)
.operands_in(vec![Operand::new("x", Int)])
.operands_out(vec![Operand::new("a", IntTo)]),
.operands_in(vec![Operand::new("x", &Int.wider())
.with_doc("A scalar integer type, wider than the controlling type")])
.operands_out(vec![Operand::new("a", Int)]),
);
let I16or32or64xN = &TypeVar::new(
@@ -3272,17 +3267,10 @@ pub(crate) fn define(
.operands_out(vec![Operand::new("a", I16x8)]),
);
{
let IntTo = &TypeVar::new(
"IntTo",
"A larger integer type with the same number of lanes",
TypeSetBuilder::new().ints(Interval::All).build(),
);
ig.push(
Inst::new(
"uextend",
r#"
ig.push(
Inst::new(
"uextend",
r#"
Convert `x` to a larger integer type by zero-extending.
Each lane in `x` is converted to a larger integer type by adding
@@ -3293,16 +3281,18 @@ pub(crate) fn define(
and each lane must not have fewer bits that the input lanes. If the
input and output types are the same, this is a no-op.
"#,
&formats.unary,
)
.operands_in(vec![Operand::new("x", Int)])
.operands_out(vec![Operand::new("a", IntTo)]),
);
&formats.unary,
)
.operands_in(vec![Operand::new("x", &Int.narrower()).with_doc(
"A scalar integer type, narrower than the controlling type",
)])
.operands_out(vec![Operand::new("a", Int)]),
);
ig.push(
Inst::new(
"sextend",
r#"
ig.push(
Inst::new(
"sextend",
r#"
Convert `x` to a larger integer type by sign-extending.
Each lane in `x` is converted to a larger integer type by replicating
@@ -3313,12 +3303,13 @@ pub(crate) fn define(
and each lane must not have fewer bits that the input lanes. If the
input and output types are the same, this is a no-op.
"#,
&formats.unary,
)
.operands_in(vec![Operand::new("x", Int)])
.operands_out(vec![Operand::new("a", IntTo)]),
);
}
&formats.unary,
)
.operands_in(vec![Operand::new("x", &Int.narrower()).with_doc(
"A scalar integer type, narrower than the controlling type",
)])
.operands_out(vec![Operand::new("a", Int)]),
);
let FloatScalar = &TypeVar::new(
"FloatScalar",
@@ -3326,12 +3317,6 @@ pub(crate) fn define(
TypeSetBuilder::new().floats(Interval::All).build(),
);
let FloatScalarTo = &TypeVar::new(
"FloatScalarTo",
"A scalar only floating point number",
TypeSetBuilder::new().floats(Interval::All).build(),
);
ig.push(
Inst::new(
"fpromote",
@@ -3349,8 +3334,10 @@ pub(crate) fn define(
"#,
&formats.unary,
)
.operands_in(vec![Operand::new("x", FloatScalar)])
.operands_out(vec![Operand::new("a", FloatScalarTo)]),
.operands_in(vec![Operand::new("x", &FloatScalar.narrower()).with_doc(
"A scalar only floating point number, narrower than the controlling type",
)])
.operands_out(vec![Operand::new("a", FloatScalar)]),
);
ig.push(
@@ -3370,8 +3357,10 @@ pub(crate) fn define(
"#,
&formats.unary,
)
.operands_in(vec![Operand::new("x", FloatScalar)])
.operands_out(vec![Operand::new("a", FloatScalarTo)]),
.operands_in(vec![Operand::new("x", &FloatScalar.wider()).with_doc(
"A scalar only floating point number, wider than the controlling type",
)])
.operands_out(vec![Operand::new("a", FloatScalar)]),
);
let F64x2 = &TypeVar::new(