diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index 76a7b8662bae6..14ad5531f22c8 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -1394,10 +1394,19 @@ class MachineInstr return getOpcode() == TargetOpcode::JUMP_TABLE_DEBUG_INFO; } - bool isPHI() const { - return getOpcode() == TargetOpcode::PHI || - getOpcode() == TargetOpcode::G_PHI; + bool isPHI() const { return getDesc().isPhi(); } + + unsigned getIndexFirstPHIPair() const { + assert(isPHI()); + + if (getOpcode() == TargetOpcode::G_PHI || getOpcode() == TargetOpcode::PHI) + return 1; + // The only other instruction marked as PHI node is OpPhi, in the SPIR-V + // backend. The only difference is the [reg, BB] pairs starts at index 2, + // not 1. + return 2; } + bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } bool isInlineAsm() const { diff --git a/llvm/include/llvm/MC/MCInstrDesc.h b/llvm/include/llvm/MC/MCInstrDesc.h index ef0b3c0a73992..3e7786bf2a3d8 100644 --- a/llvm/include/llvm/MC/MCInstrDesc.h +++ b/llvm/include/llvm/MC/MCInstrDesc.h @@ -187,6 +187,7 @@ enum Flag { Trap, VariadicOpsAreDefs, Authenticated, + Phi, }; } // namespace MCID @@ -292,6 +293,10 @@ class MCInstrDesc { /// unconditional branches and return instructions. bool isBarrier() const { return Flags & (1ULL << MCID::Barrier); } + /// Returns true if this instruction acts as a PHI node. + /// Not all PHI operands need to dominates the definition. + bool isPhi() const { return Flags & (1ULL << MCID::Phi); } + /// Returns true if this instruction part of the terminator for /// a basic block. Typically this is things like return and branch /// instructions. diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index f5e62dda6fd04..b8a4b9bba3cf6 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -96,6 +96,7 @@ def G_PHI : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins variable_ops); let hasSideEffects = false; + let isPhi = true; } def G_FRAME_INDEX : GenericInstruction { diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 3e037affe1cfd..2b459f0df4228 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -635,6 +635,7 @@ class Instruction : InstructionEncoding { bit isBitcast = false; // Is this instruction a bitcast instruction? bit isSelect = false; // Is this instruction a select instruction? bit isBarrier = false; // Can control flow fall through this instruction? + bit isPhi = false; // Is this instruction a phi instruction? bit isCall = false; // Is this instruction a call instruction? bit isAdd = false; // Is this instruction an add instruction? bit isTrap = false; // Is this instruction a trap instruction? @@ -1174,6 +1175,7 @@ def PHI : StandardPseudoInstruction { let InOperandList = (ins variable_ops); let AsmString = "PHINODE"; let hasSideEffects = false; + let isPhi = true; } def INLINEASM : StandardPseudoInstruction { let OutOperandList = (outs); diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 24a0f41775cc1..ed843e7a7550f 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -3213,7 +3213,8 @@ void MachineVerifier::calcRegsRequired() { // Handle the PHI node. for (const MachineInstr &MI : MBB.phis()) { - for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2) { + for (unsigned i = MI.getIndexFirstPHIPair(), e = MI.getNumOperands(); + i != e; i += 2) { // Skip those Operands which are undef regs or not regs. if (!MI.getOperand(i).isReg() || !MI.getOperand(i).readsReg()) continue; @@ -3268,7 +3269,8 @@ void MachineVerifier::checkPHIOps(const MachineBasicBlock &MBB) { if (!DefReg.isVirtual()) report("Expected first PHI operand to be a virtual register", &MODef, 0); - for (unsigned I = 1, E = Phi.getNumOperands(); I != E; I += 2) { + for (unsigned I = Phi.getIndexFirstPHIPair(), E = Phi.getNumOperands(); + I != E; I += 2) { const MachineOperand &MO0 = Phi.getOperand(I); if (!MO0.isReg()) { report("Expected PHI operand to be a register", &MO0, I); diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index 51bacb00b1c51..6af0c857b1c58 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -615,8 +615,10 @@ def OpFwidthCoarse: UnOp<"OpFwidthCoarse", 215>; // 3.42.17 Control-Flow Instructions -def OpPhi: Op<245, (outs ID:$res), (ins TYPE:$type, ID:$var0, ID:$block0, variable_ops), - "$res = OpPhi $type $var0 $block0">; +let isPhi = 1 in { + def OpPhi: Op<245, (outs ID:$res), (ins TYPE:$type, ID:$var0, ID:$block0, variable_ops), + "$res = OpPhi $type $var0 $block0">; +} def OpLoopMerge: Op<246, (outs), (ins unknown:$merge, unknown:$continue, LoopControl:$lc, variable_ops), "OpLoopMerge $merge $continue $lc">; def OpSelectionMerge: Op<247, (outs), (ins unknown:$merge, SelectionControl:$sc), diff --git a/llvm/utils/TableGen/Common/CodeGenInstruction.cpp b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp index 452b084aa6f7d..a8ae77bcca3ef 100644 --- a/llvm/utils/TableGen/Common/CodeGenInstruction.cpp +++ b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp @@ -469,6 +469,7 @@ CodeGenInstruction::CodeGenInstruction(const Record *R) FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore"); variadicOpsAreDefs = R->getValueAsBit("variadicOpsAreDefs"); isAuthenticated = R->getValueAsBit("isAuthenticated"); + isPhi = R->getValueAsBit("isPhi"); bool Unset; mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); diff --git a/llvm/utils/TableGen/Common/CodeGenInstruction.h b/llvm/utils/TableGen/Common/CodeGenInstruction.h index 18294b157fedb..c6374ba3366ff 100644 --- a/llvm/utils/TableGen/Common/CodeGenInstruction.h +++ b/llvm/utils/TableGen/Common/CodeGenInstruction.h @@ -286,6 +286,7 @@ class CodeGenInstruction { bool hasChain_Inferred : 1; bool variadicOpsAreDefs : 1; bool isAuthenticated : 1; + bool isPhi : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp index 46605095ba85f..3bd4d051692b0 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -1240,6 +1240,8 @@ void InstrInfoEmitter::emitRecord( OS << "|(1ULL<