aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/decompose.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2016-01-11 21:05:33 -0800
committerKeith Randall <khr@golang.org>2016-01-20 22:37:11 +0000
commita734bbc95349a487c78ff02eda07e3f219808be3 (patch)
treefcd7692dd11201d31597f31c14f03efa481671c6 /src/cmd/compile/internal/ssa/decompose.go
parentb5c5efd5de4c4668b149d1dba4d9b00c88dd0b80 (diff)
downloadgo-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.go91
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")
}