github.com/euank/go@v0.0.0-20160829210321-495514729181/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 := Fun(c, "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 := Fun(c, "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 := Fun(c, "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 := Fun(c, "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 := Fun(c, "entry", blocks...)
   156  				Deadcode(fun.f)
   157  				fun.f.Free()
   158  			}
   159  		})
   160  	}
   161  }