[llvm] r274708 - [PM] Port TailCallElim
Sean Silva via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 6 16:48:41 PDT 2016
Author: silvas
Date: Wed Jul 6 18:48:41 2016
New Revision: 274708
URL: http://llvm.org/viewvc/llvm-project?rev=274708&view=rev
Log:
[PM] Port TailCallElim
Added:
llvm/trunk/include/llvm/Transforms/Scalar/TailRecursionElimination.h
Modified:
llvm/trunk/lib/Passes/PassBuilder.cpp
llvm/trunk/lib/Passes/PassRegistry.def
llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll
Added: llvm/trunk/include/llvm/Transforms/Scalar/TailRecursionElimination.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/TailRecursionElimination.h?rev=274708&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar/TailRecursionElimination.h (added)
+++ llvm/trunk/include/llvm/Transforms/Scalar/TailRecursionElimination.h Wed Jul 6 18:48:41 2016
@@ -0,0 +1,66 @@
+//===---- TailRecursionElimination.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file transforms calls of the current function (self recursion) followed
+// by a return instruction with a branch to the entry of the function, creating
+// a loop. This pass also implements the following extensions to the basic
+// algorithm:
+//
+// 1. Trivial instructions between the call and return do not prevent the
+// transformation from taking place, though currently the analysis cannot
+// support moving any really useful instructions (only dead ones).
+// 2. This pass transforms functions that are prevented from being tail
+// recursive by an associative and commutative expression to use an
+// accumulator variable, thus compiling the typical naive factorial or
+// 'fib' implementation into efficient code.
+// 3. TRE is performed if the function returns void, if the return
+// returns the result returned by the call, or if the function returns a
+// run-time constant on all exits from the function. It is possible, though
+// unlikely, that the return returns something else (like constant 0), and
+// can still be TRE'd. It can be TRE'd if ALL OTHER return instructions in
+// the function return the exact same value.
+// 4. If it can prove that callees do not access their caller stack frame,
+// they are marked as eligible for tail call elimination (by the code
+// generator).
+//
+// There are several improvements that could be made:
+//
+// 1. If the function has any alloca instructions, these instructions will be
+// moved out of the entry block of the function, causing them to be
+// evaluated each time through the tail recursion. Safely keeping allocas
+// in the entry block requires analysis to proves that the tail-called
+// function does not read or write the stack object.
+// 2. Tail recursion is only performed if the call immediately precedes the
+// return instruction. It's possible that there could be a jump between
+// the call and the return.
+// 3. There can be intervening operations between the call and the return that
+// prevent the TRE from occurring. For example, there could be GEP's and
+// stores to memory that will not be read or written by the call. This
+// requires some substantial analysis (such as with DSA) to prove safe to
+// move ahead of the call, but doing so could allow many more TREs to be
+// performed, for example in TreeAdd/TreeAlloc from the treeadd benchmark.
+// 4. The algorithm we use to detect if callees access their caller stack
+// frames is very primitive.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_TAILRECURSIONELIMINATION_H
+#define LLVM_TRANSFORMS_SCALAR_TAILRECURSIONELIMINATION_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct TailCallElimPass : PassInfoMixin<TailCallElimPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_TAILRECURSIONELIMINATION_H
Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=274708&r1=274707&r2=274708&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
+++ llvm/trunk/lib/Passes/PassBuilder.cpp Wed Jul 6 18:48:41 2016
@@ -98,6 +98,7 @@
#include "llvm/Transforms/Scalar/SROA.h"
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
#include "llvm/Transforms/Scalar/Sink.h"
+#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
#include "llvm/Transforms/Utils/AddDiscriminators.h"
#include "llvm/Transforms/Utils/LCSSA.h"
#include "llvm/Transforms/Utils/Mem2Reg.h"
Modified: llvm/trunk/lib/Passes/PassRegistry.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=274708&r1=274707&r2=274708&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/PassRegistry.def (original)
+++ llvm/trunk/lib/Passes/PassRegistry.def Wed Jul 6 18:48:41 2016
@@ -163,6 +163,7 @@ FUNCTION_PASS("simplify-cfg", SimplifyCF
FUNCTION_PASS("sink", SinkingPass())
FUNCTION_PASS("slp-vectorizer", SLPVectorizerPass())
FUNCTION_PASS("sroa", SROA())
+FUNCTION_PASS("tailcallelim", TailCallElimPass())
FUNCTION_PASS("verify", VerifierPass())
FUNCTION_PASS("verify<domtree>", DominatorTreeVerifierPass())
FUNCTION_PASS("verify<memoryssa>", MemorySSAVerifierPass())
Modified: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp?rev=274708&r1=274707&r2=274708&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Wed Jul 6 18:48:41 2016
@@ -50,6 +50,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -731,6 +732,9 @@ static bool processReturningBlock(Return
}
static bool eliminateTailRecursion(Function &F, const TargetTransformInfo *TTI) {
+ if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
+ return false;
+
bool MadeChange = false;
bool AllCallsAreTailCalls = false;
MadeChange |= markTails(F, AllCallsAreTailCalls);
@@ -800,8 +804,7 @@ struct TailCallElim : public FunctionPas
}
bool runOnFunction(Function &F) override {
- if (skipFunction(F) ||
- F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
+ if (skipFunction(F))
return false;
return eliminateTailRecursion(
@@ -821,3 +824,17 @@ INITIALIZE_PASS_END(TailCallElim, "tailc
FunctionPass *llvm::createTailCallEliminationPass() {
return new TailCallElim();
}
+
+PreservedAnalyses TailCallElimPass::run(Function &F,
+ FunctionAnalysisManager &AM) {
+
+ TargetTransformInfo &TTI = AM.getResult<TargetIRAnalysis>(F);
+
+ bool Changed = eliminateTailRecursion(F, &TTI);
+
+ if (!Changed)
+ return PreservedAnalyses::all();
+ PreservedAnalyses PA;
+ PA.preserve<GlobalsAA>();
+ return PA;
+}
Modified: llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll?rev=274708&r1=274707&r2=274708&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll (original)
+++ llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll Wed Jul 6 18:48:41 2016
@@ -1,4 +1,5 @@
; RUN: opt < %s -tailcallelim -S | FileCheck %s
+; RUN: opt < %s -passes=tailcallelim -S | FileCheck %s
define i32 @test1_factorial(i32 %x) {
entry:
More information about the llvm-commits
mailing list