Skip to content

Commit 990540f

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 990540f

File tree

4 files changed

+289
-3
lines changed

4 files changed

+289
-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: 95 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,13 @@ 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+
if (!isFIDef(*MI, FrameIndex, TII))
151+
continue;
152+
MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]
153+
.push_back(CurInstr);
154+
}
129155
if (!isValidRegDef(MO))
130156
continue;
131157
for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
@@ -209,19 +235,62 @@ void ReachingDefAnalysis::processBasicBlock(
209235
leaveBasicBlock(MBB);
210236
}
211237

238+
void ReachingDefAnalysis::printAllReachingDefs(MachineFunction &MF) {
239+
dbgs() << "RDA results for " << MF.getName() << "\n";
240+
int Num = 0;
241+
DenseMap<MachineInstr *, int> InstToNumMap;
242+
SmallPtrSet<MachineInstr *, 2> Defs;
243+
for (MachineBasicBlock &MBB : MF) {
244+
for (MachineInstr &MI : MBB) {
245+
for (MachineOperand &MO : MI.operands()) {
246+
Register Reg;
247+
if (MO.isFI()) {
248+
int FrameIndex = MO.getIndex();
249+
Reg = Register::index2StackSlot(FrameIndex);
250+
} else if (MO.isReg()) {
251+
if (MO.isDef())
252+
continue;
253+
Reg = MO.getReg();
254+
if (Reg == MCRegister::NoRegister)
255+
continue;
256+
} else {
257+
continue;
258+
}
259+
Defs.clear();
260+
getGlobalReachingDefs(&MI, Reg, Defs);
261+
MO.print(dbgs(), TRI);
262+
dbgs() << ":{ ";
263+
for (MachineInstr *Def : Defs) {
264+
dbgs() << InstToNumMap[Def] << " ";
265+
}
266+
dbgs() << "}\n";
267+
}
268+
dbgs() << Num << ": " << MI << "\n";
269+
InstToNumMap[&MI] = Num;
270+
++Num;
271+
}
272+
}
273+
}
274+
212275
bool ReachingDefAnalysis::runOnMachineFunction(MachineFunction &mf) {
213276
MF = &mf;
214277
TRI = MF->getSubtarget().getRegisterInfo();
278+
const TargetSubtargetInfo &STI = MF->getSubtarget();
279+
TRI = STI.getRegisterInfo();
280+
TII = STI.getInstrInfo();
215281
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n");
216282
init();
217283
traverse();
284+
if (PrintAllReachingDefs)
285+
printAllReachingDefs(*MF);
218286
return false;
219287
}
220288

221289
void ReachingDefAnalysis::releaseMemory() {
222290
// Clear the internal vectors.
223291
MBBOutRegsInfos.clear();
224292
MBBReachingDefs.clear();
293+
MBBFrameObjsReachingDefs.clear();
225294
InstIds.clear();
226295
LiveRegs.clear();
227296
}
@@ -234,7 +303,10 @@ void ReachingDefAnalysis::reset() {
234303

235304
void ReachingDefAnalysis::init() {
236305
NumRegUnits = TRI->getNumRegUnits();
306+
NumStackObjects = MF->getFrameInfo().getNumObjects();
307+
ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin();
237308
MBBReachingDefs.init(MF->getNumBlockIDs());
309+
MBBFrameObjsReachingDefs.resize(MF->getNumBlockIDs());
238310
// Initialize the MBBOutRegsInfos
239311
MBBOutRegsInfos.resize(MF->getNumBlockIDs());
240312
LoopTraversal Traversal;
@@ -269,6 +341,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI,
269341
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
270342
"Unexpected basic block number.");
271343
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+
272357
for (MCRegUnit Unit : TRI->regunits(Reg)) {
273358
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
274359
if (Def >= InstId)
@@ -422,7 +507,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, MCRegister Reg,
422507
VisitedBBs.insert(MBB);
423508
LiveRegUnits LiveRegs(*TRI);
424509
LiveRegs.addLiveOuts(*MBB);
425-
if (LiveRegs.available(Reg))
510+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
426511
return;
427512

428513
if (auto *Def = getLocalLiveOutMIDef(MBB, Reg))
@@ -505,7 +590,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI,
505590
MachineBasicBlock *MBB = MI->getParent();
506591
LiveRegUnits LiveRegs(*TRI);
507592
LiveRegs.addLiveOuts(*MBB);
508-
if (LiveRegs.available(Reg))
593+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
509594
return false;
510595

511596
auto Last = MBB->getLastNonDebugInstr();
@@ -525,14 +610,21 @@ MachineInstr *ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
525610
MCRegister Reg) const {
526611
LiveRegUnits LiveRegs(*TRI);
527612
LiveRegs.addLiveOuts(*MBB);
528-
if (LiveRegs.available(Reg))
613+
if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
529614
return nullptr;
530615

531616
auto Last = MBB->getLastNonDebugInstr();
532617
if (Last == MBB->end())
533618
return nullptr;
534619

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