diff options
author | Keith Randall <khr@golang.org> | 2016-01-11 21:05:33 -0800 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2016-01-20 22:37:11 +0000 |
commit | a734bbc95349a487c78ff02eda07e3f219808be3 (patch) | |
tree | fcd7692dd11201d31597f31c14f03efa481671c6 /src/cmd/compile/internal/ssa/decompose.go | |
parent | b5c5efd5de4c4668b149d1dba4d9b00c88dd0b80 (diff) | |
download | go-a734bbc95349a487c78ff02eda07e3f219808be3.tar.gz go-a734bbc95349a487c78ff02eda07e3f219808be3.zip |
[dev.ssa] cmd/compile: Allow structs to be SSAd
Break small structs up into their components so they
can be registerized.
Change StructSelect to use field indexes instead of
field offsets, as field offsets aren't unique in the
presence of zero-sized fields.
Change-Id: I2f1dc89f7fa58e1cf58aa1a32b238959d53f62e4
Reviewed-on: https://go-review.googlesource.com/18570
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/decompose.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/decompose.go | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go index c8a1df281a..6dc11250ca 100644 --- a/src/cmd/compile/internal/ssa/decompose.go +++ b/src/cmd/compile/internal/ssa/decompose.go @@ -13,23 +13,9 @@ func decompose(f *Func) { if v.Op != OpPhi { continue } - switch { - case v.Type.IsComplex(): - decomposeComplexPhi(v) - case v.Type.IsString(): - decomposeStringPhi(v) - case v.Type.IsSlice(): - decomposeSlicePhi(v) - case v.Type.IsInterface(): - decomposeInterfacePhi(v) - //case v.Type.IsStruct(): - // decomposeStructPhi(v) - case v.Type.Size() > f.Config.IntSize: - f.Unimplementedf("undecomposed type %s", v.Type) - } + decomposePhi(v) } } - // TODO: decompose 64-bit ops on 32-bit archs? // Split up named values into their components. // NOTE: the component values we are making are dead at this point. @@ -92,14 +78,39 @@ func decompose(f *Func) { f.NamedValues[typeName] = append(f.NamedValues[typeName], typ) f.NamedValues[dataName] = append(f.NamedValues[dataName], data) } - //case t.IsStruct(): - // TODO + case t.IsStruct(): + n := t.NumFields() + for _, v := range f.NamedValues[name] { + for i := int64(0); i < n; i++ { + fname := LocalSlot{name.N, t.FieldType(i), name.Off + t.FieldOff(i)} // TODO: use actual field name? + x := v.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), i, v) + f.NamedValues[fname] = append(f.NamedValues[fname], x) + } + } case t.Size() > f.Config.IntSize: - f.Unimplementedf("undecomposed type %s", t) + f.Unimplementedf("undecomposed named type %s", t) } } } +func decomposePhi(v *Value) { + // TODO: decompose 64-bit ops on 32-bit archs? + switch { + case v.Type.IsComplex(): + decomposeComplexPhi(v) + case v.Type.IsString(): + decomposeStringPhi(v) + case v.Type.IsSlice(): + decomposeSlicePhi(v) + case v.Type.IsInterface(): + decomposeInterfacePhi(v) + case v.Type.IsStruct(): + decomposeStructPhi(v) + case v.Type.Size() > v.Block.Func.Config.IntSize: + v.Unimplementedf("undecomposed type %s", v.Type) + } +} + func decomposeStringPhi(v *Value) { fe := v.Block.Func.Config.fe ptrType := fe.TypeBytePtr() @@ -184,5 +195,47 @@ func decomposeInterfacePhi(v *Value) { v.AddArg(data) } func decomposeStructPhi(v *Value) { - // TODO + t := v.Type + n := t.NumFields() + var fields [MaxStruct]*Value + for i := int64(0); i < n; i++ { + fields[i] = v.Block.NewValue0(v.Line, OpPhi, t.FieldType(i)) + } + for _, a := range v.Args { + for i := int64(0); i < n; i++ { + fields[i].AddArg(a.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), i, a)) + } + } + v.Op = StructMakeOp(n) + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArgs(fields[:n]...) + + // Recursively decompose phis for each field. + for _, f := range fields[:n] { + decomposePhi(f) + } +} + +// MaxStruct is the maximum number of fields a struct +// can have and still be SSAable. +const MaxStruct = 4 + +// StructMakeOp returns the opcode to construct a struct with the +// given number of fields. +func StructMakeOp(nf int64) Op { + switch nf { + case 0: + return OpStructMake0 + case 1: + return OpStructMake1 + case 2: + return OpStructMake2 + case 3: + return OpStructMake3 + case 4: + return OpStructMake4 + } + panic("too many fields in an SSAable struct") } |