Skip to content

cmd/compile: Inaccurate AuxInt value for newobject call #68631

@And-ZJ

Description

@And-ZJ

Go version

go version go1.23rc2 linux/arm64

Output of go env in your module/workspace:

Pasted part of content:

GO111MODULE='auto'
GOARCH='arm64'
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOOS='linux'
GOROOT='/usr1/GoRelease/go1.23rc2'
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr1/GoRelease/go1.23rc2/pkg/tool/linux_arm64'
GOVERSION='go1.23rc2'
GODEBUG=''
GOTELEMETRY='local'
GOARM64='v8.0'

What did you do?

When I look at the call to runtime.newobject in SSA, it looks like the AuxInt value is inaccurate.

I think It is larger than expected. In addition, the value is larger in ARM64 than in AMD64.

My test code temp.go:

package main

var g1 *int64

//go:noinline
func test1(a *int64) *int64 {
	g1 = a
	return a
}

func main() {
	a := new(int64)
	test1(a)
}

Build, dump SSA and view assembly code:

GOSSAFUNC=main.main go build -a -trimpath temp.go
objdump -rd --disassemble=main.main temp

ARM64(SSA dump in before insert phis phase):

b1:
v1 (?) = InitMem <mem>
v2 (?) = SP <uintptr>
v3 (?) = SB <uintptr>
v4 (?) = Addr <*uint8> {type:int64} v3
v5 (12) = StaticLECall <*int64,mem> {AuxCall{runtime.newobject}} [24] v4 v1
v6 (12) = SelectN <mem> [1] v5
v7 (12) = SelectN <*int64> [0] v5 (a[*int64])
v8 (13) = StaticLECall <*int64,mem> {AuxCall{main.test1}} [8] v7 v6
v9 (13) = SelectN <mem> [1] v8
v10 (13) = SelectN <*int64> [0] v8
v11 (14) = MakeResult <mem> v9
Ret v11 (14)
name a[*int64]: v7

ARM64(assembly code):

0000000000076f70 <main.main>:
   76f70:	f9400b90 	ldr	x16, [x28, #16]
   76f74:	eb3063ff 	cmp	sp, x16
   76f78:	54000169 	b.ls	76fa4 <main.main+0x34>  // b.plast
   76f7c:	f81d0ffe 	str	x30, [sp, #-48]!
   76f80:	f81f83fd 	stur	x29, [sp, #-8]
   76f84:	d10023fd 	sub	x29, sp, #0x8
   76f88:	f0000060 	adrp	x0, 85000 <type:*+0x5000>
   76f8c:	910e0000 	add	x0, x0, #0x380
   76f90:	97fe8da8 	bl	1a630 <runtime.newobject>
   76f94:	97ffffdf 	bl	76f10 <main.test1>
   76f98:	a97ffbfd 	ldp	x29, x30, [sp, #-8]
   76f9c:	9100c3ff 	add	sp, sp, #0x30
   76fa0:	d65f03c0 	ret
   76fa4:	aa1e03e3 	mov	x3, x30
   76fa8:	97ffed62 	bl	72530 <runtime.morestack_noctxt.abi0>
   76fac:	17fffff1 	b	76f70 <main.main>

AMD64(SSA dump in before insert phis phase):

b1:
v1 (?) = InitMem <mem>
v2 (?) = SP <uintptr>
v3 (?) = SB <uintptr>
v4 (?) = Addr <*uint8> {type:int64} v3
v5 (12) = StaticLECall <*int64,mem> {AuxCall{runtime.newobject}} [16] v4 v1
v6 (12) = SelectN <mem> [1] v5
v7 (12) = SelectN <*int64> [0] v5 (a[*int64])
v8 (13) = StaticLECall <*int64,mem> {AuxCall{main.test1}} [8] v7 v6
v9 (13) = SelectN <mem> [1] v8
v10 (13) = SelectN <*int64> [0] v8
v11 (14) = MakeResult <mem> v9
Ret v11 (14)
name a[*int64]: v7

AMD64(assembly code):

0000000000466820 <main.main>:
  466820:	49 3b 66 10          	cmp    0x10(%r14),%rsp
  466824:	76 1f                	jbe    466845 <main.main+0x25>
  466826:	55                   	push   %rbp
  466827:	48 89 e5             	mov    %rsp,%rbp
  46682a:	48 83 ec 10          	sub    $0x10,%rsp
  46682e:	48 8d 05 4b 5b 00 00 	lea    0x5b4b(%rip),%rax        # 46c380 <type:*+0x5380>
  466835:	e8 a6 4a fa ff       	callq  40b2e0 <runtime.newobject>
  46683a:	e8 81 ff ff ff       	callq  4667c0 <main.test1>
  46683f:	48 83 c4 10          	add    $0x10,%rsp
  466843:	5d                   	pop    %rbp
  466844:	c3                   	retq   
  466845:	e8 b6 b0 ff ff       	callq  461900 <runtime.morestack_noctxt.abi0>
  46684a:	eb d4                	jmp    466820 <main.main>

In ARM64:
The newobject's AuxInt is 24. The test1's AuxInt is 8. Note the test1 function that has only one input parameter and one return value.
The stack space of the main function uses 48 bytes.

In AMD64:
The newobject's AuxInt is 16. The test1's AuxInt is 8.
The stack space of the main function uses 24 bytes (0x10 + 8).

The StaticLECall in

{name: "StaticLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded static call function aux.(*ssa.AuxCall.Fn). arg0..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem.

Here, AuxInt indicates the size of the input parameter, but it is not specified whether the mem parameter is included. It is suspected that the mem parameter is not included.

The auxCallOff in

auxCallOff // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size

Here, AuxInt indicates includes the size of the input and output parameters?

The runtime call newobject may emit at (*state).newObject at

func (s *state) newObject(typ *types.Type, rtype *ssa.Value) *ssa.Value {

In this way, it call (*state).rtcall at

func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args ...*ssa.Value) []*ssa.Value {

AuxInt appears to be the sum of the size of the input and output parameters and FixedFrameSize.

The common call test1 may emit at (*state).call at

func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool, deferExtra ir.Expr) *ssa.Value {

In this way, AuxInt mostly equal to (*ABIParamResultInfo).ArgWidth(), This should be the size of the stack space to be used when calling. The space includes the spill space of the register transfer parameter, and the space on the stack of the input and output parameters of the stack transfer parameter.

So, I've got a lot of explanations for AuxInt of this situation and I'm confused.

From the main function assembly, I think the space used on the stack is larger than what is actually needed.

image

The gray areas that are marked here are what I consider to be unused space.

For other functions that use the (*state).rtcall, the situation may be similar.

This should have happened in previous versions of go.

I haven't been able to find out if anyone else has had the same problem.

Thank you for your reading.

My understanding may be incorrect, please point it out, thanks.

What did you see happen?

The caller's stack space used by newobject is larger than my expected. It's AuxInt is inaccurate?

What did you expect to see?

More precise AuxInt of newobject and other runtime calls?

Metadata

Metadata

Assignees

Labels

NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions