Source file src/cmd/compile/internal/ssa/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 ssa
     6  
     7  import (
     8  	"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  }
   162  

View as plain text