diff options
Diffstat (limited to 'src/cmd/compile/internal/ssa/decompose.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/decompose.go | 140 |
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] } |