Skip to content

Commit 5dda80c

Browse files
committed
Add flag for live variable analysis
Add an mir test
1 parent 2ede4b5 commit 5dda80c

File tree

5 files changed

+123
-23
lines changed

5 files changed

+123
-23
lines changed

llvm/lib/Target/RISCV/RISCVLiveVariables.cpp

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/CodeGen/TargetRegisterInfo.h"
3232
#include "llvm/InitializePasses.h"
3333
#include "llvm/Support/Debug.h"
34+
#include "llvm/Support/ErrorHandling.h"
3435
#include "llvm/Support/raw_ostream.h"
3536
#include <set>
3637

@@ -99,6 +100,7 @@ class RISCVLiveVariables : public MachineFunctionPass {
99100
/// Print liveness information for debugging
100101
void print(raw_ostream &OS, const Module *M = nullptr) const override;
101102

103+
void verifyLiveness(MachineFunction &MF) const;
102104
private:
103105
/// Compute local liveness information (Use and Def sets) for each block
104106
void computeLocalLiveness(MachineFunction &MF);
@@ -160,7 +162,7 @@ bool RISCVLiveVariables::isTrackableRegister(
160162
void RISCVLiveVariables::processInstruction(const MachineInstr &MI,
161163
LivenessInfo &Info,
162164
const TargetRegisterInfo *TRI) {
163-
// Process all operands
165+
std::vector<Register> GenVec;
164166
for (const MachineOperand &MO : MI.operands()) {
165167
if (!MO.isReg() || !MO.getReg())
166168
continue;
@@ -195,16 +197,16 @@ void RISCVLiveVariables::processInstruction(const MachineInstr &MI,
195197
}
196198
}
197199

198-
if (MO.isDef()) {
199-
// This is a definition
200-
Info.Gen.insert(Reg);
200+
if (MO.isDef()) // Collect defs for later processing.
201+
GenVec.push_back(Reg);
202+
}
201203

202-
// Also handle sub-registers for physical registers
203-
if (Reg.isPhysical()) {
204-
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/false);
205-
SubRegs.isValid(); ++SubRegs) {
206-
Info.Gen.insert(*SubRegs);
207-
}
204+
for (auto Reg : GenVec) {
205+
Info.Gen.insert(Reg);
206+
if (Reg.isPhysical()) {
207+
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/false);
208+
SubRegs.isValid(); ++SubRegs) {
209+
Info.Gen.insert(*SubRegs);
208210
}
209211
}
210212
}
@@ -253,7 +255,7 @@ void RISCVLiveVariables::computeLocalLiveness(MachineFunction &MF) {
253255
for (Register Reg : Info.Use)
254256
dbgs() << printReg(Reg, TRI) << " ";
255257
dbgs() << "\n Def: ";
256-
for (Register Reg : Info.Def)
258+
for (Register Reg : Info.Gen)
257259
dbgs() << printReg(Reg, TRI) << " ";
258260
dbgs() << "\n";
259261
});
@@ -273,7 +275,7 @@ void RISCVLiveVariables::computeGlobalLiveness(MachineFunction &MF) {
273275
Changed = false;
274276
++Iterations;
275277

276-
// Process blocks in reverse post-order for better convergence
278+
// Process blocks in **post-order** for better convergence
277279
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
278280

279281
for (MachineBasicBlock *MBB : RPOT) {
@@ -320,13 +322,6 @@ void RISCVLiveVariables::computeGlobalLiveness(MachineFunction &MF) {
320322
const MachineBasicBlock &EntryBB = MF.front();
321323
NumLiveRegsAtEntry += BlockLiveness[&EntryBB].LiveIn.size();
322324
}
323-
324-
for (auto &BB : MF) {
325-
auto &computedLivein = BlockLiveness[&BB].LiveIn;
326-
for (auto &LI : BB.getLiveIns()) {
327-
assert(0 && computedLivein.count(LI.PhysReg));
328-
}
329-
}
330325
}
331326

332327
bool RISCVLiveVariables::isLiveAt(Register Reg,
@@ -355,8 +350,25 @@ bool RISCVLiveVariables::isLiveAt(Register Reg,
355350
return false;
356351
}
357352

353+
void RISCVLiveVariables::verifyLiveness(MachineFunction &MF) const {
354+
for (auto &BB : MF) {
355+
auto BBLiveness = BlockLiveness.find(&BB);
356+
assert(BBLiveness != BlockLiveness.end() && "Missing Liveness");
357+
auto &ComputedLivein = BBLiveness->second.LiveIn;
358+
for (auto &LI : BB.getLiveIns()) {
359+
if (!ComputedLivein.count(LI.PhysReg)) {
360+
LLVM_DEBUG(dbgs() << "Warning: Live-in register "
361+
<< printReg(LI.PhysReg, TRI)
362+
<< " missing from computed live-in set of block "
363+
<< BB.getName() << "\n");
364+
llvm_unreachable("Computed live-in set is inconsistent with MBB.");
365+
}
366+
}
367+
}
368+
}
369+
358370
bool RISCVLiveVariables::runOnMachineFunction(MachineFunction &MF) {
359-
if (skipFunction(MF.getFunction()))
371+
if (skipFunction(MF.getFunction()) || MF.empty())
360372
return false;
361373

362374
const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
@@ -373,8 +385,6 @@ bool RISCVLiveVariables::runOnMachineFunction(MachineFunction &MF) {
373385

374386
LLVM_DEBUG(dbgs() << "***** RISC-V Live Variable Analysis *****\n");
375387
LLVM_DEBUG(dbgs() << "Function: " << MF.getName() << "\n");
376-
LLVM_DEBUG(dbgs() << "Target: RV" << (Subtarget.is64Bit() ? "64" : "32")
377-
<< "\n");
378388

379389
// Clear any previous analysis
380390
BlockLiveness.clear();
@@ -390,6 +400,7 @@ bool RISCVLiveVariables::runOnMachineFunction(MachineFunction &MF) {
390400
print(dbgs());
391401
});
392402

403+
verifyLiveness(MF);
393404
// This is an analysis pass, it doesn't modify the function
394405
return false;
395406
}

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ static cl::opt<bool>
103103
cl::desc("Enable Machine Pipeliner for RISC-V"),
104104
cl::init(false), cl::Hidden);
105105

106+
static cl::opt<bool>
107+
EnableRISCVLiveVariables("riscv-live-variables",
108+
cl::desc("Enable Live Variable Analysis for RISC-V"),
109+
cl::init(false), cl::Hidden);
110+
106111
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
107112
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
108113
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
@@ -620,7 +625,8 @@ void RISCVPassConfig::addPostRegAlloc() {
620625
EnableRedundantCopyElimination)
621626
addPass(createRISCVRedundantCopyEliminationPass());
622627

623-
addPass(createRISCVLiveVariablesPass());
628+
if (EnableRISCVLiveVariables)
629+
addPass(createRISCVLiveVariablesPass());
624630
}
625631

626632
bool RISCVPassConfig::addILPOpts() {

llvm/test/CodeGen/RISCV/live-variables-basic.mir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#
44
# Test basic live variable analysis with simple control flow and basic blocks
55

6+
# REQUIRES: Assertions
7+
68
--- |
79
define i64 @test_simple_add(i64 %a, i64 %b) {
810
entry:

llvm/test/CodeGen/RISCV/live-variables-calls.mir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# Test live variable analysis with function calls and register clobbering
55
# Function calls clobber caller-saved registers, which affects liveness
66

7+
# REQUIRES: Assertions
8+
79
--- |
810
declare i64 @external_func(i64, i64)
911
declare void @void_func(i64)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# RUN: llc -mtriple=riscv64 -verify-machineinstrs -run-pass=riscv-live-variables -debug < %s | FileCheck %s
2+
3+
# REQUIRES: asserts
4+
5+
;CHECK: Block: (Number: 1)
6+
;CHECK: Live-In: { }
7+
;CHECK: Live-Out: { }
8+
;CHECK: Use: { }
9+
;CHECK: Def: { $x10 $x11 $x12 $x13 $x14 $x15 $x16 $x10_h $x11_h $x12_h $x13_h $x14_h $x15_h $x16_h $x10_w $x11_w $x12_w $x13_w $x14_w $x15_w $x16_w }
10+
;CHECK:
11+
;CHECK: Block: (Number: 0)
12+
;CHECK: Live-In: { $x11 $x12 $x13 $x14 $x15 $x16 $x17 $x11_h $x12_h $x13_h $x14_h $x15_h $x16_h $x17_h $x11_w $x12_w $x13_w $x14_w $x15_w $x16_w $x17_w }
13+
;CHECK: Live-Out: { }
14+
;CHECK: Use: { $x11 $x12 $x13 $x14 $x15 $x16 $x17 $x11_h $x12_h $x13_h $x14_h $x15_h $x16_h $x17_h $x11_w $x12_w $x13_w $x14_w $x15_w $x16_w $x17_w }
15+
;CHECK: Def: { $x10 $x11 $x12 $x10_h $x11_h $x12_h $x10_w $x11_w $x12_w }
16+
17+
--- |
18+
19+
source_filename = "liveness-varargs.ll"
20+
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
21+
target triple = "riscv64"
22+
23+
declare void @notdead(ptr)
24+
25+
define i32 @va1(ptr %fmt, ...) {
26+
%va = alloca ptr, align 8
27+
call void @llvm.va_start.p0(ptr %va)
28+
%argp.cur = load ptr, ptr %va, align 4
29+
%argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
30+
store ptr %argp.next, ptr %va, align 4
31+
%1 = load i32, ptr %argp.cur, align 4
32+
call void @llvm.va_end.p0(ptr %va)
33+
ret i32 %1
34+
}
35+
36+
declare void @llvm.va_start.p0(ptr) #1
37+
38+
declare void @llvm.va_end.p0(ptr) #1
39+
40+
declare void @llvm.va_copy.p0(ptr, ptr) #1
41+
42+
attributes #0 = { nounwind }
43+
attributes #1 = { nocallback nofree nosync nounwind willreturn }
44+
...
45+
46+
---
47+
name: va1
48+
tracksRegLiveness: true
49+
noVRegs: false
50+
fixedStack:
51+
- { id: 0, offset: 8, size: 8, alignment: 8, isImmutable: false }
52+
- { id: 1, offset: 56, size: 56, alignment: 8, isImmutable: true }
53+
- { id: 2, offset: 64, size: 8, alignment: 16, isImmutable: true }
54+
stack:
55+
- { id: 0, name: va, size: 2, alignment: 2, stack-id: default }
56+
57+
body: |
58+
bb.0:
59+
liveins: $x11, $x12, $x13, $x14, $x15, $x16, $x17
60+
SD killed renamable $x11, %fixed-stack.1, 0 :: (store (s64) into %fixed-stack.1)
61+
SD killed renamable $x12, %fixed-stack.1, 8 :: (store (s64) into %fixed-stack.1 + 8)
62+
SD killed renamable $x13, %fixed-stack.1, 16 :: (store (s64) into %fixed-stack.1 + 16)
63+
SD killed renamable $x14, %fixed-stack.1, 24 :: (store (s64) into %fixed-stack.1 + 24)
64+
renamable $x10 = ADDI %stack.0.va, 0
65+
renamable $x11 = ADDI %fixed-stack.1, 0
66+
SD killed renamable $x11, %stack.0.va, 0 :: (store (s64) into %ir.va)
67+
renamable $x10 = LW killed renamable $x10, 4 :: (dereferenceable load (s32) from %ir.va + 4)
68+
renamable $x11 = LWU %stack.0.va, 0 :: (dereferenceable load (s32) from %ir.va)
69+
SD killed renamable $x15, %fixed-stack.1, 32 :: (store (s64) into %fixed-stack.1 + 32)
70+
SD killed renamable $x16, %fixed-stack.1, 40 :: (store (s64) into %fixed-stack.1 + 40)
71+
SD killed renamable $x17, %fixed-stack.1, 48 :: (store (s64) into %fixed-stack.1 + 48)
72+
renamable $x10 = SLLI killed renamable $x10, 32
73+
renamable $x10 = OR killed renamable $x10, killed renamable $x11
74+
renamable $x11 = nuw nusw inbounds ADDI renamable $x10, 4
75+
renamable $x12 = SRLI renamable $x11, 32
76+
SW killed renamable $x11, %stack.0.va, 0 :: (store (s32) into %ir.va)
77+
SW killed renamable $x12, %stack.0.va, 4 :: (store (s32) into %ir.va + 4)
78+
renamable $x10 = LW killed renamable $x10, 0 :: (load (s32) from %ir.argp.cur)
79+
PseudoRET implicit $x10

0 commit comments

Comments
 (0)