aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/ssa/_gen/dec.rules3
-rw-r--r--src/cmd/compile/internal/ssa/_gen/generic.rules13
-rw-r--r--src/cmd/compile/internal/ssa/_gen/genericOps.go8
-rw-r--r--src/cmd/compile/internal/ssa/check.go4
-rw-r--r--src/cmd/compile/internal/ssa/copyelim.go6
-rw-r--r--src/cmd/compile/internal/ssa/decompose.go10
-rw-r--r--src/cmd/compile/internal/ssa/expand_calls.go8
-rw-r--r--src/cmd/compile/internal/ssa/opGen.go12
-rw-r--r--src/cmd/compile/internal/ssa/rewritedec.go21
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go67
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go21
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)
}