[llvm] [MachineSSAUpdater][AMDGPU] Add faster version of MachineSSAUpdater class. (PR #145722)

Valery Pykhtin via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 31 05:46:11 PDT 2025


================
@@ -0,0 +1,181 @@
+//===- MachineIDFSSAUpdater.cpp - Unstructured SSA Update Tool ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MachineIDFSSAUpdater class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineIDFSSAUpdater.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Analysis/IteratedDominanceFrontier.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/Debug.h"
+
+namespace llvm {
+
+template <bool IsPostDom>
+class MachineIDFCalculator final
+    : public IDFCalculatorBase<MachineBasicBlock, IsPostDom> {
+public:
+  using IDFCalculatorBase =
+      typename llvm::IDFCalculatorBase<MachineBasicBlock, IsPostDom>;
+  using ChildrenGetterTy = typename IDFCalculatorBase::ChildrenGetterTy;
+
+  MachineIDFCalculator(DominatorTreeBase<MachineBasicBlock, IsPostDom> &DT)
+      : IDFCalculatorBase(DT) {}
+};
+
+using MachineForwardIDFCalculator = MachineIDFCalculator<false>;
+using MachineReverseIDFCalculator = MachineIDFCalculator<true>;
+
+} // namespace llvm
+
+using namespace llvm;
+
+/// Given sets of UsingBlocks and DefBlocks, compute the set of LiveInBlocks.
+/// This is basically a subgraph limited by DefBlocks and UsingBlocks.
+static void
+computeLiveInBlocks(const SmallPtrSetImpl<MachineBasicBlock *> &UsingBlocks,
+                    const SmallPtrSetImpl<MachineBasicBlock *> &DefBlocks,
+                    SmallPtrSetImpl<MachineBasicBlock *> &LiveInBlocks) {
+  // To determine liveness, we must iterate through the predecessors of blocks
+  // where the def is live.  Blocks are added to the worklist if we need to
+  // check their predecessors.  Start with all the using blocks.
+  SmallVector<MachineBasicBlock *, 64> LiveInBlockWorklist(UsingBlocks.begin(),
+                                                           UsingBlocks.end());
+
+  // Now that we have a set of blocks where the phi is live-in, recursively add
+  // their predecessors until we find the full region the value is live.
+  while (!LiveInBlockWorklist.empty()) {
+    MachineBasicBlock *BB = LiveInBlockWorklist.pop_back_val();
+
+    // The block really is live in here, insert it into the set.  If already in
+    // the set, then it has already been processed.
+    if (!LiveInBlocks.insert(BB).second)
+      continue;
+
+    // Since the value is live into BB, it is either defined in a predecessor or
+    // live into it to.  Add the preds to the worklist unless they are a
+    // defining block.
+    for (MachineBasicBlock *P : BB->predecessors()) {
+      // The value is not live into a predecessor if it defines the value.
+      if (DefBlocks.count(P))
+        continue;
+
+      // Otherwise it is, add to the worklist.
+      LiveInBlockWorklist.push_back(P);
+    }
+  }
+}
+
+MachineInstrBuilder
+MachineIDFSSAUpdater::createInst(unsigned Opc, MachineBasicBlock *BB,
+                                 MachineBasicBlock::iterator I) {
+  return BuildMI(*BB, I, DebugLoc(), TII.get(Opc),
+                 MRI.createVirtualRegister(RegAttrs));
+}
+
+// IsLiveOut indicates whether we are computing live-out values (true) or
+// live-in values (false).
+Register MachineIDFSSAUpdater::computeValue(MachineBasicBlock *BB,
+                                            bool IsLiveOut) {
+  BBValueInfo *BBInfo = &BBInfos[BB];
+
+  if (IsLiveOut && BBInfo->LiveOutValue)
+    return BBInfo->LiveOutValue;
+
+  if (BBInfo->LiveInValue)
+    return BBInfo->LiveInValue;
+
+  SmallVector<BBValueInfo *, 4> DomPath = {BBInfo};
+  MachineBasicBlock *DomBB = BB, *TopDomBB = BB;
+  Register V;
+
+  while (DT.isReachableFromEntry(DomBB) && !DomBB->pred_empty() &&
+         (DomBB = DT.getNode(DomBB)->getIDom()->getBlock())) {
+    BBInfo = &BBInfos[DomBB];
+    if (BBInfo->LiveOutValue) {
+      V = BBInfo->LiveOutValue;
+      break;
+    }
+    if (BBInfo->LiveInValue) {
+      V = BBInfo->LiveInValue;
+      break;
+    }
+    TopDomBB = DomBB;
+    DomPath.emplace_back(BBInfo);
+  }
+
+  if (!V) {
+    V = createInst(TargetOpcode::IMPLICIT_DEF, TopDomBB,
----------------
vpykhtin wrote:

I feel that making this class working on generic registers isn't trivial and better should be done in the related change with appropriate testing (looks like even members of the class can be different). For that reason I reverted the change with G_IMPLICIT_DEF for now.

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


More information about the llvm-commits mailing list