Skip to content

Commit 3c3c850

Browse files
[ReachingDefAnalysis] Extend the analysis to stack objects. (#118097)
We track definitions of stack objects, the implementation is identical to tracking of registers. Also, added printing of all found reaching definitions for testing purposes. --------- Co-authored-by: Michael Maitland <[email protected]>
1 parent 8baa0d9 commit 3c3c850

File tree

4 files changed

+294
-3
lines changed

4 files changed

+294
-3
lines changed

llvm/include/llvm/CodeGen/ReachingDefAnalysis.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,11 @@ class ReachingDefAnalysis : public MachineFunctionPass {
114114
private:
115115
MachineFunction *MF = nullptr;
116116
const TargetRegisterInfo *TRI = nullptr;
117+
const TargetInstrInfo *TII = nullptr;
117118
LoopTraversal::TraversalOrder TraversedMBBOrder;
118119
unsigned NumRegUnits = 0;
120+
unsigned NumStackObjects = 0;
121+
int ObjectIndexBegin = 0;
119122
/// Instruction that defined each register, relative to the beginning of the
120123
/// current basic block. When a LiveRegsDefInfo is used to represent a
121124
/// live-out register, this value is relative to the end of the basic block,
@@ -138,6 +141,13 @@ class ReachingDefAnalysis : public MachineFunctionPass {
138141
DenseMap<MachineInstr *, int> InstIds;
139142

140143
MBBReachingDefsInfo MBBReachingDefs;
144+
using MBBFrameObjsReachingDefsInfo =
145+
DenseMap<unsigned, DenseMap<int, SmallVector<int>>>;
146+
// MBBFrameObjsReachingDefs[i][j] is a list of instruction indices (relative
147+
// to begining of MBB) that define frame index (j +
148+
// MF->getFrameInfo().getObjectIndexBegin()) in MBB i. This is used in
149+
// answering reaching definition queries.
150+
MBBFrameObjsReachingDefsInfo MBBFrameObjsReachingDefs;
141151

142152
/// Default values are 'nothing happened a long time ago'.
143153
const int ReachingDefDefaultVal = -(1 << 21);
@@ -158,6 +168,7 @@ class ReachingDefAnalysis : public MachineFunctionPass {
158168
MachineFunctionPass::getAnalysisUsage(AU);
159169
}
160170

171+
void printAllReachingDefs(MachineFunction &MF);
161172
bool runOnMachineFunction(MachineFunction &MF) override;
162173

163174
MachineFunctionProperties getRequiredProperties() const override {
@@ -177,6 +188,7 @@ class ReachingDefAnalysis : public MachineFunctionPass {
177188

178189
/// Provides the instruction id of the closest reaching def instruction of
179190
/// Reg that reaches MI, relative to the begining of MI's basic block.
191+
/// Note that Reg may represent a stack slot.
180192
int getReachingDef(MachineInstr *MI, Register Reg) const;
181193

182194
/// Return whether A and B use the same def of Reg.
@@ -305,6 +317,7 @@ class ReachingDefAnalysis : public MachineFunctionPass {
305317

306318
/// Provides the instruction of the closest reaching def instruction of
307319
/// Reg that reaches MI, relative to the begining of MI's basic block.
320+
/// Note that Reg may represent a stack slot.
308321
MachineInstr *getReachingLocalMIDef(MachineInstr *MI, Register Reg) const;
309322
};
310323

llvm/lib/CodeGen/ReachingDefAnalysis.cpp

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "llvm/ADT/SetOperations.h"
1111
#include "llvm/ADT/SmallSet.h"
1212
#include "llvm/CodeGen/LiveRegUnits.h"
13+
#include "llvm/CodeGen/MachineFrameInfo.h"
14+
#include "llvm/CodeGen/TargetInstrInfo.h"
1315
#include "llvm/CodeGen/TargetRegisterInfo.h"
1416
#include "llvm/CodeGen/TargetSubtargetInfo.h"
1517
#include "llvm/Support/Debug.h"
@@ -18,6 +20,10 @@ using namespace llvm;
1820

1921
#define DEBUG_TYPE "reaching-defs-analysis"
2022

23+
static cl::opt<bool> PrintAllReachingDefs("print-all-reaching-defs", cl::Hidden,
24+
cl::desc("Used for test purpuses"),
25+
cl::Hidden);
26+
2127
char ReachingDefAnalysis::ID = 0;
2228
INITIALIZE_PASS(ReachingDefAnalysis, DEBUG_TYPE, "ReachingDefAnalysis", false,
2329
true)
@@ -48,6 +54,16 @@ static bool isValidRegDefOf(const MachineOperand &MO, Register Reg,
4854
return TRI->regsOverlap(MO.getReg(), Reg);
4955
}
5056

57+
static bool isFIDef(const MachineInstr &MI, int FrameIndex,
58+
const TargetInstrInfo *TII) {
59+
int DefFrameIndex = 0;
60+
int SrcFrameIndex = 0;
61+
if (TII->isStoreToStackSlot(MI, DefFrameIndex) ||
62+
TII->isStackSlotCopy(MI, DefFrameIndex, SrcFrameIndex))
63+
return DefFrameIndex == FrameIndex;
64+
return false;
65+
}
66+
5167
void ReachingDefAnalysis::enterBasicBlock(MachineBasicBlock *MBB) {
5268
unsigned MBBNumber = MBB->getNumber();
5369
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
@@ -126,6 +142,22 @@ void ReachingDefAnalysis::processDefs(MachineInstr *MI) {
126142
"Unexpected basic block number.");
127143

128144
for (auto &MO : MI->operands()) {
145+
if (MO.isFI()) {
146+
int FrameIndex = MO.getIndex();
147+
assert(FrameIndex >= 0 && "Can't handle negative frame indicies yet!");
148+
if (!isFIDef(*MI, FrameIndex, TII))
149+
continue;
150+
if (MBBFrameObjsReachingDefs.contains(MBBNumber)) {
151+
auto Frame2InstrIdx = MBBFrameObjsReachingDefs[MBBNumber];
152+
if (Frame2InstrIdx.count(FrameIndex - ObjectIndexBegin) > 0)
153+
Frame2InstrIdx[FrameIndex - ObjectIndexBegin].push_back(CurInstr);
154+
else
155+
Frame2InstrIdx[FrameIndex - ObjectIndexBegin] = {CurInstr};
156+
} else {
157+
MBBFrameObjsReachingDefs[MBBNumber] = {
158+
{FrameIndex - ObjectIndexBegin, {CurInstr}}};
159+
}
160+
}
129161
if (!isValidRegDef(MO))
130162
continue;
131163
for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
@@ -209,19 +241,62 @@ void ReachingDefAnalysis::processBasicBlock(
209241
leaveBasicBlock(MBB);
210242
}
211243

244+
void ReachingDefAnalysis::printAllReachingDefs(MachineFunction &MF) {
245+
dbgs() << "RDA results for " << MF.getName() << "\n";
246+
int Num = 0;
247+
DenseMap<MachineInstr *, int> InstToNumMap;
248+
SmallPtrSet<MachineInstr *, 2> Defs;
249+
for (MachineBasicBlock &MBB : MF) {
250+
for (MachineInstr &MI : MBB) {
251+
for (MachineOperand &MO : MI.operands()) {
252+
Register Reg;
253+
if (MO.isFI()) {
254+
int FrameIndex = MO.getIndex();
255+
assert(FrameIndex >= 0 &&
256+
"Can't handle negative frame indicies yet!");
257+
Reg = Register::index2StackSlot(FrameIndex);
258+
} else if (MO.isReg()) {
259+
if (MO.isDef())
260+
continue;
261+
Reg = MO.getReg();
262+
if (!Reg.isValid())
263+
continue;
264+
} else
265+
continue;
266+
Defs.clear();
267+
getGlobalReachingDefs(&MI, Reg, Defs);
268+
MO.print(dbgs(), TRI);
269+
dbgs() << ":{ ";
270+
for (MachineInstr *Def : Defs)
271+
dbgs() << InstToNumMap[Def] << " ";
272+
dbgs() << "}\n";
273+
}
274+
dbgs() << Num << ": " << MI << "\n";
275+
InstToNumMap[&MI] = Num;
276+
++Num;
277+
}
278+
}
279+
}
280+
212281
bool ReachingDefAnalysis::runOnMachineFunction(MachineFunction &mf) {
213282
MF = &mf;
214283
TRI = MF->getSubtarget().getRegisterInfo();
284+
const TargetSubtargetInfo &STI = MF->getSubtarget();
285+
TRI = STI.getRegisterInfo();
286+
TII = STI.getInstrInfo();
215287
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n");
216288
init();
217289
traverse();
290+
if (PrintAllReachingDefs)
291+
printAllReachingDefs(*MF);
218292
return false;
219293
}
220294

221295
void ReachingDefAnalysis::releaseMemory() {
222296
// Clear the internal vectors.
223297
MBBOutRegsInfos.clear();
224298
MBBReachingDefs.clear();
299+
MBBFrameObjsReachingDefs.clear();
225300
InstIds.clear();
226301
LiveRegs.clear();
227302
}
@@ -234,6 +309,8 @@ void ReachingDefAnalysis::reset() {
234309

235310
void ReachingDefAnalysis::init() {
236311
NumRegUnits = TRI->getNumRegUnits();
312+
NumStackObjects = MF->getFrameInfo().getNumObjects();
313+
ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin();
237314
MBBReachingDefs.init(MF->getNumBlockIDs());
238315
// Initialize the MBBOutRegsInfos
239316
MBBOutRegsInfos.resize(MF->getNumBlockIDs());
@@ -268,6 +345,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, Register Reg) const {
268345
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
269346
"Unexpected basic block number.");
270347
int LatestDef = ReachingDefDefaultVal;
348+
349+
if (Register::isStackSlot(Reg)) {
350+
int FrameIndex = Register::stackSlot2Index(Reg);
351+
for (int Def : MBBFrameObjsReachingDefs.lookup(MBBNumber).lookup(
352+
FrameIndex - ObjectIndexBegin)) {
353+
if (Def >= InstId)
354+
break;
355+
DefRes = Def;
356+
}
357+
LatestDef = std::max(LatestDef, DefRes);
358+
return LatestDef;
359+
}
360+
271361
for (MCRegUnit Unit : TRI->regunits(Reg)) {
272362
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
273363
if (Def >= InstId)
@@ -419,7 +509,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, Register Reg,
419509
VisitedBBs.insert(MBB);
420510
LiveRegUnits LiveRegs(*TRI);
421511
LiveRegs.addLiveOuts(*MBB);
422-
if (LiveRegs.available(Reg))
512+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
423513
return;
424514

425515
if (auto *Def = getLocalLiveOutMIDef(MBB, Reg))
@@ -500,7 +590,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI,
500590
MachineBasicBlock *MBB = MI->getParent();
501591
LiveRegUnits LiveRegs(*TRI);
502592
LiveRegs.addLiveOuts(*MBB);
503-
if (LiveRegs.available(Reg))
593+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
504594
return false;
505595

506596
auto Last = MBB->getLastNonDebugInstr();
@@ -520,14 +610,21 @@ MachineInstr *ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
520610
Register Reg) const {
521611
LiveRegUnits LiveRegs(*TRI);
522612
LiveRegs.addLiveOuts(*MBB);
523-
if (LiveRegs.available(Reg))
613+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
524614
return nullptr;
525615

526616
auto Last = MBB->getLastNonDebugInstr();
527617
if (Last == MBB->end())
528618
return nullptr;
529619

620+
if (Register::isStackSlot(Reg)) {
621+
int FrameIndex = Register::stackSlot2Index(Reg);
622+
if (isFIDef(*Last, FrameIndex, TII))
623+
return &*Last;
624+
}
625+
530626
int Def = getReachingDef(&*Last, Reg);
627+
531628
for (auto &MO : Last->operands())
532629
if (isValidRegDefOf(MO, Reg, TRI))
533630
return &*Last;

llvm/test/CodeGen/RISCV/rda-stack.mir

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# RUN: llc %s -mtriple=riscv64 -run-pass=reaching-defs-analysis -print-all-reaching-defs -o - 2>&1 | FileCheck %s
2+
3+
---
4+
name: test0
5+
tracksRegLiveness: true
6+
stack:
7+
- { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
8+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
9+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
10+
body: |
11+
; CHECK-LABEL: RDA results for test0
12+
; CHECK-NEXT: %stack.0:{ }
13+
; CHECK-NEXT:0: $x10 = LD %stack.0, 0 :: (load (s64))
14+
; CHECK-EMPTY:
15+
; CHECK-NEXT: implicit $x10:{ 0 }
16+
; CHECK-NEXT:1: PseudoRET implicit $x10
17+
18+
bb.0.entry:
19+
$x10 = LD %stack.0, 0 :: (load (s64))
20+
PseudoRET implicit $x10
21+
22+
...
23+
---
24+
name: test1
25+
tracksRegLiveness: true
26+
stack:
27+
- { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
28+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
29+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
30+
- { id: 1, name: '', type: default, offset: 0, size: 4, alignment: 4,
31+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
32+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
33+
body: |
34+
; CHECK-LABEL: RDA results for test1
35+
; CHECK-NEXT: %stack.0:{ }
36+
; CHECK-NEXT: 0: $x10 = LD %stack.0, 0 :: (load (s64))
37+
; CHECK-EMPTY:
38+
; CHECK-NEXT: %stack.1:{ }
39+
; CHECK-NEXT: 1: $x11 = LD %stack.1, 0 :: (load (s64))
40+
; CHECK-EMPTY:
41+
; CHECK-NEXT: $x10:{ 0 }
42+
; CHECK-NEXT: $x11:{ 1 }
43+
; CHECK-NEXT: 2: $x10 = ADD $x10, $x11
44+
; CHECK-EMPTY:
45+
; CHECK-NEXT: implicit $x10:{ 2 }
46+
; CHECK-NEXT: 3: PseudoRET implicit $x10
47+
48+
bb.0.entry:
49+
$x10 = LD %stack.0, 0 :: (load (s64))
50+
$x11 = LD %stack.1, 0 :: (load (s64))
51+
$x10 = ADD $x10, $x11
52+
PseudoRET implicit $x10
53+
54+
...
55+
---
56+
name: test2
57+
tracksRegLiveness: true
58+
stack:
59+
- { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
60+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
61+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
62+
- { id: 1, name: '', type: default, offset: 0, size: 4, alignment: 4,
63+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
64+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
65+
body: |
66+
; CHECK-LABEL: RDA results for test2
67+
; CHECK-NEXT: %stack.0:{ }
68+
; CHECK-NEXT: 0: $x10 = LD %stack.0, 0 :: (load (s64))
69+
; CHECK-EMPTY:
70+
; CHECK-NEXT: %stack.1:{ }
71+
; CHECK-NEXT: 1: $x11 = LD %stack.1, 0 :: (load (s64))
72+
; CHECK-EMPTY:
73+
; CHECK-NEXT: $x10:{ 0 }
74+
; CHECK-NEXT: $x11:{ 1 }
75+
; CHECK-NEXT: 2: $x10 = ADD $x10, $x11
76+
; CHECK-EMPTY:
77+
; CHECK-NEXT: $x10:{ 2 }
78+
; CHECK-NEXT: %stack.0:{ }
79+
; CHECK-NEXT: 3: SD $x10, %stack.0, 0 :: (store (s64))
80+
; CHECK-EMPTY:
81+
; CHECK-NEXT: %stack.0:{ 3 }
82+
; CHECK-NEXT: 4: $x10 = LD %stack.0, 0 :: (load (s64))
83+
; CHECK-EMPTY:
84+
; CHECK-NEXT: implicit $x10:{ 4 }
85+
; CHECK-NEXT: 5: PseudoRET implicit $x10
86+
87+
bb.0.entry:
88+
$x10 = LD %stack.0, 0 :: (load (s64))
89+
$x11 = LD %stack.1, 0 :: (load (s64))
90+
$x10 = ADD $x10, $x11
91+
SD $x10, %stack.0, 0 :: (store (s64))
92+
$x10 = LD %stack.0, 0 :: (load (s64))
93+
PseudoRET implicit $x10
94+
95+
...
96+
---
97+
name: test3
98+
tracksRegLiveness: true
99+
stack:
100+
- { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
101+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
102+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
103+
body: |
104+
; CHECK-LABEL: RDA results for test3
105+
; CHECK-NEXT: $x10:{ }
106+
; CHECK-NEXT: $x0:{ }
107+
; CHECK-NEXT: 0: BEQ $x10, $x0, %bb.2
108+
; CHECK-EMPTY:
109+
; CHECK-NEXT: $x10:{ }
110+
; CHECK-NEXT: 1: $x10 = ADDI $x10, 1
111+
; CHECK-EMPTY:
112+
; CHECK-NEXT: $x10:{ 1 }
113+
; CHECK-NEXT: %stack.0:{ }
114+
; CHECK-NEXT: 2: SD $x10, %stack.0, 0 :: (store (s64))
115+
; CHECK-EMPTY:
116+
; CHECK-NEXT: $x0:{ }
117+
; CHECK-NEXT: $x0:{ }
118+
; CHECK-NEXT: 3: BEQ $x0, $x0, %bb.3
119+
; CHECK-EMPTY:
120+
; CHECK-NEXT: $x10:{ 1 }
121+
; CHECK-NEXT: 4: $x10 = ADDI $x10, 2
122+
; CHECK-EMPTY:
123+
; CHECK-NEXT: $x10:{ 4 }
124+
; CHECK-NEXT: %stack.0:{ 2 }
125+
; CHECK-NEXT: 5: SD $x10, %stack.0, 0 :: (store (s64))
126+
; CHECK-EMPTY:
127+
; CHECK-NEXT: %stack.0:{ 2 5 }
128+
; CHECK-NEXT: 6: $x10 = LD %stack.0, 0 :: (load (s64))
129+
; CHECK-EMPTY:
130+
; CHECK-NEXT: implicit $x10:{ 6 }
131+
; CHECK-NEXT: 7: PseudoRET implicit $x10
132+
133+
bb.0.entry:
134+
liveins: $x10
135+
BEQ $x10, $x0, %bb.2
136+
137+
bb.1:
138+
liveins: $x10
139+
$x10 = ADDI $x10, 1
140+
SD $x10, %stack.0, 0 :: (store (s64))
141+
BEQ $x0, $x0, %bb.3
142+
143+
bb.2:
144+
liveins: $x10
145+
$x10 = ADDI $x10, 2
146+
SD $x10, %stack.0, 0 :: (store (s64))
147+
148+
bb.3:
149+
$x10 = LD %stack.0, 0 :: (load (s64))
150+
PseudoRET implicit $x10
151+
...

0 commit comments

Comments
 (0)