xref: /aosp_15_r20/external/mesa3d/src/nouveau/compiler/nak/builder.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 pub trait Builder {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr7*61046927SAndroid Build Coastguard Worker     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr;
8*61046927SAndroid Build Coastguard Worker 
sm(&self) -> u89*61046927SAndroid Build Coastguard Worker     fn sm(&self) -> u8;
10*61046927SAndroid Build Coastguard Worker 
push_op(&mut self, op: impl Into<Op>) -> &mut Instr11*61046927SAndroid Build Coastguard Worker     fn push_op(&mut self, op: impl Into<Op>) -> &mut Instr {
12*61046927SAndroid Build Coastguard Worker         self.push_instr(Instr::new_boxed(op))
13*61046927SAndroid Build Coastguard Worker     }
14*61046927SAndroid Build Coastguard Worker 
predicate(&mut self, pred: Pred) -> PredicatedBuilder<'_, Self> where Self: Sized,15*61046927SAndroid Build Coastguard Worker     fn predicate(&mut self, pred: Pred) -> PredicatedBuilder<'_, Self>
16*61046927SAndroid Build Coastguard Worker     where
17*61046927SAndroid Build Coastguard Worker         Self: Sized,
18*61046927SAndroid Build Coastguard Worker     {
19*61046927SAndroid Build Coastguard Worker         PredicatedBuilder {
20*61046927SAndroid Build Coastguard Worker             b: self,
21*61046927SAndroid Build Coastguard Worker             pred: pred,
22*61046927SAndroid Build Coastguard Worker         }
23*61046927SAndroid Build Coastguard Worker     }
24*61046927SAndroid Build Coastguard Worker 
lop2_to(&mut self, dst: Dst, op: LogicOp2, mut x: Src, mut y: Src)25*61046927SAndroid Build Coastguard Worker     fn lop2_to(&mut self, dst: Dst, op: LogicOp2, mut x: Src, mut y: Src) {
26*61046927SAndroid Build Coastguard Worker         let is_predicate = match dst {
27*61046927SAndroid Build Coastguard Worker             Dst::None => panic!("No LOP destination"),
28*61046927SAndroid Build Coastguard Worker             Dst::SSA(ssa) => ssa.is_predicate(),
29*61046927SAndroid Build Coastguard Worker             Dst::Reg(reg) => reg.is_predicate(),
30*61046927SAndroid Build Coastguard Worker         };
31*61046927SAndroid Build Coastguard Worker         assert!(x.is_predicate() == is_predicate);
32*61046927SAndroid Build Coastguard Worker         assert!(y.is_predicate() == is_predicate);
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
35*61046927SAndroid Build Coastguard Worker             let mut op = op.to_lut();
36*61046927SAndroid Build Coastguard Worker             if x.src_mod.is_bnot() {
37*61046927SAndroid Build Coastguard Worker                 op = LogicOp3::new_lut(&|x, y, _| op.eval(!x, y, 0));
38*61046927SAndroid Build Coastguard Worker                 x.src_mod = SrcMod::None;
39*61046927SAndroid Build Coastguard Worker             }
40*61046927SAndroid Build Coastguard Worker             if y.src_mod.is_bnot() {
41*61046927SAndroid Build Coastguard Worker                 op = LogicOp3::new_lut(&|x, y, _| op.eval(x, !y, 0));
42*61046927SAndroid Build Coastguard Worker                 y.src_mod = SrcMod::None;
43*61046927SAndroid Build Coastguard Worker             }
44*61046927SAndroid Build Coastguard Worker             if is_predicate {
45*61046927SAndroid Build Coastguard Worker                 self.push_op(OpPLop3 {
46*61046927SAndroid Build Coastguard Worker                     dsts: [dst, Dst::None],
47*61046927SAndroid Build Coastguard Worker                     srcs: [x, y, true.into()],
48*61046927SAndroid Build Coastguard Worker                     ops: [op, LogicOp3::new_const(false)],
49*61046927SAndroid Build Coastguard Worker                 });
50*61046927SAndroid Build Coastguard Worker             } else {
51*61046927SAndroid Build Coastguard Worker                 self.push_op(OpLop3 {
52*61046927SAndroid Build Coastguard Worker                     dst: dst,
53*61046927SAndroid Build Coastguard Worker                     srcs: [x, y, 0.into()],
54*61046927SAndroid Build Coastguard Worker                     op: op,
55*61046927SAndroid Build Coastguard Worker                 });
56*61046927SAndroid Build Coastguard Worker             }
57*61046927SAndroid Build Coastguard Worker         } else {
58*61046927SAndroid Build Coastguard Worker             if is_predicate {
59*61046927SAndroid Build Coastguard Worker                 let mut x = x;
60*61046927SAndroid Build Coastguard Worker                 let cmp_op = match op {
61*61046927SAndroid Build Coastguard Worker                     LogicOp2::And => PredSetOp::And,
62*61046927SAndroid Build Coastguard Worker                     LogicOp2::Or => PredSetOp::Or,
63*61046927SAndroid Build Coastguard Worker                     LogicOp2::Xor => PredSetOp::Xor,
64*61046927SAndroid Build Coastguard Worker                     LogicOp2::PassB => {
65*61046927SAndroid Build Coastguard Worker                         // Pass through B by AND with PT
66*61046927SAndroid Build Coastguard Worker                         x = true.into();
67*61046927SAndroid Build Coastguard Worker                         PredSetOp::And
68*61046927SAndroid Build Coastguard Worker                     }
69*61046927SAndroid Build Coastguard Worker                 };
70*61046927SAndroid Build Coastguard Worker                 self.push_op(OpPSetP {
71*61046927SAndroid Build Coastguard Worker                     dsts: [dst, Dst::None],
72*61046927SAndroid Build Coastguard Worker                     ops: [cmp_op, PredSetOp::And],
73*61046927SAndroid Build Coastguard Worker                     srcs: [x, y, true.into()],
74*61046927SAndroid Build Coastguard Worker                 });
75*61046927SAndroid Build Coastguard Worker             } else {
76*61046927SAndroid Build Coastguard Worker                 self.push_op(OpLop2 {
77*61046927SAndroid Build Coastguard Worker                     dst: dst,
78*61046927SAndroid Build Coastguard Worker                     srcs: [x, y],
79*61046927SAndroid Build Coastguard Worker                     op: op,
80*61046927SAndroid Build Coastguard Worker                 });
81*61046927SAndroid Build Coastguard Worker             }
82*61046927SAndroid Build Coastguard Worker         }
83*61046927SAndroid Build Coastguard Worker     }
84*61046927SAndroid Build Coastguard Worker 
prmt_to(&mut self, dst: Dst, x: Src, y: Src, sel: [u8; 4])85*61046927SAndroid Build Coastguard Worker     fn prmt_to(&mut self, dst: Dst, x: Src, y: Src, sel: [u8; 4]) {
86*61046927SAndroid Build Coastguard Worker         if sel == [0, 1, 2, 3] {
87*61046927SAndroid Build Coastguard Worker             self.copy_to(dst, x);
88*61046927SAndroid Build Coastguard Worker         } else if sel == [4, 5, 6, 7] {
89*61046927SAndroid Build Coastguard Worker             self.copy_to(dst, y);
90*61046927SAndroid Build Coastguard Worker         } else {
91*61046927SAndroid Build Coastguard Worker             let mut sel_u32 = 0;
92*61046927SAndroid Build Coastguard Worker             for i in 0..4 {
93*61046927SAndroid Build Coastguard Worker                 assert!(sel[i] < 16);
94*61046927SAndroid Build Coastguard Worker                 sel_u32 |= u32::from(sel[i]) << (i * 4);
95*61046927SAndroid Build Coastguard Worker             }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker             self.push_op(OpPrmt {
98*61046927SAndroid Build Coastguard Worker                 dst: dst,
99*61046927SAndroid Build Coastguard Worker                 srcs: [x, y],
100*61046927SAndroid Build Coastguard Worker                 sel: sel_u32.into(),
101*61046927SAndroid Build Coastguard Worker                 mode: PrmtMode::Index,
102*61046927SAndroid Build Coastguard Worker             });
103*61046927SAndroid Build Coastguard Worker         }
104*61046927SAndroid Build Coastguard Worker     }
105*61046927SAndroid Build Coastguard Worker 
copy_to(&mut self, dst: Dst, src: Src)106*61046927SAndroid Build Coastguard Worker     fn copy_to(&mut self, dst: Dst, src: Src) {
107*61046927SAndroid Build Coastguard Worker         self.push_op(OpCopy { dst: dst, src: src });
108*61046927SAndroid Build Coastguard Worker     }
109*61046927SAndroid Build Coastguard Worker 
swap(&mut self, x: RegRef, y: RegRef)110*61046927SAndroid Build Coastguard Worker     fn swap(&mut self, x: RegRef, y: RegRef) {
111*61046927SAndroid Build Coastguard Worker         assert!(x.file() == y.file());
112*61046927SAndroid Build Coastguard Worker         self.push_op(OpSwap {
113*61046927SAndroid Build Coastguard Worker             dsts: [x.into(), y.into()],
114*61046927SAndroid Build Coastguard Worker             srcs: [y.into(), x.into()],
115*61046927SAndroid Build Coastguard Worker         });
116*61046927SAndroid Build Coastguard Worker     }
117*61046927SAndroid Build Coastguard Worker }
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker pub trait SSABuilder: Builder {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef120*61046927SAndroid Build Coastguard Worker     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef;
121*61046927SAndroid Build Coastguard Worker 
shl(&mut self, x: Src, shift: Src) -> SSARef122*61046927SAndroid Build Coastguard Worker     fn shl(&mut self, x: Src, shift: Src) -> SSARef {
123*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
124*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
125*61046927SAndroid Build Coastguard Worker             self.push_op(OpShf {
126*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
127*61046927SAndroid Build Coastguard Worker                 low: x,
128*61046927SAndroid Build Coastguard Worker                 high: 0.into(),
129*61046927SAndroid Build Coastguard Worker                 shift: shift,
130*61046927SAndroid Build Coastguard Worker                 right: false,
131*61046927SAndroid Build Coastguard Worker                 wrap: true,
132*61046927SAndroid Build Coastguard Worker                 data_type: IntType::I32,
133*61046927SAndroid Build Coastguard Worker                 dst_high: false,
134*61046927SAndroid Build Coastguard Worker             });
135*61046927SAndroid Build Coastguard Worker         } else {
136*61046927SAndroid Build Coastguard Worker             self.push_op(OpShl {
137*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
138*61046927SAndroid Build Coastguard Worker                 src: x,
139*61046927SAndroid Build Coastguard Worker                 shift: shift,
140*61046927SAndroid Build Coastguard Worker                 wrap: true,
141*61046927SAndroid Build Coastguard Worker             });
142*61046927SAndroid Build Coastguard Worker         }
143*61046927SAndroid Build Coastguard Worker         dst
144*61046927SAndroid Build Coastguard Worker     }
145*61046927SAndroid Build Coastguard Worker 
shl64(&mut self, x: Src, shift: Src) -> SSARef146*61046927SAndroid Build Coastguard Worker     fn shl64(&mut self, x: Src, shift: Src) -> SSARef {
147*61046927SAndroid Build Coastguard Worker         let x = x.as_ssa().unwrap();
148*61046927SAndroid Build Coastguard Worker         debug_assert!(shift.src_mod.is_none());
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 2);
151*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
152*61046927SAndroid Build Coastguard Worker             self.push_op(OpShf {
153*61046927SAndroid Build Coastguard Worker                 dst: dst[0].into(),
154*61046927SAndroid Build Coastguard Worker                 low: x[0].into(),
155*61046927SAndroid Build Coastguard Worker                 high: 0.into(),
156*61046927SAndroid Build Coastguard Worker                 shift,
157*61046927SAndroid Build Coastguard Worker                 right: false,
158*61046927SAndroid Build Coastguard Worker                 wrap: true,
159*61046927SAndroid Build Coastguard Worker                 data_type: IntType::U64,
160*61046927SAndroid Build Coastguard Worker                 dst_high: false,
161*61046927SAndroid Build Coastguard Worker             });
162*61046927SAndroid Build Coastguard Worker         } else {
163*61046927SAndroid Build Coastguard Worker             // On Maxwell and earlier, shf.l doesn't work without .high so we
164*61046927SAndroid Build Coastguard Worker             // have to use a regular 32-bit shift here.  32-bit shift doesn't
165*61046927SAndroid Build Coastguard Worker             // have the NIR wrap semantics so we need to wrap manually.
166*61046927SAndroid Build Coastguard Worker             let shift = if let SrcRef::Imm32(imm) = shift.src_ref {
167*61046927SAndroid Build Coastguard Worker                 (imm & 0x3f).into()
168*61046927SAndroid Build Coastguard Worker             } else {
169*61046927SAndroid Build Coastguard Worker                 self.lop2(LogicOp2::And, shift, 0x3f.into()).into()
170*61046927SAndroid Build Coastguard Worker             };
171*61046927SAndroid Build Coastguard Worker             self.push_op(OpShf {
172*61046927SAndroid Build Coastguard Worker                 dst: dst[0].into(),
173*61046927SAndroid Build Coastguard Worker                 low: 0.into(),
174*61046927SAndroid Build Coastguard Worker                 high: x[0].into(),
175*61046927SAndroid Build Coastguard Worker                 shift,
176*61046927SAndroid Build Coastguard Worker                 right: false,
177*61046927SAndroid Build Coastguard Worker                 wrap: false,
178*61046927SAndroid Build Coastguard Worker                 data_type: IntType::U32,
179*61046927SAndroid Build Coastguard Worker                 dst_high: true,
180*61046927SAndroid Build Coastguard Worker             });
181*61046927SAndroid Build Coastguard Worker         }
182*61046927SAndroid Build Coastguard Worker         self.push_op(OpShf {
183*61046927SAndroid Build Coastguard Worker             dst: dst[1].into(),
184*61046927SAndroid Build Coastguard Worker             low: x[0].into(),
185*61046927SAndroid Build Coastguard Worker             high: x[1].into(),
186*61046927SAndroid Build Coastguard Worker             shift,
187*61046927SAndroid Build Coastguard Worker             right: false,
188*61046927SAndroid Build Coastguard Worker             wrap: true,
189*61046927SAndroid Build Coastguard Worker             data_type: IntType::U64,
190*61046927SAndroid Build Coastguard Worker             dst_high: true,
191*61046927SAndroid Build Coastguard Worker         });
192*61046927SAndroid Build Coastguard Worker         dst
193*61046927SAndroid Build Coastguard Worker     }
194*61046927SAndroid Build Coastguard Worker 
shr(&mut self, x: Src, shift: Src, signed: bool) -> SSARef195*61046927SAndroid Build Coastguard Worker     fn shr(&mut self, x: Src, shift: Src, signed: bool) -> SSARef {
196*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
197*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
198*61046927SAndroid Build Coastguard Worker             self.push_op(OpShf {
199*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
200*61046927SAndroid Build Coastguard Worker                 low: 0.into(),
201*61046927SAndroid Build Coastguard Worker                 high: x,
202*61046927SAndroid Build Coastguard Worker                 shift: shift,
203*61046927SAndroid Build Coastguard Worker                 right: true,
204*61046927SAndroid Build Coastguard Worker                 wrap: true,
205*61046927SAndroid Build Coastguard Worker                 data_type: if signed { IntType::I32 } else { IntType::U32 },
206*61046927SAndroid Build Coastguard Worker                 dst_high: true,
207*61046927SAndroid Build Coastguard Worker             });
208*61046927SAndroid Build Coastguard Worker         } else {
209*61046927SAndroid Build Coastguard Worker             self.push_op(OpShr {
210*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
211*61046927SAndroid Build Coastguard Worker                 src: x,
212*61046927SAndroid Build Coastguard Worker                 shift: shift,
213*61046927SAndroid Build Coastguard Worker                 wrap: true,
214*61046927SAndroid Build Coastguard Worker                 signed,
215*61046927SAndroid Build Coastguard Worker             });
216*61046927SAndroid Build Coastguard Worker         }
217*61046927SAndroid Build Coastguard Worker         dst
218*61046927SAndroid Build Coastguard Worker     }
219*61046927SAndroid Build Coastguard Worker 
shr64(&mut self, x: Src, shift: Src, signed: bool) -> SSARef220*61046927SAndroid Build Coastguard Worker     fn shr64(&mut self, x: Src, shift: Src, signed: bool) -> SSARef {
221*61046927SAndroid Build Coastguard Worker         let x = x.as_ssa().unwrap();
222*61046927SAndroid Build Coastguard Worker         debug_assert!(shift.src_mod.is_none());
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 2);
225*61046927SAndroid Build Coastguard Worker         self.push_op(OpShf {
226*61046927SAndroid Build Coastguard Worker             dst: dst[0].into(),
227*61046927SAndroid Build Coastguard Worker             low: x[0].into(),
228*61046927SAndroid Build Coastguard Worker             high: x[1].into(),
229*61046927SAndroid Build Coastguard Worker             shift,
230*61046927SAndroid Build Coastguard Worker             right: true,
231*61046927SAndroid Build Coastguard Worker             wrap: true,
232*61046927SAndroid Build Coastguard Worker             data_type: if signed { IntType::I64 } else { IntType::U64 },
233*61046927SAndroid Build Coastguard Worker             dst_high: false,
234*61046927SAndroid Build Coastguard Worker         });
235*61046927SAndroid Build Coastguard Worker         self.push_op(OpShf {
236*61046927SAndroid Build Coastguard Worker             dst: dst[1].into(),
237*61046927SAndroid Build Coastguard Worker             low: 0.into(),
238*61046927SAndroid Build Coastguard Worker             high: x[1].into(),
239*61046927SAndroid Build Coastguard Worker             shift,
240*61046927SAndroid Build Coastguard Worker             right: true,
241*61046927SAndroid Build Coastguard Worker             wrap: true,
242*61046927SAndroid Build Coastguard Worker             data_type: if signed { IntType::I64 } else { IntType::U64 },
243*61046927SAndroid Build Coastguard Worker             dst_high: true,
244*61046927SAndroid Build Coastguard Worker         });
245*61046927SAndroid Build Coastguard Worker         dst
246*61046927SAndroid Build Coastguard Worker     }
247*61046927SAndroid Build Coastguard Worker 
fadd(&mut self, x: Src, y: Src) -> SSARef248*61046927SAndroid Build Coastguard Worker     fn fadd(&mut self, x: Src, y: Src) -> SSARef {
249*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
250*61046927SAndroid Build Coastguard Worker         self.push_op(OpFAdd {
251*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
252*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
253*61046927SAndroid Build Coastguard Worker             saturate: false,
254*61046927SAndroid Build Coastguard Worker             rnd_mode: FRndMode::NearestEven,
255*61046927SAndroid Build Coastguard Worker             ftz: false,
256*61046927SAndroid Build Coastguard Worker         });
257*61046927SAndroid Build Coastguard Worker         dst
258*61046927SAndroid Build Coastguard Worker     }
259*61046927SAndroid Build Coastguard Worker 
fmul(&mut self, x: Src, y: Src) -> SSARef260*61046927SAndroid Build Coastguard Worker     fn fmul(&mut self, x: Src, y: Src) -> SSARef {
261*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
262*61046927SAndroid Build Coastguard Worker         self.push_op(OpFMul {
263*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
264*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
265*61046927SAndroid Build Coastguard Worker             saturate: false,
266*61046927SAndroid Build Coastguard Worker             rnd_mode: FRndMode::NearestEven,
267*61046927SAndroid Build Coastguard Worker             ftz: false,
268*61046927SAndroid Build Coastguard Worker             dnz: false,
269*61046927SAndroid Build Coastguard Worker         });
270*61046927SAndroid Build Coastguard Worker         dst
271*61046927SAndroid Build Coastguard Worker     }
272*61046927SAndroid Build Coastguard Worker 
fset(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef273*61046927SAndroid Build Coastguard Worker     fn fset(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
274*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
275*61046927SAndroid Build Coastguard Worker         self.push_op(OpFSet {
276*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
277*61046927SAndroid Build Coastguard Worker             cmp_op: cmp_op,
278*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
279*61046927SAndroid Build Coastguard Worker             ftz: false,
280*61046927SAndroid Build Coastguard Worker         });
281*61046927SAndroid Build Coastguard Worker         dst
282*61046927SAndroid Build Coastguard Worker     }
283*61046927SAndroid Build Coastguard Worker 
fsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef284*61046927SAndroid Build Coastguard Worker     fn fsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
285*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::Pred, 1);
286*61046927SAndroid Build Coastguard Worker         self.push_op(OpFSetP {
287*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
288*61046927SAndroid Build Coastguard Worker             set_op: PredSetOp::And,
289*61046927SAndroid Build Coastguard Worker             cmp_op: cmp_op,
290*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
291*61046927SAndroid Build Coastguard Worker             accum: SrcRef::True.into(),
292*61046927SAndroid Build Coastguard Worker             ftz: false,
293*61046927SAndroid Build Coastguard Worker         });
294*61046927SAndroid Build Coastguard Worker         dst
295*61046927SAndroid Build Coastguard Worker     }
296*61046927SAndroid Build Coastguard Worker 
hadd2(&mut self, x: Src, y: Src) -> SSARef297*61046927SAndroid Build Coastguard Worker     fn hadd2(&mut self, x: Src, y: Src) -> SSARef {
298*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
299*61046927SAndroid Build Coastguard Worker         self.push_op(OpHAdd2 {
300*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
301*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
302*61046927SAndroid Build Coastguard Worker             saturate: false,
303*61046927SAndroid Build Coastguard Worker             ftz: false,
304*61046927SAndroid Build Coastguard Worker             f32: false,
305*61046927SAndroid Build Coastguard Worker         });
306*61046927SAndroid Build Coastguard Worker         dst
307*61046927SAndroid Build Coastguard Worker     }
308*61046927SAndroid Build Coastguard Worker 
hset2(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef309*61046927SAndroid Build Coastguard Worker     fn hset2(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
310*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
311*61046927SAndroid Build Coastguard Worker         self.push_op(OpHSet2 {
312*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
313*61046927SAndroid Build Coastguard Worker             set_op: PredSetOp::And,
314*61046927SAndroid Build Coastguard Worker             cmp_op: cmp_op,
315*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
316*61046927SAndroid Build Coastguard Worker             ftz: false,
317*61046927SAndroid Build Coastguard Worker             accum: SrcRef::True.into(),
318*61046927SAndroid Build Coastguard Worker         });
319*61046927SAndroid Build Coastguard Worker         dst
320*61046927SAndroid Build Coastguard Worker     }
321*61046927SAndroid Build Coastguard Worker 
dsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef322*61046927SAndroid Build Coastguard Worker     fn dsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
323*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::Pred, 1);
324*61046927SAndroid Build Coastguard Worker         self.push_op(OpDSetP {
325*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
326*61046927SAndroid Build Coastguard Worker             set_op: PredSetOp::And,
327*61046927SAndroid Build Coastguard Worker             cmp_op: cmp_op,
328*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
329*61046927SAndroid Build Coastguard Worker             accum: SrcRef::True.into(),
330*61046927SAndroid Build Coastguard Worker         });
331*61046927SAndroid Build Coastguard Worker         dst
332*61046927SAndroid Build Coastguard Worker     }
333*61046927SAndroid Build Coastguard Worker 
iabs(&mut self, i: Src) -> SSARef334*61046927SAndroid Build Coastguard Worker     fn iabs(&mut self, i: Src) -> SSARef {
335*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
336*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
337*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAbs {
338*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
339*61046927SAndroid Build Coastguard Worker                 src: i,
340*61046927SAndroid Build Coastguard Worker             });
341*61046927SAndroid Build Coastguard Worker         } else {
342*61046927SAndroid Build Coastguard Worker             self.push_op(OpI2I {
343*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
344*61046927SAndroid Build Coastguard Worker                 src: i,
345*61046927SAndroid Build Coastguard Worker                 src_type: IntType::I32,
346*61046927SAndroid Build Coastguard Worker                 dst_type: IntType::I32,
347*61046927SAndroid Build Coastguard Worker                 saturate: false,
348*61046927SAndroid Build Coastguard Worker                 abs: true,
349*61046927SAndroid Build Coastguard Worker                 neg: false,
350*61046927SAndroid Build Coastguard Worker             });
351*61046927SAndroid Build Coastguard Worker         }
352*61046927SAndroid Build Coastguard Worker         dst
353*61046927SAndroid Build Coastguard Worker     }
354*61046927SAndroid Build Coastguard Worker 
iadd(&mut self, x: Src, y: Src, z: Src) -> SSARef355*61046927SAndroid Build Coastguard Worker     fn iadd(&mut self, x: Src, y: Src, z: Src) -> SSARef {
356*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
357*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
358*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd3 {
359*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
360*61046927SAndroid Build Coastguard Worker                 srcs: [x, y, z],
361*61046927SAndroid Build Coastguard Worker                 overflow: [Dst::None; 2],
362*61046927SAndroid Build Coastguard Worker             });
363*61046927SAndroid Build Coastguard Worker         } else {
364*61046927SAndroid Build Coastguard Worker             assert!(z.is_zero());
365*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd2 {
366*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
367*61046927SAndroid Build Coastguard Worker                 srcs: [x, y],
368*61046927SAndroid Build Coastguard Worker                 carry_out: Dst::None,
369*61046927SAndroid Build Coastguard Worker             });
370*61046927SAndroid Build Coastguard Worker         }
371*61046927SAndroid Build Coastguard Worker         dst
372*61046927SAndroid Build Coastguard Worker     }
373*61046927SAndroid Build Coastguard Worker 
iadd64(&mut self, x: Src, y: Src, z: Src) -> SSARef374*61046927SAndroid Build Coastguard Worker     fn iadd64(&mut self, x: Src, y: Src, z: Src) -> SSARef {
375*61046927SAndroid Build Coastguard Worker         fn split_iadd64_src(src: Src) -> [Src; 2] {
376*61046927SAndroid Build Coastguard Worker             match src.src_ref {
377*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero => [0.into(), 0.into()],
378*61046927SAndroid Build Coastguard Worker                 SrcRef::SSA(ssa) => {
379*61046927SAndroid Build Coastguard Worker                     if src.src_mod.is_ineg() {
380*61046927SAndroid Build Coastguard Worker                         [Src::from(ssa[0]).ineg(), Src::from(ssa[1]).bnot()]
381*61046927SAndroid Build Coastguard Worker                     } else {
382*61046927SAndroid Build Coastguard Worker                         [Src::from(ssa[0]), Src::from(ssa[1])]
383*61046927SAndroid Build Coastguard Worker                     }
384*61046927SAndroid Build Coastguard Worker                 }
385*61046927SAndroid Build Coastguard Worker                 _ => panic!("Unsupported iadd64 source"),
386*61046927SAndroid Build Coastguard Worker             }
387*61046927SAndroid Build Coastguard Worker         }
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker         let is_3src = !x.is_zero() && !y.is_zero() && !z.is_zero();
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker         let x = split_iadd64_src(x);
392*61046927SAndroid Build Coastguard Worker         let y = split_iadd64_src(y);
393*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 2);
394*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
395*61046927SAndroid Build Coastguard Worker             let carry1 = self.alloc_ssa(RegFile::Pred, 1);
396*61046927SAndroid Build Coastguard Worker             let (carry2_dst, carry2_src) = if is_3src {
397*61046927SAndroid Build Coastguard Worker                 let carry2 = self.alloc_ssa(RegFile::Pred, 1);
398*61046927SAndroid Build Coastguard Worker                 (carry2.into(), carry2.into())
399*61046927SAndroid Build Coastguard Worker             } else {
400*61046927SAndroid Build Coastguard Worker                 // If one of the sources is known to be zero, we only need one
401*61046927SAndroid Build Coastguard Worker                 // carry predicate.
402*61046927SAndroid Build Coastguard Worker                 (Dst::None, false.into())
403*61046927SAndroid Build Coastguard Worker             };
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker             let z = split_iadd64_src(z);
406*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd3 {
407*61046927SAndroid Build Coastguard Worker                 dst: dst[0].into(),
408*61046927SAndroid Build Coastguard Worker                 overflow: [carry1.into(), carry2_dst],
409*61046927SAndroid Build Coastguard Worker                 srcs: [x[0], y[0], z[0]],
410*61046927SAndroid Build Coastguard Worker             });
411*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd3X {
412*61046927SAndroid Build Coastguard Worker                 dst: dst[1].into(),
413*61046927SAndroid Build Coastguard Worker                 overflow: [Dst::None, Dst::None],
414*61046927SAndroid Build Coastguard Worker                 srcs: [x[1], y[1], z[1]],
415*61046927SAndroid Build Coastguard Worker                 carry: [carry1.into(), carry2_src],
416*61046927SAndroid Build Coastguard Worker             });
417*61046927SAndroid Build Coastguard Worker         } else {
418*61046927SAndroid Build Coastguard Worker             assert!(z.is_zero());
419*61046927SAndroid Build Coastguard Worker             let carry = self.alloc_ssa(RegFile::Carry, 1);
420*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd2 {
421*61046927SAndroid Build Coastguard Worker                 dst: dst[0].into(),
422*61046927SAndroid Build Coastguard Worker                 srcs: [x[0], y[0]],
423*61046927SAndroid Build Coastguard Worker                 carry_out: carry.into(),
424*61046927SAndroid Build Coastguard Worker             });
425*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd2X {
426*61046927SAndroid Build Coastguard Worker                 dst: dst[1].into(),
427*61046927SAndroid Build Coastguard Worker                 srcs: [x[1], y[1]],
428*61046927SAndroid Build Coastguard Worker                 carry_out: Dst::None,
429*61046927SAndroid Build Coastguard Worker                 carry_in: carry.into(),
430*61046927SAndroid Build Coastguard Worker             });
431*61046927SAndroid Build Coastguard Worker         }
432*61046927SAndroid Build Coastguard Worker         dst
433*61046927SAndroid Build Coastguard Worker     }
434*61046927SAndroid Build Coastguard Worker 
imnmx(&mut self, tp: IntCmpType, x: Src, y: Src, min: Src) -> SSARef435*61046927SAndroid Build Coastguard Worker     fn imnmx(&mut self, tp: IntCmpType, x: Src, y: Src, min: Src) -> SSARef {
436*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
437*61046927SAndroid Build Coastguard Worker         self.push_op(OpIMnMx {
438*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
439*61046927SAndroid Build Coastguard Worker             cmp_type: tp,
440*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
441*61046927SAndroid Build Coastguard Worker             min: min,
442*61046927SAndroid Build Coastguard Worker         });
443*61046927SAndroid Build Coastguard Worker         dst
444*61046927SAndroid Build Coastguard Worker     }
445*61046927SAndroid Build Coastguard Worker 
imul(&mut self, x: Src, y: Src) -> SSARef446*61046927SAndroid Build Coastguard Worker     fn imul(&mut self, x: Src, y: Src) -> SSARef {
447*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
448*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
449*61046927SAndroid Build Coastguard Worker             self.push_op(OpIMad {
450*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
451*61046927SAndroid Build Coastguard Worker                 srcs: [x, y, 0.into()],
452*61046927SAndroid Build Coastguard Worker                 signed: false,
453*61046927SAndroid Build Coastguard Worker             });
454*61046927SAndroid Build Coastguard Worker         } else {
455*61046927SAndroid Build Coastguard Worker             self.push_op(OpIMul {
456*61046927SAndroid Build Coastguard Worker                 dst: dst[0].into(),
457*61046927SAndroid Build Coastguard Worker                 srcs: [x, y],
458*61046927SAndroid Build Coastguard Worker                 signed: [false; 2],
459*61046927SAndroid Build Coastguard Worker                 high: false,
460*61046927SAndroid Build Coastguard Worker             });
461*61046927SAndroid Build Coastguard Worker         }
462*61046927SAndroid Build Coastguard Worker         dst
463*61046927SAndroid Build Coastguard Worker     }
464*61046927SAndroid Build Coastguard Worker 
imul_2x32_64(&mut self, x: Src, y: Src, signed: bool) -> SSARef465*61046927SAndroid Build Coastguard Worker     fn imul_2x32_64(&mut self, x: Src, y: Src, signed: bool) -> SSARef {
466*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 2);
467*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
468*61046927SAndroid Build Coastguard Worker             self.push_op(OpIMad64 {
469*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
470*61046927SAndroid Build Coastguard Worker                 srcs: [x, y, 0.into()],
471*61046927SAndroid Build Coastguard Worker                 signed,
472*61046927SAndroid Build Coastguard Worker             });
473*61046927SAndroid Build Coastguard Worker         } else {
474*61046927SAndroid Build Coastguard Worker             self.push_op(OpIMul {
475*61046927SAndroid Build Coastguard Worker                 dst: dst[0].into(),
476*61046927SAndroid Build Coastguard Worker                 srcs: [x, y],
477*61046927SAndroid Build Coastguard Worker                 signed: [signed; 2],
478*61046927SAndroid Build Coastguard Worker                 high: false,
479*61046927SAndroid Build Coastguard Worker             });
480*61046927SAndroid Build Coastguard Worker             self.push_op(OpIMul {
481*61046927SAndroid Build Coastguard Worker                 dst: dst[1].into(),
482*61046927SAndroid Build Coastguard Worker                 srcs: [x, y],
483*61046927SAndroid Build Coastguard Worker                 signed: [signed; 2],
484*61046927SAndroid Build Coastguard Worker                 high: true,
485*61046927SAndroid Build Coastguard Worker             });
486*61046927SAndroid Build Coastguard Worker         }
487*61046927SAndroid Build Coastguard Worker         dst
488*61046927SAndroid Build Coastguard Worker     }
489*61046927SAndroid Build Coastguard Worker 
ineg(&mut self, i: Src) -> SSARef490*61046927SAndroid Build Coastguard Worker     fn ineg(&mut self, i: Src) -> SSARef {
491*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
492*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
493*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd3 {
494*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
495*61046927SAndroid Build Coastguard Worker                 overflow: [Dst::None; 2],
496*61046927SAndroid Build Coastguard Worker                 srcs: [0.into(), i.ineg(), 0.into()],
497*61046927SAndroid Build Coastguard Worker             });
498*61046927SAndroid Build Coastguard Worker         } else {
499*61046927SAndroid Build Coastguard Worker             self.push_op(OpIAdd2 {
500*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
501*61046927SAndroid Build Coastguard Worker                 srcs: [0.into(), i.ineg()],
502*61046927SAndroid Build Coastguard Worker                 carry_out: Dst::None,
503*61046927SAndroid Build Coastguard Worker             });
504*61046927SAndroid Build Coastguard Worker         }
505*61046927SAndroid Build Coastguard Worker         dst
506*61046927SAndroid Build Coastguard Worker     }
507*61046927SAndroid Build Coastguard Worker 
ineg64(&mut self, x: Src) -> SSARef508*61046927SAndroid Build Coastguard Worker     fn ineg64(&mut self, x: Src) -> SSARef {
509*61046927SAndroid Build Coastguard Worker         self.iadd64(0.into(), x.ineg(), 0.into())
510*61046927SAndroid Build Coastguard Worker     }
511*61046927SAndroid Build Coastguard Worker 
isetp( &mut self, cmp_type: IntCmpType, cmp_op: IntCmpOp, x: Src, y: Src, ) -> SSARef512*61046927SAndroid Build Coastguard Worker     fn isetp(
513*61046927SAndroid Build Coastguard Worker         &mut self,
514*61046927SAndroid Build Coastguard Worker         cmp_type: IntCmpType,
515*61046927SAndroid Build Coastguard Worker         cmp_op: IntCmpOp,
516*61046927SAndroid Build Coastguard Worker         x: Src,
517*61046927SAndroid Build Coastguard Worker         y: Src,
518*61046927SAndroid Build Coastguard Worker     ) -> SSARef {
519*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::Pred, 1);
520*61046927SAndroid Build Coastguard Worker         self.push_op(OpISetP {
521*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
522*61046927SAndroid Build Coastguard Worker             set_op: PredSetOp::And,
523*61046927SAndroid Build Coastguard Worker             cmp_op: cmp_op,
524*61046927SAndroid Build Coastguard Worker             cmp_type: cmp_type,
525*61046927SAndroid Build Coastguard Worker             ex: false,
526*61046927SAndroid Build Coastguard Worker             srcs: [x, y],
527*61046927SAndroid Build Coastguard Worker             accum: true.into(),
528*61046927SAndroid Build Coastguard Worker             low_cmp: true.into(),
529*61046927SAndroid Build Coastguard Worker         });
530*61046927SAndroid Build Coastguard Worker         dst
531*61046927SAndroid Build Coastguard Worker     }
532*61046927SAndroid Build Coastguard Worker 
isetp64( &mut self, cmp_type: IntCmpType, cmp_op: IntCmpOp, x: Src, y: Src, ) -> SSARef533*61046927SAndroid Build Coastguard Worker     fn isetp64(
534*61046927SAndroid Build Coastguard Worker         &mut self,
535*61046927SAndroid Build Coastguard Worker         cmp_type: IntCmpType,
536*61046927SAndroid Build Coastguard Worker         cmp_op: IntCmpOp,
537*61046927SAndroid Build Coastguard Worker         x: Src,
538*61046927SAndroid Build Coastguard Worker         y: Src,
539*61046927SAndroid Build Coastguard Worker     ) -> SSARef {
540*61046927SAndroid Build Coastguard Worker         let x = x.as_ssa().unwrap();
541*61046927SAndroid Build Coastguard Worker         let y = y.as_ssa().unwrap();
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker         // Low bits are always an unsigned comparison
544*61046927SAndroid Build Coastguard Worker         let low = self.isetp(IntCmpType::U32, cmp_op, x[0].into(), y[0].into());
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::Pred, 1);
547*61046927SAndroid Build Coastguard Worker         match cmp_op {
548*61046927SAndroid Build Coastguard Worker             IntCmpOp::Eq | IntCmpOp::Ne => {
549*61046927SAndroid Build Coastguard Worker                 self.push_op(OpISetP {
550*61046927SAndroid Build Coastguard Worker                     dst: dst.into(),
551*61046927SAndroid Build Coastguard Worker                     set_op: match cmp_op {
552*61046927SAndroid Build Coastguard Worker                         IntCmpOp::Eq => PredSetOp::And,
553*61046927SAndroid Build Coastguard Worker                         IntCmpOp::Ne => PredSetOp::Or,
554*61046927SAndroid Build Coastguard Worker                         _ => panic!("Not an integer equality"),
555*61046927SAndroid Build Coastguard Worker                     },
556*61046927SAndroid Build Coastguard Worker                     cmp_op: cmp_op,
557*61046927SAndroid Build Coastguard Worker                     cmp_type: IntCmpType::U32,
558*61046927SAndroid Build Coastguard Worker                     ex: false,
559*61046927SAndroid Build Coastguard Worker                     srcs: [x[1].into(), y[1].into()],
560*61046927SAndroid Build Coastguard Worker                     accum: low.into(),
561*61046927SAndroid Build Coastguard Worker                     low_cmp: true.into(),
562*61046927SAndroid Build Coastguard Worker                 });
563*61046927SAndroid Build Coastguard Worker             }
564*61046927SAndroid Build Coastguard Worker             IntCmpOp::Ge | IntCmpOp::Gt | IntCmpOp::Le | IntCmpOp::Lt => {
565*61046927SAndroid Build Coastguard Worker                 if self.sm() >= 70 {
566*61046927SAndroid Build Coastguard Worker                     self.push_op(OpISetP {
567*61046927SAndroid Build Coastguard Worker                         dst: dst.into(),
568*61046927SAndroid Build Coastguard Worker                         set_op: PredSetOp::And,
569*61046927SAndroid Build Coastguard Worker                         cmp_op,
570*61046927SAndroid Build Coastguard Worker                         cmp_type,
571*61046927SAndroid Build Coastguard Worker                         ex: true,
572*61046927SAndroid Build Coastguard Worker                         srcs: [x[1].into(), y[1].into()],
573*61046927SAndroid Build Coastguard Worker                         accum: true.into(),
574*61046927SAndroid Build Coastguard Worker                         low_cmp: low.into(),
575*61046927SAndroid Build Coastguard Worker                     });
576*61046927SAndroid Build Coastguard Worker                 } else {
577*61046927SAndroid Build Coastguard Worker                     // On Maxwell, iset.ex doesn't do what we want so we need to
578*61046927SAndroid Build Coastguard Worker                     // do it with 3 comparisons.  Fortunately, we can chain them
579*61046927SAndroid Build Coastguard Worker                     // together and don't need the extra logic that the NIR
580*61046927SAndroid Build Coastguard Worker                     // lowering would emit.
581*61046927SAndroid Build Coastguard Worker                     let low_and_high_eq = self.alloc_ssa(RegFile::Pred, 1);
582*61046927SAndroid Build Coastguard Worker                     self.push_op(OpISetP {
583*61046927SAndroid Build Coastguard Worker                         dst: low_and_high_eq.into(),
584*61046927SAndroid Build Coastguard Worker                         set_op: PredSetOp::And,
585*61046927SAndroid Build Coastguard Worker                         cmp_op: IntCmpOp::Eq,
586*61046927SAndroid Build Coastguard Worker                         cmp_type: IntCmpType::U32,
587*61046927SAndroid Build Coastguard Worker                         ex: false,
588*61046927SAndroid Build Coastguard Worker                         srcs: [x[1].into(), y[1].into()],
589*61046927SAndroid Build Coastguard Worker                         accum: low.into(),
590*61046927SAndroid Build Coastguard Worker                         low_cmp: true.into(),
591*61046927SAndroid Build Coastguard Worker                     });
592*61046927SAndroid Build Coastguard Worker                     self.push_op(OpISetP {
593*61046927SAndroid Build Coastguard Worker                         dst: dst.into(),
594*61046927SAndroid Build Coastguard Worker                         set_op: PredSetOp::Or,
595*61046927SAndroid Build Coastguard Worker                         // We always want a strict inequality for the high part
596*61046927SAndroid Build Coastguard Worker                         // so it's false when the two are equal and safe to OR
597*61046927SAndroid Build Coastguard Worker                         // with the low part.
598*61046927SAndroid Build Coastguard Worker                         cmp_op: match cmp_op {
599*61046927SAndroid Build Coastguard Worker                             IntCmpOp::Lt | IntCmpOp::Le => IntCmpOp::Lt,
600*61046927SAndroid Build Coastguard Worker                             IntCmpOp::Gt | IntCmpOp::Ge => IntCmpOp::Gt,
601*61046927SAndroid Build Coastguard Worker                             _ => panic!("Not an integer inequality"),
602*61046927SAndroid Build Coastguard Worker                         },
603*61046927SAndroid Build Coastguard Worker                         cmp_type,
604*61046927SAndroid Build Coastguard Worker                         ex: false,
605*61046927SAndroid Build Coastguard Worker                         srcs: [x[1].into(), y[1].into()],
606*61046927SAndroid Build Coastguard Worker                         accum: low_and_high_eq.into(),
607*61046927SAndroid Build Coastguard Worker                         low_cmp: true.into(),
608*61046927SAndroid Build Coastguard Worker                     });
609*61046927SAndroid Build Coastguard Worker                 }
610*61046927SAndroid Build Coastguard Worker             }
611*61046927SAndroid Build Coastguard Worker         }
612*61046927SAndroid Build Coastguard Worker         dst
613*61046927SAndroid Build Coastguard Worker     }
614*61046927SAndroid Build Coastguard Worker 
lop2(&mut self, op: LogicOp2, x: Src, y: Src) -> SSARef615*61046927SAndroid Build Coastguard Worker     fn lop2(&mut self, op: LogicOp2, x: Src, y: Src) -> SSARef {
616*61046927SAndroid Build Coastguard Worker         let dst = if x.is_predicate() {
617*61046927SAndroid Build Coastguard Worker             self.alloc_ssa(RegFile::Pred, 1)
618*61046927SAndroid Build Coastguard Worker         } else {
619*61046927SAndroid Build Coastguard Worker             self.alloc_ssa(RegFile::GPR, 1)
620*61046927SAndroid Build Coastguard Worker         };
621*61046927SAndroid Build Coastguard Worker         self.lop2_to(dst.into(), op, x, y);
622*61046927SAndroid Build Coastguard Worker         dst
623*61046927SAndroid Build Coastguard Worker     }
624*61046927SAndroid Build Coastguard Worker 
brev(&mut self, x: Src) -> SSARef625*61046927SAndroid Build Coastguard Worker     fn brev(&mut self, x: Src) -> SSARef {
626*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
627*61046927SAndroid Build Coastguard Worker         if self.sm() >= 70 {
628*61046927SAndroid Build Coastguard Worker             self.push_op(OpBRev {
629*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
630*61046927SAndroid Build Coastguard Worker                 src: x,
631*61046927SAndroid Build Coastguard Worker             });
632*61046927SAndroid Build Coastguard Worker         } else {
633*61046927SAndroid Build Coastguard Worker             // No BREV in Maxwell
634*61046927SAndroid Build Coastguard Worker             self.push_op(OpBfe {
635*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
636*61046927SAndroid Build Coastguard Worker                 base: x,
637*61046927SAndroid Build Coastguard Worker                 signed: false,
638*61046927SAndroid Build Coastguard Worker                 range: Src::new_imm_u32(0x2000),
639*61046927SAndroid Build Coastguard Worker                 reverse: true,
640*61046927SAndroid Build Coastguard Worker             });
641*61046927SAndroid Build Coastguard Worker         }
642*61046927SAndroid Build Coastguard Worker         dst
643*61046927SAndroid Build Coastguard Worker     }
644*61046927SAndroid Build Coastguard Worker 
mufu(&mut self, op: MuFuOp, src: Src) -> SSARef645*61046927SAndroid Build Coastguard Worker     fn mufu(&mut self, op: MuFuOp, src: Src) -> SSARef {
646*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
647*61046927SAndroid Build Coastguard Worker         self.push_op(OpMuFu {
648*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
649*61046927SAndroid Build Coastguard Worker             op: op,
650*61046927SAndroid Build Coastguard Worker             src: src,
651*61046927SAndroid Build Coastguard Worker         });
652*61046927SAndroid Build Coastguard Worker         dst
653*61046927SAndroid Build Coastguard Worker     }
654*61046927SAndroid Build Coastguard Worker 
fsin(&mut self, src: Src) -> SSARef655*61046927SAndroid Build Coastguard Worker     fn fsin(&mut self, src: Src) -> SSARef {
656*61046927SAndroid Build Coastguard Worker         let tmp = if self.sm() >= 70 {
657*61046927SAndroid Build Coastguard Worker             let frac_1_2pi = 1.0 / (2.0 * std::f32::consts::PI);
658*61046927SAndroid Build Coastguard Worker             self.fmul(src, frac_1_2pi.into())
659*61046927SAndroid Build Coastguard Worker         } else {
660*61046927SAndroid Build Coastguard Worker             let tmp = self.alloc_ssa(RegFile::GPR, 1);
661*61046927SAndroid Build Coastguard Worker             self.push_op(OpRro {
662*61046927SAndroid Build Coastguard Worker                 dst: tmp.into(),
663*61046927SAndroid Build Coastguard Worker                 op: RroOp::SinCos,
664*61046927SAndroid Build Coastguard Worker                 src,
665*61046927SAndroid Build Coastguard Worker             });
666*61046927SAndroid Build Coastguard Worker             tmp
667*61046927SAndroid Build Coastguard Worker         };
668*61046927SAndroid Build Coastguard Worker         self.mufu(MuFuOp::Sin, tmp.into())
669*61046927SAndroid Build Coastguard Worker     }
670*61046927SAndroid Build Coastguard Worker 
fcos(&mut self, src: Src) -> SSARef671*61046927SAndroid Build Coastguard Worker     fn fcos(&mut self, src: Src) -> SSARef {
672*61046927SAndroid Build Coastguard Worker         let tmp = if self.sm() >= 70 {
673*61046927SAndroid Build Coastguard Worker             let frac_1_2pi = 1.0 / (2.0 * std::f32::consts::PI);
674*61046927SAndroid Build Coastguard Worker             self.fmul(src, frac_1_2pi.into())
675*61046927SAndroid Build Coastguard Worker         } else {
676*61046927SAndroid Build Coastguard Worker             let tmp = self.alloc_ssa(RegFile::GPR, 1);
677*61046927SAndroid Build Coastguard Worker             self.push_op(OpRro {
678*61046927SAndroid Build Coastguard Worker                 dst: tmp.into(),
679*61046927SAndroid Build Coastguard Worker                 op: RroOp::SinCos,
680*61046927SAndroid Build Coastguard Worker                 src,
681*61046927SAndroid Build Coastguard Worker             });
682*61046927SAndroid Build Coastguard Worker             tmp
683*61046927SAndroid Build Coastguard Worker         };
684*61046927SAndroid Build Coastguard Worker         self.mufu(MuFuOp::Cos, tmp.into())
685*61046927SAndroid Build Coastguard Worker     }
686*61046927SAndroid Build Coastguard Worker 
fexp2(&mut self, src: Src) -> SSARef687*61046927SAndroid Build Coastguard Worker     fn fexp2(&mut self, src: Src) -> SSARef {
688*61046927SAndroid Build Coastguard Worker         let tmp = if self.sm() >= 70 {
689*61046927SAndroid Build Coastguard Worker             src
690*61046927SAndroid Build Coastguard Worker         } else {
691*61046927SAndroid Build Coastguard Worker             let tmp = self.alloc_ssa(RegFile::GPR, 1);
692*61046927SAndroid Build Coastguard Worker             self.push_op(OpRro {
693*61046927SAndroid Build Coastguard Worker                 dst: tmp.into(),
694*61046927SAndroid Build Coastguard Worker                 op: RroOp::Exp2,
695*61046927SAndroid Build Coastguard Worker                 src,
696*61046927SAndroid Build Coastguard Worker             });
697*61046927SAndroid Build Coastguard Worker             tmp.into()
698*61046927SAndroid Build Coastguard Worker         };
699*61046927SAndroid Build Coastguard Worker         self.mufu(MuFuOp::Exp2, tmp)
700*61046927SAndroid Build Coastguard Worker     }
701*61046927SAndroid Build Coastguard Worker 
prmt(&mut self, x: Src, y: Src, sel: [u8; 4]) -> SSARef702*61046927SAndroid Build Coastguard Worker     fn prmt(&mut self, x: Src, y: Src, sel: [u8; 4]) -> SSARef {
703*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
704*61046927SAndroid Build Coastguard Worker         self.prmt_to(dst.into(), x, y, sel);
705*61046927SAndroid Build Coastguard Worker         dst
706*61046927SAndroid Build Coastguard Worker     }
707*61046927SAndroid Build Coastguard Worker 
prmt4(&mut self, src: [Src; 4], sel: [u8; 4]) -> SSARef708*61046927SAndroid Build Coastguard Worker     fn prmt4(&mut self, src: [Src; 4], sel: [u8; 4]) -> SSARef {
709*61046927SAndroid Build Coastguard Worker         let max_sel = *sel.iter().max().unwrap();
710*61046927SAndroid Build Coastguard Worker         if max_sel < 8 {
711*61046927SAndroid Build Coastguard Worker             self.prmt(src[0], src[1], sel)
712*61046927SAndroid Build Coastguard Worker         } else if max_sel < 12 {
713*61046927SAndroid Build Coastguard Worker             let mut sel_a = [0_u8; 4];
714*61046927SAndroid Build Coastguard Worker             let mut sel_b = [0_u8; 4];
715*61046927SAndroid Build Coastguard Worker             for i in 0..4_u8 {
716*61046927SAndroid Build Coastguard Worker                 if sel[usize::from(i)] < 8 {
717*61046927SAndroid Build Coastguard Worker                     sel_a[usize::from(i)] = sel[usize::from(i)];
718*61046927SAndroid Build Coastguard Worker                     sel_b[usize::from(i)] = i;
719*61046927SAndroid Build Coastguard Worker                 } else {
720*61046927SAndroid Build Coastguard Worker                     sel_b[usize::from(i)] = (sel[usize::from(i)] - 8) + 4;
721*61046927SAndroid Build Coastguard Worker                 }
722*61046927SAndroid Build Coastguard Worker             }
723*61046927SAndroid Build Coastguard Worker             let a = self.prmt(src[0], src[1], sel_a);
724*61046927SAndroid Build Coastguard Worker             self.prmt(a.into(), src[2], sel_b)
725*61046927SAndroid Build Coastguard Worker         } else if max_sel < 16 {
726*61046927SAndroid Build Coastguard Worker             let mut sel_a = [0_u8; 4];
727*61046927SAndroid Build Coastguard Worker             let mut sel_b = [0_u8; 4];
728*61046927SAndroid Build Coastguard Worker             let mut sel_c = [0_u8; 4];
729*61046927SAndroid Build Coastguard Worker             for i in 0..4_u8 {
730*61046927SAndroid Build Coastguard Worker                 if sel[usize::from(i)] < 8 {
731*61046927SAndroid Build Coastguard Worker                     sel_a[usize::from(i)] = sel[usize::from(i)];
732*61046927SAndroid Build Coastguard Worker                     sel_c[usize::from(i)] = i;
733*61046927SAndroid Build Coastguard Worker                 } else {
734*61046927SAndroid Build Coastguard Worker                     sel_b[usize::from(i)] = sel[usize::from(i)] - 8;
735*61046927SAndroid Build Coastguard Worker                     sel_c[usize::from(i)] = 4 + i;
736*61046927SAndroid Build Coastguard Worker                 }
737*61046927SAndroid Build Coastguard Worker             }
738*61046927SAndroid Build Coastguard Worker             let a = self.prmt(src[0], src[1], sel_a);
739*61046927SAndroid Build Coastguard Worker             let b = self.prmt(src[2], src[3], sel_b);
740*61046927SAndroid Build Coastguard Worker             self.prmt(a.into(), b.into(), sel_c)
741*61046927SAndroid Build Coastguard Worker         } else {
742*61046927SAndroid Build Coastguard Worker             panic!("Invalid permute value: {max_sel}");
743*61046927SAndroid Build Coastguard Worker         }
744*61046927SAndroid Build Coastguard Worker     }
745*61046927SAndroid Build Coastguard Worker 
sel(&mut self, cond: Src, x: Src, y: Src) -> SSARef746*61046927SAndroid Build Coastguard Worker     fn sel(&mut self, cond: Src, x: Src, y: Src) -> SSARef {
747*61046927SAndroid Build Coastguard Worker         assert!(cond.src_ref.is_predicate());
748*61046927SAndroid Build Coastguard Worker         assert!(x.is_predicate() == y.is_predicate());
749*61046927SAndroid Build Coastguard Worker         if x.is_predicate() {
750*61046927SAndroid Build Coastguard Worker             let dst = self.alloc_ssa(RegFile::Pred, 1);
751*61046927SAndroid Build Coastguard Worker             if self.sm() >= 70 {
752*61046927SAndroid Build Coastguard Worker                 self.push_op(OpPLop3 {
753*61046927SAndroid Build Coastguard Worker                     dsts: [dst.into(), Dst::None],
754*61046927SAndroid Build Coastguard Worker                     srcs: [cond, x, y],
755*61046927SAndroid Build Coastguard Worker                     ops: [
756*61046927SAndroid Build Coastguard Worker                         LogicOp3::new_lut(&|c, x, y| (c & x) | (!c & y)),
757*61046927SAndroid Build Coastguard Worker                         LogicOp3::new_const(false),
758*61046927SAndroid Build Coastguard Worker                     ],
759*61046927SAndroid Build Coastguard Worker                 });
760*61046927SAndroid Build Coastguard Worker             } else {
761*61046927SAndroid Build Coastguard Worker                 let tmp = self.alloc_ssa(RegFile::Pred, 1);
762*61046927SAndroid Build Coastguard Worker                 self.push_op(OpPSetP {
763*61046927SAndroid Build Coastguard Worker                     dsts: [tmp.into(), Dst::None],
764*61046927SAndroid Build Coastguard Worker                     ops: [PredSetOp::And, PredSetOp::And],
765*61046927SAndroid Build Coastguard Worker                     srcs: [cond, x, true.into()],
766*61046927SAndroid Build Coastguard Worker                 });
767*61046927SAndroid Build Coastguard Worker                 self.push_op(OpPSetP {
768*61046927SAndroid Build Coastguard Worker                     dsts: [dst.into(), Dst::None],
769*61046927SAndroid Build Coastguard Worker                     ops: [PredSetOp::And, PredSetOp::Or],
770*61046927SAndroid Build Coastguard Worker                     srcs: [cond.bnot(), y, tmp.into()],
771*61046927SAndroid Build Coastguard Worker                 });
772*61046927SAndroid Build Coastguard Worker             }
773*61046927SAndroid Build Coastguard Worker             dst
774*61046927SAndroid Build Coastguard Worker         } else {
775*61046927SAndroid Build Coastguard Worker             let dst = self.alloc_ssa(RegFile::GPR, 1);
776*61046927SAndroid Build Coastguard Worker             self.push_op(OpSel {
777*61046927SAndroid Build Coastguard Worker                 dst: dst.into(),
778*61046927SAndroid Build Coastguard Worker                 cond: cond,
779*61046927SAndroid Build Coastguard Worker                 srcs: [x, y],
780*61046927SAndroid Build Coastguard Worker             });
781*61046927SAndroid Build Coastguard Worker             dst
782*61046927SAndroid Build Coastguard Worker         }
783*61046927SAndroid Build Coastguard Worker     }
784*61046927SAndroid Build Coastguard Worker 
undef(&mut self) -> SSARef785*61046927SAndroid Build Coastguard Worker     fn undef(&mut self) -> SSARef {
786*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
787*61046927SAndroid Build Coastguard Worker         self.push_op(OpUndef { dst: dst.into() });
788*61046927SAndroid Build Coastguard Worker         dst
789*61046927SAndroid Build Coastguard Worker     }
790*61046927SAndroid Build Coastguard Worker 
copy(&mut self, src: Src) -> SSARef791*61046927SAndroid Build Coastguard Worker     fn copy(&mut self, src: Src) -> SSARef {
792*61046927SAndroid Build Coastguard Worker         let dst = if src.is_predicate() {
793*61046927SAndroid Build Coastguard Worker             self.alloc_ssa(RegFile::Pred, 1)
794*61046927SAndroid Build Coastguard Worker         } else {
795*61046927SAndroid Build Coastguard Worker             self.alloc_ssa(RegFile::GPR, 1)
796*61046927SAndroid Build Coastguard Worker         };
797*61046927SAndroid Build Coastguard Worker         self.copy_to(dst.into(), src);
798*61046927SAndroid Build Coastguard Worker         dst
799*61046927SAndroid Build Coastguard Worker     }
800*61046927SAndroid Build Coastguard Worker 
bmov_to_bar(&mut self, src: Src) -> SSARef801*61046927SAndroid Build Coastguard Worker     fn bmov_to_bar(&mut self, src: Src) -> SSARef {
802*61046927SAndroid Build Coastguard Worker         assert!(src.src_ref.as_ssa().unwrap().file() == Some(RegFile::GPR));
803*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::Bar, 1);
804*61046927SAndroid Build Coastguard Worker         self.push_op(OpBMov {
805*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
806*61046927SAndroid Build Coastguard Worker             src: src,
807*61046927SAndroid Build Coastguard Worker             clear: false,
808*61046927SAndroid Build Coastguard Worker         });
809*61046927SAndroid Build Coastguard Worker         dst
810*61046927SAndroid Build Coastguard Worker     }
811*61046927SAndroid Build Coastguard Worker 
bmov_to_gpr(&mut self, src: Src) -> SSARef812*61046927SAndroid Build Coastguard Worker     fn bmov_to_gpr(&mut self, src: Src) -> SSARef {
813*61046927SAndroid Build Coastguard Worker         assert!(src.src_ref.as_ssa().unwrap().file() == Some(RegFile::Bar));
814*61046927SAndroid Build Coastguard Worker         let dst = self.alloc_ssa(RegFile::GPR, 1);
815*61046927SAndroid Build Coastguard Worker         self.push_op(OpBMov {
816*61046927SAndroid Build Coastguard Worker             dst: dst.into(),
817*61046927SAndroid Build Coastguard Worker             src: src,
818*61046927SAndroid Build Coastguard Worker             clear: false,
819*61046927SAndroid Build Coastguard Worker         });
820*61046927SAndroid Build Coastguard Worker         dst
821*61046927SAndroid Build Coastguard Worker     }
822*61046927SAndroid Build Coastguard Worker }
823*61046927SAndroid Build Coastguard Worker 
824*61046927SAndroid Build Coastguard Worker pub struct InstrBuilder<'a> {
825*61046927SAndroid Build Coastguard Worker     instrs: MappedInstrs,
826*61046927SAndroid Build Coastguard Worker     sm: &'a dyn ShaderModel,
827*61046927SAndroid Build Coastguard Worker }
828*61046927SAndroid Build Coastguard Worker 
829*61046927SAndroid Build Coastguard Worker impl<'a> InstrBuilder<'a> {
new(sm: &'a dyn ShaderModel) -> Self830*61046927SAndroid Build Coastguard Worker     pub fn new(sm: &'a dyn ShaderModel) -> Self {
831*61046927SAndroid Build Coastguard Worker         Self {
832*61046927SAndroid Build Coastguard Worker             instrs: MappedInstrs::None,
833*61046927SAndroid Build Coastguard Worker             sm,
834*61046927SAndroid Build Coastguard Worker         }
835*61046927SAndroid Build Coastguard Worker     }
836*61046927SAndroid Build Coastguard Worker }
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker impl InstrBuilder<'_> {
as_vec(self) -> Vec<Box<Instr>>839*61046927SAndroid Build Coastguard Worker     pub fn as_vec(self) -> Vec<Box<Instr>> {
840*61046927SAndroid Build Coastguard Worker         match self.instrs {
841*61046927SAndroid Build Coastguard Worker             MappedInstrs::None => Vec::new(),
842*61046927SAndroid Build Coastguard Worker             MappedInstrs::One(i) => vec![i],
843*61046927SAndroid Build Coastguard Worker             MappedInstrs::Many(v) => v,
844*61046927SAndroid Build Coastguard Worker         }
845*61046927SAndroid Build Coastguard Worker     }
846*61046927SAndroid Build Coastguard Worker 
as_mapped_instrs(self) -> MappedInstrs847*61046927SAndroid Build Coastguard Worker     pub fn as_mapped_instrs(self) -> MappedInstrs {
848*61046927SAndroid Build Coastguard Worker         self.instrs
849*61046927SAndroid Build Coastguard Worker     }
850*61046927SAndroid Build Coastguard Worker }
851*61046927SAndroid Build Coastguard Worker 
852*61046927SAndroid Build Coastguard Worker impl Builder for InstrBuilder<'_> {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr853*61046927SAndroid Build Coastguard Worker     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
854*61046927SAndroid Build Coastguard Worker         self.instrs.push(instr);
855*61046927SAndroid Build Coastguard Worker         self.instrs.last_mut().unwrap().as_mut()
856*61046927SAndroid Build Coastguard Worker     }
857*61046927SAndroid Build Coastguard Worker 
sm(&self) -> u8858*61046927SAndroid Build Coastguard Worker     fn sm(&self) -> u8 {
859*61046927SAndroid Build Coastguard Worker         self.sm.sm()
860*61046927SAndroid Build Coastguard Worker     }
861*61046927SAndroid Build Coastguard Worker }
862*61046927SAndroid Build Coastguard Worker 
863*61046927SAndroid Build Coastguard Worker pub struct SSAInstrBuilder<'a> {
864*61046927SAndroid Build Coastguard Worker     b: InstrBuilder<'a>,
865*61046927SAndroid Build Coastguard Worker     alloc: &'a mut SSAValueAllocator,
866*61046927SAndroid Build Coastguard Worker }
867*61046927SAndroid Build Coastguard Worker 
868*61046927SAndroid Build Coastguard Worker impl<'a> SSAInstrBuilder<'a> {
new( sm: &'a dyn ShaderModel, alloc: &'a mut SSAValueAllocator, ) -> Self869*61046927SAndroid Build Coastguard Worker     pub fn new(
870*61046927SAndroid Build Coastguard Worker         sm: &'a dyn ShaderModel,
871*61046927SAndroid Build Coastguard Worker         alloc: &'a mut SSAValueAllocator,
872*61046927SAndroid Build Coastguard Worker     ) -> Self {
873*61046927SAndroid Build Coastguard Worker         Self {
874*61046927SAndroid Build Coastguard Worker             b: InstrBuilder::new(sm),
875*61046927SAndroid Build Coastguard Worker             alloc: alloc,
876*61046927SAndroid Build Coastguard Worker         }
877*61046927SAndroid Build Coastguard Worker     }
878*61046927SAndroid Build Coastguard Worker }
879*61046927SAndroid Build Coastguard Worker 
880*61046927SAndroid Build Coastguard Worker impl SSAInstrBuilder<'_> {
as_vec(self) -> Vec<Box<Instr>>881*61046927SAndroid Build Coastguard Worker     pub fn as_vec(self) -> Vec<Box<Instr>> {
882*61046927SAndroid Build Coastguard Worker         self.b.as_vec()
883*61046927SAndroid Build Coastguard Worker     }
884*61046927SAndroid Build Coastguard Worker 
885*61046927SAndroid Build Coastguard Worker     #[allow(dead_code)]
as_mapped_instrs(self) -> MappedInstrs886*61046927SAndroid Build Coastguard Worker     pub fn as_mapped_instrs(self) -> MappedInstrs {
887*61046927SAndroid Build Coastguard Worker         self.b.as_mapped_instrs()
888*61046927SAndroid Build Coastguard Worker     }
889*61046927SAndroid Build Coastguard Worker }
890*61046927SAndroid Build Coastguard Worker 
891*61046927SAndroid Build Coastguard Worker impl<'a> Builder for SSAInstrBuilder<'a> {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr892*61046927SAndroid Build Coastguard Worker     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
893*61046927SAndroid Build Coastguard Worker         self.b.push_instr(instr)
894*61046927SAndroid Build Coastguard Worker     }
895*61046927SAndroid Build Coastguard Worker 
sm(&self) -> u8896*61046927SAndroid Build Coastguard Worker     fn sm(&self) -> u8 {
897*61046927SAndroid Build Coastguard Worker         self.b.sm()
898*61046927SAndroid Build Coastguard Worker     }
899*61046927SAndroid Build Coastguard Worker }
900*61046927SAndroid Build Coastguard Worker 
901*61046927SAndroid Build Coastguard Worker impl<'a> SSABuilder for SSAInstrBuilder<'a> {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef902*61046927SAndroid Build Coastguard Worker     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
903*61046927SAndroid Build Coastguard Worker         self.alloc.alloc_vec(file, comps)
904*61046927SAndroid Build Coastguard Worker     }
905*61046927SAndroid Build Coastguard Worker }
906*61046927SAndroid Build Coastguard Worker 
907*61046927SAndroid Build Coastguard Worker pub struct PredicatedBuilder<'a, T: Builder> {
908*61046927SAndroid Build Coastguard Worker     b: &'a mut T,
909*61046927SAndroid Build Coastguard Worker     pred: Pred,
910*61046927SAndroid Build Coastguard Worker }
911*61046927SAndroid Build Coastguard Worker 
912*61046927SAndroid Build Coastguard Worker impl<'a, T: Builder> Builder for PredicatedBuilder<'a, T> {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr913*61046927SAndroid Build Coastguard Worker     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
914*61046927SAndroid Build Coastguard Worker         let mut instr = instr;
915*61046927SAndroid Build Coastguard Worker         assert!(instr.pred.is_true());
916*61046927SAndroid Build Coastguard Worker         instr.pred = self.pred;
917*61046927SAndroid Build Coastguard Worker         self.b.push_instr(instr)
918*61046927SAndroid Build Coastguard Worker     }
919*61046927SAndroid Build Coastguard Worker 
sm(&self) -> u8920*61046927SAndroid Build Coastguard Worker     fn sm(&self) -> u8 {
921*61046927SAndroid Build Coastguard Worker         self.b.sm()
922*61046927SAndroid Build Coastguard Worker     }
923*61046927SAndroid Build Coastguard Worker }
924*61046927SAndroid Build Coastguard Worker 
925*61046927SAndroid Build Coastguard Worker impl<'a, T: SSABuilder> SSABuilder for PredicatedBuilder<'a, T> {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef926*61046927SAndroid Build Coastguard Worker     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
927*61046927SAndroid Build Coastguard Worker         self.b.alloc_ssa(file, comps)
928*61046927SAndroid Build Coastguard Worker     }
929*61046927SAndroid Build Coastguard Worker }
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker pub struct UniformBuilder<'a, T: Builder> {
932*61046927SAndroid Build Coastguard Worker     b: &'a mut T,
933*61046927SAndroid Build Coastguard Worker     uniform: bool,
934*61046927SAndroid Build Coastguard Worker }
935*61046927SAndroid Build Coastguard Worker 
936*61046927SAndroid Build Coastguard Worker impl<'a, T: Builder> UniformBuilder<'a, T> {
new(b: &'a mut T, uniform: bool) -> Self937*61046927SAndroid Build Coastguard Worker     pub fn new(b: &'a mut T, uniform: bool) -> Self {
938*61046927SAndroid Build Coastguard Worker         Self { b, uniform }
939*61046927SAndroid Build Coastguard Worker     }
940*61046927SAndroid Build Coastguard Worker }
941*61046927SAndroid Build Coastguard Worker 
942*61046927SAndroid Build Coastguard Worker impl<'a, T: Builder> Builder for UniformBuilder<'a, T> {
push_instr(&mut self, instr: Box<Instr>) -> &mut Instr943*61046927SAndroid Build Coastguard Worker     fn push_instr(&mut self, instr: Box<Instr>) -> &mut Instr {
944*61046927SAndroid Build Coastguard Worker         self.b.push_instr(instr)
945*61046927SAndroid Build Coastguard Worker     }
946*61046927SAndroid Build Coastguard Worker 
sm(&self) -> u8947*61046927SAndroid Build Coastguard Worker     fn sm(&self) -> u8 {
948*61046927SAndroid Build Coastguard Worker         self.b.sm()
949*61046927SAndroid Build Coastguard Worker     }
950*61046927SAndroid Build Coastguard Worker }
951*61046927SAndroid Build Coastguard Worker 
952*61046927SAndroid Build Coastguard Worker impl<'a, T: SSABuilder> SSABuilder for UniformBuilder<'a, T> {
alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef953*61046927SAndroid Build Coastguard Worker     fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
954*61046927SAndroid Build Coastguard Worker         let file = if self.uniform {
955*61046927SAndroid Build Coastguard Worker             file.to_uniform().unwrap()
956*61046927SAndroid Build Coastguard Worker         } else {
957*61046927SAndroid Build Coastguard Worker             file
958*61046927SAndroid Build Coastguard Worker         };
959*61046927SAndroid Build Coastguard Worker         self.b.alloc_ssa(file, comps)
960*61046927SAndroid Build Coastguard Worker     }
961*61046927SAndroid Build Coastguard Worker }
962