Skip to content

Commit 63917e1

Browse files
authored
[MachineLICM] Allow hoisting loads from invariant address (#70796)
Sometimes, loads can appear in a loop after the LICM pass is executed the final time. For example, ExpandMemCmp pass creates loads in a loop, and one of the operands may be an invariant address. This patch extends the pre-regalloc stage MachineLICM by allowing to hoist invariant loads from loops that don't have any stores or calls and allows load reorderings.
1 parent b57abb7 commit 63917e1

14 files changed

+630
-127
lines changed

llvm/lib/CodeGen/MachineLICM.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ static cl::opt<bool>
7272
HoistConstStores("hoist-const-stores",
7373
cl::desc("Hoist invariant stores"),
7474
cl::init(true), cl::Hidden);
75+
76+
static cl::opt<bool> HoistConstLoads("hoist-const-loads",
77+
cl::desc("Hoist invariant loads"),
78+
cl::init(true), cl::Hidden);
79+
7580
// The default threshold of 100 (i.e. if target block is 100 times hotter)
7681
// is based on empirical data on a single target and is subject to tuning.
7782
static cl::opt<unsigned>
@@ -132,6 +137,9 @@ namespace {
132137
bool Changed = false; // True if a loop is changed.
133138
bool FirstInLoop = false; // True if it's the first LICM in the loop.
134139

140+
// Holds information about whether it is allowed to move load instructions
141+
// out of the loop
142+
SmallDenseMap<MachineLoop *, bool> AllowedToHoistLoads;
135143

136144
// Exit blocks of each Loop.
137145
DenseMap<MachineLoop *, SmallVector<MachineBasicBlock *, 8>> ExitBlockMap;
@@ -281,6 +289,8 @@ namespace {
281289

282290
void InitCSEMap(MachineBasicBlock *BB);
283291

292+
void InitializeLoadsHoistableLoops();
293+
284294
bool isTgtHotterThanSrc(MachineBasicBlock *SrcBlock,
285295
MachineBasicBlock *TgtBlock);
286296
MachineBasicBlock *getCurPreheader(MachineLoop *CurLoop,
@@ -368,6 +378,9 @@ bool MachineLICMBase::runOnMachineFunction(MachineFunction &MF) {
368378
DT = &getAnalysis<MachineDominatorTree>();
369379
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
370380

381+
if (HoistConstLoads)
382+
InitializeLoadsHoistableLoops();
383+
371384
SmallVector<MachineLoop *, 8> Worklist(MLI->begin(), MLI->end());
372385
while (!Worklist.empty()) {
373386
MachineLoop *CurLoop = Worklist.pop_back_val();
@@ -992,7 +1005,7 @@ static bool isCopyFeedingInvariantStore(const MachineInstr &MI,
9921005
/// e.g. If the instruction is a call, then it's obviously not safe to hoist it.
9931006
bool MachineLICMBase::IsLICMCandidate(MachineInstr &I, MachineLoop *CurLoop) {
9941007
// Check if it's safe to move the instruction.
995-
bool DontMoveAcrossStore = true;
1008+
bool DontMoveAcrossStore = !HoistConstLoads || !AllowedToHoistLoads[CurLoop];
9961009
if ((!I.isSafeToMove(AA, DontMoveAcrossStore)) &&
9971010
!(HoistConstStores && isInvariantStore(I, TRI, MRI))) {
9981011
LLVM_DEBUG(dbgs() << "LICM: Instruction not safe to move.\n");
@@ -1333,6 +1346,46 @@ void MachineLICMBase::InitCSEMap(MachineBasicBlock *BB) {
13331346
CSEMap[BB][MI.getOpcode()].push_back(&MI);
13341347
}
13351348

1349+
/// Initialize AllowedToHoistLoads with information about whether invariant
1350+
/// loads can be moved outside a given loop
1351+
void MachineLICMBase::InitializeLoadsHoistableLoops() {
1352+
SmallVector<MachineLoop *, 8> Worklist(MLI->begin(), MLI->end());
1353+
SmallVector<MachineLoop *, 8> LoopsInPreOrder;
1354+
1355+
// Mark all loops as hoistable initially and prepare a list of loops in
1356+
// pre-order DFS.
1357+
while (!Worklist.empty()) {
1358+
auto *L = Worklist.pop_back_val();
1359+
AllowedToHoistLoads[L] = true;
1360+
LoopsInPreOrder.push_back(L);
1361+
Worklist.insert(Worklist.end(), L->getSubLoops().begin(),
1362+
L->getSubLoops().end());
1363+
}
1364+
1365+
// Going from the innermost to outermost loops, check if a loop has
1366+
// instructions preventing invariant load hoisting. If such instruction is
1367+
// found, mark this loop and its parent as non-hoistable and continue
1368+
// investigating the next loop.
1369+
// Visiting in a reversed pre-ordered DFS manner
1370+
// allows us to not process all the instructions of the outer loop if the
1371+
// inner loop is proved to be non-load-hoistable.
1372+
for (auto *Loop : reverse(LoopsInPreOrder)) {
1373+
for (auto *MBB : Loop->blocks()) {
1374+
// If this loop has already been marked as non-hoistable, skip it.
1375+
if (!AllowedToHoistLoads[Loop])
1376+
continue;
1377+
for (auto &MI : *MBB) {
1378+
if (!MI.mayStore() && !MI.isCall() &&
1379+
!(MI.mayLoad() && MI.hasOrderedMemoryRef()))
1380+
continue;
1381+
for (MachineLoop *L = Loop; L != nullptr; L = L->getParentLoop())
1382+
AllowedToHoistLoads[L] = false;
1383+
break;
1384+
}
1385+
}
1386+
}
1387+
}
1388+
13361389
/// Find an instruction amount PrevMIs that is a duplicate of MI.
13371390
/// Return this instruction if it's found.
13381391
MachineInstr *

0 commit comments

Comments
 (0)