Skip to content

Commit 8d4cde5

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 9e65dca commit 8d4cde5

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
@@ -2202,7 +2202,7 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
22022202
if (MI->getFlag(MachineInstr::NoConvergent) && !MCID.isConvergent())
22032203
report("NoConvergent flag expected only on convergent instructions.", MI);
22042204

2205-
if (MI->isPHI()) {
2205+
if (TII->isPhiInstr(*MI)) {
22062206
if (MF->getProperties().hasProperty(
22072207
MachineFunctionProperties::Property::NoPHIs))
22082208
report("Found PHI instruction with NoPHIs property set", MI);
@@ -2705,7 +2705,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
27052705
break;
27062706

27072707
case MachineOperand::MO_MachineBasicBlock:
2708-
if (MI->isPHI() && !MO->getMBB()->isSuccessor(MI->getParent()))
2708+
if (TII->isPhiInstr(*MI) && !MO->getMBB()->isSuccessor(MI->getParent()))
27092709
report("PHI operand is not in the CFG", MO, MONum);
27102710
break;
27112711

@@ -2776,7 +2776,7 @@ void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO,
27762776
}
27772777

27782778
LiveQueryResult LRQ = LR.Query(UseIdx);
2779-
bool HasValue = LRQ.valueIn() || (MI->isPHI() && LRQ.valueOut());
2779+
bool HasValue = LRQ.valueIn() || (TII->isPhiInstr(*MI) && LRQ.valueOut());
27802780
// Check if we have a segment at the use, note however that we only need one
27812781
// live subregister range, the others may be dead.
27822782
if (!HasValue && LaneMask.none()) {
@@ -2895,7 +2895,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
28952895
// Check LiveInts liveness and kill.
28962896
if (LiveInts && !LiveInts->isNotInMIMap(*MI)) {
28972897
SlotIndex UseIdx;
2898-
if (MI->isPHI()) {
2898+
if (TII->isPhiInstr(*MI)) {
28992899
// PHI use occurs on the edge, so check for live out here instead.
29002900
UseIdx = LiveInts->getMBBEndIdx(
29012901
MI->getOperand(MONum + 1).getMBB()).getPrevSlot();
@@ -2926,7 +2926,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
29262926
continue;
29272927
checkLivenessAtUse(MO, MONum, UseIdx, SR, Reg, SR.LaneMask);
29282928
LiveQueryResult LRQ = SR.Query(UseIdx);
2929-
if (LRQ.valueIn() || (MI->isPHI() && LRQ.valueOut()))
2929+
if (LRQ.valueIn() || (TII->isPhiInstr(*MI) && LRQ.valueOut()))
29302930
LiveInMask |= SR.LaneMask;
29312931
}
29322932
// At least parts of the register has to be live at the use.
@@ -2936,7 +2936,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
29362936
report_context(UseIdx);
29372937
}
29382938
// For PHIs all lanes should be live
2939-
if (MI->isPHI() && LiveInMask != MOMask) {
2939+
if (TII->isPhiInstr(*MI) && LiveInMask != MOMask) {
29402940
report("Not all lanes of PHI source live at use", MO, MONum);
29412941
report_context(*LI);
29422942
report_context(UseIdx);
@@ -2987,7 +2987,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
29872987
// must be live in. PHI instructions are handled separately.
29882988
if (MInfo.regsKilled.count(Reg))
29892989
report("Using a killed virtual register", MO, MONum);
2990-
else if (!MI->isPHI())
2990+
else if (!TII->isPhiInstr(*MI))
29912991
MInfo.vregsLiveIn.insert(std::make_pair(Reg, MI));
29922992
}
29932993
}
@@ -3211,17 +3211,22 @@ void MachineVerifier::calcRegsRequired() {
32113211
todo.insert(Pred);
32123212
}
32133213

3214-
// Handle the PHI node.
3215-
for (const MachineInstr &MI : MBB.phis()) {
3216-
for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2) {
3214+
// Handle the PHI nodes.
3215+
// Note: MBB.phis() only returns range containing PHI/G_PHI instructions.
3216+
// MachineVerifier checks MIR post-ISel, and some backends do have their own
3217+
// phi nodes.
3218+
for (const MachineInstr &MI : MBB) {
3219+
// PHI nodes must be the first instructions of the MBB.
3220+
if (!TII->isPhiInstr(MI))
3221+
break;
3222+
for (unsigned i = 0; i < TII->getNumPhiIncomingPair(MI); ++i) {
3223+
auto [Op, Pred] = TII->getPhiIncomingPair(MI, i);
32173224
// Skip those Operands which are undef regs or not regs.
3218-
if (!MI.getOperand(i).isReg() || !MI.getOperand(i).readsReg())
3225+
if (!Op.isReg() || !Op.readsReg())
32193226
continue;
32203227

32213228
// Get register and predecessor for one PHI edge.
3222-
Register Reg = MI.getOperand(i).getReg();
3223-
const MachineBasicBlock *Pred = MI.getOperand(i + 1).getMBB();
3224-
3229+
Register Reg = Op.getReg();
32253230
BBInfo &PInfo = MBBInfoMap[Pred];
32263231
if (PInfo.addRequired(Reg))
32273232
todo.insert(Pred);

llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp

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

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)