[llvm-commits] CVS: llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp
Chris Lattner
lattner at cs.uiuc.edu
Mon Dec 8 17:38:01 PST 2003
Changes in directory llvm/lib/Transforms/Scalar:
TailRecursionElimination.cpp updated: 1.10 -> 1.11
---
Log message:
Implement: TailCallElim/accum_recursion_constant_arg.ll
Also make sure to clean up any PHI nodes that are inserted which are pointless.
---
Diffs of the changes: (+60 -6)
Index: llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp
diff -u llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp:1.10 llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp:1.11
--- llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp:1.10 Mon Dec 8 17:19:26 2003
+++ llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp Mon Dec 8 17:37:35 2003
@@ -89,6 +89,36 @@
if (ReturnInst *Ret = dyn_cast<ReturnInst>(BB->getTerminator()))
MadeChange |= ProcessReturningBlock(Ret, OldEntry, ArgumentPHIs);
+ // If we eliminated any tail recursions, it's possible that we inserted some
+ // silly PHI nodes which just merge an initial value (the incoming operand)
+ // with themselves. Check to see if we did and clean up our mess if so. This
+ // occurs when a function passes an argument straight through to its tail
+ // call.
+ if (!ArgumentPHIs.empty()) {
+ unsigned NumIncoming = ArgumentPHIs[0]->getNumIncomingValues();
+ for (unsigned i = 0, e = ArgumentPHIs.size(); i != e; ++i) {
+ PHINode *PN = ArgumentPHIs[i];
+ Value *V = 0;
+ for (unsigned op = 0, e = NumIncoming; op != e; ++op) {
+ Value *Op = PN->getIncomingValue(op);
+ if (Op != PN) {
+ if (V == 0) {
+ V = Op; // First value seen?
+ } else if (V != Op) {
+ V = 0;
+ break;
+ }
+ }
+ }
+
+ // If the PHI Node is a dynamic constant, replace it with the value it is.
+ if (V) {
+ PN->replaceAllUsesWith(V);
+ PN->getParent()->getInstList().erase(PN);
+ }
+ }
+ }
+
return MadeChange;
}
@@ -143,16 +173,40 @@
for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI)
if (ReturnInst *RI = dyn_cast<ReturnInst>(BBI->getTerminator())) {
Value *RetOp = RI->getOperand(0);
- if (isa<Constant>(RetOp)) {
+ if (RetOp != I) { // Ignore the one returning I.
+ // We can only perform this transformation if the value returned is
+ // evaluatable at the start of the initial invocation of the function,
+ // instead of at the end of the evaluation.
+ //
+ // We currently handle static constants and arguments that are not
+ // modified as part of the recursion.
+ if (!isa<Constant>(RetOp)) { // Constants are always ok
+ // Check to see if this is an immutable argument, if so, the value
+ // will be available to initialize the accumulator.
+ if (Argument *Arg = dyn_cast<Argument>(RetOp)) {
+ // Figure out which argument number this is...
+ unsigned ArgNo = 0;
+ for (Function::aiterator AI = F->abegin(); &*AI != Arg; ++AI)
+ ++ArgNo;
+
+ // If we are passing this argument into call as the corresponding
+ // argument operand, then the argument is dynamically constant.
+ // Otherwise, we cannot transform this function safely.
+ if (CI->getOperand(ArgNo+1) != Arg)
+ return 0;
+
+ } else {
+ // Not a constant or immutable argument, we can't safely transform.
+ return 0;
+ }
+ }
+
if (ReturnedValue && RetOp != ReturnedValue)
- return 0; // Cannot transform if differing constants are returned.
+ return 0; // Cannot transform if differing values are returned.
ReturnedValue = RetOp;
-
- } else if (RetOp != I) { // Ignore the one returning I.
- return 0; // Not returning a constant, cannot transform.
}
}
-
+
// Ok, if we passed this battery of tests, we can perform accumulator
// recursion elimination.
return ReturnedValue;
More information about the llvm-commits
mailing list