Hi everybody!

Recently, I noticed that there are some restrictions on the arguments 
passed to functions in registers.

For example, if `a` is a struct, it must have fewer than 5 fields, and its 
size must be less than `5 * ptrsz`. You can find these restrictions in 
`cmd/compile/internal/ssa/value.go` at line 590 in the `CanSSA` function:

```
// CanSSA reports whether values of type t can be represented as a Value.
func CanSSA(t *types.Type) bool {
types.CalcSize(t)
if t.Size() > int64(4*types.PtrSize) {
// 4*Widthptr is an arbitrary constant. We want it
// to be at least 3*Widthptr so slices can be registerized.
// Too big and we'll introduce too much register pressure.
return false
}
switch t.Kind() {
...
case types.TSTRUCT:
if t.NumFields() > MaxStruct { // MaxStruct = 4
return false
}
}
}
```

Consider the following example:

```
type A struct {
s1, s2 string
i1     int64
}

func (a A) GetInt() int64 {
return a.i1
}
```

This compiles to:

```
f90007e0                MOVD R0, 8(RSP)
f9000be1                MOVD R1, 16(RSP)
f9000fe2                MOVD R2, 24(RSP)
f90013e3                MOVD R3, 32(RSP)
f90017e4                MOVD R4, 40(RSP)
aa0403e0                MOVD R4, R0
d65f03c0                RET
```

In the recent merged changes 
(CL#611075)[https://go-review.googlesource.com/c/go/+/611075/4] and 
(CL#611076)[https://go-review.googlesource.com/c/go/+/611076/6], support 
was added for making structs with any number of fields SSA-able. With these 
changes, I was able to remove the size restriction for structs that can be 
SSA-ized.

Without these restrictions, the above example compiles to:

```
f90007e0                MOVD R0, 8(RSP)
f9000fe2                MOVD R2, 24(RSP)
aa0403e0                MOVD R4, R0
d65f03c0                RET
```

So, I am wondering: why does the restriction on size exist in the first 
place? It seems unreasonable to place the argument in registers only to 
later push it to the stack. The comment mentions that it helps reduce 
register pressure, but can't the register allocator decide to spill the 
argument if necessary? Also, if we’re preemptively pushing the structure to 
the stack, why not just pass it on the stack from the beginning?

Thank you for your time and attention,  
Arseny.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/3ba584bd-c57b-4c3c-8ae3-f39942ada7b8n%40googlegroups.com.

Reply via email to