github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/compile/internal/ssa/deadstore_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 "testing"
     8  
     9  func TestDeadStore(t *testing.T) {
    10  	c := testConfig(t)
    11  	elemType := &TypeImpl{Size_: 1, Name: "testtype"}
    12  	ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr", Elem_: elemType} // dummy for testing
    13  	fun := c.Fun("entry",
    14  		Bloc("entry",
    15  			Valu("start", OpInitMem, TypeMem, 0, nil),
    16  			Valu("sb", OpSB, TypeInvalid, 0, nil),
    17  			Valu("v", OpConstBool, TypeBool, 1, nil),
    18  			Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
    19  			Valu("addr2", OpAddr, ptrType, 0, nil, "sb"),
    20  			Valu("addr3", OpAddr, ptrType, 0, nil, "sb"),
    21  			Valu("zero1", OpZero, TypeMem, 1, TypeBool, "addr3", "start"),
    22  			Valu("store1", OpStore, TypeMem, 0, TypeBool, "addr1", "v", "zero1"),
    23  			Valu("store2", OpStore, TypeMem, 0, TypeBool, "addr2", "v", "store1"),
    24  			Valu("store3", OpStore, TypeMem, 0, TypeBool, "addr1", "v", "store2"),
    25  			Valu("store4", OpStore, TypeMem, 0, TypeBool, "addr3", "v", "store3"),
    26  			Goto("exit")),
    27  		Bloc("exit",
    28  			Exit("store3")))
    29  
    30  	CheckFunc(fun.f)
    31  	dse(fun.f)
    32  	CheckFunc(fun.f)
    33  
    34  	v1 := fun.values["store1"]
    35  	if v1.Op != OpCopy {
    36  		t.Errorf("dead store not removed")
    37  	}
    38  
    39  	v2 := fun.values["zero1"]
    40  	if v2.Op != OpCopy {
    41  		t.Errorf("dead store (zero) not removed")
    42  	}
    43  }
    44  func TestDeadStorePhi(t *testing.T) {
    45  	// make sure we don't get into an infinite loop with phi values.
    46  	c := testConfig(t)
    47  	ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
    48  	fun := c.Fun("entry",
    49  		Bloc("entry",
    50  			Valu("start", OpInitMem, TypeMem, 0, nil),
    51  			Valu("sb", OpSB, TypeInvalid, 0, nil),
    52  			Valu("v", OpConstBool, TypeBool, 1, nil),
    53  			Valu("addr", OpAddr, ptrType, 0, nil, "sb"),
    54  			Goto("loop")),
    55  		Bloc("loop",
    56  			Valu("phi", OpPhi, TypeMem, 0, nil, "start", "store"),
    57  			Valu("store", OpStore, TypeMem, 0, TypeBool, "addr", "v", "phi"),
    58  			If("v", "loop", "exit")),
    59  		Bloc("exit",
    60  			Exit("store")))
    61  
    62  	CheckFunc(fun.f)
    63  	dse(fun.f)
    64  	CheckFunc(fun.f)
    65  }
    66  
    67  func TestDeadStoreTypes(t *testing.T) {
    68  	// Make sure a narrow store can't shadow a wider one. We test an even
    69  	// stronger restriction, that one store can't shadow another unless the
    70  	// types of the address fields are identical (where identicalness is
    71  	// decided by the CSE pass).
    72  	c := testConfig(t)
    73  	t1 := &TypeImpl{Size_: 8, Ptr: true, Name: "t1"}
    74  	t2 := &TypeImpl{Size_: 4, Ptr: true, Name: "t2"}
    75  	fun := c.Fun("entry",
    76  		Bloc("entry",
    77  			Valu("start", OpInitMem, TypeMem, 0, nil),
    78  			Valu("sb", OpSB, TypeInvalid, 0, nil),
    79  			Valu("v", OpConstBool, TypeBool, 1, nil),
    80  			Valu("addr1", OpAddr, t1, 0, nil, "sb"),
    81  			Valu("addr2", OpAddr, t2, 0, nil, "sb"),
    82  			Valu("store1", OpStore, TypeMem, 0, TypeBool, "addr1", "v", "start"),
    83  			Valu("store2", OpStore, TypeMem, 0, TypeBool, "addr2", "v", "store1"),
    84  			Goto("exit")),
    85  		Bloc("exit",
    86  			Exit("store2")))
    87  
    88  	CheckFunc(fun.f)
    89  	cse(fun.f)
    90  	dse(fun.f)
    91  	CheckFunc(fun.f)
    92  
    93  	v := fun.values["store1"]
    94  	if v.Op == OpCopy {
    95  		t.Errorf("store %s incorrectly removed", v)
    96  	}
    97  }
    98  
    99  func TestDeadStoreUnsafe(t *testing.T) {
   100  	// Make sure a narrow store can't shadow a wider one. The test above
   101  	// covers the case of two different types, but unsafe pointer casting
   102  	// can get to a point where the size is changed but type unchanged.
   103  	c := testConfig(t)
   104  	ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
   105  	fun := c.Fun("entry",
   106  		Bloc("entry",
   107  			Valu("start", OpInitMem, TypeMem, 0, nil),
   108  			Valu("sb", OpSB, TypeInvalid, 0, nil),
   109  			Valu("v", OpConstBool, TypeBool, 1, nil),
   110  			Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
   111  			Valu("store1", OpStore, TypeMem, 0, TypeInt64, "addr1", "v", "start"), // store 8 bytes
   112  			Valu("store2", OpStore, TypeMem, 0, TypeBool, "addr1", "v", "store1"), // store 1 byte
   113  			Goto("exit")),
   114  		Bloc("exit",
   115  			Exit("store2")))
   116  
   117  	CheckFunc(fun.f)
   118  	cse(fun.f)
   119  	dse(fun.f)
   120  	CheckFunc(fun.f)
   121  
   122  	v := fun.values["store1"]
   123  	if v.Op == OpCopy {
   124  		t.Errorf("store %s incorrectly removed", v)
   125  	}
   126  }