github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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 "github.com/gagliardetto/golang-go/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 // dead loop 23 Bloc("deadblock", 24 // dead value in dead block 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 }