Consider the following SSA:
# (uint | u64 | void)
type :tagged_union = align 8 {
{ w 1, w 1 }
{ w 1, l 1 }
}
# fn bar() uint = {
# return foo(): uint;
# };
section ".text.bar" "ax"
function w $bar() {
@start.0
@body.1
%foo =:tagged_union call $foo()
%.1 =l copy %foo
%.2 =l add %.1, 4
%uint =w loaduw %.2
ret %uint
}
# fn foo() (uint | u64 | void) = {
# return 10u;
# };
section ".text.foo" "ax"
function :tagged_union $foo() {
@start.9
%object =l alloc8 16
@body.10
storew 1906196061, %object
%.1 =l add %object, 4
storew 10, %.1
ret %object
}
The following x86_64 assembly is produced:
.section ".text.bar","ax"
bar:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
callq foo
movq %rax, %rcx
movq %rdx, %rax
movq %rcx, -16(%rbp)
movq %rax, -8(%rbp)
movl -12(%rbp), %eax
leave
ret
.type bar, @function
.size bar, .-bar
/* end function bar */
.section ".text.foo","ax"
foo:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl $1906196061, -16(%rbp)
movl $10, -12(%rbp)
movq -16(%rbp), %rax
movq -8(%rbp), %rdx
leave
ret
.type foo, @function
.size foo, .-foo
/* end function foo */
.section .note.GNU-stack,"",@progbits
In both functions, it should not be necessary to allocate space on the
stack; those slots can be eliminated and we can just work with
registers.
Hi Drew,
The reason those don't disappear is that the memory optimizations don't see them: they appear at abi1 stage, and it's too late at this point to kill them.
The point of abi0 is to encode part of the abi early so it can be optimized away. So the work to do is clear: make abi0 smarter.
I am currently focusing on systematizing pattern matching in qbe to make instruction selection smarter in an elegant way (treematch branch). I can look at abi0 after that, or I can mentor someone into this work.
Hope that all makes sense.
On Mon, Jul 10, 2023, at 08:22, Drew DeVault wrote:
> Consider the following SSA:
>
> # (uint | u64 | void)
> type :tagged_union = align 8 {
> { w 1, w 1 }
> { w 1, l 1 }
> }
>
> # fn bar() uint = {
> # return foo(): uint;
> # };
> section ".text.bar" "ax"
> function w $bar() {
> @start.0
> @body.1
> %foo =:tagged_union call $foo()
> %.1 =l copy %foo
> %.2 =l add %.1, 4
> %uint =w loaduw %.2
> ret %uint
> }
>
> # fn foo() (uint | u64 | void) = {
> # return 10u;
> # };
> section ".text.foo" "ax"
> function :tagged_union $foo() {
> @start.9
> %object =l alloc8 16
> @body.10
> storew 1906196061, %object
> %.1 =l add %object, 4
> storew 10, %.1
> ret %object
> }
>
> The following x86_64 assembly is produced:
>
> .section ".text.bar","ax"
> bar:
> pushq %rbp
> movq %rsp, %rbp
> subq $16, %rsp
> callq foo
> movq %rax, %rcx
> movq %rdx, %rax
> movq %rcx, -16(%rbp)
> movq %rax, -8(%rbp)
> movl -12(%rbp), %eax
> leave
> ret
> .type bar, @function
> .size bar, .-bar
> /* end function bar */
>
> .section ".text.foo","ax"
> foo:
> pushq %rbp
> movq %rsp, %rbp
> subq $16, %rsp
> movl $1906196061, -16(%rbp)
> movl $10, -12(%rbp)
> movq -16(%rbp), %rax
> movq -8(%rbp), %rdx
> leave
> ret
> .type foo, @function
> .size foo, .-foo
> /* end function foo */
>
> .section .note.GNU-stack,"",@progbits
>
> In both functions, it should not be necessary to allocate space on the
> stack; those slots can be eliminated and we can just work with
> registers.