Revert "cmd/compile: allow multi-field structs to be stored directly in interfaces"

This reverts commit cd55f86b8d (CL 681937)

Reason for revert: still causing compiler failures on Google test code

Change-Id: I5cd482fd607fd060a523257082d48821b5f965d6
Reviewed-on: https://go-review.googlesource.com/c/go/+/695016
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
Keith Randall 2025-08-11 17:32:05 -07:00 committed by Gopher Robot
parent c31359138c
commit 74421a305b
7 changed files with 36 additions and 33 deletions

View file

@ -921,8 +921,8 @@
@x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem) @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
// Putting struct{*byte} and similar into direct interfaces. // Putting struct{*byte} and similar into direct interfaces.
(IMake _typ (StructMake val)) => imakeOfStructMake(v) (IMake _typ (StructMake val)) => (IMake _typ val)
(StructSelect [_] (IData x)) => (IData x) (StructSelect [0] (IData x)) => (IData x)
// un-SSAable values use mem->mem copies // un-SSAable values use mem->mem copies
(Store {t} dst (Load src mem) mem) && !CanSSA(t) => (Store {t} dst (Load src mem) mem) && !CanSSA(t) =>

View file

@ -423,14 +423,7 @@ func (x *expandState) decomposeAsNecessary(pos src.XPos, b *Block, a, m0 *Value,
if a.Op == OpIMake { if a.Op == OpIMake {
data := a.Args[1] data := a.Args[1]
for data.Op == OpStructMake || data.Op == OpArrayMake1 { for data.Op == OpStructMake || data.Op == OpArrayMake1 {
// A struct make might have a few zero-sized fields. data = data.Args[0]
// Use the pointer-y one we know is there.
for _, a := range data.Args {
if a.Type.Size() > 0 {
data = a
break
}
}
} }
return x.decomposeAsNecessary(pos, b, data, mem, rc.next(data.Type)) return x.decomposeAsNecessary(pos, b, data, mem, rc.next(data.Type))
} }

View file

@ -2621,17 +2621,3 @@ func panicBoundsCToAux(p PanicBoundsC) Aux {
func panicBoundsCCToAux(p PanicBoundsCC) Aux { func panicBoundsCCToAux(p PanicBoundsCC) Aux {
return p return p
} }
// When v is (IMake typ (StructMake ...)), convert to
// (IMake typ arg) where arg is the pointer-y argument to
// the StructMake (there must be exactly one).
func imakeOfStructMake(v *Value) *Value {
var arg *Value
for _, a := range v.Args[1].Args {
if a.Type.Size() > 0 {
arg = a
break
}
}
return v.Block.NewValue2(v.Pos, OpIMake, v.Type, v.Args[0], arg)
}

View file

@ -11201,12 +11201,15 @@ func rewriteValuegeneric_OpIMake(v *Value) bool {
v_1 := v.Args[1] v_1 := v.Args[1]
v_0 := v.Args[0] v_0 := v.Args[0]
// match: (IMake _typ (StructMake val)) // match: (IMake _typ (StructMake val))
// result: imakeOfStructMake(v) // result: (IMake _typ val)
for { for {
_typ := v_0
if v_1.Op != OpStructMake || len(v_1.Args) != 1 { if v_1.Op != OpStructMake || len(v_1.Args) != 1 {
break break
} }
v.copyOf(imakeOfStructMake(v)) val := v_1.Args[0]
v.reset(OpIMake)
v.AddArg2(_typ, val)
return true return true
} }
// match: (IMake _typ (ArrayMake1 val)) // match: (IMake _typ (ArrayMake1 val))
@ -32042,10 +32045,10 @@ func rewriteValuegeneric_OpStructSelect(v *Value) bool {
v0.AddArg2(v1, mem) v0.AddArg2(v1, mem)
return true return true
} }
// match: (StructSelect [_] (IData x)) // match: (StructSelect [0] (IData x))
// result: (IData x) // result: (IData x)
for { for {
if v_0.Op != OpIData { if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpIData {
break break
} }
x := v_0.Args[0] x := v_0.Args[0]

View file

@ -1822,7 +1822,26 @@ func IsReflexive(t *Type) bool {
// Can this type be stored directly in an interface word? // Can this type be stored directly in an interface word?
// Yes, if the representation is a single pointer. // Yes, if the representation is a single pointer.
func IsDirectIface(t *Type) bool { func IsDirectIface(t *Type) bool {
return t.Size() == int64(PtrSize) && PtrDataSize(t) == int64(PtrSize) switch t.Kind() {
case TPTR:
// Pointers to notinheap types must be stored indirectly. See issue 42076.
return !t.Elem().NotInHeap()
case TCHAN,
TMAP,
TFUNC,
TUNSAFEPTR:
return true
case TARRAY:
// Array of 1 direct iface type can be direct.
return t.NumElem() == 1 && IsDirectIface(t.Elem())
case TSTRUCT:
// Struct with 1 field of direct iface type can be direct.
return t.NumFields() == 1 && IsDirectIface(t.Field(0).Type)
}
return false
} }
// IsInterfaceMethod reports whether (field) m is // IsInterfaceMethod reports whether (field) m is

View file

@ -121,8 +121,8 @@ const (
TFlagGCMaskOnDemand TFlag = 1 << 4 TFlagGCMaskOnDemand TFlag = 1 << 4
// TFlagDirectIface means that a value of this type is stored directly // TFlagDirectIface means that a value of this type is stored directly
// in the data field of an interface, instead of indirectly. // in the data field of an interface, instead of indirectly. Normally
// This flag is just a cached computation of Size_ == PtrBytes == goarch.PtrSize. // this means the type is pointer-ish.
TFlagDirectIface TFlag = 1 << 5 TFlagDirectIface TFlag = 1 << 5
// Leaving this breadcrumb behind for dlv. It should not be used, and no // Leaving this breadcrumb behind for dlv. It should not be used, and no

View file

@ -2524,7 +2524,8 @@ func StructOf(fields []StructField) Type {
} }
switch { switch {
case typ.Size_ == goarch.PtrSize && typ.PtrBytes == goarch.PtrSize: case len(fs) == 1 && fs[0].Typ.IsDirectIface():
// structs of 1 direct iface type can be direct
typ.TFlag |= abi.TFlagDirectIface typ.TFlag |= abi.TFlagDirectIface
default: default:
typ.TFlag &^= abi.TFlagDirectIface typ.TFlag &^= abi.TFlagDirectIface
@ -2693,7 +2694,8 @@ func ArrayOf(length int, elem Type) Type {
} }
switch { switch {
case array.Size_ == goarch.PtrSize && array.PtrBytes == goarch.PtrSize: case length == 1 && typ.IsDirectIface():
// array of 1 direct iface type can be direct
array.TFlag |= abi.TFlagDirectIface array.TFlag |= abi.TFlagDirectIface
default: default:
array.TFlag &^= abi.TFlagDirectIface array.TFlag &^= abi.TFlagDirectIface