diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -73,7 +73,7 @@ "return_call \t$callee", "return_call\t$callee", 0x12>, Requires<[HasTailCall]>; -let isReturn = 1 in +let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in defm RET_CALL_INDIRECT : I<(outs), (ins TypeIndex:$type, table32_op:$table, variable_ops), (outs), (ins TypeIndex:$type, table32_op:$table), [], diff --git a/llvm/test/CodeGen/WebAssembly/tailcall.ll b/llvm/test/CodeGen/WebAssembly/tailcall.ll --- a/llvm/test/CodeGen/WebAssembly/tailcall.ll +++ b/llvm/test/CodeGen/WebAssembly/tailcall.ll @@ -257,6 +257,24 @@ ret i32 %v } +; Test if SP restoring code is generated correctly before the return_call_indirect. +; Note: the second global.set is to restore the SP. +; CHECK-LABEL: alloca_and_indirect_tail_call +; CHECK: global.get $push{{[0-9]+}}=, __stack_pointer +; CHECK: global.set __stack_pointer, $pop{{[0-9]+}} +; CHECK: global.set __stack_pointer, $pop{{[0-9]+}} +; CHECK: return_call_indirect , $0, $1 +declare void @do_something(ptr) +define i32 @alloca_and_indirect_tail_call(ptr %p) { + ; consume stack + %a = alloca i8 + call void @do_something(ptr %a) + + %f = load ptr, ptr %p + %v = musttail call i32 %f(ptr %p) + ret i32 %v +} + ; CHECK-LABEL: .section .custom_section.target_features ; CHECK-NEXT: .int8 1 ; CHECK-NEXT: .int8 43