Skip to content

Commit 67d7fe7

Browse files
committed
[MachineVerifier] Query TargetInstrInfo for PHI nodes.
MachineVerifier can run post-ISel, and the SPIR-V can emit phi nodes. This means G_PHI/PHI are not the only 2 opcodes representing phi nodes. In addition, the SPIR-V instruction operands are ordered slightly differently (1 additional operand before the pairs). There are multiple ways to solve this, but here I decided to go with the less invasive, but less generic method. However the refactoring mentioned in the rest of this commit can still be done later, as it also relies on TII exposing an `isPhiInstr`. Alternative designs =================== 1st alternative: ---------------- Add a bit in MCInstDesc for phi instructions (See llvm#110019). This was refused as the MCInstDesc bits are "pricy", and a that only impacts 3 instructions is not a wise expense. 2nd alternative: ---------------- Refactorize MachineInstr::isPHI() to use TargetInstrInfo. This was almost possible, as MachineInstr often has a parent MBB, and thus a parent MF which links to the TargetInstrInfo. In MachineInstr: this->getMF().getTargetInstrInfo().isPhiInstr(*this) This however breaks as soon as the MachineInstr is removed from it's parent block. Solving this requires passing TII as a parameter to isPHI. Passing TII requires each code using `isPHI` to also pass TII. This is a very invasive change, which impacts almost every backends, and several passes. Fixes llvm#108844 Signed-off-by: Nathan Gauër <[email protected]>
1 parent 8993367 commit 67d7fe7

File tree

4 files changed

+74
-14
lines changed

4 files changed

+74
-14
lines changed

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,32 @@ class TargetInstrInfo : public MCInstrInfo {
22782278
llvm_unreachable("unknown number of operands necessary");
22792279
}
22802280

2281+
// This this instruction a PHI node.
2282+
// This function should be favored over MI.isPHI() as it allows backends to
2283+
// define additional PHI instructions.
2284+
virtual bool isPhiInstr(const MachineInstr &MI) const {
2285+
return MI.getOpcode() == TargetOpcode::G_PHI ||
2286+
MI.getOpcode() == TargetOpcode::PHI;
2287+
}
2288+
2289+
// Returns the number of [Value, Src] pairs this phi instruction has.
2290+
// Only valid to call on a phi node.
2291+
virtual unsigned getNumPhiIncomingPair(const MachineInstr &MI) const {
2292+
assert(isPhiInstr(MI));
2293+
// G_PHI/PHI only have a single operand before the pairs. 2 Operands per
2294+
// pair.
2295+
return (MI.getNumOperands() - 1) / 2;
2296+
}
2297+
2298+
// Returns the |index|'th [Value, Src] pair of this phi instruction.
2299+
virtual std::pair<MachineOperand, MachineBasicBlock *>
2300+
getPhiIncomingPair(const MachineInstr &MI, unsigned index) const {
2301+
// Behavior for G_PHI/PHI instructions.
2302+
MachineOperand Operand = MI.getOperand(index * 2 + 1);
2303+
MachineBasicBlock *MBB = MI.getOperand(index * 2 + 2).getMBB();
2304+
return {Operand, MBB};
2305+
}
2306+
22812307
private:
22822308
mutable std::unique_ptr<MIRFormatter> Formatter;
22832309
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
22312231
if (MI->getFlag(MachineInstr::NoConvergent) && !MCID.isConvergent())
22322232
report("NoConvergent flag expected only on convergent instructions.", MI);
22332233

2234-
if (MI->isPHI()) {
2234+
if (TII->isPhiInstr(*MI)) {
22352235
if (MF->getProperties().hasProperty(
22362236
MachineFunctionProperties::Property::NoPHIs))
22372237
report("Found PHI instruction with NoPHIs property set", MI);
@@ -2734,7 +2734,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
27342734
break;
27352735

27362736
case MachineOperand::MO_MachineBasicBlock:
2737-
if (MI->isPHI() && !MO->getMBB()->isSuccessor(MI->getParent()))
2737+
if (TII->isPhiInstr(*MI) && !MO->getMBB()->isSuccessor(MI->getParent()))
27382738
report("PHI operand is not in the CFG", MO, MONum);
27392739
break;
27402740

@@ -2805,7 +2805,7 @@ void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO,
28052805
}
28062806

28072807
LiveQueryResult LRQ = LR.Query(UseIdx);
2808-
bool HasValue = LRQ.valueIn() || (MI->isPHI() && LRQ.valueOut());
2808+
bool HasValue = LRQ.valueIn() || (TII->isPhiInstr(*MI) && LRQ.valueOut());
28092809
// Check if we have a segment at the use, note however that we only need one
28102810
// live subregister range, the others may be dead.
28112811
if (!HasValue && LaneMask.none()) {
@@ -2924,7 +2924,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
29242924
// Check LiveInts liveness and kill.
29252925
if (LiveInts && !LiveInts->isNotInMIMap(*MI)) {
29262926
SlotIndex UseIdx;
2927-
if (MI->isPHI()) {
2927+
if (TII->isPhiInstr(*MI)) {
29282928
// PHI use occurs on the edge, so check for live out here instead.
29292929
UseIdx = LiveInts->getMBBEndIdx(
29302930
MI->getOperand(MONum + 1).getMBB()).getPrevSlot();
@@ -2955,7 +2955,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
29552955
continue;
29562956
checkLivenessAtUse(MO, MONum, UseIdx, SR, Reg, SR.LaneMask);
29572957
LiveQueryResult LRQ = SR.Query(UseIdx);
2958-
if (LRQ.valueIn() || (MI->isPHI() && LRQ.valueOut()))
2958+
if (LRQ.valueIn() || (TII->isPhiInstr(*MI) && LRQ.valueOut()))
29592959
LiveInMask |= SR.LaneMask;
29602960
}
29612961
// At least parts of the register has to be live at the use.
@@ -2965,7 +2965,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
29652965
report_context(UseIdx);
29662966
}
29672967
// For PHIs all lanes should be live
2968-
if (MI->isPHI() && LiveInMask != MOMask) {
2968+
if (TII->isPhiInstr(*MI) && LiveInMask != MOMask) {
29692969
report("Not all lanes of PHI source live at use", MO, MONum);
29702970
report_context(*LI);
29712971
report_context(UseIdx);
@@ -3016,7 +3016,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
30163016
// must be live in. PHI instructions are handled separately.
30173017
if (MInfo.regsKilled.count(Reg))
30183018
report("Using a killed virtual register", MO, MONum);
3019-
else if (!MI->isPHI())
3019+
else if (!TII->isPhiInstr(*MI))
30203020
MInfo.vregsLiveIn.insert(std::make_pair(Reg, MI));
30213021
}
30223022
}
@@ -3240,17 +3240,22 @@ void MachineVerifier::calcRegsRequired() {
32403240
todo.insert(Pred);
32413241
}
32423242

3243-
// Handle the PHI node.
3244-
for (const MachineInstr &MI : MBB.phis()) {
3245-
for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2) {
3243+
// Handle the PHI nodes.
3244+
// Note: MBB.phis() only returns range containing PHI/G_PHI instructions.
3245+
// MachineVerifier checks MIR post-ISel, and some backends do have their own
3246+
// phi nodes.
3247+
for (const MachineInstr &MI : MBB) {
3248+
// PHI nodes must be the first instructions of the MBB.
3249+
if (!TII->isPhiInstr(MI))
3250+
break;
3251+
for (unsigned i = 0; i < TII->getNumPhiIncomingPair(MI); ++i) {
3252+
auto [Op, Pred] = TII->getPhiIncomingPair(MI, i);
32463253
// Skip those Operands which are undef regs or not regs.
3247-
if (!MI.getOperand(i).isReg() || !MI.getOperand(i).readsReg())
3254+
if (!Op.isReg() || !Op.readsReg())
32483255
continue;
32493256

32503257
// Get register and predecessor for one PHI edge.
3251-
Register Reg = MI.getOperand(i).getReg();
3252-
const MachineBasicBlock *Pred = MI.getOperand(i + 1).getMBB();
3253-
3258+
Register Reg = Op.getReg();
32543259
BBInfo &PInfo = MBBInfoMap[Pred];
32553260
if (PInfo.addRequired(Reg))
32563261
todo.insert(Pred);

llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,27 @@ bool SPIRVInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
269269
}
270270
return false;
271271
}
272+
273+
// The SPIR-V backends can emit the OpPhi instruction.
274+
bool SPIRVInstrInfo::isPhiInstr(const MachineInstr &MI) const {
275+
return TargetInstrInfo::isPhiInstr(MI) || MI.getOpcode() == SPIRV::OpPhi;
276+
}
277+
278+
unsigned SPIRVInstrInfo::getNumPhiIncomingPair(const MachineInstr &MI) const {
279+
// OpPhi has 2 operands before the [Value, Src] pairs.
280+
if (MI.getOpcode() == SPIRV::OpPhi)
281+
return (MI.getNumOperands() - 2) / 2;
282+
return TargetInstrInfo::getNumPhiIncomingPair(MI);
283+
}
284+
285+
std::pair<MachineOperand, MachineBasicBlock *>
286+
SPIRVInstrInfo::getPhiIncomingPair(const MachineInstr &MI,
287+
unsigned index) const {
288+
if (MI.getOpcode() != SPIRV::OpPhi)
289+
return TargetInstrInfo::getPhiIncomingPair(MI, index);
290+
291+
// Skip the first 2 operands (dst, type), and access each [Value, Src] pairs.
292+
MachineOperand Operand = MI.getOperand(index * 2 + 2);
293+
MachineBasicBlock *MBB = MI.getOperand(index * 2 + 3).getMBB();
294+
return {Operand, MBB};
295+
}

llvm/lib/Target/SPIRV/SPIRVInstrInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ class SPIRVInstrInfo : public SPIRVGenInstrInfo {
5454
bool KillSrc, bool RenamableDest = false,
5555
bool RenamableSrc = false) const override;
5656
bool expandPostRAPseudo(MachineInstr &MI) const override;
57+
58+
bool isPhiInstr(const MachineInstr &MI) const override;
59+
unsigned getNumPhiIncomingPair(const MachineInstr &MI) const override;
60+
std::pair<MachineOperand, MachineBasicBlock *>
61+
getPhiIncomingPair(const MachineInstr &MI, unsigned index) const override;
5762
};
5863

5964
namespace SPIRV {

0 commit comments

Comments
 (0)