Skip to content

Commit 8c4abac

Browse files
committed
[RISCV][VLOpt] Reorganize visit order and worklist management
This implements a suggestion by Craig in PR llvm#123878. We can move the worklist management out of the per-instruction work and do it once at the end of scanning all the instructions. This should reduce repeat visitation of the same instruction when no changes can be made. Note that this does not remove the inherent O(N^2) in the algorithm. We're still potentially visiiting every user of every def. I also included a guard for unreachable blocks since that had been mentioned as a possible cause. It seems we've rulled that out, but guarding for this case is still a good idea.
1 parent e700106 commit 8c4abac

File tree

1 file changed

+68
-55
lines changed

1 file changed

+68
-55
lines changed

llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp

Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,53 +1292,60 @@ std::optional<MachineOperand> RISCVVLOptimizer::checkUsers(MachineInstr &MI) {
12921292
return CommonVL;
12931293
}
12941294

1295-
bool RISCVVLOptimizer::tryReduceVL(MachineInstr &OrigMI) {
1296-
SetVector<MachineInstr *> Worklist;
1297-
Worklist.insert(&OrigMI);
1295+
bool RISCVVLOptimizer::tryReduceVL(MachineInstr &MI) {
1296+
LLVM_DEBUG(dbgs() << "Trying to reduce VL for " << MI << "\n");
12981297

1299-
bool MadeChange = false;
1300-
while (!Worklist.empty()) {
1301-
MachineInstr &MI = *Worklist.pop_back_val();
1302-
LLVM_DEBUG(dbgs() << "Trying to reduce VL for " << MI << "\n");
1298+
if (!isVectorRegClass(MI.getOperand(0).getReg(), MRI))
1299+
return false;
13031300

1304-
if (!isVectorRegClass(MI.getOperand(0).getReg(), MRI))
1305-
continue;
1301+
auto CommonVL = checkUsers(MI);
1302+
if (!CommonVL)
1303+
return false;
13061304

1307-
auto CommonVL = checkUsers(MI);
1308-
if (!CommonVL)
1309-
continue;
1305+
assert((CommonVL->isImm() || CommonVL->getReg().isVirtual()) &&
1306+
"Expected VL to be an Imm or virtual Reg");
13101307

1311-
assert((CommonVL->isImm() || CommonVL->getReg().isVirtual()) &&
1312-
"Expected VL to be an Imm or virtual Reg");
1308+
unsigned VLOpNum = RISCVII::getVLOpNum(MI.getDesc());
1309+
MachineOperand &VLOp = MI.getOperand(VLOpNum);
13131310

1314-
unsigned VLOpNum = RISCVII::getVLOpNum(MI.getDesc());
1315-
MachineOperand &VLOp = MI.getOperand(VLOpNum);
1311+
if (!RISCV::isVLKnownLE(*CommonVL, VLOp)) {
1312+
LLVM_DEBUG(dbgs() << " Abort due to CommonVL not <= VLOp.\n");
1313+
return false;
1314+
}
13161315

1317-
if (!RISCV::isVLKnownLE(*CommonVL, VLOp)) {
1318-
LLVM_DEBUG(dbgs() << " Abort due to CommonVL not <= VLOp.\n");
1319-
continue;
1320-
}
1316+
if (CommonVL->isImm()) {
1317+
LLVM_DEBUG(dbgs() << " Reduce VL from " << VLOp << " to "
1318+
<< CommonVL->getImm() << " for " << MI << "\n");
1319+
VLOp.ChangeToImmediate(CommonVL->getImm());
1320+
return true;
1321+
}
1322+
const MachineInstr *VLMI = MRI->getVRegDef(CommonVL->getReg());
1323+
if (!MDT->dominates(VLMI, &MI))
1324+
return false;
1325+
LLVM_DEBUG(
1326+
dbgs() << " Reduce VL from " << VLOp << " to "
1327+
<< printReg(CommonVL->getReg(), MRI->getTargetRegisterInfo())
1328+
<< " for " << MI << "\n");
13211329

1322-
if (CommonVL->isImm()) {
1323-
LLVM_DEBUG(dbgs() << " Reduce VL from " << VLOp << " to "
1324-
<< CommonVL->getImm() << " for " << MI << "\n");
1325-
VLOp.ChangeToImmediate(CommonVL->getImm());
1326-
} else {
1327-
const MachineInstr *VLMI = MRI->getVRegDef(CommonVL->getReg());
1328-
if (!MDT->dominates(VLMI, &MI))
1329-
continue;
1330-
LLVM_DEBUG(
1331-
dbgs() << " Reduce VL from " << VLOp << " to "
1332-
<< printReg(CommonVL->getReg(), MRI->getTargetRegisterInfo())
1333-
<< " for " << MI << "\n");
1330+
// All our checks passed. We can reduce VL.
1331+
VLOp.ChangeToRegister(CommonVL->getReg(), false);
1332+
return true;
1333+
}
13341334

1335-
// All our checks passed. We can reduce VL.
1336-
VLOp.ChangeToRegister(CommonVL->getReg(), false);
1337-
}
1335+
bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
1336+
if (skipFunction(MF.getFunction()))
1337+
return false;
1338+
1339+
MRI = &MF.getRegInfo();
1340+
MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
13381341

1339-
MadeChange = true;
1342+
const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
1343+
if (!ST.hasVInstructions())
1344+
return false;
13401345

1341-
// Now add all inputs to this instruction to the worklist.
1346+
SetVector<MachineInstr *> Worklist;
1347+
auto PushOperands = [this, &Worklist](MachineInstr &MI,
1348+
bool IgnoreSameBlock) {
13421349
for (auto &Op : MI.operands()) {
13431350
if (!Op.isReg() || !Op.isUse() || !Op.getReg().isVirtual())
13441351
continue;
@@ -1351,34 +1358,40 @@ bool RISCVVLOptimizer::tryReduceVL(MachineInstr &OrigMI) {
13511358
if (!isCandidate(*DefMI))
13521359
continue;
13531360

1361+
if (IgnoreSameBlock && DefMI->getParent() == MI.getParent())
1362+
continue;
1363+
13541364
Worklist.insert(DefMI);
13551365
}
1356-
}
1357-
1358-
return MadeChange;
1359-
}
1360-
1361-
bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
1362-
if (skipFunction(MF.getFunction()))
1363-
return false;
1364-
1365-
MRI = &MF.getRegInfo();
1366-
MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1367-
1368-
const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
1369-
if (!ST.hasVInstructions())
1370-
return false;
1366+
};
13711367

1368+
// Do a first pass eagerly rewriting in roughly reverse instruction
1369+
// order, populate the worklist with any instructions we might need to
1370+
// revisit. We avoid adding definitions to the worklist if they're
1371+
// in the same block - we're about to visit them anyways.
13721372
bool MadeChange = false;
13731373
for (MachineBasicBlock &MBB : MF) {
1374-
// Visit instructions in reverse order.
1374+
// Avoid unreachable blocks as they have degenerate dominance
1375+
if (!MDT->isReachableFromEntry(&MBB))
1376+
continue;
1377+
13751378
for (auto &MI : make_range(MBB.rbegin(), MBB.rend())) {
13761379
if (!isCandidate(MI))
13771380
continue;
1378-
1379-
MadeChange |= tryReduceVL(MI);
1381+
if (!tryReduceVL(MI))
1382+
continue;
1383+
MadeChange = true;
1384+
PushOperands(MI, /*IgnoreSameBlock*/ true);
13801385
}
13811386
}
13821387

1388+
while (!Worklist.empty()) {
1389+
assert(MadeChange);
1390+
MachineInstr &MI = *Worklist.pop_back_val();
1391+
if (!tryReduceVL(MI))
1392+
continue;
1393+
PushOperands(MI, /*IgnoreSameBlock*/ false);
1394+
}
1395+
13831396
return MadeChange;
13841397
}

0 commit comments

Comments
 (0)