Source file src/cmd/compile/internal/compare/compare_test.go

     1  // Copyright 2022 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 compare
     6  
     7  import (
     8  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/typecheck"
    10  	"cmd/compile/internal/types"
    11  	"cmd/internal/obj"
    12  	"cmd/internal/src"
    13  	"cmd/internal/sys"
    14  	"testing"
    15  )
    16  
    17  type typefn func() *types.Type
    18  
    19  func init() {
    20  	// These are the few constants that need to be initialized in order to use
    21  	// the types package without using the typecheck package by calling
    22  	// typecheck.InitUniverse() (the normal way to initialize the types package).
    23  	types.PtrSize = 8
    24  	types.RegSize = 8
    25  	types.MaxWidth = 1 << 50
    26  	typecheck.InitUniverse()
    27  	base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
    28  }
    29  
    30  func TestEqStructCost(t *testing.T) {
    31  	repeat := func(n int, typ *types.Type) []*types.Type {
    32  		typs := make([]*types.Type, n)
    33  		for i := range typs {
    34  			typs[i] = typ
    35  		}
    36  		return typs
    37  	}
    38  
    39  	tt := []struct {
    40  		name             string
    41  		cost             int64
    42  		nonMergeLoadCost int64
    43  		fieldTypes       []*types.Type
    44  	}{
    45  		{"struct without fields", 0, 0, nil},
    46  		{"struct with 1 byte field", 1, 1, repeat(1, types.ByteType)},
    47  		{"struct with 8 byte fields", 1, 8, repeat(8, types.ByteType)},
    48  		{"struct with 16 byte fields", 2, 16, repeat(16, types.ByteType)},
    49  		{"struct with 32 byte fields", 4, 32, repeat(32, types.ByteType)},
    50  		{"struct with 2 int32 fields", 1, 2, repeat(2, types.Types[types.TINT32])},
    51  		{"struct with 2 int32 fields and 1 int64", 2, 3,
    52  			[]*types.Type{
    53  				types.Types[types.TINT32],
    54  				types.Types[types.TINT32],
    55  				types.Types[types.TINT64],
    56  			},
    57  		},
    58  		{"struct with 1 int field and 1 string", 3, 3,
    59  			[]*types.Type{
    60  				types.Types[types.TINT64],
    61  				types.Types[types.TSTRING],
    62  			},
    63  		},
    64  		{"struct with 2 strings", 4, 4, repeat(2, types.Types[types.TSTRING])},
    65  		{"struct with 1 large byte array field", 26, 101,
    66  			[]*types.Type{
    67  				types.NewArray(types.Types[types.TUINT16], 101),
    68  			},
    69  		},
    70  		{"struct with string array field", 4, 4,
    71  			[]*types.Type{
    72  				types.NewArray(types.Types[types.TSTRING], 2),
    73  			},
    74  		},
    75  	}
    76  
    77  	for _, tc := range tt {
    78  		t.Run(tc.name, func(t *testing.T) {
    79  			fields := make([]*types.Field, len(tc.fieldTypes))
    80  			for i, ftyp := range tc.fieldTypes {
    81  				fields[i] = types.NewField(src.NoXPos, typecheck.LookupNum("f", i), ftyp)
    82  			}
    83  			typ := types.NewStruct(fields)
    84  			types.CalcSize(typ)
    85  
    86  			want := tc.cost
    87  			base.Ctxt.Arch.CanMergeLoads = true
    88  			actual := EqStructCost(typ)
    89  			if actual != want {
    90  				t.Errorf("CanMergeLoads=true EqStructCost(%v) = %d, want %d", typ, actual, want)
    91  			}
    92  
    93  			base.Ctxt.Arch.CanMergeLoads = false
    94  			want = tc.nonMergeLoadCost
    95  			actual = EqStructCost(typ)
    96  			if actual != want {
    97  				t.Errorf("CanMergeLoads=false EqStructCost(%v) = %d, want %d", typ, actual, want)
    98  			}
    99  		})
   100  	}
   101  }
   102  

View as plain text