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