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 }