Source file src/cmd/compile/internal/ssacompile/deadcode_test.go

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

View as plain text