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