[llvm] 3c3c850 - [ReachingDefAnalysis] Extend the analysis to stack objects. (#118097)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 29 07:55:19 PST 2025
Author: Mikhail Gudim
Date: 2025-01-29T10:55:16-05:00
New Revision: 3c3c850a45c8f1ea1e9d6aa514e2b6076d1a4534
URL: https://github.com/llvm/llvm-project/commit/3c3c850a45c8f1ea1e9d6aa514e2b6076d1a4534
DIFF: https://github.com/llvm/llvm-project/commit/3c3c850a45c8f1ea1e9d6aa514e2b6076d1a4534.diff
LOG: [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 <michaeltmaitland at gmail.com>
Added:
llvm/test/CodeGen/RISCV/rda-stack.mir
llvm/test/CodeGen/SystemZ/rda-stack-copy.mir
Modified:
llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
llvm/lib/CodeGen/ReachingDefAnalysis.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h b/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
index 2e976a88b4cea1..cff422f539f62d 100644
--- a/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
+++ b/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
@@ -114,8 +114,11 @@ class ReachingDefAnalysis : public MachineFunctionPass {
private:
MachineFunction *MF = nullptr;
const TargetRegisterInfo *TRI = nullptr;
+ const TargetInstrInfo *TII = nullptr;
LoopTraversal::TraversalOrder TraversedMBBOrder;
unsigned NumRegUnits = 0;
+ unsigned NumStackObjects = 0;
+ int ObjectIndexBegin = 0;
/// Instruction that defined each register, relative to the beginning of the
/// current basic block. When a LiveRegsDefInfo is used to represent a
/// live-out register, this value is relative to the end of the basic block,
@@ -138,6 +141,13 @@ class ReachingDefAnalysis : public MachineFunctionPass {
DenseMap<MachineInstr *, int> InstIds;
MBBReachingDefsInfo MBBReachingDefs;
+ using MBBFrameObjsReachingDefsInfo =
+ DenseMap<unsigned, DenseMap<int, SmallVector<int>>>;
+ // MBBFrameObjsReachingDefs[i][j] is a list of instruction indices (relative
+ // to begining of MBB) that define frame index (j +
+ // MF->getFrameInfo().getObjectIndexBegin()) in MBB i. This is used in
+ // answering reaching definition queries.
+ MBBFrameObjsReachingDefsInfo MBBFrameObjsReachingDefs;
/// Default values are 'nothing happened a long time ago'.
const int ReachingDefDefaultVal = -(1 << 21);
@@ -158,6 +168,7 @@ class ReachingDefAnalysis : public MachineFunctionPass {
MachineFunctionPass::getAnalysisUsage(AU);
}
+ void printAllReachingDefs(MachineFunction &MF);
bool runOnMachineFunction(MachineFunction &MF) override;
MachineFunctionProperties getRequiredProperties() const override {
@@ -177,6 +188,7 @@ class ReachingDefAnalysis : public MachineFunctionPass {
/// Provides the instruction id of the closest reaching def instruction of
/// Reg that reaches MI, relative to the begining of MI's basic block.
+ /// Note that Reg may represent a stack slot.
int getReachingDef(MachineInstr *MI, Register Reg) const;
/// Return whether A and B use the same def of Reg.
@@ -305,6 +317,7 @@ class ReachingDefAnalysis : public MachineFunctionPass {
/// Provides the instruction of the closest reaching def instruction of
/// Reg that reaches MI, relative to the begining of MI's basic block.
+ /// Note that Reg may represent a stack slot.
MachineInstr *getReachingLocalMIDef(MachineInstr *MI, Register Reg) const;
};
diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
index 9459904d56e4c3..3d88c6815d51c9 100644
--- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
+++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
@@ -10,6 +10,8 @@
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/LiveRegUnits.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Support/Debug.h"
@@ -18,6 +20,10 @@ using namespace llvm;
#define DEBUG_TYPE "reaching-defs-analysis"
+static cl::opt<bool> PrintAllReachingDefs("print-all-reaching-defs", cl::Hidden,
+ cl::desc("Used for test purpuses"),
+ cl::Hidden);
+
char ReachingDefAnalysis::ID = 0;
INITIALIZE_PASS(ReachingDefAnalysis, DEBUG_TYPE, "ReachingDefAnalysis", false,
true)
@@ -48,6 +54,16 @@ static bool isValidRegDefOf(const MachineOperand &MO, Register Reg,
return TRI->regsOverlap(MO.getReg(), Reg);
}
+static bool isFIDef(const MachineInstr &MI, int FrameIndex,
+ const TargetInstrInfo *TII) {
+ int DefFrameIndex = 0;
+ int SrcFrameIndex = 0;
+ if (TII->isStoreToStackSlot(MI, DefFrameIndex) ||
+ TII->isStackSlotCopy(MI, DefFrameIndex, SrcFrameIndex))
+ return DefFrameIndex == FrameIndex;
+ return false;
+}
+
void ReachingDefAnalysis::enterBasicBlock(MachineBasicBlock *MBB) {
unsigned MBBNumber = MBB->getNumber();
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
@@ -126,6 +142,22 @@ void ReachingDefAnalysis::processDefs(MachineInstr *MI) {
"Unexpected basic block number.");
for (auto &MO : MI->operands()) {
+ if (MO.isFI()) {
+ int FrameIndex = MO.getIndex();
+ assert(FrameIndex >= 0 && "Can't handle negative frame indicies yet!");
+ if (!isFIDef(*MI, FrameIndex, TII))
+ continue;
+ if (MBBFrameObjsReachingDefs.contains(MBBNumber)) {
+ auto Frame2InstrIdx = MBBFrameObjsReachingDefs[MBBNumber];
+ if (Frame2InstrIdx.count(FrameIndex - ObjectIndexBegin) > 0)
+ Frame2InstrIdx[FrameIndex - ObjectIndexBegin].push_back(CurInstr);
+ else
+ Frame2InstrIdx[FrameIndex - ObjectIndexBegin] = {CurInstr};
+ } else {
+ MBBFrameObjsReachingDefs[MBBNumber] = {
+ {FrameIndex - ObjectIndexBegin, {CurInstr}}};
+ }
+ }
if (!isValidRegDef(MO))
continue;
for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
@@ -209,12 +241,54 @@ void ReachingDefAnalysis::processBasicBlock(
leaveBasicBlock(MBB);
}
+void ReachingDefAnalysis::printAllReachingDefs(MachineFunction &MF) {
+ dbgs() << "RDA results for " << MF.getName() << "\n";
+ int Num = 0;
+ DenseMap<MachineInstr *, int> InstToNumMap;
+ SmallPtrSet<MachineInstr *, 2> Defs;
+ for (MachineBasicBlock &MBB : MF) {
+ for (MachineInstr &MI : MBB) {
+ for (MachineOperand &MO : MI.operands()) {
+ Register Reg;
+ if (MO.isFI()) {
+ int FrameIndex = MO.getIndex();
+ assert(FrameIndex >= 0 &&
+ "Can't handle negative frame indicies yet!");
+ Reg = Register::index2StackSlot(FrameIndex);
+ } else if (MO.isReg()) {
+ if (MO.isDef())
+ continue;
+ Reg = MO.getReg();
+ if (!Reg.isValid())
+ continue;
+ } else
+ continue;
+ Defs.clear();
+ getGlobalReachingDefs(&MI, Reg, Defs);
+ MO.print(dbgs(), TRI);
+ dbgs() << ":{ ";
+ for (MachineInstr *Def : Defs)
+ dbgs() << InstToNumMap[Def] << " ";
+ dbgs() << "}\n";
+ }
+ dbgs() << Num << ": " << MI << "\n";
+ InstToNumMap[&MI] = Num;
+ ++Num;
+ }
+ }
+}
+
bool ReachingDefAnalysis::runOnMachineFunction(MachineFunction &mf) {
MF = &mf;
TRI = MF->getSubtarget().getRegisterInfo();
+ const TargetSubtargetInfo &STI = MF->getSubtarget();
+ TRI = STI.getRegisterInfo();
+ TII = STI.getInstrInfo();
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n");
init();
traverse();
+ if (PrintAllReachingDefs)
+ printAllReachingDefs(*MF);
return false;
}
@@ -222,6 +296,7 @@ void ReachingDefAnalysis::releaseMemory() {
// Clear the internal vectors.
MBBOutRegsInfos.clear();
MBBReachingDefs.clear();
+ MBBFrameObjsReachingDefs.clear();
InstIds.clear();
LiveRegs.clear();
}
@@ -234,6 +309,8 @@ void ReachingDefAnalysis::reset() {
void ReachingDefAnalysis::init() {
NumRegUnits = TRI->getNumRegUnits();
+ NumStackObjects = MF->getFrameInfo().getNumObjects();
+ ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin();
MBBReachingDefs.init(MF->getNumBlockIDs());
// Initialize the MBBOutRegsInfos
MBBOutRegsInfos.resize(MF->getNumBlockIDs());
@@ -268,6 +345,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, Register Reg) const {
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
"Unexpected basic block number.");
int LatestDef = ReachingDefDefaultVal;
+
+ if (Register::isStackSlot(Reg)) {
+ int FrameIndex = Register::stackSlot2Index(Reg);
+ for (int Def : MBBFrameObjsReachingDefs.lookup(MBBNumber).lookup(
+ FrameIndex - ObjectIndexBegin)) {
+ if (Def >= InstId)
+ break;
+ DefRes = Def;
+ }
+ LatestDef = std::max(LatestDef, DefRes);
+ return LatestDef;
+ }
+
for (MCRegUnit Unit : TRI->regunits(Reg)) {
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
if (Def >= InstId)
@@ -419,7 +509,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, Register Reg,
VisitedBBs.insert(MBB);
LiveRegUnits LiveRegs(*TRI);
LiveRegs.addLiveOuts(*MBB);
- if (LiveRegs.available(Reg))
+ if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
return;
if (auto *Def = getLocalLiveOutMIDef(MBB, Reg))
@@ -500,7 +590,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI,
MachineBasicBlock *MBB = MI->getParent();
LiveRegUnits LiveRegs(*TRI);
LiveRegs.addLiveOuts(*MBB);
- if (LiveRegs.available(Reg))
+ if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
return false;
auto Last = MBB->getLastNonDebugInstr();
@@ -520,14 +610,21 @@ MachineInstr *ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
Register Reg) const {
LiveRegUnits LiveRegs(*TRI);
LiveRegs.addLiveOuts(*MBB);
- if (LiveRegs.available(Reg))
+ if (Register::isPhysicalRegister(Reg) && LiveRegs.available(Reg))
return nullptr;
auto Last = MBB->getLastNonDebugInstr();
if (Last == MBB->end())
return nullptr;
+ if (Register::isStackSlot(Reg)) {
+ int FrameIndex = Register::stackSlot2Index(Reg);
+ if (isFIDef(*Last, FrameIndex, TII))
+ return &*Last;
+ }
+
int Def = getReachingDef(&*Last, Reg);
+
for (auto &MO : Last->operands())
if (isValidRegDefOf(MO, Reg, TRI))
return &*Last;
diff --git a/llvm/test/CodeGen/RISCV/rda-stack.mir b/llvm/test/CodeGen/RISCV/rda-stack.mir
new file mode 100644
index 00000000000000..5f4974181c1cd5
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rda-stack.mir
@@ -0,0 +1,151 @@
+# RUN: llc %s -mtriple=riscv64 -run-pass=reaching-defs-analysis -print-all-reaching-defs -o - 2>&1 | FileCheck %s
+
+---
+name: test0
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ ; CHECK-LABEL: RDA results for test0
+ ; CHECK-NEXT: %stack.0:{ }
+ ; CHECK-NEXT:0: $x10 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: implicit $x10:{ 0 }
+ ; CHECK-NEXT:1: PseudoRET implicit $x10
+
+ bb.0.entry:
+ $x10 = LD %stack.0, 0 :: (load (s64))
+ PseudoRET implicit $x10
+
+...
+---
+name: test1
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 1, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ ; CHECK-LABEL: RDA results for test1
+ ; CHECK-NEXT: %stack.0:{ }
+ ; CHECK-NEXT: 0: $x10 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: %stack.1:{ }
+ ; CHECK-NEXT: 1: $x11 = LD %stack.1, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ 0 }
+ ; CHECK-NEXT: $x11:{ 1 }
+ ; CHECK-NEXT: 2: $x10 = ADD $x10, $x11
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: implicit $x10:{ 2 }
+ ; CHECK-NEXT: 3: PseudoRET implicit $x10
+
+ bb.0.entry:
+ $x10 = LD %stack.0, 0 :: (load (s64))
+ $x11 = LD %stack.1, 0 :: (load (s64))
+ $x10 = ADD $x10, $x11
+ PseudoRET implicit $x10
+
+...
+---
+name: test2
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 1, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ ; CHECK-LABEL: RDA results for test2
+ ; CHECK-NEXT: %stack.0:{ }
+ ; CHECK-NEXT: 0: $x10 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: %stack.1:{ }
+ ; CHECK-NEXT: 1: $x11 = LD %stack.1, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ 0 }
+ ; CHECK-NEXT: $x11:{ 1 }
+ ; CHECK-NEXT: 2: $x10 = ADD $x10, $x11
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ 2 }
+ ; CHECK-NEXT: %stack.0:{ }
+ ; CHECK-NEXT: 3: SD $x10, %stack.0, 0 :: (store (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: %stack.0:{ 3 }
+ ; CHECK-NEXT: 4: $x10 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: implicit $x10:{ 4 }
+ ; CHECK-NEXT: 5: PseudoRET implicit $x10
+
+ bb.0.entry:
+ $x10 = LD %stack.0, 0 :: (load (s64))
+ $x11 = LD %stack.1, 0 :: (load (s64))
+ $x10 = ADD $x10, $x11
+ SD $x10, %stack.0, 0 :: (store (s64))
+ $x10 = LD %stack.0, 0 :: (load (s64))
+ PseudoRET implicit $x10
+
+...
+---
+name: test3
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ ; CHECK-LABEL: RDA results for test3
+ ; CHECK-NEXT: $x10:{ }
+ ; CHECK-NEXT: $x0:{ }
+ ; CHECK-NEXT: 0: BEQ $x10, $x0, %bb.2
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ }
+ ; CHECK-NEXT: 1: $x10 = ADDI $x10, 1
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ 1 }
+ ; CHECK-NEXT: %stack.0:{ }
+ ; CHECK-NEXT: 2: SD $x10, %stack.0, 0 :: (store (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x0:{ }
+ ; CHECK-NEXT: $x0:{ }
+ ; CHECK-NEXT: 3: BEQ $x0, $x0, %bb.3
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ 1 }
+ ; CHECK-NEXT: 4: $x10 = ADDI $x10, 2
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: $x10:{ 4 }
+ ; CHECK-NEXT: %stack.0:{ 2 }
+ ; CHECK-NEXT: 5: SD $x10, %stack.0, 0 :: (store (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: %stack.0:{ 2 5 }
+ ; CHECK-NEXT: 6: $x10 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: implicit $x10:{ 6 }
+ ; CHECK-NEXT: 7: PseudoRET implicit $x10
+
+ bb.0.entry:
+ liveins: $x10
+ BEQ $x10, $x0, %bb.2
+
+ bb.1:
+ liveins: $x10
+ $x10 = ADDI $x10, 1
+ SD $x10, %stack.0, 0 :: (store (s64))
+ BEQ $x0, $x0, %bb.3
+
+ bb.2:
+ liveins: $x10
+ $x10 = ADDI $x10, 2
+ SD $x10, %stack.0, 0 :: (store (s64))
+
+ bb.3:
+ $x10 = LD %stack.0, 0 :: (load (s64))
+ PseudoRET implicit $x10
+...
diff --git a/llvm/test/CodeGen/SystemZ/rda-stack-copy.mir b/llvm/test/CodeGen/SystemZ/rda-stack-copy.mir
new file mode 100644
index 00000000000000..a93b59324a8e52
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/rda-stack-copy.mir
@@ -0,0 +1,30 @@
+# RUN: llc %s -mtriple=s390x-linux-gnu -run-pass=reaching-defs-analysis -print-all-reaching-defs -o - 2>&1 | FileCheck %s
+
+---
+name: test0
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 1, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ ; CHECK-LABEL: RDA results for test0
+ ; CHECK-NEXT: %stack.1:{ }
+ ; CHECK-NEXT: %stack.0:{ }
+ ; CHECK-NEXT: 0: MVC %stack.1, 0, 4, %stack.0, 0 :: (store (s32) into %stack.1), (load (s32) from %stack.0)
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: %stack.1:{ 0 }
+ ; CHECK-NEXT: 1: $r2l = L %stack.1, 0, $noreg
+ ; CHECK-EMPTY:
+ ; CHECK-NEXT: implicit $r2l:{ 1 }
+ ; CHECK-NEXT: 2: Return implicit $r2l
+
+ bb.0:
+ MVC %stack.1, 0 , 4, %stack.0, 0:: (store (s32) into %stack.1), (load (s32) from %stack.0)
+ $r2l = L %stack.1, 0, $noreg
+ Return implicit $r2l
+
+...
More information about the llvm-commits
mailing list