Skip to content

Regression: WebAssembly backend does not generate return_call for musttail calls with multiple return values #133292

Open
@camilstaps

Description

@camilstaps

Given x.ll

%t = type { i64, i64 }

declare %t @f()

define private %t @g() {
entry:
  %0 = musttail call %t @f()
  ret %t %0
}

the WebAssembly backend does not generate a return_call but a plain call, thus growing the stack.

I'm using LLVM 20.1.2 with the invocation llc-20 -mattr=+multivalue,+tail-call -mtriple=wasm64-unknown-unknown --filetype=asm -o x.wat x.ll, but the same issue arises on wasm32 and without multivalue enabled.

When changing the type to %t = type i64, return_call is used as expected.

The (faulty) generated WebAssembly for the module above is:

	.file	"x.ll"
	.globaltype	__stack_pointer, i64
	.functype	f (i64) -> ()
	.functype	.Lg (i64) -> ()
	.section	.text..Lg,"",@
	.type	.Lg,@function                   # -- Begin function g
.Lg:                                    # @g
	.functype	.Lg (i64) -> ()
	.local  	i64, i64
# %bb.0:                                # %entry
	global.get	__stack_pointer
	i64.const	16
	i64.sub 
	local.tee	1
	global.set	__stack_pointer
	local.get	1
	call	f
	local.get	1
	i64.load	0
	local.set	2
	local.get	0
	local.get	1
	i64.load	8
	i64.store	8
	local.get	0
	local.get	2
	i64.store	0
	local.get	1
	i64.const	16
	i64.add 
	global.set	__stack_pointer
                                        # fallthrough-return
	end_function
                                        # -- End function
	.section	.custom_section.target_features,"",@
	.int8	10
	.int8	43
	.int8	11
	.ascii	"bulk-memory"
	.int8	43
	.int8	15
	.ascii	"bulk-memory-opt"
	.int8	43
	.int8	22
	.ascii	"call-indirect-overlong"
	.int8	43
	.int8	10
	.ascii	"multivalue"
	.int8	43
	.int8	15
	.ascii	"mutable-globals"
	.int8	43
	.int8	19
	.ascii	"nontrapping-fptoint"
	.int8	43
	.int8	15
	.ascii	"reference-types"
	.int8	43
	.int8	8
	.ascii	"sign-ext"
	.int8	43
	.int8	9
	.ascii	"tail-call"
	.int8	43
	.int8	8
	.ascii	"memory64"
	.section	.text..Lg,"",@

Note that this is a regression: LLVM 18 would generate a return_call:

.Lg:                                    # @g
	.functype	.Lg () -> (i64, i64)
# %bb.0:                                # %entry
	return_call	f
	end_function

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions