Skip to content

Commit f991109

Browse files
mgudimMikhail Gudim
authored andcommitted
[ReachingDefAnalysis] Extend the analysis to stack objects.
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.
1 parent beba4b0 commit f991109

File tree

4 files changed

+290
-3
lines changed

4 files changed

+290
-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+
std::vector<std::vector<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, MCRegister Reg) const;
181193

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

309321
/// Provides the instruction of the closest reaching def instruction of
310322
/// Reg that reaches MI, relative to the begining of MI's basic block.
323+
// Note that Reg may represent a stack slot.
311324
MachineInstr *getReachingLocalMIDef(MachineInstr *MI, MCRegister Reg) const;
312325
};
313326

llvm/lib/CodeGen/ReachingDefAnalysis.cpp

Lines changed: 96 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,12 +54,25 @@ static bool isValidRegDefOf(const MachineOperand &MO, MCRegister 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+
}
65+
return false;
66+
}
67+
5168
void ReachingDefAnalysis::enterBasicBlock(MachineBasicBlock *MBB) {
5269
unsigned MBBNumber = MBB->getNumber();
5370
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
5471
"Unexpected basic block number.");
5572
MBBReachingDefs.startBasicBlock(MBBNumber, NumRegUnits);
5673

74+
MBBFrameObjsReachingDefs[MBBNumber].resize(NumStackObjects, {-1});
75+
5776
// Reset instruction counter in each basic block.
5877
CurInstr = 0;
5978

@@ -126,6 +145,14 @@ void ReachingDefAnalysis::processDefs(MachineInstr *MI) {
126145
"Unexpected basic block number.");
127146

128147
for (auto &MO : MI->operands()) {
148+
if (MO.isFI()) {
149+
int FrameIndex = MO.getIndex();
150+
assert(FrameIndex >= 0 && "Can't handle negative frame indicies yet!");
151+
if (!isFIDef(*MI, FrameIndex, TII))
152+
continue;
153+
MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]
154+
.push_back(CurInstr);
155+
}
129156
if (!isValidRegDef(MO))
130157
continue;
131158
for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
@@ -209,19 +236,62 @@ void ReachingDefAnalysis::processBasicBlock(
209236
leaveBasicBlock(MBB);
210237
}
211238

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

221290
void ReachingDefAnalysis::releaseMemory() {
222291
// Clear the internal vectors.
223292
MBBOutRegsInfos.clear();
224293
MBBReachingDefs.clear();
294+
MBBFrameObjsReachingDefs.clear();
225295
InstIds.clear();
226296
LiveRegs.clear();
227297
}
@@ -234,7 +304,10 @@ void ReachingDefAnalysis::reset() {
234304

235305
void ReachingDefAnalysis::init() {
236306
NumRegUnits = TRI->getNumRegUnits();
307+
NumStackObjects = MF->getFrameInfo().getNumObjects();
308+
ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin();
237309
MBBReachingDefs.init(MF->getNumBlockIDs());
310+
MBBFrameObjsReachingDefs.resize(MF->getNumBlockIDs());
238311
// Initialize the MBBOutRegsInfos
239312
MBBOutRegsInfos.resize(MF->getNumBlockIDs());
240313
LoopTraversal Traversal;
@@ -269,6 +342,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI,
269342
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
270343
"Unexpected basic block number.");
271344
int LatestDef = ReachingDefDefaultVal;
345+
346+
if (Register::isStackSlot(Reg)) {
347+
int FrameIndex = Register::stackSlot2Index(Reg);
348+
for (int Def :
349+
MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]) {
350+
if (Def >= InstId)
351+
break;
352+
DefRes = Def;
353+
}
354+
LatestDef = std::max(LatestDef, DefRes);
355+
return LatestDef;
356+
}
357+
272358
for (MCRegUnit Unit : TRI->regunits(Reg)) {
273359
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
274360
if (Def >= InstId)
@@ -422,7 +508,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, MCRegister Reg,
422508
VisitedBBs.insert(MBB);
423509
LiveRegUnits LiveRegs(*TRI);
424510
LiveRegs.addLiveOuts(*MBB);
425-
if (LiveRegs.available(Reg))
511+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
426512
return;
427513

428514
if (auto *Def = getLocalLiveOutMIDef(MBB, Reg))
@@ -505,7 +591,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI,
505591
MachineBasicBlock *MBB = MI->getParent();
506592
LiveRegUnits LiveRegs(*TRI);
507593
LiveRegs.addLiveOuts(*MBB);
508-
if (LiveRegs.available(Reg))
594+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
509595
return false;
510596

511597
auto Last = MBB->getLastNonDebugInstr();
@@ -525,14 +611,21 @@ MachineInstr *ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
525611
MCRegister Reg) const {
526612
LiveRegUnits LiveRegs(*TRI);
527613
LiveRegs.addLiveOuts(*MBB);
528-
if (LiveRegs.available(Reg))
614+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
529615
return nullptr;
530616

531617
auto Last = MBB->getLastNonDebugInstr();
532618
if (Last == MBB->end())
533619
return nullptr;
534620

621+
if (Register::isStackSlot(Reg)) {
622+
int FrameIndex = Register::stackSlot2Index(Reg);
623+
if (isFIDef(*Last, FrameIndex, TII))
624+
return &*Last;
625+
}
626+
535627
int Def = getReachingDef(&*Last, Reg);
628+
536629
for (auto &MO : Last->operands())
537630
if (isValidRegDefOf(MO, Reg, TRI))
538631
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)