llvm.org GIT mirror llvm / daf2128
Avoid tail recursion elimination across calls with operand bundles Summary: In some specific scenarios with well understood operand bundle types (like `"deopt"`) it may be possible to go ahead and convert recursion to iteration, but TailRecursionElimination does not have that logic today so avoid doing the right thing for now. I need some input on whether `"funclet"` operand bundles should also block tail recursion elimination. If not, I'll allow TRE across calls with `"funclet"` operand bundles and add a test case. Reviewers: rnk, majnemer, nlewycky, ahatanak Subscribers: mcrosier, llvm-commits Differential Revision: https://reviews.llvm.org/D26270 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286147 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 2 years ago
2 changed file(s) with 59 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
235235 if (!CI || CI->isTailCall())
236236 continue;
237237
238 bool IsNoTail = CI->isNoTailCall();
238 bool IsNoTail = CI->isNoTailCall() || CI->hasOperandBundles();
239239
240240 if (!IsNoTail && CI->doesNotAccessMemory()) {
241241 // A call to a readnone function whose arguments are all things computed
255255 SafeToTail = false;
256256 break;
257257 }
258 SafeToTail &= CI->hasOperandBundles();
258259 if (SafeToTail) {
259260 emitOptimizationRemark(
260261 F.getContext(), "tailcallelim", F, CI->getDebugLoc(),
0 ; RUN: opt < %s -tailcallelim -S | FileCheck %s
1
2 define i32 @f_1(i32 %x) {
3 ; CHECK-LABEL: @f_1(
4 wentry:
5 %cond = icmp ugt i32 %x, 0
6 br i1 %cond, label %return, label %body
7
8 body:
9 ; CHECK: body:
10 ; CHECK: call i32 @f_1(i32 %y) [ "deopt"() ]
11 %y = add i32 %x, 1
12 %tmp = call i32 @f_1(i32 %y) [ "deopt"() ]
13 ret i32 0
14
15 return:
16 ret i32 1
17 }
18
19 define i32 @f_2(i32 %x) {
20 ; CHECK-LABEL: @f_2
21
22 entry:
23 %cond = icmp ugt i32 %x, 0
24 br i1 %cond, label %return, label %body
25
26 body:
27 ; CHECK: body:
28 ; CHECK: call i32 @f_2(i32 %y) [ "unknown"() ]
29 %y = add i32 %x, 1
30 %tmp = call i32 @f_2(i32 %y) [ "unknown"() ]
31 ret i32 0
32
33 return:
34 ret i32 1
35 }
36
37 declare void @func()
38
39 define void @f_3(i1 %B) personality i8 42 {
40 ; CHECK-LABEL: @f_3(
41 entry:
42 invoke void @func()
43 to label %exit unwind label %merge
44 merge:
45 %cs1 = catchswitch within none [label %catch] unwind to caller
46
47 catch:
48 ; CHECK: catch:
49 ; CHECK: call void @f_3(i1 %B) [ "funclet"(token %cp) ]
50 %cp = catchpad within %cs1 []
51 call void @f_3(i1 %B) [ "funclet"(token %cp) ]
52 ret void
53
54 exit:
55 ret void
56 }