]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: implement ITAB
authorKeith Randall <khr@golang.org>
Tue, 4 Aug 2015 22:47:22 +0000 (15:47 -0700)
committerKeith Randall <khr@golang.org>
Tue, 4 Aug 2015 23:32:42 +0000 (23:32 +0000)
Implement ITAB, selecting the itable field of an interface.

Soften the lowering check to allow lowerings that leave
generic but dead ops behind.  (The ITAB lowering does this.)

Change-Id: Icc84961dd4060d143602f001311aa1d8be0d7fc0
Reviewed-on: https://go-review.googlesource.com/13144
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/compile.go
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/lower.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteAMD64.go

index 247eacbee4b9c78e01078098ee6621dbc8264f2a..b63b66212622386c27b10d10abb89e77d5e490fa 100644 (file)
@@ -1247,6 +1247,10 @@ func (s *state) expr(n *Node) *ssa.Value {
                        return s.constInt(Types[TINT], n.Left.Type.Bound)
                }
 
+       case OITAB:
+               a := s.expr(n.Left)
+               return s.newValue1(ssa.OpITab, n.Type, a)
+
        case OCALLFUNC, OCALLMETH:
                left := n.Left
                static := left.Op == ONAME && left.Class == PFUNC
index 001530ae8011adfc50eeb89263e5854c08f2be94..9111254a3218454af6f63e14992b0ba9dbf0e315 100644 (file)
@@ -68,6 +68,7 @@ var passes = [...]pass{
        {"lower", lower},
        {"lowered cse", cse},
        {"lowered deadcode", deadcode},
+       {"checkLower", checkLower},
        {"critical", critical}, // remove critical edges
        {"layout", layout},     // schedule blocks
        {"schedule", schedule}, // schedule values
@@ -101,6 +102,9 @@ var passOrder = [...]constraint{
        {"schedule", "regalloc"},
        // stack allocation requires register allocation
        {"regalloc", "stackalloc"},
+       // checkLower must run after lowering & subsequent dead code elim
+       {"lower", "checkLower"},
+       {"lowered deadcode", "checkLower"},
 }
 
 func init() {
index dd34404b70d148f91713a78d2383e1386b1316dc..e7c712eb17480364bce95ed53736893d644d1af4 100644 (file)
 
 (Addr {sym} base) -> (LEAQ {sym} base)
 
+(ITab (Load ptr mem)) -> (MOVQload ptr mem)
+
 // block rewrites
 (If (SETL cmp) yes no) -> (LT cmp yes no)
 (If (SETLE cmp) yes no) -> (LE cmp yes no)
index 7536415216a62baac2d99d9ed9f13131f73a5f24..657973e3332500780216a5acea2398bfad07c8b7 100644 (file)
@@ -244,6 +244,9 @@ var genericOps = []opData{
        {name: "StringPtr"},  // ptr(arg0)
        {name: "StringLen"},  // len(arg0)
 
+       // Interfaces
+       {name: "ITab"}, // arg0=interface, returns itable field
+
        // Spill&restore ops for the register allocator.  These are
        // semantically identical to OpCopy; they do not take/return
        // stores like regular memory ops do.  We can get away without memory
index 6499dc8565d458af41ef57457a3208e87897680c..6f6b885062cfa6f4c1e57690bb9a479f1ff6ca15 100644 (file)
@@ -8,8 +8,13 @@ package ssa
 func lower(f *Func) {
        // repeat rewrites until we find no more rewrites
        applyRewrite(f, f.Config.lowerBlock, f.Config.lowerValue)
+}
 
-       // Check for unlowered opcodes, fail if we find one.
+// checkLower checks for unlowered opcodes and fails if we find one.
+func checkLower(f *Func) {
+       // Needs to be a separate phase because it must run after both
+       // lowering and a subsequent dead code elimination (because lowering
+       // rules may leave dead generic ops behind).
        for _, b := range f.Blocks {
                for _, v := range b.Values {
                        if opcodeTable[v.Op].generic && v.Op != OpSP && v.Op != OpSB && v.Op != OpArg && v.Op != OpCopy && v.Op != OpPhi {
index b0f86a9cbee4a9545e592ae70260873c1905d40f..e77df40ebdd9d03cd01404d289e7ec27cfc0c2b6 100644 (file)
@@ -370,6 +370,7 @@ const (
        OpStringMake
        OpStringPtr
        OpStringLen
+       OpITab
        OpStoreReg
        OpLoadReg
        OpFwdRef
@@ -2773,6 +2774,10 @@ var opcodeTable = [...]opInfo{
                name:    "StringLen",
                generic: true,
        },
+       {
+               name:    "ITab",
+               generic: true,
+       },
        {
                name:    "StoreReg",
                generic: true,
index 5a87169324b6ab003333c18aabc55c27c58325e8..1e7d957f9266511e984c1cdc04718b9c9d0ca41f 100644 (file)
@@ -1972,6 +1972,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
                goto end22eaafbcfe70447f79d9b3e6cc395bbd
        end22eaafbcfe70447f79d9b3e6cc395bbd:
                ;
+       case OpITab:
+               // match: (ITab (Load ptr mem))
+               // cond:
+               // result: (MOVQload ptr mem)
+               {
+                       if v.Args[0].Op != OpLoad {
+                               goto enda49fcae3630a097c78aa58189c90a97a
+                       }
+                       ptr := v.Args[0].Args[0]
+                       mem := v.Args[0].Args[1]
+                       v.Op = OpAMD64MOVQload
+                       v.AuxInt = 0
+                       v.Aux = nil
+                       v.resetArgs()
+                       v.AddArg(ptr)
+                       v.AddArg(mem)
+                       return true
+               }
+               goto enda49fcae3630a097c78aa58189c90a97a
+       enda49fcae3630a097c78aa58189c90a97a:
+               ;
        case OpIsInBounds:
                // match: (IsInBounds idx len)
                // cond: