diff options
| -rw-r--r-- | src/cmd/compile/internal/ssa/_gen/dec.rules | 3 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/_gen/generic.rules | 13 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/_gen/genericOps.go | 8 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/check.go | 4 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/copyelim.go | 6 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/decompose.go | 10 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/expand_calls.go | 8 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/opGen.go | 12 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/rewritedec.go | 21 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/rewritegeneric.go | 67 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssagen/ssa.go | 21 |
11 files changed, 76 insertions, 97 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/dec.rules b/src/cmd/compile/internal/ssa/_gen/dec.rules index a04a7cd5f8..97bc2a5978 100644 --- a/src/cmd/compile/internal/ssa/_gen/dec.rules +++ b/src/cmd/compile/internal/ssa/_gen/dec.rules @@ -101,8 +101,7 @@ (IMake _typ (StructMake ___)) => imakeOfStructMake(v) (StructSelect (IData x)) && v.Type.Size() > 0 => (IData x) -(StructSelect (IData x)) && v.Type.Size() == 0 && v.Type.IsStruct() => (StructMake) -(StructSelect (IData x)) && v.Type.Size() == 0 && v.Type.IsArray() => (ArrayMake0) +(StructSelect (IData x)) && v.Type.Size() == 0 => (Empty) (StructSelect [i] x:(StructMake ___)) => x.Args[i] diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index fe8fc5b262..37ce662381 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -941,7 +941,7 @@ // struct operations (StructSelect [i] x:(StructMake ___)) => x.Args[i] -(Load <t> _ _) && t.IsStruct() && CanSSA(t) && !t.IsSIMD() => rewriteStructLoad(v) +(Load <t> _ _) && t.IsStruct() && t.Size() > 0 && CanSSA(t) && !t.IsSIMD() => rewriteStructLoad(v) (Store _ (StructMake ___) _) => rewriteStructStore(v) (StructSelect [i] x:(Load <t> ptr mem)) && !CanSSA(t) => @@ -950,8 +950,7 @@ // Putting struct{*byte} and similar into direct interfaces. (IMake _typ (StructMake ___)) => imakeOfStructMake(v) (StructSelect (IData x)) && v.Type.Size() > 0 => (IData x) -(StructSelect (IData x)) && v.Type.Size() == 0 && v.Type.IsStruct() => (StructMake) -(StructSelect (IData x)) && v.Type.Size() == 0 && v.Type.IsArray() => (ArrayMake0) +(StructSelect (IData x)) && v.Type.Size() == 0 => (Empty) // un-SSAable values use mem->mem copies (Store {t} dst (Load src mem) mem) && !CanSSA(t) => @@ -962,19 +961,19 @@ // array ops (ArraySelect (ArrayMake1 x)) => x -(Load <t> _ _) && t.IsArray() && t.NumElem() == 0 => - (ArrayMake0) - (Load <t> ptr mem) && t.IsArray() && t.NumElem() == 1 && CanSSA(t) => (ArrayMake1 (Load <t.Elem()> ptr mem)) -(Store _ (ArrayMake0) mem) => mem (Store dst (ArrayMake1 e) mem) => (Store {e.Type} dst e mem) // Putting [1]*byte and similar into direct interfaces. (IMake _typ (ArrayMake1 val)) => (IMake _typ val) (ArraySelect [0] (IData x)) => (IData x) +// zero-sized values. +(Load <t> _ _) && t.Size() == 0 => (Empty) +(Store _ (Empty) mem) => mem + // string ops // Decomposing StringMake and lowering of StringPtr and StringLen // happens in a later pass, dec, so that these operations are available diff --git a/src/cmd/compile/internal/ssa/_gen/genericOps.go b/src/cmd/compile/internal/ssa/_gen/genericOps.go index 85bde1aab2..2f75656e0b 100644 --- a/src/cmd/compile/internal/ssa/_gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/_gen/genericOps.go @@ -537,12 +537,11 @@ var genericOps = []opData{ {name: "IData", argLength: 1}, // arg0=interface, returns data field // Structs - {name: "StructMake", argLength: -1}, // args...=field0..n-1. Returns struct with n fields. + {name: "StructMake", argLength: -1}, // args...=field0..n-1. Returns struct with n fields. Must have >0 size (use Empty otherwise). {name: "StructSelect", argLength: 1, aux: "Int64"}, // arg0=struct, auxint=field index. Returns the auxint'th field. // Arrays - {name: "ArrayMake0"}, // Returns array with 0 elements - {name: "ArrayMake1", argLength: 1}, // Returns array with 1 element + {name: "ArrayMake1", argLength: 1}, // Returns array with 1 element. Use Empty if the element is zero-sized. {name: "ArraySelect", argLength: 1, aux: "Int64"}, // arg0=array, auxint=index. Returns a[i]. // Spill&restore ops for the register allocator. These are @@ -682,6 +681,9 @@ var genericOps = []opData{ // Helper instruction which is semantically equivalent to calling runtime.memequal, but some targets may prefer to custom lower it later, e.g. for specific constant sizes. {name: "MemEq", argLength: 4, commutative: true, typ: "Bool"}, // arg0=ptr0, arg1=ptr1, arg2=size, arg3=memory. + // Value of a zero-sized type. + {name: "Empty", argLength: 0}, + // SIMD {name: "ZeroSIMD", argLength: 0}, // zero value of a vector diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 4ea8561304..a41c110faa 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -274,6 +274,10 @@ func checkFunc(f *Func) { } } + if (v.Op == OpStructMake || v.Op == OpArrayMake1) && v.Type.Size() == 0 { + f.Fatalf("zero-sized Make; use Empty instead %v", v) + } + if f.RegAlloc != nil && f.Config.SoftFloat && v.Type.IsFloat() { f.Fatalf("unexpected floating-point type %v", v.LongString()) } diff --git a/src/cmd/compile/internal/ssa/copyelim.go b/src/cmd/compile/internal/ssa/copyelim.go index 09df63565b..762ffe1bd2 100644 --- a/src/cmd/compile/internal/ssa/copyelim.go +++ b/src/cmd/compile/internal/ssa/copyelim.go @@ -105,11 +105,7 @@ func phielim(f *Func) { // This is an early place in SSA where all values are examined. // Rewrite all 0-sized Go values to remove accessors, dereferences, loads, etc. if t := v.Type; (t.IsStruct() || t.IsArray()) && t.Size() == 0 { - if t.IsStruct() { - v.reset(OpStructMake) - } else { - v.reset(OpArrayMake0) - } + v.reset(OpEmpty) } // Modify all values so no arg (including args // of OpCopy) is a copy. diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go index a3d0fbd406..6ea69da016 100644 --- a/src/cmd/compile/internal/ssa/decompose.go +++ b/src/cmd/compile/internal/ssa/decompose.go @@ -266,7 +266,7 @@ func decomposeUser(f *Func) { // returned. func decomposeUserArrayInto(f *Func, name *LocalSlot, slots []*LocalSlot) []*LocalSlot { t := name.Type - if t.NumElem() == 0 { + if t.Size() == 0 { // TODO(khr): Not sure what to do here. Probably nothing. // Names for empty arrays aren't important. return slots @@ -362,6 +362,10 @@ func decomposeUserPhi(v *Value) { // and then recursively decomposes the phis for each field. func decomposeStructPhi(v *Value) { t := v.Type + if t.Size() == 0 { + v.reset(OpEmpty) + return + } n := t.NumFields() fields := make([]*Value, 0, MaxStruct) for i := 0; i < n; i++ { @@ -385,8 +389,8 @@ func decomposeStructPhi(v *Value) { // and then recursively decomposes the element phi. func decomposeArrayPhi(v *Value) { t := v.Type - if t.NumElem() == 0 { - v.reset(OpArrayMake0) + if t.Size() == 0 { + v.reset(OpEmpty) return } if t.NumElem() != 1 { diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index ba2bedc65f..3b434e4791 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -508,13 +508,7 @@ func (x *expandState) rewriteSelectOrArg(pos src.XPos, b *Block, container, a, m if at.Size() == 0 { // For consistency, create these values even though they'll ultimately be unused - if at.IsArray() { - return makeOf(a, OpArrayMake0, nil) - } - if at.IsStruct() { - return makeOf(a, OpStructMake, nil) - } - return a + return makeOf(a, OpEmpty, nil) } sk := selKey{from: container, size: 0, offsetOrIndex: rc.storeOffset, typ: at} diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 816b078605..db0a152ae8 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -6034,7 +6034,6 @@ const ( OpIData OpStructMake OpStructSelect - OpArrayMake0 OpArrayMake1 OpArraySelect OpStoreReg @@ -6126,6 +6125,7 @@ const ( OpPrefetchCache OpPrefetchCacheStreamed OpMemEq + OpEmpty OpZeroSIMD OpCvt16toMask8x16 OpCvt32toMask8x32 @@ -88195,11 +88195,6 @@ var opcodeTable = [...]opInfo{ generic: true, }, { - name: "ArrayMake0", - argLen: 0, - generic: true, - }, - { name: "ArrayMake1", argLen: 1, generic: true, @@ -88720,6 +88715,11 @@ var opcodeTable = [...]opInfo{ generic: true, }, { + name: "Empty", + argLen: 0, + generic: true, + }, + { name: "ZeroSIMD", argLen: 0, generic: true, diff --git a/src/cmd/compile/internal/ssa/rewritedec.go b/src/cmd/compile/internal/ssa/rewritedec.go index 1e5c19cd23..1141d322bf 100644 --- a/src/cmd/compile/internal/ssa/rewritedec.go +++ b/src/cmd/compile/internal/ssa/rewritedec.go @@ -868,29 +868,16 @@ func rewriteValuedec_OpStructSelect(v *Value) bool { return true } // match: (StructSelect (IData x)) - // cond: v.Type.Size() == 0 && v.Type.IsStruct() - // result: (StructMake) + // cond: v.Type.Size() == 0 + // result: (Empty) for { if v_0.Op != OpIData { break } - if !(v.Type.Size() == 0 && v.Type.IsStruct()) { + if !(v.Type.Size() == 0) { break } - v.reset(OpStructMake) - return true - } - // match: (StructSelect (IData x)) - // cond: v.Type.Size() == 0 && v.Type.IsArray() - // result: (ArrayMake0) - for { - if v_0.Op != OpIData { - break - } - if !(v.Type.Size() == 0 && v.Type.IsArray()) { - break - } - v.reset(OpArrayMake0) + v.reset(OpEmpty) return true } // match: (StructSelect [i] x:(StructMake ___)) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index dbbb7105af..be944ef854 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -12420,27 +12420,16 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { return true } // match: (Load <t> _ _) - // cond: t.IsStruct() && CanSSA(t) && !t.IsSIMD() + // cond: t.IsStruct() && t.Size() > 0 && CanSSA(t) && !t.IsSIMD() // result: rewriteStructLoad(v) for { t := v.Type - if !(t.IsStruct() && CanSSA(t) && !t.IsSIMD()) { + if !(t.IsStruct() && t.Size() > 0 && CanSSA(t) && !t.IsSIMD()) { break } v.copyOf(rewriteStructLoad(v)) return true } - // match: (Load <t> _ _) - // cond: t.IsArray() && t.NumElem() == 0 - // result: (ArrayMake0) - for { - t := v.Type - if !(t.IsArray() && t.NumElem() == 0) { - break - } - v.reset(OpArrayMake0) - return true - } // match: (Load <t> ptr mem) // cond: t.IsArray() && t.NumElem() == 1 && CanSSA(t) // result: (ArrayMake1 (Load <t.Elem()> ptr mem)) @@ -12457,6 +12446,17 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { v.AddArg(v0) return true } + // match: (Load <t> _ _) + // cond: t.Size() == 0 + // result: (Empty) + for { + t := v.Type + if !(t.Size() == 0) { + break + } + v.reset(OpEmpty) + return true + } // match: (Load <typ.Int8> sptr:(Addr {scon} (SB)) mem) // cond: symIsRO(scon) // result: (Const8 <typ.Int8> [int8(read8(scon,0))]) @@ -32005,16 +32005,6 @@ func rewriteValuegeneric_OpStore(v *Value) bool { v.AddArg3(dst, src, v0) return true } - // match: (Store _ (ArrayMake0) mem) - // result: mem - for { - if v_1.Op != OpArrayMake0 { - break - } - mem := v_2 - v.copyOf(mem) - return true - } // match: (Store dst (ArrayMake1 e) mem) // result: (Store {e.Type} dst e mem) for { @@ -32029,6 +32019,16 @@ func rewriteValuegeneric_OpStore(v *Value) bool { v.AddArg3(dst, e, mem) return true } + // match: (Store _ (Empty) mem) + // result: mem + for { + if v_1.Op != OpEmpty { + break + } + mem := v_2 + v.copyOf(mem) + return true + } // match: (Store (SelectN [0] call:(StaticLECall ___)) x mem:(SelectN [1] call)) // cond: isConstZero(x) && isMalloc(call.Aux) // result: mem @@ -32520,29 +32520,16 @@ func rewriteValuegeneric_OpStructSelect(v *Value) bool { return true } // match: (StructSelect (IData x)) - // cond: v.Type.Size() == 0 && v.Type.IsStruct() - // result: (StructMake) - for { - if v_0.Op != OpIData { - break - } - if !(v.Type.Size() == 0 && v.Type.IsStruct()) { - break - } - v.reset(OpStructMake) - return true - } - // match: (StructSelect (IData x)) - // cond: v.Type.Size() == 0 && v.Type.IsArray() - // result: (ArrayMake0) + // cond: v.Type.Size() == 0 + // result: (Empty) for { if v_0.Op != OpIData { break } - if !(v.Type.Size() == 0 && v.Type.IsArray()) { + if !(v.Type.Size() == 0) { break } - v.reset(OpArrayMake0) + v.reset(OpEmpty) return true } return false diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 50b4e11f5e..3f4a4cf31e 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4488,6 +4488,11 @@ func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool // Grab old value of structure. old := s.expr(left.X) + if left.Type().Size() == 0 { + // Nothing to do when assigning zero-sized things. + return + } + // Make new structure. new := s.newValue0(ssa.OpStructMake, t) @@ -4525,6 +4530,10 @@ func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool if n != 1 { s.Fatalf("assigning to non-1-length array") } + if t.Size() == 0 { + return + } + // Rewrite to a = [1]{v} len := s.constInt(types.Types[types.TINT], 1) s.boundsCheck(i, len, ssa.BoundsIndex, false) // checks i == 0 @@ -4570,6 +4579,9 @@ func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool // zeroVal returns the zero value for type t. func (s *state) zeroVal(t *types.Type) *ssa.Value { + if t.Size() == 0 { + return s.entryNewValue0(ssa.OpEmpty, t) + } switch { case t.IsInteger(): switch t.Size() { @@ -4622,13 +4634,8 @@ func (s *state) zeroVal(t *types.Type) *ssa.Value { v.AddArg(s.zeroVal(t.FieldType(i))) } return v - case t.IsArray(): - switch t.NumElem() { - case 0: - return s.entryNewValue0(ssa.OpArrayMake0, t) - case 1: - return s.entryNewValue1(ssa.OpArrayMake1, t, s.zeroVal(t.Elem())) - } + case t.IsArray() && t.NumElem() == 1: + return s.entryNewValue1(ssa.OpArrayMake1, t, s.zeroVal(t.Elem())) case t.IsSIMD(): return s.newValue0(ssa.OpZeroSIMD, t) } |
