[llvm] [CodeGen] Notify delegate before erasing folded instruction (PR #222919)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 06:53:19 PDT 2026
https://github.com/GongJianxiang-Ben updated https://github.com/llvm/llvm-project/pull/222919
>From afe85ca4ac23a76bddb371b592080573889d7edc Mon Sep 17 00:00:00 2001
From: Gong Jianxiang <3247276791 at qq.com>
Date: Fri, 11 Sep 2026 18:50:20 +0800
Subject: [PATCH 1/3] [CodeGen] Notify delegate before erasing folded
instruction
---
llvm/lib/CodeGen/LiveRangeEdit.cpp | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp
index 1d6b835f16468..3059b4f583724 100644
--- a/llvm/lib/CodeGen/LiveRangeEdit.cpp
+++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp
@@ -24,12 +24,12 @@ using namespace llvm;
#define DEBUG_TYPE "regalloc"
-STATISTIC(NumDCEDeleted, "Number of instructions deleted by DCE");
-STATISTIC(NumDCEFoldedLoads, "Number of single use loads folded after DCE");
-STATISTIC(NumFracRanges, "Number of live ranges fractured by DCE");
+STATISTIC(NumDCEDeleted, "Number of instructions deleted by DCE");
+STATISTIC(NumDCEFoldedLoads, "Number of single use loads folded after DCE");
+STATISTIC(NumFracRanges, "Number of live ranges fractured by DCE");
STATISTIC(NumReMaterialization, "Number of instructions rematerialized");
-void LiveRangeEdit::Delegate::anchor() { }
+void LiveRangeEdit::Delegate::anchor() {}
LiveInterval &LiveRangeEdit::createEmptyIntervalFrom(Register OldReg,
bool createSubRanges) {
@@ -108,7 +108,7 @@ void LiveRangeEdit::eraseVirtReg(Register Reg) {
}
bool LiveRangeEdit::foldAsLoad(LiveInterval *LI,
- SmallVectorImpl<MachineInstr*> &Dead) {
+ SmallVectorImpl<MachineInstr *> &Dead) {
MachineInstr *DefMI = nullptr, *UseMI = nullptr;
// Check that there is a single def and a single use.
@@ -161,6 +161,8 @@ bool LiveRangeEdit::foldAsLoad(LiveInterval *LI,
// Update the call info.
if (UseMI->shouldUpdateAdditionalCallInfo())
UseMI->getMF()->moveAdditionalCallInfo(UseMI, FoldMI);
+ if (TheDelegate)
+ TheDelegate->LRE_WillEraseInstruction(UseMI);
UseMI->eraseFromParent();
DefMI->addRegisterDead(LI->reg(), nullptr);
Dead.push_back(DefMI);
@@ -339,10 +341,10 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
MI->setDesc(TII.get(TargetOpcode::KILL));
// Remove all operands that aren't physregs.
for (unsigned i = MI->getNumOperands(); i; --i) {
- const MachineOperand &MO = MI->getOperand(i-1);
+ const MachineOperand &MO = MI->getOperand(i - 1);
if (MO.isReg() && MO.getReg().isPhysical())
continue;
- MI->removeOperand(i-1);
+ MI->removeOperand(i - 1);
}
MI->dropMemRefs(*MI->getMF());
LLVM_DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
@@ -395,7 +397,7 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr *> &Dead,
// LI may have been separated, create new intervals.
LI->RenumberValues();
- SmallVector<LiveInterval*, 8> SplitLIs;
+ SmallVector<LiveInterval *, 8> SplitLIs;
LIS.splitSeparateComponents(*LI, SplitLIs);
if (!SplitLIs.empty())
++NumFracRanges;
@@ -415,8 +417,7 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr *> &Dead,
// Keep track of new virtual registers created via
// MachineRegisterInfo::createVirtualRegister.
-void
-LiveRangeEdit::MRI_NoteNewVirtualRegister(Register VReg) {
+void LiveRangeEdit::MRI_NoteNewVirtualRegister(Register VReg) {
if (VRM)
VRM->grow();
>From 45afaa06b7248cedaea596e6f7310f377f0c03d2 Mon Sep 17 00:00:00 2001
From: Gong Jianxiang <3247276791 at qq.com>
Date: Fri, 11 Sep 2026 20:02:40 +0800
Subject: [PATCH 2/3] Revert some formatting changes
---
llvm/lib/CodeGen/LiveRangeEdit.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp
index 3059b4f583724..71b1dda6edd8c 100644
--- a/llvm/lib/CodeGen/LiveRangeEdit.cpp
+++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp
@@ -24,12 +24,12 @@ using namespace llvm;
#define DEBUG_TYPE "regalloc"
-STATISTIC(NumDCEDeleted, "Number of instructions deleted by DCE");
-STATISTIC(NumDCEFoldedLoads, "Number of single use loads folded after DCE");
-STATISTIC(NumFracRanges, "Number of live ranges fractured by DCE");
+STATISTIC(NumDCEDeleted, "Number of instructions deleted by DCE");
+STATISTIC(NumDCEFoldedLoads, "Number of single use loads folded after DCE");
+STATISTIC(NumFracRanges, "Number of live ranges fractured by DCE");
STATISTIC(NumReMaterialization, "Number of instructions rematerialized");
-void LiveRangeEdit::Delegate::anchor() {}
+void LiveRangeEdit::Delegate::anchor() { }
LiveInterval &LiveRangeEdit::createEmptyIntervalFrom(Register OldReg,
bool createSubRanges) {
@@ -108,7 +108,7 @@ void LiveRangeEdit::eraseVirtReg(Register Reg) {
}
bool LiveRangeEdit::foldAsLoad(LiveInterval *LI,
- SmallVectorImpl<MachineInstr *> &Dead) {
+ SmallVectorImpl<MachineInstr*> &Dead) {
MachineInstr *DefMI = nullptr, *UseMI = nullptr;
// Check that there is a single def and a single use.
@@ -341,10 +341,10 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
MI->setDesc(TII.get(TargetOpcode::KILL));
// Remove all operands that aren't physregs.
for (unsigned i = MI->getNumOperands(); i; --i) {
- const MachineOperand &MO = MI->getOperand(i - 1);
+ const MachineOperand &MO = MI->getOperand(i-1);
if (MO.isReg() && MO.getReg().isPhysical())
continue;
- MI->removeOperand(i - 1);
+ MI->removeOperand(i-1);
}
MI->dropMemRefs(*MI->getMF());
LLVM_DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
@@ -397,7 +397,7 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr *> &Dead,
// LI may have been separated, create new intervals.
LI->RenumberValues();
- SmallVector<LiveInterval *, 8> SplitLIs;
+ SmallVector<LiveInterval*, 8> SplitLIs;
LIS.splitSeparateComponents(*LI, SplitLIs);
if (!SplitLIs.empty())
++NumFracRanges;
>From 113f7d5ed45ed80ddb233882d0a9a854e7632ba7 Mon Sep 17 00:00:00 2001
From: Gong Jianxiang <3247276791 at qq.com>
Date: Fri, 11 Sep 2026 21:51:09 +0800
Subject: [PATCH 3/3] Include some RISCVInstrInfo backend and a test case
---
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 13 +++++++++
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 +-
.../CodeGen/RISCV/foldasload-coalescer-uaf.ll | 27 +++++++++++++++++++
3 files changed, 41 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/RISCV/foldasload-coalescer-uaf.ll
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index ee47963aa041e..a7e21c8652c41 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -969,6 +969,19 @@ MachineInstr *RISCVInstrInfo::foldMemoryOperandImpl(
MachineInstr &LoadMI, MachineInstr *&CopyMI, LiveIntervals *LIS,
VirtRegMap *VRM) const {
MachineBasicBlock::iterator InsertPt = MI;
+
+ if (MI.isCopy() && Ops.size() == 1 && Ops[0] == 1 &&
+ LoadMI.getOpcode() == RISCV::ADDI &&
+ LoadMI.getOperand(1).getReg() == RISCV::X0 &&
+ LoadMI.getOperand(2).isImm()) {
+ int64_t Imm = LoadMI.getOperand(2).getImm();
+ if (!isInt<32>(Imm))
+ return nullptr;
+ return BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(),
+ get(RISCV::PseudoMovImm), MI.getOperand(0).getReg())
+ .addImm(Imm);
+ }
+
// For now, only handle RISCV::PseudoCCMOVGPR.
if (MI.getOpcode() != RISCV::PseudoCCMOVGPR)
return nullptr;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index a9dafff24862c..626c38b1f807d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -862,7 +862,7 @@ def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
// ADDI isn't always rematerializable, but isReMaterializable will be used as
// a hint which is verified in isReMaterializableImpl.
-let isReMaterializable = 1, isAsCheapAsAMove = 1 in
+let canFoldAsLoad = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in
def ADDI : ALU_ri<0b000, "addi">;
let IsSignExtendingOpW = 1 in {
diff --git a/llvm/test/CodeGen/RISCV/foldasload-coalescer-uaf.ll b/llvm/test/CodeGen/RISCV/foldasload-coalescer-uaf.ll
new file mode 100644
index 0000000000000..75cf4fec3c327
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/foldasload-coalescer-uaf.ll
@@ -0,0 +1,27 @@
+; RUN: llc -O3 -mtriple=riscv64 -riscv-use-rematerializable-movimm \
+; RUN: < %s -o /dev/null
+
+; This keeps a rematerializable immediate and a COPY alive through register
+; coalescing. LiveRangeEdit::foldAsLoad() folds the immediate into the COPY,
+; then removes the old COPY from the coalescer worklist.
+
+target triple = "riscv64-pc-unknown-gnu"
+
+define void @f() {
+entry:
+ br label %loop
+
+loop:
+ %i32 = phi i32 [ %and, %inc ], [ 3, %entry ]
+ %i8 = phi i8 [ %tr, %inc ], [ 3, %entry ]
+ %c = icmp eq i8 %i8, 0
+ br i1 %c, label %exit, label %inc
+
+exit:
+ ret void
+
+inc:
+ %tr = trunc i32 %i32 to i8
+ %and = and i32 %i32, 255
+ br label %loop
+}
\ No newline at end of file
More information about the llvm-commits
mailing list