github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/compile/internal/ssa/shift_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  	"testing"
     9  )
    10  
    11  func TestShiftConstAMD64(t *testing.T) {
    12  	c := testConfig(t)
    13  	fun := makeConstShiftFunc(c, 18, OpLsh64x64, TypeUInt64)
    14  	checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHLQconst: 1, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
    15  
    16  	fun = makeConstShiftFunc(c, 66, OpLsh64x64, TypeUInt64)
    17  	checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHLQconst: 0, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
    18  
    19  	fun = makeConstShiftFunc(c, 18, OpRsh64Ux64, TypeUInt64)
    20  	checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHRQconst: 1, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
    21  
    22  	fun = makeConstShiftFunc(c, 66, OpRsh64Ux64, TypeUInt64)
    23  	checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHRQconst: 0, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
    24  
    25  	fun = makeConstShiftFunc(c, 18, OpRsh64x64, TypeInt64)
    26  	checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SARQconst: 1, OpAMD64CMPQconst: 0})
    27  
    28  	fun = makeConstShiftFunc(c, 66, OpRsh64x64, TypeInt64)
    29  	checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SARQconst: 1, OpAMD64CMPQconst: 0})
    30  }
    31  
    32  func makeConstShiftFunc(c *Conf, amount int64, op Op, typ Type) fun {
    33  	ptyp := &TypeImpl{Size_: 8, Ptr: true, Name: "ptr"}
    34  	fun := c.Fun("entry",
    35  		Bloc("entry",
    36  			Valu("mem", OpInitMem, TypeMem, 0, nil),
    37  			Valu("SP", OpSP, TypeUInt64, 0, nil),
    38  			Valu("argptr", OpOffPtr, ptyp, 8, nil, "SP"),
    39  			Valu("resptr", OpOffPtr, ptyp, 16, nil, "SP"),
    40  			Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"),
    41  			Valu("c", OpConst64, TypeUInt64, amount, nil),
    42  			Valu("shift", op, typ, 0, nil, "load", "c"),
    43  			Valu("store", OpStore, TypeMem, 0, TypeUInt64, "resptr", "shift", "mem"),
    44  			Exit("store")))
    45  	Compile(fun.f)
    46  	return fun
    47  }
    48  
    49  func TestShiftToExtensionAMD64(t *testing.T) {
    50  	// Test that eligible pairs of constant shifts are converted to extensions.
    51  	// For example:
    52  	//   (uint64(x) << 32) >> 32 -> uint64(uint32(x))
    53  	ops := map[Op]int{
    54  		OpAMD64SHLQconst: 0, OpAMD64SHLLconst: 0,
    55  		OpAMD64SHRQconst: 0, OpAMD64SHRLconst: 0,
    56  		OpAMD64SARQconst: 0, OpAMD64SARLconst: 0,
    57  	}
    58  	tests := [...]struct {
    59  		amount      int64
    60  		left, right Op
    61  		typ         Type
    62  	}{
    63  		// unsigned
    64  		{56, OpLsh64x64, OpRsh64Ux64, TypeUInt64},
    65  		{48, OpLsh64x64, OpRsh64Ux64, TypeUInt64},
    66  		{32, OpLsh64x64, OpRsh64Ux64, TypeUInt64},
    67  		{24, OpLsh32x64, OpRsh32Ux64, TypeUInt32},
    68  		{16, OpLsh32x64, OpRsh32Ux64, TypeUInt32},
    69  		{8, OpLsh16x64, OpRsh16Ux64, TypeUInt16},
    70  		// signed
    71  		{56, OpLsh64x64, OpRsh64x64, TypeInt64},
    72  		{48, OpLsh64x64, OpRsh64x64, TypeInt64},
    73  		{32, OpLsh64x64, OpRsh64x64, TypeInt64},
    74  		{24, OpLsh32x64, OpRsh32x64, TypeInt32},
    75  		{16, OpLsh32x64, OpRsh32x64, TypeInt32},
    76  		{8, OpLsh16x64, OpRsh16x64, TypeInt16},
    77  	}
    78  	c := testConfig(t)
    79  	for _, tc := range tests {
    80  		fun := makeShiftExtensionFunc(c, tc.amount, tc.left, tc.right, tc.typ)
    81  		checkOpcodeCounts(t, fun.f, ops)
    82  	}
    83  }
    84  
    85  // makeShiftExtensionFunc generates a function containing:
    86  //
    87  //   (rshift (lshift (Const64 [amount])) (Const64 [amount]))
    88  //
    89  // This may be equivalent to a sign or zero extension.
    90  func makeShiftExtensionFunc(c *Conf, amount int64, lshift, rshift Op, typ Type) fun {
    91  	ptyp := &TypeImpl{Size_: 8, Ptr: true, Name: "ptr"}
    92  	fun := c.Fun("entry",
    93  		Bloc("entry",
    94  			Valu("mem", OpInitMem, TypeMem, 0, nil),
    95  			Valu("SP", OpSP, TypeUInt64, 0, nil),
    96  			Valu("argptr", OpOffPtr, ptyp, 8, nil, "SP"),
    97  			Valu("resptr", OpOffPtr, ptyp, 16, nil, "SP"),
    98  			Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"),
    99  			Valu("c", OpConst64, TypeUInt64, amount, nil),
   100  			Valu("lshift", lshift, typ, 0, nil, "load", "c"),
   101  			Valu("rshift", rshift, typ, 0, nil, "lshift", "c"),
   102  			Valu("store", OpStore, TypeMem, 0, TypeUInt64, "resptr", "rshift", "mem"),
   103  			Exit("store")))
   104  	Compile(fun.f)
   105  	return fun
   106  }