github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/compare/compare_test.go (about)

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