aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp79
1 files changed, 53 insertions, 26 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp b/contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp
index c6756b1d3737..cd8644029530 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/MachineCSE.cpp
@@ -60,6 +60,11 @@ STATISTIC(NumCrossBBCSEs,
"Number of cross-MBB physreg referencing CS eliminated");
STATISTIC(NumCommutes, "Number of copies coalesced after commuting");
+// Threshold to avoid excessive cost to compute isProfitableToCSE.
+static cl::opt<int>
+ CSUsesThreshold("csuses-threshold", cl::Hidden, cl::init(1024),
+ cl::desc("Threshold for the size of CSUses"));
+
namespace {
class MachineCSE : public MachineFunctionPass {
@@ -140,7 +145,7 @@ namespace {
DenseMap<MachineDomTreeNode*, unsigned> &OpenChildren);
bool PerformCSE(MachineDomTreeNode *Node);
- bool isPRECandidate(MachineInstr *MI);
+ bool isPRECandidate(MachineInstr *MI, SmallSet<MCRegister, 8> &PhysRefs);
bool ProcessBlockPRE(MachineDominatorTree *MDT, MachineBasicBlock *MBB);
bool PerformSimplePRE(MachineDominatorTree *DT);
/// Heuristics to see if it's profitable to move common computations of MBB
@@ -174,14 +179,14 @@ bool MachineCSE::PerformTrivialCopyPropagation(MachineInstr *MI,
if (!MO.isReg() || !MO.isUse())
continue;
Register Reg = MO.getReg();
- if (!Register::isVirtualRegister(Reg))
+ if (!Reg.isVirtual())
continue;
bool OnlyOneUse = MRI->hasOneNonDBGUse(Reg);
MachineInstr *DefMI = MRI->getVRegDef(Reg);
if (!DefMI->isCopy())
continue;
Register SrcReg = DefMI->getOperand(1).getReg();
- if (!Register::isVirtualRegister(SrcReg))
+ if (!SrcReg.isVirtual())
continue;
if (DefMI->getOperand(0).getSubReg())
continue;
@@ -260,8 +265,10 @@ bool MachineCSE::isPhysDefTriviallyDead(
}
static bool isCallerPreservedOrConstPhysReg(MCRegister Reg,
+ const MachineOperand &MO,
const MachineFunction &MF,
- const TargetRegisterInfo &TRI) {
+ const TargetRegisterInfo &TRI,
+ const TargetInstrInfo &TII) {
// MachineRegisterInfo::isConstantPhysReg directly called by
// MachineRegisterInfo::isCallerPreservedOrConstPhysReg expects the
// reserved registers to be frozen. That doesn't cause a problem post-ISel as
@@ -270,7 +277,7 @@ static bool isCallerPreservedOrConstPhysReg(MCRegister Reg,
// It does cause issues mid-GlobalISel, however, hence the additional
// reservedRegsFrozen check.
const MachineRegisterInfo &MRI = MF.getRegInfo();
- return TRI.isCallerPreservedPhysReg(Reg, MF) ||
+ return TRI.isCallerPreservedPhysReg(Reg, MF) || TII.isIgnorableUse(MO) ||
(MRI.reservedRegsFrozen() && MRI.isConstantPhysReg(Reg));
}
@@ -290,10 +297,11 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
Register Reg = MO.getReg();
if (!Reg)
continue;
- if (Register::isVirtualRegister(Reg))
+ if (Reg.isVirtual())
continue;
// Reading either caller preserved or constant physregs is ok.
- if (!isCallerPreservedOrConstPhysReg(Reg.asMCReg(), *MI->getMF(), *TRI))
+ if (!isCallerPreservedOrConstPhysReg(Reg.asMCReg(), MO, *MI->getMF(), *TRI,
+ *TII))
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
PhysRefs.insert(*AI);
}
@@ -309,7 +317,7 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
Register Reg = MO.getReg();
if (!Reg)
continue;
- if (Register::isVirtualRegister(Reg))
+ if (Reg.isVirtual())
continue;
// Check against PhysRefs even if the def is "dead".
if (PhysRefs.count(Reg.asMCReg()))
@@ -384,7 +392,7 @@ bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
if (!MO.isReg() || !MO.isDef())
continue;
Register MOReg = MO.getReg();
- if (Register::isVirtualRegister(MOReg))
+ if (MOReg.isVirtual())
continue;
if (PhysRefs.count(MOReg.asMCReg()))
return false;
@@ -440,18 +448,26 @@ bool MachineCSE::isProfitableToCSE(Register CSReg, Register Reg,
// If CSReg is used at all uses of Reg, CSE should not increase register
// pressure of CSReg.
bool MayIncreasePressure = true;
- if (Register::isVirtualRegister(CSReg) && Register::isVirtualRegister(Reg)) {
+ if (CSReg.isVirtual() && Reg.isVirtual()) {
MayIncreasePressure = false;
SmallPtrSet<MachineInstr*, 8> CSUses;
+ int NumOfUses = 0;
for (MachineInstr &MI : MRI->use_nodbg_instructions(CSReg)) {
CSUses.insert(&MI);
- }
- for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
- if (!CSUses.count(&MI)) {
+ // Too costly to compute if NumOfUses is very large. Conservatively assume
+ // MayIncreasePressure to avoid spending too much time here.
+ if (++NumOfUses > CSUsesThreshold) {
MayIncreasePressure = true;
break;
}
}
+ if (!MayIncreasePressure)
+ for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
+ if (!CSUses.count(&MI)) {
+ MayIncreasePressure = true;
+ break;
+ }
+ }
}
if (!MayIncreasePressure) return true;
@@ -468,7 +484,7 @@ bool MachineCSE::isProfitableToCSE(Register CSReg, Register Reg,
// of the redundant computation are copies, do not cse.
bool HasVRegUse = false;
for (const MachineOperand &MO : MI->operands()) {
- if (MO.isReg() && MO.isUse() && Register::isVirtualRegister(MO.getReg())) {
+ if (MO.isReg() && MO.isUse() && MO.getReg().isVirtual()) {
HasVRegUse = true;
break;
}
@@ -632,8 +648,7 @@ bool MachineCSE::ProcessBlockCSE(MachineBasicBlock *MBB) {
continue;
}
- assert(Register::isVirtualRegister(OldReg) &&
- Register::isVirtualRegister(NewReg) &&
+ assert(OldReg.isVirtual() && NewReg.isVirtual() &&
"Do not CSE physical register defs!");
if (!isProfitableToCSE(NewReg, OldReg, CSMI->getParent(), &MI)) {
@@ -785,22 +800,24 @@ bool MachineCSE::PerformCSE(MachineDomTreeNode *Node) {
// We use stronger checks for PRE candidate rather than for CSE ones to embrace
// checks inside ProcessBlockCSE(), not only inside isCSECandidate(). This helps
// to exclude instrs created by PRE that won't be CSEed later.
-bool MachineCSE::isPRECandidate(MachineInstr *MI) {
+bool MachineCSE::isPRECandidate(MachineInstr *MI,
+ SmallSet<MCRegister, 8> &PhysRefs) {
if (!isCSECandidate(MI) ||
MI->isNotDuplicable() ||
MI->mayLoad() ||
- MI->isAsCheapAsAMove() ||
+ TII->isAsCheapAsAMove(*MI) ||
MI->getNumDefs() != 1 ||
MI->getNumExplicitDefs() != 1)
return false;
- for (const auto &def : MI->defs())
- if (!Register::isVirtualRegister(def.getReg()))
- return false;
-
- for (const auto &use : MI->uses())
- if (use.isReg() && !Register::isVirtualRegister(use.getReg()))
- return false;
+ for (const MachineOperand &MO : MI->operands()) {
+ if (MO.isReg() && !MO.getReg().isVirtual()) {
+ if (MO.isDef())
+ return false;
+ else
+ PhysRefs.insert(MO.getReg());
+ }
+ }
return true;
}
@@ -809,7 +826,8 @@ bool MachineCSE::ProcessBlockPRE(MachineDominatorTree *DT,
MachineBasicBlock *MBB) {
bool Changed = false;
for (MachineInstr &MI : llvm::make_early_inc_range(*MBB)) {
- if (!isPRECandidate(&MI))
+ SmallSet<MCRegister, 8> PhysRefs;
+ if (!isPRECandidate(&MI, PhysRefs))
continue;
if (!PREMap.count(&MI)) {
@@ -845,6 +863,15 @@ bool MachineCSE::ProcessBlockPRE(MachineDominatorTree *DT,
if (MI.isConvergent() && CMBB != MBB)
continue;
+ // If this instruction uses physical registers then we can only do PRE
+ // if it's using the value that is live at the place we're hoisting to.
+ bool NonLocal;
+ PhysDefVector PhysDefs;
+ if (!PhysRefs.empty() &&
+ !PhysRegDefsReach(&*(CMBB->getFirstTerminator()), &MI, PhysRefs,
+ PhysDefs, NonLocal))
+ continue;
+
assert(MI.getOperand(0).isDef() &&
"First operand of instr with one explicit def must be this def");
Register VReg = MI.getOperand(0).getReg();