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

     1  // Copyright 2016 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  	"testing"
     9  
    10  	"cmd/compile/internal/ssa/ssaop"
    11  	"cmd/compile/internal/types"
    12  )
    13  
    14  type tstAux struct {
    15  	s string
    16  }
    17  
    18  func (*tstAux) CanBeAnSSAAux() {}
    19  
    20  // This tests for a bug found when partitioning, but not sorting by the Aux value.
    21  func TestCSEAuxPartitionBug(t *testing.T) {
    22  	c := testConfig(t)
    23  	arg1Aux := &tstAux{"arg1-aux"}
    24  	arg2Aux := &tstAux{"arg2-aux"}
    25  	arg3Aux := &tstAux{"arg3-aux"}
    26  	a := c.Temp(c.config.Types.Int8.PtrTo())
    27  
    28  	// construct lots of values with args that have aux values and place
    29  	// them in an order that triggers the bug
    30  	fun := c.Fun("entry",
    31  		Bloc("entry",
    32  			Valu("start", ssaop.OpInitMem, types.TypeMem, 0, nil),
    33  			Valu("sp", ssaop.OpSP, c.config.Types.Uintptr, 0, nil),
    34  			Valu("r7", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg1"),
    35  			Valu("r1", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
    36  			Valu("arg1", ssaop.OpArg, c.config.Types.Int64, 0, arg1Aux),
    37  			Valu("arg2", ssaop.OpArg, c.config.Types.Int64, 0, arg2Aux),
    38  			Valu("arg3", ssaop.OpArg, c.config.Types.Int64, 0, arg3Aux),
    39  			Valu("r9", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "r7", "r8"),
    40  			Valu("r4", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
    41  			Valu("r8", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "arg3", "arg2"),
    42  			Valu("r2", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
    43  			Valu("raddr", ssaop.OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
    44  			Valu("raddrdef", ssaop.OpVarDef, types.TypeMem, 0, a, "start"),
    45  			Valu("r6", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "r4", "r5"),
    46  			Valu("r3", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "arg1", "arg2"),
    47  			Valu("r5", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "r2", "r3"),
    48  			Valu("r10", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "r6", "r9"),
    49  			Valu("rstore", ssaop.OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r10", "raddrdef"),
    50  			Goto("exit")),
    51  		Bloc("exit",
    52  			Exit("rstore")))
    53  
    54  	CheckFunc(fun.f)
    55  	cse(fun.f)
    56  	deadcode(fun.f)
    57  	CheckFunc(fun.f)
    58  
    59  	s1Cnt := 2
    60  	// r1 == r2 == r3, needs to remove two of this set
    61  	s2Cnt := 1
    62  	// r4 == r5, needs to remove one of these
    63  	for k, v := range fun.values {
    64  		if v.Op == ssaop.OpInvalid {
    65  			switch k {
    66  			case "r1":
    67  				fallthrough
    68  			case "r2":
    69  				fallthrough
    70  			case "r3":
    71  				if s1Cnt == 0 {
    72  					t.Errorf("cse removed all of r1,r2,r3")
    73  				}
    74  				s1Cnt--
    75  
    76  			case "r4":
    77  				fallthrough
    78  			case "r5":
    79  				if s2Cnt == 0 {
    80  					t.Errorf("cse removed all of r4,r5")
    81  				}
    82  				s2Cnt--
    83  			default:
    84  				t.Errorf("cse removed %s, but shouldn't have", k)
    85  			}
    86  		}
    87  	}
    88  
    89  	if s1Cnt != 0 || s2Cnt != 0 {
    90  		t.Errorf("%d values missed during cse", s1Cnt+s2Cnt)
    91  	}
    92  }
    93  
    94  // TestZCSE tests the zero arg cse.
    95  func TestZCSE(t *testing.T) {
    96  	c := testConfig(t)
    97  	a := c.Temp(c.config.Types.Int8.PtrTo())
    98  
    99  	fun := c.Fun("entry",
   100  		Bloc("entry",
   101  			Valu("start", ssaop.OpInitMem, types.TypeMem, 0, nil),
   102  			Valu("sp", ssaop.OpSP, c.config.Types.Uintptr, 0, nil),
   103  			Valu("sb1", ssaop.OpSB, c.config.Types.Uintptr, 0, nil),
   104  			Valu("sb2", ssaop.OpSB, c.config.Types.Uintptr, 0, nil),
   105  			Valu("addr1", ssaop.OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb1"),
   106  			Valu("addr2", ssaop.OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sb2"),
   107  			Valu("a1ld", ssaop.OpLoad, c.config.Types.Int64, 0, nil, "addr1", "start"),
   108  			Valu("a2ld", ssaop.OpLoad, c.config.Types.Int64, 0, nil, "addr2", "start"),
   109  			Valu("c1", ssaop.OpConst64, c.config.Types.Int64, 1, nil),
   110  			Valu("r1", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "a1ld", "c1"),
   111  			Valu("c2", ssaop.OpConst64, c.config.Types.Int64, 1, nil),
   112  			Valu("r2", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "a2ld", "c2"),
   113  			Valu("r3", ssaop.OpAdd64, c.config.Types.Int64, 0, nil, "r1", "r2"),
   114  			Valu("raddr", ssaop.OpLocalAddr, c.config.Types.Int64.PtrTo(), 0, nil, "sp", "start"),
   115  			Valu("raddrdef", ssaop.OpVarDef, types.TypeMem, 0, a, "start"),
   116  			Valu("rstore", ssaop.OpStore, types.TypeMem, 0, c.config.Types.Int64, "raddr", "r3", "raddrdef"),
   117  			Goto("exit")),
   118  		Bloc("exit",
   119  			Exit("rstore")))
   120  
   121  	CheckFunc(fun.f)
   122  	zcse(fun.f)
   123  	deadcode(fun.f)
   124  	CheckFunc(fun.f)
   125  
   126  	if fun.values["c1"].Op != ssaop.OpInvalid && fun.values["c2"].Op != ssaop.OpInvalid {
   127  		t.Errorf("zsce should have removed c1 or c2")
   128  	}
   129  	if fun.values["sb1"].Op != ssaop.OpInvalid && fun.values["sb2"].Op != ssaop.OpInvalid {
   130  		t.Errorf("zsce should have removed sb1 or sb2")
   131  	}
   132  }
   133  

View as plain text