]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: fix iface and slice comparisons
authorKeith Randall <khr@golang.org>
Thu, 10 Sep 2015 20:53:27 +0000 (13:53 -0700)
committerKeith Randall <khr@golang.org>
Wed, 16 Sep 2015 23:21:15 +0000 (23:21 +0000)
A simpler way to do iface/slice comparisons.  Fixes some
cases of failed lowerings.

Change-Id: Ia252bc8648293a2d460f63c41f1591785543a1e9
Reviewed-on: https://go-review.googlesource.com/14493
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewritegeneric.go

index 5cd074b0c6d5d1b414dd1f71975e37a1b8d3bdda..30c3f2f88c51bdb13f1a188c2d193aafee81b863 100644 (file)
@@ -950,8 +950,8 @@ var opToSSA = map[opAndType]ssa.Op{
        opAndType{OEQ, TUINT32}:    ssa.OpEq32,
        opAndType{OEQ, TINT64}:     ssa.OpEq64,
        opAndType{OEQ, TUINT64}:    ssa.OpEq64,
-       opAndType{OEQ, TINTER}:     ssa.OpEqFat, // e == nil only
-       opAndType{OEQ, TARRAY}:     ssa.OpEqFat, // slice only; a == nil only
+       opAndType{OEQ, TINTER}:     ssa.OpEqInter,
+       opAndType{OEQ, TARRAY}:     ssa.OpEqSlice,
        opAndType{OEQ, TFUNC}:      ssa.OpEqPtr,
        opAndType{OEQ, TMAP}:       ssa.OpEqPtr,
        opAndType{OEQ, TCHAN}:      ssa.OpEqPtr,
@@ -970,8 +970,8 @@ var opToSSA = map[opAndType]ssa.Op{
        opAndType{ONE, TUINT32}:    ssa.OpNeq32,
        opAndType{ONE, TINT64}:     ssa.OpNeq64,
        opAndType{ONE, TUINT64}:    ssa.OpNeq64,
-       opAndType{ONE, TINTER}:     ssa.OpNeqFat, // e != nil only
-       opAndType{ONE, TARRAY}:     ssa.OpNeqFat, // slice only; a != nil only
+       opAndType{ONE, TINTER}:     ssa.OpNeqInter,
+       opAndType{ONE, TARRAY}:     ssa.OpNeqSlice,
        opAndType{ONE, TFUNC}:      ssa.OpNeqPtr,
        opAndType{ONE, TMAP}:       ssa.OpNeqPtr,
        opAndType{ONE, TCHAN}:      ssa.OpNeqPtr,
@@ -1522,7 +1522,6 @@ func (s *state) expr(n *Node) *ssa.Value {
                        default:
                                s.Fatalf("ordered complex compare %s", opnames[n.Op])
                        }
-
                }
                return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b)
        case OMUL:
index b704014287f0fde69f2f6848231c490c3989aa8a..f54496e8a871ab0a9f26e542bc69ef12c9be27f1 100644 (file)
 (EqPtr (ConstNil) p) -> (Not (IsNonNil p))
 
 // slice and interface comparisons
-// the frontend ensures that we can only compare against nil
-// start by putting nil on the right to simplify the other rules
-(EqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (EqFat y x)
-(NeqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (NeqFat y x)
-// it suffices to check the first word (backing array for slices, dynamic type for interfaces)
-(EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr [0]))
-(NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr [0]))
+// The frontend ensures that we can only compare against nil,
+// so we need only compare the first word (interface type or slice ptr).
+(EqInter x y)  -> (EqPtr  (ITab x) (ITab y))
+(NeqInter x y) -> (NeqPtr (ITab x) (ITab y))
+(EqSlice x y)  -> (EqPtr  (SlicePtr x) (SlicePtr y))
+(NeqSlice x y) -> (NeqPtr (SlicePtr x) (SlicePtr y))
 
 // indexing operations
 // Note: bounds check has already been done
index dcaff959c3882764e279678d542bb015ec4f92b4..71683c16bd5dea99712bc42600824a8b0d12efe2 100644 (file)
@@ -160,7 +160,8 @@ var genericOps = []opData{
        {name: "Eq32"},
        {name: "Eq64"},
        {name: "EqPtr"},
-       {name: "EqFat"}, // slice/interface; arg0 or arg1 is nil; other cases handled by frontend
+       {name: "EqInter"}, // arg0 or arg1 is nil; other cases handled by frontend
+       {name: "EqSlice"}, // arg0 or arg1 is nil; other cases handled by frontend
        {name: "Eq32F"},
        {name: "Eq64F"},
 
@@ -169,7 +170,8 @@ var genericOps = []opData{
        {name: "Neq32"},
        {name: "Neq64"},
        {name: "NeqPtr"},
-       {name: "NeqFat"}, // slice/interface; arg0 or arg1 is nil; other cases handled by frontend
+       {name: "NeqInter"}, // arg0 or arg1 is nil; other cases handled by frontend
+       {name: "NeqSlice"}, // arg0 or arg1 is nil; other cases handled by frontend
        {name: "Neq32F"},
        {name: "Neq64F"},
 
@@ -334,10 +336,10 @@ var genericOps = []opData{
        {name: "StructSelect"}, // arg0=struct, auxint=field offset.  Returns field at that offset (size=size of result type)
 
        // Slices
-       {name: "SliceMake"}, // arg0=ptr, arg1=len, arg2=cap
-       {name: "SlicePtr"},  // ptr(arg0)
-       {name: "SliceLen"},  // len(arg0)
-       {name: "SliceCap"},  // cap(arg0)
+       {name: "SliceMake"},                // arg0=ptr, arg1=len, arg2=cap
+       {name: "SlicePtr", typ: "Uintptr"}, // ptr(arg0)
+       {name: "SliceLen"},                 // len(arg0)
+       {name: "SliceCap"},                 // cap(arg0)
 
        // Complex (part/whole)
        {name: "ComplexMake"}, // arg0=real, arg1=imag
@@ -350,9 +352,9 @@ var genericOps = []opData{
        {name: "StringLen"},  // len(arg0)
 
        // Interfaces
-       {name: "IMake"}, // arg0=itab, arg1=data
-       {name: "ITab"},  // arg0=interface, returns itable field
-       {name: "IData"}, // arg0=interface, returns data field
+       {name: "IMake"},                // arg0=itab, arg1=data
+       {name: "ITab", typ: "Uintptr"}, // arg0=interface, returns itable field
+       {name: "IData"},                // arg0=interface, returns data field
 
        // Spill&restore ops for the register allocator.  These are
        // semantically identical to OpCopy; they do not take/return
index f7f1ca30687fad6d0531a90155cb7db878075f03..0a7e8c75c7203469e047bdaed575bced2e65e06b 100644 (file)
@@ -387,7 +387,8 @@ const (
        OpEq32
        OpEq64
        OpEqPtr
-       OpEqFat
+       OpEqInter
+       OpEqSlice
        OpEq32F
        OpEq64F
        OpNeq8
@@ -395,7 +396,8 @@ const (
        OpNeq32
        OpNeq64
        OpNeqPtr
-       OpNeqFat
+       OpNeqInter
+       OpNeqSlice
        OpNeq32F
        OpNeq64F
        OpLess8
@@ -3576,7 +3578,11 @@ var opcodeTable = [...]opInfo{
                generic: true,
        },
        {
-               name:    "EqFat",
+               name:    "EqInter",
+               generic: true,
+       },
+       {
+               name:    "EqSlice",
                generic: true,
        },
        {
@@ -3608,7 +3614,11 @@ var opcodeTable = [...]opInfo{
                generic: true,
        },
        {
-               name:    "NeqFat",
+               name:    "NeqInter",
+               generic: true,
+       },
+       {
+               name:    "NeqSlice",
                generic: true,
        },
        {
index 0334c0cd95bd11af0c2d79bf75b4d6367744e363..afca4cfed983170eb2a1e041613b13dccd8cae9a 100644 (file)
@@ -427,56 +427,29 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
                goto enda66da0d3e7e51624ee46527727c48a9a
        enda66da0d3e7e51624ee46527727c48a9a:
                ;
-       case OpEqFat:
-               // match: (EqFat x y)
-               // cond: x.Op == OpConstNil && y.Op != OpConstNil
-               // result: (EqFat y x)
+       case OpEqInter:
+               // match: (EqInter x y)
+               // cond:
+               // result: (EqPtr (ITab x) (ITab y))
                {
                        x := v.Args[0]
                        y := v.Args[1]
-                       if !(x.Op == OpConstNil && y.Op != OpConstNil) {
-                               goto endcea7f7399afcff860c54d82230a9a934
-                       }
-                       v.Op = OpEqFat
-                       v.AuxInt = 0
-                       v.Aux = nil
-                       v.resetArgs()
-                       v.AddArg(y)
-                       v.AddArg(x)
-                       return true
-               }
-               goto endcea7f7399afcff860c54d82230a9a934
-       endcea7f7399afcff860c54d82230a9a934:
-               ;
-               // match: (EqFat (Load ptr mem) (ConstNil))
-               // cond:
-               // result: (EqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr [0]))
-               {
-                       if v.Args[0].Op != OpLoad {
-                               goto end6f10fb57a906a2c23667c770acb6abf9
-                       }
-                       ptr := v.Args[0].Args[0]
-                       mem := v.Args[0].Args[1]
-                       if v.Args[1].Op != OpConstNil {
-                               goto end6f10fb57a906a2c23667c770acb6abf9
-                       }
                        v.Op = OpEqPtr
                        v.AuxInt = 0
                        v.Aux = nil
                        v.resetArgs()
-                       v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
+                       v0 := b.NewValue0(v.Line, OpITab, TypeInvalid)
+                       v0.AddArg(x)
                        v0.Type = config.fe.TypeUintptr()
-                       v0.AddArg(ptr)
-                       v0.AddArg(mem)
                        v.AddArg(v0)
-                       v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
-                       v1.AuxInt = 0
+                       v1 := b.NewValue0(v.Line, OpITab, TypeInvalid)
+                       v1.AddArg(y)
                        v1.Type = config.fe.TypeUintptr()
                        v.AddArg(v1)
                        return true
                }
-               goto end6f10fb57a906a2c23667c770acb6abf9
-       end6f10fb57a906a2c23667c770acb6abf9:
+               goto endfcedc545b9bbbe3790786c8981b12d32
+       endfcedc545b9bbbe3790786c8981b12d32:
                ;
        case OpEqPtr:
                // match: (EqPtr p (ConstNil))
@@ -521,6 +494,30 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
                goto end7cdc0d5c38fbffe6287c8928803b038e
        end7cdc0d5c38fbffe6287c8928803b038e:
                ;
+       case OpEqSlice:
+               // match: (EqSlice x y)
+               // cond:
+               // result: (EqPtr (SlicePtr x) (SlicePtr y))
+               {
+                       x := v.Args[0]
+                       y := v.Args[1]
+                       v.Op = OpEqPtr
+                       v.AuxInt = 0
+                       v.Aux = nil
+                       v.resetArgs()
+                       v0 := b.NewValue0(v.Line, OpSlicePtr, TypeInvalid)
+                       v0.AddArg(x)
+                       v0.Type = config.fe.TypeUintptr()
+                       v.AddArg(v0)
+                       v1 := b.NewValue0(v.Line, OpSlicePtr, TypeInvalid)
+                       v1.AddArg(y)
+                       v1.Type = config.fe.TypeUintptr()
+                       v.AddArg(v1)
+                       return true
+               }
+               goto end2937092dca53f896cd527e59e92cab1d
+       end2937092dca53f896cd527e59e92cab1d:
+               ;
        case OpIData:
                // match: (IData (IMake _ data))
                // cond:
@@ -953,56 +950,29 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
                goto end09a0deaf3c42627d0d2d3efa96e30745
        end09a0deaf3c42627d0d2d3efa96e30745:
                ;
-       case OpNeqFat:
-               // match: (NeqFat x y)
-               // cond: x.Op == OpConstNil && y.Op != OpConstNil
-               // result: (NeqFat y x)
+       case OpNeqInter:
+               // match: (NeqInter x y)
+               // cond:
+               // result: (NeqPtr (ITab x) (ITab y))
                {
                        x := v.Args[0]
                        y := v.Args[1]
-                       if !(x.Op == OpConstNil && y.Op != OpConstNil) {
-                               goto end94c68f7dc30c66ed42e507e01c4e5dc7
-                       }
-                       v.Op = OpNeqFat
-                       v.AuxInt = 0
-                       v.Aux = nil
-                       v.resetArgs()
-                       v.AddArg(y)
-                       v.AddArg(x)
-                       return true
-               }
-               goto end94c68f7dc30c66ed42e507e01c4e5dc7
-       end94c68f7dc30c66ed42e507e01c4e5dc7:
-               ;
-               // match: (NeqFat (Load ptr mem) (ConstNil))
-               // cond:
-               // result: (NeqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr [0]))
-               {
-                       if v.Args[0].Op != OpLoad {
-                               goto end3ffd7685735a83eaee8dc2577ae89d79
-                       }
-                       ptr := v.Args[0].Args[0]
-                       mem := v.Args[0].Args[1]
-                       if v.Args[1].Op != OpConstNil {
-                               goto end3ffd7685735a83eaee8dc2577ae89d79
-                       }
                        v.Op = OpNeqPtr
                        v.AuxInt = 0
                        v.Aux = nil
                        v.resetArgs()
-                       v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
+                       v0 := b.NewValue0(v.Line, OpITab, TypeInvalid)
+                       v0.AddArg(x)
                        v0.Type = config.fe.TypeUintptr()
-                       v0.AddArg(ptr)
-                       v0.AddArg(mem)
                        v.AddArg(v0)
-                       v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
-                       v1.AuxInt = 0
+                       v1 := b.NewValue0(v.Line, OpITab, TypeInvalid)
+                       v1.AddArg(y)
                        v1.Type = config.fe.TypeUintptr()
                        v.AddArg(v1)
                        return true
                }
-               goto end3ffd7685735a83eaee8dc2577ae89d79
-       end3ffd7685735a83eaee8dc2577ae89d79:
+               goto end17b2333bf57e9fe81a671be02f9c4c14
+       end17b2333bf57e9fe81a671be02f9c4c14:
                ;
        case OpNeqPtr:
                // match: (NeqPtr p (ConstNil))
@@ -1041,6 +1011,30 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
                goto enddd95e9c3606d9fd48034f1a703561e45
        enddd95e9c3606d9fd48034f1a703561e45:
                ;
+       case OpNeqSlice:
+               // match: (NeqSlice x y)
+               // cond:
+               // result: (NeqPtr (SlicePtr x) (SlicePtr y))
+               {
+                       x := v.Args[0]
+                       y := v.Args[1]
+                       v.Op = OpNeqPtr
+                       v.AuxInt = 0
+                       v.Aux = nil
+                       v.resetArgs()
+                       v0 := b.NewValue0(v.Line, OpSlicePtr, TypeInvalid)
+                       v0.AddArg(x)
+                       v0.Type = config.fe.TypeUintptr()
+                       v.AddArg(v0)
+                       v1 := b.NewValue0(v.Line, OpSlicePtr, TypeInvalid)
+                       v1.AddArg(y)
+                       v1.Type = config.fe.TypeUintptr()
+                       v.AddArg(v1)
+                       return true
+               }
+               goto endc6bc83c506e491236ca66ea1081231a2
+       endc6bc83c506e491236ca66ea1081231a2:
+               ;
        case OpOr16:
                // match: (Or16 x x)
                // cond: