Skip to content

Commit 94a42d4

Browse files
committed
Refactor Effect and EffectPair, fix printer
1 parent b24dd7b commit 94a42d4

1 file changed

Lines changed: 42 additions & 41 deletions

File tree

zjit/src/hir_effect/mod.rs

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,24 @@ use crate::hir::{PtrPrintMap};
66
// NOTE: Effect very intentionally does not support Eq or PartialEq; we almost never want to check
77
// bit equality of types in the compiler but instead check subtyping, intersection, union, etc.
88
#[derive(Copy, Clone, Debug)]
9-
// TODO(Jacob): Update this comment
10-
/// The main work horse of intraprocedural type inference and specialization. The main interfaces
9+
/// The main work horse of effect inference and specialization. The main interfaces
1110
/// will look like:
1211
///
1312
/// * is effect A a subset of effect B
1413
/// * union/meet effect A and effect B
1514
///
1615
/// Most questions can be rewritten in terms of these operations.
17-
// TODO(Jacob): Convert from read_bits and write_bits to just bits
18-
// Rename this struct to be about a memory location, with another struct
19-
// of Effects that combines the two.
16+
17+
// TODO(Jacob): Fix up comments for Effect and EffectPair
18+
// Make it clear why we need both of these. Effect handles all lattice operations
19+
// EffectPair is our typical use case because we care about having both read and write effects
2020
pub struct Effect {
21+
bits: u64
22+
}
23+
24+
pub struct EffectPair {
2125
/// Unlike ZJIT's type system, effects do not have a notion of subclasses.
22-
/// Instead of specializations, the Effects struct contains two bitsets.
26+
/// Instead of specializations, the Effects struct contains two Effect bitsets.
2327
/// We have read and write bitsets, both representing the same lattice.
2428
///
2529
/// TODO(Jacob): Provide an example about why we split based on read / write
@@ -28,31 +32,37 @@ pub struct Effect {
2832
/// This should include top, bottom, and how you move up or down in between
2933
///
3034
/// These fields should not be directly read or written except by internal `Effect` APIs.
31-
read_bits: u64,
32-
write_bits: u64
35+
read_bits: Effect,
36+
write_bits: Effect
3337
}
3438

3539
include!("hir_effect.inc.rs");
3640

37-
/// Print adaptor for [`Effect`]. See [`PtrPrintMap`].
41+
42+
/// Print adaptor for [`BitSet`]. See [`PtrPrintMap`].
3843
pub struct EffectPrinter<'a> {
3944
inner: Effect,
4045
ptr_map: &'a PtrPrintMap,
4146
}
4247

43-
// TODO(Jacob): Port from types to effects
4448
impl<'a> std::fmt::Display for EffectPrinter<'a> {
4549
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46-
let ty = self.inner;
50+
let effect = self.inner;
51+
// TODO(Jacob): Is it better to have 2*n in terms of list traversals, or allocate 1 bitset?
52+
// We could just remove this first loop through and make the function simpler. This seems better to me?
53+
//
54+
// If there's an exact match, write and return
4755
for (name, pattern) in bits::AllBitPatterns {
48-
if ty.bits == pattern {
56+
if effect.bits == pattern {
57+
// TODO(Jacob): Figure out if this is horrible rust
4958
write!(f, "{name}")?;
50-
return write_spec(f, self);
59+
return Ok(());
5160
}
5261
}
53-
#TODO(Jacob): Convert to debug assert
54-
assert!(bits::AllBitPatterns.is_sorted_by(|(_, left), (_, right)| left > right));
55-
let mut bits = ty.bits;
62+
// Otherwise, find the most descriptive sub-effect write it, and mask out the handled bits.
63+
// Most descriptive means "highest number of bits set while remaining fully contained within `effect`"
64+
debug_assert!(bits::AllBitPatterns.is_sorted_by(|(_, left), (_, right)| left > right));
65+
let mut bits = effect.bits;
5666
let mut sep = "";
5767
for (name, pattern) in bits::AllBitPatterns {
5868
if bits == 0 { break; }
@@ -62,11 +72,14 @@ impl<'a> std::fmt::Display for EffectPrinter<'a> {
6272
bits &= !pattern;
6373
}
6474
}
65-
assert_eq!(bits, 0, "Should have eliminated all bits by iterating over all patterns");
66-
write_spec(f, self)
75+
debug_assert_eq!(bits, 0, "Should have eliminated all bits by iterating over all patterns");
76+
Ok(())
6777
}
6878
}
6979

80+
// TODO(Jacob): Add EffectPairPrinter that just calls out to EffectPrinter twice
81+
// TODO(Jacob): Add functions for effect pair. print differing effects in the pair
82+
7083
impl std::fmt::Display for Effect {
7184
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
7285
self.print(&PtrPrintMap::identity()).fmt(f)
@@ -76,48 +89,36 @@ impl std::fmt::Display for Effect {
7689
impl Effect {
7790
// TODO(Jacob): Double check this comment below that was pulled from types
7891
/// Private. Only for creating effect globals.
79-
const fn from_bits(read_bits: u64, write_bits: u64) -> Effect {
92+
const fn from_bits(bits: u64) -> Effect {
8093
Effect {
81-
read_bits,
82-
write_bits,
94+
bits
8395
}
8496
}
8597

8698
pub fn union(&self, other: Effect) -> Effect {
87-
let read_bits = self.read_bits | other.read_bits;
88-
let write_bits = self.write_bits | other.write_bits;
89-
Effect::from_bits(read_bits, write_bits)
99+
Effect::from_bits(self.bits | other.bits)
90100
}
91101

92-
pub fn intersection(&self, other: Effect) -> Effect {
93-
let read_bits = self.read_bits & other.read_bits;
94-
let write_bits = self.write_bits & other.write_bits;
95-
Effect::from_bits(read_bits, write_bits)
102+
pub fn intersect(&self, other: Effect) -> Effect {
103+
Effect::from_bits(self.bits & other.bits)
96104
}
97105

98-
pub fn overlaps(&self, other: Effect) -> bool {
99-
!self.intersection(other).bit_equal(effects::None)
106+
pub fn exclude(&self, other: Effect) -> Effect {
107+
Effect::from_bits(self.bits - (self.bits & other.bits))
100108
}
101109

102110
// TODO(Jacob): Rewrite comment and see if this is intended to be used or not. We don't have subtypes...
103111
/// Check bit equality of two `Type`s. Do not use! You are probably looking for [`Effect::includes`].
104112
pub fn bit_equal(&self, other: Effect) -> bool {
105-
self.read_bits == other.read_bits && self.write_bits == other.write_bits
113+
self.bits == other.bits
106114
}
107115

108116
pub fn includes(&self, other: Effect) -> bool {
109-
let union = Effect::union(self, other);
110-
Effect::bit_equal(self, union)
111-
}
112-
113-
pub fn includes_read(&self, other: Effect) -> bool {
114-
let union = Effect::union(self, other);
115-
self.read_bits == union.read_bits
117+
self.bit_equal(Effect::union(self, other))
116118
}
117119

118-
pub fn includes_write(&self, other: Effect) -> bool {
119-
let union = Effect::union(self, other);
120-
self.write_bits == union.write_bits
120+
pub fn overlaps(&self, other: Effect) -> bool {
121+
!self.intersect(other).bit_equal(effects::None)
121122
}
122123

123124
pub fn print(self, ptr_map: &PtrPrintMap) -> EffectPrinter<'_> {

0 commit comments

Comments
 (0)