Dan noticed that the verifier wasn't thoroughly checking uses of

invoke results (see the testcases).  Tighten up the checking.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72586 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2009-05-29 19:39:36 +00:00
parent d80ddc0b64
commit 44008257a4
4 changed files with 99 additions and 50 deletions

View File

@ -1244,8 +1244,7 @@ void Verifier::visitInstruction(Instruction &I) {
if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential
for (Value::use_iterator UI = I.use_begin(), UE = I.use_end(); for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
UI != UE; ++UI) UI != UE; ++UI)
Assert1(*UI != (User*)&I || Assert1(*UI != (User*)&I || !DT->isReachableFromEntry(BB),
!DT->dominates(&BB->getParent()->getEntryBlock(), BB),
"Only PHI nodes may reference their own value!", &I); "Only PHI nodes may reference their own value!", &I);
} }
@ -1306,67 +1305,67 @@ void Verifier::visitInstruction(Instruction &I) {
BasicBlock *OpBlock = Op->getParent(); BasicBlock *OpBlock = Op->getParent();
// Check that a definition dominates all of its uses. // Check that a definition dominates all of its uses.
if (!isa<PHINode>(I)) { if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) {
// Invoke results are only usable in the normal destination, not in the // Invoke results are only usable in the normal destination, not in the
// exceptional destination. // exceptional destination.
if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { BasicBlock *NormalDest = II->getNormalDest();
OpBlock = II->getNormalDest();
Assert2(NormalDest != II->getUnwindDest(),
Assert2(OpBlock != II->getUnwindDest(), "No uses of invoke possible due to dominance structure!",
"No uses of invoke possible due to dominance structure!", Op, &I);
Op, II);
// PHI nodes differ from other nodes because they actually "use" the
// value in the predecessor basic blocks they correspond to.
BasicBlock *UseBlock = BB;
if (isa<PHINode>(I))
UseBlock = cast<BasicBlock>(I.getOperand(i+1));
if (isa<PHINode>(I) && UseBlock == OpBlock) {
// Special case of a phi node in the normal destination or the unwind
// destination.
Assert2(BB == NormalDest || !DT->isReachableFromEntry(UseBlock),
"Invoke result not available in the unwind destination!",
Op, &I);
} else {
Assert2(DT->dominates(NormalDest, UseBlock) ||
!DT->isReachableFromEntry(UseBlock),
"Invoke result does not dominate all uses!", Op, &I);
// If the normal successor of an invoke instruction has multiple // If the normal successor of an invoke instruction has multiple
// predecessors, then the normal edge from the invoke is critical, so // predecessors, then the normal edge from the invoke is critical,
// the invoke value can only be live if the destination block // so the invoke value can only be live if the destination block
// dominates all of it's predecessors (other than the invoke) or if // dominates all of it's predecessors (other than the invoke).
// the invoke value is only used by a phi in the successor. if (!NormalDest->getSinglePredecessor() &&
if (!OpBlock->getSinglePredecessor() && DT->isReachableFromEntry(UseBlock))
DT->dominates(&BB->getParent()->getEntryBlock(), BB)) {
// The first case we allow is if the use is a PHI operand in the
// normal block, and if that PHI operand corresponds to the invoke's
// block.
bool Bad = true;
if (PHINode *PN = dyn_cast<PHINode>(&I))
if (PN->getParent() == OpBlock &&
PN->getIncomingBlock(i/2) == Op->getParent())
Bad = false;
// If it is used by something non-phi, then the other case is that // If it is used by something non-phi, then the other case is that
// 'OpBlock' dominates all of its predecessors other than the // 'NormalDest' dominates all of its predecessors other than the
// invoke. In this case, the invoke value can still be used. // invoke. In this case, the invoke value can still be used.
if (Bad) { for (pred_iterator PI = pred_begin(NormalDest),
Bad = false; E = pred_end(NormalDest); PI != E; ++PI)
for (pred_iterator PI = pred_begin(OpBlock), if (*PI != II->getParent() && !DT->dominates(NormalDest, *PI) &&
E = pred_end(OpBlock); PI != E; ++PI) { DT->isReachableFromEntry(*PI)) {
if (*PI != II->getParent() && !DT->dominates(OpBlock, *PI)) { CheckFailed("Invoke result does not dominate all uses!", Op,&I);
Bad = true; return;
break;
}
} }
} }
Assert2(!Bad, } else if (isa<PHINode>(I)) {
"Invoke value defined on critical edge but not dead!", &I, // PHI nodes are more difficult than other nodes because they actually
Op); // "use" the value in the predecessor basic blocks they correspond to.
} BasicBlock *PredBB = cast<BasicBlock>(I.getOperand(i+1));
} else if (OpBlock == BB) { Assert2(DT->dominates(OpBlock, PredBB) ||
!DT->isReachableFromEntry(PredBB),
"Instruction does not dominate all uses!", Op, &I);
} else {
if (OpBlock == BB) {
// If they are in the same basic block, make sure that the definition // If they are in the same basic block, make sure that the definition
// comes before the use. // comes before the use.
Assert2(InstsInThisBlock.count(Op) || Assert2(InstsInThisBlock.count(Op) || !DT->isReachableFromEntry(BB),
!DT->dominates(&BB->getParent()->getEntryBlock(), BB),
"Instruction does not dominate all uses!", Op, &I); "Instruction does not dominate all uses!", Op, &I);
} }
// Definition must dominate use unless use is unreachable! // Definition must dominate use unless use is unreachable!
Assert2(InstsInThisBlock.count(Op) || DT->dominates(Op, &I) || Assert2(InstsInThisBlock.count(Op) || DT->dominates(Op, &I) ||
!DT->dominates(&BB->getParent()->getEntryBlock(), BB), !DT->isReachableFromEntry(BB),
"Instruction does not dominate all uses!", Op, &I);
} else {
// PHI nodes are more difficult than other nodes because they actually
// "use" the value in the predecessor basic blocks they correspond to.
BasicBlock *PredBB = cast<BasicBlock>(I.getOperand(i+1));
Assert2(DT->dominates(OpBlock, PredBB) ||
!DT->dominates(&BB->getParent()->getEntryBlock(), PredBB),
"Instruction does not dominate all uses!", Op, &I); "Instruction does not dominate all uses!", Op, &I);
} }
} else if (isa<InlineAsm>(I.getOperand(i))) { } else if (isa<InlineAsm>(I.getOperand(i))) {

View File

@ -0,0 +1,15 @@
; RUN: not llvm-as < %s >& /dev/null
declare i32 @v()
define i32 @f() {
e:
%r = invoke i32 @v()
to label %c unwind label %u ; <i32> [#uses=2]
c: ; preds = %e
ret i32 %r
u: ; preds = %e
ret i32 %r
}

View File

@ -0,0 +1,16 @@
; RUN: not llvm-as < %s >& /dev/null
declare i32 @v()
define i32 @g() {
e:
%s = invoke i32 @v()
to label %c unwind label %u ; <i32> [#uses=2]
c: ; preds = %e
ret i32 %s
u: ; preds = %e
%t = phi i32 [ %s, %e ] ; <i32> [#uses=1]
ret i32 %t
}

View File

@ -0,0 +1,19 @@
; RUN: not llvm-as < %s >& /dev/null
declare i32 @v()
define i32 @h() {
e:
%s = invoke i32 @v()
to label %c unwind label %u ; <i32> [#uses=2]
c: ; preds = %e
br label %d
d: ; preds = %u, %c
%p = phi i32 [ %s, %c ], [ %s, %u ] ; <i32> [#uses=1]
ret i32 %p
u: ; preds = %e
br label %d
}