Skip to content

Commit dd0bbae

Browse files
committed
[WebAssembly] Fix epilogue insertion for indirect tail calls
Previously epilogues were incorrectly inserted after indirect tail calls because they did not have the `isTerminator` property. Add that property and test that they get correct epilogues. To be safe, also add other properties that were defined for direct tail calls. Differential Revision: https://reviews.llvm.org/D146569
1 parent d868135 commit dd0bbae

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ defm RET_CALL :
7373
"return_call \t$callee", "return_call\t$callee", 0x12>,
7474
Requires<[HasTailCall]>;
7575

76-
let isReturn = 1 in
76+
let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in
7777
defm RET_CALL_INDIRECT :
7878
I<(outs), (ins TypeIndex:$type, table32_op:$table, variable_ops),
7979
(outs), (ins TypeIndex:$type, table32_op:$table), [],

llvm/test/CodeGen/WebAssembly/tailcall.ll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,43 @@ define i32 @stack_arg_cast(i32 %x) {
507507
ret i32 %v
508508
}
509509

510+
; Checks that epilogues are inserted after return calls.
511+
define i32 @direct_epilogue() {
512+
; CHECK-LABEL: direct_epilogue:
513+
; CHECK: .functype direct_epilogue () -> (i32)
514+
; CHECK-NEXT: # %bb.0:
515+
; CHECK-NEXT: global.get $push0=, __stack_pointer
516+
; CHECK-NEXT: i32.const $push1=, 256
517+
; CHECK-NEXT: i32.sub $push5=, $pop0, $pop1
518+
; CHECK-NEXT: local.tee $push4=, $0=, $pop5
519+
; CHECK-NEXT: global.set __stack_pointer, $pop4
520+
; CHECK-NEXT: i32.const $push2=, 256
521+
; CHECK-NEXT: i32.add $push3=, $0, $pop2
522+
; CHECK-NEXT: global.set __stack_pointer, $pop3
523+
; CHECK-NEXT: return_call direct_epilogue
524+
%a = alloca [64 x i32]
525+
%v = musttail call i32 @direct_epilogue()
526+
ret i32 %v
527+
}
528+
529+
define i32 @indirect_epilogue(ptr %p) {
530+
; CHECK-LABEL: indirect_epilogue:
531+
; CHECK: .functype indirect_epilogue (i32) -> (i32)
532+
; CHECK-NEXT: # %bb.0:
533+
; CHECK-NEXT: global.get $push0=, __stack_pointer
534+
; CHECK-NEXT: i32.const $push1=, 256
535+
; CHECK-NEXT: i32.sub $push5=, $pop0, $pop1
536+
; CHECK-NEXT: local.tee $push4=, $1=, $pop5
537+
; CHECK-NEXT: global.set __stack_pointer, $pop4
538+
; CHECK-NEXT: i32.const $push2=, 256
539+
; CHECK-NEXT: i32.add $push3=, $1, $pop2
540+
; CHECK-NEXT: global.set __stack_pointer, $pop3
541+
; CHECK-NEXT: return_call_indirect , $0, $0
542+
%a = alloca [64 x i32]
543+
%v = musttail call i32 %p(ptr %p)
544+
ret i32 %v
545+
}
546+
510547
; Check that the signatures generated for external indirectly
511548
; return-called functions include the proper return types
512549

0 commit comments

Comments
 (0)