[llvm] [TailRecElim] Introduce support for shift accumulator optimization (PR #181331)
Federico Bruzzone via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 11 09:00:04 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
----------------
FedericoBruzzone wrote:
Good catch, I hadn't looked at the output of `utils/update_test_checks.py`.
The regression came from inverting the original logic: instead of skipping returns that depend on the recursive call, the pattern-match version bailed out on them, and after `FoldReturnIntoUncondBranch` the candidate block ends in ret (`shl %call, C`), which matches none of the patterns. The PHI/select matching was indeed useless: by that point the merged-return PHI has already been simplified to a constant return.
We don't need worklist: `getReturnValue` fails closed on any non-constant return, so a depth-1 check is enough. The returns we must skip use the call as an immediate operand. Adopted your suggestion (also matching V itself being a recursive call, to keep the old behavior for plain ret f(x-1) siblings).
https://github.com/llvm/llvm-project/pull/181331
More information about the llvm-commits
mailing list