• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ssa
6
7import (
8	"cmd/compile/internal/types"
9	"testing"
10)
11
12type tstAux struct {
13	s string
14}
15
16func (*tstAux) CanBeAnSSAAux() {}
17
18// This tests for a bug found when partitioning, but not sorting by the Aux value.
19func TestCSEAuxPartitionBug(t *testing.T) {
20	c := testConfig(t)
21	arg1Aux := &tstAux{"arg1-aux"}
22	arg2Aux := &tstAux{"arg2-aux"}
23	arg3Aux := &tstAux{"arg3-aux"}
24	a := c.Temp(c.config.Types.Int8.PtrTo())
25
26	// construct lots of values with args that have aux values and place
27	// them in an order that triggers the bug
28	fun := c.Fun("entry",
29		Bloc("entry",
30			Valu("start", OpInitMem, types.TypeMem, 0, nil),
31			Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
32			Valu("r7", OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg1"),
33			Valu("r1", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
34			Valu("arg1", OpArg, c.config.Types.Int64, 0, arg1Aux),
35			Valu("arg2", OpArg, c.config.Types.Int64, 0, arg2Aux),
36			Valu("arg3", OpArg, c.config.Types.Int64, 0, arg3Aux),
37			Valu("r9", OpAdd64, c.config.Types.Int64, 0, nil, "r7", "r8"),
38			Valu("r4", OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
39			Valu("r8", OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg2"),
40			Valu("r2", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
41			Valu("raddr", OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
42			Valu("raddrdef", OpVarDef, types.TypeMem, 0, a, "start"),
43			Valu("r6", OpAdd64, c.config.Types.Int64, 0, nil, "r4", "r5"),
44			Valu("r3", OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
45			Valu("r5", OpAdd64, c.config.Types.Int64, 0, nil, "r2", "r3"),
46			Valu("r10", OpAdd64, c.config.Types.Int64, 0, nil, "r6", "r9"),
47			Valu("rstore", OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r10", "raddrdef"),
48			Goto("exit")),
49		Bloc("exit",
50			Exit("rstore")))
51
52	CheckFunc(fun.f)
53	cse(fun.f)
54	deadcode(fun.f)
55	CheckFunc(fun.f)
56
57	s1Cnt := 2
58	// r1 == r2 == r3, needs to remove two of this set
59	s2Cnt := 1
60	// r4 == r5, needs to remove one of these
61	for k, v := range fun.values {
62		if v.Op == OpInvalid {
63			switch k {
64			case "r1":
65				fallthrough
66			case "r2":
67				fallthrough
68			case "r3":
69				if s1Cnt == 0 {
70					t.Errorf("cse removed all of r1,r2,r3")
71				}
72				s1Cnt--
73
74			case "r4":
75				fallthrough
76			case "r5":
77				if s2Cnt == 0 {
78					t.Errorf("cse removed all of r4,r5")
79				}
80				s2Cnt--
81			default:
82				t.Errorf("cse removed %s, but shouldn't have", k)
83			}
84		}
85	}
86
87	if s1Cnt != 0 || s2Cnt != 0 {
88		t.Errorf("%d values missed during cse", s1Cnt+s2Cnt)
89	}
90}
91
92// TestZCSE tests the zero arg cse.
93func TestZCSE(t *testing.T) {
94	c := testConfig(t)
95	a := c.Temp(c.config.Types.Int8.PtrTo())
96
97	fun := c.Fun("entry",
98		Bloc("entry",
99			Valu("start", OpInitMem, types.TypeMem, 0, nil),
100			Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
101			Valu("sb1", OpSB, c.config.Types.Uintptr, 0, nil),
102			Valu("sb2", OpSB, c.config.Types.Uintptr, 0, nil),
103			Valu("addr1", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb1"),
104			Valu("addr2", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb2"),
105			Valu("a1ld", OpLoad, c.config.Types.Int64, 0, nil, "addr1", "start"),
106			Valu("a2ld", OpLoad, c.config.Types.Int64, 0, nil, "addr2", "start"),
107			Valu("c1", OpConst64, c.config.Types.Int64, 1, nil),
108			Valu("r1", OpAdd64, c.config.Types.Int64, 0, nil, "a1ld", "c1"),
109			Valu("c2", OpConst64, c.config.Types.Int64, 1, nil),
110			Valu("r2", OpAdd64, c.config.Types.Int64, 0, nil, "a2ld", "c2"),
111			Valu("r3", OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
112			Valu("raddr", OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
113			Valu("raddrdef", OpVarDef, types.TypeMem, 0, a, "start"),
114			Valu("rstore", OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r3", "raddrdef"),
115			Goto("exit")),
116		Bloc("exit",
117			Exit("rstore")))
118
119	CheckFunc(fun.f)
120	zcse(fun.f)
121	deadcode(fun.f)
122	CheckFunc(fun.f)
123
124	if fun.values["c1"].Op != OpInvalid && fun.values["c2"].Op != OpInvalid {
125		t.Errorf("zsce should have removed c1 or c2")
126	}
127	if fun.values["sb1"].Op != OpInvalid && fun.values["sb2"].Op != OpInvalid {
128		t.Errorf("zsce should have removed sb1 or sb2")
129	}
130}
131