xref: /aosp_15_r20/external/mesa3d/src/nouveau/compiler/nak/liveness.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker // Copyright © 2022 Collabora, Ltd.
2*61046927SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker 
4*61046927SAndroid Build Coastguard Worker use crate::ir::*;
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker use compiler::bitset::BitSet;
7*61046927SAndroid Build Coastguard Worker use std::cell::RefCell;
8*61046927SAndroid Build Coastguard Worker use std::cmp::{max, Ord, Ordering};
9*61046927SAndroid Build Coastguard Worker use std::collections::{hash_set, HashMap, HashSet};
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #[derive(Clone)]
12*61046927SAndroid Build Coastguard Worker pub struct LiveSet {
13*61046927SAndroid Build Coastguard Worker     live: PerRegFile<u32>,
14*61046927SAndroid Build Coastguard Worker     set: HashSet<SSAValue>,
15*61046927SAndroid Build Coastguard Worker }
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker impl LiveSet {
new() -> LiveSet18*61046927SAndroid Build Coastguard Worker     pub fn new() -> LiveSet {
19*61046927SAndroid Build Coastguard Worker         LiveSet {
20*61046927SAndroid Build Coastguard Worker             live: Default::default(),
21*61046927SAndroid Build Coastguard Worker             set: HashSet::new(),
22*61046927SAndroid Build Coastguard Worker         }
23*61046927SAndroid Build Coastguard Worker     }
24*61046927SAndroid Build Coastguard Worker 
contains(&self, ssa: &SSAValue) -> bool25*61046927SAndroid Build Coastguard Worker     pub fn contains(&self, ssa: &SSAValue) -> bool {
26*61046927SAndroid Build Coastguard Worker         self.set.contains(ssa)
27*61046927SAndroid Build Coastguard Worker     }
28*61046927SAndroid Build Coastguard Worker 
count(&self, file: RegFile) -> u3229*61046927SAndroid Build Coastguard Worker     pub fn count(&self, file: RegFile) -> u32 {
30*61046927SAndroid Build Coastguard Worker         self.live[file]
31*61046927SAndroid Build Coastguard Worker     }
32*61046927SAndroid Build Coastguard Worker 
insert(&mut self, ssa: SSAValue) -> bool33*61046927SAndroid Build Coastguard Worker     pub fn insert(&mut self, ssa: SSAValue) -> bool {
34*61046927SAndroid Build Coastguard Worker         if self.set.insert(ssa) {
35*61046927SAndroid Build Coastguard Worker             self.live[ssa.file()] += 1;
36*61046927SAndroid Build Coastguard Worker             true
37*61046927SAndroid Build Coastguard Worker         } else {
38*61046927SAndroid Build Coastguard Worker             false
39*61046927SAndroid Build Coastguard Worker         }
40*61046927SAndroid Build Coastguard Worker     }
41*61046927SAndroid Build Coastguard Worker 
iter(&self) -> hash_set::Iter<SSAValue>42*61046927SAndroid Build Coastguard Worker     pub fn iter(&self) -> hash_set::Iter<SSAValue> {
43*61046927SAndroid Build Coastguard Worker         self.set.iter()
44*61046927SAndroid Build Coastguard Worker     }
45*61046927SAndroid Build Coastguard Worker 
remove(&mut self, ssa: &SSAValue) -> bool46*61046927SAndroid Build Coastguard Worker     pub fn remove(&mut self, ssa: &SSAValue) -> bool {
47*61046927SAndroid Build Coastguard Worker         if self.set.remove(ssa) {
48*61046927SAndroid Build Coastguard Worker             self.live[ssa.file()] -= 1;
49*61046927SAndroid Build Coastguard Worker             true
50*61046927SAndroid Build Coastguard Worker         } else {
51*61046927SAndroid Build Coastguard Worker             false
52*61046927SAndroid Build Coastguard Worker         }
53*61046927SAndroid Build Coastguard Worker     }
54*61046927SAndroid Build Coastguard Worker 
insert_instr_top_down<L: BlockLiveness>( &mut self, ip: usize, instr: &Instr, bl: &L, ) -> PerRegFile<u32>55*61046927SAndroid Build Coastguard Worker     pub fn insert_instr_top_down<L: BlockLiveness>(
56*61046927SAndroid Build Coastguard Worker         &mut self,
57*61046927SAndroid Build Coastguard Worker         ip: usize,
58*61046927SAndroid Build Coastguard Worker         instr: &Instr,
59*61046927SAndroid Build Coastguard Worker         bl: &L,
60*61046927SAndroid Build Coastguard Worker     ) -> PerRegFile<u32> {
61*61046927SAndroid Build Coastguard Worker         // Vector destinations go live before sources are killed.  Even
62*61046927SAndroid Build Coastguard Worker         // in the case where the destination is immediately killed, it
63*61046927SAndroid Build Coastguard Worker         // still may contribute to pressure temporarily.
64*61046927SAndroid Build Coastguard Worker         for dst in instr.dsts() {
65*61046927SAndroid Build Coastguard Worker             if let Dst::SSA(vec) = dst {
66*61046927SAndroid Build Coastguard Worker                 if vec.comps() > 1 {
67*61046927SAndroid Build Coastguard Worker                     for ssa in vec.iter() {
68*61046927SAndroid Build Coastguard Worker                         self.insert(*ssa);
69*61046927SAndroid Build Coastguard Worker                     }
70*61046927SAndroid Build Coastguard Worker                 }
71*61046927SAndroid Build Coastguard Worker             }
72*61046927SAndroid Build Coastguard Worker         }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker         let after_dsts_live = self.live;
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker         instr.for_each_ssa_use(|ssa| {
77*61046927SAndroid Build Coastguard Worker             if !bl.is_live_after_ip(ssa, ip) {
78*61046927SAndroid Build Coastguard Worker                 self.remove(ssa);
79*61046927SAndroid Build Coastguard Worker             }
80*61046927SAndroid Build Coastguard Worker         });
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker         // Scalar destinations are allocated last
83*61046927SAndroid Build Coastguard Worker         for dst in instr.dsts() {
84*61046927SAndroid Build Coastguard Worker             if let Dst::SSA(vec) = dst {
85*61046927SAndroid Build Coastguard Worker                 if vec.comps() == 1 {
86*61046927SAndroid Build Coastguard Worker                     self.insert(vec[0]);
87*61046927SAndroid Build Coastguard Worker                 }
88*61046927SAndroid Build Coastguard Worker             }
89*61046927SAndroid Build Coastguard Worker         }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker         let max_live = PerRegFile::new_with(|file| {
92*61046927SAndroid Build Coastguard Worker             max(self.live[file], after_dsts_live[file])
93*61046927SAndroid Build Coastguard Worker         });
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker         // It's possible (but unlikely) that a destination is immediately
96*61046927SAndroid Build Coastguard Worker         // killed. Remove any which are killed by this instruction.
97*61046927SAndroid Build Coastguard Worker         instr.for_each_ssa_def(|ssa| {
98*61046927SAndroid Build Coastguard Worker             debug_assert!(self.contains(ssa));
99*61046927SAndroid Build Coastguard Worker             if !bl.is_live_after_ip(ssa, ip) {
100*61046927SAndroid Build Coastguard Worker                 self.remove(ssa);
101*61046927SAndroid Build Coastguard Worker             }
102*61046927SAndroid Build Coastguard Worker         });
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker         max_live
105*61046927SAndroid Build Coastguard Worker     }
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker impl FromIterator<SSAValue> for LiveSet {
from_iter<T: IntoIterator<Item = SSAValue>>(iter: T) -> Self109*61046927SAndroid Build Coastguard Worker     fn from_iter<T: IntoIterator<Item = SSAValue>>(iter: T) -> Self {
110*61046927SAndroid Build Coastguard Worker         let mut set = LiveSet::new();
111*61046927SAndroid Build Coastguard Worker         for ssa in iter {
112*61046927SAndroid Build Coastguard Worker             set.insert(ssa);
113*61046927SAndroid Build Coastguard Worker         }
114*61046927SAndroid Build Coastguard Worker         set
115*61046927SAndroid Build Coastguard Worker     }
116*61046927SAndroid Build Coastguard Worker }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker impl Extend<SSAValue> for LiveSet {
extend<T: IntoIterator<Item = SSAValue>>(&mut self, iter: T)119*61046927SAndroid Build Coastguard Worker     fn extend<T: IntoIterator<Item = SSAValue>>(&mut self, iter: T) {
120*61046927SAndroid Build Coastguard Worker         for ssa in iter {
121*61046927SAndroid Build Coastguard Worker             self.insert(ssa);
122*61046927SAndroid Build Coastguard Worker         }
123*61046927SAndroid Build Coastguard Worker     }
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker pub trait BlockLiveness {
127*61046927SAndroid Build Coastguard Worker     /// Returns true if @val is still live after @ip
is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool128*61046927SAndroid Build Coastguard Worker     fn is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker     /// Returns true if @val is live-in to this block
is_live_in(&self, val: &SSAValue) -> bool131*61046927SAndroid Build Coastguard Worker     fn is_live_in(&self, val: &SSAValue) -> bool;
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker     /// Returns true if @val is live-out of this block
is_live_out(&self, val: &SSAValue) -> bool134*61046927SAndroid Build Coastguard Worker     fn is_live_out(&self, val: &SSAValue) -> bool;
135*61046927SAndroid Build Coastguard Worker 
get_instr_pressure(&self, ip: usize, instr: &Instr) -> PerRegFile<u8>136*61046927SAndroid Build Coastguard Worker     fn get_instr_pressure(&self, ip: usize, instr: &Instr) -> PerRegFile<u8> {
137*61046927SAndroid Build Coastguard Worker         let mut live = PerRegFile::new_with(|_| 0_i8);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker         // Vector destinations go live before sources are killed.
140*61046927SAndroid Build Coastguard Worker         for dst in instr.dsts() {
141*61046927SAndroid Build Coastguard Worker             if let Dst::SSA(vec) = dst {
142*61046927SAndroid Build Coastguard Worker                 if vec.comps() > 1 {
143*61046927SAndroid Build Coastguard Worker                     for ssa in vec.iter() {
144*61046927SAndroid Build Coastguard Worker                         live[ssa.file()] += 1;
145*61046927SAndroid Build Coastguard Worker                     }
146*61046927SAndroid Build Coastguard Worker                 }
147*61046927SAndroid Build Coastguard Worker             }
148*61046927SAndroid Build Coastguard Worker         }
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker         // This is the first high point
151*61046927SAndroid Build Coastguard Worker         let vec_dst_live = live;
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker         // Use a hash set because sources may occur more than once
154*61046927SAndroid Build Coastguard Worker         let mut killed = HashSet::new();
155*61046927SAndroid Build Coastguard Worker         instr.for_each_ssa_use(|ssa| {
156*61046927SAndroid Build Coastguard Worker             if !self.is_live_after_ip(ssa, ip) {
157*61046927SAndroid Build Coastguard Worker                 killed.insert(*ssa);
158*61046927SAndroid Build Coastguard Worker             }
159*61046927SAndroid Build Coastguard Worker         });
160*61046927SAndroid Build Coastguard Worker         for ssa in killed.drain() {
161*61046927SAndroid Build Coastguard Worker             live[ssa.file()] -= 1;
162*61046927SAndroid Build Coastguard Worker         }
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker         // Scalar destinations are allocated last
165*61046927SAndroid Build Coastguard Worker         for dst in instr.dsts() {
166*61046927SAndroid Build Coastguard Worker             if let Dst::SSA(vec) = dst {
167*61046927SAndroid Build Coastguard Worker                 if vec.comps() == 1 {
168*61046927SAndroid Build Coastguard Worker                     live[vec[0].file()] += 1;
169*61046927SAndroid Build Coastguard Worker                 }
170*61046927SAndroid Build Coastguard Worker             }
171*61046927SAndroid Build Coastguard Worker         }
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker         PerRegFile::new_with(|file| {
174*61046927SAndroid Build Coastguard Worker             max(0, max(vec_dst_live[file], live[file]))
175*61046927SAndroid Build Coastguard Worker                 .try_into()
176*61046927SAndroid Build Coastguard Worker                 .unwrap()
177*61046927SAndroid Build Coastguard Worker         })
178*61046927SAndroid Build Coastguard Worker     }
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker pub trait Liveness {
182*61046927SAndroid Build Coastguard Worker     type PerBlock: BlockLiveness;
183*61046927SAndroid Build Coastguard Worker 
block_live(&self, idx: usize) -> &Self::PerBlock184*61046927SAndroid Build Coastguard Worker     fn block_live(&self, idx: usize) -> &Self::PerBlock;
185*61046927SAndroid Build Coastguard Worker 
calc_max_live(&self, f: &Function) -> PerRegFile<u32>186*61046927SAndroid Build Coastguard Worker     fn calc_max_live(&self, f: &Function) -> PerRegFile<u32> {
187*61046927SAndroid Build Coastguard Worker         let mut max_live: PerRegFile<u32> = Default::default();
188*61046927SAndroid Build Coastguard Worker         let mut block_live_out: Vec<LiveSet> = Vec::new();
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker         for (bb_idx, bb) in f.blocks.iter().enumerate() {
191*61046927SAndroid Build Coastguard Worker             let bl = self.block_live(bb_idx);
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker             let mut live = LiveSet::new();
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker             // Predecessors are added block order so we can just grab the first
196*61046927SAndroid Build Coastguard Worker             // one (if any) and it will be a block we've processed.
197*61046927SAndroid Build Coastguard Worker             if let Some(pred_idx) = f.blocks.pred_indices(bb_idx).first() {
198*61046927SAndroid Build Coastguard Worker                 let pred_out = &block_live_out[*pred_idx];
199*61046927SAndroid Build Coastguard Worker                 for ssa in pred_out.iter() {
200*61046927SAndroid Build Coastguard Worker                     if bl.is_live_in(ssa) {
201*61046927SAndroid Build Coastguard Worker                         live.insert(*ssa);
202*61046927SAndroid Build Coastguard Worker                     }
203*61046927SAndroid Build Coastguard Worker                 }
204*61046927SAndroid Build Coastguard Worker             }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker             for (ip, instr) in bb.instrs.iter().enumerate() {
207*61046927SAndroid Build Coastguard Worker                 let live_at_instr = live.insert_instr_top_down(ip, instr, bl);
208*61046927SAndroid Build Coastguard Worker                 max_live = PerRegFile::new_with(|file| {
209*61046927SAndroid Build Coastguard Worker                     max(max_live[file], live_at_instr[file])
210*61046927SAndroid Build Coastguard Worker                 });
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker                 if let Op::RegOut(reg_out) = &instr.op {
213*61046927SAndroid Build Coastguard Worker                     // This should be the last instruction.  Everything should
214*61046927SAndroid Build Coastguard Worker                     // be dead once we've processed it.
215*61046927SAndroid Build Coastguard Worker                     debug_assert!(live.count(RegFile::GPR) == 0);
216*61046927SAndroid Build Coastguard Worker                     let num_gprs_out = reg_out.srcs.len().try_into().unwrap();
217*61046927SAndroid Build Coastguard Worker                     max_live[RegFile::GPR] =
218*61046927SAndroid Build Coastguard Worker                         max(max_live[RegFile::GPR], num_gprs_out);
219*61046927SAndroid Build Coastguard Worker                 }
220*61046927SAndroid Build Coastguard Worker             }
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker             assert!(block_live_out.len() == bb_idx);
223*61046927SAndroid Build Coastguard Worker             block_live_out.push(live);
224*61046927SAndroid Build Coastguard Worker         }
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker         max_live
227*61046927SAndroid Build Coastguard Worker     }
228*61046927SAndroid Build Coastguard Worker }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker pub struct SimpleBlockLiveness {
231*61046927SAndroid Build Coastguard Worker     defs: BitSet,
232*61046927SAndroid Build Coastguard Worker     uses: BitSet,
233*61046927SAndroid Build Coastguard Worker     last_use: HashMap<u32, usize>,
234*61046927SAndroid Build Coastguard Worker     live_in: BitSet,
235*61046927SAndroid Build Coastguard Worker     live_out: BitSet,
236*61046927SAndroid Build Coastguard Worker }
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker impl SimpleBlockLiveness {
new() -> Self239*61046927SAndroid Build Coastguard Worker     fn new() -> Self {
240*61046927SAndroid Build Coastguard Worker         Self {
241*61046927SAndroid Build Coastguard Worker             defs: BitSet::new(),
242*61046927SAndroid Build Coastguard Worker             uses: BitSet::new(),
243*61046927SAndroid Build Coastguard Worker             last_use: HashMap::new(),
244*61046927SAndroid Build Coastguard Worker             live_in: BitSet::new(),
245*61046927SAndroid Build Coastguard Worker             live_out: BitSet::new(),
246*61046927SAndroid Build Coastguard Worker         }
247*61046927SAndroid Build Coastguard Worker     }
248*61046927SAndroid Build Coastguard Worker 
add_def(&mut self, ssa: SSAValue)249*61046927SAndroid Build Coastguard Worker     fn add_def(&mut self, ssa: SSAValue) {
250*61046927SAndroid Build Coastguard Worker         self.defs.insert(ssa.idx().try_into().unwrap());
251*61046927SAndroid Build Coastguard Worker     }
252*61046927SAndroid Build Coastguard Worker 
add_use(&mut self, ssa: SSAValue, ip: usize)253*61046927SAndroid Build Coastguard Worker     fn add_use(&mut self, ssa: SSAValue, ip: usize) {
254*61046927SAndroid Build Coastguard Worker         self.uses.insert(ssa.idx().try_into().unwrap());
255*61046927SAndroid Build Coastguard Worker         self.last_use.insert(ssa.idx(), ip);
256*61046927SAndroid Build Coastguard Worker     }
257*61046927SAndroid Build Coastguard Worker }
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker impl BlockLiveness for SimpleBlockLiveness {
is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool260*61046927SAndroid Build Coastguard Worker     fn is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool {
261*61046927SAndroid Build Coastguard Worker         if self.live_out.get(val.idx().try_into().unwrap()) {
262*61046927SAndroid Build Coastguard Worker             true
263*61046927SAndroid Build Coastguard Worker         } else {
264*61046927SAndroid Build Coastguard Worker             if let Some(last_use_ip) = self.last_use.get(&val.idx()) {
265*61046927SAndroid Build Coastguard Worker                 *last_use_ip > ip
266*61046927SAndroid Build Coastguard Worker             } else {
267*61046927SAndroid Build Coastguard Worker                 false
268*61046927SAndroid Build Coastguard Worker             }
269*61046927SAndroid Build Coastguard Worker         }
270*61046927SAndroid Build Coastguard Worker     }
271*61046927SAndroid Build Coastguard Worker 
is_live_in(&self, val: &SSAValue) -> bool272*61046927SAndroid Build Coastguard Worker     fn is_live_in(&self, val: &SSAValue) -> bool {
273*61046927SAndroid Build Coastguard Worker         self.live_in.get(val.idx().try_into().unwrap())
274*61046927SAndroid Build Coastguard Worker     }
275*61046927SAndroid Build Coastguard Worker 
is_live_out(&self, val: &SSAValue) -> bool276*61046927SAndroid Build Coastguard Worker     fn is_live_out(&self, val: &SSAValue) -> bool {
277*61046927SAndroid Build Coastguard Worker         self.live_out.get(val.idx().try_into().unwrap())
278*61046927SAndroid Build Coastguard Worker     }
279*61046927SAndroid Build Coastguard Worker }
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker pub struct SimpleLiveness {
282*61046927SAndroid Build Coastguard Worker     ssa_block_ip: HashMap<SSAValue, (usize, usize)>,
283*61046927SAndroid Build Coastguard Worker     blocks: Vec<SimpleBlockLiveness>,
284*61046927SAndroid Build Coastguard Worker }
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker impl SimpleLiveness {
for_function(func: &Function) -> SimpleLiveness287*61046927SAndroid Build Coastguard Worker     pub fn for_function(func: &Function) -> SimpleLiveness {
288*61046927SAndroid Build Coastguard Worker         let mut l = SimpleLiveness {
289*61046927SAndroid Build Coastguard Worker             ssa_block_ip: HashMap::new(),
290*61046927SAndroid Build Coastguard Worker             blocks: Vec::new(),
291*61046927SAndroid Build Coastguard Worker         };
292*61046927SAndroid Build Coastguard Worker         let mut live_in = Vec::new();
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker         for (bi, b) in func.blocks.iter().enumerate() {
295*61046927SAndroid Build Coastguard Worker             let mut bl = SimpleBlockLiveness::new();
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker             for (ip, instr) in b.instrs.iter().enumerate() {
298*61046927SAndroid Build Coastguard Worker                 instr.for_each_ssa_use(|ssa| {
299*61046927SAndroid Build Coastguard Worker                     bl.add_use(*ssa, ip);
300*61046927SAndroid Build Coastguard Worker                 });
301*61046927SAndroid Build Coastguard Worker                 instr.for_each_ssa_def(|ssa| {
302*61046927SAndroid Build Coastguard Worker                     l.ssa_block_ip.insert(*ssa, (bi, ip));
303*61046927SAndroid Build Coastguard Worker                     bl.add_def(*ssa);
304*61046927SAndroid Build Coastguard Worker                 });
305*61046927SAndroid Build Coastguard Worker             }
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker             l.blocks.push(bl);
308*61046927SAndroid Build Coastguard Worker             live_in.push(BitSet::new());
309*61046927SAndroid Build Coastguard Worker         }
310*61046927SAndroid Build Coastguard Worker         assert!(l.blocks.len() == func.blocks.len());
311*61046927SAndroid Build Coastguard Worker         assert!(live_in.len() == func.blocks.len());
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker         let num_ssa = usize::try_from(func.ssa_alloc.max_idx() + 1).unwrap();
314*61046927SAndroid Build Coastguard Worker         let mut tmp = BitSet::new();
315*61046927SAndroid Build Coastguard Worker         tmp.reserve(num_ssa);
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker         let mut to_do = true;
318*61046927SAndroid Build Coastguard Worker         while to_do {
319*61046927SAndroid Build Coastguard Worker             to_do = false;
320*61046927SAndroid Build Coastguard Worker             for (b_idx, bl) in l.blocks.iter_mut().enumerate().rev() {
321*61046927SAndroid Build Coastguard Worker                 // Compute live-out
322*61046927SAndroid Build Coastguard Worker                 for sb_idx in func.blocks.succ_indices(b_idx) {
323*61046927SAndroid Build Coastguard Worker                     to_do |= bl.live_out.union_with(&live_in[*sb_idx]);
324*61046927SAndroid Build Coastguard Worker                 }
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker                 tmp.clear();
327*61046927SAndroid Build Coastguard Worker                 tmp.set_words(0..num_ssa, |w| {
328*61046927SAndroid Build Coastguard Worker                     (bl.live_out.get_word(w) | bl.uses.get_word(w))
329*61046927SAndroid Build Coastguard Worker                         & !bl.defs.get_word(w)
330*61046927SAndroid Build Coastguard Worker                 });
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker                 to_do |= live_in[b_idx].union_with(&tmp);
333*61046927SAndroid Build Coastguard Worker             }
334*61046927SAndroid Build Coastguard Worker         }
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker         for (bl, b_live_in) in l.blocks.iter_mut().zip(live_in.into_iter()) {
337*61046927SAndroid Build Coastguard Worker             bl.live_in = b_live_in;
338*61046927SAndroid Build Coastguard Worker         }
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker         l
341*61046927SAndroid Build Coastguard Worker     }
342*61046927SAndroid Build Coastguard Worker }
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker impl SimpleLiveness {
def_block_ip(&self, ssa: &SSAValue) -> (usize, usize)345*61046927SAndroid Build Coastguard Worker     pub fn def_block_ip(&self, ssa: &SSAValue) -> (usize, usize) {
346*61046927SAndroid Build Coastguard Worker         *self.ssa_block_ip.get(ssa).unwrap()
347*61046927SAndroid Build Coastguard Worker     }
348*61046927SAndroid Build Coastguard Worker 
interferes(&self, a: &SSAValue, b: &SSAValue) -> bool349*61046927SAndroid Build Coastguard Worker     pub fn interferes(&self, a: &SSAValue, b: &SSAValue) -> bool {
350*61046927SAndroid Build Coastguard Worker         let (ab, ai) = self.def_block_ip(a);
351*61046927SAndroid Build Coastguard Worker         let (bb, bi) = self.def_block_ip(b);
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker         match ab.cmp(&bb).then(ai.cmp(&bi)) {
354*61046927SAndroid Build Coastguard Worker             Ordering::Equal => true,
355*61046927SAndroid Build Coastguard Worker             Ordering::Less => self.block_live(bb).is_live_after_ip(a, bi),
356*61046927SAndroid Build Coastguard Worker             Ordering::Greater => self.block_live(ab).is_live_after_ip(b, ai),
357*61046927SAndroid Build Coastguard Worker         }
358*61046927SAndroid Build Coastguard Worker     }
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker impl Liveness for SimpleLiveness {
362*61046927SAndroid Build Coastguard Worker     type PerBlock = SimpleBlockLiveness;
363*61046927SAndroid Build Coastguard Worker 
block_live(&self, idx: usize) -> &SimpleBlockLiveness364*61046927SAndroid Build Coastguard Worker     fn block_live(&self, idx: usize) -> &SimpleBlockLiveness {
365*61046927SAndroid Build Coastguard Worker         &self.blocks[idx]
366*61046927SAndroid Build Coastguard Worker     }
367*61046927SAndroid Build Coastguard Worker }
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker struct SSAUseDef {
370*61046927SAndroid Build Coastguard Worker     defined: bool,
371*61046927SAndroid Build Coastguard Worker     uses: Vec<usize>,
372*61046927SAndroid Build Coastguard Worker }
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker impl SSAUseDef {
add_def(&mut self)375*61046927SAndroid Build Coastguard Worker     fn add_def(&mut self) {
376*61046927SAndroid Build Coastguard Worker         self.defined = true;
377*61046927SAndroid Build Coastguard Worker     }
378*61046927SAndroid Build Coastguard Worker 
add_in_block_use(&mut self, use_ip: usize)379*61046927SAndroid Build Coastguard Worker     fn add_in_block_use(&mut self, use_ip: usize) {
380*61046927SAndroid Build Coastguard Worker         self.uses.push(use_ip);
381*61046927SAndroid Build Coastguard Worker     }
382*61046927SAndroid Build Coastguard Worker 
add_successor_use( &mut self, num_block_instrs: usize, use_ip: usize, ) -> bool383*61046927SAndroid Build Coastguard Worker     fn add_successor_use(
384*61046927SAndroid Build Coastguard Worker         &mut self,
385*61046927SAndroid Build Coastguard Worker         num_block_instrs: usize,
386*61046927SAndroid Build Coastguard Worker         use_ip: usize,
387*61046927SAndroid Build Coastguard Worker     ) -> bool {
388*61046927SAndroid Build Coastguard Worker         // IPs are relative to the start of their block
389*61046927SAndroid Build Coastguard Worker         let use_ip = num_block_instrs + use_ip;
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker         if let Some(last_use_ip) = self.uses.last_mut() {
392*61046927SAndroid Build Coastguard Worker             if *last_use_ip < num_block_instrs {
393*61046927SAndroid Build Coastguard Worker                 // We've never seen a successor use before
394*61046927SAndroid Build Coastguard Worker                 self.uses.push(use_ip);
395*61046927SAndroid Build Coastguard Worker                 true
396*61046927SAndroid Build Coastguard Worker             } else if *last_use_ip > use_ip {
397*61046927SAndroid Build Coastguard Worker                 // Otherwise, we want the minimum next use
398*61046927SAndroid Build Coastguard Worker                 *last_use_ip = use_ip;
399*61046927SAndroid Build Coastguard Worker                 true
400*61046927SAndroid Build Coastguard Worker             } else {
401*61046927SAndroid Build Coastguard Worker                 false
402*61046927SAndroid Build Coastguard Worker             }
403*61046927SAndroid Build Coastguard Worker         } else {
404*61046927SAndroid Build Coastguard Worker             self.uses.push(use_ip);
405*61046927SAndroid Build Coastguard Worker             true
406*61046927SAndroid Build Coastguard Worker         }
407*61046927SAndroid Build Coastguard Worker     }
408*61046927SAndroid Build Coastguard Worker }
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker pub struct NextUseBlockLiveness {
411*61046927SAndroid Build Coastguard Worker     num_instrs: usize,
412*61046927SAndroid Build Coastguard Worker     ssa_map: HashMap<SSAValue, SSAUseDef>,
413*61046927SAndroid Build Coastguard Worker }
414*61046927SAndroid Build Coastguard Worker 
415*61046927SAndroid Build Coastguard Worker impl NextUseBlockLiveness {
new(num_instrs: usize) -> Self416*61046927SAndroid Build Coastguard Worker     fn new(num_instrs: usize) -> Self {
417*61046927SAndroid Build Coastguard Worker         Self {
418*61046927SAndroid Build Coastguard Worker             num_instrs: num_instrs,
419*61046927SAndroid Build Coastguard Worker             ssa_map: HashMap::new(),
420*61046927SAndroid Build Coastguard Worker         }
421*61046927SAndroid Build Coastguard Worker     }
422*61046927SAndroid Build Coastguard Worker 
entry_mut(&mut self, ssa: SSAValue) -> &mut SSAUseDef423*61046927SAndroid Build Coastguard Worker     fn entry_mut(&mut self, ssa: SSAValue) -> &mut SSAUseDef {
424*61046927SAndroid Build Coastguard Worker         self.ssa_map.entry(ssa).or_insert_with(|| SSAUseDef {
425*61046927SAndroid Build Coastguard Worker             defined: false,
426*61046927SAndroid Build Coastguard Worker             uses: Vec::new(),
427*61046927SAndroid Build Coastguard Worker         })
428*61046927SAndroid Build Coastguard Worker     }
429*61046927SAndroid Build Coastguard Worker 
add_def(&mut self, ssa: SSAValue)430*61046927SAndroid Build Coastguard Worker     fn add_def(&mut self, ssa: SSAValue) {
431*61046927SAndroid Build Coastguard Worker         self.entry_mut(ssa).add_def();
432*61046927SAndroid Build Coastguard Worker     }
433*61046927SAndroid Build Coastguard Worker 
add_use(&mut self, ssa: SSAValue, ip: usize)434*61046927SAndroid Build Coastguard Worker     fn add_use(&mut self, ssa: SSAValue, ip: usize) {
435*61046927SAndroid Build Coastguard Worker         self.entry_mut(ssa).add_in_block_use(ip);
436*61046927SAndroid Build Coastguard Worker     }
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker     /// Returns an iterator over all the values which are live-in to this block
iter_live_in(&self) -> impl Iterator<Item = &SSAValue>439*61046927SAndroid Build Coastguard Worker     pub fn iter_live_in(&self) -> impl Iterator<Item = &SSAValue> {
440*61046927SAndroid Build Coastguard Worker         self.ssa_map.iter().filter_map(|(ssa, entry)| {
441*61046927SAndroid Build Coastguard Worker             if entry.defined || entry.uses.is_empty() {
442*61046927SAndroid Build Coastguard Worker                 None
443*61046927SAndroid Build Coastguard Worker             } else {
444*61046927SAndroid Build Coastguard Worker                 Some(ssa)
445*61046927SAndroid Build Coastguard Worker             }
446*61046927SAndroid Build Coastguard Worker         })
447*61046927SAndroid Build Coastguard Worker     }
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker     /// Returns the IP of the first use of @val
450*61046927SAndroid Build Coastguard Worker     ///
451*61046927SAndroid Build Coastguard Worker     /// The returned IP is relative to the start of this block.  If the next use
452*61046927SAndroid Build Coastguard Worker     /// is in some successor block, the returned IP is relative to the start of
453*61046927SAndroid Build Coastguard Worker     /// this block.  If @val is not used in this block and is not live-out, None
454*61046927SAndroid Build Coastguard Worker     /// is returned.
first_use(&self, val: &SSAValue) -> Option<usize>455*61046927SAndroid Build Coastguard Worker     pub fn first_use(&self, val: &SSAValue) -> Option<usize> {
456*61046927SAndroid Build Coastguard Worker         if let Some(entry) = self.ssa_map.get(val) {
457*61046927SAndroid Build Coastguard Worker             entry.uses.first().cloned()
458*61046927SAndroid Build Coastguard Worker         } else {
459*61046927SAndroid Build Coastguard Worker             None
460*61046927SAndroid Build Coastguard Worker         }
461*61046927SAndroid Build Coastguard Worker     }
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker     /// Returns the IP of the first use of @val which is greater than or equal
464*61046927SAndroid Build Coastguard Worker     /// to @ip
465*61046927SAndroid Build Coastguard Worker     ///
466*61046927SAndroid Build Coastguard Worker     /// All IPs are relative to the start of the block.  If the next use is some
467*61046927SAndroid Build Coastguard Worker     /// successor block, the returned IP is relative to the start of this block.
next_use_after_or_at_ip( &self, val: &SSAValue, ip: usize, ) -> Option<usize>468*61046927SAndroid Build Coastguard Worker     pub fn next_use_after_or_at_ip(
469*61046927SAndroid Build Coastguard Worker         &self,
470*61046927SAndroid Build Coastguard Worker         val: &SSAValue,
471*61046927SAndroid Build Coastguard Worker         ip: usize,
472*61046927SAndroid Build Coastguard Worker     ) -> Option<usize> {
473*61046927SAndroid Build Coastguard Worker         if let Some(entry) = self.ssa_map.get(val) {
474*61046927SAndroid Build Coastguard Worker             let i = entry.uses.partition_point(|u| *u < ip);
475*61046927SAndroid Build Coastguard Worker             if i < entry.uses.len() {
476*61046927SAndroid Build Coastguard Worker                 Some(entry.uses[i])
477*61046927SAndroid Build Coastguard Worker             } else {
478*61046927SAndroid Build Coastguard Worker                 None
479*61046927SAndroid Build Coastguard Worker             }
480*61046927SAndroid Build Coastguard Worker         } else {
481*61046927SAndroid Build Coastguard Worker             None
482*61046927SAndroid Build Coastguard Worker         }
483*61046927SAndroid Build Coastguard Worker     }
484*61046927SAndroid Build Coastguard Worker }
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker impl BlockLiveness for NextUseBlockLiveness {
is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool487*61046927SAndroid Build Coastguard Worker     fn is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool {
488*61046927SAndroid Build Coastguard Worker         if let Some(entry) = self.ssa_map.get(val) {
489*61046927SAndroid Build Coastguard Worker             if let Some(last_use_ip) = entry.uses.last() {
490*61046927SAndroid Build Coastguard Worker                 *last_use_ip > ip
491*61046927SAndroid Build Coastguard Worker             } else {
492*61046927SAndroid Build Coastguard Worker                 false
493*61046927SAndroid Build Coastguard Worker             }
494*61046927SAndroid Build Coastguard Worker         } else {
495*61046927SAndroid Build Coastguard Worker             false
496*61046927SAndroid Build Coastguard Worker         }
497*61046927SAndroid Build Coastguard Worker     }
498*61046927SAndroid Build Coastguard Worker 
is_live_in(&self, val: &SSAValue) -> bool499*61046927SAndroid Build Coastguard Worker     fn is_live_in(&self, val: &SSAValue) -> bool {
500*61046927SAndroid Build Coastguard Worker         if let Some(entry) = self.ssa_map.get(val) {
501*61046927SAndroid Build Coastguard Worker             !entry.defined && !entry.uses.is_empty()
502*61046927SAndroid Build Coastguard Worker         } else {
503*61046927SAndroid Build Coastguard Worker             false
504*61046927SAndroid Build Coastguard Worker         }
505*61046927SAndroid Build Coastguard Worker     }
506*61046927SAndroid Build Coastguard Worker 
is_live_out(&self, val: &SSAValue) -> bool507*61046927SAndroid Build Coastguard Worker     fn is_live_out(&self, val: &SSAValue) -> bool {
508*61046927SAndroid Build Coastguard Worker         if let Some(entry) = self.ssa_map.get(val) {
509*61046927SAndroid Build Coastguard Worker             if let Some(last_use_ip) = entry.uses.last() {
510*61046927SAndroid Build Coastguard Worker                 *last_use_ip >= self.num_instrs
511*61046927SAndroid Build Coastguard Worker             } else {
512*61046927SAndroid Build Coastguard Worker                 false
513*61046927SAndroid Build Coastguard Worker             }
514*61046927SAndroid Build Coastguard Worker         } else {
515*61046927SAndroid Build Coastguard Worker             false
516*61046927SAndroid Build Coastguard Worker         }
517*61046927SAndroid Build Coastguard Worker     }
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker /// An implementation of Liveness that tracks next-use IPs for each SSAValue
521*61046927SAndroid Build Coastguard Worker ///
522*61046927SAndroid Build Coastguard Worker /// Along with the usual liveness information, this tracks next-use IPs for each
523*61046927SAndroid Build Coastguard Worker /// SSAValue.  Cross-block next-use IPs computed are as per the global next-use
524*61046927SAndroid Build Coastguard Worker /// distance algorithm described in "Register Spilling and Live-Range Splitting
525*61046927SAndroid Build Coastguard Worker /// for SSA-Form Programs" by Braun and Hack.
526*61046927SAndroid Build Coastguard Worker pub struct NextUseLiveness {
527*61046927SAndroid Build Coastguard Worker     blocks: Vec<NextUseBlockLiveness>,
528*61046927SAndroid Build Coastguard Worker }
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker impl NextUseLiveness {
for_function( func: &Function, files: &RegFileSet, ) -> NextUseLiveness531*61046927SAndroid Build Coastguard Worker     pub fn for_function(
532*61046927SAndroid Build Coastguard Worker         func: &Function,
533*61046927SAndroid Build Coastguard Worker         files: &RegFileSet,
534*61046927SAndroid Build Coastguard Worker     ) -> NextUseLiveness {
535*61046927SAndroid Build Coastguard Worker         let mut blocks = Vec::new();
536*61046927SAndroid Build Coastguard Worker         for (bi, b) in func.blocks.iter().enumerate() {
537*61046927SAndroid Build Coastguard Worker             let mut bl = NextUseBlockLiveness::new(b.instrs.len());
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker             for (ip, instr) in b.instrs.iter().enumerate() {
540*61046927SAndroid Build Coastguard Worker                 instr.for_each_ssa_use(|ssa| {
541*61046927SAndroid Build Coastguard Worker                     if files.contains(ssa.file()) {
542*61046927SAndroid Build Coastguard Worker                         bl.add_use(*ssa, ip);
543*61046927SAndroid Build Coastguard Worker                     }
544*61046927SAndroid Build Coastguard Worker                 });
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker                 instr.for_each_ssa_def(|ssa| {
547*61046927SAndroid Build Coastguard Worker                     if files.contains(ssa.file()) {
548*61046927SAndroid Build Coastguard Worker                         bl.add_def(*ssa);
549*61046927SAndroid Build Coastguard Worker                     }
550*61046927SAndroid Build Coastguard Worker                 });
551*61046927SAndroid Build Coastguard Worker             }
552*61046927SAndroid Build Coastguard Worker 
553*61046927SAndroid Build Coastguard Worker             debug_assert!(bi == blocks.len());
554*61046927SAndroid Build Coastguard Worker             blocks.push(RefCell::new(bl));
555*61046927SAndroid Build Coastguard Worker         }
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker         let mut to_do = true;
558*61046927SAndroid Build Coastguard Worker         while to_do {
559*61046927SAndroid Build Coastguard Worker             to_do = false;
560*61046927SAndroid Build Coastguard Worker             for (b_idx, b) in func.blocks.iter().enumerate().rev() {
561*61046927SAndroid Build Coastguard Worker                 let num_instrs = b.instrs.len();
562*61046927SAndroid Build Coastguard Worker                 let mut bl = blocks[b_idx].borrow_mut();
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker                 // Compute live-out
565*61046927SAndroid Build Coastguard Worker                 for sb_idx in func.blocks.succ_indices(b_idx) {
566*61046927SAndroid Build Coastguard Worker                     if *sb_idx == b_idx {
567*61046927SAndroid Build Coastguard Worker                         for entry in bl.ssa_map.values_mut() {
568*61046927SAndroid Build Coastguard Worker                             if entry.defined {
569*61046927SAndroid Build Coastguard Worker                                 continue;
570*61046927SAndroid Build Coastguard Worker                             }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker                             let Some(first_use_ip) = entry.uses.first() else {
573*61046927SAndroid Build Coastguard Worker                                 continue;
574*61046927SAndroid Build Coastguard Worker                             };
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker                             to_do |= entry
577*61046927SAndroid Build Coastguard Worker                                 .add_successor_use(num_instrs, *first_use_ip);
578*61046927SAndroid Build Coastguard Worker                         }
579*61046927SAndroid Build Coastguard Worker                     } else {
580*61046927SAndroid Build Coastguard Worker                         let sbl = blocks[*sb_idx].borrow();
581*61046927SAndroid Build Coastguard Worker                         for (ssa, entry) in sbl.ssa_map.iter() {
582*61046927SAndroid Build Coastguard Worker                             if entry.defined {
583*61046927SAndroid Build Coastguard Worker                                 continue;
584*61046927SAndroid Build Coastguard Worker                             }
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker                             let Some(first_use_ip) = entry.uses.first() else {
587*61046927SAndroid Build Coastguard Worker                                 continue;
588*61046927SAndroid Build Coastguard Worker                             };
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker                             to_do |= bl
591*61046927SAndroid Build Coastguard Worker                                 .entry_mut(*ssa)
592*61046927SAndroid Build Coastguard Worker                                 .add_successor_use(num_instrs, *first_use_ip);
593*61046927SAndroid Build Coastguard Worker                         }
594*61046927SAndroid Build Coastguard Worker                     }
595*61046927SAndroid Build Coastguard Worker                 }
596*61046927SAndroid Build Coastguard Worker             }
597*61046927SAndroid Build Coastguard Worker         }
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker         NextUseLiveness {
600*61046927SAndroid Build Coastguard Worker             blocks: blocks.into_iter().map(|bl| bl.into_inner()).collect(),
601*61046927SAndroid Build Coastguard Worker         }
602*61046927SAndroid Build Coastguard Worker     }
603*61046927SAndroid Build Coastguard Worker }
604*61046927SAndroid Build Coastguard Worker 
605*61046927SAndroid Build Coastguard Worker impl Liveness for NextUseLiveness {
606*61046927SAndroid Build Coastguard Worker     type PerBlock = NextUseBlockLiveness;
607*61046927SAndroid Build Coastguard Worker 
block_live(&self, idx: usize) -> &NextUseBlockLiveness608*61046927SAndroid Build Coastguard Worker     fn block_live(&self, idx: usize) -> &NextUseBlockLiveness {
609*61046927SAndroid Build Coastguard Worker         &self.blocks[idx]
610*61046927SAndroid Build Coastguard Worker     }
611*61046927SAndroid Build Coastguard Worker }
612