aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/decompose.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ssa/decompose.go')
-rw-r--r--src/cmd/compile/internal/ssa/decompose.go140
1 files changed, 87 insertions, 53 deletions
diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go
index ba48b6b3b9..753d69cebc 100644
--- a/src/cmd/compile/internal/ssa/decompose.go
+++ b/src/cmd/compile/internal/ssa/decompose.go
@@ -36,64 +36,65 @@ func decomposeBuiltIn(f *Func) {
// accumulate new LocalSlots in newNames for addition after the iteration. This decomposition is for
// builtin types with leaf components, and thus there is no need to reprocess the newly create LocalSlots.
var toDelete []namedVal
- var newNames []LocalSlot
+ var newNames []*LocalSlot
for i, name := range f.Names {
t := name.Type
switch {
case t.IsInteger() && t.Size() > f.Config.RegSize:
- hiName, loName := f.fe.SplitInt64(name)
- newNames = append(newNames, hiName, loName)
- for j, v := range f.NamedValues[name] {
+ hiName, loName := f.SplitInt64(name)
+ newNames = maybeAppend2(f, newNames, hiName, loName)
+ for j, v := range f.NamedValues[*name] {
if v.Op != OpInt64Make {
continue
}
- f.NamedValues[hiName] = append(f.NamedValues[hiName], v.Args[0])
- f.NamedValues[loName] = append(f.NamedValues[loName], v.Args[1])
+ f.NamedValues[*hiName] = append(f.NamedValues[*hiName], v.Args[0])
+ f.NamedValues[*loName] = append(f.NamedValues[*loName], v.Args[1])
toDelete = append(toDelete, namedVal{i, j})
}
case t.IsComplex():
- rName, iName := f.fe.SplitComplex(name)
- newNames = append(newNames, rName, iName)
- for j, v := range f.NamedValues[name] {
+ rName, iName := f.SplitComplex(name)
+ newNames = maybeAppend2(f, newNames, rName, iName)
+ for j, v := range f.NamedValues[*name] {
if v.Op != OpComplexMake {
continue
}
- f.NamedValues[rName] = append(f.NamedValues[rName], v.Args[0])
- f.NamedValues[iName] = append(f.NamedValues[iName], v.Args[1])
+ f.NamedValues[*rName] = append(f.NamedValues[*rName], v.Args[0])
+ f.NamedValues[*iName] = append(f.NamedValues[*iName], v.Args[1])
toDelete = append(toDelete, namedVal{i, j})
}
case t.IsString():
- ptrName, lenName := f.fe.SplitString(name)
- newNames = append(newNames, ptrName, lenName)
- for j, v := range f.NamedValues[name] {
+ ptrName, lenName := f.SplitString(name)
+ newNames = maybeAppend2(f, newNames, ptrName, lenName)
+ for j, v := range f.NamedValues[*name] {
if v.Op != OpStringMake {
continue
}
- f.NamedValues[ptrName] = append(f.NamedValues[ptrName], v.Args[0])
- f.NamedValues[lenName] = append(f.NamedValues[lenName], v.Args[1])
+ f.NamedValues[*ptrName] = append(f.NamedValues[*ptrName], v.Args[0])
+ f.NamedValues[*lenName] = append(f.NamedValues[*lenName], v.Args[1])
toDelete = append(toDelete, namedVal{i, j})
}
case t.IsSlice():
- ptrName, lenName, capName := f.fe.SplitSlice(name)
- newNames = append(newNames, ptrName, lenName, capName)
- for j, v := range f.NamedValues[name] {
+ ptrName, lenName, capName := f.SplitSlice(name)
+ newNames = maybeAppend2(f, newNames, ptrName, lenName)
+ newNames = maybeAppend(f, newNames, capName)
+ for j, v := range f.NamedValues[*name] {
if v.Op != OpSliceMake {
continue
}
- f.NamedValues[ptrName] = append(f.NamedValues[ptrName], v.Args[0])
- f.NamedValues[lenName] = append(f.NamedValues[lenName], v.Args[1])
- f.NamedValues[capName] = append(f.NamedValues[capName], v.Args[2])
+ f.NamedValues[*ptrName] = append(f.NamedValues[*ptrName], v.Args[0])
+ f.NamedValues[*lenName] = append(f.NamedValues[*lenName], v.Args[1])
+ f.NamedValues[*capName] = append(f.NamedValues[*capName], v.Args[2])
toDelete = append(toDelete, namedVal{i, j})
}
case t.IsInterface():
- typeName, dataName := f.fe.SplitInterface(name)
- newNames = append(newNames, typeName, dataName)
- for j, v := range f.NamedValues[name] {
+ typeName, dataName := f.SplitInterface(name)
+ newNames = maybeAppend2(f, newNames, typeName, dataName)
+ for j, v := range f.NamedValues[*name] {
if v.Op != OpIMake {
continue
}
- f.NamedValues[typeName] = append(f.NamedValues[typeName], v.Args[0])
- f.NamedValues[dataName] = append(f.NamedValues[dataName], v.Args[1])
+ f.NamedValues[*typeName] = append(f.NamedValues[*typeName], v.Args[0])
+ f.NamedValues[*dataName] = append(f.NamedValues[*dataName], v.Args[1])
toDelete = append(toDelete, namedVal{i, j})
}
case t.IsFloat():
@@ -107,6 +108,18 @@ func decomposeBuiltIn(f *Func) {
f.Names = append(f.Names, newNames...)
}
+func maybeAppend(f *Func, ss []*LocalSlot, s *LocalSlot) []*LocalSlot {
+ if _, ok := f.NamedValues[*s]; !ok {
+ f.NamedValues[*s] = nil
+ return append(ss, s)
+ }
+ return ss
+}
+
+func maybeAppend2(f *Func, ss []*LocalSlot, s1, s2 *LocalSlot) []*LocalSlot {
+ return maybeAppend(f, maybeAppend(f, ss, s1), s2)
+}
+
func decomposeBuiltInPhi(v *Value) {
switch {
case v.Type.IsInteger() && v.Type.Size() > v.Block.Func.Config.RegSize:
@@ -230,7 +243,7 @@ func decomposeUser(f *Func) {
}
// Split up named values into their components.
i := 0
- var newNames []LocalSlot
+ var newNames []*LocalSlot
for _, name := range f.Names {
t := name.Type
switch {
@@ -250,7 +263,7 @@ func decomposeUser(f *Func) {
// decomposeUserArrayInto creates names for the element(s) of arrays referenced
// by name where possible, and appends those new names to slots, which is then
// returned.
-func decomposeUserArrayInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalSlot {
+func decomposeUserArrayInto(f *Func, name *LocalSlot, slots []*LocalSlot) []*LocalSlot {
t := name.Type
if t.NumElem() == 0 {
// TODO(khr): Not sure what to do here. Probably nothing.
@@ -261,20 +274,20 @@ func decomposeUserArrayInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalS
// shouldn't get here due to CanSSA
f.Fatalf("array not of size 1")
}
- elemName := f.fe.SplitArray(name)
+ elemName := f.SplitArray(name)
var keep []*Value
- for _, v := range f.NamedValues[name] {
+ for _, v := range f.NamedValues[*name] {
if v.Op != OpArrayMake1 {
keep = append(keep, v)
continue
}
- f.NamedValues[elemName] = append(f.NamedValues[elemName], v.Args[0])
+ f.NamedValues[*elemName] = append(f.NamedValues[*elemName], v.Args[0])
}
if len(keep) == 0 {
// delete the name for the array as a whole
- delete(f.NamedValues, name)
+ delete(f.NamedValues, *name)
} else {
- f.NamedValues[name] = keep
+ f.NamedValues[*name] = keep
}
if t.Elem().IsArray() {
@@ -289,38 +302,38 @@ func decomposeUserArrayInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalS
// decomposeUserStructInto creates names for the fields(s) of structs referenced
// by name where possible, and appends those new names to slots, which is then
// returned.
-func decomposeUserStructInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalSlot {
- fnames := []LocalSlot{} // slots for struct in name
+func decomposeUserStructInto(f *Func, name *LocalSlot, slots []*LocalSlot) []*LocalSlot {
+ fnames := []*LocalSlot{} // slots for struct in name
t := name.Type
n := t.NumFields()
for i := 0; i < n; i++ {
- fs := f.fe.SplitStruct(name, i)
+ fs := f.SplitStruct(name, i)
fnames = append(fnames, fs)
// arrays and structs will be decomposed further, so
// there's no need to record a name
if !fs.Type.IsArray() && !fs.Type.IsStruct() {
- slots = append(slots, fs)
+ slots = maybeAppend(f, slots, fs)
}
}
makeOp := StructMakeOp(n)
var keep []*Value
// create named values for each struct field
- for _, v := range f.NamedValues[name] {
+ for _, v := range f.NamedValues[*name] {
if v.Op != makeOp {
keep = append(keep, v)
continue
}
for i := 0; i < len(fnames); i++ {
- f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], v.Args[i])
+ f.NamedValues[*fnames[i]] = append(f.NamedValues[*fnames[i]], v.Args[i])
}
}
if len(keep) == 0 {
// delete the name for the struct as a whole
- delete(f.NamedValues, name)
+ delete(f.NamedValues, *name)
} else {
- f.NamedValues[name] = keep
+ f.NamedValues[*name] = keep
}
// now that this f.NamedValues contains values for the struct
@@ -328,10 +341,10 @@ func decomposeUserStructInto(f *Func, name LocalSlot, slots []LocalSlot) []Local
for i := 0; i < n; i++ {
if name.Type.FieldType(i).IsStruct() {
slots = decomposeUserStructInto(f, fnames[i], slots)
- delete(f.NamedValues, fnames[i])
+ delete(f.NamedValues, *fnames[i])
} else if name.Type.FieldType(i).IsArray() {
slots = decomposeUserArrayInto(f, fnames[i], slots)
- delete(f.NamedValues, fnames[i])
+ delete(f.NamedValues, *fnames[i])
}
}
return slots
@@ -416,9 +429,10 @@ type namedVal struct {
locIndex, valIndex int // f.NamedValues[f.Names[locIndex]][valIndex] = key
}
-// deleteNamedVals removes particular values with debugger names from f's naming data structures
+// deleteNamedVals removes particular values with debugger names from f's naming data structures,
+// removes all values with OpInvalid, and re-sorts the list of Names.
func deleteNamedVals(f *Func, toDelete []namedVal) {
- // Arrange to delete from larger indices to smaller, to ensure swap-with-end deletion does not invalid pending indices.
+ // Arrange to delete from larger indices to smaller, to ensure swap-with-end deletion does not invalidate pending indices.
sort.Slice(toDelete, func(i, j int) bool {
if toDelete[i].locIndex != toDelete[j].locIndex {
return toDelete[i].locIndex > toDelete[j].locIndex
@@ -430,16 +444,36 @@ func deleteNamedVals(f *Func, toDelete []namedVal) {
// Get rid of obsolete names
for _, d := range toDelete {
loc := f.Names[d.locIndex]
- vals := f.NamedValues[loc]
+ vals := f.NamedValues[*loc]
l := len(vals) - 1
if l > 0 {
vals[d.valIndex] = vals[l]
- f.NamedValues[loc] = vals[:l]
- } else {
- delete(f.NamedValues, loc)
- l = len(f.Names) - 1
- f.Names[d.locIndex] = f.Names[l]
- f.Names = f.Names[:l]
+ }
+ vals[l] = nil
+ f.NamedValues[*loc] = vals[:l]
+ }
+ // Delete locations with no values attached.
+ end := len(f.Names)
+ for i := len(f.Names) - 1; i >= 0; i-- {
+ loc := f.Names[i]
+ vals := f.NamedValues[*loc]
+ last := len(vals)
+ for j := len(vals) - 1; j >= 0; j-- {
+ if vals[j].Op == OpInvalid {
+ last--
+ vals[j] = vals[last]
+ vals[last] = nil
+ }
+ }
+ if last < len(vals) {
+ f.NamedValues[*loc] = vals[:last]
+ }
+ if len(vals) == 0 {
+ delete(f.NamedValues, *loc)
+ end--
+ f.Names[i] = f.Names[end]
+ f.Names[end] = nil
}
}
+ f.Names = f.Names[:end]
}