mirror of https://github.com/golang/go.git
cmd/compile/internal/ssa: rename ssagen.TypeOK as CanSSA
No need to indirect through Frontend for this. Change-Id: I5812eb4dadfda79267cabc9d13aeab126c1479e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/526517 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Matthew Dempsky <mdempsky@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
af8a2bde7b
commit
45d3d10071
|
|
@ -204,7 +204,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
|
|||
if c == '.' || n.Type().IsUntyped() {
|
||||
continue
|
||||
}
|
||||
if n.Class == ir.PPARAM && !ssagen.TypeOK(n.Type()) {
|
||||
if n.Class == ir.PPARAM && !ssa.CanSSA(n.Type()) {
|
||||
// SSA-able args get location lists, and may move in and
|
||||
// out of registers, so those are handled elsewhere.
|
||||
// Autos and named output params seem to get handled
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func ArgLiveness(fn *ir.Func, f *ssa.Func, pp *objw.Progs) (blockIdx, valueIdx m
|
|||
}
|
||||
|
||||
// We spill address-taken or non-SSA-able value upfront, so they are always live.
|
||||
alwaysLive := func(n *ir.Name) bool { return n.Addrtaken() || !f.Frontend().CanSSA(n.Type()) }
|
||||
alwaysLive := func(n *ir.Name) bool { return n.Addrtaken() || !ssa.CanSSA(n.Type()) }
|
||||
|
||||
// We'll emit the smallest offset for the slots that need liveness info.
|
||||
// No need to include a slot with a lower offset if it is always live.
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@
|
|||
(Store {t2} p2 _
|
||||
mem:(Zero [n] p3 _)))
|
||||
&& o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3)
|
||||
&& fe.CanSSA(t1)
|
||||
&& CanSSA(t1)
|
||||
&& disjoint(op, t1.Size(), p2, t2.Size())
|
||||
=> @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p3) mem)
|
||||
(Load <t1> op:(OffPtr [o1] p1)
|
||||
|
|
@ -712,7 +712,7 @@
|
|||
(Store {t3} p3 _
|
||||
mem:(Zero [n] p4 _))))
|
||||
&& o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4)
|
||||
&& fe.CanSSA(t1)
|
||||
&& CanSSA(t1)
|
||||
&& disjoint(op, t1.Size(), p2, t2.Size())
|
||||
&& disjoint(op, t1.Size(), p3, t3.Size())
|
||||
=> @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p4) mem)
|
||||
|
|
@ -722,7 +722,7 @@
|
|||
(Store {t4} p4 _
|
||||
mem:(Zero [n] p5 _)))))
|
||||
&& o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5)
|
||||
&& fe.CanSSA(t1)
|
||||
&& CanSSA(t1)
|
||||
&& disjoint(op, t1.Size(), p2, t2.Size())
|
||||
&& disjoint(op, t1.Size(), p3, t3.Size())
|
||||
&& disjoint(op, t1.Size(), p4, t4.Size())
|
||||
|
|
@ -734,7 +734,7 @@
|
|||
(Store {t5} p5 _
|
||||
mem:(Zero [n] p6 _))))))
|
||||
&& o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6)
|
||||
&& fe.CanSSA(t1)
|
||||
&& CanSSA(t1)
|
||||
&& disjoint(op, t1.Size(), p2, t2.Size())
|
||||
&& disjoint(op, t1.Size(), p3, t3.Size())
|
||||
&& disjoint(op, t1.Size(), p4, t4.Size())
|
||||
|
|
@ -848,28 +848,28 @@
|
|||
(StructSelect [2] (StructMake4 _ _ x _)) => x
|
||||
(StructSelect [3] (StructMake4 _ _ _ x)) => x
|
||||
|
||||
(Load <t> _ _) && t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t) =>
|
||||
(Load <t> _ _) && t.IsStruct() && t.NumFields() == 0 && CanSSA(t) =>
|
||||
(StructMake0)
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t) =>
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 1 && CanSSA(t) =>
|
||||
(StructMake1
|
||||
(Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem))
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t) =>
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 2 && CanSSA(t) =>
|
||||
(StructMake2
|
||||
(Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem)
|
||||
(Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem))
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t) =>
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 3 && CanSSA(t) =>
|
||||
(StructMake3
|
||||
(Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem)
|
||||
(Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem)
|
||||
(Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem))
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t) =>
|
||||
(Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 4 && CanSSA(t) =>
|
||||
(StructMake4
|
||||
(Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem)
|
||||
(Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem)
|
||||
(Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem)
|
||||
(Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
|
||||
|
||||
(StructSelect [i] x:(Load <t> ptr mem)) && !fe.CanSSA(t) =>
|
||||
(StructSelect [i] x:(Load <t> ptr mem)) && !CanSSA(t) =>
|
||||
@x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
|
||||
|
||||
(Store _ (StructMake0) mem) => mem
|
||||
|
|
@ -911,9 +911,9 @@
|
|||
(StructSelect [0] (IData x)) => (IData x)
|
||||
|
||||
// un-SSAable values use mem->mem copies
|
||||
(Store {t} dst (Load src mem) mem) && !fe.CanSSA(t) =>
|
||||
(Store {t} dst (Load src mem) mem) && !CanSSA(t) =>
|
||||
(Move {t} [t.Size()] dst src mem)
|
||||
(Store {t} dst (Load src mem) (VarDef {x} mem)) && !fe.CanSSA(t) =>
|
||||
(Store {t} dst (Load src mem) (VarDef {x} mem)) && !CanSSA(t) =>
|
||||
(Move {t} [t.Size()] dst src (VarDef {x} mem))
|
||||
|
||||
// array ops
|
||||
|
|
@ -922,7 +922,7 @@
|
|||
(Load <t> _ _) && t.IsArray() && t.NumElem() == 0 =>
|
||||
(ArrayMake0)
|
||||
|
||||
(Load <t> ptr mem) && t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t) =>
|
||||
(Load <t> ptr mem) && t.IsArray() && t.NumElem() == 1 && CanSSA(t) =>
|
||||
(ArrayMake1 (Load <t.Elem()> ptr mem))
|
||||
|
||||
(Store _ (ArrayMake0) mem) => mem
|
||||
|
|
|
|||
|
|
@ -143,9 +143,6 @@ type Logger interface {
|
|||
type Frontend interface {
|
||||
Logger
|
||||
|
||||
// CanSSA reports whether variables of type t are SSA-able.
|
||||
CanSSA(t *types.Type) bool
|
||||
|
||||
// StringData returns a symbol pointing to the given string's contents.
|
||||
StringData(string) *obj.LSym
|
||||
|
||||
|
|
|
|||
|
|
@ -177,7 +177,6 @@ type expandState struct {
|
|||
f *Func
|
||||
abi1 *abi.ABIConfig
|
||||
debug int // odd values log lost statement markers, so likely settings are 1 (stmts), 2 (expansion), and 3 (both)
|
||||
canSSAType func(*types.Type) bool
|
||||
regSize int64
|
||||
sp *Value
|
||||
typs *Types
|
||||
|
|
@ -211,7 +210,7 @@ func (x *expandState) intPairTypes(et types.Kind) (tHi, tLo *types.Type) {
|
|||
// so this is all aggregate types -- small struct and array, complex, interface, string, slice, and 64-bit
|
||||
// integer on 32-bit).
|
||||
func (x *expandState) isAlreadyExpandedAggregateType(t *types.Type) bool {
|
||||
if !x.canSSAType(t) {
|
||||
if !CanSSA(t) {
|
||||
return false
|
||||
}
|
||||
return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice() ||
|
||||
|
|
@ -426,7 +425,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64,
|
|||
|
||||
} else {
|
||||
leafType := removeTrivialWrapperTypes(leaf.Type)
|
||||
if x.canSSAType(leafType) {
|
||||
if CanSSA(leafType) {
|
||||
pt := types.NewPtr(leafType)
|
||||
// Any selection right out of the arg area/registers has to be same Block as call, use call as mem input.
|
||||
// Create a "mem" for any loads that need to occur.
|
||||
|
|
@ -1195,7 +1194,6 @@ func expandCalls(f *Func) {
|
|||
f: f,
|
||||
abi1: f.ABI1,
|
||||
debug: f.pass.debug,
|
||||
canSSAType: f.fe.CanSSA,
|
||||
regSize: f.Config.RegSize,
|
||||
sp: sp,
|
||||
typs: &f.Config.Types,
|
||||
|
|
|
|||
|
|
@ -120,10 +120,3 @@ func init() {
|
|||
typecheck.InitUniverse()
|
||||
testTypes.SetTypPtrs()
|
||||
}
|
||||
|
||||
func (d TestFrontend) DerefItab(sym *obj.LSym, off int64) *obj.LSym { return nil }
|
||||
|
||||
func (d TestFrontend) CanSSA(t *types.Type) bool {
|
||||
// There are no un-SSAable types in test land.
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ func rewriteValuePPC64latelower_OpPPC64ISEL(v *Value) bool {
|
|||
func rewriteValuePPC64latelower_OpPPC64RLDICL(v *Value) bool {
|
||||
v_0 := v.Args[0]
|
||||
// match: (RLDICL [em] x:(SRDconst [s] a))
|
||||
// cond: (em&0xFF0000)==0
|
||||
// cond: (em&0xFF0000) == 0
|
||||
// result: (RLDICL [mergePPC64RLDICLandSRDconst(em, s)] a)
|
||||
for {
|
||||
em := auxIntToInt64(v.AuxInt)
|
||||
|
|
|
|||
|
|
@ -12587,7 +12587,6 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
v_0 := v.Args[0]
|
||||
b := v.Block
|
||||
config := b.Func.Config
|
||||
fe := b.Func.fe
|
||||
// match: (Load <t1> p1 (Store {t2} p2 x _))
|
||||
// cond: isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()
|
||||
// result: x
|
||||
|
|
@ -12799,7 +12798,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ mem:(Zero [n] p3 _)))
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size())
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size())
|
||||
// result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p3) mem)
|
||||
for {
|
||||
t1 := v.Type
|
||||
|
|
@ -12821,7 +12820,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
}
|
||||
n := auxIntToInt64(mem.AuxInt)
|
||||
p3 := mem.Args[0]
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size())) {
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p3) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size())) {
|
||||
break
|
||||
}
|
||||
b = mem.Block
|
||||
|
|
@ -12834,7 +12833,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ (Store {t3} p3 _ mem:(Zero [n] p4 _))))
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())
|
||||
// result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p4) mem)
|
||||
for {
|
||||
t1 := v.Type
|
||||
|
|
@ -12863,7 +12862,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
}
|
||||
n := auxIntToInt64(mem.AuxInt)
|
||||
p4 := mem.Args[0]
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())) {
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p4) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size())) {
|
||||
break
|
||||
}
|
||||
b = mem.Block
|
||||
|
|
@ -12876,7 +12875,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ mem:(Zero [n] p5 _)))))
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())
|
||||
// result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p5) mem)
|
||||
for {
|
||||
t1 := v.Type
|
||||
|
|
@ -12912,7 +12911,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
}
|
||||
n := auxIntToInt64(mem.AuxInt)
|
||||
p5 := mem.Args[0]
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())) {
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p5) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size())) {
|
||||
break
|
||||
}
|
||||
b = mem.Block
|
||||
|
|
@ -12925,7 +12924,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ (Store {t3} p3 _ (Store {t4} p4 _ (Store {t5} p5 _ mem:(Zero [n] p6 _))))))
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size()) && disjoint(op, t1.Size(), p5, t5.Size())
|
||||
// cond: o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size()) && disjoint(op, t1.Size(), p5, t5.Size())
|
||||
// result: @mem.Block (Load <t1> (OffPtr <op.Type> [o1] p6) mem)
|
||||
for {
|
||||
t1 := v.Type
|
||||
|
|
@ -12968,7 +12967,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
}
|
||||
n := auxIntToInt64(mem.AuxInt)
|
||||
p6 := mem.Args[0]
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6) && fe.CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size()) && disjoint(op, t1.Size(), p5, t5.Size())) {
|
||||
if !(o1 >= 0 && o1+t1.Size() <= n && isSamePtr(p1, p6) && CanSSA(t1) && disjoint(op, t1.Size(), p2, t2.Size()) && disjoint(op, t1.Size(), p3, t3.Size()) && disjoint(op, t1.Size(), p4, t4.Size()) && disjoint(op, t1.Size(), p5, t5.Size())) {
|
||||
break
|
||||
}
|
||||
b = mem.Block
|
||||
|
|
@ -13135,24 +13134,24 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t> _ _)
|
||||
// cond: t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)
|
||||
// cond: t.IsStruct() && t.NumFields() == 0 && CanSSA(t)
|
||||
// result: (StructMake0)
|
||||
for {
|
||||
t := v.Type
|
||||
if !(t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)) {
|
||||
if !(t.IsStruct() && t.NumFields() == 0 && CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpStructMake0)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)
|
||||
// cond: t.IsStruct() && t.NumFields() == 1 && CanSSA(t)
|
||||
// result: (StructMake1 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem))
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v_0
|
||||
mem := v_1
|
||||
if !(t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)) {
|
||||
if !(t.IsStruct() && t.NumFields() == 1 && CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpStructMake1)
|
||||
|
|
@ -13165,13 +13164,13 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)
|
||||
// cond: t.IsStruct() && t.NumFields() == 2 && CanSSA(t)
|
||||
// result: (StructMake2 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem) (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem))
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v_0
|
||||
mem := v_1
|
||||
if !(t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)) {
|
||||
if !(t.IsStruct() && t.NumFields() == 2 && CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpStructMake2)
|
||||
|
|
@ -13189,13 +13188,13 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)
|
||||
// cond: t.IsStruct() && t.NumFields() == 3 && CanSSA(t)
|
||||
// result: (StructMake3 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem) (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem) (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem))
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v_0
|
||||
mem := v_1
|
||||
if !(t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)) {
|
||||
if !(t.IsStruct() && t.NumFields() == 3 && CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpStructMake3)
|
||||
|
|
@ -13218,13 +13217,13 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)
|
||||
// cond: t.IsStruct() && t.NumFields() == 4 && CanSSA(t)
|
||||
// result: (StructMake4 (Load <t.FieldType(0)> (OffPtr <t.FieldType(0).PtrTo()> [0] ptr) mem) (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem) (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem) (Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v_0
|
||||
mem := v_1
|
||||
if !(t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)) {
|
||||
if !(t.IsStruct() && t.NumFields() == 4 && CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpStructMake4)
|
||||
|
|
@ -13263,13 +13262,13 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)
|
||||
// cond: t.IsArray() && t.NumElem() == 1 && CanSSA(t)
|
||||
// result: (ArrayMake1 (Load <t.Elem()> ptr mem))
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v_0
|
||||
mem := v_1
|
||||
if !(t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)) {
|
||||
if !(t.IsArray() && t.NumElem() == 1 && CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpArrayMake1)
|
||||
|
|
@ -28610,7 +28609,6 @@ func rewriteValuegeneric_OpStore(v *Value) bool {
|
|||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
b := v.Block
|
||||
fe := b.Func.fe
|
||||
// match: (Store {t1} p1 (Load <t2> p2 mem) mem)
|
||||
// cond: isSamePtr(p1, p2) && t2.Size() == t1.Size()
|
||||
// result: mem
|
||||
|
|
@ -28987,7 +28985,7 @@ func rewriteValuegeneric_OpStore(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Store {t} dst (Load src mem) mem)
|
||||
// cond: !fe.CanSSA(t)
|
||||
// cond: !CanSSA(t)
|
||||
// result: (Move {t} [t.Size()] dst src mem)
|
||||
for {
|
||||
t := auxToType(v.Aux)
|
||||
|
|
@ -28997,7 +28995,7 @@ func rewriteValuegeneric_OpStore(v *Value) bool {
|
|||
}
|
||||
mem := v_1.Args[1]
|
||||
src := v_1.Args[0]
|
||||
if mem != v_2 || !(!fe.CanSSA(t)) {
|
||||
if mem != v_2 || !(!CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpMove)
|
||||
|
|
@ -29007,7 +29005,7 @@ func rewriteValuegeneric_OpStore(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (Store {t} dst (Load src mem) (VarDef {x} mem))
|
||||
// cond: !fe.CanSSA(t)
|
||||
// cond: !CanSSA(t)
|
||||
// result: (Move {t} [t.Size()] dst src (VarDef {x} mem))
|
||||
for {
|
||||
t := auxToType(v.Aux)
|
||||
|
|
@ -29021,7 +29019,7 @@ func rewriteValuegeneric_OpStore(v *Value) bool {
|
|||
break
|
||||
}
|
||||
x := auxToSym(v_2.Aux)
|
||||
if mem != v_2.Args[0] || !(!fe.CanSSA(t)) {
|
||||
if mem != v_2.Args[0] || !(!CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpMove)
|
||||
|
|
@ -29497,7 +29495,6 @@ func rewriteValuegeneric_OpStringPtr(v *Value) bool {
|
|||
func rewriteValuegeneric_OpStructSelect(v *Value) bool {
|
||||
v_0 := v.Args[0]
|
||||
b := v.Block
|
||||
fe := b.Func.fe
|
||||
// match: (StructSelect (StructMake1 x))
|
||||
// result: x
|
||||
for {
|
||||
|
|
@ -29599,7 +29596,7 @@ func rewriteValuegeneric_OpStructSelect(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (StructSelect [i] x:(Load <t> ptr mem))
|
||||
// cond: !fe.CanSSA(t)
|
||||
// cond: !CanSSA(t)
|
||||
// result: @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
|
||||
for {
|
||||
i := auxIntToInt64(v.AuxInt)
|
||||
|
|
@ -29610,7 +29607,7 @@ func rewriteValuegeneric_OpStructSelect(v *Value) bool {
|
|||
t := x.Type
|
||||
mem := x.Args[1]
|
||||
ptr := x.Args[0]
|
||||
if !(!fe.CanSSA(t)) {
|
||||
if !(!CanSSA(t)) {
|
||||
break
|
||||
}
|
||||
b = x.Block
|
||||
|
|
|
|||
|
|
@ -581,3 +581,36 @@ func AutoVar(v *Value) (*ir.Name, int64) {
|
|||
nameOff := v.Aux.(*AuxNameOffset)
|
||||
return nameOff.Name, nameOff.Offset
|
||||
}
|
||||
|
||||
// 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.TARRAY:
|
||||
// We can't do larger arrays because dynamic indexing is
|
||||
// not supported on SSA variables.
|
||||
// TODO: allow if all indexes are constant.
|
||||
if t.NumElem() <= 1 {
|
||||
return CanSSA(t.Elem())
|
||||
}
|
||||
return false
|
||||
case types.TSTRUCT:
|
||||
if t.NumFields() > MaxStruct {
|
||||
return false
|
||||
}
|
||||
for _, t1 := range t.Fields() {
|
||||
if !CanSSA(t1.Type) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
|||
} else { // address was taken AND/OR too large for SSA
|
||||
paramAssignment := ssa.ParamAssignmentForArgName(s.f, n)
|
||||
if len(paramAssignment.Registers) > 0 {
|
||||
if TypeOK(n.Type()) { // SSA-able type, so address was taken -- receive value in OpArg, DO NOT bind to var, store immediately to memory.
|
||||
if ssa.CanSSA(n.Type()) { // SSA-able type, so address was taken -- receive value in OpArg, DO NOT bind to var, store immediately to memory.
|
||||
v := s.newValue0A(ssa.OpArg, n.Type(), n)
|
||||
s.store(n.Type(), s.decladdrs[n], v)
|
||||
} else { // Too big for SSA.
|
||||
|
|
@ -526,7 +526,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
|||
// runtime calls that did (#43701). Since we don't
|
||||
// convert Addrtaken variables to SSA anyway, no point
|
||||
// in promoting them either.
|
||||
if n.Byval() && !n.Addrtaken() && TypeOK(n.Type()) {
|
||||
if n.Byval() && !n.Addrtaken() && ssa.CanSSA(n.Type()) {
|
||||
n.Class = ir.PAUTO
|
||||
fn.Dcl = append(fn.Dcl, n)
|
||||
s.assign(n, s.load(n.Type(), ptr), false, 0)
|
||||
|
|
@ -621,7 +621,7 @@ func (s *state) zeroResults() {
|
|||
continue
|
||||
}
|
||||
// Zero the stack location containing f.
|
||||
if typ := n.Type(); TypeOK(typ) {
|
||||
if typ := n.Type(); ssa.CanSSA(typ) {
|
||||
s.assign(n, s.zeroVal(typ), false, 0)
|
||||
} else {
|
||||
if typ.HasPointers() {
|
||||
|
|
@ -1493,7 +1493,7 @@ func (s *state) stmt(n ir.Node) {
|
|||
res, resok = s.dynamicDottype(n.Rhs[0].(*ir.DynamicTypeAssertExpr), true)
|
||||
}
|
||||
deref := false
|
||||
if !TypeOK(n.Rhs[0].Type()) {
|
||||
if !ssa.CanSSA(n.Rhs[0].Type()) {
|
||||
if res.Op != ssa.OpLoad {
|
||||
s.Fatalf("dottype of non-load")
|
||||
}
|
||||
|
|
@ -1652,7 +1652,7 @@ func (s *state) stmt(n ir.Node) {
|
|||
}
|
||||
|
||||
var r *ssa.Value
|
||||
deref := !TypeOK(t)
|
||||
deref := !ssa.CanSSA(t)
|
||||
if deref {
|
||||
if rhs == nil {
|
||||
r = nil // Signal assign to use OpZero.
|
||||
|
|
@ -3156,7 +3156,7 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value {
|
|||
p := s.addr(n)
|
||||
return s.load(n.X.Type().Elem(), p)
|
||||
case n.X.Type().IsArray():
|
||||
if TypeOK(n.X.Type()) {
|
||||
if ssa.CanSSA(n.X.Type()) {
|
||||
// SSA can handle arrays of length at most 1.
|
||||
bound := n.X.Type().NumElem()
|
||||
a := s.expr(n.X)
|
||||
|
|
@ -3359,7 +3359,7 @@ func (s *state) resultOfCall(c *ssa.Value, which int64, t *types.Type) *ssa.Valu
|
|||
pa := aux.ParamAssignmentForResult(which)
|
||||
// TODO(register args) determine if in-memory TypeOK is better loaded early from SelectNAddr or later when SelectN is expanded.
|
||||
// SelectN is better for pattern-matching and possible call-aware analysis we might want to do in the future.
|
||||
if len(pa.Registers) == 0 && !TypeOK(t) {
|
||||
if len(pa.Registers) == 0 && !ssa.CanSSA(t) {
|
||||
addr := s.newValue1I(ssa.OpSelectNAddr, types.NewPtr(t), which, c)
|
||||
return s.rawLoad(t, addr)
|
||||
}
|
||||
|
|
@ -3515,7 +3515,7 @@ func (s *state) append(n *ir.CallExpr, inplace bool) *ssa.Value {
|
|||
}
|
||||
args := make([]argRec, 0, len(n.Args[1:]))
|
||||
for _, n := range n.Args[1:] {
|
||||
if TypeOK(n.Type()) {
|
||||
if ssa.CanSSA(n.Type()) {
|
||||
args = append(args, argRec{v: s.expr(n), store: true})
|
||||
} else {
|
||||
v := s.addr(n)
|
||||
|
|
@ -5047,7 +5047,7 @@ func (s *state) openDeferRecord(n *ir.CallExpr) {
|
|||
// (therefore SSAable). val is the value to be stored. The function returns an SSA
|
||||
// value representing a pointer to the autotmp location.
|
||||
func (s *state) openDeferSave(t *types.Type, val *ssa.Value) *ssa.Value {
|
||||
if !TypeOK(t) {
|
||||
if !ssa.CanSSA(t) {
|
||||
s.Fatalf("openDeferSave of non-SSA-able type %v val=%v", t, val)
|
||||
}
|
||||
if !t.HasPointers() {
|
||||
|
|
@ -5558,7 +5558,7 @@ func (s *state) canSSA(n ir.Node) bool {
|
|||
if n.Op() != ir.ONAME {
|
||||
return false
|
||||
}
|
||||
return s.canSSAName(n.(*ir.Name)) && TypeOK(n.Type())
|
||||
return s.canSSAName(n.(*ir.Name)) && ssa.CanSSA(n.Type())
|
||||
}
|
||||
|
||||
func (s *state) canSSAName(name *ir.Name) bool {
|
||||
|
|
@ -5585,39 +5585,6 @@ func (s *state) canSSAName(name *ir.Name) bool {
|
|||
// TODO: try to make more variables SSAable?
|
||||
}
|
||||
|
||||
// TypeOK reports whether variables of type t are SSA-able.
|
||||
func TypeOK(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.TARRAY:
|
||||
// We can't do larger arrays because dynamic indexing is
|
||||
// not supported on SSA variables.
|
||||
// TODO: allow if all indexes are constant.
|
||||
if t.NumElem() <= 1 {
|
||||
return TypeOK(t.Elem())
|
||||
}
|
||||
return false
|
||||
case types.TSTRUCT:
|
||||
if t.NumFields() > ssa.MaxStruct {
|
||||
return false
|
||||
}
|
||||
for _, t1 := range t.Fields() {
|
||||
if !TypeOK(t1.Type) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// exprPtr evaluates n to a pointer and nil-checks it.
|
||||
func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value {
|
||||
p := s.expr(n)
|
||||
|
|
@ -5943,7 +5910,7 @@ func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) {
|
|||
// putArg evaluates n for the purpose of passing it as an argument to a function and returns the value for the call.
|
||||
func (s *state) putArg(n ir.Node, t *types.Type) *ssa.Value {
|
||||
var a *ssa.Value
|
||||
if !TypeOK(t) {
|
||||
if !ssa.CanSSA(t) {
|
||||
a = s.newValue2(ssa.OpDereference, t, s.addr(n), s.mem())
|
||||
} else {
|
||||
a = s.expr(n)
|
||||
|
|
@ -5961,7 +5928,7 @@ func (s *state) storeArgWithBase(n ir.Node, t *types.Type, base *ssa.Value, off
|
|||
addr = s.newValue1I(ssa.OpOffPtr, pt, off, base)
|
||||
}
|
||||
|
||||
if !TypeOK(t) {
|
||||
if !ssa.CanSSA(t) {
|
||||
a := s.addr(n)
|
||||
s.move(t, addr, a)
|
||||
return
|
||||
|
|
@ -6546,7 +6513,7 @@ func (s *state) dottype1(pos src.XPos, src, dst *types.Type, iface, source, targ
|
|||
|
||||
var tmp ir.Node // temporary for use with large types
|
||||
var addr *ssa.Value // address of tmp
|
||||
if commaok && !TypeOK(dst) {
|
||||
if commaok && !ssa.CanSSA(dst) {
|
||||
// unSSAable type, use temporary.
|
||||
// TODO: get rid of some of these temporaries.
|
||||
tmp, addr = s.temp(pos, dst)
|
||||
|
|
@ -7530,7 +7497,7 @@ func defframe(s *State, e *ssafn, f *ssa.Func) {
|
|||
continue
|
||||
}
|
||||
n, off := ssa.AutoVar(v)
|
||||
if n.Class != ir.PPARAM || n.Addrtaken() || !TypeOK(n.Type()) || !s.partLiveArgs[n] {
|
||||
if n.Class != ir.PPARAM || n.Addrtaken() || !ssa.CanSSA(n.Type()) || !s.partLiveArgs[n] {
|
||||
continue
|
||||
}
|
||||
partLiveArgsSpilled[nameOff{n, off}] = true
|
||||
|
|
@ -7539,7 +7506,7 @@ func defframe(s *State, e *ssafn, f *ssa.Func) {
|
|||
// Then, insert code to spill registers if not already.
|
||||
for _, a := range f.OwnAux.ABIInfo().InParams() {
|
||||
n, ok := a.Name.(*ir.Name)
|
||||
if !ok || n.Addrtaken() || !TypeOK(n.Type()) || !s.partLiveArgs[n] || len(a.Registers) <= 1 {
|
||||
if !ok || n.Addrtaken() || !ssa.CanSSA(n.Type()) || !s.partLiveArgs[n] || len(a.Registers) <= 1 {
|
||||
continue
|
||||
}
|
||||
rts, offs := a.RegisterTypesAndOffsets()
|
||||
|
|
@ -7970,10 +7937,6 @@ func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t
|
|||
return ssa.LocalSlot{N: n, Type: t, Off: 0, SplitOf: parent, SplitOffset: offset}
|
||||
}
|
||||
|
||||
func (e *ssafn) CanSSA(t *types.Type) bool {
|
||||
return TypeOK(t)
|
||||
}
|
||||
|
||||
// Logf logs a message from the compiler.
|
||||
func (e *ssafn) Logf(msg string, args ...interface{}) {
|
||||
if e.log {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ package walk
|
|||
import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/ssagen"
|
||||
"cmd/compile/internal/ssa"
|
||||
"cmd/compile/internal/staticdata"
|
||||
"cmd/compile/internal/staticinit"
|
||||
"cmd/compile/internal/typecheck"
|
||||
|
|
@ -18,7 +18,7 @@ import (
|
|||
// walkCompLit walks a composite literal node:
|
||||
// OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT (all CompLitExpr), or OPTRLIT (AddrExpr).
|
||||
func walkCompLit(n ir.Node, init *ir.Nodes) ir.Node {
|
||||
if isStaticCompositeLiteral(n) && !ssagen.TypeOK(n.Type()) {
|
||||
if isStaticCompositeLiteral(n) && !ssa.CanSSA(n.Type()) {
|
||||
n := n.(*ir.CompLitExpr) // not OPTRLIT
|
||||
// n can be directly represented in the read-only data section.
|
||||
// Make direct reference to the static data. See issue 12841.
|
||||
|
|
|
|||
Loading…
Reference in New Issue