[llvm] PHIElimination: add target hook to control reuse. (PR #163604)
Junjie Gu via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 28 16:23:18 PDT 2025
https://github.com/jgu222 updated https://github.com/llvm/llvm-project/pull/163604
>From a4bb8a115fb461eee6f4de9167daf39b7ef718ad Mon Sep 17 00:00:00 2001
From: "Gu, Junjie" <junjie.gu at intel.com>
Date: Wed, 15 Oct 2025 10:42:31 -0700
Subject: [PATCH 1/2] PHIElimination: add target hook to control reuse.
Add PHI reuse hook so that a target can decide if temporary register
during PHI node elimination can be reused. By default, two phis are
allowed to use the same temporary register if their right-hand-sides
are the same.
However, the left-hand sides of phis need to be checked as well
for some targets, such as a GPU target. If the register banks of
phis's left-hand sides are diffrerent, reuse is not allowed.
Thus, this change adds a target hook for this kind of checking
as it is target-dependent.
This change has no functional change.
This is to resolve the issue:
https://github.com/llvm/llvm-project/issues/163500
---
llvm/include/llvm/CodeGen/TargetInstrInfo.h | 15 +++++++++++++--
llvm/lib/CodeGen/PHIElimination.cpp | 2 +-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 175f205328361..041958b7a3649 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2158,7 +2158,7 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
return TargetOpcode::COPY;
}
- /// During PHI eleimination lets target to make necessary checks and
+ /// During PHI elimination lets target to make necessary checks and
/// insert the copy to the PHI destination register in a target specific
/// manner.
virtual MachineInstr *createPHIDestinationCopy(
@@ -2168,7 +2168,7 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
.addReg(Src);
}
- /// During PHI eleimination lets target to make necessary checks and
+ /// During PHI elimination lets target to make necessary checks and
/// insert the copy to the PHI destination register in a target specific
/// manner.
virtual MachineInstr *createPHISourceCopy(MachineBasicBlock &MBB,
@@ -2180,6 +2180,17 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
.addReg(Src, 0, SrcSubReg);
}
+ /// During PHI elimination lets target to decide if two phis can use the
+ /// same register \p Reg when they have the same rhs. Register \p Reg has
+ /// been used for the first phi and \p PHIReg is the DestReg of the second
+ /// Phi. This function is to check if the second phi can reuse \p Reg as
+ /// its temporary register.
+ /// The default is to allow reuse.
+ virtual bool allowPHIReuse(Register Reg, Register PHIReg,
+ const MachineFunction &MF) const {
+ return true;
+ }
+
/// Returns a \p outliner::OutlinedFunction struct containing target-specific
/// information for a set of outlining candidates. Returns std::nullopt if the
/// candidates are not suitable for outlining. \p MinRepeats is the minimum
diff --git a/llvm/lib/CodeGen/PHIElimination.cpp b/llvm/lib/CodeGen/PHIElimination.cpp
index 34a9d5d0e401f..fc2ecb9317bc4 100644
--- a/llvm/lib/CodeGen/PHIElimination.cpp
+++ b/llvm/lib/CodeGen/PHIElimination.cpp
@@ -380,7 +380,7 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
Register *Entry = nullptr;
if (AllEdgesCritical)
Entry = &LoweredPHIs[MPhi];
- if (Entry && *Entry) {
+ if (Entry && *Entry && TII->allowPHIReuse(*Entry, DestReg, MF)) {
// An identical PHI node was already lowered. Reuse the incoming register.
IncomingReg = *Entry;
reusedIncoming = true;
>From 9ead58d5685f398c56c51e24c89e16dd1efe046a Mon Sep 17 00:00:00 2001
From: "Gu, Junjie" <junjie.gu at intel.com>
Date: Sun, 26 Oct 2025 12:50:34 -0700
Subject: [PATCH 2/2] Use common register class
Remove target hook. Instead, use common register class to
check if two phis are allowed to reuse the same temp.
---
llvm/include/llvm/CodeGen/TargetInstrInfo.h | 15 ++-------------
llvm/lib/CodeGen/PHIElimination.cpp | 13 ++++++++++++-
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 041958b7a3649..175f205328361 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2158,7 +2158,7 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
return TargetOpcode::COPY;
}
- /// During PHI elimination lets target to make necessary checks and
+ /// During PHI eleimination lets target to make necessary checks and
/// insert the copy to the PHI destination register in a target specific
/// manner.
virtual MachineInstr *createPHIDestinationCopy(
@@ -2168,7 +2168,7 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
.addReg(Src);
}
- /// During PHI elimination lets target to make necessary checks and
+ /// During PHI eleimination lets target to make necessary checks and
/// insert the copy to the PHI destination register in a target specific
/// manner.
virtual MachineInstr *createPHISourceCopy(MachineBasicBlock &MBB,
@@ -2180,17 +2180,6 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
.addReg(Src, 0, SrcSubReg);
}
- /// During PHI elimination lets target to decide if two phis can use the
- /// same register \p Reg when they have the same rhs. Register \p Reg has
- /// been used for the first phi and \p PHIReg is the DestReg of the second
- /// Phi. This function is to check if the second phi can reuse \p Reg as
- /// its temporary register.
- /// The default is to allow reuse.
- virtual bool allowPHIReuse(Register Reg, Register PHIReg,
- const MachineFunction &MF) const {
- return true;
- }
-
/// Returns a \p outliner::OutlinedFunction struct containing target-specific
/// information for a set of outlining candidates. Returns std::nullopt if the
/// candidates are not suitable for outlining. \p MinRepeats is the minimum
diff --git a/llvm/lib/CodeGen/PHIElimination.cpp b/llvm/lib/CodeGen/PHIElimination.cpp
index fc2ecb9317bc4..41c2a576dc76a 100644
--- a/llvm/lib/CodeGen/PHIElimination.cpp
+++ b/llvm/lib/CodeGen/PHIElimination.cpp
@@ -377,10 +377,21 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
// typically those created by tail duplication. Typically, an identical PHI
// node can't occur, so avoid hashing/storing such PHIs, which is somewhat
// expensive.
+
+ // canReuse() checks if two phis of the same rhs have the common sub class
+ // for their lhs's and allow reuse if so. (useful for some GPU targets)
+ auto canReuse = [](Register Reg0, Register Reg1, MachineFunction &MF) {
+ auto &MRI = MF.getRegInfo();
+ auto *RC0 = MRI.getRegClass(Reg0);
+ auto *RC1 = MRI.getRegClass(Reg1);
+ return MF.getSubtarget().getRegisterInfo()->getCommonSubClass(RC0, RC1) !=
+ nullptr;
+ };
+
Register *Entry = nullptr;
if (AllEdgesCritical)
Entry = &LoweredPHIs[MPhi];
- if (Entry && *Entry && TII->allowPHIReuse(*Entry, DestReg, MF)) {
+ if (Entry && *Entry && canReuse(*Entry, DestReg, MF)) {
// An identical PHI node was already lowered. Reuse the incoming register.
IncomingReg = *Entry;
reusedIncoming = true;
More information about the llvm-commits
mailing list