| // Copyright 2015 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package ssa | |
| import ( | |
| "cmd/compile/internal/types" | |
| "fmt" | |
| "strconv" | |
| "testing" | |
| ) | |
| func TestDeadLoop(t *testing.T) { | |
| c := testConfig(t) | |
| fun := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("mem", OpInitMem, types.TypeMem, 0, nil), | |
| Goto("exit")), | |
| Bloc("exit", | |
| Exit("mem")), | |
| // dead loop | |
| Bloc("deadblock", | |
| // dead value in dead block | |
| Valu("deadval", OpConstBool, c.config.Types.Bool, 1, nil), | |
| If("deadval", "deadblock", "exit"))) | |
| CheckFunc(fun.f) | |
| Deadcode(fun.f) | |
| CheckFunc(fun.f) | |
| for _, b := range fun.f.Blocks { | |
| if b == fun.blocks["deadblock"] { | |
| t.Errorf("dead block not removed") | |
| } | |
| for _, v := range b.Values { | |
| if v == fun.values["deadval"] { | |
| t.Errorf("control value of dead block not removed") | |
| } | |
| } | |
| } | |
| } | |
| func TestDeadValue(t *testing.T) { | |
| c := testConfig(t) | |
| fun := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("mem", OpInitMem, types.TypeMem, 0, nil), | |
| Valu("deadval", OpConst64, c.config.Types.Int64, 37, nil), | |
| Goto("exit")), | |
| Bloc("exit", | |
| Exit("mem"))) | |
| CheckFunc(fun.f) | |
| Deadcode(fun.f) | |
| CheckFunc(fun.f) | |
| for _, b := range fun.f.Blocks { | |
| for _, v := range b.Values { | |
| if v == fun.values["deadval"] { | |
| t.Errorf("dead value not removed") | |
| } | |
| } | |
| } | |
| } | |
| func TestNeverTaken(t *testing.T) { | |
| c := testConfig(t) | |
| fun := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("cond", OpConstBool, c.config.Types.Bool, 0, nil), | |
| Valu("mem", OpInitMem, types.TypeMem, 0, nil), | |
| If("cond", "then", "else")), | |
| Bloc("then", | |
| Goto("exit")), | |
| Bloc("else", | |
| Goto("exit")), | |
| Bloc("exit", | |
| Exit("mem"))) | |
| CheckFunc(fun.f) | |
| Opt(fun.f) | |
| Deadcode(fun.f) | |
| CheckFunc(fun.f) | |
| if fun.blocks["entry"].Kind != BlockPlain { | |
| t.Errorf("if(false) not simplified") | |
| } | |
| for _, b := range fun.f.Blocks { | |
| if b == fun.blocks["then"] { | |
| t.Errorf("then block still present") | |
| } | |
| for _, v := range b.Values { | |
| if v == fun.values["cond"] { | |
| t.Errorf("constant condition still present") | |
| } | |
| } | |
| } | |
| } | |
| func TestNestedDeadBlocks(t *testing.T) { | |
| c := testConfig(t) | |
| fun := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("mem", OpInitMem, types.TypeMem, 0, nil), | |
| Valu("cond", OpConstBool, c.config.Types.Bool, 0, nil), | |
| If("cond", "b2", "b4")), | |
| Bloc("b2", | |
| If("cond", "b3", "b4")), | |
| Bloc("b3", | |
| If("cond", "b3", "b4")), | |
| Bloc("b4", | |
| If("cond", "b3", "exit")), | |
| Bloc("exit", | |
| Exit("mem"))) | |
| CheckFunc(fun.f) | |
| Opt(fun.f) | |
| CheckFunc(fun.f) | |
| Deadcode(fun.f) | |
| CheckFunc(fun.f) | |
| if fun.blocks["entry"].Kind != BlockPlain { | |
| t.Errorf("if(false) not simplified") | |
| } | |
| for _, b := range fun.f.Blocks { | |
| if b == fun.blocks["b2"] { | |
| t.Errorf("b2 block still present") | |
| } | |
| if b == fun.blocks["b3"] { | |
| t.Errorf("b3 block still present") | |
| } | |
| for _, v := range b.Values { | |
| if v == fun.values["cond"] { | |
| t.Errorf("constant condition still present") | |
| } | |
| } | |
| } | |
| } | |
| func BenchmarkDeadCode(b *testing.B) { | |
| for _, n := range [...]int{1, 10, 100, 1000, 10000, 100000, 200000} { | |
| b.Run(strconv.Itoa(n), func(b *testing.B) { | |
| c := testConfig(b) | |
| blocks := make([]bloc, 0, n+2) | |
| blocks = append(blocks, | |
| Bloc("entry", | |
| Valu("mem", OpInitMem, types.TypeMem, 0, nil), | |
| Goto("exit"))) | |
| blocks = append(blocks, Bloc("exit", Exit("mem"))) | |
| for i := 0; i < n; i++ { | |
| blocks = append(blocks, Bloc(fmt.Sprintf("dead%d", i), Goto("exit"))) | |
| } | |
| b.ResetTimer() | |
| for i := 0; i < b.N; i++ { | |
| fun := c.Fun("entry", blocks...) | |
| Deadcode(fun.f) | |
| } | |
| }) | |
| } | |
| } |