• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright © 2022 Collabora, Ltd.
2 // SPDX-License-Identifier: MIT
3 
4 use crate::ir::*;
5 
6 pub trait Builder {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr7     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr;
8 
sm(&self) -> u89     fn sm(&self) -> u8;
10 
push_op(&mut self, op: impl Into<Op>) -> &mut Instr11     fn push_op(&mut self, op: impl Into<Op>) -> &mut Instr {
12         self.push_instr(Instr::new_boxed(op))
13     }
14 
predicate(&mut self, pred: Pred) -> PredicatedBuilder<'_, Self> where Self: Sized,15     fn predicate(&mut self, pred: Pred) -> PredicatedBuilder<'_, Self>
16     where
17         Self: Sized,
18     {
19         PredicatedBuilder {
20             b: self,
21             pred: pred,
22         }
23     }
24 
lop2_to(&mut self, dst: Dst, op: LogicOp2, mut x: Src, mut y: Src)25     fn lop2_to(&mut self, dst: Dst, op: LogicOp2, mut x: Src, mut y: Src) {
26         let is_predicate = match dst {
27             Dst::None => panic!("No LOP destination"),
28             Dst::SSA(ssa) => ssa.is_predicate(),
29             Dst::Reg(reg) => reg.is_predicate(),
30         };
31         assert!(x.is_predicate() == is_predicate);
32         assert!(y.is_predicate() == is_predicate);
33 
34         if self.sm() >= 70 {
35             let mut op = op.to_lut();
36             if x.src_mod.is_bnot() {
37                 op = LogicOp3::new_lut(&|x, y, _| op.eval(!x, y, 0));
38                 x.src_mod = SrcMod::None;
39             }
40             if y.src_mod.is_bnot() {
41                 op = LogicOp3::new_lut(&|x, y, _| op.eval(x, !y, 0));
42                 y.src_mod = SrcMod::None;
43             }
44             if is_predicate {
45                 self.push_op(OpPLop3 {
46                     dsts: [dst, Dst::None],
47                     srcs: [x, y, true.into()],
48                     ops: [op, LogicOp3::new_const(false)],
49                 });
50             } else {
51                 self.push_op(OpLop3 {
52                     dst: dst,
53                     srcs: [x, y, 0.into()],
54                     op: op,
55                 });
56             }
57         } else {
58             if is_predicate {
59                 let mut x = x;
60                 let cmp_op = match op {
61                     LogicOp2::And => PredSetOp::And,
62                     LogicOp2::Or => PredSetOp::Or,
63                     LogicOp2::Xor => PredSetOp::Xor,
64                     LogicOp2::PassB => {
65                         // Pass through B by AND with PT
66                         x = true.into();
67                         PredSetOp::And
68                     }
69                 };
70                 self.push_op(OpPSetP {
71                     dsts: [dst, Dst::None],
72                     ops: [cmp_op, PredSetOp::And],
73                     srcs: [x, y, true.into()],
74                 });
75             } else {
76                 self.push_op(OpLop2 {
77                     dst: dst,
78                     srcs: [x, y],
79                     op: op,
80                 });
81             }
82         }
83     }
84 
prmt_to(&mut self, dst: Dst, x: Src, y: Src, sel: [u8; 4])85     fn prmt_to(&mut self, dst: Dst, x: Src, y: Src, sel: [u8; 4]) {
86         if sel == [0, 1, 2, 3] {
87             self.copy_to(dst, x);
88         } else if sel == [4, 5, 6, 7] {
89             self.copy_to(dst, y);
90         } else {
91             let mut sel_u32 = 0;
92             for i in 0..4 {
93                 assert!(sel[i] < 16);
94                 sel_u32 |= u32::from(sel[i]) << (i * 4);
95             }
96 
97             self.push_op(OpPrmt {
98                 dst: dst,
99                 srcs: [x, y],
100                 sel: sel_u32.into(),
101                 mode: PrmtMode::Index,
102             });
103         }
104     }
105 
copy_to(&mut self, dst: Dst, src: Src)106     fn copy_to(&mut self, dst: Dst, src: Src) {
107         self.push_op(OpCopy { dst: dst, src: src });
108     }
109 
swap(&mut self, x: RegRef, y: RegRef)110     fn swap(&mut self, x: RegRef, y: RegRef) {
111         assert!(x.file() == y.file());
112         self.push_op(OpSwap {
113             dsts: [x.into(), y.into()],
114             srcs: [y.into(), x.into()],
115         });
116     }
117 }
118 
119 pub trait SSABuilder: Builder {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef120     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef;
121 
shl(&mut self, x: Src, shift: Src) -> SSARef122     fn shl(&mut self, x: Src, shift: Src) -> SSARef {
123         let dst = self.alloc_ssa(RegFile::GPR, 1);
124         if self.sm() >= 70 {
125             self.push_op(OpShf {
126                 dst: dst.into(),
127                 low: x,
128                 high: 0.into(),
129                 shift: shift,
130                 right: false,
131                 wrap: true,
132                 data_type: IntType::I32,
133                 dst_high: false,
134             });
135         } else {
136             self.push_op(OpShl {
137                 dst: dst.into(),
138                 src: x,
139                 shift: shift,
140                 wrap: true,
141             });
142         }
143         dst
144     }
145 
shr(&mut self, x: Src, shift: Src, signed: bool) -> SSARef146     fn shr(&mut self, x: Src, shift: Src, signed: bool) -> SSARef {
147         let dst = self.alloc_ssa(RegFile::GPR, 1);
148         if self.sm() >= 70 {
149             self.push_op(OpShf {
150                 dst: dst.into(),
151                 low: 0.into(),
152                 high: x,
153                 shift: shift,
154                 right: true,
155                 wrap: true,
156                 data_type: if signed { IntType::I32 } else { IntType::U32 },
157                 dst_high: true,
158             });
159         } else {
160             self.push_op(OpShr {
161                 dst: dst.into(),
162                 src: x,
163                 shift: shift,
164                 wrap: true,
165                 signed,
166             });
167         }
168         dst
169     }
170 
fadd(&mut self, x: Src, y: Src) -> SSARef171     fn fadd(&mut self, x: Src, y: Src) -> SSARef {
172         let dst = self.alloc_ssa(RegFile::GPR, 1);
173         self.push_op(OpFAdd {
174             dst: dst.into(),
175             srcs: [x, y],
176             saturate: false,
177             rnd_mode: FRndMode::NearestEven,
178             ftz: false,
179         });
180         dst
181     }
182 
fmul(&mut self, x: Src, y: Src) -> SSARef183     fn fmul(&mut self, x: Src, y: Src) -> SSARef {
184         let dst = self.alloc_ssa(RegFile::GPR, 1);
185         self.push_op(OpFMul {
186             dst: dst.into(),
187             srcs: [x, y],
188             saturate: false,
189             rnd_mode: FRndMode::NearestEven,
190             ftz: false,
191             dnz: false,
192         });
193         dst
194     }
195 
fset(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef196     fn fset(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
197         let dst = self.alloc_ssa(RegFile::GPR, 1);
198         self.push_op(OpFSet {
199             dst: dst.into(),
200             cmp_op: cmp_op,
201             srcs: [x, y],
202             ftz: false,
203         });
204         dst
205     }
206 
fsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef207     fn fsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
208         let dst = self.alloc_ssa(RegFile::Pred, 1);
209         self.push_op(OpFSetP {
210             dst: dst.into(),
211             set_op: PredSetOp::And,
212             cmp_op: cmp_op,
213             srcs: [x, y],
214             accum: SrcRef::True.into(),
215             ftz: false,
216         });
217         dst
218     }
219 
dsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef220     fn dsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
221         let dst = self.alloc_ssa(RegFile::Pred, 1);
222         self.push_op(OpDSetP {
223             dst: dst.into(),
224             set_op: PredSetOp::And,
225             cmp_op: cmp_op,
226             srcs: [x, y],
227             accum: SrcRef::True.into(),
228         });
229         dst
230     }
231 
iabs(&mut self, i: Src) -> SSARef232     fn iabs(&mut self, i: Src) -> SSARef {
233         let dst = self.alloc_ssa(RegFile::GPR, 1);
234         if self.sm() >= 70 {
235             self.push_op(OpIAbs {
236                 dst: dst.into(),
237                 src: i,
238             });
239         } else {
240             self.push_op(OpI2I {
241                 dst: dst.into(),
242                 src: i,
243                 src_type: IntType::I32,
244                 dst_type: IntType::I32,
245                 saturate: false,
246                 abs: true,
247                 neg: false,
248             });
249         }
250         dst
251     }
252 
iadd(&mut self, x: Src, y: Src, z: Src) -> SSARef253     fn iadd(&mut self, x: Src, y: Src, z: Src) -> SSARef {
254         let dst = self.alloc_ssa(RegFile::GPR, 1);
255         if self.sm() >= 70 {
256             self.push_op(OpIAdd3 {
257                 dst: dst.into(),
258                 srcs: [x, y, z],
259                 overflow: [Dst::None; 2],
260             });
261         } else {
262             assert!(z.is_zero());
263             self.push_op(OpIAdd2 {
264                 dst: dst.into(),
265                 srcs: [x, y],
266                 carry_in: 0.into(),
267                 carry_out: Dst::None,
268             });
269         }
270         dst
271     }
272 
iadd64(&mut self, x: Src, y: Src, z: Src) -> SSARef273     fn iadd64(&mut self, x: Src, y: Src, z: Src) -> SSARef {
274         let x = x.as_ssa().unwrap();
275         let y = y.as_ssa().unwrap();
276         let dst = self.alloc_ssa(RegFile::GPR, 2);
277         if self.sm() >= 70 {
278             if let Some(z) = z.as_ssa() {
279                 let carry = [
280                     self.alloc_ssa(RegFile::Pred, 1),
281                     self.alloc_ssa(RegFile::Pred, 1),
282                 ];
283                 self.push_op(OpIAdd3 {
284                     dst: dst[0].into(),
285                     overflow: [carry[0].into(), carry[1].into()],
286                     srcs: [x[0].into(), y[0].into(), z[0].into()],
287                 });
288                 self.push_op(OpIAdd3X {
289                     dst: dst[1].into(),
290                     overflow: [Dst::None, Dst::None],
291                     srcs: [x[1].into(), y[1].into(), z[1].into()],
292                     carry: [carry[0].into(), carry[1].into()],
293                 });
294             } else {
295                 assert!(z.is_zero());
296                 let carry = self.alloc_ssa(RegFile::Pred, 1);
297                 self.push_op(OpIAdd3 {
298                     dst: dst[0].into(),
299                     overflow: [carry.into(), Dst::None],
300                     srcs: [x[0].into(), y[0].into(), 0.into()],
301                 });
302                 self.push_op(OpIAdd3X {
303                     dst: dst[1].into(),
304                     overflow: [Dst::None, Dst::None],
305                     srcs: [x[1].into(), y[1].into(), 0.into()],
306                     carry: [carry.into(), false.into()],
307                 });
308             }
309         } else {
310             assert!(z.is_zero());
311             let carry = self.alloc_ssa(RegFile::Carry, 1);
312             self.push_op(OpIAdd2 {
313                 dst: dst[0].into(),
314                 srcs: [x[0].into(), y[0].into()],
315                 carry_out: carry.into(),
316                 carry_in: 0.into(),
317             });
318             self.push_op(OpIAdd2 {
319                 dst: dst[1].into(),
320                 srcs: [x[1].into(), y[1].into()],
321                 carry_out: Dst::None,
322                 carry_in: carry.into(),
323             });
324         }
325         dst
326     }
327 
imnmx(&mut self, tp: IntCmpType, x: Src, y: Src, min: Src) -> SSARef328     fn imnmx(&mut self, tp: IntCmpType, x: Src, y: Src, min: Src) -> SSARef {
329         let dst = self.alloc_ssa(RegFile::GPR, 1);
330         self.push_op(OpIMnMx {
331             dst: dst.into(),
332             cmp_type: tp,
333             srcs: [x, y],
334             min: min,
335         });
336         dst
337     }
338 
imul(&mut self, x: Src, y: Src) -> SSARef339     fn imul(&mut self, x: Src, y: Src) -> SSARef {
340         let dst = self.alloc_ssa(RegFile::GPR, 1);
341         if self.sm() >= 70 {
342             self.push_op(OpIMad {
343                 dst: dst.into(),
344                 srcs: [x, y, 0.into()],
345                 signed: false,
346             });
347         } else {
348             self.push_op(OpIMul {
349                 dst: dst[0].into(),
350                 srcs: [x, y],
351                 signed: [false; 2],
352                 high: false,
353             });
354         }
355         dst
356     }
357 
imul_2x32_64(&mut self, x: Src, y: Src, signed: bool) -> SSARef358     fn imul_2x32_64(&mut self, x: Src, y: Src, signed: bool) -> SSARef {
359         let dst = self.alloc_ssa(RegFile::GPR, 2);
360         if self.sm() >= 70 {
361             self.push_op(OpIMad64 {
362                 dst: dst.into(),
363                 srcs: [x, y, 0.into()],
364                 signed,
365             });
366         } else {
367             self.push_op(OpIMul {
368                 dst: dst[0].into(),
369                 srcs: [x, y],
370                 signed: [signed; 2],
371                 high: false,
372             });
373             self.push_op(OpIMul {
374                 dst: dst[1].into(),
375                 srcs: [x, y],
376                 signed: [signed; 2],
377                 high: true,
378             });
379         }
380         dst
381     }
382 
ineg(&mut self, i: Src) -> SSARef383     fn ineg(&mut self, i: Src) -> SSARef {
384         let dst = self.alloc_ssa(RegFile::GPR, 1);
385         self.push_op(OpINeg {
386             dst: dst.into(),
387             src: i,
388         });
389         dst
390     }
391 
isetp( &mut self, cmp_type: IntCmpType, cmp_op: IntCmpOp, x: Src, y: Src, ) -> SSARef392     fn isetp(
393         &mut self,
394         cmp_type: IntCmpType,
395         cmp_op: IntCmpOp,
396         x: Src,
397         y: Src,
398     ) -> SSARef {
399         let dst = self.alloc_ssa(RegFile::Pred, 1);
400         self.push_op(OpISetP {
401             dst: dst.into(),
402             set_op: PredSetOp::And,
403             cmp_op: cmp_op,
404             cmp_type: cmp_type,
405             ex: false,
406             srcs: [x, y],
407             accum: true.into(),
408             low_cmp: true.into(),
409         });
410         dst
411     }
412 
isetp64( &mut self, cmp_type: IntCmpType, cmp_op: IntCmpOp, x: Src, y: Src, ) -> SSARef413     fn isetp64(
414         &mut self,
415         cmp_type: IntCmpType,
416         cmp_op: IntCmpOp,
417         x: Src,
418         y: Src,
419     ) -> SSARef {
420         let x = x.as_ssa().unwrap();
421         let y = y.as_ssa().unwrap();
422 
423         // Low bits are always an unsigned comparison
424         let low = self.isetp(IntCmpType::U32, cmp_op, x[0].into(), y[0].into());
425 
426         let dst = self.alloc_ssa(RegFile::Pred, 1);
427         match cmp_op {
428             IntCmpOp::Eq | IntCmpOp::Ne => {
429                 self.push_op(OpISetP {
430                     dst: dst.into(),
431                     set_op: match cmp_op {
432                         IntCmpOp::Eq => PredSetOp::And,
433                         IntCmpOp::Ne => PredSetOp::Or,
434                         _ => panic!("Not an integer equality"),
435                     },
436                     cmp_op: cmp_op,
437                     cmp_type: IntCmpType::U32,
438                     ex: false,
439                     srcs: [x[1].into(), y[1].into()],
440                     accum: low.into(),
441                     low_cmp: true.into(),
442                 });
443             }
444             IntCmpOp::Ge | IntCmpOp::Gt | IntCmpOp::Le | IntCmpOp::Lt => {
445                 self.push_op(OpISetP {
446                     dst: dst.into(),
447                     set_op: PredSetOp::And,
448                     cmp_op: cmp_op,
449                     cmp_type: cmp_type,
450                     ex: true,
451                     srcs: [x[1].into(), y[1].into()],
452                     accum: true.into(),
453                     low_cmp: low.into(),
454                 });
455             }
456         }
457         dst
458     }
459 
lop2(&mut self, op: LogicOp2, x: Src, y: Src) -> SSARef460     fn lop2(&mut self, op: LogicOp2, x: Src, y: Src) -> SSARef {
461         let dst = if x.is_predicate() {
462             self.alloc_ssa(RegFile::Pred, 1)
463         } else {
464             self.alloc_ssa(RegFile::GPR, 1)
465         };
466         self.lop2_to(dst.into(), op, x, y);
467         dst
468     }
469 
mufu(&mut self, op: MuFuOp, src: Src) -> SSARef470     fn mufu(&mut self, op: MuFuOp, src: Src) -> SSARef {
471         let dst = self.alloc_ssa(RegFile::GPR, 1);
472         self.push_op(OpMuFu {
473             dst: dst.into(),
474             op: op,
475             src: src,
476         });
477         dst
478     }
479 
fsin(&mut self, src: Src) -> SSARef480     fn fsin(&mut self, src: Src) -> SSARef {
481         let tmp = if self.sm() >= 70 {
482             let frac_1_2pi = 1.0 / (2.0 * std::f32::consts::PI);
483             self.fmul(src, frac_1_2pi.into())
484         } else {
485             let tmp = self.alloc_ssa(RegFile::GPR, 1);
486             self.push_op(OpRro {
487                 dst: tmp.into(),
488                 op: RroOp::SinCos,
489                 src,
490             });
491             tmp
492         };
493         self.mufu(MuFuOp::Sin, tmp.into())
494     }
495 
fcos(&mut self, src: Src) -> SSARef496     fn fcos(&mut self, src: Src) -> SSARef {
497         let tmp = if self.sm() >= 70 {
498             let frac_1_2pi = 1.0 / (2.0 * std::f32::consts::PI);
499             self.fmul(src, frac_1_2pi.into())
500         } else {
501             let tmp = self.alloc_ssa(RegFile::GPR, 1);
502             self.push_op(OpRro {
503                 dst: tmp.into(),
504                 op: RroOp::SinCos,
505                 src,
506             });
507             tmp
508         };
509         self.mufu(MuFuOp::Cos, tmp.into())
510     }
511 
fexp2(&mut self, src: Src) -> SSARef512     fn fexp2(&mut self, src: Src) -> SSARef {
513         let tmp = if self.sm() >= 70 {
514             src
515         } else {
516             let tmp = self.alloc_ssa(RegFile::GPR, 1);
517             self.push_op(OpRro {
518                 dst: tmp.into(),
519                 op: RroOp::Exp2,
520                 src,
521             });
522             tmp.into()
523         };
524         self.mufu(MuFuOp::Exp2, tmp)
525     }
526 
prmt(&mut self, x: Src, y: Src, sel: [u8; 4]) -> SSARef527     fn prmt(&mut self, x: Src, y: Src, sel: [u8; 4]) -> SSARef {
528         let dst = self.alloc_ssa(RegFile::GPR, 1);
529         self.prmt_to(dst.into(), x, y, sel);
530         dst
531     }
532 
prmt4(&mut self, src: [Src; 4], sel: [u8; 4]) -> SSARef533     fn prmt4(&mut self, src: [Src; 4], sel: [u8; 4]) -> SSARef {
534         let max_sel = *sel.iter().max().unwrap();
535         if max_sel < 8 {
536             self.prmt(src[0], src[1], sel)
537         } else if max_sel < 12 {
538             let mut sel_a = [0_u8; 4];
539             let mut sel_b = [0_u8; 4];
540             for i in 0..4_u8 {
541                 if sel[usize::from(i)] < 8 {
542                     sel_a[usize::from(i)] = sel[usize::from(i)];
543                     sel_b[usize::from(i)] = i;
544                 } else {
545                     sel_b[usize::from(i)] = (sel[usize::from(i)] - 8) + 4;
546                 }
547             }
548             let a = self.prmt(src[0], src[1], sel_a);
549             self.prmt(a.into(), src[2], sel_b)
550         } else if max_sel < 16 {
551             let mut sel_a = [0_u8; 4];
552             let mut sel_b = [0_u8; 4];
553             let mut sel_c = [0_u8; 4];
554             for i in 0..4_u8 {
555                 if sel[usize::from(i)] < 8 {
556                     sel_a[usize::from(i)] = sel[usize::from(i)];
557                     sel_c[usize::from(i)] = i;
558                 } else {
559                     sel_b[usize::from(i)] = sel[usize::from(i)] - 8;
560                     sel_c[usize::from(i)] = 4 + i;
561                 }
562             }
563             let a = self.prmt(src[0], src[1], sel_a);
564             let b = self.prmt(src[2], src[3], sel_b);
565             self.prmt(a.into(), b.into(), sel_c)
566         } else {
567             panic!("Invalid permute value: {max_sel}");
568         }
569     }
570 
sel(&mut self, cond: Src, x: Src, y: Src) -> SSARef571     fn sel(&mut self, cond: Src, x: Src, y: Src) -> SSARef {
572         assert!(cond.src_ref.is_predicate());
573         assert!(x.is_predicate() == y.is_predicate());
574         if x.is_predicate() {
575             let dst = self.alloc_ssa(RegFile::Pred, 1);
576             if self.sm() >= 70 {
577                 self.push_op(OpPLop3 {
578                     dsts: [dst.into(), Dst::None],
579                     srcs: [cond, x, y],
580                     ops: [
581                         LogicOp3::new_lut(&|c, x, y| (c & x) | (!c & y)),
582                         LogicOp3::new_const(false),
583                     ],
584                 });
585             } else {
586                 let tmp = self.alloc_ssa(RegFile::Pred, 1);
587                 self.push_op(OpPSetP {
588                     dsts: [tmp.into(), Dst::None],
589                     ops: [PredSetOp::And, PredSetOp::And],
590                     srcs: [cond, x, true.into()],
591                 });
592                 self.push_op(OpPSetP {
593                     dsts: [dst.into(), Dst::None],
594                     ops: [PredSetOp::And, PredSetOp::Or],
595                     srcs: [cond.bnot(), y, tmp.into()],
596                 });
597             }
598             dst
599         } else {
600             let dst = self.alloc_ssa(RegFile::GPR, 1);
601             self.push_op(OpSel {
602                 dst: dst.into(),
603                 cond: cond,
604                 srcs: [x, y],
605             });
606             dst
607         }
608     }
609 
copy(&mut self, src: Src) -> SSARef610     fn copy(&mut self, src: Src) -> SSARef {
611         let dst = if src.is_predicate() {
612             self.alloc_ssa(RegFile::Pred, 1)
613         } else {
614             self.alloc_ssa(RegFile::GPR, 1)
615         };
616         self.copy_to(dst.into(), src);
617         dst
618     }
619 
bmov_to_bar(&mut self, src: Src) -> SSARef620     fn bmov_to_bar(&mut self, src: Src) -> SSARef {
621         assert!(src.src_ref.as_ssa().unwrap().file() == RegFile::GPR);
622         let dst = self.alloc_ssa(RegFile::Bar, 1);
623         self.push_op(OpBMov {
624             dst: dst.into(),
625             src: src,
626             clear: false,
627         });
628         dst
629     }
630 
bmov_to_gpr(&mut self, src: Src) -> SSARef631     fn bmov_to_gpr(&mut self, src: Src) -> SSARef {
632         assert!(src.src_ref.as_ssa().unwrap().file() == RegFile::Bar);
633         let dst = self.alloc_ssa(RegFile::GPR, 1);
634         self.push_op(OpBMov {
635             dst: dst.into(),
636             src: src,
637             clear: false,
638         });
639         dst
640     }
641 }
642 
643 pub struct InstrBuilder {
644     instrs: MappedInstrs,
645     sm: u8,
646 }
647 
648 impl InstrBuilder {
new(sm: u8) -> Self649     pub fn new(sm: u8) -> Self {
650         Self {
651             instrs: MappedInstrs::None,
652             sm,
653         }
654     }
655 
as_vec(self) -> Vec<Box<Instr>>656     pub fn as_vec(self) -> Vec<Box<Instr>> {
657         match self.instrs {
658             MappedInstrs::None => Vec::new(),
659             MappedInstrs::One(i) => vec![i],
660             MappedInstrs::Many(v) => v,
661         }
662     }
663 
as_mapped_instrs(self) -> MappedInstrs664     pub fn as_mapped_instrs(self) -> MappedInstrs {
665         self.instrs
666     }
667 }
668 
669 impl Builder for InstrBuilder {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr670     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
671         self.instrs.push(instr);
672         self.instrs.last_mut().unwrap().as_mut()
673     }
674 
sm(&self) -> u8675     fn sm(&self) -> u8 {
676         self.sm
677     }
678 }
679 
680 pub struct SSAInstrBuilder<'a> {
681     b: InstrBuilder,
682     alloc: &'a mut SSAValueAllocator,
683 }
684 
685 impl<'a> SSAInstrBuilder<'a> {
new(sm: u8, alloc: &'a mut SSAValueAllocator) -> Self686     pub fn new(sm: u8, alloc: &'a mut SSAValueAllocator) -> Self {
687         Self {
688             b: InstrBuilder::new(sm),
689             alloc: alloc,
690         }
691     }
692 
as_vec(self) -> Vec<Box<Instr>>693     pub fn as_vec(self) -> Vec<Box<Instr>> {
694         self.b.as_vec()
695     }
696 
697     #[allow(dead_code)]
as_mapped_instrs(self) -> MappedInstrs698     pub fn as_mapped_instrs(self) -> MappedInstrs {
699         self.b.as_mapped_instrs()
700     }
701 }
702 
703 impl<'a> Builder for SSAInstrBuilder<'a> {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr704     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
705         self.b.push_instr(instr)
706     }
707 
sm(&self) -> u8708     fn sm(&self) -> u8 {
709         self.b.sm()
710     }
711 }
712 
713 impl<'a> SSABuilder for SSAInstrBuilder<'a> {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef714     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
715         self.alloc.alloc_vec(file, comps)
716     }
717 }
718 
719 pub struct PredicatedBuilder<'a, T: Builder> {
720     b: &'a mut T,
721     pred: Pred,
722 }
723 
724 impl<'a, T: Builder> Builder for PredicatedBuilder<'a, T> {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr725     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
726         let mut instr = instr;
727         assert!(instr.pred.is_true());
728         instr.pred = self.pred;
729         self.b.push_instr(instr)
730     }
731 
sm(&self) -> u8732     fn sm(&self) -> u8 {
733         self.b.sm()
734     }
735 }
736 
737 impl<'a, T: SSABuilder> SSABuilder for PredicatedBuilder<'a, T> {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef738     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
739         self.b.alloc_ssa(file, comps)
740     }
741 }
742