Skip to content

Commit 7cb15b2

Browse files
[CGP] Consider arguments and ret values in dupRetToEnableTailCallOpts
Hint further tail call optimization opportunities when the examined returned value is either the return value of a call instruction, or a function argument. Moreover, take into account the cases in which incoming values from phi-nodes, not directly tail call instructions, may still be simplified. Fixes: #75455.
1 parent 225ccca commit 7cb15b2

File tree

4 files changed

+85
-44
lines changed

4 files changed

+85
-44
lines changed

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,7 +2523,8 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) {
25232523
}
25242524

25252525
/// Look for opportunities to duplicate return instructions to the predecessor
2526-
/// to enable tail call optimizations. The case it is currently looking for is:
2526+
/// to enable tail call optimizations. The case it is currently looking for are
2527+
/// simple return of call values, function arguments, or phi nodes as follows:
25272528
/// @code
25282529
/// bb0:
25292530
/// %tmp0 = tail call i32 @f0()
@@ -2580,7 +2581,7 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB,
25802581
}
25812582

25822583
PN = dyn_cast<PHINode>(V);
2583-
if (!PN)
2584+
if (!PN && !isa<Argument>(V) && !isa<CallInst>(V))
25842585
return false;
25852586
}
25862587

@@ -2620,8 +2621,58 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB,
26202621
// Make sure the phi value is indeed produced by the tail call.
26212622
if (CI && CI->hasOneUse() && CI->getParent() == PredBB &&
26222623
TLI->mayBeEmittedAsTailCall(CI) &&
2623-
attributesPermitTailCall(F, CI, RetI, *TLI))
2624+
attributesPermitTailCall(F, CI, RetI, *TLI)) {
26242625
TailCallBBs.push_back(PredBB);
2626+
} else {
2627+
/// Consider the cases in which the phi value is indirectly produced by
2628+
/// the tail call, for example when encountering memset(), memmove(),
2629+
/// strcpy(), whose return value may have been optimized out. In such
2630+
/// cases, the value needs to be the first function argument.
2631+
/// @code
2632+
/// bb0:
2633+
/// tail call void @llvm.memset.p0.i64(ptr %0, i8 0, i64 %1)
2634+
/// br label %return
2635+
/// return:
2636+
/// %phi = phi ptr [ %0, %bb0 ], [ %2, %entry ]
2637+
/// @endcode
2638+
if (PredBB && PredBB->getSingleSuccessor() == BB)
2639+
CI = dyn_cast_or_null<CallInst>(
2640+
PredBB->getTerminator()->getPrevNonDebugInstruction(true));
2641+
2642+
bool IsIntrinsicOrLibFuncToBeTailCalled = false;
2643+
if (CI && CI->use_empty() && CI->hasArgument(IncomingVal) &&
2644+
IncomingVal == CI->getArgOperand(0)) {
2645+
if (const auto *II = dyn_cast<IntrinsicInst>(CI))
2646+
switch (II->getIntrinsicID()) {
2647+
case Intrinsic::memset:
2648+
case Intrinsic::memcpy:
2649+
case Intrinsic::memmove:
2650+
IsIntrinsicOrLibFuncToBeTailCalled = true;
2651+
[[fallthrough]];
2652+
default:
2653+
break;
2654+
}
2655+
2656+
LibFunc LF;
2657+
Function *Callee = CI->getCalledFunction();
2658+
if (Callee && TLInfo && TLInfo->getLibFunc(*Callee, LF))
2659+
switch (LF) {
2660+
case LibFunc_strcpy:
2661+
case LibFunc_strncpy:
2662+
case LibFunc_strcat:
2663+
case LibFunc_strncat:
2664+
IsIntrinsicOrLibFuncToBeTailCalled = true;
2665+
[[fallthrough]];
2666+
default:
2667+
break;
2668+
}
2669+
}
2670+
2671+
if (IsIntrinsicOrLibFuncToBeTailCalled &&
2672+
TLI->mayBeEmittedAsTailCall(CI) &&
2673+
attributesPermitTailCall(F, CI, RetI, *TLI))
2674+
TailCallBBs.push_back(PredBB);
2675+
}
26252676
}
26262677
} else {
26272678
SmallPtrSet<BasicBlock *, 4> VisitedBBs;

llvm/test/CodeGen/Thumb2/constant-islands-cbz.ll

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ define ptr @test(ptr returned %this, i32 %event_size, ptr %event_pointer) {
88
; CHECK-T1-NEXT: .save {r4, lr}
99
; CHECK-T1-NEXT: push {r4, lr}
1010
; CHECK-T1-NEXT: mov r4, r0
11-
; CHECK-T1-NEXT: movs r0, #0
12-
; CHECK-T1-NEXT: str r0, [r4, #4]
13-
; CHECK-T1-NEXT: str r0, [r4, #8]
14-
; CHECK-T1-NEXT: str r0, [r4, #12]
15-
; CHECK-T1-NEXT: str r0, [r4, #16]
16-
; CHECK-T1-NEXT: mov r0, r4
11+
; CHECK-T1-NEXT: movs r3, #0
12+
; CHECK-T1-NEXT: str r3, [r0, #4]
13+
; CHECK-T1-NEXT: str r3, [r0, #8]
14+
; CHECK-T1-NEXT: str r3, [r0, #12]
15+
; CHECK-T1-NEXT: str r3, [r0, #16]
1716
; CHECK-T1-NEXT: cbz r2, .LBB0_2
1817
; CHECK-T1-NEXT: @ %bb.1: @ %if.else
1918
; CHECK-T1-NEXT: bl equeue_create_inplace
@@ -28,11 +27,10 @@ define ptr @test(ptr returned %this, i32 %event_size, ptr %event_pointer) {
2827
; CHECK-T2: @ %bb.0: @ %entry
2928
; CHECK-T2-NEXT: .save {r4, lr}
3029
; CHECK-T2-NEXT: push {r4, lr}
30+
; CHECK-T2-NEXT: movs r3, #0
3131
; CHECK-T2-NEXT: mov r4, r0
32-
; CHECK-T2-NEXT: movs r0, #0
33-
; CHECK-T2-NEXT: strd r0, r0, [r4, #4]
34-
; CHECK-T2-NEXT: strd r0, r0, [r4, #12]
35-
; CHECK-T2-NEXT: mov r0, r4
32+
; CHECK-T2-NEXT: strd r3, r3, [r0, #4]
33+
; CHECK-T2-NEXT: strd r3, r3, [r0, #12]
3634
; CHECK-T2-NEXT: cbz r2, .LBB0_2
3735
; CHECK-T2-NEXT: @ %bb.1: @ %if.else
3836
; CHECK-T2-NEXT: bl equeue_create_inplace

llvm/test/CodeGen/X86/tailcall-cgp-dup.ll

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,14 @@ return:
188188
define ptr @memset_tailc(ptr %ret_val, i64 %sz) {
189189
; CHECK-LABEL: memset_tailc:
190190
; CHECK: ## %bb.0: ## %entry
191-
; CHECK: pushq %rbx
192-
; CHECK: movq %rdi, %rbx
193191
; CHECK: testq %rdi, %rdi
194-
; CHECK: je LBB4_2
195-
; CHECK: ## %bb.1: ## %if.then
192+
; CHECK: je LBB4_1
193+
; CHECK: ## %bb.2: ## %if.then
196194
; CHECK: movq %rsi, %rdx
197-
; CHECK: movq %rbx, %rdi
198195
; CHECK: xorl %esi, %esi
199-
; CHECK: callq _memset
200-
; CHECK: LBB4_2: ## %return
201-
; CHECK: movq %rbx, %rax
202-
; CHECK: popq %rbx
196+
; CHECK: jmp _memset ## TAILCALL
197+
; CHECK: LBB4_1: ## %return
198+
; CHECK: movq %rdi, %rax
203199
; CHECK: retq
204200
entry:
205201
%cmp = icmp eq ptr %ret_val, null
@@ -216,21 +212,15 @@ return:
216212
define ptr @memcpy_tailc(ptr %ret_val, i64 %sz, ptr %src) {
217213
; CHECK-LABEL: memcpy_tailc:
218214
; CHECK: ## %bb.0: ## %entry
219-
; CHECK: pushq %rbx
220215
; CHECK: testq %rsi, %rsi
221216
; CHECK: je LBB5_1
222217
; CHECK: ## %bb.2: ## %if.then
223218
; CHECK: movq %rsi, %rax
224-
; CHECK: movq %rdi, %rbx
225219
; CHECK: movq %rdx, %rsi
226220
; CHECK: movq %rax, %rdx
227-
; CHECK: callq _memcpy
228-
; CHECK: jmp LBB5_3
229-
; CHECK: LBB5_1:
230-
; CHECK: movq %rdx, %rbx
231-
; CHECK: LBB5_3: ## %return
232-
; CHECK: movq %rbx, %rax
233-
; CHECK: popq %rbx
221+
; CHECK: jmp _memcpy ## TAILCALL
222+
; CHECK: LBB5_1: ## %return
223+
; CHECK: movq %rdx, %rax
234224
; CHECK: retq
235225
entry:
236226
%cmp = icmp eq i64 %sz, 0
@@ -256,13 +246,15 @@ define ptr @strcpy_tailc(i64 %0, ptr %src) {
256246
; CHECK: movl $20, %edi
257247
; CHECK: callq _malloc
258248
; CHECK: testq %r14, %r14
259-
; CHECK: je LBB6_2
260-
; CHECK: ## %bb.1: ## %if.then
249+
; CHECK: je LBB6_1
250+
; CHECK: ## %bb.2: ## %if.then
261251
; CHECK: movq %rax, %rdi
262252
; CHECK: movq %rbx, %rsi
263-
; CHECK: movq %rax, %rbx
264-
; CHECK: callq _strcpy
265-
; CHECK: LBB6_2: ## %return
253+
; CHECK: addq $8, %rsp
254+
; CHECK: popq %rbx
255+
; CHECK: popq %r14
256+
; CHECK: jmp _strcpy ## TAILCALL
257+
; CHECK: LBB6_1: ## %return
266258
; CHECK: movq %rbx, %rax
267259
; CHECK: addq $8, %rsp
268260
; CHECK: popq %rbx

llvm/test/DebugInfo/X86/live-debug-values-expr-conflict.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@
2424
; one in the block two, and none in block three.
2525
; CHECK: ![[BAZVAR:[0-9]+]] = !DILocalVariable(name: "baz",
2626
; CHECK-LABEL: bb.0.entry:
27-
; CHECK: DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
27+
; CHECK: DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
2828
; CHECK-SAME: !DIExpression()
2929
; CHECK-LABEL: bb.1.if.then:
30-
; CHECK-LABEL: bb.2.if.else:
31-
; CHECK: DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
30+
; CHECK-LABEL: bb.3.if.else:
31+
; CHECK: DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
3232
; CHECK-SAME: !DIExpression()
33-
; CHECK: DBG_VALUE_LIST ![[BAZVAR]],
34-
; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_plus_uconst, 1, DW_OP_stack_value)
35-
; CHECK-SAME: {{[0-9a-zA-Z$%_]*}}
36-
; CHECK-LABEL: bb.3.if.end:
33+
; CHECK: DBG_VALUE_LIST ![[BAZVAR]],
34+
; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_plus_uconst, 1, DW_OP_stack_value)
35+
; CHECK-SAME: {{[0-9a-zA-Z$%_]*}}
36+
; CHECK-LABEL: bb.2.if.then:
3737
; CHECK-NOT: DBG_VALUE
38-
; CHECK-NOT: DBG_VALUE_LIST
38+
; CHECK-NOT: DBG_VALUE_LIST
3939

4040
declare void @escape1(i32)
4141
declare void @escape2(i32)

0 commit comments

Comments
 (0)