summaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/TailRecursionElimination.cpp
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2009-11-07 21:10:15 +0000
committerNick Lewycky <nicholas@mxc.ca>2009-11-07 21:10:15 +0000
commitf80fcd00b3590626a6110fe5fbe9b5fd2a8be1ae (patch)
tree9090f3aa1b8170993671f2479436182b6ee9fc09 /lib/Transforms/Scalar/TailRecursionElimination.cpp
parentbf992817f28bdab09fe1d1349561efb0c89fb0dd (diff)
downloadllvm-f80fcd00b3590626a6110fe5fbe9b5fd2a8be1ae.tar.gz
llvm-f80fcd00b3590626a6110fe5fbe9b5fd2a8be1ae.tar.bz2
llvm-f80fcd00b3590626a6110fe5fbe9b5fd2a8be1ae.tar.xz
Improve tail call elimination to handle the switch statement.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86403 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/TailRecursionElimination.cpp')
-rw-r--r--lib/Transforms/Scalar/TailRecursionElimination.cpp13
1 files changed, 11 insertions, 2 deletions
diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp
index e05991373a..4119cb9db4 100644
--- a/lib/Transforms/Scalar/TailRecursionElimination.cpp
+++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp
@@ -234,7 +234,7 @@ bool TailCallElim::CanMoveAboveCall(Instruction *I, CallInst *CI) {
// We currently handle static constants and arguments that are not modified as
// part of the recursion.
//
-static bool isDynamicConstant(Value *V, CallInst *CI) {
+static bool isDynamicConstant(Value *V, CallInst *CI, ReturnInst *RI) {
if (isa<Constant>(V)) return true; // Static constants are always dyn consts
// Check to see if this is an immutable argument, if so, the value
@@ -252,6 +252,15 @@ static bool isDynamicConstant(Value *V, CallInst *CI) {
if (CI->getOperand(ArgNo+1) == Arg)
return true;
}
+
+ // Switch cases are always constant integers. If the value is being switched
+ // on and the return is only reachable from one of its cases, it's
+ // effectively constant.
+ if (BasicBlock *UniquePred = RI->getParent()->getUniquePredecessor())
+ if (SwitchInst *SI = dyn_cast<SwitchInst>(UniquePred->getTerminator()))
+ if (SI->getCondition() == V)
+ return SI->getDefaultDest() != RI->getParent();
+
// Not a constant or immutable argument, we can't safely transform.
return false;
}
@@ -273,7 +282,7 @@ static Value *getCommonReturnValue(ReturnInst *TheRI, CallInst *CI) {
// evaluatable at the start of the initial invocation of the function,
// instead of at the end of the evaluation.
//
- if (!isDynamicConstant(RetOp, CI))
+ if (!isDynamicConstant(RetOp, CI, RI))
return 0;
if (ReturnedValue && RetOp != ReturnedValue)