summaryrefslogtreecommitdiffstats
path: root/src/cmd/compile/internal/ssa/copyelim.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:19:13 +0000
commitccd992355df7192993c666236047820244914598 (patch)
treef00fea65147227b7743083c6148396f74cd66935 /src/cmd/compile/internal/ssa/copyelim.go
parentInitial commit. (diff)
downloadgolang-1.21-ccd992355df7192993c666236047820244914598.tar.xz
golang-1.21-ccd992355df7192993c666236047820244914598.zip
Adding upstream version 1.21.8.upstream/1.21.8
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/copyelim.go')
-rw-r--r--src/cmd/compile/internal/ssa/copyelim.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/copyelim.go b/src/cmd/compile/internal/ssa/copyelim.go
new file mode 100644
index 0000000..17f6512
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/copyelim.go
@@ -0,0 +1,84 @@
+// 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
+
+// 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 {
+ copyelimValue(v)
+ }
+ }
+
+ // Update block control values.
+ for _, b := range f.Blocks {
+ for i, v := range b.ControlValues() {
+ if v.Op == OpCopy {
+ b.ReplaceControl(i, v.Args[0])
+ }
+ }
+ }
+
+ // Update named values.
+ for _, name := range f.Names {
+ values := f.NamedValues[*name]
+ for i, v := range values {
+ if v.Op == OpCopy {
+ values[i] = v.Args[0]
+ }
+ }
+ }
+}
+
+// copySource returns the (non-copy) op which is the
+// ultimate source of v. v must be a copy op.
+func copySource(v *Value) *Value {
+ w := v.Args[0]
+
+ // This loop is just:
+ // for w.Op == OpCopy {
+ // w = w.Args[0]
+ // }
+ // but we take some extra care to make sure we
+ // don't get stuck in an infinite loop.
+ // Infinite copy loops may happen in unreachable code.
+ // (TODO: or can they? Needs a test.)
+ slow := w
+ var advance bool
+ for w.Op == OpCopy {
+ w = w.Args[0]
+ if w == slow {
+ w.reset(OpUnknown)
+ break
+ }
+ if advance {
+ slow = slow.Args[0]
+ }
+ advance = !advance
+ }
+
+ // The answer is w. Update all the copies we saw
+ // to point directly to w. Doing this update makes
+ // sure that we don't end up doing O(n^2) work
+ // for a chain of n copies.
+ for v != w {
+ x := v.Args[0]
+ v.SetArg(0, w)
+ v = x
+ }
+ return w
+}
+
+// copyelimValue ensures that no args of v are copies.
+func copyelimValue(v *Value) {
+ for i, a := range v.Args {
+ if a.Op == OpCopy {
+ v.SetArg(i, copySource(a))
+ }
+ }
+}