LLVM 24.0.0git
MachineIDFSSAUpdater.cpp
Go to the documentation of this file.
1//===- MachineIDFSSAUpdater.cpp - Unstructured SSA Update Tool ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the MachineIDFSSAUpdater class, which provides an
10// efficient SSA form maintenance utility for machine-level IR. It uses the
11// iterated dominance frontier (IDF) algorithm via MachineForwardIDFCalculator
12// to compute phi-function placement, offering better performance than the
13// incremental MachineSSAUpdater approach. The updater requires a single call
14// to calculate() after all definitions and uses have been registered.
15//
16//===----------------------------------------------------------------------===//
17
19#include "llvm/ADT/DenseMap.h"
30#include "llvm/IR/DebugLoc.h"
31
32namespace llvm {
33
34template <bool IsPostDom>
45
48
49} // namespace llvm
50
51using namespace llvm;
52
53/// Given sets of UsingBlocks and DefBlocks, compute the set of LiveInBlocks.
54/// This is basically a subgraph limited by DefBlocks and UsingBlocks.
55static void
59 // To determine liveness, we must iterate through the predecessors of blocks
60 // where the def is live. Blocks are added to the worklist if we need to
61 // check their predecessors. Start with all the using blocks.
62 SmallVector<MachineBasicBlock *, 64> LiveInBlockWorklist(UsingBlocks.begin(),
63 UsingBlocks.end());
64
65 // Now that we have a set of blocks where the phi is live-in, recursively add
66 // their predecessors until we find the full region the value is live.
67 while (!LiveInBlockWorklist.empty()) {
68 MachineBasicBlock *BB = LiveInBlockWorklist.pop_back_val();
69
70 // The block really is live in here, insert it into the set. If already in
71 // the set, then it has already been processed.
72 if (!LiveInBlocks.insert(BB).second)
73 continue;
74
75 // Since the value is live into BB, it is either defined in a predecessor or
76 // live into it to. Add the preds to the worklist unless they are a
77 // defining block.
78 for (MachineBasicBlock *P : BB->predecessors()) {
79 // The value is not live into a predecessor if it defines the value.
80 if (DefBlocks.count(P))
81 continue;
82
83 // Otherwise it is, add to the worklist.
84 LiveInBlockWorklist.push_back(P);
85 }
86 }
87}
88
90MachineIDFSSAUpdater::createInst(unsigned Opc, MachineBasicBlock *BB,
92 return BuildMI(*BB, I, DebugLoc(), TII.get(Opc),
93 MRI.createVirtualRegister(RegAttrs));
94}
95
96// IsLiveOut indicates whether we are computing live-out values (true) or
97// live-in values (false).
98Register MachineIDFSSAUpdater::computeValue(MachineBasicBlock *BB,
99 bool IsLiveOut) {
100 BBValueInfo *BBInfo = &BBInfos[BB];
101
102 if (IsLiveOut && BBInfo->LiveOutValue)
103 return BBInfo->LiveOutValue;
104
105 if (BBInfo->LiveInValue)
106 return BBInfo->LiveInValue;
107
108 SmallVector<BBValueInfo *, 4> DomPath = {BBInfo};
109 MachineBasicBlock *DomBB = BB, *TopDomBB = BB;
110 Register V;
111
112 while (DT.isReachableFromEntry(DomBB) && !DomBB->pred_empty() &&
113 (DomBB = DT.getNode(DomBB)->getIDom()->getBlock())) {
114 BBInfo = &BBInfos[DomBB];
115 if (BBInfo->LiveOutValue) {
116 V = BBInfo->LiveOutValue;
117 break;
118 }
119 if (BBInfo->LiveInValue) {
120 V = BBInfo->LiveInValue;
121 break;
122 }
123 TopDomBB = DomBB;
124 DomPath.emplace_back(BBInfo);
125 }
126
127 if (!V) {
128 V = createInst(TargetOpcode::IMPLICIT_DEF, TopDomBB,
129 TopDomBB->getFirstNonPHI())
130 .getReg(0);
131 }
132
133 for (BBValueInfo *BBInfo : DomPath) {
134 // Loop above can insert new entries into the BBInfos map: assume the
135 // map shouldn't grow as the caller should have been allocated enough
136 // buckets, see [1].
137 BBInfo->LiveInValue = V;
138 }
139
140 return V;
141}
142
143/// Perform all the necessary updates, including new PHI-nodes insertion and the
144/// requested uses update.
147
149 for (auto [BB, V] : Defines)
150 DefBlocks.insert(BB);
151 IDF.setDefiningBlocks(DefBlocks);
152
153 SmallPtrSet<MachineBasicBlock *, 2> UsingBlocks(UseBlocks.begin(),
154 UseBlocks.end());
157 computeLiveInBlocks(UsingBlocks, DefBlocks, LiveInBlocks);
158 IDF.setLiveInBlocks(LiveInBlocks);
159 IDF.calculate(IDFBlocks);
160
161 // Reserve sufficient buckets to prevent map growth. [1]
162 BBInfos.reserve(LiveInBlocks.size() + DefBlocks.size());
163
164 for (auto [BB, V] : Defines)
165 BBInfos[BB].LiveOutValue = V;
166
167 for (MachineBasicBlock *FrontierBB : IDFBlocks) {
168 Register NewVR =
169 createInst(TargetOpcode::PHI, FrontierBB, FrontierBB->begin())
170 .getReg(0);
171 BBInfos[FrontierBB].LiveInValue = NewVR;
172 }
173
174 for (MachineBasicBlock *BB : IDFBlocks) {
175 auto *PHI = &BB->front();
176 assert(PHI->isPHI());
177 MachineInstrBuilder MIB(*BB->getParent(), PHI);
178 for (MachineBasicBlock *Pred : BB->predecessors())
179 MIB.addReg(computeValue(Pred, /*IsLiveOut=*/true)).addMBB(Pred);
180 }
181}
182
184 return computeValue(BB, /*IsLiveOut=*/false);
185}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:57
static void computeLiveInBlocks(const SmallPtrSetImpl< MachineBasicBlock * > &UsingBlocks, const SmallPtrSetImpl< MachineBasicBlock * > &DefBlocks, SmallPtrSetImpl< MachineBasicBlock * > &LiveInBlocks)
Given sets of UsingBlocks and DefBlocks, compute the set of LiveInBlocks.
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
Core dominator tree base class.
Determine the iterated dominance frontier, given a set of defining blocks, and optionally,...
void calculate(SmallVectorImpl< NodeTy * > &IDFBlocks)
Calculate iterated dominance frontiers.
void setLiveInBlocks(const SmallPtrSetImpl< NodeTy * > &Blocks)
Give the IDF calculator the set of blocks in which the value is live on entry to the block.
void setDefiningBlocks(const SmallPtrSetImpl< NodeTy * > &Blocks)
Give the IDF calculator the set of blocks in which the value is defined.
IDFCalculatorDetail::ChildrenGetterTy< NodeTy, IsPostDom > ChildrenGetterTy
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
typename llvm::IDFCalculatorBase< MachineBasicBlock, IsPostDom > IDFCalculatorBase
typename IDFCalculatorBase::ChildrenGetterTy ChildrenGetterTy
MachineIDFCalculator(DominatorTreeBase< MachineBasicBlock, IsPostDom > &DT)
LLVM_ABI Register getValueInMiddleOfBlock(MachineBasicBlock *BB)
See SSAUpdater::GetValueInMiddleOfBlock description.
LLVM_ABI void calculate()
Calculate and insert necessary PHI nodes for SSA form.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
size_type size() const
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
iterator end() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
iterator begin() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineIDFCalculator< false > MachineForwardIDFCalculator
MachineIDFCalculator< true > MachineReverseIDFCalculator
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...