Index: llvm/include/llvm/CodeGen/MachineOperand.h =================================================================== --- llvm/include/llvm/CodeGen/MachineOperand.h +++ llvm/include/llvm/CodeGen/MachineOperand.h @@ -460,6 +460,16 @@ return !isUndef() && !isInternalRead() && (isUse() || getSubReg()); } + /// Return true if this operand can validly be appended to an arbitrary + /// operand list. i.e. this behaves like an implicit operand. + bool isValidExcessOperand() const { + if ((isReg() && isImplicit()) || isRegMask()) + return true; + + // Debug operands + return isMetadata() || isMCSymbol(); + } + //===--------------------------------------------------------------------===// // Mutators for Register Operands //===--------------------------------------------------------------------===// Index: llvm/lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -1094,11 +1094,23 @@ return true; } - // TODO: Check for extraneous machine operands. MI = MF.CreateMachineInstr(MCID, DebugLocation, /*NoImplicit=*/true); MI->setFlags(Flags); - for (const auto &Operand : Operands) + + unsigned NumExplicitOps = 0; + for (const auto &Operand : Operands) { + bool IsImplicitOp = Operand.Operand.isReg() && Operand.Operand.isImplicit(); + if (!IsImplicitOp) { + if (!MCID.isVariadic() && NumExplicitOps >= MCID.getNumOperands() && + !Operand.Operand.isValidExcessOperand()) + return error("too many operands for instruction"); + + ++NumExplicitOps; + } + MI->addOperand(MF, Operand.Operand); + } + if (assignRegisterTies(*MI, Operands)) return true; if (PreInstrSymbol) Index: llvm/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/lib/CodeGen/MachineInstr.cpp +++ llvm/lib/CodeGen/MachineInstr.cpp @@ -232,16 +232,12 @@ } } -#ifndef NDEBUG - bool isDebugOp = Op.getType() == MachineOperand::MO_Metadata || - Op.getType() == MachineOperand::MO_MCSymbol; // OpNo now points as the desired insertion point. Unless this is a variadic // instruction, only implicit regs are allowed beyond MCID->getNumOperands(). // RegMask operands go between the explicit and implicit operands. - assert((isImpReg || Op.isRegMask() || MCID->isVariadic() || - OpNo < MCID->getNumOperands() || isDebugOp) && + assert((MCID->isVariadic() || OpNo < MCID->getNumOperands() || + Op.isValidExcessOperand()) && "Trying to add an operand to a machine instr that is already done!"); -#endif MachineRegisterInfo *MRI = getRegInfo(); Index: llvm/test/CodeGen/MIR/AMDGPU/extra-imm-operand.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/MIR/AMDGPU/extra-imm-operand.mir @@ -0,0 +1,12 @@ +# RUN: not llc -march=amdgcn -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: extra_imm_operand +body: | + bb.0: + ; CHECK: [[@LINE+3]]:18: too many operands for instruction + ; CHECK-NEXT: S_ENDPGM 0, 0 + ; CHECK_NEXT: ^ + S_ENDPGM 0, 0 + +... Index: llvm/test/CodeGen/MIR/AMDGPU/extra-reg-operand.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/MIR/AMDGPU/extra-reg-operand.mir @@ -0,0 +1,12 @@ +# RUN: not llc -march=amdgcn -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: extra_reg_operand +body: | + bb.0: + ; CHECK: [[@LINE+3]]:29: too many operands for instruction + ; S_ENDPGM 0, undef $vgpr0 + ; CHECK_NEXT: ^ + S_ENDPGM 0, undef $vgpr0 + +...