Skip to content

Commit 799e1c2

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 6805d7e commit 799e1c2

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, 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: 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, 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+
}
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;
@@ -268,6 +341,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, Register Reg) const {
268341
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
269342
"Unexpected basic block number.");
270343
int LatestDef = ReachingDefDefaultVal;
344+
345+
if (Register::isStackSlot(Reg)) {
346+
int FrameIndex = Register::stackSlot2Index(Reg);
347+
for (int Def :
348+
MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]) {
349+
if (Def >= InstId)
350+
break;
351+
DefRes = Def;
352+
}
353+
LatestDef = std::max(LatestDef, DefRes);
354+
return LatestDef;
355+
}
356+
271357
for (MCRegUnit Unit : TRI->regunits(Reg)) {
272358
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
273359
if (Def >= InstId)
@@ -419,7 +505,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, Register Reg,
419505
VisitedBBs.insert(MBB);
420506
LiveRegUnits LiveRegs(*TRI);
421507
LiveRegs.addLiveOuts(*MBB);
422-
if (LiveRegs.available(Reg))
508+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
423509
return;
424510

425511
if (auto *Def = getLocalLiveOutMIDef(MBB, Reg))
@@ -500,7 +586,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI,
500586
MachineBasicBlock *MBB = MI->getParent();
501587
LiveRegUnits LiveRegs(*TRI);
502588
LiveRegs.addLiveOuts(*MBB);
503-
if (LiveRegs.available(Reg))
589+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
504590
return false;
505591

506592
auto Last = MBB->getLastNonDebugInstr();
@@ -520,14 +606,21 @@ MachineInstr *ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
520606
Register Reg) const {
521607
LiveRegUnits LiveRegs(*TRI);
522608
LiveRegs.addLiveOuts(*MBB);
523-
if (LiveRegs.available(Reg))
609+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
524610
return nullptr;
525611

526612
auto Last = MBB->getLastNonDebugInstr();
527613
if (Last == MBB->end())
528614
return nullptr;
529615

616+
if (Register::isStackSlot(Reg)) {
617+
int FrameIndex = Register::stackSlot2Index(Reg);
618+
if (isFIDef(*Last, FrameIndex, TII))
619+
return &*Last;
620+
}
621+
530622
int Def = getReachingDef(&*Last, Reg);
623+
531624
for (auto &MO : Last->operands())
532625
if (isValidRegDefOf(MO, Reg, TRI))
533626
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)