summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-09-20 23:28:51 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-09-20 23:28:51 +0000
commit79782fc8649e081b59fe2f96265042eaec1542a7 (patch)
treec02f594c33d6dd57ee8382490e31e7eaa2bc7c44
parente97190fdf875843e8161a942f2046fd3ef81330f (diff)
downloadllvm-79782fc8649e081b59fe2f96265042eaec1542a7.tar.gz
llvm-79782fc8649e081b59fe2f96265042eaec1542a7.tar.bz2
llvm-79782fc8649e081b59fe2f96265042eaec1542a7.tar.xz
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
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp44
-rw-r--r--test/Transforms/SCCP/ipsccp-basic.ll18
2 files changed, 53 insertions, 9 deletions
diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp
index 02e6b72d3a..196a847fc0 100644
--- a/lib/Transforms/Scalar/SCCP.cpp
+++ b/lib/Transforms/Scalar/SCCP.cpp
@@ -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.
diff --git a/test/Transforms/SCCP/ipsccp-basic.ll b/test/Transforms/SCCP/ipsccp-basic.ll
index 6ccfd98234..8340f0c1e1 100644
--- a/test/Transforms/SCCP/ipsccp-basic.ll
+++ b/test/Transforms/SCCP/ipsccp-basic.ll
@@ -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
+}