[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

Nathan Gauër via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 9 02:58:46 PDT 2024


================
@@ -744,79 +744,139 @@ static void insertSpirvDecorations(MachineFunction &MF, MachineIRBuilder MIB) {
     MI->eraseFromParent();
 }
 
-// Find basic blocks of the switch and replace registers in spv_switch() by its
-// MBB equivalent.
-static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR,
-                            MachineIRBuilder MIB) {
-  DenseMap<const BasicBlock *, MachineBasicBlock *> BB2MBB;
-  SmallVector<std::pair<MachineInstr *, SmallVector<MachineInstr *, 8>>>
-      Switches;
+// LLVM allows the switches to use registers as cases, while SPIR-V required
+// those to be immediate values. This function replaces such operands with the
+// equivalent immediate constant.
+static void processSwitchesConstants(MachineFunction &MF,
+                                     SPIRVGlobalRegistry *GR,
+                                     MachineIRBuilder MIB) {
+  MachineRegisterInfo &MRI = MF.getRegInfo();
   for (MachineBasicBlock &MBB : MF) {
-    MachineRegisterInfo &MRI = MF.getRegInfo();
-    BB2MBB[MBB.getBasicBlock()] = &MBB;
     for (MachineInstr &MI : MBB) {
       if (!isSpvIntrinsic(MI, Intrinsic::spv_switch))
         continue;
-      // Calls to spv_switch intrinsics representing IR switches.
-      SmallVector<MachineInstr *, 8> NewOps;
-      for (unsigned i = 2; i < MI.getNumOperands(); ++i) {
+
+      SmallVector<MachineOperand, 8> NewOperands;
+      NewOperands.push_back(MI.getOperand(0)); // Opcode
+      NewOperands.push_back(MI.getOperand(1)); // Condition
+      NewOperands.push_back(MI.getOperand(2)); // Default
+      for (unsigned i = 3; i < MI.getNumOperands(); i += 2) {
         Register Reg = MI.getOperand(i).getReg();
-        if (i % 2 == 1) {
-          MachineInstr *ConstInstr = getDefInstrMaybeConstant(Reg, &MRI);
-          NewOps.push_back(ConstInstr);
-        } else {
-          MachineInstr *BuildMBB = MRI.getVRegDef(Reg);
-          assert(BuildMBB &&
-                 BuildMBB->getOpcode() == TargetOpcode::G_BLOCK_ADDR &&
-                 BuildMBB->getOperand(1).isBlockAddress() &&
-                 BuildMBB->getOperand(1).getBlockAddress());
-          NewOps.push_back(BuildMBB);
-        }
+        MachineInstr *ConstInstr = getDefInstrMaybeConstant(Reg, &MRI);
+        NewOperands.push_back(
+            MachineOperand::CreateCImm(ConstInstr->getOperand(1).getCImm()));
+
+        NewOperands.push_back(MI.getOperand(i + 1));
       }
-      Switches.push_back(std::make_pair(&MI, NewOps));
+
+      assert(MI.getNumOperands() == NewOperands.size());
+      while (MI.getNumOperands() > 0)
+        MI.removeOperand(0);
+      for (auto &MO : NewOperands)
+        MI.addOperand(MO);
     }
   }
+}
 
+// Some instructions are used during CodeGen but should never be emitted.
+// Cleaning up those.
+static void cleanupHelperInstructions(MachineFunction &MF) {
   SmallPtrSet<MachineInstr *, 8> ToEraseMI;
----------------
Keenuts wrote:

That's correct! updated.

https://github.com/llvm/llvm-project/pull/107408


More information about the cfe-commits mailing list