]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: replace eqstring with memequal
authorMartin Möhrmann <moehrmann@google.com>
Mon, 7 Aug 2017 20:36:22 +0000 (22:36 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Tue, 22 Aug 2017 17:59:02 +0000 (17:59 +0000)
eqstring is only called for strings with equal lengths.
Instead of pushing a pointer and length for each argument string
on the stack we can omit pushing one of the lengths on the stack.

Changing eqstrings signature to eqstring(*uint8, *uint8, int) bool
to implement the above optimization would make it very similar to the
existing memequal(*any, *any, uintptr) bool function.

Since string lengths are positive we can avoid code redundancy and
use memequal instead of using eqstring with an optimized signature.

go command binary size reduced by 4128 bytes on amd64.

name                          old time/op    new time/op    delta
CompareStringEqual              6.03ns ± 1%    5.71ns ± 1%   -5.23%  (p=0.000 n=19+18)
CompareStringIdentical          2.88ns ± 1%    3.22ns ± 7%  +11.86%  (p=0.000 n=20+20)
CompareStringSameLength         4.31ns ± 1%    4.01ns ± 1%   -7.17%  (p=0.000 n=19+19)
CompareStringDifferentLength    0.29ns ± 2%    0.29ns ± 2%     ~     (p=1.000 n=20+20)
CompareStringBigUnaligned       64.3µs ± 2%    64.1µs ± 3%     ~     (p=0.164 n=20+19)
CompareStringBig                61.9µs ± 1%    61.6µs ± 2%   -0.46%  (p=0.033 n=20+19)

Change-Id: Ice15f3b937c981f0d3bc8479a9ea0d10658ac8df
Reviewed-on: https://go-review.googlesource.com/53650
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
14 files changed:
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/walk.go
src/runtime/asm_386.s
src/runtime/asm_amd64.s
src/runtime/asm_amd64p32.s
src/runtime/asm_arm.s
src/runtime/asm_arm64.s
src/runtime/asm_mips64x.s
src/runtime/asm_mipsx.s
src/runtime/asm_ppc64x.s
src/runtime/asm_s390x.s
src/runtime/runtime_test.go
src/runtime/stubs.go

index 05836cc951fde485415c4b9f31b2cb4004396893..fb3fdf90df9a87e4e1f1ea4922558d9f071b7d0e 100644 (file)
@@ -39,117 +39,116 @@ var runtimeDecls = [...]struct {
        {"concatstring5", funcTag, 29},
        {"concatstrings", funcTag, 31},
        {"cmpstring", funcTag, 33},
-       {"eqstring", funcTag, 34},
-       {"intstring", funcTag, 37},
-       {"slicebytetostring", funcTag, 39},
-       {"slicebytetostringtmp", funcTag, 40},
-       {"slicerunetostring", funcTag, 43},
-       {"stringtoslicebyte", funcTag, 44},
-       {"stringtoslicerune", funcTag, 47},
-       {"decoderune", funcTag, 48},
-       {"slicecopy", funcTag, 50},
-       {"slicestringcopy", funcTag, 51},
-       {"convI2I", funcTag, 52},
-       {"convT2E", funcTag, 53},
-       {"convT2E16", funcTag, 53},
-       {"convT2E32", funcTag, 53},
-       {"convT2E64", funcTag, 53},
-       {"convT2Estring", funcTag, 53},
-       {"convT2Eslice", funcTag, 53},
-       {"convT2Enoptr", funcTag, 53},
-       {"convT2I", funcTag, 53},
-       {"convT2I16", funcTag, 53},
-       {"convT2I32", funcTag, 53},
-       {"convT2I64", funcTag, 53},
-       {"convT2Istring", funcTag, 53},
-       {"convT2Islice", funcTag, 53},
-       {"convT2Inoptr", funcTag, 53},
-       {"assertE2I", funcTag, 52},
-       {"assertE2I2", funcTag, 54},
-       {"assertI2I", funcTag, 52},
-       {"assertI2I2", funcTag, 54},
-       {"panicdottypeE", funcTag, 55},
-       {"panicdottypeI", funcTag, 55},
-       {"panicnildottype", funcTag, 56},
-       {"ifaceeq", funcTag, 59},
-       {"efaceeq", funcTag, 59},
-       {"makemap", funcTag, 61},
-       {"mapaccess1", funcTag, 62},
-       {"mapaccess1_fast32", funcTag, 63},
-       {"mapaccess1_fast64", funcTag, 63},
-       {"mapaccess1_faststr", funcTag, 63},
-       {"mapaccess1_fat", funcTag, 64},
-       {"mapaccess2", funcTag, 65},
-       {"mapaccess2_fast32", funcTag, 66},
-       {"mapaccess2_fast64", funcTag, 66},
-       {"mapaccess2_faststr", funcTag, 66},
-       {"mapaccess2_fat", funcTag, 67},
-       {"mapassign", funcTag, 62},
-       {"mapassign_fast32", funcTag, 63},
-       {"mapassign_fast64", funcTag, 63},
-       {"mapassign_faststr", funcTag, 63},
-       {"mapiterinit", funcTag, 68},
-       {"mapdelete", funcTag, 68},
-       {"mapdelete_fast32", funcTag, 69},
-       {"mapdelete_fast64", funcTag, 69},
-       {"mapdelete_faststr", funcTag, 69},
-       {"mapiternext", funcTag, 70},
-       {"makechan64", funcTag, 72},
-       {"makechan", funcTag, 73},
-       {"chanrecv1", funcTag, 75},
-       {"chanrecv2", funcTag, 76},
-       {"chansend1", funcTag, 78},
+       {"intstring", funcTag, 36},
+       {"slicebytetostring", funcTag, 38},
+       {"slicebytetostringtmp", funcTag, 39},
+       {"slicerunetostring", funcTag, 42},
+       {"stringtoslicebyte", funcTag, 43},
+       {"stringtoslicerune", funcTag, 46},
+       {"decoderune", funcTag, 47},
+       {"slicecopy", funcTag, 49},
+       {"slicestringcopy", funcTag, 50},
+       {"convI2I", funcTag, 51},
+       {"convT2E", funcTag, 52},
+       {"convT2E16", funcTag, 52},
+       {"convT2E32", funcTag, 52},
+       {"convT2E64", funcTag, 52},
+       {"convT2Estring", funcTag, 52},
+       {"convT2Eslice", funcTag, 52},
+       {"convT2Enoptr", funcTag, 52},
+       {"convT2I", funcTag, 52},
+       {"convT2I16", funcTag, 52},
+       {"convT2I32", funcTag, 52},
+       {"convT2I64", funcTag, 52},
+       {"convT2Istring", funcTag, 52},
+       {"convT2Islice", funcTag, 52},
+       {"convT2Inoptr", funcTag, 52},
+       {"assertE2I", funcTag, 51},
+       {"assertE2I2", funcTag, 53},
+       {"assertI2I", funcTag, 51},
+       {"assertI2I2", funcTag, 53},
+       {"panicdottypeE", funcTag, 54},
+       {"panicdottypeI", funcTag, 54},
+       {"panicnildottype", funcTag, 55},
+       {"ifaceeq", funcTag, 58},
+       {"efaceeq", funcTag, 58},
+       {"makemap", funcTag, 60},
+       {"mapaccess1", funcTag, 61},
+       {"mapaccess1_fast32", funcTag, 62},
+       {"mapaccess1_fast64", funcTag, 62},
+       {"mapaccess1_faststr", funcTag, 62},
+       {"mapaccess1_fat", funcTag, 63},
+       {"mapaccess2", funcTag, 64},
+       {"mapaccess2_fast32", funcTag, 65},
+       {"mapaccess2_fast64", funcTag, 65},
+       {"mapaccess2_faststr", funcTag, 65},
+       {"mapaccess2_fat", funcTag, 66},
+       {"mapassign", funcTag, 61},
+       {"mapassign_fast32", funcTag, 62},
+       {"mapassign_fast64", funcTag, 62},
+       {"mapassign_faststr", funcTag, 62},
+       {"mapiterinit", funcTag, 67},
+       {"mapdelete", funcTag, 67},
+       {"mapdelete_fast32", funcTag, 68},
+       {"mapdelete_fast64", funcTag, 68},
+       {"mapdelete_faststr", funcTag, 68},
+       {"mapiternext", funcTag, 69},
+       {"makechan64", funcTag, 71},
+       {"makechan", funcTag, 72},
+       {"chanrecv1", funcTag, 74},
+       {"chanrecv2", funcTag, 75},
+       {"chansend1", funcTag, 77},
        {"closechan", funcTag, 23},
-       {"writeBarrier", varTag, 80},
-       {"writebarrierptr", funcTag, 81},
-       {"typedmemmove", funcTag, 82},
-       {"typedmemclr", funcTag, 83},
-       {"typedslicecopy", funcTag, 84},
-       {"selectnbsend", funcTag, 85},
-       {"selectnbrecv", funcTag, 86},
-       {"selectnbrecv2", funcTag, 88},
-       {"newselect", funcTag, 89},
-       {"selectsend", funcTag, 90},
-       {"selectrecv", funcTag, 91},
-       {"selectdefault", funcTag, 56},
-       {"selectgo", funcTag, 92},
+       {"writeBarrier", varTag, 79},
+       {"writebarrierptr", funcTag, 80},
+       {"typedmemmove", funcTag, 81},
+       {"typedmemclr", funcTag, 82},
+       {"typedslicecopy", funcTag, 83},
+       {"selectnbsend", funcTag, 84},
+       {"selectnbrecv", funcTag, 85},
+       {"selectnbrecv2", funcTag, 87},
+       {"newselect", funcTag, 88},
+       {"selectsend", funcTag, 89},
+       {"selectrecv", funcTag, 90},
+       {"selectdefault", funcTag, 55},
+       {"selectgo", funcTag, 91},
        {"block", funcTag, 5},
-       {"makeslice", funcTag, 94},
-       {"makeslice64", funcTag, 95},
-       {"growslice", funcTag, 96},
-       {"memmove", funcTag, 97},
-       {"memclrNoHeapPointers", funcTag, 98},
-       {"memclrHasPointers", funcTag, 98},
-       {"memequal", funcTag, 99},
-       {"memequal8", funcTag, 100},
-       {"memequal16", funcTag, 100},
-       {"memequal32", funcTag, 100},
-       {"memequal64", funcTag, 100},
-       {"memequal128", funcTag, 100},
-       {"int64div", funcTag, 101},
-       {"uint64div", funcTag, 102},
-       {"int64mod", funcTag, 101},
-       {"uint64mod", funcTag, 102},
-       {"float64toint64", funcTag, 103},
-       {"float64touint64", funcTag, 104},
-       {"float64touint32", funcTag, 106},
-       {"int64tofloat64", funcTag, 107},
-       {"uint64tofloat64", funcTag, 108},
-       {"uint32tofloat64", funcTag, 109},
-       {"complex128div", funcTag, 110},
-       {"racefuncenter", funcTag, 111},
+       {"makeslice", funcTag, 93},
+       {"makeslice64", funcTag, 94},
+       {"growslice", funcTag, 95},
+       {"memmove", funcTag, 96},
+       {"memclrNoHeapPointers", funcTag, 97},
+       {"memclrHasPointers", funcTag, 97},
+       {"memequal", funcTag, 98},
+       {"memequal8", funcTag, 99},
+       {"memequal16", funcTag, 99},
+       {"memequal32", funcTag, 99},
+       {"memequal64", funcTag, 99},
+       {"memequal128", funcTag, 99},
+       {"int64div", funcTag, 100},
+       {"uint64div", funcTag, 101},
+       {"int64mod", funcTag, 100},
+       {"uint64mod", funcTag, 101},
+       {"float64toint64", funcTag, 102},
+       {"float64touint64", funcTag, 103},
+       {"float64touint32", funcTag, 105},
+       {"int64tofloat64", funcTag, 106},
+       {"uint64tofloat64", funcTag, 107},
+       {"uint32tofloat64", funcTag, 108},
+       {"complex128div", funcTag, 109},
+       {"racefuncenter", funcTag, 110},
        {"racefuncexit", funcTag, 5},
-       {"raceread", funcTag, 111},
-       {"racewrite", funcTag, 111},
-       {"racereadrange", funcTag, 112},
-       {"racewriterange", funcTag, 112},
-       {"msanread", funcTag, 112},
-       {"msanwrite", funcTag, 112},
+       {"raceread", funcTag, 110},
+       {"racewrite", funcTag, 110},
+       {"racereadrange", funcTag, 111},
+       {"racewriterange", funcTag, 111},
+       {"msanread", funcTag, 111},
+       {"msanwrite", funcTag, 111},
        {"support_popcnt", varTag, 11},
 }
 
 func runtimeTypes() []*types.Type {
-       var typs [113]*types.Type
+       var typs [112]*types.Type
        typs[0] = types.Bytetype
        typs[1] = types.NewPtr(typs[0])
        typs[2] = types.Types[TANY]
@@ -184,84 +183,83 @@ func runtimeTypes() []*types.Type {
        typs[31] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[30])}, []*Node{anonfield(typs[21])})
        typs[32] = types.Types[TINT]
        typs[33] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, []*Node{anonfield(typs[32])})
-       typs[34] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, []*Node{anonfield(typs[11])})
-       typs[35] = types.NewArray(typs[0], 4)
-       typs[36] = types.NewPtr(typs[35])
-       typs[37] = functype(nil, []*Node{anonfield(typs[36]), anonfield(typs[15])}, []*Node{anonfield(typs[21])})
-       typs[38] = types.NewSlice(typs[0])
-       typs[39] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[38])}, []*Node{anonfield(typs[21])})
-       typs[40] = functype(nil, []*Node{anonfield(typs[38])}, []*Node{anonfield(typs[21])})
-       typs[41] = types.Runetype
-       typs[42] = types.NewSlice(typs[41])
-       typs[43] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[42])}, []*Node{anonfield(typs[21])})
-       typs[44] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[21])}, []*Node{anonfield(typs[38])})
-       typs[45] = types.NewArray(typs[41], 32)
-       typs[46] = types.NewPtr(typs[45])
-       typs[47] = functype(nil, []*Node{anonfield(typs[46]), anonfield(typs[21])}, []*Node{anonfield(typs[42])})
-       typs[48] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[32])}, []*Node{anonfield(typs[41]), anonfield(typs[32])})
-       typs[49] = types.Types[TUINTPTR]
-       typs[50] = functype(nil, []*Node{anonfield(typs[2]), anonfield(typs[2]), anonfield(typs[49])}, []*Node{anonfield(typs[32])})
-       typs[51] = functype(nil, []*Node{anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
-       typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
-       typs[53] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
-       typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
-       typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
-       typs[56] = functype(nil, []*Node{anonfield(typs[1])}, nil)
-       typs[57] = types.NewPtr(typs[49])
-       typs[58] = types.Types[TUNSAFEPTR]
-       typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])})
-       typs[60] = types.NewMap(typs[2], typs[2])
-       typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[60])})
-       typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
-       typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
-       typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
-       typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
-       typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
-       typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
-       typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, nil)
-       typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, nil)
-       typs[70] = functype(nil, []*Node{anonfield(typs[3])}, nil)
-       typs[71] = types.NewChan(typs[2], types.Cboth)
-       typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[71])})
-       typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[71])})
-       typs[74] = types.NewChan(typs[2], types.Crecv)
-       typs[75] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, nil)
-       typs[76] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
-       typs[77] = types.NewChan(typs[2], types.Csend)
-       typs[78] = functype(nil, []*Node{anonfield(typs[77]), anonfield(typs[3])}, nil)
-       typs[79] = types.NewArray(typs[0], 3)
-       typs[80] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[79]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
-       typs[81] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil)
-       typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
-       typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
-       typs[84] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
-       typs[85] = functype(nil, []*Node{anonfield(typs[77]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
-       typs[86] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[74])}, []*Node{anonfield(typs[11])})
-       typs[87] = types.NewPtr(typs[11])
-       typs[88] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[87]), anonfield(typs[74])}, []*Node{anonfield(typs[11])})
-       typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil)
-       typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[77]), anonfield(typs[3])}, nil)
-       typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[74]), anonfield(typs[3]), anonfield(typs[87])}, nil)
-       typs[92] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])})
-       typs[93] = types.NewSlice(typs[2])
-       typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[93])})
-       typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[93])})
-       typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[93]), anonfield(typs[32])}, []*Node{anonfield(typs[93])})
-       typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[49])}, nil)
-       typs[98] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[49])}, nil)
-       typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[49])}, []*Node{anonfield(typs[11])})
-       typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
-       typs[101] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
-       typs[102] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
-       typs[103] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
-       typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
-       typs[105] = types.Types[TUINT32]
-       typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[105])})
-       typs[107] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
-       typs[108] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
-       typs[109] = functype(nil, []*Node{anonfield(typs[105])}, []*Node{anonfield(typs[13])})
-       typs[110] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
-       typs[111] = functype(nil, []*Node{anonfield(typs[49])}, nil)
-       typs[112] = functype(nil, []*Node{anonfield(typs[49]), anonfield(typs[49])}, nil)
+       typs[34] = types.NewArray(typs[0], 4)
+       typs[35] = types.NewPtr(typs[34])
+       typs[36] = functype(nil, []*Node{anonfield(typs[35]), anonfield(typs[15])}, []*Node{anonfield(typs[21])})
+       typs[37] = types.NewSlice(typs[0])
+       typs[38] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[37])}, []*Node{anonfield(typs[21])})
+       typs[39] = functype(nil, []*Node{anonfield(typs[37])}, []*Node{anonfield(typs[21])})
+       typs[40] = types.Runetype
+       typs[41] = types.NewSlice(typs[40])
+       typs[42] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[41])}, []*Node{anonfield(typs[21])})
+       typs[43] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[21])}, []*Node{anonfield(typs[37])})
+       typs[44] = types.NewArray(typs[40], 32)
+       typs[45] = types.NewPtr(typs[44])
+       typs[46] = functype(nil, []*Node{anonfield(typs[45]), anonfield(typs[21])}, []*Node{anonfield(typs[41])})
+       typs[47] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[32])}, []*Node{anonfield(typs[40]), anonfield(typs[32])})
+       typs[48] = types.Types[TUINTPTR]
+       typs[49] = functype(nil, []*Node{anonfield(typs[2]), anonfield(typs[2]), anonfield(typs[48])}, []*Node{anonfield(typs[32])})
+       typs[50] = functype(nil, []*Node{anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
+       typs[51] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
+       typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
+       typs[53] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
+       typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
+       typs[55] = functype(nil, []*Node{anonfield(typs[1])}, nil)
+       typs[56] = types.NewPtr(typs[48])
+       typs[57] = types.Types[TUNSAFEPTR]
+       typs[58] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[57]), anonfield(typs[57])}, []*Node{anonfield(typs[11])})
+       typs[59] = types.NewMap(typs[2], typs[2])
+       typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[59])})
+       typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
+       typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
+       typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
+       typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
+       typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
+       typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
+       typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, nil)
+       typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, nil)
+       typs[69] = functype(nil, []*Node{anonfield(typs[3])}, nil)
+       typs[70] = types.NewChan(typs[2], types.Cboth)
+       typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[70])})
+       typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[70])})
+       typs[73] = types.NewChan(typs[2], types.Crecv)
+       typs[74] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, nil)
+       typs[75] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
+       typs[76] = types.NewChan(typs[2], types.Csend)
+       typs[77] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, nil)
+       typs[78] = types.NewArray(typs[0], 3)
+       typs[79] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[78]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
+       typs[80] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil)
+       typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
+       typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
+       typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
+       typs[84] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
+       typs[85] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[73])}, []*Node{anonfield(typs[11])})
+       typs[86] = types.NewPtr(typs[11])
+       typs[87] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[86]), anonfield(typs[73])}, []*Node{anonfield(typs[11])})
+       typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil)
+       typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[76]), anonfield(typs[3])}, nil)
+       typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[73]), anonfield(typs[3]), anonfield(typs[86])}, nil)
+       typs[91] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])})
+       typs[92] = types.NewSlice(typs[2])
+       typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[92])})
+       typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[92])})
+       typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[92]), anonfield(typs[32])}, []*Node{anonfield(typs[92])})
+       typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, nil)
+       typs[97] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[48])}, nil)
+       typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, []*Node{anonfield(typs[11])})
+       typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
+       typs[100] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
+       typs[101] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
+       typs[102] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
+       typs[103] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
+       typs[104] = types.Types[TUINT32]
+       typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[104])})
+       typs[106] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
+       typs[107] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
+       typs[108] = functype(nil, []*Node{anonfield(typs[104])}, []*Node{anonfield(typs[13])})
+       typs[109] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
+       typs[110] = functype(nil, []*Node{anonfield(typs[48])}, nil)
+       typs[111] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[48])}, nil)
        return typs[:]
 }
index f69459c5490a5026de4a65c5d92898a937363d84..6313b1a44c0dea2a7fc1062247cb7ceaddb55610 100644 (file)
@@ -48,7 +48,6 @@ func concatstring5(*[32]byte, string, string, string, string, string) string
 func concatstrings(*[32]byte, []string) string
 
 func cmpstring(string, string) int
-func eqstring(string, string) bool
 func intstring(*[4]byte, int64) string
 func slicebytetostring(*[32]byte, []byte) string
 func slicebytetostringtmp([]byte) string
index dea5893beae8f639bdfe2fc3f2474527c1ba42d7..3ed4bc3edd3f55f5a560a1fb0adc828a2ec84a90 100644 (file)
@@ -1369,18 +1369,27 @@ opswitch:
                        n.Left = cheapexpr(n.Left, init)
                        n.Right = cheapexpr(n.Right, init)
 
-                       r = mkcall("eqstring", types.Types[TBOOL], init, conv(n.Left, types.Types[TSTRING]), conv(n.Right, types.Types[TSTRING]))
-
-                       // quick check of len before full compare for == or !=
-                       // eqstring assumes that the lengths are equal
+                       lstr := conv(n.Left, types.Types[TSTRING])
+                       rstr := conv(n.Right, types.Types[TSTRING])
+                       lptr := nod(OSPTR, lstr, nil)
+                       rptr := nod(OSPTR, rstr, nil)
+                       llen := conv(nod(OLEN, lstr, nil), types.Types[TUINTPTR])
+                       rlen := conv(nod(OLEN, rstr, nil), types.Types[TUINTPTR])
+
+                       fn := syslook("memequal")
+                       fn = substArgTypes(fn, types.Types[TUINT8], types.Types[TUINT8])
+                       r = mkcall1(fn, types.Types[TBOOL], init, lptr, rptr, llen)
+
+                       // quick check of len before full compare for == or !=.
+                       // memequal then tests equality up to length len.
                        // TODO(marvin): Fix Node.EType type union.
                        if Op(n.Etype) == OEQ {
-                               // len(left) == len(right) && eqstring(left, right)
-                               r = nod(OANDAND, nod(OEQ, nod(OLEN, n.Left, nil), nod(OLEN, n.Right, nil)), r)
+                               // len(left) == len(right) && memequal(left, right, len)
+                               r = nod(OANDAND, nod(OEQ, llen, rlen), r)
                        } else {
-                               // len(left) != len(right) || !eqstring(left, right)
+                               // len(left) != len(right) || !memequal(left, right, len)
                                r = nod(ONOT, r, nil)
-                               r = nod(OOROR, nod(ONE, nod(OLEN, n.Left, nil), nod(OLEN, n.Right, nil)), r)
+                               r = nod(OOROR, nod(ONE, llen, rlen), r)
                        }
 
                        r = typecheck(r, Erv)
index e1c3267153e2d42eb9486077e261fd5bb51d5be3..76758686e52508fd6e9a2ffccae9144dc053bf86 100644 (file)
@@ -1306,23 +1306,6 @@ eq:
        MOVB    $1, ret+8(FP)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-17
-       MOVL    s1_base+0(FP), SI
-       MOVL    s2_base+8(FP), DI
-       CMPL    SI, DI
-       JEQ     same
-       MOVL    s1_len+4(FP), BX
-       LEAL    ret+16(FP), AX
-       JMP     runtime·memeqbody(SB)
-same:
-       MOVB    $1, ret+16(FP)
-       RET
-
 TEXT bytes·Equal(SB),NOSPLIT,$0-25
        MOVL    a_len+4(FP), BX
        MOVL    b_len+16(FP), CX
index dfa49de5445377869ee066123c5248590c187ae1..f99227679410aaf7438adbfc0475b5cc4ad2cd8f 100644 (file)
@@ -1326,23 +1326,6 @@ eq:
        MOVB    $1, ret+16(FP)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-33
-       MOVQ    s1_base+0(FP), SI
-       MOVQ    s2_base+16(FP), DI
-       CMPQ    SI, DI
-       JEQ     eq
-       MOVQ    s1_len+8(FP), BX
-       LEAQ    ret+32(FP), AX
-       JMP     runtime·memeqbody(SB)
-eq:
-       MOVB    $1, ret+32(FP)
-       RET
-
 // a in SI
 // b in DI
 // count in BX
index 1f70ab87f1fdd2091cc3edcc1f84cae27948ba7e..f9417196c594f174c97f98da0000b535324c43fb 100644 (file)
@@ -641,24 +641,6 @@ eq:
        MOVB    $1, ret+8(FP)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-17
-       MOVL    s1_base+0(FP), SI
-       MOVL    s2_base+8(FP), DI
-       CMPL    SI, DI
-       JEQ     same
-       MOVL    s1_len+4(FP), BX
-       CALL    runtime·memeqbody(SB)
-       MOVB    AX, ret+16(FP)
-       RET
-same:
-       MOVB    $1, ret+16(FP)
-       RET
-
 // a in SI
 // b in DI
 // count in BX
index 74761d445020de9aba275613c5133c8428b3bb44..79c5d43ec768a568eac552dc7f8017a4c16042dd 100644 (file)
@@ -813,31 +813,6 @@ samebytes:
        MOVW    R0, (R7)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
-       MOVW    s1_base+0(FP), R2
-       MOVW    s2_base+8(FP), R3
-       MOVW    $1, R8
-       MOVB    R8, ret+16(FP)
-       CMP     R2, R3
-       RET.EQ
-       MOVW    s1_len+4(FP), R0
-       ADD     R2, R0, R6
-loop:
-       CMP     R2, R6
-       RET.EQ
-       MOVBU.P 1(R2), R4
-       MOVBU.P 1(R3), R5
-       CMP     R4, R5
-       BEQ     loop
-       MOVW    $0, R8
-       MOVB    R8, ret+16(FP)
-       RET
-
 // TODO: share code with memequal?
 TEXT bytes·Equal(SB),NOSPLIT,$0-25
        MOVW    a_len+4(FP), R1
index 32c06d5c3735ee0c69e14893582841bf611a6c2e..4a68b4ab23f55f5d454d7e0e9d9ebf91a26614eb 100644 (file)
@@ -806,31 +806,6 @@ samebytes:
        MOVD    R4, (R7)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-33
-       MOVD    s1_base+0(FP), R0
-       MOVD    s1_len+8(FP), R1
-       MOVD    s2_base+16(FP), R2
-       ADD     R0, R1          // end
-loop:
-       CMP     R0, R1
-       BEQ     equal           // reaches the end
-       MOVBU.P 1(R0), R4
-       MOVBU.P 1(R2), R5
-       CMP     R4, R5
-       BEQ     loop
-notequal:
-       MOVB    ZR, ret+32(FP)
-       RET
-equal:
-       MOVD    $1, R0
-       MOVB    R0, ret+32(FP)
-       RET
-
 //
 // functions for other packages
 //
index 58ee58ed5b31a54f9c02254fdf8950fe80477834..338f6d4487812aa625cf43fff4bb54df73c6df6b 100644 (file)
@@ -679,31 +679,6 @@ eq:
        MOVB    R1, ret+16(FP)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-33
-       MOVV    s1_base+0(FP), R1
-       MOVV    s2_base+16(FP), R2
-       MOVV    $1, R3
-       MOVB    R3, ret+32(FP)
-       BNE     R1, R2, 2(PC)
-       RET
-       MOVV    s1_len+8(FP), R3
-       ADDV    R1, R3, R4
-loop:
-       BNE     R1, R4, 2(PC)
-       RET
-       MOVBU   (R1), R6
-       ADDV    $1, R1
-       MOVBU   (R2), R7
-       ADDV    $1, R2
-       BEQ     R6, R7, loop
-       MOVB    R0, ret+32(FP)
-       RET
-
 // TODO: share code with memequal?
 TEXT bytes·Equal(SB),NOSPLIT,$0-49
        MOVV    a_len+8(FP), R3
index 7a365419b049e80105cbe4ab7046861ce9860058..476e207bf934ed9c12220e352997d595970669c1 100644 (file)
@@ -695,31 +695,6 @@ eq:
        MOVB    R1, ret+8(FP)
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-17
-       MOVW    s1_base+0(FP), R1
-       MOVW    s2_base+8(FP), R2
-       MOVW    $1, R3
-       MOVBU   R3, ret+16(FP)
-       BNE     R1, R2, 2(PC)
-       RET
-       MOVW    s1_len+4(FP), R3
-       ADDU    R1, R3, R4
-loop:
-       BNE     R1, R4, 2(PC)
-       RET
-       MOVBU   (R1), R6
-       ADDU    $1, R1
-       MOVBU   (R2), R7
-       ADDU    $1, R2
-       BEQ     R6, R7, loop
-       MOVB    R0, ret+16(FP)
-       RET
-
 TEXT bytes·Equal(SB),NOSPLIT,$0-25
        MOVW    a_len+4(FP), R3
        MOVW    b_len+16(FP), R4
index 142ecdb2b1b07803602816540498ace8b7b76736..0251689b37dc704f7fe4eac95bdf2a619b8fc96d 100644 (file)
@@ -1057,24 +1057,6 @@ equal:
        MOVD    $1, R9
        RET
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT,$0-33
-       MOVD    s1_base+0(FP), R3
-       MOVD    s2_base+16(FP), R4
-       MOVD    $1, R5
-       MOVB    R5, ret+32(FP)
-       CMP     R3, R4
-       BNE     2(PC)
-       RET
-       MOVD    s1_len+8(FP), R5
-       BL      runtime·memeqbody(SB)
-       MOVB    R9, ret+32(FP)
-       RET
-
 TEXT bytes·Equal(SB),NOSPLIT,$0-49
        MOVD    a_len+8(FP), R4
        MOVD    b_len+32(FP), R5
index 757627d1ea522ddffefd709aeb7e17104fe712c1..bde4f0e5d991efa8f6a620f6bd548436c6d7a9b1 100644 (file)
@@ -704,18 +704,6 @@ TEXT runtime·memequal_varlen(SB),NOSPLIT|NOFRAME,$0-17
        LA      ret+16(FP), R7
        BR      runtime·memeqbody(SB)
 
-// eqstring tests whether two strings are equal.
-// The compiler guarantees that strings passed
-// to eqstring have equal length.
-// See runtime_test.go:eqstring_generic for
-// equivalent Go code.
-TEXT runtime·eqstring(SB),NOSPLIT|NOFRAME,$0-33
-       MOVD    s1_base+0(FP), R3
-       MOVD    s1_len+8(FP), R6
-       MOVD    s2_base+16(FP), R5
-       LA      ret+32(FP), R7
-       BR      runtime·memeqbody(SB)
-
 TEXT bytes·Equal(SB),NOSPLIT|NOFRAME,$0-49
        MOVD    a_len+8(FP), R2
        MOVD    b_len+32(FP), R6
index e9bc2567123ac265ea1e8395a389bcf398d35119..922cd830bcc3e59dd39fe08a5220ef66a58c18f7 100644 (file)
@@ -196,9 +196,9 @@ func eqstring_generic(s1, s2 string) bool {
 }
 
 func TestEqString(t *testing.T) {
-       // This isn't really an exhaustive test of eqstring, it's
+       // This isn't really an exhaustive test of == on strings, it's
        // just a convenient way of documenting (via eqstring_generic)
-       // what eqstring does.
+       // what == does.
        s := []string{
                "",
                "a",
@@ -213,7 +213,7 @@ func TestEqString(t *testing.T) {
                        x := s1 == s2
                        y := eqstring_generic(s1, s2)
                        if x != y {
-                               t.Errorf(`eqstring("%s","%s") = %t, want %t`, s1, s2, x, y)
+                               t.Errorf(`("%s" == "%s") = %t, want %t`, s1, s2, x, y)
                        }
                }
        }
index 1af704cb24a5eec60f1c78c45e58538dbeccbd61..19cddc9f65c239b2d3f184991a4cd1391661d5ea 100644 (file)
@@ -300,7 +300,6 @@ func round(n, a uintptr) uintptr {
 func checkASM() bool
 
 func memequal_varlen(a, b unsafe.Pointer) bool
-func eqstring(s1, s2 string) bool
 
 // bool2int returns 0 if x is false or 1 if x is true.
 func bool2int(x bool) int {