Skip to content

Commit 486e88d

Browse files
committed
Redesigned effect lattice and made lots of improvements
1 parent 481109b commit 486e88d

3 files changed

Lines changed: 63 additions & 60 deletions

File tree

zjit/src/hir_effect/gen_hir_effect.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ def to_graphviz type
4545
# Start at Any. All types are subtypes of Any.
4646
any = Type.new "Any"
4747
# Build the effect universe.
48-
world = any.subtype "World"
49-
other = world.subtype "Other"
50-
frame = world.subtype "Frame"
48+
allocator = any.subtype "Allocator"
49+
control = any.subtype "Control"
50+
memory = any.subtype "Memory"
51+
other = memory.subtype "Other"
52+
frame = memory.subtype "Frame"
5153
pc = frame.subtype "PC"
5254
locals = frame.subtype "Locals"
5355
stack = frame.subtype "Stack"
@@ -84,8 +86,8 @@ def final_type name, base: $object, c_name: nil
8486

8587
# Assign individual bits to type leaves and union bit patterns to nodes with subtypes
8688
num_bits = 0
87-
$bits = {"None" => ["0#{$int_label}"]}
88-
$numeric_bits = {"None" => 0}
89+
$bits = {"Empty" => ["0#{$int_label}"]}
90+
$numeric_bits = {"Empty" => 0}
8991
Set[any, *any.all_subtypes].sort_by(&:name).each {|type|
9092
subtypes = type.subtypes
9193
if subtypes.empty?

zjit/src/hir_effect/hir_effect.inc.rs

Lines changed: 20 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zjit/src/hir_effect/mod.rs

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! High-level intermediate representation effects.
22
33
// TODO(Jacob): Replace Effect with EffectSet and EffectPair with Effect
4-
//
54

65
#![allow(non_upper_case_globals)]
76
use crate::hir::{PtrPrintMap};
@@ -58,25 +57,22 @@ pub struct EffectPrinter<'a> {
5857
impl<'a> std::fmt::Display for EffectPrinter<'a> {
5958
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
6059
let effect = self.inner;
61-
// If there's an exact match, write and return
62-
for (name, pattern) in bits::AllBitPatterns {
63-
if effect.bits == pattern {
64-
write!(f, "{name}")?;
65-
return Ok(());
66-
}
67-
}
68-
// Otherwise, find the most descriptive sub-effect write it, and mask out the handled bits.
69-
// Most descriptive means "highest number of bits set while remaining fully contained within `effect`"
70-
debug_assert!(bits::AllBitPatterns.is_sorted_by(|(_, left), (_, right)| left > right));
7160
let mut bits = effect.bits;
7261
let mut sep = "";
62+
// First, make sure patterns are sorted from higher order bits to lower order.
63+
// For each match where `bits` contains the pattern, we mask off the matched bits
64+
// and continue searching for matches until bits == 0.
65+
// Our first match could be exact and may not require a separator, but all subsequent
66+
// matches do.
67+
debug_assert!(bits::AllBitPatterns.is_sorted_by(|(_, left), (_, right)| left > right));
7368
for (name, pattern) in bits::AllBitPatterns {
74-
if bits == 0 { break; }
7569
if (bits & pattern) == pattern {
7670
write!(f, "{sep}{name}")?;
7771
sep = "|";
7872
bits &= !pattern;
7973
}
74+
// The `sep != ""` check allows us to handle the effects::None case gracefully.
75+
if (bits == 0) & (sep != "") { break; }
8076
}
8177
debug_assert_eq!(bits, 0, "Should have eliminated all bits by iterating over all patterns");
8278
Ok(())
@@ -89,6 +85,7 @@ impl std::fmt::Display for Effect {
8985
}
9086
}
9187

88+
// TODO(Jacob): Modify union and effect to work on an arbitrary number of args
9289
impl Effect {
9390
const fn from_bits(bits: EffectBits) -> Effect {
9491
Effect { bits }
@@ -116,7 +113,7 @@ impl Effect {
116113
}
117114

118115
pub fn overlaps(&self, other: Effect) -> bool {
119-
!self.intersect(other).bit_equal(effects::None)
116+
!self.intersect(other).bit_equal(effects::Empty)
120117
}
121118

122119
pub fn print(self, ptr_map: &PtrPrintMap) -> EffectPrinter<'_> {
@@ -145,24 +142,22 @@ mod tests {
145142

146143
#[test]
147144
fn none_is_subeffect_of_everything() {
148-
assert_subeffect(effects::None, effects::None);
149-
assert_subeffect(effects::None, effects::Any);
150-
assert_subeffect(effects::None, effects::World);
151-
assert_subeffect(effects::None, effects::Frame);
152-
assert_subeffect(effects::None, effects::Other);
153-
assert_subeffect(effects::None, effects::Stack);
154-
assert_subeffect(effects::None, effects::Locals);
155-
assert_subeffect(effects::None, effects::PC);
145+
assert_subeffect(effects::Empty, effects::Empty);
146+
assert_subeffect(effects::Empty, effects::Any);
147+
assert_subeffect(effects::Empty, effects::Control);
148+
assert_subeffect(effects::Empty, effects::Frame);
149+
assert_subeffect(effects::Empty, effects::Stack);
150+
assert_subeffect(effects::Empty, effects::Locals);
151+
assert_subeffect(effects::Empty, effects::Allocator);
156152
}
157153

158154
#[test]
159155
fn everything_is_subeffect_of_any() {
160-
assert_subeffect(effects::None, effects::Any);
156+
assert_subeffect(effects::Empty, effects::Any);
161157
assert_subeffect(effects::Any, effects::Any);
162-
assert_subeffect(effects::World, effects::Any);
158+
assert_subeffect(effects::Control, effects::Any);
163159
assert_subeffect(effects::Frame, effects::Any);
164-
assert_subeffect(effects::Other, effects::Any);
165-
assert_subeffect(effects::Stack, effects::Any);
160+
assert_subeffect(effects::Memory, effects::Any);
166161
assert_subeffect(effects::Locals, effects::Any);
167162
assert_subeffect(effects::PC, effects::Any);
168163
}
@@ -173,7 +168,7 @@ mod tests {
173168
for i in [0, 1, 4, 6, 10, 15] {
174169
let e = Effect::from_bits(i);
175170
// Testing on bottom, top, and some arbitrary element in the middle
176-
assert_subeffect(effects::None, effects::None.union(e));
171+
assert_subeffect(effects::Empty, effects::Empty.union(e));
177172
assert_subeffect(effects::Any, effects::Any.union(e));
178173
assert_subeffect(effects::Frame, effects::Frame.union(e));
179174
}
@@ -185,7 +180,7 @@ mod tests {
185180
for i in [0, 3, 6, 8, 15] {
186181
let e = Effect::from_bits(i);
187182
// Testing on bottom, top, and some arbitrary element in the middle
188-
assert_subeffect(effects::None.intersect(e), effects::None);
183+
assert_subeffect(effects::Empty.intersect(e), effects::Empty);
189184
assert_subeffect(effects::Any.intersect(e), effects::Any);
190185
assert_subeffect(effects::Frame.intersect(e), effects::Frame);
191186
}
@@ -194,8 +189,8 @@ mod tests {
194189
#[test]
195190
fn self_is_included() {
196191
assert!(effects::Stack.includes(effects::Stack));
197-
assert!(effects::Other.includes(effects::Other));
198-
assert!(effects::Stack.includes(effects::Stack));
192+
assert!(effects::Any.includes(effects::Any));
193+
assert!(effects::Empty.includes(effects::Empty));
199194
}
200195

201196
#[test]
@@ -212,29 +207,28 @@ mod tests {
212207
}
213208

214209
#[test]
215-
fn world_includes_other() {
216-
assert_subeffect(effects::Other, effects::World);
217-
}
218-
219-
#[test]
220-
fn any_includes_world_and_frame() {
221-
assert_subeffect(effects::World, effects::Any);
210+
fn any_includes_some_subeffects() {
211+
assert_subeffect(effects::Allocator, effects::Any);
222212
assert_subeffect(effects::Frame, effects::Any);
213+
assert_subeffect(effects::Memory, effects::Any);
223214
}
224215

225216
#[test]
226217
fn display_exact_bits_match() {
227-
assert_eq!(format!("{}", effects::None), "None");
218+
assert_eq!(format!("{}", effects::Empty), "Empty");
228219
assert_eq!(format!("{}", effects::PC), "PC");
229-
assert_eq!(format!("{}", effects::Other), "Other");
220+
assert_eq!(format!("{}", effects::Any), "Any");
221+
assert_eq!(format!("{}", effects::Frame), "Frame");
222+
assert_eq!(format!("{}", effects::Stack.union(effects::Locals.union(effects::PC))), "Frame");
230223
}
231224

232-
// TODO(Jacob): Figure out why these last two comments cause test failures
233225
#[test]
234226
fn display_multiple_bits() {
235-
assert_eq!(format!("{}", effects::Frame), "Frame");
227+
let union = effects::Stack.union(effects::Locals);
236228
assert_eq!(format!("{}", effects::Stack.union(effects::Locals.union(effects::PC))), "Frame");
237-
// assert_eq!(format!("{}", effects::Stack.union(effects::Locals)), "Locals|Stack");
238-
// assert_eq!(format!("{}", effects::Any), "Any");
229+
println!("{}", union);
230+
println!("{}", effects::Stack.union(effects::Locals.union(effects::PC)));
231+
assert_eq!(format!("{}", effects::Stack.union(effects::Locals)), "Stack|Locals");
232+
assert_eq!(format!("{}", effects::PC.union(effects::Allocator)), "PC|Allocator");
239233
}
240234
}

0 commit comments

Comments
 (0)