]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: combine phielim and copyelim into a single pass
authorjeffery <superajun@gmail.com>
Mon, 22 Apr 2024 08:02:22 +0000 (08:02 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 22 Apr 2024 14:55:18 +0000 (14:55 +0000)
Change-Id: Id21145b14169d28bac2144a31f6d3d9729f4be1e
GitHub-Last-Rev: 5413f4753e5acb60db6a93cb3409047bddc8df6d
GitHub-Pull-Request: golang/go#63818
Reviewed-on: https://go-review.googlesource.com/c/go/+/538535
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/ssa/compile.go
src/cmd/compile/internal/ssa/copyelim.go
src/cmd/compile/internal/ssa/phielim.go [deleted file]

index d125891f88c58f798e9cd490ba999b0b2ef88ba8..80ef53d085db6257f0df1e1bc69b2a92e1eebda8 100644 (file)
@@ -455,10 +455,8 @@ commas. For example:
 
 // list of passes for the compiler
 var passes = [...]pass{
-       // TODO: combine phielim and copyelim into a single pass?
        {name: "number lines", fn: numberLines, required: true},
-       {name: "early phielim", fn: phielim},
-       {name: "early copyelim", fn: copyelim},
+       {name: "early phielim and copyelim", fn: copyelim},
        {name: "early deadcode", fn: deadcode}, // remove generated dead code to avoid doing pointless work during opt
        {name: "short circuit", fn: shortcircuit},
        {name: "decompose user", fn: decomposeUser, required: true},
@@ -496,8 +494,7 @@ var passes = [...]pass{
        {name: "tighten tuple selectors", fn: tightenTupleSelectors, required: true},
        {name: "lowered deadcode", fn: deadcode, required: true},
        {name: "checkLower", fn: checkLower, required: true},
-       {name: "late phielim", fn: phielim},
-       {name: "late copyelim", fn: copyelim},
+       {name: "late phielim and copyelim", fn: copyelim},
        {name: "tighten", fn: tighten, required: true}, // move values closer to their uses
        {name: "late deadcode", fn: deadcode},
        {name: "critical", fn: critical, required: true}, // remove critical edges
index 17471e3b5fc6292cd9fb7045f1da2ddba23076a6..ea888f46f9f51234ab035d9d86d0346a6c95173d 100644 (file)
@@ -4,28 +4,13 @@
 
 package ssa
 
+// combine copyelim and phielim into a single pass.
 // copyelim removes all uses of OpCopy values from f.
 // A subsequent deadcode pass is needed to actually remove the copies.
 func copyelim(f *Func) {
-       // Modify all values so no arg (including args
-       // of OpCopy) is a copy.
-       for _, b := range f.Blocks {
-               for _, v := range b.Values {
-
-                       // This is an early place in SSA where all values are examined.
-                       // Rewrite all 0-sized Go values to remove accessors, dereferences, loads, etc.
-                       if t := v.Type; (t.IsStruct() || t.IsArray()) && t.Size() == 0 {
-                               if t.IsStruct() {
-                                       v.reset(OpStructMake0)
-                               } else {
-                                       v.reset(OpArrayMake0)
-                               }
-                       }
-
-                       copyelimValue(v)
-               }
-       }
+       phielim(f)
 
+       // loop of copyelimValue(v) process has been done in phielim() pass.
        // Update block control values.
        for _, b := range f.Blocks {
                for i, v := range b.ControlValues() {
@@ -93,3 +78,84 @@ func copyelimValue(v *Value) {
                }
        }
 }
+
+// phielim eliminates redundant phi values from f.
+// A phi is redundant if its arguments are all equal. For
+// purposes of counting, ignore the phi itself. Both of
+// these phis are redundant:
+//
+//     v = phi(x,x,x)
+//     v = phi(x,v,x,v)
+//
+// We repeat this process to also catch situations like:
+//
+//     v = phi(x, phi(x, x), phi(x, v))
+//
+// TODO: Can we also simplify cases like:
+//
+//     v = phi(v, w, x)
+//     w = phi(v, w, x)
+//
+// and would that be useful?
+func phielim(f *Func) {
+       for {
+               change := false
+               for _, b := range f.Blocks {
+                       for _, v := range b.Values {
+                               // This is an early place in SSA where all values are examined.
+                               // Rewrite all 0-sized Go values to remove accessors, dereferences, loads, etc.
+                               if t := v.Type; (t.IsStruct() || t.IsArray()) && t.Size() == 0 {
+                                       if t.IsStruct() {
+                                               v.reset(OpStructMake0)
+                                       } else {
+                                               v.reset(OpArrayMake0)
+                                       }
+                               }
+                               // Modify all values so no arg (including args
+                               // of OpCopy) is a copy.
+                               copyelimValue(v)
+                               change = phielimValue(v) || change
+                       }
+               }
+               if !change {
+                       break
+               }
+       }
+}
+
+// phielimValue tries to convert the phi v to a copy.
+func phielimValue(v *Value) bool {
+       if v.Op != OpPhi {
+               return false
+       }
+
+       // If there are two distinct args of v which
+       // are not v itself, then the phi must remain.
+       // Otherwise, we can replace it with a copy.
+       var w *Value
+       for _, x := range v.Args {
+               if x == v {
+                       continue
+               }
+               if x == w {
+                       continue
+               }
+               if w != nil {
+                       return false
+               }
+               w = x
+       }
+
+       if w == nil {
+               // v references only itself. It must be in
+               // a dead code loop. Don't bother modifying it.
+               return false
+       }
+       v.Op = OpCopy
+       v.SetArgs1(w)
+       f := v.Block.Func
+       if f.pass.debug > 0 {
+               f.Warnl(v.Pos, "eliminated phi")
+       }
+       return true
+}
diff --git a/src/cmd/compile/internal/ssa/phielim.go b/src/cmd/compile/internal/ssa/phielim.go
deleted file mode 100644 (file)
index 4fc9423..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssa
-
-// phielim eliminates redundant phi values from f.
-// A phi is redundant if its arguments are all equal. For
-// purposes of counting, ignore the phi itself. Both of
-// these phis are redundant:
-//
-//     v = phi(x,x,x)
-//     v = phi(x,v,x,v)
-//
-// We repeat this process to also catch situations like:
-//
-//     v = phi(x, phi(x, x), phi(x, v))
-//
-// TODO: Can we also simplify cases like:
-//
-//     v = phi(v, w, x)
-//     w = phi(v, w, x)
-//
-// and would that be useful?
-func phielim(f *Func) {
-       for {
-               change := false
-               for _, b := range f.Blocks {
-                       for _, v := range b.Values {
-                               copyelimValue(v)
-                               change = phielimValue(v) || change
-                       }
-               }
-               if !change {
-                       break
-               }
-       }
-}
-
-// phielimValue tries to convert the phi v to a copy.
-func phielimValue(v *Value) bool {
-       if v.Op != OpPhi {
-               return false
-       }
-
-       // If there are two distinct args of v which
-       // are not v itself, then the phi must remain.
-       // Otherwise, we can replace it with a copy.
-       var w *Value
-       for _, x := range v.Args {
-               if x == v {
-                       continue
-               }
-               if x == w {
-                       continue
-               }
-               if w != nil {
-                       return false
-               }
-               w = x
-       }
-
-       if w == nil {
-               // v references only itself. It must be in
-               // a dead code loop. Don't bother modifying it.
-               return false
-       }
-       v.Op = OpCopy
-       v.SetArgs1(w)
-       f := v.Block.Func
-       if f.pass.debug > 0 {
-               f.Warnl(v.Pos, "eliminated phi")
-       }
-       return true
-}