[llvm] [TailRecElim] Introduce support for shift accumulator optimization (PR #181331)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 25 06:49:38 PDT 2026
================
@@ -374,29 +374,117 @@ static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA) {
return !is_contained(I->operands(), CI);
}
-static bool canTransformAccumulatorRecursion(Instruction *I, CallInst *CI) {
- if (!I->isAssociative() || !I->isCommutative())
+// While shifts are neither associative nor commutative, a chain of shifts by a
+// constant amount C is equivalent to a single shift by the sum of the amounts:
+// ... (Base << C) << C) ... << C == Base << (C * Iterations)
+// This relation applies to left shifts as well as arithmetic/logical right
+// shifts when the shift amount is a constant.
+static bool isPseudoAssociative(Instruction *I) {
+ if (!I->isShift())
return false;
+ return isa<ConstantInt>(I->getOperand(1));
+}
+
+// Return true if V is a recursive call to F or an instruction directly using
+// the result of one. A depth-1 check is enough here: the value feeding a
+// return either uses the recursive call as an immediate operand (the
+// accumulator instruction, or the PHI merging it with the base case), or it
+// is rejected by getReturnValue below as a non-constant anyway.
+static bool usesRecursiveCall(Value *V, Function &F) {
+ auto IsRecursiveCall = [&F](Value *V) {
+ auto *CI = dyn_cast<CallInst>(V);
+ return CI && CI->getCalledFunction() == &F;
+ };
+ if (IsRecursiveCall(V))
+ return true;
+ auto *I = dyn_cast<Instruction>(V);
+ return I && llvm::any_of(I->operands(), IsRecursiveCall);
+}
+
+// Find the base-case return value for function F: examine all return
+// instructions, skipping those whose return value depends on a recursive call
+// to F (that value differs for each iteration of the recursion). If the
+// remaining returns yield exactly one distinct constant, return it; otherwise
+// return nullptr to indicate failure.
+//
+// FIXME: There is a room for improvement here in the future, e.g., consider
+// non-constant values and multiple base cases -- e.g., we want to be able to
+// handle code like:
+// ```
+// int f(int x) {
+// if (x == 1) return 1;
+// if (x == 10) return 10;
+// return f(x-1) << 1;
+// }
+// ```
+static Constant *getReturnValue(Function &F) {
----------------
antoniofrighetto wrote:
s/getReturnValue/findBaseCaseRetConstant/g
https://github.com/llvm/llvm-project/pull/181331
More information about the llvm-commits
mailing list