@@ -438,186 +438,75 @@ static void processInstrsWithTypeFolding(MachineFunction &MF,
438
438
}
439
439
}
440
440
441
+ // Find basic blocks of the switch and replace registers in spv_switch() by its
442
+ // MBB equivalent.
441
443
static void processSwitches (MachineFunction &MF, SPIRVGlobalRegistry *GR,
442
444
MachineIRBuilder MIB) {
443
- // Before IRTranslator pass, calls to spv_switch intrinsic are inserted before
444
- // each switch instruction. IRTranslator lowers switches to G_ICMP + G_BRCOND
445
- // + G_BR triples. A switch with two cases may be transformed to this MIR
446
- // sequence:
447
- //
448
- // intrinsic(@llvm.spv.switch), %CmpReg, %Const0, %Const1
449
- // %Dst0 = G_ICMP intpred(eq), %CmpReg, %Const0
450
- // G_BRCOND %Dst0, %bb.2
451
- // G_BR %bb.5
452
- // bb.5.entry:
453
- // %Dst1 = G_ICMP intpred(eq), %CmpReg, %Const1
454
- // G_BRCOND %Dst1, %bb.3
455
- // G_BR %bb.4
456
- // bb.2.sw.bb:
457
- // ...
458
- // bb.3.sw.bb1:
459
- // ...
460
- // bb.4.sw.epilog:
461
- // ...
462
- //
463
- // Sometimes (in case of range-compare switches), additional G_SUBs
464
- // instructions are inserted before G_ICMPs. Those need to be additionally
465
- // processed.
466
- //
467
- // This function modifies spv_switch call's operands to include destination
468
- // MBBs (default and for each constant value).
469
- //
470
- // At the end, the function removes redundant [G_SUB] + G_ICMP + G_BRCOND +
471
- // G_BR sequences.
472
-
473
- MachineRegisterInfo &MRI = MF.getRegInfo ();
474
-
475
- // Collect spv_switches and G_ICMPs across all MBBs in MF.
476
- std::vector<MachineInstr *> RelevantInsts;
477
-
478
- // Collect redundant MIs from [G_SUB] + G_ICMP + G_BRCOND + G_BR sequences.
479
- // After updating spv_switches, the instructions can be removed.
480
- std::vector<MachineInstr *> PostUpdateArtifacts;
481
-
482
- // Temporary set of compare registers. G_SUBs and G_ICMPs relating to
483
- // spv_switch use these registers.
484
- DenseSet<Register> CompareRegs;
445
+ DenseMap<const BasicBlock *, MachineBasicBlock *> BB2MBB;
446
+ SmallVector<std::pair<MachineInstr *, SmallVector<MachineInstr *, 8 >>>
447
+ Switches;
485
448
for (MachineBasicBlock &MBB : MF) {
449
+ MachineRegisterInfo &MRI = MF.getRegInfo ();
450
+ BB2MBB[MBB.getBasicBlock ()] = &MBB;
486
451
for (MachineInstr &MI : MBB) {
452
+ if (!isSpvIntrinsic (MI, Intrinsic::spv_switch))
453
+ continue ;
487
454
// Calls to spv_switch intrinsics representing IR switches.
488
- if (isSpvIntrinsic (MI, Intrinsic::spv_switch)) {
489
- assert (MI.getOperand (1 ).isReg ());
490
- CompareRegs.insert (MI.getOperand (1 ).getReg ());
491
- RelevantInsts.push_back (&MI);
492
- }
493
-
494
- // G_SUBs coming from range-compare switch lowering. G_SUBs are found
495
- // after spv_switch but before G_ICMP.
496
- if (MI.getOpcode () == TargetOpcode::G_SUB && MI.getOperand (1 ).isReg () &&
497
- CompareRegs.contains (MI.getOperand (1 ).getReg ())) {
498
- assert (MI.getOperand (0 ).isReg () && MI.getOperand (1 ).isReg ());
499
- Register Dst = MI.getOperand (0 ).getReg ();
500
- CompareRegs.insert (Dst);
501
- PostUpdateArtifacts.push_back (&MI);
502
- }
503
-
504
- // G_ICMPs relating to switches.
505
- if (MI.getOpcode () == TargetOpcode::G_ICMP && MI.getOperand (2 ).isReg () &&
506
- CompareRegs.contains (MI.getOperand (2 ).getReg ())) {
507
- Register Dst = MI.getOperand (0 ).getReg ();
508
- RelevantInsts.push_back (&MI);
509
- PostUpdateArtifacts.push_back (&MI);
510
- MachineInstr *CBr = MRI.use_begin (Dst)->getParent ();
511
- assert (CBr->getOpcode () == SPIRV::G_BRCOND);
512
- PostUpdateArtifacts.push_back (CBr);
513
- MachineInstr *Br = CBr->getNextNode ();
514
- assert (Br->getOpcode () == SPIRV::G_BR);
515
- PostUpdateArtifacts.push_back (Br);
455
+ SmallVector<MachineInstr *, 8 > NewOps;
456
+ for (unsigned i = 2 ; i < MI.getNumOperands (); ++i) {
457
+ Register Reg = MI.getOperand (i).getReg ();
458
+ if (i % 2 == 1 ) {
459
+ MachineInstr *ConstInstr = getDefInstrMaybeConstant (Reg, &MRI);
460
+ NewOps.push_back (ConstInstr);
461
+ } else {
462
+ MachineInstr *BuildMBB = MRI.getVRegDef (Reg);
463
+ assert (BuildMBB &&
464
+ BuildMBB->getOpcode () == TargetOpcode::G_BLOCK_ADDR &&
465
+ BuildMBB->getOperand (1 ).isBlockAddress () &&
466
+ BuildMBB->getOperand (1 ).getBlockAddress ());
467
+ NewOps.push_back (BuildMBB);
468
+ }
516
469
}
470
+ Switches.push_back (std::make_pair (&MI, NewOps));
517
471
}
518
472
}
519
473
520
- // Update each spv_switch with destination MBBs.
521
- for (auto i = RelevantInsts.begin (); i != RelevantInsts.end (); i++) {
522
- if (!isSpvIntrinsic (**i, Intrinsic::spv_switch))
523
- continue ;
524
-
525
- // Currently considered spv_switch.
526
- MachineInstr *Switch = *i;
527
- // Set the first successor as default MBB to support empty switches.
528
- MachineBasicBlock *DefaultMBB = *Switch->getParent ()->succ_begin ();
529
- // Container for mapping values to MMBs.
530
- SmallDenseMap<uint64_t , MachineBasicBlock *> ValuesToMBBs;
531
-
532
- // Walk all G_ICMPs to collect ValuesToMBBs. Start at currently considered
533
- // spv_switch (i) and break at any spv_switch with the same compare
534
- // register (indicating we are back at the same scope).
535
- Register CompareReg = Switch->getOperand (1 ).getReg ();
536
- for (auto j = i + 1 ; j != RelevantInsts.end (); j++) {
537
- if (isSpvIntrinsic (**j, Intrinsic::spv_switch) &&
538
- (*j)->getOperand (1 ).getReg () == CompareReg)
539
- break ;
540
-
541
- if (!((*j)->getOpcode () == TargetOpcode::G_ICMP &&
542
- (*j)->getOperand (2 ).getReg () == CompareReg))
543
- continue ;
544
-
545
- MachineInstr *ICMP = *j;
546
- Register Dst = ICMP->getOperand (0 ).getReg ();
547
- MachineOperand &PredOp = ICMP->getOperand (1 );
548
- const auto CC = static_cast <CmpInst::Predicate>(PredOp.getPredicate ());
549
- (void )CC;
550
- assert ((CC == CmpInst::ICMP_EQ || CC == CmpInst::ICMP_ULE) &&
551
- MRI.hasOneUse (Dst) && MRI.hasOneDef (CompareReg));
552
- uint64_t Value = getIConstVal (ICMP->getOperand (3 ).getReg (), &MRI);
553
- MachineInstr *CBr = MRI.use_begin (Dst)->getParent ();
554
- assert (CBr->getOpcode () == SPIRV::G_BRCOND && CBr->getOperand (1 ).isMBB ());
555
- MachineBasicBlock *MBB = CBr->getOperand (1 ).getMBB ();
556
-
557
- // Map switch case Value to target MBB.
558
- ValuesToMBBs[Value] = MBB;
559
-
560
- // Add target MBB as successor to the switch's MBB.
561
- Switch->getParent ()->addSuccessor (MBB);
562
-
563
- // The next MI is always G_BR to either the next case or the default.
564
- MachineInstr *NextMI = CBr->getNextNode ();
565
- assert (NextMI->getOpcode () == SPIRV::G_BR &&
566
- NextMI->getOperand (0 ).isMBB ());
567
- MachineBasicBlock *NextMBB = NextMI->getOperand (0 ).getMBB ();
568
- // Default MBB does not begin with G_ICMP using spv_switch compare
569
- // register.
570
- if (NextMBB->front ().getOpcode () != SPIRV::G_ICMP ||
571
- (NextMBB->front ().getOperand (2 ).isReg () &&
572
- NextMBB->front ().getOperand (2 ).getReg () != CompareReg)) {
573
- // Set default MBB and add it as successor to the switch's MBB.
574
- DefaultMBB = NextMBB;
575
- Switch->getParent ()->addSuccessor (DefaultMBB);
474
+ SmallPtrSet<MachineInstr *, 8 > ToEraseMI;
475
+ for (auto &SwIt : Switches) {
476
+ MachineInstr &MI = *SwIt.first ;
477
+ SmallVector<MachineInstr *, 8 > &Ins = SwIt.second ;
478
+ SmallVector<MachineOperand, 8 > NewOps;
479
+ for (unsigned i = 0 ; i < Ins.size (); ++i) {
480
+ if (Ins[i]->getOpcode () == TargetOpcode::G_BLOCK_ADDR) {
481
+ BasicBlock *CaseBB =
482
+ Ins[i]->getOperand (1 ).getBlockAddress ()->getBasicBlock ();
483
+ auto It = BB2MBB.find (CaseBB);
484
+ if (It == BB2MBB.end ())
485
+ report_fatal_error (" cannot find a machine basic block by a basic "
486
+ " block in a switch statement" );
487
+ NewOps.push_back (MachineOperand::CreateMBB (It->second ));
488
+ MI.getParent ()->addSuccessor (It->second );
489
+ ToEraseMI.insert (Ins[i]);
490
+ } else {
491
+ NewOps.push_back (
492
+ MachineOperand::CreateCImm (Ins[i]->getOperand (1 ).getCImm ()));
576
493
}
577
494
}
578
-
579
- // Modify considered spv_switch operands using collected Values and
580
- // MBBs.
581
- SmallVector<const ConstantInt *, 3 > Values;
582
- SmallVector<MachineBasicBlock *, 3 > MBBs;
583
- for (unsigned k = 2 ; k < Switch->getNumExplicitOperands (); k++) {
584
- Register CReg = Switch->getOperand (k).getReg ();
585
- uint64_t Val = getIConstVal (CReg, &MRI);
586
- MachineInstr *ConstInstr = getDefInstrMaybeConstant (CReg, &MRI);
587
- if (!ValuesToMBBs[Val])
588
- continue ;
589
-
590
- Values.push_back (ConstInstr->getOperand (1 ).getCImm ());
591
- MBBs.push_back (ValuesToMBBs[Val]);
592
- }
593
-
594
- for (unsigned k = Switch->getNumExplicitOperands () - 1 ; k > 1 ; k--)
595
- Switch->removeOperand (k);
596
-
597
- Switch->addOperand (MachineOperand::CreateMBB (DefaultMBB));
598
- for (unsigned k = 0 ; k < Values.size (); k++) {
599
- Switch->addOperand (MachineOperand::CreateCImm (Values[k]));
600
- Switch->addOperand (MachineOperand::CreateMBB (MBBs[k]));
601
- }
602
- }
603
-
604
- for (MachineInstr *MI : PostUpdateArtifacts) {
605
- MachineBasicBlock *ParentMBB = MI->getParent ();
606
- MI->eraseFromParent ();
607
- // If G_ICMP + G_BRCOND + G_BR were the only MIs in MBB, erase this MBB. It
608
- // can be safely assumed, there are no breaks or phis directing into this
609
- // MBB. However, we need to remove this MBB from the CFG graph. MBBs must be
610
- // erased top-down.
611
- if (ParentMBB->empty ()) {
612
- while (!ParentMBB->pred_empty ())
613
- (*ParentMBB->pred_begin ())->removeSuccessor (ParentMBB);
614
-
615
- while (!ParentMBB->succ_empty ())
616
- ParentMBB->removeSuccessor (ParentMBB->succ_begin ());
617
-
618
- ParentMBB->eraseFromParent ();
495
+ for (unsigned i = MI.getNumOperands () - 1 ; i > 1 ; --i)
496
+ MI.removeOperand (i);
497
+ for (auto &MO : NewOps)
498
+ MI.addOperand (MO);
499
+ if (MachineInstr *Next = MI.getNextNode ()) {
500
+ if (isSpvIntrinsic (*Next, Intrinsic::spv_track_constant)) {
501
+ ToEraseMI.insert (Next);
502
+ Next = MI.getNextNode ();
503
+ }
504
+ if (Next && Next->getOpcode () == TargetOpcode::G_BRINDIRECT)
505
+ ToEraseMI.insert (Next);
619
506
}
620
507
}
508
+ for (MachineInstr *BlockAddrI : ToEraseMI)
509
+ BlockAddrI->eraseFromParent ();
621
510
}
622
511
623
512
static bool isImplicitFallthrough (MachineBasicBlock &MBB) {
0 commit comments