[llvm] [ReachingDefAnalysis] Extend the analysis to stack objects. (PR #118097)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 29 06:37:40 PST 2024
https://github.com/mgudim created https://github.com/llvm/llvm-project/pull/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.
>From 087bd440ec9b1d725d9346f43e2e76b8c5ea25c8 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Fri, 29 Nov 2024 09:26:12 -0500
Subject: [PATCH] [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.
---
.../llvm/CodeGen/ReachingDefAnalysis.h | 6 +
llvm/lib/CodeGen/ReachingDefAnalysis.cpp | 96 ++++++++++-
llvm/test/CodeGen/RISCV/rda-stack.mir | 151 ++++++++++++++++++
3 files changed, 250 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/rda-stack.mir
diff --git a/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h b/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
index d6a1f064ec0a58..b7a22a054d2ce5 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,9 @@ class ReachingDefAnalysis : public MachineFunctionPass {
DenseMap<MachineInstr *, int> InstIds;
MBBReachingDefsInfo MBBReachingDefs;
+ using MBBFrameObjsReachingDefsInfo =
+ std::vector<std::vector<std::vector<int>>>;
+ MBBFrameObjsReachingDefsInfo MBBFrameObjsReachingDefs;
/// Default values are 'nothing happened a long time ago'.
const int ReachingDefDefaultVal = -(1 << 21);
diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
index 0e8220ec6251cb..f97049b9ccfdfa 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-deps-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,12 +54,28 @@ static bool isValidRegDefOf(const MachineOperand &MO, MCRegister PhysReg,
return TRI->regsOverlap(MO.getReg(), PhysReg);
}
+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() &&
"Unexpected basic block number.");
MBBReachingDefs.startBasicBlock(MBBNumber, NumRegUnits);
+ MBBFrameObjsReachingDefs[MBBNumber].resize(NumStackObjects);
+ for (unsigned FOIdx = 0; FOIdx < NumStackObjects; ++FOIdx) {
+ MBBFrameObjsReachingDefs[MBBNumber][FOIdx].push_back(-1);
+ }
+
// Reset instruction counter in each basic block.
CurInstr = 0;
@@ -126,6 +148,13 @@ void ReachingDefAnalysis::processDefs(MachineInstr *MI) {
"Unexpected basic block number.");
for (auto &MO : MI->operands()) {
+ if (MO.isFI()) {
+ int FrameIndex = MO.getIndex();
+ if (!isFIDef(*MI, FrameIndex, TII))
+ continue;
+ MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]
+ .push_back(CurInstr);
+ }
if (!isValidRegDef(MO))
continue;
for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
@@ -212,9 +241,46 @@ void ReachingDefAnalysis::processBasicBlock(
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) {
+ 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();
+ Reg = Register::index2StackSlot(FrameIndex);
+ } else if (MO.isReg()) {
+ if (MO.isDef())
+ continue;
+ Reg = MO.getReg();
+ } 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;
+ }
+ }
+ }
return false;
}
@@ -222,6 +288,7 @@ void ReachingDefAnalysis::releaseMemory() {
// Clear the internal vectors.
MBBOutRegsInfos.clear();
MBBReachingDefs.clear();
+ MBBFrameObjsReachingDefs.clear();
InstIds.clear();
LiveRegs.clear();
}
@@ -234,7 +301,10 @@ void ReachingDefAnalysis::reset() {
void ReachingDefAnalysis::init() {
NumRegUnits = TRI->getNumRegUnits();
+ NumStackObjects = MF->getFrameInfo().getNumObjects();
+ ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin();
MBBReachingDefs.init(MF->getNumBlockIDs());
+ MBBFrameObjsReachingDefs.resize(MF->getNumBlockIDs());
// Initialize the MBBOutRegsInfos
MBBOutRegsInfos.resize(MF->getNumBlockIDs());
LoopTraversal Traversal;
@@ -269,6 +339,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI,
assert(MBBNumber < MBBReachingDefs.numBlockIDs() &&
"Unexpected basic block number.");
int LatestDef = ReachingDefDefaultVal;
+
+ if (Register::isStackSlot(PhysReg)) {
+ int FrameIndex = Register::stackSlot2Index(PhysReg);
+ for (int Def :
+ MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]) {
+ if (Def >= InstId)
+ break;
+ DefRes = Def;
+ }
+ LatestDef = std::max(LatestDef, DefRes);
+ return LatestDef;
+ }
+
for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
if (Def >= InstId)
@@ -425,7 +508,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB,
VisitedBBs.insert(MBB);
LiveRegUnits LiveRegs(*TRI);
LiveRegs.addLiveOuts(*MBB);
- if (LiveRegs.available(PhysReg))
+ if (Register::isPhysicalRegister(PhysReg) && LiveRegs.available(PhysReg))
return;
if (auto *Def = getLocalLiveOutMIDef(MBB, PhysReg))
@@ -508,7 +591,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI,
MachineBasicBlock *MBB = MI->getParent();
LiveRegUnits LiveRegs(*TRI);
LiveRegs.addLiveOuts(*MBB);
- if (LiveRegs.available(PhysReg))
+ if (Register::isPhysicalRegister(PhysReg) && LiveRegs.available(PhysReg))
return false;
auto Last = MBB->getLastNonDebugInstr();
@@ -529,7 +612,7 @@ ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
MCRegister PhysReg) const {
LiveRegUnits LiveRegs(*TRI);
LiveRegs.addLiveOuts(*MBB);
- if (LiveRegs.available(PhysReg))
+ if (Register::isPhysicalRegister(PhysReg) && LiveRegs.available(PhysReg))
return nullptr;
auto Last = MBB->getLastNonDebugInstr();
@@ -537,6 +620,13 @@ ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB,
return nullptr;
int Def = getReachingDef(&*Last, PhysReg);
+
+ if (Register::isStackSlot(PhysReg)) {
+ int FrameIndex = Register::stackSlot2Index(PhysReg);
+ if (isFIDef(*Last, FrameIndex, TII))
+ return &*Last;
+ }
+
for (auto &MO : Last->operands())
if (isValidRegDefOf(MO, PhysReg, 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..2f7b546526f241
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rda-stack.mir
@@ -0,0 +1,151 @@
+# RUN: llc %s -mtriple=riscv64 -run-pass=reaching-deps-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
+...
More information about the llvm-commits
mailing list