Skip to content

Commit 8cb8bb0

Browse files
committed
[MachineLICM] Rematerialize instructions that may be hoisted before LICM
1 parent a4993a2 commit 8cb8bb0

File tree

4 files changed

+175
-81
lines changed

4 files changed

+175
-81
lines changed

llvm/include/llvm/CodeGen/MachineCycleAnalysis.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ class LLVM_ABI MachineCycleInfoWrapperPass : public MachineFunctionPass {
4848
// version.
4949
LLVM_ABI bool isCycleInvariant(const MachineCycle *Cycle, MachineInstr &I);
5050

51+
/// Returns true if this machine instruction loads from global offset table or
52+
/// constant pool.
53+
bool mayLoadFromGOTOrConstantPool(MachineInstr &MI);
54+
55+
/// Returns true if this machine instruction can be a sink candidate.
56+
bool isSinkIntoCycleCandidate(MachineInstr &MI, MachineCycle *Cycle,
57+
MachineRegisterInfo *MRI,
58+
const TargetInstrInfo *TII);
59+
5160
class MachineCycleAnalysis : public AnalysisInfoMixin<MachineCycleAnalysis> {
5261
friend AnalysisInfoMixin<MachineCycleAnalysis>;
5362
LLVM_ABI static AnalysisKey Key;

llvm/lib/CodeGen/MachineCycleAnalysis.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,48 @@ bool llvm::isCycleInvariant(const MachineCycle *Cycle, MachineInstr &I) {
167167
// If we got this far, the instruction is cycle invariant!
168168
return true;
169169
}
170+
171+
bool llvm::mayLoadFromGOTOrConstantPool(MachineInstr &MI) {
172+
assert(MI.mayLoad() && "Expected MI that loads!");
173+
174+
// If we lost memory operands, conservatively assume that the instruction
175+
// reads from everything..
176+
if (MI.memoperands_empty())
177+
return true;
178+
179+
for (MachineMemOperand *MemOp : MI.memoperands())
180+
if (const PseudoSourceValue *PSV = MemOp->getPseudoValue())
181+
if (PSV->isGOT() || PSV->isConstantPool())
182+
return true;
183+
184+
return false;
185+
}
186+
187+
bool llvm::isSinkIntoCycleCandidate(MachineInstr &MI, MachineCycle *Cycle,
188+
MachineRegisterInfo *MRI,
189+
const TargetInstrInfo *TII) {
190+
// Not sinking meta instruction.
191+
if (MI.isMetaInstruction())
192+
return false;
193+
// Instruction not a candidate for this target.
194+
if (!TII->shouldSink(MI))
195+
return false;
196+
// Instruction is not cycle invariant.
197+
if (!isCycleInvariant(Cycle, MI))
198+
return false;
199+
// Instruction not safe to move.
200+
bool DontMoveAcrossStore = true;
201+
if (!MI.isSafeToMove(DontMoveAcrossStore))
202+
return false;
203+
// Dont sink GOT or constant pool loads.
204+
if (MI.mayLoad() && !mayLoadFromGOTOrConstantPool(MI))
205+
return false;
206+
if (MI.isConvergent())
207+
return false;
208+
const MachineOperand &MO = MI.getOperand(0);
209+
if (!MO.isReg() || !MO.getReg() || !MO.isDef())
210+
return false;
211+
if (!MRI->hasOneDef(MO.getReg()))
212+
return false;
213+
return true;
214+
}

llvm/lib/CodeGen/MachineLICM.cpp

Lines changed: 117 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ DisableHoistingToHotterBlocks("disable-hoisting-to-hotter-blocks",
9898
clEnumValN(UseBFI::All, "all",
9999
"enable the feature with/wo profile data")));
100100

101+
static cl::opt<bool> SinkInstsIntoCycleBeforeLICM(
102+
"sink-insts-before-licm",
103+
cl::desc("Sink instructions into cycles to avoid "
104+
"register spills"),
105+
cl::init(true), cl::Hidden);
106+
101107
STATISTIC(NumHoisted,
102108
"Number of machine instructions hoisted out of loops");
103109
STATISTIC(NumLowRP,
@@ -287,6 +293,8 @@ namespace {
287293
bool isTgtHotterThanSrc(MachineBasicBlock *SrcBlock,
288294
MachineBasicBlock *TgtBlock);
289295
MachineBasicBlock *getOrCreatePreheader(MachineLoop *CurLoop);
296+
297+
bool rematerializeIntoCycle(MachineCycle *Cycle, MachineInstr &I);
290298
};
291299

292300
class MachineLICMBase : public MachineFunctionPass {
@@ -304,7 +312,11 @@ namespace {
304312
AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
305313
AU.addRequired<MachineDominatorTreeWrapperPass>();
306314
AU.addRequired<AAResultsWrapperPass>();
315+
if (PreRegAlloc)
316+
AU.addRequired<MachineCycleInfoWrapperPass>();
307317
AU.addPreserved<MachineLoopInfoWrapperPass>();
318+
if (PreRegAlloc)
319+
AU.addPreserved<MachineCycleInfoWrapperPass>();
308320
MachineFunctionPass::getAnalysisUsage(AU);
309321
}
310322
};
@@ -348,6 +360,7 @@ INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
348360
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
349361
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
350362
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
363+
INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
351364
INITIALIZE_PASS_END(EarlyMachineLICM, "early-machinelicm",
352365
"Early Machine Loop Invariant Code Motion", false, false)
353366

@@ -396,6 +409,26 @@ bool MachineLICMImpl::run(MachineFunction &MF) {
396409
LLVM_DEBUG(dbgs() << MF.getName() << " ********\n");
397410

398411
if (PreRegAlloc) {
412+
if (SinkInstsIntoCycleBeforeLICM) {
413+
auto *CI = GET_RESULT(MachineCycle, getCycleInfo, Info);
414+
SmallVector<MachineCycle *, 8> Cycles(CI->toplevel_cycles());
415+
for (auto *Cycle : Cycles) {
416+
MachineBasicBlock *Preheader = Cycle->getCyclePreheader();
417+
if (!Preheader) {
418+
LLVM_DEBUG(dbgs() << "Rematerialization: Can't find preheader\n");
419+
continue;
420+
}
421+
SmallVector<MachineInstr *, 8> Candidates;
422+
for (auto &MI : *Preheader)
423+
if (isSinkIntoCycleCandidate(MI, Cycle, MRI, TII))
424+
Candidates.push_back(&MI);
425+
// Walk the candidates in reverse order so that we start with the use
426+
// of a def-use chain, if there is any.
427+
for (MachineInstr *I : llvm::reverse(Candidates))
428+
if (rematerializeIntoCycle(Cycle, *I))
429+
Changed = true;
430+
}
431+
}
399432
// Estimate register pressure during pre-regalloc pass.
400433
unsigned NumRPS = TRI->getNumRegPressureSets();
401434
RegPressure.resize(NumRPS);
@@ -1005,24 +1038,6 @@ MachineLICMImpl::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen,
10051038
return Cost;
10061039
}
10071040

1008-
/// Return true if this machine instruction loads from global offset table or
1009-
/// constant pool.
1010-
static bool mayLoadFromGOTOrConstantPool(MachineInstr &MI) {
1011-
assert(MI.mayLoad() && "Expected MI that loads!");
1012-
1013-
// If we lost memory operands, conservatively assume that the instruction
1014-
// reads from everything..
1015-
if (MI.memoperands_empty())
1016-
return true;
1017-
1018-
for (MachineMemOperand *MemOp : MI.memoperands())
1019-
if (const PseudoSourceValue *PSV = MemOp->getPseudoValue())
1020-
if (PSV->isGOT() || PSV->isConstantPool())
1021-
return true;
1022-
1023-
return false;
1024-
}
1025-
10261041
// This function iterates through all the operands of the input store MI and
10271042
// checks that each register operand statisfies isCallerPreservedPhysReg.
10281043
// This means, the value being stored and the address where it is being stored
@@ -1744,13 +1759,97 @@ bool MachineLICMImpl::isTgtHotterThanSrc(MachineBasicBlock *SrcBlock,
17441759
return Ratio > BlockFrequencyRatioThreshold;
17451760
}
17461761

1762+
/// Rematerialize instructions into cycles before Machine LICM,
1763+
/// since LICM in the middle-end hoisted every instructions without considering
1764+
/// register pressure.
1765+
bool MachineLICMImpl::rematerializeIntoCycle(MachineCycle *Cycle,
1766+
MachineInstr &I) {
1767+
LLVM_DEBUG(dbgs() << "Rematerialization: Finding sink block for: " << I);
1768+
MachineBasicBlock *Preheader = Cycle->getCyclePreheader();
1769+
assert(Preheader && "Cycle sink needs a preheader block");
1770+
MachineBasicBlock *SinkBlock = nullptr;
1771+
const MachineOperand &MO = I.getOperand(0);
1772+
for (MachineInstr &MI : MRI->use_instructions(MO.getReg())) {
1773+
LLVM_DEBUG(dbgs() << "Rematerialization: Analysing use: " << MI);
1774+
if (!Cycle->contains(MI.getParent())) {
1775+
LLVM_DEBUG(
1776+
dbgs() << "Rematerialization: Use not in cycle, can't sink.\n");
1777+
return false;
1778+
}
1779+
if (!SinkBlock) {
1780+
SinkBlock = MI.getParent();
1781+
LLVM_DEBUG(dbgs() << "Rematerialization: Setting sink block to: "
1782+
<< printMBBReference(*SinkBlock) << "\n");
1783+
continue;
1784+
}
1785+
if (MI.isPHI()) {
1786+
for (unsigned I = 1; I != MI.getNumOperands(); I += 2) {
1787+
Register SrcReg = MI.getOperand(I).getReg();
1788+
if (TRI->regsOverlap(SrcReg, MO.getReg())) {
1789+
MachineBasicBlock *SrcBB = MI.getOperand(I + 1).getMBB();
1790+
if (SrcBB != SinkBlock) {
1791+
SinkBlock =
1792+
MDTU->getDomTree().findNearestCommonDominator(SinkBlock, SrcBB);
1793+
if (!SinkBlock)
1794+
break;
1795+
}
1796+
}
1797+
}
1798+
} else {
1799+
SinkBlock = MDTU->getDomTree().findNearestCommonDominator(SinkBlock,
1800+
MI.getParent());
1801+
}
1802+
if (!SinkBlock) {
1803+
LLVM_DEBUG(
1804+
dbgs() << "Rematerialization: Can't find nearest dominator\n");
1805+
return false;
1806+
}
1807+
LLVM_DEBUG(
1808+
dbgs() << "Rematerialization: Setting nearest common dom block: "
1809+
<< printMBBReference(*SinkBlock) << "\n");
1810+
}
1811+
if (!SinkBlock) {
1812+
LLVM_DEBUG(
1813+
dbgs() << "Rematerialization: Not sinking, can't find sink block.\n");
1814+
return false;
1815+
}
1816+
if (SinkBlock == Preheader) {
1817+
LLVM_DEBUG(
1818+
dbgs()
1819+
<< "Rematerialization: Not sinking, sink block is the preheader\n");
1820+
return false;
1821+
}
1822+
for (MachineInstr &MI : MRI->use_instructions(MO.getReg())) {
1823+
if (MI.isPHI() && MI.getParent() == SinkBlock) {
1824+
LLVM_DEBUG(dbgs() << "Rematerialization: Not sinking, sink block is "
1825+
"using it on PHI.\n");
1826+
return false;
1827+
}
1828+
}
1829+
LLVM_DEBUG(dbgs() << "Rematerialization: Sinking instruction!\n");
1830+
SinkBlock->splice(SinkBlock->SkipPHIsAndLabels(SinkBlock->begin()), Preheader,
1831+
I);
1832+
// Conservatively clear any kill flags on uses of sunk instruction
1833+
for (MachineOperand &MO : I.operands()) {
1834+
if (MO.isReg() && MO.readsReg())
1835+
MRI->clearKillFlags(MO.getReg());
1836+
}
1837+
// The instruction is moved from its basic block, so do not retain the
1838+
// debug information.
1839+
assert(!I.isDebugInstr() && "Should not sink debug inst");
1840+
I.setDebugLoc(DebugLoc());
1841+
return true;
1842+
}
1843+
17471844
template <typename DerivedT, bool PreRegAlloc>
17481845
PreservedAnalyses MachineLICMBasePass<DerivedT, PreRegAlloc>::run(
17491846
MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) {
17501847
bool Changed = MachineLICMImpl(PreRegAlloc, nullptr, &MFAM).run(MF);
17511848
if (!Changed)
17521849
return PreservedAnalyses::all();
17531850
auto PA = getMachineFunctionPassPreservedAnalyses();
1851+
if (PreRegAlloc)
1852+
PA.preserve<MachineCycleAnalysis>();
17541853
PA.preserve<MachineLoopAnalysis>();
17551854
return PA;
17561855
}

llvm/lib/CodeGen/MachineSink.cpp

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/CodeGen/MachineFunctionPass.h"
4040
#include "llvm/CodeGen/MachineInstr.h"
4141
#include "llvm/CodeGen/MachineLoopInfo.h"
42+
#include "llvm/CodeGen/MachineLoopUtils.h"
4243
#include "llvm/CodeGen/MachineOperand.h"
4344
#include "llvm/CodeGen/MachinePostDominators.h"
4445
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -258,9 +259,6 @@ class MachineSinking {
258259
bool &BreakPHIEdge,
259260
AllSuccsCache &AllSuccessors);
260261

261-
void FindCycleSinkCandidates(MachineCycle *Cycle, MachineBasicBlock *BB,
262-
SmallVectorImpl<MachineInstr *> &Candidates);
263-
264262
bool
265263
aggressivelySinkIntoCycle(MachineCycle *Cycle, MachineInstr &I,
266264
DenseMap<SinkItem, MachineInstr *> &SunkInstrs);
@@ -694,65 +692,6 @@ bool MachineSinking::AllUsesDominatedByBlock(Register Reg,
694692
return true;
695693
}
696694

697-
/// Return true if this machine instruction loads from global offset table or
698-
/// constant pool.
699-
static bool mayLoadFromGOTOrConstantPool(MachineInstr &MI) {
700-
assert(MI.mayLoad() && "Expected MI that loads!");
701-
702-
// If we lost memory operands, conservatively assume that the instruction
703-
// reads from everything..
704-
if (MI.memoperands_empty())
705-
return true;
706-
707-
for (MachineMemOperand *MemOp : MI.memoperands())
708-
if (const PseudoSourceValue *PSV = MemOp->getPseudoValue())
709-
if (PSV->isGOT() || PSV->isConstantPool())
710-
return true;
711-
712-
return false;
713-
}
714-
715-
void MachineSinking::FindCycleSinkCandidates(
716-
MachineCycle *Cycle, MachineBasicBlock *BB,
717-
SmallVectorImpl<MachineInstr *> &Candidates) {
718-
for (auto &MI : *BB) {
719-
LLVM_DEBUG(dbgs() << "CycleSink: Analysing candidate: " << MI);
720-
if (MI.isMetaInstruction()) {
721-
LLVM_DEBUG(dbgs() << "CycleSink: not sinking meta instruction\n");
722-
continue;
723-
}
724-
if (!TII->shouldSink(MI)) {
725-
LLVM_DEBUG(dbgs() << "CycleSink: Instruction not a candidate for this "
726-
"target\n");
727-
continue;
728-
}
729-
if (!isCycleInvariant(Cycle, MI)) {
730-
LLVM_DEBUG(dbgs() << "CycleSink: Instruction is not cycle invariant\n");
731-
continue;
732-
}
733-
bool DontMoveAcrossStore = true;
734-
if (!MI.isSafeToMove(DontMoveAcrossStore)) {
735-
LLVM_DEBUG(dbgs() << "CycleSink: Instruction not safe to move.\n");
736-
continue;
737-
}
738-
if (MI.mayLoad() && !mayLoadFromGOTOrConstantPool(MI)) {
739-
LLVM_DEBUG(dbgs() << "CycleSink: Dont sink GOT or constant pool loads\n");
740-
continue;
741-
}
742-
if (MI.isConvergent())
743-
continue;
744-
745-
const MachineOperand &MO = MI.getOperand(0);
746-
if (!MO.isReg() || !MO.getReg() || !MO.isDef())
747-
continue;
748-
if (!MRI->hasOneDef(MO.getReg()))
749-
continue;
750-
751-
LLVM_DEBUG(dbgs() << "CycleSink: Instruction added as candidate.\n");
752-
Candidates.push_back(&MI);
753-
}
754-
}
755-
756695
PreservedAnalyses
757696
MachineSinkingPass::run(MachineFunction &MF,
758697
MachineFunctionAnalysisManager &MFAM) {
@@ -892,7 +831,9 @@ bool MachineSinking::run(MachineFunction &MF) {
892831
continue;
893832
}
894833
SmallVector<MachineInstr *, 8> Candidates;
895-
FindCycleSinkCandidates(Cycle, Preheader, Candidates);
834+
for (auto &MI : *Preheader)
835+
if (isSinkIntoCycleCandidate(MI, Cycle, MRI, TII))
836+
Candidates.push_back(&MI);
896837

897838
unsigned i = 0;
898839

0 commit comments

Comments
 (0)