Make sure IPSCCP never marks a tracked call as overdefined in SCCPSolver::ResolvedUndefsIn. If we do, we can end up in a situation where a function is resolved to return a constant, but the caller is marked overdefined, which confuses the code later.

<rdar://problem/9956541> (again).



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140210 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2011-09-20 23:28:51 +00:00
parent e97190fdf8
commit 79782fc864
2 changed files with 53 additions and 9 deletions

View File

@ -1433,15 +1433,25 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
if (I->getType()->isVoidTy()) continue;
if (StructType *STy = dyn_cast<StructType>(I->getType())) {
// Only a few things that can be structs matter for undef. Just send
// all their results to overdefined. We could be more precise than this
// but it isn't worth bothering.
if (!isa<ExtractValueInst>(I) && !isa<InsertValueInst>(I)) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
LatticeVal &LV = getStructValueState(I, i);
if (LV.isUndefined())
markOverdefined(LV, I);
}
// Only a few things that can be structs matter for undef.
// Tracked calls must never be marked overdefined in ResolvedUndefsIn.
if (CallSite CS = CallSite(I))
if (Function *F = CS.getCalledFunction())
if (MRVFunctionsTracked.count(F))
continue;
// extractvalue and insertvalue don't need to be marked; they are
// tracked as precisely as their operands.
if (isa<ExtractValueInst>(I) || isa<InsertValueInst>(I))
continue;
// Send the results of everything else to overdefined. We could be
// more precise than this but it isn't worth bothering.
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
LatticeVal &LV = getStructValueState(I, i);
if (LV.isUndefined())
markOverdefined(LV, I);
}
continue;
}
@ -1594,6 +1604,22 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
break;
markOverdefined(I);
return true;
case Instruction::Call:
case Instruction::Invoke: {
// There are two reasons a call can have an undef result
// 1. It could be tracked.
// 2. It could be constant-foldable.
// Because of the way we solve return values, tracked calls must
// never be marked overdefined in ResolvedUndefsIn.
if (Function *F = CallSite(I).getCalledFunction())
if (TrackedRetVals.count(F))
break;
// If the call is constant-foldable, we mark it overdefined because
// we do not know what return values are valid.
markOverdefined(I);
return true;
}
default:
// If we don't know what should happen here, conservatively mark it
// overdefined.

View File

@ -209,3 +209,21 @@ entry:
}
declare i32 @__gxx_personality_v0(...)
;;======================== test10
define i32 @test10a() nounwind {
entry:
%call = call i32 @test10b(i32 undef)
ret i32 %call
; CHECK: define i32 @test10a
; CHECK: ret i32 0
}
define internal i32 @test10b(i32 %x) nounwind {
entry:
%r = and i32 %x, 1
ret i32 %r
; CHECK: define internal i32 @test10b
; CHECK: ret i32 undef
}