mirror of
https://github.com/golang/go.git
synced 2025-10-19 19:13:18 +00:00

It's currently hard to automate refactorings around the Value.Aux field, because we don't have any static typing information for it. Adding a tag interface will make subsequent CLs easier and safer. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I41ae8e411a66bda3195a0957b60c2fe8a8002893 Reviewed-on: https://go-review.googlesource.com/c/go/+/275756 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Trust: Matthew Dempsky <mdempsky@google.com>
131 lines
4.2 KiB
Go
131 lines
4.2 KiB
Go
// Copyright 2016 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
|
|
|
|
import (
|
|
"cmd/compile/internal/types"
|
|
"cmd/internal/src"
|
|
"testing"
|
|
)
|
|
|
|
type tstAux struct {
|
|
s string
|
|
}
|
|
|
|
func (*tstAux) CanBeAnSSAAux() {}
|
|
|
|
// This tests for a bug found when partitioning, but not sorting by the Aux value.
|
|
func TestCSEAuxPartitionBug(t *testing.T) {
|
|
c := testConfig(t)
|
|
arg1Aux := &tstAux{"arg1-aux"}
|
|
arg2Aux := &tstAux{"arg2-aux"}
|
|
arg3Aux := &tstAux{"arg3-aux"}
|
|
a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8)
|
|
|
|
// construct lots of values with args that have aux values and place
|
|
// them in an order that triggers the bug
|
|
fun := c.Fun("entry",
|
|
Bloc("entry",
|
|
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
|
Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
|
|
Valu("r7", OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg1"),
|
|
Valu("r1", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
|
|
Valu("arg1", OpArg, c.config.Types.Int64, 0, arg1Aux),
|
|
Valu("arg2", OpArg, c.config.Types.Int64, 0, arg2Aux),
|
|
Valu("arg3", OpArg, c.config.Types.Int64, 0, arg3Aux),
|
|
Valu("r9", OpAdd64, c.config.Types.Int64, 0, nil, "r7", "r8"),
|
|
Valu("r4", OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
|
|
Valu("r8", OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg2"),
|
|
Valu("r2", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
|
|
Valu("raddr", OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
|
|
Valu("raddrdef", OpVarDef, types.TypeMem, 0, a, "start"),
|
|
Valu("r6", OpAdd64, c.config.Types.Int64, 0, nil, "r4", "r5"),
|
|
Valu("r3", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
|
|
Valu("r5", OpAdd64, c.config.Types.Int64, 0, nil, "r2", "r3"),
|
|
Valu("r10", OpAdd64, c.config.Types.Int64, 0, nil, "r6", "r9"),
|
|
Valu("rstore", OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r10", "raddrdef"),
|
|
Goto("exit")),
|
|
Bloc("exit",
|
|
Exit("rstore")))
|
|
|
|
CheckFunc(fun.f)
|
|
cse(fun.f)
|
|
deadcode(fun.f)
|
|
CheckFunc(fun.f)
|
|
|
|
s1Cnt := 2
|
|
// r1 == r2 == r3, needs to remove two of this set
|
|
s2Cnt := 1
|
|
// r4 == r5, needs to remove one of these
|
|
for k, v := range fun.values {
|
|
if v.Op == OpInvalid {
|
|
switch k {
|
|
case "r1":
|
|
fallthrough
|
|
case "r2":
|
|
fallthrough
|
|
case "r3":
|
|
if s1Cnt == 0 {
|
|
t.Errorf("cse removed all of r1,r2,r3")
|
|
}
|
|
s1Cnt--
|
|
|
|
case "r4":
|
|
fallthrough
|
|
case "r5":
|
|
if s2Cnt == 0 {
|
|
t.Errorf("cse removed all of r4,r5")
|
|
}
|
|
s2Cnt--
|
|
default:
|
|
t.Errorf("cse removed %s, but shouldn't have", k)
|
|
}
|
|
}
|
|
}
|
|
|
|
if s1Cnt != 0 || s2Cnt != 0 {
|
|
t.Errorf("%d values missed during cse", s1Cnt+s2Cnt)
|
|
}
|
|
}
|
|
|
|
// TestZCSE tests the zero arg cse.
|
|
func TestZCSE(t *testing.T) {
|
|
c := testConfig(t)
|
|
a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8)
|
|
|
|
fun := c.Fun("entry",
|
|
Bloc("entry",
|
|
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
|
Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
|
|
Valu("sb1", OpSB, c.config.Types.Uintptr, 0, nil),
|
|
Valu("sb2", OpSB, c.config.Types.Uintptr, 0, nil),
|
|
Valu("addr1", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb1"),
|
|
Valu("addr2", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb2"),
|
|
Valu("a1ld", OpLoad, c.config.Types.Int64, 0, nil, "addr1", "start"),
|
|
Valu("a2ld", OpLoad, c.config.Types.Int64, 0, nil, "addr2", "start"),
|
|
Valu("c1", OpConst64, c.config.Types.Int64, 1, nil),
|
|
Valu("r1", OpAdd64, c.config.Types.Int64, 0, nil, "a1ld", "c1"),
|
|
Valu("c2", OpConst64, c.config.Types.Int64, 1, nil),
|
|
Valu("r2", OpAdd64, c.config.Types.Int64, 0, nil, "a2ld", "c2"),
|
|
Valu("r3", OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
|
|
Valu("raddr", OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
|
|
Valu("raddrdef", OpVarDef, types.TypeMem, 0, a, "start"),
|
|
Valu("rstore", OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r3", "raddrdef"),
|
|
Goto("exit")),
|
|
Bloc("exit",
|
|
Exit("rstore")))
|
|
|
|
CheckFunc(fun.f)
|
|
zcse(fun.f)
|
|
deadcode(fun.f)
|
|
CheckFunc(fun.f)
|
|
|
|
if fun.values["c1"].Op != OpInvalid && fun.values["c2"].Op != OpInvalid {
|
|
t.Errorf("zsce should have removed c1 or c2")
|
|
}
|
|
if fun.values["sb1"].Op != OpInvalid && fun.values["sb2"].Op != OpInvalid {
|
|
t.Errorf("zsce should have removed sb1 or sb2")
|
|
}
|
|
}
|