[llvm] [TailRecElim] Introduce support for shift accumulator optimization (PR #181331)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 03:52:01 PDT 2026
================
@@ -0,0 +1,179 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes="tailcallelim" -verify-dom-info -S | FileCheck %s
+
+; NOTE: All the following test cases are generate from the underlying C code (-O1)
+; before that the shift accumulator optimization was implemented
+
+
+
+; InstCombine strength-reduce `f(x-1) + f(x-1)` to shl:
+; int f(int x) {
+; if (x == 1) return 7;
+; return f(x-1) + f(x-1); // f(x-1) * 2
+; }
+define i32 @test_shl_const_accumulator(i32 %x) {
+; CHECK-LABEL: define i32 @test_shl_const_accumulator(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[TAILRECURSE:.*:]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 1
+; CHECK-NEXT: br i1 [[CMP]], label %[[COMMON_RET:.*]], label %[[IF_END:.*]]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret i32 7
+; CHECK: [[IF_END]]:
+; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[X]], -1
+; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = tail call i32 @test_shl_const_accumulator(i32 [[SUB]])
+; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[ACCUMULATOR_TR]], 1
----------------
antoniofrighetto wrote:
Hmm, it looks like we actually lost the tail elimination while trying to replace walking the use-def chain starting from the return value with the pattern match (01dc728e94ec86ff6c710b2bf0f3c5fc8799109e), this call shouldn't be here.
Looking at this better, possibly pattern-matching the PHI/select here is not anything useful. Could you please evaluate whether we actually need a worklist here? If we just need to check whether the shift is using the result of the recursive call, maybe we could go with something along the following lines?
```cpp
static bool usesRecursiveCall(Value *V, Function &F) {
auto *I = dyn_cast<Instruction>(V);
if (!I)
return false;
for (Use &U : I->operands())
if (auto *CI = dyn_cast<CallInst>(U.get()))
if (CI->getCalledFunction() == &F)
return true;
return false;
}
```
https://github.com/llvm/llvm-project/pull/181331
More information about the llvm-commits
mailing list