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