]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: handle rewrite of Phis.
authorAlexandru Moșoi <mosoi@google.com>
Tue, 9 Feb 2016 18:46:26 +0000 (19:46 +0100)
committerAlexandru Moșoi <alexandru@mosoi.ro>
Tue, 9 Feb 2016 20:46:16 +0000 (20:46 +0000)
* Phis can have variable number of arguments, but rulegen assumed that
each operation has fixed number of arguments.
* Rewriting Phis is necessary to handle the following case:

func f1_ssa(a bool, x int) int {
        v := 0
        if a {
                v = -1
        } else {
                v = -1
        }
        return x|v
}

Change-Id: Iff6bd411b854f3d1d6d3ce21934bf566757094f2
Reviewed-on: https://go-review.googlesource.com/19412
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/testdata/arith_ssa.go
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/gen/main.go
src/cmd/compile/internal/ssa/gen/rulegen.go
src/cmd/compile/internal/ssa/rewritegeneric.go

index 22a78105e00703f05c8ba5e862be48ed031b659c..821c0dd12dee397f08990c82d48e9ded021afa75 100644 (file)
@@ -358,6 +358,26 @@ func testSubConst() {
        }
 }
 
+//go:noinline
+func orPhi_ssa(a bool, x int) int {
+       v := 0
+       if a {
+               v = -1
+       } else {
+               v = -1
+       }
+       return x | v
+}
+
+func testOrPhi() {
+       if want, got := -1, orPhi_ssa(true, 4); got != want {
+               println("orPhi_ssa(true, 4)=", got, " want ", want)
+       }
+       if want, got := -1, orPhi_ssa(false, 0); got != want {
+               println("orPhi_ssa(false, 0)=", got, " want ", want)
+       }
+}
+
 var failed = false
 
 func main() {
index a3cc5654eada229d2166da64ab0aa126b557ba19..29b1d42c9e8bd3852785c7f13f94475b38195b96 100644 (file)
 (Sub8 (Add8 x y) x) -> y
 (Sub8 (Add8 x y) y) -> x
 
+// basic phi simplifications
+(Phi (Const8 [c]) (Const8 [d])) && int8(c) == int8(d) -> (Const8 [c])
+(Phi (Const16 [c]) (Const16 [d])) && int16(c) == int16(d) -> (Const16 [c])
+(Phi (Const32 [c]) (Const32 [d])) && int32(c) == int32(d) -> (Const32 [c])
+(Phi (Const64 [c]) (Const64 [c])) -> (Const64 [c])
+
 // user nil checks
 (NeqPtr p (ConstNil)) -> (IsNonNil p)
 (NeqPtr (ConstNil) p) -> (IsNonNil p)
index ec74859cbcb30ce1f600d002adc629a7f6e6ea27..fe5169d233914cb1f3674f3cb4c295e21a2a36e5 100644 (file)
@@ -240,8 +240,8 @@ var genericOps = []opData{
        {name: "Sqrt"}, // sqrt(arg0), float64 only
 
        // Data movement
-       {name: "Phi"},  // select an argument based on which predecessor block we came from
-       {name: "Copy"}, // output = arg0
+       {name: "Phi", variableLength: true}, // select an argument based on which predecessor block we came from
+       {name: "Copy"},                      // output = arg0
        // Convert converts between pointers and integers.
        // We have a special op for this so as to not confuse GC
        // (particularly stack maps).  It takes a memory arg so it
index f8f6c8b5f6bcdaa107e75c9343a567785040124c..d739b290794f8ae499468b7cf00be74b0f12f510 100644 (file)
@@ -32,6 +32,7 @@ type opData struct {
        typ               string // default result type
        aux               string
        rematerializeable bool
+       variableLength    bool // if true the operation has a variable number of arguments
 }
 
 type blockData struct {
index 1a0f5d4b1e73fa9104bb3a33bde482ba08d4559f..b9aa51d165a07e4f418f1d594c643c518aa606c0 100644 (file)
@@ -395,6 +395,23 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
                        argnum++
                }
        }
+
+       variableLength := false
+       for _, op := range genericOps {
+               if op.name == s[0] {
+                       variableLength = op.variableLength
+                       break
+               }
+       }
+       for _, op := range arch.ops {
+               if op.name == s[0] {
+                       variableLength = op.variableLength
+                       break
+               }
+       }
+       if variableLength {
+               fmt.Fprintf(w, "if len(%s.Args) != %d {\nbreak\n}\n", v, argnum)
+       }
 }
 
 func genResult(w io.Writer, arch arch, result string) {
index a724a2d369eca63f11b4f8bfd6c5356ee9bbd83b..e0f03d2e45d8dc4624083cbcbce7352992be41be 100644 (file)
@@ -213,6 +213,8 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
                return rewriteValuegeneric_OpOr64(v, config)
        case OpOr8:
                return rewriteValuegeneric_OpOr8(v, config)
+       case OpPhi:
+               return rewriteValuegeneric_OpPhi(v, config)
        case OpPtrIndex:
                return rewriteValuegeneric_OpPtrIndex(v, config)
        case OpRsh16Ux16:
@@ -3965,6 +3967,98 @@ func rewriteValuegeneric_OpOr8(v *Value, config *Config) bool {
        }
        return false
 }
+func rewriteValuegeneric_OpPhi(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (Phi (Const8 [c]) (Const8 [d]))
+       // cond: int8(c) == int8(d)
+       // result: (Const8 [c])
+       for {
+               if v.Args[0].Op != OpConst8 {
+                       break
+               }
+               c := v.Args[0].AuxInt
+               if v.Args[1].Op != OpConst8 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if len(v.Args) != 2 {
+                       break
+               }
+               if !(int8(c) == int8(d)) {
+                       break
+               }
+               v.reset(OpConst8)
+               v.AuxInt = c
+               return true
+       }
+       // match: (Phi (Const16 [c]) (Const16 [d]))
+       // cond: int16(c) == int16(d)
+       // result: (Const16 [c])
+       for {
+               if v.Args[0].Op != OpConst16 {
+                       break
+               }
+               c := v.Args[0].AuxInt
+               if v.Args[1].Op != OpConst16 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if len(v.Args) != 2 {
+                       break
+               }
+               if !(int16(c) == int16(d)) {
+                       break
+               }
+               v.reset(OpConst16)
+               v.AuxInt = c
+               return true
+       }
+       // match: (Phi (Const32 [c]) (Const32 [d]))
+       // cond: int32(c) == int32(d)
+       // result: (Const32 [c])
+       for {
+               if v.Args[0].Op != OpConst32 {
+                       break
+               }
+               c := v.Args[0].AuxInt
+               if v.Args[1].Op != OpConst32 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if len(v.Args) != 2 {
+                       break
+               }
+               if !(int32(c) == int32(d)) {
+                       break
+               }
+               v.reset(OpConst32)
+               v.AuxInt = c
+               return true
+       }
+       // match: (Phi (Const64 [c]) (Const64 [c]))
+       // cond:
+       // result: (Const64 [c])
+       for {
+               if v.Args[0].Op != OpConst64 {
+                       break
+               }
+               c := v.Args[0].AuxInt
+               if v.Args[1].Op != OpConst64 {
+                       break
+               }
+               if v.Args[1].AuxInt != v.Args[0].AuxInt {
+                       break
+               }
+               if len(v.Args) != 2 {
+                       break
+               }
+               v.reset(OpConst64)
+               v.AuxInt = c
+               return true
+       }
+       return false
+}
 func rewriteValuegeneric_OpPtrIndex(v *Value, config *Config) bool {
        b := v.Block
        _ = b