diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index bf4882044b64..f83cdfba5aac 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -215,7 +215,6 @@ namespace { const LiveInterval &LI); void verifyInlineAsm(const MachineInstr *MI); - void verifyTiedOperands(const MachineInstr *MI); void checkLiveness(const MachineOperand *MO, unsigned MONum); void markReachable(const MachineBasicBlock *MBB); @@ -742,38 +741,6 @@ void MachineVerifier::verifyInlineAsm(const MachineInstr *MI) { } } -// Verify the consistency of tied operands. -void MachineVerifier::verifyTiedOperands(const MachineInstr *MI) { - const MCInstrDesc &MCID = MI->getDesc(); - SmallVector Defs; - SmallVector Uses; - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isTied()) - continue; - if (MO.isDef()) { - Defs.push_back(i); - continue; - } - Uses.push_back(i); - if (Defs.size() < Uses.size()) { - report("No tied def for tied use", &MO, i); - break; - } - if (i >= MCID.getNumOperands()) - continue; - int DefIdx = MCID.getOperandConstraint(i, MCOI::TIED_TO); - if (unsigned(DefIdx) != Defs[Uses.size() - 1]) { - report(" def doesn't match MCInstrDesc", &MO, i); - *OS << "Descriptor says tied def should be operand " << DefIdx << ".\n"; - } - } - if (Defs.size() > Uses.size()) { - unsigned i = Defs[Uses.size() - 1]; - report("No tied use for tied def", &MI->getOperand(i), i); - } -} - void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { const MCInstrDesc &MCID = MI->getDesc(); if (MI->getNumOperands() < MCID.getNumOperands()) { @@ -785,8 +752,6 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { // Check the tied operands. if (MI->isInlineAsm()) verifyInlineAsm(MI); - else - verifyTiedOperands(MI); // Check the MachineMemOperands for basic consistency. for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), @@ -844,11 +809,14 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { report("Explicit operand marked as implicit", MO, MONum); } - if (MCID.getOperandConstraint(MONum, MCOI::TIED_TO) != -1) { + int TiedTo = MCID.getOperandConstraint(MONum, MCOI::TIED_TO); + if (TiedTo != -1) { if (!MO->isReg()) report("Tied use must be a register", MO, MONum); else if (!MO->isTied()) report("Operand should be tied", MO, MONum); + else if (unsigned(TiedTo) != MI->findTiedOperandIdx(MONum)) + report("Tied def doesn't match MCInstrDesc", MO, MONum); } else if (MO->isReg() && MO->isTied()) report("Explicit operand should not be tied", MO, MONum); } else { @@ -865,6 +833,28 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { if (MRI->tracksLiveness() && !MI->isDebugValue()) checkLiveness(MO, MONum); + // Verify the consistency of tied operands. + if (MO->isTied()) { + unsigned OtherIdx = MI->findTiedOperandIdx(MONum); + const MachineOperand &OtherMO = MI->getOperand(OtherIdx); + if (!OtherMO.isReg()) + report("Must be tied to a register", MO, MONum); + if (!OtherMO.isTied()) + report("Missing tie flags on tied operand", MO, MONum); + if (MI->findTiedOperandIdx(OtherIdx) != MONum) + report("Inconsistent tie links", MO, MONum); + if (MONum < MCID.getNumDefs()) { + if (OtherIdx < MCID.getNumOperands()) { + if (-1 == MCID.getOperandConstraint(OtherIdx, MCOI::TIED_TO)) + report("Explicit def tied to explicit use without tie constraint", + MO, MONum); + } else { + if (!OtherMO.isImplicit()) + report("Explicit def should be tied to implicit use", MO, MONum); + } + } + } + // Verify two-address constraints after leaving SSA form. unsigned DefIdx; if (!MRI->isSSA() && MO->isUse() && diff --git a/llvm/test/CodeGen/PowerPC/inlineasm-copy.ll b/llvm/test/CodeGen/PowerPC/inlineasm-copy.ll index e1ff82d5f9b7..59c338883561 100644 --- a/llvm/test/CodeGen/PowerPC/inlineasm-copy.ll +++ b/llvm/test/CodeGen/PowerPC/inlineasm-copy.ll @@ -1,5 +1,6 @@ -; RUN: llc < %s -march=ppc32 | not grep mr +; RUN: llc < %s -march=ppc32 -verify-machineinstrs | FileCheck %s +; CHECK-NOT: mr define i32 @test(i32 %Y, i32 %X) { entry: %tmp = tail call i32 asm "foo $0", "=r"( ) ; [#uses=1] @@ -12,3 +13,9 @@ entry: ret i32 %tmp1 } +; CHECK: test3 +define i32 @test3(i32 %Y, i32 %X) { +entry: + %tmp1 = tail call { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } asm sideeffect "foo $0, $1", "=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19"( i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y, i32 %X, i32 %Y ) ; [#uses=1] + ret i32 1 +}