1
2
3
4
5 package ssacompile
6
7 import (
8 "fmt"
9 "strconv"
10 "testing"
11
12 "cmd/compile/internal/ssa/block"
13 "cmd/compile/internal/ssa/ssaop"
14 "cmd/compile/internal/types"
15 )
16
17 func TestDeadLoop(t *testing.T) {
18 c := testConfig(t)
19 fun := c.Fun("entry",
20 Bloc("entry",
21 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
22 Goto("exit")),
23 Bloc("exit",
24 Exit("mem")),
25
26 Bloc("deadblock",
27
28 Valu("deadval", ssaop.OpConstBool, c.config.Types.Bool, 1, nil),
29 If("deadval", "deadblock", "exit")))
30
31 CheckFunc(fun.f)
32 Deadcode(fun.f)
33 CheckFunc(fun.f)
34
35 for _, b := range fun.f.Blocks {
36 if b == fun.blocks["deadblock"] {
37 t.Errorf("dead block not removed")
38 }
39 for _, v := range b.Values {
40 if v == fun.values["deadval"] {
41 t.Errorf("control value of dead block not removed")
42 }
43 }
44 }
45 }
46
47 func TestDeadValue(t *testing.T) {
48 c := testConfig(t)
49 fun := c.Fun("entry",
50 Bloc("entry",
51 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
52 Valu("deadval", ssaop.OpConst64, c.config.Types.Int64, 37, nil),
53 Goto("exit")),
54 Bloc("exit",
55 Exit("mem")))
56
57 CheckFunc(fun.f)
58 Deadcode(fun.f)
59 CheckFunc(fun.f)
60
61 for _, b := range fun.f.Blocks {
62 for _, v := range b.Values {
63 if v == fun.values["deadval"] {
64 t.Errorf("dead value not removed")
65 }
66 }
67 }
68 }
69
70 func TestNeverTaken(t *testing.T) {
71 c := testConfig(t)
72 fun := c.Fun("entry",
73 Bloc("entry",
74 Valu("cond", ssaop.OpConstBool, c.config.Types.Bool, 0, nil),
75 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
76 If("cond", "then", "else")),
77 Bloc("then",
78 Goto("exit")),
79 Bloc("else",
80 Goto("exit")),
81 Bloc("exit",
82 Exit("mem")))
83
84 CheckFunc(fun.f)
85 Opt(fun.f)
86 Deadcode(fun.f)
87 CheckFunc(fun.f)
88
89 if fun.blocks["entry"].Kind != block.BlockPlain {
90 t.Errorf("if(false) not simplified")
91 }
92 for _, b := range fun.f.Blocks {
93 if b == fun.blocks["then"] {
94 t.Errorf("then block still present")
95 }
96 for _, v := range b.Values {
97 if v == fun.values["cond"] {
98 t.Errorf("constant condition still present")
99 }
100 }
101 }
102
103 }
104
105 func TestNestedDeadBlocks(t *testing.T) {
106 c := testConfig(t)
107 fun := c.Fun("entry",
108 Bloc("entry",
109 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
110 Valu("cond", ssaop.OpConstBool, c.config.Types.Bool, 0, nil),
111 If("cond", "b2", "b4")),
112 Bloc("b2",
113 If("cond", "b3", "b4")),
114 Bloc("b3",
115 If("cond", "b3", "b4")),
116 Bloc("b4",
117 If("cond", "b3", "exit")),
118 Bloc("exit",
119 Exit("mem")))
120
121 CheckFunc(fun.f)
122 Opt(fun.f)
123 CheckFunc(fun.f)
124 Deadcode(fun.f)
125 CheckFunc(fun.f)
126 if fun.blocks["entry"].Kind != block.BlockPlain {
127 t.Errorf("if(false) not simplified")
128 }
129 for _, b := range fun.f.Blocks {
130 if b == fun.blocks["b2"] {
131 t.Errorf("b2 block still present")
132 }
133 if b == fun.blocks["b3"] {
134 t.Errorf("b3 block still present")
135 }
136 for _, v := range b.Values {
137 if v == fun.values["cond"] {
138 t.Errorf("constant condition still present")
139 }
140 }
141 }
142 }
143
144 func BenchmarkDeadCode(b *testing.B) {
145 for _, n := range [...]int{1, 10, 100, 1000, 10000, 100000, 200000} {
146 b.Run(strconv.Itoa(n), func(b *testing.B) {
147 c := testConfig(b)
148 blocks := make([]bloc, 0, n+2)
149 blocks = append(blocks,
150 Bloc("entry",
151 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
152 Goto("exit")))
153 blocks = append(blocks, Bloc("exit", Exit("mem")))
154 for i := 0; i < n; i++ {
155 blocks = append(blocks, Bloc(fmt.Sprintf("dead%d", i), Goto("exit")))
156 }
157 b.ResetTimer()
158 for i := 0; i < b.N; i++ {
159 fun := c.Fun("entry", blocks...)
160 Deadcode(fun.f)
161 }
162 })
163 }
164 }
165
View as plain text