[dev.ssa] cmd/compile/internal/ssa: implement ODOT

Implement ODOT.  Similar to ArrayIndex, StructSelect selects a field
out of a larger Value.

We may need more ways to rewrite StructSelect, but StructSelect/Load
is the typical way it is used.

Change-Id: Ida7b8aab3298f4754eaf9fee733974cf8736e45d
Reviewed-on: https://go-review.googlesource.com/12265
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 78cb2c8..ca523ee 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -383,6 +383,32 @@
 		}
 		goto end061edc5d85c73ad909089af2556d9380
 	end061edc5d85c73ad909089af2556d9380:
+		;
+	case OpStructSelect:
+		// match: (StructSelect [idx] (Load ptr mem))
+		// cond:
+		// result: (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
+		{
+			idx := v.AuxInt
+			if v.Args[0].Op != OpLoad {
+				goto end16fdb45e1dd08feb36e3cc3fb5ed8935
+			}
+			ptr := v.Args[0].Args[0]
+			mem := v.Args[0].Args[1]
+			v.Op = OpLoad
+			v.AuxInt = 0
+			v.Aux = nil
+			v.resetArgs()
+			v0 := v.Block.NewValue0(v.Line, OpOffPtr, TypeInvalid)
+			v0.Type = v.Type.PtrTo()
+			v0.AuxInt = idx
+			v0.AddArg(ptr)
+			v.AddArg(v0)
+			v.AddArg(mem)
+			return true
+		}
+		goto end16fdb45e1dd08feb36e3cc3fb5ed8935
+	end16fdb45e1dd08feb36e3cc3fb5ed8935:
 	}
 	return false
 }