1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/types"
9 "testing"
10 )
11
12
13 func TestBranchElimIf(t *testing.T) {
14 var testData = []struct {
15 arch string
16 intType string
17 ok bool
18 }{
19 {"arm64", "int32", true},
20 {"amd64", "int32", true},
21 {"amd64", "int8", false},
22 }
23
24 for _, data := range testData {
25 t.Run(data.arch+"/"+data.intType, func(t *testing.T) {
26 c := testConfigArch(t, data.arch)
27 boolType := c.config.Types.Bool
28 var intType *types.Type
29 switch data.intType {
30 case "int32":
31 intType = c.config.Types.Int32
32 case "int8":
33 intType = c.config.Types.Int8
34 default:
35 t.Fatal("invalid integer type:", data.intType)
36 }
37 fun := c.Fun("entry",
38 Bloc("entry",
39 Valu("start", OpInitMem, types.TypeMem, 0, nil),
40 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
41 Valu("const1", OpConst32, intType, 1, nil),
42 Valu("const2", OpConst32, intType, 2, nil),
43 Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
44 Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
45 If("cond", "b2", "b3")),
46 Bloc("b2",
47 Goto("b3")),
48 Bloc("b3",
49 Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
50 Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
51 Exit("retstore")))
52
53 CheckFunc(fun.f)
54 branchelim(fun.f)
55 CheckFunc(fun.f)
56 Deadcode(fun.f)
57 CheckFunc(fun.f)
58
59 if data.ok {
60
61 if len(fun.f.Blocks) != 1 {
62 t.Fatalf("expected 1 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
63 }
64 if fun.values["phi"].Op != OpCondSelect {
65 t.Fatalf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
66 }
67 if fun.values["phi"].Args[2] != fun.values["cond"] {
68 t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
69 }
70 if fun.blocks["entry"].Kind != BlockExit {
71 t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
72 }
73 } else {
74 if len(fun.f.Blocks) != 3 {
75 t.Fatalf("expected 3 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
76 }
77 }
78 })
79 }
80 }
81
82
83 func TestBranchElimIfElse(t *testing.T) {
84 for _, arch := range []string{"arm64", "amd64"} {
85 t.Run(arch, func(t *testing.T) {
86 c := testConfigArch(t, arch)
87 boolType := c.config.Types.Bool
88 intType := c.config.Types.Int32
89 fun := c.Fun("entry",
90 Bloc("entry",
91 Valu("start", OpInitMem, types.TypeMem, 0, nil),
92 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
93 Valu("const1", OpConst32, intType, 1, nil),
94 Valu("const2", OpConst32, intType, 2, nil),
95 Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
96 Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
97 If("cond", "b2", "b3")),
98 Bloc("b2",
99 Goto("b4")),
100 Bloc("b3",
101 Goto("b4")),
102 Bloc("b4",
103 Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
104 Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
105 Exit("retstore")))
106
107 CheckFunc(fun.f)
108 branchelim(fun.f)
109 CheckFunc(fun.f)
110 Deadcode(fun.f)
111 CheckFunc(fun.f)
112
113 if len(fun.f.Blocks) != 1 {
114 t.Fatalf("expected 1 block after branchelim; found %d", len(fun.f.Blocks))
115 }
116 if fun.values["phi"].Op != OpCondSelect {
117 t.Fatalf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
118 }
119 if fun.values["phi"].Args[2] != fun.values["cond"] {
120 t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
121 }
122 if fun.blocks["entry"].Kind != BlockExit {
123 t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
124 }
125 })
126 }
127 }
128
129
130
131 func TestNoBranchElimLoop(t *testing.T) {
132 for _, arch := range []string{"arm64", "amd64"} {
133 t.Run(arch, func(t *testing.T) {
134 c := testConfigArch(t, arch)
135 boolType := c.config.Types.Bool
136 intType := c.config.Types.Int32
137
138
139
140
141 fun := c.Fun("entry",
142 Bloc("entry",
143 Valu("start", OpInitMem, types.TypeMem, 0, nil),
144 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
145 Valu("const2", OpConst32, intType, 2, nil),
146 Valu("const3", OpConst32, intType, 3, nil),
147 Goto("b5")),
148 Bloc("b2",
149 Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
150 Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
151 Valu("phi", OpPhi, intType, 0, nil, "const2", "const3"),
152 If("cond", "b3", "b4")),
153 Bloc("b3",
154 Goto("b2")),
155 Bloc("b4",
156 Goto("b2")),
157 Bloc("b5",
158 Exit("start")))
159
160 CheckFunc(fun.f)
161 branchelim(fun.f)
162 CheckFunc(fun.f)
163
164 if len(fun.f.Blocks) != 5 {
165 t.Errorf("expected 5 block after branchelim; found %d", len(fun.f.Blocks))
166 }
167 if fun.values["phi"].Op != OpPhi {
168 t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
169 }
170 })
171 }
172 }
173
View as plain text