cmd/compile: unify reflect, string and slice copy runtime functions

Use a common runtime slicecopy function to copy strings or slices
into slices. This deduplicates similar code previously used in
reflect.slicecopy and runtime.stringslicecopy.

Change-Id: I09572ff0647a9e12bb5c6989689ce1c43f16b7f1
Reviewed-on: https://go-review.googlesource.com/c/go/+/254658
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index 861ffaa..da7b107 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -64,136 +64,135 @@
 	{"stringtoslicebyte", funcTag, 49},
 	{"stringtoslicerune", funcTag, 52},
 	{"slicecopy", funcTag, 53},
-	{"slicestringcopy", funcTag, 54},
-	{"decoderune", funcTag, 55},
-	{"countrunes", funcTag, 56},
-	{"convI2I", funcTag, 57},
-	{"convT16", funcTag, 58},
-	{"convT32", funcTag, 58},
-	{"convT64", funcTag, 58},
-	{"convTstring", funcTag, 58},
-	{"convTslice", funcTag, 58},
-	{"convT2E", funcTag, 59},
-	{"convT2Enoptr", funcTag, 59},
-	{"convT2I", funcTag, 59},
-	{"convT2Inoptr", funcTag, 59},
-	{"assertE2I", funcTag, 57},
-	{"assertE2I2", funcTag, 60},
-	{"assertI2I", funcTag, 57},
-	{"assertI2I2", funcTag, 60},
-	{"panicdottypeE", funcTag, 61},
-	{"panicdottypeI", funcTag, 61},
-	{"panicnildottype", funcTag, 62},
-	{"ifaceeq", funcTag, 64},
-	{"efaceeq", funcTag, 64},
-	{"fastrand", funcTag, 66},
-	{"makemap64", funcTag, 68},
-	{"makemap", funcTag, 69},
-	{"makemap_small", funcTag, 70},
-	{"mapaccess1", funcTag, 71},
-	{"mapaccess1_fast32", funcTag, 72},
-	{"mapaccess1_fast64", funcTag, 72},
-	{"mapaccess1_faststr", funcTag, 72},
-	{"mapaccess1_fat", funcTag, 73},
-	{"mapaccess2", funcTag, 74},
-	{"mapaccess2_fast32", funcTag, 75},
-	{"mapaccess2_fast64", funcTag, 75},
-	{"mapaccess2_faststr", funcTag, 75},
-	{"mapaccess2_fat", funcTag, 76},
-	{"mapassign", funcTag, 71},
-	{"mapassign_fast32", funcTag, 72},
-	{"mapassign_fast32ptr", funcTag, 72},
-	{"mapassign_fast64", funcTag, 72},
-	{"mapassign_fast64ptr", funcTag, 72},
-	{"mapassign_faststr", funcTag, 72},
-	{"mapiterinit", funcTag, 77},
-	{"mapdelete", funcTag, 77},
-	{"mapdelete_fast32", funcTag, 78},
-	{"mapdelete_fast64", funcTag, 78},
-	{"mapdelete_faststr", funcTag, 78},
-	{"mapiternext", funcTag, 79},
-	{"mapclear", funcTag, 80},
-	{"makechan64", funcTag, 82},
-	{"makechan", funcTag, 83},
-	{"chanrecv1", funcTag, 85},
-	{"chanrecv2", funcTag, 86},
-	{"chansend1", funcTag, 88},
+	{"decoderune", funcTag, 54},
+	{"countrunes", funcTag, 55},
+	{"convI2I", funcTag, 56},
+	{"convT16", funcTag, 57},
+	{"convT32", funcTag, 57},
+	{"convT64", funcTag, 57},
+	{"convTstring", funcTag, 57},
+	{"convTslice", funcTag, 57},
+	{"convT2E", funcTag, 58},
+	{"convT2Enoptr", funcTag, 58},
+	{"convT2I", funcTag, 58},
+	{"convT2Inoptr", funcTag, 58},
+	{"assertE2I", funcTag, 56},
+	{"assertE2I2", funcTag, 59},
+	{"assertI2I", funcTag, 56},
+	{"assertI2I2", funcTag, 59},
+	{"panicdottypeE", funcTag, 60},
+	{"panicdottypeI", funcTag, 60},
+	{"panicnildottype", funcTag, 61},
+	{"ifaceeq", funcTag, 63},
+	{"efaceeq", funcTag, 63},
+	{"fastrand", funcTag, 65},
+	{"makemap64", funcTag, 67},
+	{"makemap", funcTag, 68},
+	{"makemap_small", funcTag, 69},
+	{"mapaccess1", funcTag, 70},
+	{"mapaccess1_fast32", funcTag, 71},
+	{"mapaccess1_fast64", funcTag, 71},
+	{"mapaccess1_faststr", funcTag, 71},
+	{"mapaccess1_fat", funcTag, 72},
+	{"mapaccess2", funcTag, 73},
+	{"mapaccess2_fast32", funcTag, 74},
+	{"mapaccess2_fast64", funcTag, 74},
+	{"mapaccess2_faststr", funcTag, 74},
+	{"mapaccess2_fat", funcTag, 75},
+	{"mapassign", funcTag, 70},
+	{"mapassign_fast32", funcTag, 71},
+	{"mapassign_fast32ptr", funcTag, 71},
+	{"mapassign_fast64", funcTag, 71},
+	{"mapassign_fast64ptr", funcTag, 71},
+	{"mapassign_faststr", funcTag, 71},
+	{"mapiterinit", funcTag, 76},
+	{"mapdelete", funcTag, 76},
+	{"mapdelete_fast32", funcTag, 77},
+	{"mapdelete_fast64", funcTag, 77},
+	{"mapdelete_faststr", funcTag, 77},
+	{"mapiternext", funcTag, 78},
+	{"mapclear", funcTag, 79},
+	{"makechan64", funcTag, 81},
+	{"makechan", funcTag, 82},
+	{"chanrecv1", funcTag, 84},
+	{"chanrecv2", funcTag, 85},
+	{"chansend1", funcTag, 87},
 	{"closechan", funcTag, 30},
-	{"writeBarrier", varTag, 90},
-	{"typedmemmove", funcTag, 91},
-	{"typedmemclr", funcTag, 92},
-	{"typedslicecopy", funcTag, 93},
-	{"selectnbsend", funcTag, 94},
-	{"selectnbrecv", funcTag, 95},
-	{"selectnbrecv2", funcTag, 97},
-	{"selectsetpc", funcTag, 98},
-	{"selectgo", funcTag, 99},
+	{"writeBarrier", varTag, 89},
+	{"typedmemmove", funcTag, 90},
+	{"typedmemclr", funcTag, 91},
+	{"typedslicecopy", funcTag, 92},
+	{"selectnbsend", funcTag, 93},
+	{"selectnbrecv", funcTag, 94},
+	{"selectnbrecv2", funcTag, 96},
+	{"selectsetpc", funcTag, 97},
+	{"selectgo", funcTag, 98},
 	{"block", funcTag, 9},
-	{"makeslice", funcTag, 100},
-	{"makeslice64", funcTag, 101},
-	{"makeslicecopy", funcTag, 102},
-	{"growslice", funcTag, 104},
-	{"memmove", funcTag, 105},
-	{"memclrNoHeapPointers", funcTag, 106},
-	{"memclrHasPointers", funcTag, 106},
-	{"memequal", funcTag, 107},
-	{"memequal0", funcTag, 108},
-	{"memequal8", funcTag, 108},
-	{"memequal16", funcTag, 108},
-	{"memequal32", funcTag, 108},
-	{"memequal64", funcTag, 108},
-	{"memequal128", funcTag, 108},
-	{"f32equal", funcTag, 109},
-	{"f64equal", funcTag, 109},
-	{"c64equal", funcTag, 109},
-	{"c128equal", funcTag, 109},
-	{"strequal", funcTag, 109},
-	{"interequal", funcTag, 109},
-	{"nilinterequal", funcTag, 109},
-	{"memhash", funcTag, 110},
-	{"memhash0", funcTag, 111},
-	{"memhash8", funcTag, 111},
-	{"memhash16", funcTag, 111},
-	{"memhash32", funcTag, 111},
-	{"memhash64", funcTag, 111},
-	{"memhash128", funcTag, 111},
-	{"f32hash", funcTag, 111},
-	{"f64hash", funcTag, 111},
-	{"c64hash", funcTag, 111},
-	{"c128hash", funcTag, 111},
-	{"strhash", funcTag, 111},
-	{"interhash", funcTag, 111},
-	{"nilinterhash", funcTag, 111},
-	{"int64div", funcTag, 112},
-	{"uint64div", funcTag, 113},
-	{"int64mod", funcTag, 112},
-	{"uint64mod", funcTag, 113},
-	{"float64toint64", funcTag, 114},
-	{"float64touint64", funcTag, 115},
-	{"float64touint32", funcTag, 116},
-	{"int64tofloat64", funcTag, 117},
-	{"uint64tofloat64", funcTag, 118},
-	{"uint32tofloat64", funcTag, 119},
-	{"complex128div", funcTag, 120},
-	{"racefuncenter", funcTag, 121},
+	{"makeslice", funcTag, 99},
+	{"makeslice64", funcTag, 100},
+	{"makeslicecopy", funcTag, 101},
+	{"growslice", funcTag, 103},
+	{"memmove", funcTag, 104},
+	{"memclrNoHeapPointers", funcTag, 105},
+	{"memclrHasPointers", funcTag, 105},
+	{"memequal", funcTag, 106},
+	{"memequal0", funcTag, 107},
+	{"memequal8", funcTag, 107},
+	{"memequal16", funcTag, 107},
+	{"memequal32", funcTag, 107},
+	{"memequal64", funcTag, 107},
+	{"memequal128", funcTag, 107},
+	{"f32equal", funcTag, 108},
+	{"f64equal", funcTag, 108},
+	{"c64equal", funcTag, 108},
+	{"c128equal", funcTag, 108},
+	{"strequal", funcTag, 108},
+	{"interequal", funcTag, 108},
+	{"nilinterequal", funcTag, 108},
+	{"memhash", funcTag, 109},
+	{"memhash0", funcTag, 110},
+	{"memhash8", funcTag, 110},
+	{"memhash16", funcTag, 110},
+	{"memhash32", funcTag, 110},
+	{"memhash64", funcTag, 110},
+	{"memhash128", funcTag, 110},
+	{"f32hash", funcTag, 110},
+	{"f64hash", funcTag, 110},
+	{"c64hash", funcTag, 110},
+	{"c128hash", funcTag, 110},
+	{"strhash", funcTag, 110},
+	{"interhash", funcTag, 110},
+	{"nilinterhash", funcTag, 110},
+	{"int64div", funcTag, 111},
+	{"uint64div", funcTag, 112},
+	{"int64mod", funcTag, 111},
+	{"uint64mod", funcTag, 112},
+	{"float64toint64", funcTag, 113},
+	{"float64touint64", funcTag, 114},
+	{"float64touint32", funcTag, 115},
+	{"int64tofloat64", funcTag, 116},
+	{"uint64tofloat64", funcTag, 117},
+	{"uint32tofloat64", funcTag, 118},
+	{"complex128div", funcTag, 119},
+	{"racefuncenter", funcTag, 120},
 	{"racefuncenterfp", funcTag, 9},
 	{"racefuncexit", funcTag, 9},
-	{"raceread", funcTag, 121},
-	{"racewrite", funcTag, 121},
-	{"racereadrange", funcTag, 122},
-	{"racewriterange", funcTag, 122},
-	{"msanread", funcTag, 122},
-	{"msanwrite", funcTag, 122},
-	{"checkptrAlignment", funcTag, 123},
-	{"checkptrArithmetic", funcTag, 125},
-	{"libfuzzerTraceCmp1", funcTag, 127},
-	{"libfuzzerTraceCmp2", funcTag, 129},
-	{"libfuzzerTraceCmp4", funcTag, 130},
-	{"libfuzzerTraceCmp8", funcTag, 131},
-	{"libfuzzerTraceConstCmp1", funcTag, 127},
-	{"libfuzzerTraceConstCmp2", funcTag, 129},
-	{"libfuzzerTraceConstCmp4", funcTag, 130},
-	{"libfuzzerTraceConstCmp8", funcTag, 131},
+	{"raceread", funcTag, 120},
+	{"racewrite", funcTag, 120},
+	{"racereadrange", funcTag, 121},
+	{"racewriterange", funcTag, 121},
+	{"msanread", funcTag, 121},
+	{"msanwrite", funcTag, 121},
+	{"checkptrAlignment", funcTag, 122},
+	{"checkptrArithmetic", funcTag, 124},
+	{"libfuzzerTraceCmp1", funcTag, 126},
+	{"libfuzzerTraceCmp2", funcTag, 128},
+	{"libfuzzerTraceCmp4", funcTag, 129},
+	{"libfuzzerTraceCmp8", funcTag, 130},
+	{"libfuzzerTraceConstCmp1", funcTag, 126},
+	{"libfuzzerTraceConstCmp2", funcTag, 128},
+	{"libfuzzerTraceConstCmp4", funcTag, 129},
+	{"libfuzzerTraceConstCmp8", funcTag, 130},
 	{"x86HasPOPCNT", varTag, 6},
 	{"x86HasSSE41", varTag, 6},
 	{"x86HasFMA", varTag, 6},
@@ -202,7 +201,7 @@
 }
 
 func runtimeTypes() []*types.Type {
-	var typs [132]*types.Type
+	var typs [131]*types.Type
 	typs[0] = types.Bytetype
 	typs[1] = types.NewPtr(typs[0])
 	typs[2] = types.Types[TANY]
@@ -257,83 +256,82 @@
 	typs[51] = types.NewPtr(typs[50])
 	typs[52] = functype(nil, []*Node{anonfield(typs[51]), anonfield(typs[28])}, []*Node{anonfield(typs[46])})
 	typs[53] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*Node{anonfield(typs[15])})
-	typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[28])}, []*Node{anonfield(typs[15])})
-	typs[55] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[45]), anonfield(typs[15])})
-	typs[56] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])})
-	typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
-	typs[58] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])})
-	typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
-	typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])})
-	typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
-	typs[62] = functype(nil, []*Node{anonfield(typs[1])}, nil)
-	typs[63] = types.NewPtr(typs[5])
-	typs[64] = functype(nil, []*Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
-	typs[65] = types.Types[TUINT32]
-	typs[66] = functype(nil, nil, []*Node{anonfield(typs[65])})
-	typs[67] = types.NewMap(typs[2], typs[2])
-	typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[67])})
-	typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[67])})
-	typs[70] = functype(nil, nil, []*Node{anonfield(typs[67])})
-	typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
-	typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
-	typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
-	typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
-	typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
-	typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
-	typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil)
-	typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil)
-	typs[79] = functype(nil, []*Node{anonfield(typs[3])}, nil)
-	typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67])}, nil)
-	typs[81] = types.NewChan(typs[2], types.Cboth)
-	typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[81])})
-	typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[81])})
-	typs[84] = types.NewChan(typs[2], types.Crecv)
-	typs[85] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, nil)
-	typs[86] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
-	typs[87] = types.NewChan(typs[2], types.Csend)
-	typs[88] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, nil)
-	typs[89] = types.NewArray(typs[0], 3)
-	typs[90] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])})
-	typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
-	typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
-	typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
-	typs[94] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
-	typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[84])}, []*Node{anonfield(typs[6])})
-	typs[96] = types.NewPtr(typs[6])
-	typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*Node{anonfield(typs[6])})
-	typs[98] = functype(nil, []*Node{anonfield(typs[63])}, nil)
-	typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*Node{anonfield(typs[15]), anonfield(typs[6])})
-	typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])})
-	typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])})
-	typs[102] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])})
-	typs[103] = types.NewSlice(typs[2])
-	typs[104] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []*Node{anonfield(typs[103])})
-	typs[105] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil)
-	typs[106] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil)
-	typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])})
-	typs[108] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
-	typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
-	typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
-	typs[111] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
-	typs[112] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])})
-	typs[113] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])})
-	typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])})
-	typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])})
-	typs[116] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[65])})
-	typs[117] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])})
-	typs[118] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])})
-	typs[119] = functype(nil, []*Node{anonfield(typs[65])}, []*Node{anonfield(typs[20])})
-	typs[120] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])})
-	typs[121] = functype(nil, []*Node{anonfield(typs[5])}, nil)
-	typs[122] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil)
-	typs[123] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil)
-	typs[124] = types.NewSlice(typs[7])
-	typs[125] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[124])}, nil)
-	typs[126] = types.Types[TUINT8]
-	typs[127] = functype(nil, []*Node{anonfield(typs[126]), anonfield(typs[126])}, nil)
-	typs[128] = types.Types[TUINT16]
-	typs[129] = functype(nil, []*Node{anonfield(typs[128]), anonfield(typs[128])}, nil)
-	typs[130] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil)
-	typs[131] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil)
+	typs[54] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[45]), anonfield(typs[15])})
+	typs[55] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+	typs[56] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
+	typs[57] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])})
+	typs[58] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
+	typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])})
+	typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
+	typs[61] = functype(nil, []*Node{anonfield(typs[1])}, nil)
+	typs[62] = types.NewPtr(typs[5])
+	typs[63] = functype(nil, []*Node{anonfield(typs[62]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
+	typs[64] = types.Types[TUINT32]
+	typs[65] = functype(nil, nil, []*Node{anonfield(typs[64])})
+	typs[66] = types.NewMap(typs[2], typs[2])
+	typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[66])})
+	typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[66])})
+	typs[69] = functype(nil, nil, []*Node{anonfield(typs[66])})
+	typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
+	typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
+	typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
+	typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+	typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+	typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+	typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, nil)
+	typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, nil)
+	typs[78] = functype(nil, []*Node{anonfield(typs[3])}, nil)
+	typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66])}, nil)
+	typs[80] = types.NewChan(typs[2], types.Cboth)
+	typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[80])})
+	typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[80])})
+	typs[83] = types.NewChan(typs[2], types.Crecv)
+	typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil)
+	typs[85] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+	typs[86] = types.NewChan(typs[2], types.Csend)
+	typs[87] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, nil)
+	typs[88] = types.NewArray(typs[0], 3)
+	typs[89] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[88]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])})
+	typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
+	typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
+	typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
+	typs[93] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+	typs[94] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[83])}, []*Node{anonfield(typs[6])})
+	typs[95] = types.NewPtr(typs[6])
+	typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[95]), anonfield(typs[83])}, []*Node{anonfield(typs[6])})
+	typs[97] = functype(nil, []*Node{anonfield(typs[62])}, nil)
+	typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*Node{anonfield(typs[15]), anonfield(typs[6])})
+	typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])})
+	typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])})
+	typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])})
+	typs[102] = types.NewSlice(typs[2])
+	typs[103] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[102]), anonfield(typs[15])}, []*Node{anonfield(typs[102])})
+	typs[104] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil)
+	typs[105] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil)
+	typs[106] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])})
+	typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+	typs[108] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
+	typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
+	typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
+	typs[111] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])})
+	typs[112] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])})
+	typs[113] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])})
+	typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])})
+	typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[64])})
+	typs[116] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])})
+	typs[117] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])})
+	typs[118] = functype(nil, []*Node{anonfield(typs[64])}, []*Node{anonfield(typs[20])})
+	typs[119] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])})
+	typs[120] = functype(nil, []*Node{anonfield(typs[5])}, nil)
+	typs[121] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil)
+	typs[122] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil)
+	typs[123] = types.NewSlice(typs[7])
+	typs[124] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[123])}, nil)
+	typs[125] = types.Types[TUINT8]
+	typs[126] = functype(nil, []*Node{anonfield(typs[125]), anonfield(typs[125])}, nil)
+	typs[127] = types.Types[TUINT16]
+	typs[128] = functype(nil, []*Node{anonfield(typs[127]), anonfield(typs[127])}, nil)
+	typs[129] = functype(nil, []*Node{anonfield(typs[64]), anonfield(typs[64])}, nil)
+	typs[130] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil)
 	return typs[:]
 }
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index 635da80..02d6c7b7 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -75,8 +75,7 @@
 func slicerunetostring(*[32]byte, []rune) string
 func stringtoslicebyte(*[32]byte, string) []byte
 func stringtoslicerune(*[32]rune, string) []rune
-func slicecopy(toPtr *any, toLen int, frPtr *any, frLen int, wid uintptr) int
-func slicestringcopy(toPtr *byte, toLen int, fr string) int
+func slicecopy(toPtr *any, toLen int, fromPtr *any, fromLen int, wid uintptr) int
 
 func decoderune(string, int) (retv rune, retk int)
 func countrunes(string) int
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 5a5833d..8883e75 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -928,16 +928,20 @@
 	return false
 }
 
-// slicePtrLen extracts the pointer and length from a slice.
+// backingArrayPtrLen extracts the pointer and length from a slice or string.
 // This constructs two nodes referring to n, so n must be a cheapexpr.
-func (n *Node) slicePtrLen() (ptr, len *Node) {
+func (n *Node) backingArrayPtrLen() (ptr, len *Node) {
 	var init Nodes
 	c := cheapexpr(n, &init)
 	if c != n || init.Len() != 0 {
-		Fatalf("slicePtrLen not cheap: %v", n)
+		Fatalf("backingArrayPtrLen not cheap: %v", n)
 	}
 	ptr = nod(OSPTR, n, nil)
-	ptr.Type = n.Type.Elem().PtrTo()
+	if n.Type.IsString() {
+		ptr.Type = types.Types[TUINT8].PtrTo()
+	} else {
+		ptr.Type = n.Type.Elem().PtrTo()
+	}
 	len = nod(OLEN, n, nil)
 	len.Type = types.Types[TINT]
 	return ptr, len
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 2d29366..c3a740d 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1484,7 +1484,7 @@
 		} else {
 			// slicebytetostring(*[32]byte, ptr *byte, n int) string
 			n.Left = cheapexpr(n.Left, init)
-			ptr, len := n.Left.slicePtrLen()
+			ptr, len := n.Left.backingArrayPtrLen()
 			n = mkcall("slicebytetostring", n.Type, init, a, ptr, len)
 		}
 
@@ -1497,7 +1497,7 @@
 		}
 		// slicebytetostringtmp(ptr *byte, n int) string
 		n.Left = cheapexpr(n.Left, init)
-		ptr, len := n.Left.slicePtrLen()
+		ptr, len := n.Left.backingArrayPtrLen()
 		n = mkcall("slicebytetostringtmp", n.Type, init, ptr, len)
 
 	case OSTR2BYTES:
@@ -2764,36 +2764,25 @@
 		// instantiate typedslicecopy(typ *type, dstPtr *any, dstLen int, srcPtr *any, srcLen int) int
 		fn := syslook("typedslicecopy")
 		fn = substArgTypes(fn, l1.Type.Elem(), l2.Type.Elem())
-		ptr1, len1 := nptr1.slicePtrLen()
-		ptr2, len2 := nptr2.slicePtrLen()
+		ptr1, len1 := nptr1.backingArrayPtrLen()
+		ptr2, len2 := nptr2.backingArrayPtrLen()
 		ncopy = mkcall1(fn, types.Types[TINT], &nodes, typename(elemtype), ptr1, len1, ptr2, len2)
-
 	} else if instrumenting && !compiling_runtime {
-		// rely on runtime to instrument copy.
-		// copy(s[len(l1):], l2)
+		// rely on runtime to instrument:
+		//  copy(s[len(l1):], l2)
+		// l2 can be a slice or string.
 		nptr1 := nod(OSLICE, s, nil)
 		nptr1.Type = s.Type
 		nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
 		nptr1 = cheapexpr(nptr1, &nodes)
-
 		nptr2 := l2
 
-		if l2.Type.IsString() {
-			// instantiate func slicestringcopy(toPtr *byte, toLen int, fr string) int
-			fn := syslook("slicestringcopy")
-			ptr, len := nptr1.slicePtrLen()
-			str := nod(OCONVNOP, nptr2, nil)
-			str.Type = types.Types[TSTRING]
-			ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr, len, str)
-		} else {
-			// instantiate func slicecopy(to any, fr any, wid uintptr) int
-			fn := syslook("slicecopy")
-			fn = substArgTypes(fn, l1.Type.Elem(), l2.Type.Elem())
-			ptr1, len1 := nptr1.slicePtrLen()
-			ptr2, len2 := nptr2.slicePtrLen()
-			ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr1, len1, ptr2, len2, nodintconst(elemtype.Width))
-		}
+		ptr1, len1 := nptr1.backingArrayPtrLen()
+		ptr2, len2 := nptr2.backingArrayPtrLen()
 
+		fn := syslook("slicecopy")
+		fn = substArgTypes(fn, ptr1.Type.Elem(), ptr2.Type.Elem())
+		ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr1, len1, ptr2, len2, nodintconst(elemtype.Width))
 	} else {
 		// memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
 		nptr1 := nod(OINDEX, s, nod(OLEN, l1, nil))
@@ -3092,28 +3081,25 @@
 		Curfn.Func.setWBPos(n.Pos)
 		fn := writebarrierfn("typedslicecopy", n.Left.Type.Elem(), n.Right.Type.Elem())
 		n.Left = cheapexpr(n.Left, init)
-		ptrL, lenL := n.Left.slicePtrLen()
+		ptrL, lenL := n.Left.backingArrayPtrLen()
 		n.Right = cheapexpr(n.Right, init)
-		ptrR, lenR := n.Right.slicePtrLen()
+		ptrR, lenR := n.Right.backingArrayPtrLen()
 		return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), ptrL, lenL, ptrR, lenR)
 	}
 
 	if runtimecall {
-		if n.Right.Type.IsString() {
-			fn := syslook("slicestringcopy")
-			n.Left = cheapexpr(n.Left, init)
-			ptr, len := n.Left.slicePtrLen()
-			str := nod(OCONVNOP, n.Right, nil)
-			str.Type = types.Types[TSTRING]
-			return mkcall1(fn, n.Type, init, ptr, len, str)
-		}
+		// rely on runtime to instrument:
+		//  copy(n.Left, n.Right)
+		// n.Right can be a slice or string.
+
+		n.Left = cheapexpr(n.Left, init)
+		ptrL, lenL := n.Left.backingArrayPtrLen()
+		n.Right = cheapexpr(n.Right, init)
+		ptrR, lenR := n.Right.backingArrayPtrLen()
 
 		fn := syslook("slicecopy")
-		fn = substArgTypes(fn, n.Left.Type.Elem(), n.Right.Type.Elem())
-		n.Left = cheapexpr(n.Left, init)
-		ptrL, lenL := n.Left.slicePtrLen()
-		n.Right = cheapexpr(n.Right, init)
-		ptrR, lenR := n.Right.slicePtrLen()
+		fn = substArgTypes(fn, ptrL.Type.Elem(), ptrR.Type.Elem())
+
 		return mkcall1(fn, n.Type, init, ptrL, lenL, ptrR, lenR, nodintconst(n.Left.Type.Elem().Width))
 	}
 
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index f7875d3..2b5affc 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -281,28 +281,7 @@
 //go:linkname reflect_typedslicecopy reflect.typedslicecopy
 func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
 	if elemType.ptrdata == 0 {
-		n := dst.len
-		if n > src.len {
-			n = src.len
-		}
-		if n == 0 {
-			return 0
-		}
-
-		size := uintptr(n) * elemType.size
-		if raceenabled {
-			callerpc := getcallerpc()
-			pc := funcPC(reflect_typedslicecopy)
-			racewriterangepc(dst.array, size, callerpc, pc)
-			racereadrangepc(src.array, size, callerpc, pc)
-		}
-		if msanenabled {
-			msanwrite(dst.array, size)
-			msanread(src.array, size)
-		}
-
-		memmove(dst.array, src.array, size)
-		return n
+		return slicecopy(dst.array, dst.len, src.array, src.len, elemType.size)
 	}
 	return typedslicecopy(elemType, dst.array, dst.len, src.array, src.len)
 }
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index 0418ace..82a45c7 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -243,12 +243,13 @@
 	return x&(x-1) == 0
 }
 
-func slicecopy(toPtr unsafe.Pointer, toLen int, fmPtr unsafe.Pointer, fmLen int, width uintptr) int {
-	if fmLen == 0 || toLen == 0 {
+// slicecopy is used to copy from a string or slice of pointerless elements into a slice.
+func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen int, width uintptr) int {
+	if fromLen == 0 || toLen == 0 {
 		return 0
 	}
 
-	n := fmLen
+	n := fromLen
 	if toLen < n {
 		n = toLen
 	}
@@ -257,46 +258,23 @@
 		return n
 	}
 
+	size := uintptr(n) * width
 	if raceenabled {
 		callerpc := getcallerpc()
 		pc := funcPC(slicecopy)
-		racereadrangepc(fmPtr, uintptr(n*int(width)), callerpc, pc)
-		racewriterangepc(toPtr, uintptr(n*int(width)), callerpc, pc)
+		racereadrangepc(fromPtr, size, callerpc, pc)
+		racewriterangepc(toPtr, size, callerpc, pc)
 	}
 	if msanenabled {
-		msanread(fmPtr, uintptr(n*int(width)))
-		msanwrite(toPtr, uintptr(n*int(width)))
+		msanread(fromPtr, size)
+		msanwrite(toPtr, size)
 	}
 
-	size := uintptr(n) * width
 	if size == 1 { // common case worth about 2x to do here
 		// TODO: is this still worth it with new memmove impl?
-		*(*byte)(toPtr) = *(*byte)(fmPtr) // known to be a byte pointer
+		*(*byte)(toPtr) = *(*byte)(fromPtr) // known to be a byte pointer
 	} else {
-		memmove(toPtr, fmPtr, size)
+		memmove(toPtr, fromPtr, size)
 	}
 	return n
 }
-
-func slicestringcopy(toPtr *byte, toLen int, fm string) int {
-	if len(fm) == 0 || toLen == 0 {
-		return 0
-	}
-
-	n := len(fm)
-	if toLen < n {
-		n = toLen
-	}
-
-	if raceenabled {
-		callerpc := getcallerpc()
-		pc := funcPC(slicestringcopy)
-		racewriterangepc(unsafe.Pointer(toPtr), uintptr(n), callerpc, pc)
-	}
-	if msanenabled {
-		msanwrite(unsafe.Pointer(toPtr), uintptr(n))
-	}
-
-	memmove(unsafe.Pointer(toPtr), stringStructOf(&fm).str, uintptr(n))
-	return n
-}