Skip to content

Commit e13bb3d

Browse files
committed
Transform an limit into Requirement::Limit
In order to properly merge and split bundles, we need to propagate any limits to the registers available. Here we transform an `OperandConstraint::Limit` into a new `Requirement::Limit` and add merge rules: - when two limits meet we pick the smaller limit - when a limit meets a register we pick the limit - when a limit meets a fixed register, we pick the fixed register, but only if it fits under the limit
1 parent 60b4cb3 commit e13bb3d

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

src/ion/requirement.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,36 @@ impl RequirementConflictAt {
5858

5959
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6060
pub enum Requirement {
61-
FixedReg(PReg),
62-
FixedStack(PReg),
61+
Any,
6362
Register,
63+
FixedReg(PReg),
64+
Limit(usize),
6465
Stack,
65-
Any,
66+
FixedStack(PReg),
6667
}
6768
impl Requirement {
6869
#[inline(always)]
6970
pub fn merge(self, other: Requirement) -> Result<Requirement, RequirementConflict> {
71+
use Requirement::*;
72+
7073
match (self, other) {
71-
(other, Requirement::Any) | (Requirement::Any, other) => Ok(other),
72-
(Requirement::Register, Requirement::Register) => Ok(self),
73-
(Requirement::Stack, Requirement::Stack) => Ok(self),
74-
(Requirement::Register, Requirement::FixedReg(preg))
75-
| (Requirement::FixedReg(preg), Requirement::Register) => {
76-
Ok(Requirement::FixedReg(preg))
77-
}
78-
(Requirement::Stack, Requirement::FixedStack(preg))
79-
| (Requirement::FixedStack(preg), Requirement::Stack) => {
80-
Ok(Requirement::FixedStack(preg))
74+
// `Any` matches anything.
75+
(other, Any) | (Any, other) => Ok(other),
76+
// Same kinds match.
77+
(Register, Register) => Ok(self),
78+
(Stack, Stack) => Ok(self),
79+
(Limit(a), Limit(b)) => Ok(Limit(a.min(b))),
80+
(FixedReg(a), FixedReg(b)) if a == b => Ok(self),
81+
(FixedStack(a), FixedStack(b)) if a == b => Ok(self),
82+
// Limit a 'Register|FixedReg`.
83+
(Limit(a), Register) | (Register, Limit(a)) => Ok(Limit(a)),
84+
(Limit(a), FixedReg(b)) | (FixedReg(b), Limit(a)) if usize::from(a) > b.hw_enc() => {
85+
Ok(FixedReg(b))
8186
}
82-
(Requirement::FixedReg(a), Requirement::FixedReg(b)) if a == b => Ok(self),
83-
(Requirement::FixedStack(a), Requirement::FixedStack(b)) if a == b => Ok(self),
87+
// Constrain `Register|Stack` to `Fixed{Reg|Stack}`.
88+
(Register, FixedReg(preg)) | (FixedReg(preg), Register) => Ok(FixedReg(preg)),
89+
(Stack, FixedStack(preg)) | (FixedStack(preg), Stack) => Ok(FixedStack(preg)),
90+
// Fail otherwise.
8491
_ => Err(RequirementConflict),
8592
}
8693
}
@@ -89,15 +96,15 @@ impl Requirement {
8996
pub fn is_stack(self) -> bool {
9097
match self {
9198
Requirement::Stack | Requirement::FixedStack(..) => true,
92-
Requirement::Register | Requirement::FixedReg(..) => false,
99+
Requirement::Register | Requirement::FixedReg(..) | Requirement::Limit(..) => false,
93100
Requirement::Any => false,
94101
}
95102
}
96103

97104
#[inline(always)]
98105
pub fn is_reg(self) -> bool {
99106
match self {
100-
Requirement::Register | Requirement::FixedReg(..) => true,
107+
Requirement::Register | Requirement::FixedReg(..) | Requirement::Limit(..) => true,
101108
Requirement::Stack | Requirement::FixedStack(..) => false,
102109
Requirement::Any => false,
103110
}
@@ -116,6 +123,7 @@ impl<'a, F: Function> Env<'a, F> {
116123
}
117124
}
118125
OperandConstraint::Reg | OperandConstraint::Reuse(_) => Requirement::Register,
126+
OperandConstraint::Limit(max) => Requirement::Limit(max),
119127
OperandConstraint::Stack => Requirement::Stack,
120128
OperandConstraint::Any => Requirement::Any,
121129
}

0 commit comments

Comments
 (0)