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