diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index e7931387aa6..ef7294d8054 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -183,6 +183,29 @@ func IndexAny(s []byte, chars string) int { // Avoid scanning all of s. return -1 } + if len(s) == 1 { + r := rune(s[0]) + if r >= utf8.RuneSelf { + // search utf8.RuneError. + for _, r = range chars { + if r == utf8.RuneError { + return 0 + } + } + return -1 + } + if bytealg.IndexByteString(chars, s[0]) >= 0 { + return 0 + } + return -1 + } + if len(chars) == 1 { + r := rune(chars[0]) + if r >= utf8.RuneSelf { + r = utf8.RuneError + } + return IndexRune(s, r) + } if len(s) > 8 { if as, isASCII := makeASCIISet(chars); isASCII { for i, c := range s { @@ -197,14 +220,26 @@ func IndexAny(s []byte, chars string) int { for i := 0; i < len(s); i += width { r := rune(s[i]) if r < utf8.RuneSelf { - width = 1 - } else { - r, width = utf8.DecodeRune(s[i:]) - } - for _, ch := range chars { - if r == ch { + if bytealg.IndexByteString(chars, s[i]) >= 0 { return i } + width = 1 + continue + } + r, width = utf8.DecodeRune(s[i:]) + if r == utf8.RuneError { + for _, r = range chars { + if r == utf8.RuneError { + return i + } + } + continue + } + // r is 2 to 4 bytes. Using strings.Index is more reasonable, but as the bytes + // package should not import the strings package, use bytealg.IndexString + // instead. And this does not seem to lose much performance. + if chars == string(r) || bytealg.IndexString(chars, string(r)) >= 0 { + return i } } return -1 @@ -229,14 +264,60 @@ func LastIndexAny(s []byte, chars string) int { return -1 } } - for i := len(s); i > 0; { - r, size := utf8.DecodeLastRune(s[:i]) - i -= size - for _, c := range chars { - if r == c { + if len(s) == 1 { + r := rune(s[0]) + if r >= utf8.RuneSelf { + for _, r = range chars { + if r == utf8.RuneError { + return 0 + } + } + return -1 + } + if bytealg.IndexByteString(chars, s[0]) >= 0 { + return 0 + } + return -1 + } + if len(chars) == 1 { + cr := rune(chars[0]) + if cr >= utf8.RuneSelf { + cr = utf8.RuneError + } + for i := len(s); i > 0; { + r, size := utf8.DecodeLastRune(s[:i]) + i -= size + if r == cr { return i } } + return -1 + } + for i := len(s); i > 0; { + r := rune(s[i-1]) + if r < utf8.RuneSelf { + if bytealg.IndexByteString(chars, s[i-1]) >= 0 { + return i - 1 + } + i-- + continue + } + r, size := utf8.DecodeLastRune(s[:i]) + i -= size + if r == utf8.RuneError { + for _, r = range chars { + if r == utf8.RuneError { + return i + } + } + continue + } + // r is 2 to 4 bytes. Using strings.Index is more reasonable, but as the bytes + // package should not import the strings package, use bytealg.IndexString + // instead. And this does not seem to lose much performance. + if chars == string(r) || bytealg.IndexString(chars, string(r)) >= 0 { + return i + } } return -1 } diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index a208d4ed763..544ee46f908 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -169,6 +169,7 @@ var indexAnyTests = []BinOpTest{ {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, + {"\x80", "\xffb", 0}, {"aaa", "a", 0}, {"abc", "xyz", -1}, {"abc", "xcz", 2}, @@ -179,6 +180,7 @@ var indexAnyTests = []BinOpTest{ {dots + dots + dots, " ", -1}, {"012abcba210", "\xffb", 4}, {"012\x80bcb\x80210", "\xffb", 3}, + {"0123456\xcf\x80abc", "\xcfb\x80", 10}, } var lastIndexAnyTests = []BinOpTest{ @@ -187,6 +189,7 @@ var lastIndexAnyTests = []BinOpTest{ {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, + {"\x80", "\xffb", 0}, {"aaa", "a", 2}, {"abc", "xyz", -1}, {"abc", "ab", 1}, @@ -197,6 +200,7 @@ var lastIndexAnyTests = []BinOpTest{ {dots + dots + dots, " ", -1}, {"012abcba210", "\xffb", 6}, {"012\x80bcb\x80210", "\xffb", 7}, + {"0123456\xcf\x80abc", "\xcfb\x80", 10}, } // Execute f on each test case. funcName should be the name of f; it's used @@ -1890,10 +1894,10 @@ func BenchmarkBytesCompare(b *testing.B) { } func BenchmarkIndexAnyASCII(b *testing.B) { - x := Repeat([]byte{'#'}, 4096) // Never matches set - cs := "0123456789abcdef" - for k := 1; k <= 4096; k <<= 4 { - for j := 1; j <= 16; j <<= 1 { + x := Repeat([]byte{'#'}, 2048) // Never matches set + cs := "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { for i := 0; i < b.N; i++ { IndexAny(x[:k], cs[:j]) @@ -1903,6 +1907,48 @@ func BenchmarkIndexAnyASCII(b *testing.B) { } } +func BenchmarkIndexAnyUTF8(b *testing.B) { + x := Repeat([]byte{'#'}, 2048) // Never matches set + cs := "你好世界, hello world. 你好世界, hello world. 你好世界, hello world." + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { + b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { + for i := 0; i < b.N; i++ { + IndexAny(x[:k], cs[:j]) + } + }) + } + } +} + +func BenchmarkLastIndexAnyASCII(b *testing.B) { + x := Repeat([]byte{'#'}, 2048) // Never matches set + cs := "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { + b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { + for i := 0; i < b.N; i++ { + LastIndexAny(x[:k], cs[:j]) + } + }) + } + } +} + +func BenchmarkLastIndexAnyUTF8(b *testing.B) { + x := Repeat([]byte{'#'}, 2048) // Never matches set + cs := "你好世界, hello world. 你好世界, hello world. 你好世界, hello world." + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { + b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { + for i := 0; i < b.N; i++ { + LastIndexAny(x[:k], cs[:j]) + } + }) + } + } +} + func BenchmarkTrimASCII(b *testing.B) { cs := "0123456789abcdef" for k := 1; k <= 4096; k <<= 4 { diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index 958119a368e..6ac2b002f89 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -1064,7 +1064,7 @@ label1: // VSX AND, XX3-form // XA,XB,XT produces // XT,XA,XB - XXLANDQ VS0,VS1,VS32 + XXLAND VS0,VS1,VS32 XXLANDC VS0,VS1,VS32 XXLEQV VS0,VS1,VS32 XXLNAND VS0,VS1,VS32 @@ -1093,6 +1093,11 @@ label1: // XT,XB,UIM XXSPLTW VS0,$3,VS32 +// VSX permute, XX3-form +// XA,XB,XT produces +// XT,XA,XB + XXPERM VS0,VS1,VS32 + // VSX permute, XX3-form // XA,XB,DM,XT produces // XT,XA,XB,DM diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index e32a3a607bb..6b40a255d50 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -22,6 +22,7 @@ import ( "regexp" "sort" "strings" + "unicode" ) var ( @@ -802,6 +803,28 @@ func (p *Package) packedAttribute() string { return s + "))" } +// exportParamName returns the value of param as it should be +// displayed in a c header file. If param contains any non-ASCII +// characters, this function will return the character p followed by +// the value of position; otherwise, this function will return the +// value of param. +func exportParamName(param string, position int) string { + if param == "" { + return fmt.Sprintf("p%d", position) + } + + pname := param + + for i := 0; i < len(param); i++ { + if param[i] > unicode.MaxASCII { + pname = fmt.Sprintf("p%d", position) + break + } + } + + return pname +} + // Write out the various stubs we need to support functions exported // from Go so that they are callable from C. func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { @@ -915,42 +938,45 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { if i > 0 || fn.Recv != nil { s += ", " } - s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i) + s += fmt.Sprintf("%s %s", p.cgoType(atype).C, exportParamName(aname, i)) }) s += ")" if len(exp.Doc) > 0 { fmt.Fprintf(fgcch, "\n%s", exp.Doc) + if !strings.HasSuffix(exp.Doc, "\n") { + fmt.Fprint(fgcch, "\n") + } } - fmt.Fprintf(fgcch, "\nextern %s;\n", s) + fmt.Fprintf(fgcch, "extern %s;\n", s) fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName) fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD") fmt.Fprintf(fgcc, "\n%s\n", s) fmt.Fprintf(fgcc, "{\n") fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n") - fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute()) + fmt.Fprintf(fgcc, "\t%s %v _cgo_a;\n", ctype, p.packedAttribute()) if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) } if fn.Recv != nil { - fmt.Fprintf(fgcc, "\ta.recv = recv;\n") + fmt.Fprintf(fgcc, "\t_cgo_a.recv = recv;\n") } forFieldList(fntype.Params, func(i int, aname string, atype ast.Expr) { - fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i) + fmt.Fprintf(fgcc, "\t_cgo_a.p%d = %s;\n", i, exportParamName(aname, i)) }) fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n") - fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off) + fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &_cgo_a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off) fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") fmt.Fprintf(fgcc, "\t_cgo_release_context(_cgo_ctxt);\n") if gccResult != "void" { if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { - fmt.Fprintf(fgcc, "\treturn a.r0;\n") + fmt.Fprintf(fgcc, "\treturn _cgo_a.r0;\n") } else { forFieldList(fntype.Results, func(i int, aname string, atype ast.Expr) { - fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i) + fmt.Fprintf(fgcc, "\tr.r%d = _cgo_a.r%d;\n", i, i) }) fmt.Fprintf(fgcc, "\treturn r;\n") } diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go index 5b437d6804c..11d48154ad2 100644 --- a/src/cmd/compile/doc.go +++ b/src/cmd/compile/doc.go @@ -77,8 +77,6 @@ Flags: -lang version Set language version to compile, as in -lang=go1.12. Default is current version. - -largemodel - Generate code that assumes a large memory model. -linkobj file Write linker-specific object to file and compiler-specific object to usual output file (as specified by -o). diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index 4759b604120..c83badaa86e 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -186,6 +186,7 @@ func algtype1(t *types.Type) (AlgKind, *types.Type) { // genhash returns a symbol which is the closure used to compute // the hash of a value of type t. +// Note: the generated function must match runtime.typehash exactly. func genhash(t *types.Type) *obj.LSym { switch algtype(t) { default: diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 5e5b32bc4a2..fe73df9d574 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -673,10 +673,6 @@ func evconst(n *Node) { } case OCOMPLEX: - if nl == nil || nr == nil { - // TODO(mdempsky): Remove after early OAS2FUNC rewrite CL lands. - break - } if nl.Op == OLITERAL && nr.Op == OLITERAL { // make it a complex literal c := newMpcmplx() diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 76c91ba2d2f..8edaf54a75a 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1371,7 +1371,7 @@ func (e *Escape) finish(fns []*Node) { fn.Esc = EscFuncTagged narg := 0 - for _, fs := range types.RecvsParams { + for _, fs := range &types.RecvsParams { for _, f := range fs(fn.Type).Fields().Slice() { narg++ f.Note = e.paramTag(fn, narg, f) diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index d7fc5416e21..80726d05575 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -585,28 +585,44 @@ s%^ ........*\]%&~%g s%~ %%g */ -func symfmt(s *types.Sym, flag FmtFlag, mode fmtMode) string { +func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode fmtMode) { if s.Pkg != nil && flag&FmtShort == 0 { switch mode { case FErr: // This is for the user if s.Pkg == builtinpkg || s.Pkg == localpkg { - return s.Name + b.WriteString(s.Name) + return } // If the name was used by multiple packages, display the full path, if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 { - return fmt.Sprintf("%q.%s", s.Pkg.Path, s.Name) + fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name) + return } - return s.Pkg.Name + "." + s.Name + b.WriteString(s.Pkg.Name) + b.WriteByte('.') + b.WriteString(s.Name) + return case FDbg: - return s.Pkg.Name + "." + s.Name + b.WriteString(s.Pkg.Name) + b.WriteByte('.') + b.WriteString(s.Name) + return case FTypeIdName: - return s.Pkg.Name + "." + s.Name // dcommontype, typehash + // dcommontype, typehash + b.WriteString(s.Pkg.Name) + b.WriteByte('.') + b.WriteString(s.Name) + return case FTypeId: - return s.Pkg.Prefix + "." + s.Name // (methodsym), typesym, weaksym + // (methodsym), typesym, weaksym + b.WriteString(s.Pkg.Prefix) + b.WriteByte('.') + b.WriteString(s.Name) + return } } @@ -619,13 +635,15 @@ func symfmt(s *types.Sym, flag FmtFlag, mode fmtMode) string { } if mode == FDbg { - return fmt.Sprintf("@%q.%s", s.Pkg.Path, name) + fmt.Fprintf(b, "@%q.%s", s.Pkg.Path, name) + return } - return name + b.WriteString(name) + return } - return s.Name + b.WriteString(s.Name) } var basicnames = []string{ @@ -652,16 +670,16 @@ var basicnames = []string{ TBLANK: "blank", } -var tconvBufferPool = sync.Pool{ +var fmtBufferPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } func tconv(t *types.Type, flag FmtFlag, mode fmtMode) string { - buf := tconvBufferPool.Get().(*bytes.Buffer) + buf := fmtBufferPool.Get().(*bytes.Buffer) buf.Reset() - defer tconvBufferPool.Put(buf) + defer fmtBufferPool.Put(buf) tconv2(buf, t, flag, mode, nil) return types.InternString(buf.Bytes()) @@ -703,7 +721,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited case FTypeIdName, FTypeId: t = types.Types[t.Etype] default: - b.WriteString(sconv(t.Sym, FmtShort, mode)) + sconv2(b, t.Sym, FmtShort, mode) return } } @@ -718,15 +736,16 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited case FTypeId, FTypeIdName: if flag&FmtShort != 0 { if t.Vargen != 0 { - fmt.Fprintf(b, "%s·%d", sconv(t.Sym, FmtShort, mode), t.Vargen) + sconv2(b, t.Sym, FmtShort, mode) + fmt.Fprintf(b, "·%d", t.Vargen) return } - b.WriteString(sconv(t.Sym, FmtShort, mode)) + sconv2(b, t.Sym, FmtShort, mode) return } if mode == FTypeIdName { - b.WriteString(sconv(t.Sym, FmtUnsigned, mode)) + sconv2(b, t.Sym, FmtUnsigned, mode) return } @@ -736,7 +755,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited } } - b.WriteString(smodeString(t.Sym, mode)) + sconv2(b, t.Sym, 0, mode) return } @@ -845,13 +864,13 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited // Wrong interface definitions may have types lacking a symbol. break case types.IsExported(f.Sym.Name): - b.WriteString(sconv(f.Sym, FmtShort, mode)) + sconv2(b, f.Sym, FmtShort, mode) default: flag1 := FmtLeft if flag&FmtUnsigned != 0 { flag1 = FmtUnsigned } - b.WriteString(sconv(f.Sym, flag1, mode)) + sconv2(b, f.Sym, flag1, mode) } tconv2(b, f.Type, FmtShort, mode, visited) } @@ -941,7 +960,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited b.WriteString("undefined") if t.Sym != nil { b.WriteByte(' ') - b.WriteString(smodeString(t.Sym, mode)) + sconv2(b, t.Sym, 0, mode) } case TUNSAFEPTR: @@ -1731,9 +1750,30 @@ func sconv(s *types.Sym, flag FmtFlag, mode fmtMode) string { if s.Name == "_" { return "_" } + buf := fmtBufferPool.Get().(*bytes.Buffer) + buf.Reset() + defer fmtBufferPool.Put(buf) flag, mode = flag.update(mode) - return symfmt(s, flag, mode) + symfmt(buf, s, flag, mode) + return types.InternString(buf.Bytes()) +} + +func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode fmtMode) { + if flag&FmtLong != 0 { + panic("linksymfmt") + } + if s == nil { + b.WriteString("") + return + } + if s.Name == "_" { + b.WriteString("_") + return + } + + flag, mode = flag.update(mode) + symfmt(b, s, flag, mode) } func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode fmtMode, visited map[*types.Type]int, funarg types.Funarg) { diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 7d2fa3f675f..a3baa24bbdc 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -954,7 +954,7 @@ func (w *exportWriter) funcExt(n *Node) { w.symIdx(n.Sym) // Escape analysis. - for _, fs := range types.RecvsParams { + for _, fs := range &types.RecvsParams { for _, f := range fs(n.Type).FieldSlice() { w.string(f.Note) } diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index a9d29f121ea..dfcaa56f8ac 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -660,7 +660,7 @@ func (r *importReader) funcExt(n *Node) { r.symIdx(n.Sym) // Escape analysis. - for _, fs := range types.RecvsParams { + for _, fs := range &types.RecvsParams { for _, f := range fs(n.Type).FieldSlice() { f.Note = r.string() } diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 9b89d7b8b1f..745973e9380 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -1070,7 +1070,7 @@ func loadsys() { typecheckok = true typs := runtimeTypes() - for _, d := range runtimeDecls { + for _, d := range &runtimeDecls { sym := Runtimepkg.Lookup(d.name) typ := typs[d.typ] switch d.tag { @@ -1373,7 +1373,7 @@ var concurrentFlagOK = [256]bool{ } func concurrentBackendAllowed() bool { - for i, x := range Debug { + for i, x := range &Debug { if x != 0 && !concurrentFlagOK[i] { return false } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index b6713ba6859..b956a7d13c6 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -646,7 +646,7 @@ func (p *noder) expr(expr syntax.Expr) *Node { } n := p.nod(expr, op, p.expr(expr.X), nil) var index [3]*Node - for i, x := range expr.Index { + for i, x := range &expr.Index { if x != nil { index[i] = p.expr(x) } diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index b3262018b4a..845b2bd724f 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -419,7 +419,7 @@ func (lv *Liveness) regEffects(v *ssa.Value) (uevar, kill liveRegMask) { if v.Type.Etype != types.TTUPLE { v.Fatalf("location pair %s has non-tuple type %v", loc, v.Type) } - for i, loc1 := range loc { + for i, loc1 := range &loc { if loc1 == nil { continue } @@ -705,12 +705,6 @@ func (lv *Liveness) markUnsafePoints() { v = v.Args[0] continue } - case ssa.OpRISCV64SUBW: - // RISCV64 lowers Neq32 to include a SUBW with multiple arguments. - // TODO(jsing): it would be preferable not to use Neq32 for - // writeBuffer.enabled checks on this platform. - v = v.Args[0] - continue case ssa.Op386MOVLload, ssa.OpARM64MOVWUload, ssa.OpPPC64MOVWZload, ssa.OpWasmI64Load32U: // Args[0] is the address of the write // barrier control. Ignore Args[1], diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 34adeabae1f..ddd40010e56 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3216,7 +3216,7 @@ func init() { var p4 []*sys.Arch var p8 []*sys.Arch var lwatomics []*sys.Arch - for _, a := range sys.Archs { + for _, a := range &sys.Archs { all = append(all, a) if a.PtrSize == 4 { p4 = append(p4, a) diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 9f4e4d96802..d1072997f19 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -66,7 +66,7 @@ var builtinFuncs = [...]struct { // isBuiltinFuncName reports whether name matches a builtin function // name. func isBuiltinFuncName(name string) bool { - for _, fn := range builtinFuncs { + for _, fn := range &builtinFuncs { if fn.name == name { return true } @@ -92,7 +92,7 @@ func initUniverse() { // lexinit initializes known symbols and the basic types. func lexinit() { - for _, s := range basicTypes { + for _, s := range &basicTypes { etype := s.etype if int(etype) >= len(types.Types) { Fatalf("lexinit: %s bad etype", s.name) @@ -111,13 +111,13 @@ func lexinit() { asNode(s2.Def).Name = new(Name) } - for _, s := range builtinFuncs { + for _, s := range &builtinFuncs { s2 := builtinpkg.Lookup(s.name) s2.Def = asTypesNode(newname(s2)) asNode(s2.Def).SetSubOp(s.op) } - for _, s := range unsafeFuncs { + for _, s := range &unsafeFuncs { s2 := unsafepkg.Lookup(s.name) s2.Def = asTypesNode(newname(s2)) asNode(s2.Def).SetSubOp(s.op) @@ -402,7 +402,7 @@ func lexinit1() { dowidth(types.Runetype) // backend-dependent builtin types (e.g. int). - for _, s := range typedefs { + for _, s := range &typedefs { s1 := builtinpkg.Lookup(s.name) sameas := s.sameas32 diff --git a/src/cmd/compile/internal/logopt/log_opts.go b/src/cmd/compile/internal/logopt/log_opts.go index 2639d271055..49cb9cf57f3 100644 --- a/src/cmd/compile/internal/logopt/log_opts.go +++ b/src/cmd/compile/internal/logopt/log_opts.go @@ -390,7 +390,7 @@ func FlushLoggedOpts(ctxt *obj.Link, slashPkgPath string) { var w io.WriteCloser if slashPkgPath == "" { - slashPkgPath = string(0) + slashPkgPath = "\000" } subdirpath := filepath.Join(dest, pathEscape(slashPkgPath)) err := os.MkdirAll(subdirpath, 0755) diff --git a/src/cmd/compile/internal/ssa/addressingmodes.go b/src/cmd/compile/internal/ssa/addressingmodes.go new file mode 100644 index 00000000000..2af8a4d1fc1 --- /dev/null +++ b/src/cmd/compile/internal/ssa/addressingmodes.go @@ -0,0 +1,225 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssa + +// addressingModes combines address calculations into memory operations +// that can perform complicated addressing modes. +func addressingModes(f *Func) { + switch f.Config.arch { + default: + // Most architectures can't do this. + return + case "amd64", "386": + // TODO: s390x? + } + + var tmp []*Value + for _, b := range f.Blocks { + for _, v := range b.Values { + if !combineFirst[v.Op] { + continue + } + // All matched operations have the pointer in arg[0]. + // All results have the pointer in arg[0] and the index in arg[1]. + // *Except* for operations which update a register, + // which are marked with resultInArg0. Those have + // the pointer in arg[1], and the corresponding result op + // has the pointer in arg[1] and the index in arg[2]. + ptrIndex := 0 + if opcodeTable[v.Op].resultInArg0 { + ptrIndex = 1 + } + p := v.Args[ptrIndex] + c, ok := combine[[2]Op{v.Op, p.Op}] + if !ok { + continue + } + // See if we can combine the Aux/AuxInt values. + switch [2]auxType{opcodeTable[v.Op].auxType, opcodeTable[p.Op].auxType} { + case [2]auxType{auxSymOff, auxInt32}: + // TODO: introduce auxSymOff32 + if !is32Bit(v.AuxInt + p.AuxInt) { + continue + } + v.AuxInt += p.AuxInt + case [2]auxType{auxSymOff, auxSymOff}: + if v.Aux != nil && p.Aux != nil { + continue + } + if !is32Bit(v.AuxInt + p.AuxInt) { + continue + } + if p.Aux != nil { + v.Aux = p.Aux + } + v.AuxInt += p.AuxInt + case [2]auxType{auxSymValAndOff, auxInt32}: + vo := ValAndOff(v.AuxInt) + if !vo.canAdd(p.AuxInt) { + continue + } + v.AuxInt = vo.add(p.AuxInt) + case [2]auxType{auxSymValAndOff, auxSymOff}: + vo := ValAndOff(v.AuxInt) + if v.Aux != nil && p.Aux != nil { + continue + } + if !vo.canAdd(p.AuxInt) { + continue + } + if p.Aux != nil { + v.Aux = p.Aux + } + v.AuxInt = vo.add(p.AuxInt) + case [2]auxType{auxSymOff, auxNone}: + // nothing to do + case [2]auxType{auxSymValAndOff, auxNone}: + // nothing to do + default: + f.Fatalf("unknown aux combining for %s and %s\n", v.Op, p.Op) + } + // Combine the operations. + tmp = append(tmp[:0], v.Args[:ptrIndex]...) + tmp = append(tmp, p.Args...) + tmp = append(tmp, v.Args[ptrIndex+1:]...) + v.resetArgs() + v.Op = c + v.AddArgs(tmp...) + } + } +} + +// combineFirst contains ops which appear in combine as the +// first part of the key. +var combineFirst = map[Op]bool{} + +func init() { + for k := range combine { + combineFirst[k[0]] = true + } +} + +// For each entry k, v in this map, if we have a value x with: +// x.Op == k[0] +// x.Args[0].Op == k[1] +// then we can set x.Op to v and set x.Args like this: +// x.Args[0].Args + x.Args[1:] +// Additionally, the Aux/AuxInt from x.Args[0] is merged into x. +var combine = map[[2]Op]Op{ + // amd64 + [2]Op{OpAMD64MOVBload, OpAMD64ADDQ}: OpAMD64MOVBloadidx1, + [2]Op{OpAMD64MOVWload, OpAMD64ADDQ}: OpAMD64MOVWloadidx1, + [2]Op{OpAMD64MOVLload, OpAMD64ADDQ}: OpAMD64MOVLloadidx1, + [2]Op{OpAMD64MOVQload, OpAMD64ADDQ}: OpAMD64MOVQloadidx1, + [2]Op{OpAMD64MOVSSload, OpAMD64ADDQ}: OpAMD64MOVSSloadidx1, + [2]Op{OpAMD64MOVSDload, OpAMD64ADDQ}: OpAMD64MOVSDloadidx1, + + [2]Op{OpAMD64MOVBstore, OpAMD64ADDQ}: OpAMD64MOVBstoreidx1, + [2]Op{OpAMD64MOVWstore, OpAMD64ADDQ}: OpAMD64MOVWstoreidx1, + [2]Op{OpAMD64MOVLstore, OpAMD64ADDQ}: OpAMD64MOVLstoreidx1, + [2]Op{OpAMD64MOVQstore, OpAMD64ADDQ}: OpAMD64MOVQstoreidx1, + [2]Op{OpAMD64MOVSSstore, OpAMD64ADDQ}: OpAMD64MOVSSstoreidx1, + [2]Op{OpAMD64MOVSDstore, OpAMD64ADDQ}: OpAMD64MOVSDstoreidx1, + + [2]Op{OpAMD64MOVBstoreconst, OpAMD64ADDQ}: OpAMD64MOVBstoreconstidx1, + [2]Op{OpAMD64MOVWstoreconst, OpAMD64ADDQ}: OpAMD64MOVWstoreconstidx1, + [2]Op{OpAMD64MOVLstoreconst, OpAMD64ADDQ}: OpAMD64MOVLstoreconstidx1, + [2]Op{OpAMD64MOVQstoreconst, OpAMD64ADDQ}: OpAMD64MOVQstoreconstidx1, + + [2]Op{OpAMD64MOVBload, OpAMD64LEAQ1}: OpAMD64MOVBloadidx1, + [2]Op{OpAMD64MOVWload, OpAMD64LEAQ1}: OpAMD64MOVWloadidx1, + [2]Op{OpAMD64MOVWload, OpAMD64LEAQ2}: OpAMD64MOVWloadidx2, + [2]Op{OpAMD64MOVLload, OpAMD64LEAQ1}: OpAMD64MOVLloadidx1, + [2]Op{OpAMD64MOVLload, OpAMD64LEAQ4}: OpAMD64MOVLloadidx4, + [2]Op{OpAMD64MOVLload, OpAMD64LEAQ8}: OpAMD64MOVLloadidx8, + [2]Op{OpAMD64MOVQload, OpAMD64LEAQ1}: OpAMD64MOVQloadidx1, + [2]Op{OpAMD64MOVQload, OpAMD64LEAQ8}: OpAMD64MOVQloadidx8, + [2]Op{OpAMD64MOVSSload, OpAMD64LEAQ1}: OpAMD64MOVSSloadidx1, + [2]Op{OpAMD64MOVSSload, OpAMD64LEAQ4}: OpAMD64MOVSSloadidx4, + [2]Op{OpAMD64MOVSDload, OpAMD64LEAQ1}: OpAMD64MOVSDloadidx1, + [2]Op{OpAMD64MOVSDload, OpAMD64LEAQ8}: OpAMD64MOVSDloadidx8, + + [2]Op{OpAMD64MOVBstore, OpAMD64LEAQ1}: OpAMD64MOVBstoreidx1, + [2]Op{OpAMD64MOVWstore, OpAMD64LEAQ1}: OpAMD64MOVWstoreidx1, + [2]Op{OpAMD64MOVWstore, OpAMD64LEAQ2}: OpAMD64MOVWstoreidx2, + [2]Op{OpAMD64MOVLstore, OpAMD64LEAQ1}: OpAMD64MOVLstoreidx1, + [2]Op{OpAMD64MOVLstore, OpAMD64LEAQ4}: OpAMD64MOVLstoreidx4, + [2]Op{OpAMD64MOVLstore, OpAMD64LEAQ8}: OpAMD64MOVLstoreidx8, + [2]Op{OpAMD64MOVQstore, OpAMD64LEAQ1}: OpAMD64MOVQstoreidx1, + [2]Op{OpAMD64MOVQstore, OpAMD64LEAQ8}: OpAMD64MOVQstoreidx8, + [2]Op{OpAMD64MOVSSstore, OpAMD64LEAQ1}: OpAMD64MOVSSstoreidx1, + [2]Op{OpAMD64MOVSSstore, OpAMD64LEAQ4}: OpAMD64MOVSSstoreidx4, + [2]Op{OpAMD64MOVSDstore, OpAMD64LEAQ1}: OpAMD64MOVSDstoreidx1, + [2]Op{OpAMD64MOVSDstore, OpAMD64LEAQ8}: OpAMD64MOVSDstoreidx8, + + [2]Op{OpAMD64MOVBstoreconst, OpAMD64LEAQ1}: OpAMD64MOVBstoreconstidx1, + [2]Op{OpAMD64MOVWstoreconst, OpAMD64LEAQ1}: OpAMD64MOVWstoreconstidx1, + [2]Op{OpAMD64MOVWstoreconst, OpAMD64LEAQ2}: OpAMD64MOVWstoreconstidx2, + [2]Op{OpAMD64MOVLstoreconst, OpAMD64LEAQ1}: OpAMD64MOVLstoreconstidx1, + [2]Op{OpAMD64MOVLstoreconst, OpAMD64LEAQ4}: OpAMD64MOVLstoreconstidx4, + [2]Op{OpAMD64MOVQstoreconst, OpAMD64LEAQ1}: OpAMD64MOVQstoreconstidx1, + [2]Op{OpAMD64MOVQstoreconst, OpAMD64LEAQ8}: OpAMD64MOVQstoreconstidx8, + + // 386 + [2]Op{Op386MOVBload, Op386ADDL}: Op386MOVBloadidx1, + [2]Op{Op386MOVWload, Op386ADDL}: Op386MOVWloadidx1, + [2]Op{Op386MOVLload, Op386ADDL}: Op386MOVLloadidx1, + [2]Op{Op386MOVSSload, Op386ADDL}: Op386MOVSSloadidx1, + [2]Op{Op386MOVSDload, Op386ADDL}: Op386MOVSDloadidx1, + + [2]Op{Op386MOVBstore, Op386ADDL}: Op386MOVBstoreidx1, + [2]Op{Op386MOVWstore, Op386ADDL}: Op386MOVWstoreidx1, + [2]Op{Op386MOVLstore, Op386ADDL}: Op386MOVLstoreidx1, + [2]Op{Op386MOVSSstore, Op386ADDL}: Op386MOVSSstoreidx1, + [2]Op{Op386MOVSDstore, Op386ADDL}: Op386MOVSDstoreidx1, + + [2]Op{Op386MOVBstoreconst, Op386ADDL}: Op386MOVBstoreconstidx1, + [2]Op{Op386MOVWstoreconst, Op386ADDL}: Op386MOVWstoreconstidx1, + [2]Op{Op386MOVLstoreconst, Op386ADDL}: Op386MOVLstoreconstidx1, + + [2]Op{Op386MOVBload, Op386LEAL1}: Op386MOVBloadidx1, + [2]Op{Op386MOVWload, Op386LEAL1}: Op386MOVWloadidx1, + [2]Op{Op386MOVWload, Op386LEAL2}: Op386MOVWloadidx2, + [2]Op{Op386MOVLload, Op386LEAL1}: Op386MOVLloadidx1, + [2]Op{Op386MOVLload, Op386LEAL4}: Op386MOVLloadidx4, + [2]Op{Op386MOVSSload, Op386LEAL1}: Op386MOVSSloadidx1, + [2]Op{Op386MOVSSload, Op386LEAL4}: Op386MOVSSloadidx4, + [2]Op{Op386MOVSDload, Op386LEAL1}: Op386MOVSDloadidx1, + [2]Op{Op386MOVSDload, Op386LEAL8}: Op386MOVSDloadidx8, + + [2]Op{Op386MOVBstore, Op386LEAL1}: Op386MOVBstoreidx1, + [2]Op{Op386MOVWstore, Op386LEAL1}: Op386MOVWstoreidx1, + [2]Op{Op386MOVWstore, Op386LEAL2}: Op386MOVWstoreidx2, + [2]Op{Op386MOVLstore, Op386LEAL1}: Op386MOVLstoreidx1, + [2]Op{Op386MOVLstore, Op386LEAL4}: Op386MOVLstoreidx4, + [2]Op{Op386MOVSSstore, Op386LEAL1}: Op386MOVSSstoreidx1, + [2]Op{Op386MOVSSstore, Op386LEAL4}: Op386MOVSSstoreidx4, + [2]Op{Op386MOVSDstore, Op386LEAL1}: Op386MOVSDstoreidx1, + [2]Op{Op386MOVSDstore, Op386LEAL8}: Op386MOVSDstoreidx8, + + [2]Op{Op386MOVBstoreconst, Op386LEAL1}: Op386MOVBstoreconstidx1, + [2]Op{Op386MOVWstoreconst, Op386LEAL1}: Op386MOVWstoreconstidx1, + [2]Op{Op386MOVWstoreconst, Op386LEAL2}: Op386MOVWstoreconstidx2, + [2]Op{Op386MOVLstoreconst, Op386LEAL1}: Op386MOVLstoreconstidx1, + [2]Op{Op386MOVLstoreconst, Op386LEAL4}: Op386MOVLstoreconstidx4, + + [2]Op{Op386ADDLload, Op386LEAL4}: Op386ADDLloadidx4, + [2]Op{Op386SUBLload, Op386LEAL4}: Op386SUBLloadidx4, + [2]Op{Op386MULLload, Op386LEAL4}: Op386MULLloadidx4, + [2]Op{Op386ANDLload, Op386LEAL4}: Op386ANDLloadidx4, + [2]Op{Op386ORLload, Op386LEAL4}: Op386ORLloadidx4, + [2]Op{Op386XORLload, Op386LEAL4}: Op386XORLloadidx4, + + [2]Op{Op386ADDLmodify, Op386LEAL4}: Op386ADDLmodifyidx4, + [2]Op{Op386SUBLmodify, Op386LEAL4}: Op386SUBLmodifyidx4, + [2]Op{Op386ANDLmodify, Op386LEAL4}: Op386ANDLmodifyidx4, + [2]Op{Op386ORLmodify, Op386LEAL4}: Op386ORLmodifyidx4, + [2]Op{Op386XORLmodify, Op386LEAL4}: Op386XORLmodifyidx4, + + [2]Op{Op386ADDLconstmodify, Op386LEAL4}: Op386ADDLconstmodifyidx4, + [2]Op{Op386ANDLconstmodify, Op386LEAL4}: Op386ANDLconstmodifyidx4, + [2]Op{Op386ORLconstmodify, Op386LEAL4}: Op386ORLconstmodifyidx4, + [2]Op{Op386XORLconstmodify, Op386LEAL4}: Op386XORLconstmodifyidx4, +} diff --git a/src/cmd/compile/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go index 205fcfc7074..c1a734b20b0 100644 --- a/src/cmd/compile/internal/ssa/block.go +++ b/src/cmd/compile/internal/ssa/block.go @@ -101,6 +101,9 @@ func (e Edge) Block() *Block { func (e Edge) Index() int { return e.i } +func (e Edge) String() string { + return fmt.Sprintf("{%v,%d}", e.b, e.i) +} // kind controls successors // ------------------------------------------ diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index 2de4e133bfb..9ec4252def2 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -442,6 +442,7 @@ var passes = [...]pass{ {name: "insert resched checks", fn: insertLoopReschedChecks, disabled: objabi.Preemptibleloops_enabled == 0}, // insert resched checks in loops. {name: "lower", fn: lower, required: true}, + {name: "addressing modes", fn: addressingModes, required: false}, {name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again {name: "lowered cse", fn: cse}, {name: "elim unread autos", fn: elimUnreadAutos}, diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules index 64a6cbaf849..47984734b3b 100644 --- a/src/cmd/compile/internal/ssa/gen/386.rules +++ b/src/cmd/compile/internal/ssa/gen/386.rules @@ -588,10 +588,6 @@ (MOVWLSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWLSXload [off] {sym} ptr mem) (MOVWLZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWload [off] {sym} ptr mem) -(MOVBLZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx1 [off] {sym} ptr idx mem) -(MOVWLZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx1 [off] {sym} ptr idx mem) -(MOVWLZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx2 [off] {sym} ptr idx mem) - // replace load from same location as preceding store with zero/sign extension (or copy in case of full width) (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBLZX x) (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWLZX x) @@ -611,34 +607,22 @@ // fold constants into memory operations // Note that this is not always a good idea because if not all the uses of -// the ADDQconst get eliminated, we still have to compute the ADDQconst and we now -// have potentially two live values (ptr and (ADDQconst [off] ptr)) instead of one. +// the ADDLconst get eliminated, we still have to compute the ADDLconst and we now +// have potentially two live values (ptr and (ADDLconst [off] ptr)) instead of one. // Nevertheless, let's do it! (MOV(L|W|B|SS|SD)load [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOV(L|W|B|SS|SD)load [off1+off2] {sym} ptr mem) (MOV(L|W|B|SS|SD)store [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOV(L|W|B|SS|SD)store [off1+off2] {sym} ptr val mem) ((ADD|SUB|MUL|AND|OR|XOR)Lload [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(off1+off2) -> ((ADD|SUB|MUL|AND|OR|XOR)Lload [off1+off2] {sym} val base mem) -((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) && is32Bit(off1+off2) -> - ((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1+off2] {sym} val base idx mem) -((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) && is32Bit(off1+off2*4) -> - ((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1+off2*4] {sym} val base idx mem) ((ADD|SUB|MUL|DIV)SSload [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(off1+off2) -> ((ADD|SUB|MUL|DIV)SSload [off1+off2] {sym} val base mem) ((ADD|SUB|MUL|DIV)SDload [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(off1+off2) -> ((ADD|SUB|MUL|DIV)SDload [off1+off2] {sym} val base mem) ((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym} (ADDLconst [off2] base) val mem) && is32Bit(off1+off2) -> ((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {sym} base val mem) -((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off1] {sym} (ADDLconst [off2] base) idx val mem) && is32Bit(off1+off2) -> - ((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off1+off2] {sym} base idx val mem) -((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off1] {sym} base (ADDLconst [off2] idx) val mem) && is32Bit(off1+off2*4) -> - ((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off1+off2*4] {sym} base idx val mem) ((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) -> ((ADD|AND|OR|XOR)Lconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem) -((ADD|AND|OR|XOR)Lconstmodifyidx4 [valoff1] {sym} (ADDLconst [off2] base) idx mem) && ValAndOff(valoff1).canAdd(off2) -> - ((ADD|AND|OR|XOR)Lconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {sym} base idx mem) -((ADD|AND|OR|XOR)Lconstmodifyidx4 [valoff1] {sym} base (ADDLconst [off2] idx) mem) && ValAndOff(valoff1).canAdd(off2*4) -> - ((ADD|AND|OR|XOR)Lconstmodifyidx4 [ValAndOff(valoff1).add(off2*4)] {sym} base idx mem) // Fold constants into stores. (MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) -> @@ -652,7 +636,7 @@ (MOV(L|W|B)storeconst [sc] {s} (ADDLconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) -> (MOV(L|W|B)storeconst [ValAndOff(sc).add(off)] {s} ptr mem) -// We need to fold LEAQ into the MOVx ops so that the live variable analysis knows +// We need to fold LEAL into the MOVx ops so that the live variable analysis knows // what variables are being read/written by the ops. // Note: we turn off this merging for operations on globals when building // position-independent code (when Flag_shared is set). @@ -672,31 +656,9 @@ && (ptr.Op != OpSB || !config.ctxt.Flag_shared) -> (MOV(L|W|B)storeconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) -// generating indexed loads and stores -(MOV(B|W|L|SS|SD)load [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(B|W|L|SS|SD)loadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVWload [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOVWloadidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) -(MOV(L|SS)load [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(L|SS)loadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVSDload [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOVSDloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - -(MOV(B|W|L|SS|SD)store [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(B|W|L|SS|SD)storeidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) -(MOVWstore [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOVWstoreidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) -(MOV(L|SS)store [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(L|SS)storeidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) -(MOVSDstore [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOVSDstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - ((ADD|SUB|MUL|AND|OR|XOR)Lload [off1] {sym1} val (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> ((ADD|SUB|MUL|AND|OR|XOR)Lload [off1+off2] {mergeSym(sym1,sym2)} val base mem) -((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> - ((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) ((ADD|SUB|MUL|DIV)SSload [off1] {sym1} val (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> ((ADD|SUB|MUL|DIV)SSload [off1+off2] {mergeSym(sym1,sym2)} val base mem) @@ -706,97 +668,20 @@ ((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> ((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem) -((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off1] {sym1} (LEAL [off2] {sym2} base) idx val mem) - && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> - ((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off1+off2] {mergeSym(sym1,sym2)} base idx val mem) ((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem) && ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> ((ADD|AND|OR|XOR)Lconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem) -((ADD|AND|OR|XOR)Lconstmodifyidx4 [valoff1] {sym1} (LEAL [off2] {sym2} base) idx mem) - && ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) -> - ((ADD|AND|OR|XOR)Lconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base idx mem) - -(MOV(B|W|L|SS|SD)load [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOV(B|W|L|SS|SD)loadidx1 [off] {sym} ptr idx mem) -(MOV(B|W|L|SS|SD)store [off] {sym} (ADDL ptr idx) val mem) && ptr.Op != OpSB -> (MOV(B|W|L|SS|SD)storeidx1 [off] {sym} ptr idx val mem) - -(MOV(B|W|L)storeconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOV(B|W|L)storeconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVWstoreconst [x] {sym1} (LEAL2 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOVWstoreconstidx2 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVLstoreconst [x] {sym1} (LEAL4 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOVLstoreconstidx4 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - -(MOV(B|W|L)storeconst [x] {sym} (ADDL ptr idx) mem) -> (MOV(B|W|L)storeconstidx1 [x] {sym} ptr idx mem) - -// combine SHLL into indexed loads and stores -(MOVWloadidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) -> (MOVWloadidx2 [c] {sym} ptr idx mem) -(MOVLloadidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) -> (MOVLloadidx4 [c] {sym} ptr idx mem) -(MOVWstoreidx1 [c] {sym} ptr (SHLLconst [1] idx) val mem) -> (MOVWstoreidx2 [c] {sym} ptr idx val mem) -(MOVLstoreidx1 [c] {sym} ptr (SHLLconst [2] idx) val mem) -> (MOVLstoreidx4 [c] {sym} ptr idx val mem) -(MOVWstoreconstidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) -> (MOVWstoreconstidx2 [c] {sym} ptr idx mem) -(MOVLstoreconstidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) -> (MOVLstoreconstidx4 [c] {sym} ptr idx mem) - -// combine ADDL into indexed loads and stores -(MOV(B|W|L|SS|SD)loadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOV(B|W|L|SS|SD)loadidx1 [int64(int32(c+d))] {sym} ptr idx mem) -(MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx2 [int64(int32(c+d))] {sym} ptr idx mem) -(MOV(L|SS)loadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOV(L|SS)loadidx4 [int64(int32(c+d))] {sym} ptr idx mem) -(MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx8 [int64(int32(c+d))] {sym} ptr idx mem) - -(MOV(B|W|L|SS|SD)storeidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOV(B|W|L|SS|SD)storeidx1 [int64(int32(c+d))] {sym} ptr idx val mem) -(MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [int64(int32(c+d))] {sym} ptr idx val mem) -(MOV(L|SS)storeidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOV(L|SS)storeidx4 [int64(int32(c+d))] {sym} ptr idx val mem) -(MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [int64(int32(c+d))] {sym} ptr idx val mem) - -(MOV(B|W|L|SS|SD)loadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOV(B|W|L|SS|SD)loadidx1 [int64(int32(c+d))] {sym} ptr idx mem) -(MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx2 [int64(int32(c+2*d))] {sym} ptr idx mem) -(MOV(L|SS)loadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOV(L|SS)loadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem) -(MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx8 [int64(int32(c+8*d))] {sym} ptr idx mem) - -(MOV(B|W|L|SS|SD)storeidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOV(B|W|L|SS|SD)storeidx1 [int64(int32(c+d))] {sym} ptr idx val mem) -(MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx2 [int64(int32(c+2*d))] {sym} ptr idx val mem) -(MOV(L|SS)storeidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOV(L|SS)storeidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem) -(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem) // Merge load/store to op ((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> ((ADD|AND|OR|XOR|SUB|MUL)Lload x [off] {sym} ptr mem) -((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> - ((ADD|AND|OR|XOR|SUB|MUL)Lloadidx4 x [off] {sym} ptr idx mem) -((ADD|SUB|MUL|AND|OR|XOR)Lload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - ((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) ((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem) ((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem) (MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) -> ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem) (MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) -> ((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem) -(MOVLstoreidx4 {sym} [off] ptr idx y:((ADD|AND|OR|XOR)Lloadidx4 x [off] {sym} ptr idx mem) mem) && y.Uses==1 && clobber(y) -> - ((ADD|AND|OR|XOR)Lmodifyidx4 [off] {sym} ptr idx x mem) -(MOVLstoreidx4 {sym} [off] ptr idx y:((ADD|SUB|AND|OR|XOR)L l:(MOVLloadidx4 [off] {sym} ptr idx mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) -> - ((ADD|SUB|AND|OR|XOR)Lmodifyidx4 [off] {sym} ptr idx x mem) (MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lconst [c] l:(MOVLload [off] {sym} ptr mem)) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(c,off) -> ((ADD|AND|OR|XOR)Lconstmodify [makeValAndOff(c,off)] {sym} ptr mem) -(MOVLstoreidx4 {sym} [off] ptr idx y:((ADD|AND|OR|XOR)Lconst [c] l:(MOVLloadidx4 [off] {sym} ptr idx mem)) mem) - && y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(c,off) -> - ((ADD|AND|OR|XOR)Lconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) -((ADD|AND|OR|XOR)Lmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) && validValAndOff(c,off) -> - ((ADD|AND|OR|XOR)Lconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) -(SUBLmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) && validValAndOff(-c,off) -> - (ADDLconstmodifyidx4 [makeValAndOff(-c,off)] {sym} ptr idx mem) - -(MOV(B|W|L)storeconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) -> - (MOV(B|W|L)storeconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVWstoreconstidx2 [x] {sym} (ADDLconst [c] ptr) idx mem) -> - (MOVWstoreconstidx2 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVLstoreconstidx4 [x] {sym} (ADDLconst [c] ptr) idx mem) -> - (MOVLstoreconstidx4 [ValAndOff(x).add(c)] {sym} ptr idx mem) - -(MOV(B|W|L)storeconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) -> - (MOV(B|W|L)storeconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVWstoreconstidx2 [x] {sym} ptr (ADDLconst [c] idx) mem) -> - (MOVWstoreconstidx2 [ValAndOff(x).add(2*c)] {sym} ptr idx mem) -(MOVLstoreconstidx4 [x] {sym} ptr (ADDLconst [c] idx) mem) -> - (MOVLstoreconstidx4 [ValAndOff(x).add(4*c)] {sym} ptr idx mem) // fold LEALs together (LEAL [off1] {sym1} (LEAL [off2] {sym2} x)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> @@ -826,6 +711,16 @@ (LEAL [off1] {sym1} (LEAL8 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y) +// LEAL[1248] into LEAL[1248]. Only some such merges are possible. +(LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} x y) +(LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} y x) +(LEAL2 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) && is32Bit(off1+2*off2) && sym2 == nil -> + (LEAL4 [off1+2*off2] {sym1} x y) +(LEAL4 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) && is32Bit(off1+4*off2) && sym2 == nil -> + (LEAL8 [off1+4*off2] {sym1} x y) + // Absorb InvertFlags into branches. (LT (InvertFlags cmp) yes no) -> (GT cmp yes no) (GT (InvertFlags cmp) yes no) -> (LT cmp yes no) @@ -1039,23 +934,27 @@ // TEST %reg,%reg is shorter than CMP (CMP(L|W|B)const x [0]) -> (TEST(L|W|B) x x) +// Convert LEAL1 back to ADDL if we can +(LEAL1 [0] x y) && v.Aux == nil -> (ADDL x y) + // Combining byte loads into larger (unaligned) loads. // There are many ways these combinations could occur. This is // designed to match the way encoding/binary.LittleEndian does it. -(ORL x0:(MOVBload [i0] {s} p mem) - s0:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem))) +(ORL x0:(MOVBload [i0] {s} p0 mem) + s0:(SHLLconst [8] x1:(MOVBload [i1] {s} p1 mem))) && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, s0) - -> @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem) + -> @mergePoint(b,x0,x1) (MOVWload [i0] {s} p0 mem) (ORL o0:(ORL - x0:(MOVWload [i0] {s} p mem) - s0:(SHLLconst [16] x1:(MOVBload [i2] {s} p mem))) - s1:(SHLLconst [24] x2:(MOVBload [i3] {s} p mem))) + x0:(MOVWload [i0] {s} p0 mem) + s0:(SHLLconst [16] x1:(MOVBload [i2] {s} p1 mem))) + s1:(SHLLconst [24] x2:(MOVBload [i3] {s} p2 mem))) && i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 @@ -1064,126 +963,84 @@ && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 + && same(p0, p1, 1) + && same(p1, p2, 1) && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, s0, s1, o0) - -> @mergePoint(b,x0,x1,x2) (MOVLload [i0] {s} p mem) - -(ORL x0:(MOVBloadidx1 [i0] {s} p idx mem) - s0:(SHLLconst [8] x1:(MOVBloadidx1 [i1] {s} p idx mem))) - && i1==i0+1 - && x0.Uses == 1 - && x1.Uses == 1 - && s0.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, s0) - -> @mergePoint(b,x0,x1) (MOVWloadidx1 [i0] {s} p idx mem) - -(ORL o0:(ORL - x0:(MOVWloadidx1 [i0] {s} p idx mem) - s0:(SHLLconst [16] x1:(MOVBloadidx1 [i2] {s} p idx mem))) - s1:(SHLLconst [24] x2:(MOVBloadidx1 [i3] {s} p idx mem))) - && i2 == i0+2 - && i3 == i0+3 - && x0.Uses == 1 - && x1.Uses == 1 - && x2.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && o0.Uses == 1 - && mergePoint(b,x0,x1,x2) != nil - && clobber(x0, x1, x2, s0, s1, o0) - -> @mergePoint(b,x0,x1,x2) (MOVLloadidx1 [i0] {s} p idx mem) + -> @mergePoint(b,x0,x1,x2) (MOVLload [i0] {s} p0 mem) // Combine constant stores into larger (unaligned) stores. -(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) +(MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem)) && x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() + && same(p0, p1, 1) && clobber(x) - -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) -(MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem)) + -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) +(MOVBstoreconst [a] {s} p1 x:(MOVBstoreconst [c] {s} p0 mem)) && x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() + && same(p0, p1, 1) && clobber(x) - -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) -(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) + -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) +(MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem)) && x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() + && same(p0, p1, 1) && clobber(x) - -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) -(MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem)) + -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) +(MOVWstoreconst [a] {s} p1 x:(MOVWstoreconst [c] {s} p0 mem)) && x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() + && same(p0, p1, 1) && clobber(x) - -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) - -(MOVBstoreconstidx1 [c] {s} p i x:(MOVBstoreconstidx1 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() - && clobber(x) - -> (MOVWstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p i mem) -(MOVWstoreconstidx1 [c] {s} p i x:(MOVWstoreconstidx1 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() - && clobber(x) - -> (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p i mem) - -(MOVWstoreconstidx2 [c] {s} p i x:(MOVWstoreconstidx2 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() - && clobber(x) - -> (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p (SHLLconst [1] i) mem) + -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) // Combine stores into larger (unaligned) stores. -(MOVBstore [i] {s} p (SHR(W|L)const [8] w) x:(MOVBstore [i-1] {s} p w mem)) +(MOVBstore [i] {s} p1 (SHR(W|L)const [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVWstore [i-1] {s} p w mem) -(MOVBstore [i] {s} p w x:(MOVBstore {s} [i+1] p (SHR(W|L)const [8] w) mem)) + -> (MOVWstore [i-1] {s} p0 w mem) +(MOVBstore [i] {s} p1 w x:(MOVBstore {s} [i+1] p0 (SHR(W|L)const [8] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVWstore [i] {s} p w mem) -(MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem)) + -> (MOVWstore [i] {s} p0 w mem) +(MOVBstore [i] {s} p1 (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p0 w0:(SHRLconst [j-8] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVWstore [i-1] {s} p w0 mem) -(MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem)) + -> (MOVWstore [i-1] {s} p0 w0 mem) +(MOVWstore [i] {s} p1 (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p0 w mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVLstore [i-2] {s} p w mem) -(MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem)) + -> (MOVLstore [i-2] {s} p0 w mem) +(MOVWstore [i] {s} p1 (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p0 w0:(SHRLconst [j-16] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVLstore [i-2] {s} p w0 mem) + -> (MOVLstore [i-2] {s} p0 w0 mem) -(MOVBstoreidx1 [i] {s} p idx (SHR(L|W)const [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVWstoreidx1 [i-1] {s} p idx w mem) -(MOVBstoreidx1 [i] {s} p idx w x:(MOVBstoreidx1 [i+1] {s} p idx (SHR(L|W)const [8] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVWstoreidx1 [i] {s} p idx w mem) -(MOVBstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHRLconst [j-8] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVWstoreidx1 [i-1] {s} p idx w0 mem) -(MOVWstoreidx1 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p idx w mem) -(MOVWstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p idx w0 mem) +// Move constant offsets from LEALx up into load. This lets the above combining +// rules discover indexed load-combining instances. +(MOV(B|W|L)load [i0] {s0} l:(LEAL1 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)load [i0+i1] {s0} (LEAL1 [0] {s1} x y) mem) +(MOV(B|W|L)load [i0] {s0} l:(LEAL2 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)load [i0+i1] {s0} (LEAL2 [0] {s1} x y) mem) +(MOV(B|W|L)load [i0] {s0} l:(LEAL4 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)load [i0+i1] {s0} (LEAL4 [0] {s1} x y) mem) +(MOV(B|W|L)load [i0] {s0} l:(LEAL8 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)load [i0+i1] {s0} (LEAL8 [0] {s1} x y) mem) -(MOVWstoreidx2 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w mem) -(MOVWstoreidx2 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx2 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w0 mem) +(MOV(B|W|L)store [i0] {s0} l:(LEAL1 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)store [i0+i1] {s0} (LEAL1 [0] {s1} x y) val mem) +(MOV(B|W|L)store [i0] {s0} l:(LEAL2 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)store [i0+i1] {s0} (LEAL2 [0] {s1} x y) val mem) +(MOV(B|W|L)store [i0] {s0} l:(LEAL4 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)store [i0+i1] {s0} (LEAL4 [0] {s1} x y) val mem) +(MOV(B|W|L)store [i0] {s0} l:(LEAL8 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L)store [i0+i1] {s0} (LEAL8 [0] {s1} x y) val mem) // For PIC, break floating-point constant loading into two instructions so we have // a register to use for holding the address of the constant pool entry. diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index c165fed4856..07981d2e819 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -1043,12 +1043,6 @@ (MOVWQZX x) && zeroUpper48Bits(x,3) -> x (MOVBQZX x) && zeroUpper56Bits(x,3) -> x -(MOVBQZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx1 [off] {sym} ptr idx mem) -(MOVWQZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx1 [off] {sym} ptr idx mem) -(MOVWQZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx2 [off] {sym} ptr idx mem) -(MOVLQZX x:(MOVLloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVLloadidx1 [off] {sym} ptr idx mem) -(MOVLQZX x:(MOVLloadidx4 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVLloadidx4 [off] {sym} ptr idx mem) - // replace load from same location as preceding store with zero/sign extension (or copy in case of full width) (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBQZX x) (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWQZX x) @@ -1166,86 +1160,6 @@ && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem) -// generating indexed loads and stores -(MOV(B|W|L|Q|SS|SD)load [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(B|W|L|Q|SS|SD)loadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVWload [off1] {sym1} (LEAQ2 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOVWloadidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) -(MOV(L|SS)load [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(L|SS)loadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) -(MOV(L|Q|SD)load [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(L|Q|SD)loadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - -(MOV(B|W|L|Q|SS|SD)store [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(B|W|L|Q|SS|SD)storeidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) -(MOVWstore [off1] {sym1} (LEAQ2 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOVWstoreidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) -(MOV(L|SS)store [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(L|SS)storeidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) -(MOV(L|Q|SD)store [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> - (MOV(L|Q|SD)storeidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - -(MOV(B|W|L|Q|SS|SD)load [off] {sym} (ADDQ ptr idx) mem) && ptr.Op != OpSB -> - (MOV(B|W|L|Q|SS|SD)loadidx1 [off] {sym} ptr idx mem) -(MOV(B|W|L|Q|SS|SD)store [off] {sym} (ADDQ ptr idx) val mem) && ptr.Op != OpSB -> - (MOV(B|W|L|Q|SS|SD)storeidx1 [off] {sym} ptr idx val mem) - -(MOV(B|W|L|Q)storeconst [x] {sym1} (LEAQ1 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOV(B|W|L|Q)storeconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVWstoreconst [x] {sym1} (LEAQ2 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOVWstoreconstidx2 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVLstoreconst [x] {sym1} (LEAQ4 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOVLstoreconstidx4 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) -(MOVQstoreconst [x] {sym1} (LEAQ8 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> - (MOVQstoreconstidx8 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - -(MOV(B|W|L|Q)storeconst [x] {sym} (ADDQ ptr idx) mem) -> (MOV(B|W|L|Q)storeconstidx1 [x] {sym} ptr idx mem) - -// combine SHLQ into indexed loads and stores -(MOVWloadidx1 [c] {sym} ptr (SHLQconst [1] idx) mem) -> (MOVWloadidx2 [c] {sym} ptr idx mem) -(MOV(L|SS)loadidx1 [c] {sym} ptr (SHLQconst [2] idx) mem) -> (MOV(L|SS)loadidx4 [c] {sym} ptr idx mem) -(MOV(L|Q|SD)loadidx1 [c] {sym} ptr (SHLQconst [3] idx) mem) -> (MOV(L|Q|SD)loadidx8 [c] {sym} ptr idx mem) - -(MOVWstoreidx1 [c] {sym} ptr (SHLQconst [1] idx) val mem) -> (MOVWstoreidx2 [c] {sym} ptr idx val mem) -(MOV(L|SS)storeidx1 [c] {sym} ptr (SHLQconst [2] idx) val mem) -> (MOV(L|SS)storeidx4 [c] {sym} ptr idx val mem) -(MOV(L|Q|SD)storeidx1 [c] {sym} ptr (SHLQconst [3] idx) val mem) -> (MOV(L|Q|SD)storeidx8 [c] {sym} ptr idx val mem) -(MOVWstoreconstidx1 [c] {sym} ptr (SHLQconst [1] idx) mem) -> (MOVWstoreconstidx2 [c] {sym} ptr idx mem) -(MOVLstoreconstidx1 [c] {sym} ptr (SHLQconst [2] idx) mem) -> (MOVLstoreconstidx4 [c] {sym} ptr idx mem) -(MOVQstoreconstidx1 [c] {sym} ptr (SHLQconst [3] idx) mem) -> (MOVQstoreconstidx8 [c] {sym} ptr idx mem) - -// combine ADDQ into pointer of indexed loads and stores -(MOV(B|W|L|Q|SS|SD)loadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) && is32Bit(c+d) -> (MOV(B|W|L|Q|SS|SD)loadidx1 [c+d] {sym} ptr idx mem) -(MOVWloadidx2 [c] {sym} (ADDQconst [d] ptr) idx mem) && is32Bit(c+d) -> (MOVWloadidx2 [c+d] {sym} ptr idx mem) -(MOV(L|SS)loadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem) && is32Bit(c+d) -> (MOV(L|SS)loadidx4 [c+d] {sym} ptr idx mem) -(MOV(L|Q|SD)loadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem) && is32Bit(c+d) -> (MOV(L|Q|SD)loadidx8 [c+d] {sym} ptr idx mem) - -(MOV(B|W|L|Q|SS|SD)storeidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) && is32Bit(c+d) -> (MOV(B|W|L|Q|SS|SD)storeidx1 [c+d] {sym} ptr idx val mem) -(MOVWstoreidx2 [c] {sym} (ADDQconst [d] ptr) idx val mem) && is32Bit(c+d) -> (MOVWstoreidx2 [c+d] {sym} ptr idx val mem) -(MOV(L|SS)storeidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem) && is32Bit(c+d) -> (MOV(L|SS)storeidx4 [c+d] {sym} ptr idx val mem) -(MOV(L|Q|SD)storeidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem) && is32Bit(c+d) -> (MOV(L|Q|SD)storeidx8 [c+d] {sym} ptr idx val mem) - - -// combine ADDQ into index of indexed loads and stores -(MOV(B|W|L|Q|SS|SD)loadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) && is32Bit(c+d) -> (MOV(B|W|L|Q|SS|SD)loadidx1 [c+d] {sym} ptr idx mem) -(MOVWloadidx2 [c] {sym} ptr (ADDQconst [d] idx) mem) && is32Bit(c+2*d) -> (MOVWloadidx2 [c+2*d] {sym} ptr idx mem) -(MOV(L|SS)loadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem) && is32Bit(c+4*d) -> (MOV(L|SS)loadidx4 [c+4*d] {sym} ptr idx mem) -(MOV(L|Q|SD)loadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem) && is32Bit(c+8*d) -> (MOV(L|Q|SD)loadidx8 [c+8*d] {sym} ptr idx mem) - -(MOV(B|W|L|Q|SS|SD)storeidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) && is32Bit(c+d) -> (MOV(B|W|L|Q|SS|SD)storeidx1 [c+d] {sym} ptr idx val mem) -(MOVWstoreidx2 [c] {sym} ptr (ADDQconst [d] idx) val mem) && is32Bit(c+2*d) -> (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem) -(MOV(L|SS)storeidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem) && is32Bit(c+4*d) -> (MOV(L|SS)storeidx4 [c+4*d] {sym} ptr idx val mem) -(MOV(L|Q|SD)storeidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem) && is32Bit(c+8*d) -> (MOV(L|Q|SD)storeidx8 [c+8*d] {sym} ptr idx val mem) - -(MOV(B|W|L|Q)storeconstidx1 [x] {sym} (ADDQconst [c] ptr) idx mem) && ValAndOff(x).canAdd(c) -> (MOV(B|W|L|Q)storeconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVWstoreconstidx2 [x] {sym} (ADDQconst [c] ptr) idx mem) && ValAndOff(x).canAdd(c) -> (MOVWstoreconstidx2 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVLstoreconstidx4 [x] {sym} (ADDQconst [c] ptr) idx mem) && ValAndOff(x).canAdd(c) -> (MOVLstoreconstidx4 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVQstoreconstidx8 [x] {sym} (ADDQconst [c] ptr) idx mem) && ValAndOff(x).canAdd(c) -> (MOVQstoreconstidx8 [ValAndOff(x).add(c)] {sym} ptr idx mem) - -(MOV(B|W|L|Q)storeconstidx1 [x] {sym} ptr (ADDQconst [c] idx) mem) && ValAndOff(x).canAdd(c) -> (MOV(B|W|L|Q)storeconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) -(MOVWstoreconstidx2 [x] {sym} ptr (ADDQconst [c] idx) mem) && ValAndOff(x).canAdd(2*c) -> (MOVWstoreconstidx2 [ValAndOff(x).add(2*c)] {sym} ptr idx mem) -(MOVLstoreconstidx4 [x] {sym} ptr (ADDQconst [c] idx) mem) && ValAndOff(x).canAdd(4*c) -> (MOVLstoreconstidx4 [ValAndOff(x).add(4*c)] {sym} ptr idx mem) -(MOVQstoreconstidx8 [x] {sym} ptr (ADDQconst [c] idx) mem) && ValAndOff(x).canAdd(8*c) -> (MOVQstoreconstidx8 [ValAndOff(x).add(8*c)] {sym} ptr idx mem) - // fold LEAQs together (LEAQ [off1] {sym1} (LEAQ [off2] {sym2} x)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> (LEAQ [off1+off2] {mergeSym(sym1,sym2)} x) @@ -1274,6 +1188,17 @@ (LEAQ [off1] {sym1} (LEAQ8 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> (LEAQ8 [off1+off2] {mergeSym(sym1,sym2)} x y) +// LEAQ[1248] into LEAQ[1248]. Only some such merges are possible. +(LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} x y) +(LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} y x) +(LEAQ2 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) && is32Bit(off1+2*off2) && sym2 == nil -> + (LEAQ4 [off1+2*off2] {sym1} x y) +(LEAQ4 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) && is32Bit(off1+4*off2) && sym2 == nil -> + (LEAQ8 [off1+4*off2] {sym1} x y) +// TODO: more? + // Absorb InvertFlags into branches. (LT (InvertFlags cmp) yes no) -> (GT cmp yes no) (GT (InvertFlags cmp) yes no) -> (LT cmp yes no) @@ -1329,7 +1254,10 @@ (CMPWconst (ANDLconst _ [m]) [n]) && 0 <= int16(m) && int16(m) < int16(n) -> (FlagLT_ULT) (CMPBconst (ANDLconst _ [m]) [n]) && 0 <= int8(m) && int8(m) < int8(n) -> (FlagLT_ULT) -(TEST(Q|L)const [c] (MOV(Q|L)const [c])) -> (FlagEQ) +// TESTQ c c sets flags like CMPQ c 0. +(TEST(Q|L)const [c] (MOV(Q|L)const [c])) && c == 0 -> (FlagEQ) +(TEST(Q|L)const [c] (MOV(Q|L)const [c])) && c < 0 -> (FlagLT_UGT) +(TEST(Q|L)const [c] (MOV(Q|L)const [c])) && c > 0 -> (FlagGT_UGT) // TODO: DIVxU also. @@ -1552,60 +1480,65 @@ // Little-endian loads -(ORL x0:(MOVBload [i0] {s} p mem) - sh:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem))) +(ORL x0:(MOVBload [i0] {s} p0 mem) + sh:(SHLLconst [8] x1:(MOVBload [i1] {s} p1 mem))) && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem) + -> @mergePoint(b,x0,x1) (MOVWload [i0] {s} p0 mem) -(ORQ x0:(MOVBload [i0] {s} p mem) - sh:(SHLQconst [8] x1:(MOVBload [i1] {s} p mem))) +(ORQ x0:(MOVBload [i0] {s} p0 mem) + sh:(SHLQconst [8] x1:(MOVBload [i1] {s} p1 mem))) && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem) + -> @mergePoint(b,x0,x1) (MOVWload [i0] {s} p0 mem) -(ORL x0:(MOVWload [i0] {s} p mem) - sh:(SHLLconst [16] x1:(MOVWload [i1] {s} p mem))) +(ORL x0:(MOVWload [i0] {s} p0 mem) + sh:(SHLLconst [16] x1:(MOVWload [i1] {s} p1 mem))) && i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem) + -> @mergePoint(b,x0,x1) (MOVLload [i0] {s} p0 mem) -(ORQ x0:(MOVWload [i0] {s} p mem) - sh:(SHLQconst [16] x1:(MOVWload [i1] {s} p mem))) +(ORQ x0:(MOVWload [i0] {s} p0 mem) + sh:(SHLQconst [16] x1:(MOVWload [i1] {s} p1 mem))) && i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem) + -> @mergePoint(b,x0,x1) (MOVLload [i0] {s} p0 mem) -(ORQ x0:(MOVLload [i0] {s} p mem) - sh:(SHLQconst [32] x1:(MOVLload [i1] {s} p mem))) +(ORQ x0:(MOVLload [i0] {s} p0 mem) + sh:(SHLQconst [32] x1:(MOVLload [i1] {s} p1 mem))) && i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVQload [i0] {s} p mem) + -> @mergePoint(b,x0,x1) (MOVQload [i0] {s} p0 mem) (ORL - s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p mem)) + s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p0 mem)) or:(ORL - s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p mem)) + s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p1 mem)) y)) && i1 == i0+1 && j1 == j0+8 @@ -1615,14 +1548,15 @@ && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j0] (MOVWload [i0] {s} p mem)) y) + -> @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j0] (MOVWload [i0] {s} p0 mem)) y) (ORQ - s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p mem)) + s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p0 mem)) or:(ORQ - s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p mem)) + s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p1 mem)) y)) && i1 == i0+1 && j1 == j0+8 @@ -1632,14 +1566,15 @@ && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVWload [i0] {s} p mem)) y) + -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVWload [i0] {s} p0 mem)) y) (ORQ - s1:(SHLQconst [j1] x1:(MOVWload [i1] {s} p mem)) + s1:(SHLQconst [j1] x1:(MOVWload [i1] {s} p0 mem)) or:(ORQ - s0:(SHLQconst [j0] x0:(MOVWload [i0] {s} p mem)) + s0:(SHLQconst [j0] x0:(MOVWload [i0] {s} p1 mem)) y)) && i1 == i0+2 && j1 == j0+16 @@ -1649,180 +1584,105 @@ && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVLload [i0] {s} p mem)) y) + -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVLload [i0] {s} p0 mem)) y) // Little-endian indexed loads -(ORL x0:(MOVBloadidx1 [i0] {s} p idx mem) - sh:(SHLLconst [8] x1:(MOVBloadidx1 [i1] {s} p idx mem))) - && i1 == i0+1 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVWloadidx1 [i0] {s} p idx mem) +// Move constants offsets from LEAQx up into load. This lets the above combining +// rules discover indexed load-combining instances. +(MOV(B|W|L|Q)load [i0] {s0} l:(LEAQ1 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)load [i0+i1] {s0} (LEAQ1 [0] {s1} x y) mem) +(MOV(B|W|L|Q)load [i0] {s0} l:(LEAQ2 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)load [i0+i1] {s0} (LEAQ2 [0] {s1} x y) mem) +(MOV(B|W|L|Q)load [i0] {s0} l:(LEAQ4 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)load [i0+i1] {s0} (LEAQ4 [0] {s1} x y) mem) +(MOV(B|W|L|Q)load [i0] {s0} l:(LEAQ8 [i1] {s1} x y) mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)load [i0+i1] {s0} (LEAQ8 [0] {s1} x y) mem) -(ORQ x0:(MOVBloadidx1 [i0] {s} p idx mem) - sh:(SHLQconst [8] x1:(MOVBloadidx1 [i1] {s} p idx mem))) - && i1 == i0+1 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVWloadidx1 [i0] {s} p idx mem) - -(ORL x0:(MOVWloadidx1 [i0] {s} p idx mem) - sh:(SHLLconst [16] x1:(MOVWloadidx1 [i1] {s} p idx mem))) - && i1 == i0+2 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVLloadidx1 [i0] {s} p idx mem) - -(ORQ x0:(MOVWloadidx1 [i0] {s} p idx mem) - sh:(SHLQconst [16] x1:(MOVWloadidx1 [i1] {s} p idx mem))) - && i1 == i0+2 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVLloadidx1 [i0] {s} p idx mem) - -(ORQ x0:(MOVLloadidx1 [i0] {s} p idx mem) - sh:(SHLQconst [32] x1:(MOVLloadidx1 [i1] {s} p idx mem))) - && i1 == i0+4 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (MOVQloadidx1 [i0] {s} p idx mem) - -(ORL - s1:(SHLLconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) - or:(ORL - s0:(SHLLconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) - y)) - && i1 == i0+1 - && j1 == j0+8 - && j0 % 16 == 0 - && x0.Uses == 1 - && x1.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && or.Uses == 1 - && mergePoint(b,x0,x1,y) != nil - && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j0] (MOVWloadidx1 [i0] {s} p idx mem)) y) - -(ORQ - s1:(SHLQconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) - or:(ORQ - s0:(SHLQconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) - y)) - && i1 == i0+1 - && j1 == j0+8 - && j0 % 16 == 0 - && x0.Uses == 1 - && x1.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && or.Uses == 1 - && mergePoint(b,x0,x1,y) != nil - && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVWloadidx1 [i0] {s} p idx mem)) y) - -(ORQ - s1:(SHLQconst [j1] x1:(MOVWloadidx1 [i1] {s} p idx mem)) - or:(ORQ - s0:(SHLQconst [j0] x0:(MOVWloadidx1 [i0] {s} p idx mem)) - y)) - && i1 == i0+2 - && j1 == j0+16 - && j0 % 32 == 0 - && x0.Uses == 1 - && x1.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && or.Uses == 1 - && mergePoint(b,x0,x1,y) != nil - && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVLloadidx1 [i0] {s} p idx mem)) y) +(MOV(B|W|L|Q)store [i0] {s0} l:(LEAQ1 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)store [i0+i1] {s0} (LEAQ1 [0] {s1} x y) val mem) +(MOV(B|W|L|Q)store [i0] {s0} l:(LEAQ2 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)store [i0+i1] {s0} (LEAQ2 [0] {s1} x y) val mem) +(MOV(B|W|L|Q)store [i0] {s0} l:(LEAQ4 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)store [i0+i1] {s0} (LEAQ4 [0] {s1} x y) val mem) +(MOV(B|W|L|Q)store [i0] {s0} l:(LEAQ8 [i1] {s1} x y) val mem) && i1 != 0 && is32Bit(i0+i1) +-> (MOV(B|W|L|Q)store [i0+i1] {s0} (LEAQ8 [0] {s1} x y) val mem) // Big-endian loads (ORL - x1:(MOVBload [i1] {s} p mem) - sh:(SHLLconst [8] x0:(MOVBload [i0] {s} p mem))) + x1:(MOVBload [i1] {s} p0 mem) + sh:(SHLLconst [8] x0:(MOVBload [i0] {s} p1 mem))) && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p mem)) + -> @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p0 mem)) (ORQ - x1:(MOVBload [i1] {s} p mem) - sh:(SHLQconst [8] x0:(MOVBload [i0] {s} p mem))) + x1:(MOVBload [i1] {s} p0 mem) + sh:(SHLQconst [8] x0:(MOVBload [i0] {s} p1 mem))) && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p mem)) + -> @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p0 mem)) (ORL - r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)) - sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem)))) + r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p0 mem)) + sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p1 mem)))) && i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - -> @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p mem)) + -> @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p0 mem)) (ORQ - r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)) - sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem)))) + r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p0 mem)) + sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p1 mem)))) && i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - -> @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p mem)) + -> @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p0 mem)) (ORQ - r1:(BSWAPL x1:(MOVLload [i1] {s} p mem)) - sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i0] {s} p mem)))) + r1:(BSWAPL x1:(MOVLload [i1] {s} p0 mem)) + sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i0] {s} p1 mem)))) && i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - -> @mergePoint(b,x0,x1) (BSWAPQ (MOVQload [i0] {s} p mem)) + -> @mergePoint(b,x0,x1) (BSWAPQ (MOVQload [i0] {s} p0 mem)) (ORL - s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p mem)) + s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p0 mem)) or:(ORL - s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p mem)) + s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p1 mem)) y)) && i1 == i0+1 && j1 == j0-8 @@ -1832,14 +1692,15 @@ && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p mem))) y) + -> @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p0 mem))) y) (ORQ - s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p mem)) + s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p0 mem)) or:(ORQ - s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p mem)) + s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p1 mem)) y)) && i1 == i0+1 && j1 == j0-8 @@ -1849,14 +1710,15 @@ && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p mem))) y) + -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p0 mem))) y) (ORQ - s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem))) + s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p0 mem))) or:(ORQ - s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem))) + s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p1 mem))) y)) && i1 == i0+2 && j1 == j0-16 @@ -1868,168 +1730,41 @@ && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 + && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (BSWAPL (MOVLload [i0] {s} p mem))) y) - -// Big-endian indexed loads - -(ORL - x1:(MOVBloadidx1 [i1] {s} p idx mem) - sh:(SHLLconst [8] x0:(MOVBloadidx1 [i0] {s} p idx mem))) - && i1 == i0+1 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem)) - -(ORQ - x1:(MOVBloadidx1 [i1] {s} p idx mem) - sh:(SHLQconst [8] x0:(MOVBloadidx1 [i0] {s} p idx mem))) - && i1 == i0+1 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - -> @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem)) - -(ORL - r1:(ROLWconst [8] x1:(MOVWloadidx1 [i1] {s} p idx mem)) - sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWloadidx1 [i0] {s} p idx mem)))) - && i1 == i0+2 - && x0.Uses == 1 - && x1.Uses == 1 - && r0.Uses == 1 - && r1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, r0, r1, sh) - -> @mergePoint(b,x0,x1) (BSWAPL (MOVLloadidx1 [i0] {s} p idx mem)) - -(ORQ - r1:(ROLWconst [8] x1:(MOVWloadidx1 [i1] {s} p idx mem)) - sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWloadidx1 [i0] {s} p idx mem)))) - && i1 == i0+2 - && x0.Uses == 1 - && x1.Uses == 1 - && r0.Uses == 1 - && r1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, r0, r1, sh) - -> @mergePoint(b,x0,x1) (BSWAPL (MOVLloadidx1 [i0] {s} p idx mem)) - -(ORQ - r1:(BSWAPL x1:(MOVLloadidx1 [i1] {s} p idx mem)) - sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLloadidx1 [i0] {s} p idx mem)))) - && i1 == i0+4 - && x0.Uses == 1 - && x1.Uses == 1 - && r0.Uses == 1 - && r1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, r0, r1, sh) - -> @mergePoint(b,x0,x1) (BSWAPQ (MOVQloadidx1 [i0] {s} p idx mem)) - -(ORL - s0:(SHLLconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) - or:(ORL - s1:(SHLLconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) - y)) - && i1 == i0+1 - && j1 == j0-8 - && j1 % 16 == 0 - && x0.Uses == 1 - && x1.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && or.Uses == 1 - && mergePoint(b,x0,x1,y) != nil - && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j1] (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem))) y) - -(ORQ - s0:(SHLQconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) - or:(ORQ - s1:(SHLQconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) - y)) - && i1 == i0+1 - && j1 == j0-8 - && j1 % 16 == 0 - && x0.Uses == 1 - && x1.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && or.Uses == 1 - && mergePoint(b,x0,x1,y) != nil - && clobber(x0, x1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem))) y) - -(ORQ - s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWloadidx1 [i0] {s} p idx mem))) - or:(ORQ - s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWloadidx1 [i1] {s} p idx mem))) - y)) - && i1 == i0+2 - && j1 == j0-16 - && j1 % 32 == 0 - && x0.Uses == 1 - && x1.Uses == 1 - && r0.Uses == 1 - && r1.Uses == 1 - && s0.Uses == 1 - && s1.Uses == 1 - && or.Uses == 1 - && mergePoint(b,x0,x1,y) != nil - && clobber(x0, x1, r0, r1, s0, s1, or) - -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (BSWAPL (MOVLloadidx1 [i0] {s} p idx mem))) y) + -> @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (BSWAPL (MOVLload [i0] {s} p0 mem))) y) // Combine 2 byte stores + shift into rolw 8 + word store -(MOVBstore [i] {s} p w - x0:(MOVBstore [i-1] {s} p (SHRWconst [8] w) mem)) +(MOVBstore [i] {s} p1 w + x0:(MOVBstore [i-1] {s} p0 (SHRWconst [8] w) mem)) && x0.Uses == 1 + && same(p0, p1, 1) && clobber(x0) - -> (MOVWstore [i-1] {s} p (ROLWconst [8] w) mem) - -(MOVBstoreidx1 [i] {s} p idx w - x0:(MOVBstoreidx1 [i-1] {s} p idx (SHRWconst [8] w) mem)) - && x0.Uses == 1 - && clobber(x0) - -> (MOVWstoreidx1 [i-1] {s} p idx (ROLWconst [8] w) mem) + -> (MOVWstore [i-1] {s} p0 (ROLWconst [8] w) mem) // Combine stores + shifts into bswap and larger (unaligned) stores -(MOVBstore [i] {s} p w - x2:(MOVBstore [i-1] {s} p (SHRLconst [8] w) - x1:(MOVBstore [i-2] {s} p (SHRLconst [16] w) - x0:(MOVBstore [i-3] {s} p (SHRLconst [24] w) mem)))) +(MOVBstore [i] {s} p3 w + x2:(MOVBstore [i-1] {s} p2 (SHRLconst [8] w) + x1:(MOVBstore [i-2] {s} p1 (SHRLconst [16] w) + x0:(MOVBstore [i-3] {s} p0 (SHRLconst [24] w) mem)))) && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 + && same(p0, p1, 1) + && same(p1, p2, 1) + && same(p2, p3, 1) && clobber(x0, x1, x2) - -> (MOVLstore [i-3] {s} p (BSWAPL w) mem) + -> (MOVLstore [i-3] {s} p0 (BSWAPL w) mem) -(MOVBstoreidx1 [i] {s} p idx w - x2:(MOVBstoreidx1 [i-1] {s} p idx (SHRLconst [8] w) - x1:(MOVBstoreidx1 [i-2] {s} p idx (SHRLconst [16] w) - x0:(MOVBstoreidx1 [i-3] {s} p idx (SHRLconst [24] w) mem)))) - && x0.Uses == 1 - && x1.Uses == 1 - && x2.Uses == 1 - && clobber(x0, x1, x2) - -> (MOVLstoreidx1 [i-3] {s} p idx (BSWAPL w) mem) - -(MOVBstore [i] {s} p w - x6:(MOVBstore [i-1] {s} p (SHRQconst [8] w) - x5:(MOVBstore [i-2] {s} p (SHRQconst [16] w) - x4:(MOVBstore [i-3] {s} p (SHRQconst [24] w) - x3:(MOVBstore [i-4] {s} p (SHRQconst [32] w) - x2:(MOVBstore [i-5] {s} p (SHRQconst [40] w) - x1:(MOVBstore [i-6] {s} p (SHRQconst [48] w) - x0:(MOVBstore [i-7] {s} p (SHRQconst [56] w) mem)))))))) +(MOVBstore [i] {s} p7 w + x6:(MOVBstore [i-1] {s} p6 (SHRQconst [8] w) + x5:(MOVBstore [i-2] {s} p5 (SHRQconst [16] w) + x4:(MOVBstore [i-3] {s} p4 (SHRQconst [24] w) + x3:(MOVBstore [i-4] {s} p3 (SHRQconst [32] w) + x2:(MOVBstore [i-5] {s} p2 (SHRQconst [40] w) + x1:(MOVBstore [i-6] {s} p1 (SHRQconst [48] w) + x0:(MOVBstore [i-7] {s} p0 (SHRQconst [56] w) mem)))))))) && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 @@ -2037,165 +1772,99 @@ && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 + && same(p0, p1, 1) + && same(p1, p2, 1) + && same(p2, p3, 1) + && same(p3, p4, 1) + && same(p4, p5, 1) + && same(p5, p6, 1) + && same(p6, p7, 1) && clobber(x0, x1, x2, x3, x4, x5, x6) - -> (MOVQstore [i-7] {s} p (BSWAPQ w) mem) - -(MOVBstoreidx1 [i] {s} p idx w - x6:(MOVBstoreidx1 [i-1] {s} p idx (SHRQconst [8] w) - x5:(MOVBstoreidx1 [i-2] {s} p idx (SHRQconst [16] w) - x4:(MOVBstoreidx1 [i-3] {s} p idx (SHRQconst [24] w) - x3:(MOVBstoreidx1 [i-4] {s} p idx (SHRQconst [32] w) - x2:(MOVBstoreidx1 [i-5] {s} p idx (SHRQconst [40] w) - x1:(MOVBstoreidx1 [i-6] {s} p idx (SHRQconst [48] w) - x0:(MOVBstoreidx1 [i-7] {s} p idx (SHRQconst [56] w) mem)))))))) - && x0.Uses == 1 - && x1.Uses == 1 - && x2.Uses == 1 - && x3.Uses == 1 - && x4.Uses == 1 - && x5.Uses == 1 - && x6.Uses == 1 - && clobber(x0, x1, x2, x3, x4, x5, x6) - -> (MOVQstoreidx1 [i-7] {s} p idx (BSWAPQ w) mem) + -> (MOVQstore [i-7] {s} p0 (BSWAPQ w) mem) // Combine constant stores into larger (unaligned) stores. -(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) +(MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem)) && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) -(MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem)) + -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) +(MOVBstoreconst [a] {s} p1 x:(MOVBstoreconst [c] {s} p0 mem)) && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) -(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) + -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) +(MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem)) && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) -(MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem)) + -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) +(MOVWstoreconst [a] {s} p1 x:(MOVWstoreconst [c] {s} p0 mem)) && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) -(MOVLstoreconst [c] {s} p x:(MOVLstoreconst [a] {s} p mem)) + -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) +(MOVLstoreconst [c] {s} p1 x:(MOVLstoreconst [a] {s} p0 mem)) && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) - -> (MOVQstore [ValAndOff(a).Off()] {s} p (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) -(MOVLstoreconst [a] {s} p x:(MOVLstoreconst [c] {s} p mem)) + -> (MOVQstore [ValAndOff(a).Off()] {s} p0 (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) +(MOVLstoreconst [a] {s} p1 x:(MOVLstoreconst [c] {s} p0 mem)) && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) - -> (MOVQstore [ValAndOff(a).Off()] {s} p (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) -(MOVQstoreconst [c] {s} p x:(MOVQstoreconst [c2] {s} p mem)) + -> (MOVQstore [ValAndOff(a).Off()] {s} p0 (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) +(MOVQstoreconst [c] {s} p1 x:(MOVQstoreconst [c2] {s} p0 mem)) && config.useSSE && x.Uses == 1 + && same(p0, p1, 1) && ValAndOff(c2).Off() + 8 == ValAndOff(c).Off() && ValAndOff(c).Val() == 0 && ValAndOff(c2).Val() == 0 && clobber(x) - -> (MOVOstore [ValAndOff(c2).Off()] {s} p (MOVOconst [0]) mem) - -(MOVBstoreconstidx1 [c] {s} p i x:(MOVBstoreconstidx1 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() - && clobber(x) - -> (MOVWstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p i mem) -(MOVWstoreconstidx1 [c] {s} p i x:(MOVWstoreconstidx1 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() - && clobber(x) - -> (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p i mem) -(MOVLstoreconstidx1 [c] {s} p i x:(MOVLstoreconstidx1 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() - && clobber(x) - -> (MOVQstoreidx1 [ValAndOff(a).Off()] {s} p i (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) - -(MOVWstoreconstidx2 [c] {s} p i x:(MOVWstoreconstidx2 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() - && clobber(x) - -> (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p (SHLQconst [1] i) mem) -(MOVLstoreconstidx4 [c] {s} p i x:(MOVLstoreconstidx4 [a] {s} p i mem)) - && x.Uses == 1 - && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() - && clobber(x) - -> (MOVQstoreidx1 [ValAndOff(a).Off()] {s} p (SHLQconst [2] i) (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) + -> (MOVOstore [ValAndOff(c2).Off()] {s} p0 (MOVOconst [0]) mem) // Combine stores into larger (unaligned) stores. -(MOVBstore [i] {s} p (SHR(W|L|Q)const [8] w) x:(MOVBstore [i-1] {s} p w mem)) +(MOVBstore [i] {s} p1 (SHR(W|L|Q)const [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVWstore [i-1] {s} p w mem) -(MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHR(W|L|Q)const [8] w) mem)) + -> (MOVWstore [i-1] {s} p0 w mem) +(MOVBstore [i] {s} p1 w x:(MOVBstore [i+1] {s} p0 (SHR(W|L|Q)const [8] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVWstore [i] {s} p w mem) -(MOVBstore [i] {s} p (SHR(L|Q)const [j] w) x:(MOVBstore [i-1] {s} p w0:(SHR(L|Q)const [j-8] w) mem)) + -> (MOVWstore [i] {s} p0 w mem) +(MOVBstore [i] {s} p1 (SHR(L|Q)const [j] w) x:(MOVBstore [i-1] {s} p0 w0:(SHR(L|Q)const [j-8] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVWstore [i-1] {s} p w0 mem) -(MOVWstore [i] {s} p (SHR(L|Q)const [16] w) x:(MOVWstore [i-2] {s} p w mem)) + -> (MOVWstore [i-1] {s} p0 w0 mem) +(MOVWstore [i] {s} p1 (SHR(L|Q)const [16] w) x:(MOVWstore [i-2] {s} p0 w mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVLstore [i-2] {s} p w mem) -(MOVWstore [i] {s} p (SHR(L|Q)const [j] w) x:(MOVWstore [i-2] {s} p w0:(SHR(L|Q)const [j-16] w) mem)) + -> (MOVLstore [i-2] {s} p0 w mem) +(MOVWstore [i] {s} p1 (SHR(L|Q)const [j] w) x:(MOVWstore [i-2] {s} p0 w0:(SHR(L|Q)const [j-16] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVLstore [i-2] {s} p w0 mem) -(MOVLstore [i] {s} p (SHRQconst [32] w) x:(MOVLstore [i-4] {s} p w mem)) + -> (MOVLstore [i-2] {s} p0 w0 mem) +(MOVLstore [i] {s} p1 (SHRQconst [32] w) x:(MOVLstore [i-4] {s} p0 w mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVQstore [i-4] {s} p w mem) -(MOVLstore [i] {s} p (SHRQconst [j] w) x:(MOVLstore [i-4] {s} p w0:(SHRQconst [j-32] w) mem)) + -> (MOVQstore [i-4] {s} p0 w mem) +(MOVLstore [i] {s} p1 (SHRQconst [j] w) x:(MOVLstore [i-4] {s} p0 w0:(SHRQconst [j-32] w) mem)) && x.Uses == 1 + && same(p0, p1, 1) && clobber(x) - -> (MOVQstore [i-4] {s} p w0 mem) - -(MOVBstoreidx1 [i] {s} p idx (SHR(W|L|Q)const [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVWstoreidx1 [i-1] {s} p idx w mem) -(MOVBstoreidx1 [i] {s} p idx (SHR(L|Q)const [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHR(L|Q)const [j-8] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVWstoreidx1 [i-1] {s} p idx w0 mem) -(MOVWstoreidx1 [i] {s} p idx (SHR(L|Q)const [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p idx w mem) -(MOVWstoreidx1 [i] {s} p idx (SHR(L|Q)const [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHR(L|Q)const [j-16] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p idx w0 mem) -(MOVLstoreidx1 [i] {s} p idx (SHRQconst [32] w) x:(MOVLstoreidx1 [i-4] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVQstoreidx1 [i-4] {s} p idx w mem) -(MOVLstoreidx1 [i] {s} p idx (SHRQconst [j] w) x:(MOVLstoreidx1 [i-4] {s} p idx w0:(SHRQconst [j-32] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVQstoreidx1 [i-4] {s} p idx w0 mem) - -(MOVWstoreidx2 [i] {s} p idx (SHR(L|Q)const [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p (SHLQconst [1] idx) w mem) -(MOVWstoreidx2 [i] {s} p idx (SHRQconst [j] w) x:(MOVWstoreidx2 [i-2] {s} p idx w0:(SHRQconst [j-16] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVLstoreidx1 [i-2] {s} p (SHLQconst [1] idx) w0 mem) -(MOVLstoreidx4 [i] {s} p idx (SHRQconst [32] w) x:(MOVLstoreidx4 [i-4] {s} p idx w mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVQstoreidx1 [i-4] {s} p (SHLQconst [2] idx) w mem) -(MOVLstoreidx4 [i] {s} p idx (SHRQconst [j] w) x:(MOVLstoreidx4 [i-4] {s} p idx w0:(SHRQconst [j-32] w) mem)) - && x.Uses == 1 - && clobber(x) - -> (MOVQstoreidx1 [i-4] {s} p (SHLQconst [2] idx) w0 mem) + -> (MOVQstore [i-4] {s} p0 w0 mem) (MOVBstore [i] {s} p x1:(MOVBload [j] {s2} p2 mem) @@ -2320,41 +1989,6 @@ (BSFQ (ORQconst [1<<8] (MOVBQZX x))) -> (BSFQ (ORQconst [1<<8] x)) (BSFQ (ORQconst [1<<16] (MOVWQZX x))) -> (BSFQ (ORQconst [1<<16] x)) -// Simplify indexed loads/stores -(MOVBstoreidx1 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+c) -> (MOVBstore [i+c] {s} p w mem) -(MOVWstoreidx1 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+c) -> (MOVWstore [i+c] {s} p w mem) -(MOVLstoreidx1 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+c) -> (MOVLstore [i+c] {s} p w mem) -(MOVQstoreidx1 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+c) -> (MOVQstore [i+c] {s} p w mem) -(MOVWstoreidx2 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+2*c) -> (MOVWstore [i+2*c] {s} p w mem) -(MOVLstoreidx4 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+4*c) -> (MOVLstore [i+4*c] {s} p w mem) -(MOVLstoreidx8 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+8*c) -> (MOVLstore [i+8*c] {s} p w mem) -(MOVQstoreidx8 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+8*c) -> (MOVQstore [i+8*c] {s} p w mem) -(MOVSSstoreidx1 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+c) -> (MOVSSstore [i+c] {s} p w mem) -(MOVSSstoreidx4 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+4*c) -> (MOVSSstore [i+4*c] {s} p w mem) -(MOVSDstoreidx1 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+c) -> (MOVSDstore [i+c] {s} p w mem) -(MOVSDstoreidx8 [i] {s} p (MOVQconst [c]) w mem) && is32Bit(i+8*c) -> (MOVSDstore [i+8*c] {s} p w mem) -(MOVBloadidx1 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+c) -> (MOVBload [i+c] {s} p mem) -(MOVWloadidx1 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+c) -> (MOVWload [i+c] {s} p mem) -(MOVLloadidx1 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+c) -> (MOVLload [i+c] {s} p mem) -(MOVQloadidx1 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+c) -> (MOVQload [i+c] {s} p mem) -(MOVWloadidx2 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+2*c) -> (MOVWload [i+2*c] {s} p mem) -(MOVLloadidx4 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+4*c) -> (MOVLload [i+4*c] {s} p mem) -(MOVLloadidx8 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+8*c) -> (MOVLload [i+8*c] {s} p mem) -(MOVQloadidx8 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+8*c) -> (MOVQload [i+8*c] {s} p mem) -(MOVSSloadidx1 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+c) -> (MOVSSload [i+c] {s} p mem) -(MOVSSloadidx4 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+4*c) -> (MOVSSload [i+4*c] {s} p mem) -(MOVSDloadidx1 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+c) -> (MOVSDload [i+c] {s} p mem) -(MOVSDloadidx8 [i] {s} p (MOVQconst [c]) mem) && is32Bit(i+8*c) -> (MOVSDload [i+8*c] {s} p mem) - -// Combine consts into storeidx. -// Note that when c == 0, it takes more bytes to encode -// the immediate $0 than to zero a register and use it. -// We do the rewrite anyway, to minimize register pressure. -(MOVBstoreidx1 [off] {s} ptr idx (MOVLconst [c]) mem) && validValAndOff(int64(int8(c)), off) -> (MOVBstoreconstidx1 [makeValAndOff(int64(int8(c)), off)] {s} ptr idx mem) -(MOVWstoreidx(1|2) [off] {s} ptr idx (MOVLconst [c]) mem) && validValAndOff(int64(int16(c)), off) -> (MOVWstoreconstidx(1|2) [makeValAndOff(int64(int16(c)), off)] {s} ptr idx mem) -(MOVLstoreidx(1|4) [off] {s} ptr idx (MOVQconst [c]) mem) && validValAndOff(int64(int32(c)), off) -> (MOVLstoreconstidx(1|4) [makeValAndOff(int64(int32(c)), off)] {s} ptr idx mem) -(MOVQstoreidx(1|8) [off] {s} ptr idx (MOVQconst [c]) mem) && validValAndOff(c, off) -> (MOVQstoreconstidx(1|8) [makeValAndOff(c, off)] {s} ptr idx mem) - // Redundant sign/zero extensions // Note: see issue 21963. We have to make sure we use the right type on // the resulting extension (the outer type, not the inner type). diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index c384817d0c8..54fa54a477c 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -245,6 +245,7 @@ dd.ssa-prog { svg { cursor: default; outline: 1px solid #eee; + width: 100%; } body.darkmode { @@ -975,7 +976,7 @@ func (d *dotWriter) writeFuncSVG(w io.Writer, phase string, f *Func) { fmt.Println(err) return } - fmt.Fprint(pipe, `digraph "" { margin=0; size="4,40"; ranksep=.2; `) + fmt.Fprint(pipe, `digraph "" { margin=0; ranksep=.2; `) id := strings.Replace(phase, " ", "-", -1) fmt.Fprintf(pipe, `id="g_graph_%s";`, id) fmt.Fprintf(pipe, `node [style=filled,fillcolor=white,fontsize=16,fontname="Menlo,Times,serif",margin="0.01,0.03"];`) diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go index 4788f2d803a..12c2580c957 100644 --- a/src/cmd/compile/internal/ssa/prove.go +++ b/src/cmd/compile/internal/ssa/prove.go @@ -1305,9 +1305,9 @@ func isNonNegative(v *Value) bool { if !v.Type.IsInteger() { panic("isNonNegative bad type") } - if !v.Type.IsSigned() { - return true - } + // TODO: return true if !v.Type.IsSigned() + // SSA isn't type-safe enough to do that now (issue 37753). + // The checks below depend only on the pattern of bits. switch v.Op { case OpConst64: diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 238e2430963..b3e7d347797 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1247,3 +1247,43 @@ func read64(sym interface{}, off int64, byteorder binary.ByteOrder) uint64 { copy(buf, src) return byteorder.Uint64(buf) } + +// same reports whether x and y are the same value. +// It checks to a maximum depth of d, so it may report +// a false negative. +func same(x, y *Value, depth int) bool { + if x == y { + return true + } + if depth <= 0 { + return false + } + if x.Op != y.Op || x.Aux != y.Aux || x.AuxInt != y.AuxInt { + return false + } + if len(x.Args) != len(y.Args) { + return false + } + if opcodeTable[x.Op].commutative { + // Check exchanged ordering first. + for i, a := range x.Args { + j := i + if j < 2 { + j ^= 1 + } + b := y.Args[j] + if !same(a, b, depth-1) { + goto checkNormalOrder + } + } + return true + checkNormalOrder: + } + for i, a := range x.Args { + b := y.Args[i] + if !same(a, b, depth-1) { + return false + } + } + return true +} diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go index 8b2da94c135..e9a4b6601d8 100644 --- a/src/cmd/compile/internal/ssa/rewrite386.go +++ b/src/cmd/compile/internal/ssa/rewrite386.go @@ -18,16 +18,10 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386ADDLconst(v) case Op386ADDLconstmodify: return rewriteValue386_Op386ADDLconstmodify(v) - case Op386ADDLconstmodifyidx4: - return rewriteValue386_Op386ADDLconstmodifyidx4(v) case Op386ADDLload: return rewriteValue386_Op386ADDLload(v) - case Op386ADDLloadidx4: - return rewriteValue386_Op386ADDLloadidx4(v) case Op386ADDLmodify: return rewriteValue386_Op386ADDLmodify(v) - case Op386ADDLmodifyidx4: - return rewriteValue386_Op386ADDLmodifyidx4(v) case Op386ADDSD: return rewriteValue386_Op386ADDSD(v) case Op386ADDSDload: @@ -42,16 +36,10 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386ANDLconst(v) case Op386ANDLconstmodify: return rewriteValue386_Op386ANDLconstmodify(v) - case Op386ANDLconstmodifyidx4: - return rewriteValue386_Op386ANDLconstmodifyidx4(v) case Op386ANDLload: return rewriteValue386_Op386ANDLload(v) - case Op386ANDLloadidx4: - return rewriteValue386_Op386ANDLloadidx4(v) case Op386ANDLmodify: return rewriteValue386_Op386ANDLmodify(v) - case Op386ANDLmodifyidx4: - return rewriteValue386_Op386ANDLmodifyidx4(v) case Op386CMPB: return rewriteValue386_Op386CMPB(v) case Op386CMPBconst: @@ -96,62 +84,28 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386MOVBLZX(v) case Op386MOVBload: return rewriteValue386_Op386MOVBload(v) - case Op386MOVBloadidx1: - return rewriteValue386_Op386MOVBloadidx1(v) case Op386MOVBstore: return rewriteValue386_Op386MOVBstore(v) case Op386MOVBstoreconst: return rewriteValue386_Op386MOVBstoreconst(v) - case Op386MOVBstoreconstidx1: - return rewriteValue386_Op386MOVBstoreconstidx1(v) - case Op386MOVBstoreidx1: - return rewriteValue386_Op386MOVBstoreidx1(v) case Op386MOVLload: return rewriteValue386_Op386MOVLload(v) - case Op386MOVLloadidx1: - return rewriteValue386_Op386MOVLloadidx1(v) - case Op386MOVLloadidx4: - return rewriteValue386_Op386MOVLloadidx4(v) case Op386MOVLstore: return rewriteValue386_Op386MOVLstore(v) case Op386MOVLstoreconst: return rewriteValue386_Op386MOVLstoreconst(v) - case Op386MOVLstoreconstidx1: - return rewriteValue386_Op386MOVLstoreconstidx1(v) - case Op386MOVLstoreconstidx4: - return rewriteValue386_Op386MOVLstoreconstidx4(v) - case Op386MOVLstoreidx1: - return rewriteValue386_Op386MOVLstoreidx1(v) - case Op386MOVLstoreidx4: - return rewriteValue386_Op386MOVLstoreidx4(v) case Op386MOVSDconst: return rewriteValue386_Op386MOVSDconst(v) case Op386MOVSDload: return rewriteValue386_Op386MOVSDload(v) - case Op386MOVSDloadidx1: - return rewriteValue386_Op386MOVSDloadidx1(v) - case Op386MOVSDloadidx8: - return rewriteValue386_Op386MOVSDloadidx8(v) case Op386MOVSDstore: return rewriteValue386_Op386MOVSDstore(v) - case Op386MOVSDstoreidx1: - return rewriteValue386_Op386MOVSDstoreidx1(v) - case Op386MOVSDstoreidx8: - return rewriteValue386_Op386MOVSDstoreidx8(v) case Op386MOVSSconst: return rewriteValue386_Op386MOVSSconst(v) case Op386MOVSSload: return rewriteValue386_Op386MOVSSload(v) - case Op386MOVSSloadidx1: - return rewriteValue386_Op386MOVSSloadidx1(v) - case Op386MOVSSloadidx4: - return rewriteValue386_Op386MOVSSloadidx4(v) case Op386MOVSSstore: return rewriteValue386_Op386MOVSSstore(v) - case Op386MOVSSstoreidx1: - return rewriteValue386_Op386MOVSSstoreidx1(v) - case Op386MOVSSstoreidx4: - return rewriteValue386_Op386MOVSSstoreidx4(v) case Op386MOVWLSX: return rewriteValue386_Op386MOVWLSX(v) case Op386MOVWLSXload: @@ -160,30 +114,16 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386MOVWLZX(v) case Op386MOVWload: return rewriteValue386_Op386MOVWload(v) - case Op386MOVWloadidx1: - return rewriteValue386_Op386MOVWloadidx1(v) - case Op386MOVWloadidx2: - return rewriteValue386_Op386MOVWloadidx2(v) case Op386MOVWstore: return rewriteValue386_Op386MOVWstore(v) case Op386MOVWstoreconst: return rewriteValue386_Op386MOVWstoreconst(v) - case Op386MOVWstoreconstidx1: - return rewriteValue386_Op386MOVWstoreconstidx1(v) - case Op386MOVWstoreconstidx2: - return rewriteValue386_Op386MOVWstoreconstidx2(v) - case Op386MOVWstoreidx1: - return rewriteValue386_Op386MOVWstoreidx1(v) - case Op386MOVWstoreidx2: - return rewriteValue386_Op386MOVWstoreidx2(v) case Op386MULL: return rewriteValue386_Op386MULL(v) case Op386MULLconst: return rewriteValue386_Op386MULLconst(v) case Op386MULLload: return rewriteValue386_Op386MULLload(v) - case Op386MULLloadidx4: - return rewriteValue386_Op386MULLloadidx4(v) case Op386MULSD: return rewriteValue386_Op386MULSD(v) case Op386MULSDload: @@ -202,16 +142,10 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386ORLconst(v) case Op386ORLconstmodify: return rewriteValue386_Op386ORLconstmodify(v) - case Op386ORLconstmodifyidx4: - return rewriteValue386_Op386ORLconstmodifyidx4(v) case Op386ORLload: return rewriteValue386_Op386ORLload(v) - case Op386ORLloadidx4: - return rewriteValue386_Op386ORLloadidx4(v) case Op386ORLmodify: return rewriteValue386_Op386ORLmodify(v) - case Op386ORLmodifyidx4: - return rewriteValue386_Op386ORLmodifyidx4(v) case Op386ROLBconst: return rewriteValue386_Op386ROLBconst(v) case Op386ROLLconst: @@ -278,12 +212,8 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386SUBLconst(v) case Op386SUBLload: return rewriteValue386_Op386SUBLload(v) - case Op386SUBLloadidx4: - return rewriteValue386_Op386SUBLloadidx4(v) case Op386SUBLmodify: return rewriteValue386_Op386SUBLmodify(v) - case Op386SUBLmodifyidx4: - return rewriteValue386_Op386SUBLmodifyidx4(v) case Op386SUBSD: return rewriteValue386_Op386SUBSD(v) case Op386SUBSDload: @@ -298,16 +228,10 @@ func rewriteValue386(v *Value) bool { return rewriteValue386_Op386XORLconst(v) case Op386XORLconstmodify: return rewriteValue386_Op386XORLconstmodify(v) - case Op386XORLconstmodifyidx4: - return rewriteValue386_Op386XORLconstmodifyidx4(v) case Op386XORLload: return rewriteValue386_Op386XORLload(v) - case Op386XORLloadidx4: - return rewriteValue386_Op386XORLloadidx4(v) case Op386XORLmodify: return rewriteValue386_Op386XORLmodify(v) - case Op386XORLmodifyidx4: - return rewriteValue386_Op386XORLmodifyidx4(v) case OpAdd16: v.Op = Op386ADDL return true @@ -1042,32 +966,6 @@ func rewriteValue386_Op386ADDL(v *Value) bool { } break } - // match: (ADDL x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: canMergeLoadClobber(v, l, x) && clobber(l) - // result: (ADDLloadidx4 x [off] {sym} ptr idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - l := v_1 - if l.Op != Op386MOVLloadidx4 { - continue - } - off := l.AuxInt - sym := l.Aux - mem := l.Args[2] - ptr := l.Args[0] - idx := l.Args[1] - if !(canMergeLoadClobber(v, l, x) && clobber(l)) { - continue - } - v.reset(Op386ADDLloadidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(x, ptr, idx, mem) - return true - } - break - } // match: (ADDL x (NEGL y)) // result: (SUBL x y) for { @@ -1316,81 +1214,6 @@ func rewriteValue386_Op386ADDLconstmodify(v *Value) bool { } return false } -func rewriteValue386_Op386ADDLconstmodifyidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ADDLconstmodifyidx4 [valoff1] {sym} (ADDLconst [off2] base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) - // result: (ADDLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2)) { - break - } - v.reset(Op386ADDLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (ADDLconstmodifyidx4 [valoff1] {sym} base (ADDLconst [off2] idx) mem) - // cond: ValAndOff(valoff1).canAdd(off2*4) - // result: (ADDLconstmodifyidx4 [ValAndOff(valoff1).add(off2*4)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2 * 4)) { - break - } - v.reset(Op386ADDLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2 * 4) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (ADDLconstmodifyidx4 [valoff1] {sym1} (LEAL [off2] {sym2} base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ADDLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base idx mem) - for { - valoff1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ADDLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(base, idx, mem) - return true - } - return false -} func rewriteValue386_Op386ADDLload(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -1442,109 +1265,6 @@ func rewriteValue386_Op386ADDLload(v *Value) bool { v.AddArg3(val, base, mem) return true } - // match: (ADDLload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (ADDLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL4 { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - idx := v_1.Args[1] - ptr := v_1.Args[0] - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386ADDLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386ADDLloadidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ADDLloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) - // cond: is32Bit(off1+off2) - // result: (ADDLloadidx4 [off1+off2] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386ADDLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (ADDLloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) - // cond: is32Bit(off1+off2*4) - // result: (ADDLloadidx4 [off1+off2*4] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - base := v_1 - if v_2.Op != Op386ADDLconst { - break - } - off2 := v_2.AuxInt - idx := v_2.Args[0] - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386ADDLloadidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (ADDLloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ADDLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ADDLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, base, idx, mem) - return true - } return false } func rewriteValue386_Op386ADDLmodify(v *Value) bool { @@ -1600,107 +1320,6 @@ func rewriteValue386_Op386ADDLmodify(v *Value) bool { } return false } -func rewriteValue386_Op386ADDLmodifyidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ADDLmodifyidx4 [off1] {sym} (ADDLconst [off2] base) idx val mem) - // cond: is32Bit(off1+off2) - // result: (ADDLmodifyidx4 [off1+off2] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386ADDLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ADDLmodifyidx4 [off1] {sym} base (ADDLconst [off2] idx) val mem) - // cond: is32Bit(off1+off2*4) - // result: (ADDLmodifyidx4 [off1+off2*4] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386ADDLmodifyidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ADDLmodifyidx4 [off1] {sym1} (LEAL [off2] {sym2} base) idx val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ADDLmodifyidx4 [off1+off2] {mergeSym(sym1,sym2)} base idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ADDLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ADDLmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(c,off) - // result: (ADDLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != Op386MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(c, off)) { - break - } - v.reset(Op386ADDLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_Op386ADDSD(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -1915,32 +1534,6 @@ func rewriteValue386_Op386ANDL(v *Value) bool { } break } - // match: (ANDL x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: canMergeLoadClobber(v, l, x) && clobber(l) - // result: (ANDLloadidx4 x [off] {sym} ptr idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - l := v_1 - if l.Op != Op386MOVLloadidx4 { - continue - } - off := l.AuxInt - sym := l.Aux - mem := l.Args[2] - ptr := l.Args[0] - idx := l.Args[1] - if !(canMergeLoadClobber(v, l, x) && clobber(l)) { - continue - } - v.reset(Op386ANDLloadidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(x, ptr, idx, mem) - return true - } - break - } // match: (ANDL x x) // result: x for { @@ -2057,81 +1650,6 @@ func rewriteValue386_Op386ANDLconstmodify(v *Value) bool { } return false } -func rewriteValue386_Op386ANDLconstmodifyidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ANDLconstmodifyidx4 [valoff1] {sym} (ADDLconst [off2] base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) - // result: (ANDLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2)) { - break - } - v.reset(Op386ANDLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (ANDLconstmodifyidx4 [valoff1] {sym} base (ADDLconst [off2] idx) mem) - // cond: ValAndOff(valoff1).canAdd(off2*4) - // result: (ANDLconstmodifyidx4 [ValAndOff(valoff1).add(off2*4)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2 * 4)) { - break - } - v.reset(Op386ANDLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2 * 4) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (ANDLconstmodifyidx4 [valoff1] {sym1} (LEAL [off2] {sym2} base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ANDLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base idx mem) - for { - valoff1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ANDLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(base, idx, mem) - return true - } - return false -} func rewriteValue386_Op386ANDLload(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -2183,109 +1701,6 @@ func rewriteValue386_Op386ANDLload(v *Value) bool { v.AddArg3(val, base, mem) return true } - // match: (ANDLload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (ANDLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL4 { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - idx := v_1.Args[1] - ptr := v_1.Args[0] - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386ANDLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386ANDLloadidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ANDLloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) - // cond: is32Bit(off1+off2) - // result: (ANDLloadidx4 [off1+off2] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386ANDLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (ANDLloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) - // cond: is32Bit(off1+off2*4) - // result: (ANDLloadidx4 [off1+off2*4] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - base := v_1 - if v_2.Op != Op386ADDLconst { - break - } - off2 := v_2.AuxInt - idx := v_2.Args[0] - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386ANDLloadidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (ANDLloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ANDLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ANDLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, base, idx, mem) - return true - } return false } func rewriteValue386_Op386ANDLmodify(v *Value) bool { @@ -2341,107 +1756,6 @@ func rewriteValue386_Op386ANDLmodify(v *Value) bool { } return false } -func rewriteValue386_Op386ANDLmodifyidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ANDLmodifyidx4 [off1] {sym} (ADDLconst [off2] base) idx val mem) - // cond: is32Bit(off1+off2) - // result: (ANDLmodifyidx4 [off1+off2] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386ANDLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ANDLmodifyidx4 [off1] {sym} base (ADDLconst [off2] idx) val mem) - // cond: is32Bit(off1+off2*4) - // result: (ANDLmodifyidx4 [off1+off2*4] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386ANDLmodifyidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ANDLmodifyidx4 [off1] {sym1} (LEAL [off2] {sym2} base) idx val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ANDLmodifyidx4 [off1+off2] {mergeSym(sym1,sym2)} base idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ANDLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ANDLmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(c,off) - // result: (ANDLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != Op386MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(c, off)) { - break - } - v.reset(Op386ANDLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_Op386CMPB(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -3768,6 +3082,80 @@ func rewriteValue386_Op386LEAL1(v *Value) bool { } break } + // match: (LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != Op386LEAL1 { + continue + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[1] + if y != v_1.Args[0] || !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + continue + } + v.reset(Op386LEAL2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg2(x, y) + return true + } + break + } + // match: (LEAL1 [off1] {sym1} x (LEAL1 [off2] {sym2} x y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL2 [off1+off2] {mergeSym(sym1, sym2)} y x) + for { + off1 := v.AuxInt + sym1 := v.Aux + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != Op386LEAL1 { + continue + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { + if x != v_1_0 { + continue + } + y := v_1_1 + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + continue + } + v.reset(Op386LEAL2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg2(y, x) + return true + } + } + break + } + // match: (LEAL1 [0] x y) + // cond: v.Aux == nil + // result: (ADDL x y) + for { + if v.AuxInt != 0 { + break + } + x := v_0 + y := v_1 + if !(v.Aux == nil) { + break + } + v.reset(Op386ADDL) + v.AddArg2(x, y) + return true + } return false } func rewriteValue386_Op386LEAL2(v *Value) bool { @@ -3869,6 +3257,28 @@ func rewriteValue386_Op386LEAL2(v *Value) bool { v.AddArg2(x, y) return true } + // match: (LEAL2 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) + // cond: is32Bit(off1+2*off2) && sym2 == nil + // result: (LEAL4 [off1+2*off2] {sym1} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + x := v_0 + if v_1.Op != Op386LEAL1 { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[1] + if y != v_1.Args[0] || !(is32Bit(off1+2*off2) && sym2 == nil) { + break + } + v.reset(Op386LEAL4) + v.AuxInt = off1 + 2*off2 + v.Aux = sym1 + v.AddArg2(x, y) + return true + } return false } func rewriteValue386_Op386LEAL4(v *Value) bool { @@ -3954,6 +3364,28 @@ func rewriteValue386_Op386LEAL4(v *Value) bool { v.AddArg2(x, y) return true } + // match: (LEAL4 [off1] {sym1} x (LEAL1 [off2] {sym2} y y)) + // cond: is32Bit(off1+4*off2) && sym2 == nil + // result: (LEAL8 [off1+4*off2] {sym1} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + x := v_0 + if v_1.Op != Op386LEAL1 { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[1] + if y != v_1.Args[0] || !(is32Bit(off1+4*off2) && sym2 == nil) { + break + } + v.reset(Op386LEAL8) + v.AuxInt = off1 + 4*off2 + v.Aux = sym1 + v.AddArg2(x, y) + return true + } return false } func rewriteValue386_Op386LEAL8(v *Value) bool { @@ -4146,30 +3578,6 @@ func rewriteValue386_Op386MOVBLZX(v *Value) bool { v0.AddArg2(ptr, mem) return true } - // match: (MOVBLZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVBloadidx1 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != Op386MOVBloadidx1 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, Op386MOVBloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } // match: (MOVBLZX (ANDLconst [c] x)) // result: (ANDLconst [c & 0xff] x) for { @@ -4254,55 +3662,117 @@ func rewriteValue386_Op386MOVBload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVBload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVBloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVBload [i0] {s0} l:(LEAL1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAL1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(Op386MOVBloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(Op386MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVBload [off] {sym} (ADDL ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVBloadidx1 [off] {sym} ptr idx mem) + // match: (MOVBload [i0] {s0} l:(LEAL2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAL2 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL2 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVBloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(Op386MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVBload [i0] {s0} l:(LEAL4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAL4 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL4 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVBload [i0] {s0} l:(LEAL8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAL8 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVBload [off] {sym} (SB) _) // cond: symIsRO(sym) @@ -4319,54 +3789,6 @@ func rewriteValue386_Op386MOVBload(v *Value) bool { } return false } -func rewriteValue386_Op386MOVBloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != Op386ADDLconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVBloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386ADDLconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVBloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - return false -} func rewriteValue386_Op386MOVBstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -4473,65 +3895,13 @@ func rewriteValue386_Op386MOVBstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVBstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVBstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVBstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVBstore [off] {sym} (ADDL ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVBstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVBstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVBstore [i] {s} p (SHRWconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w mem) + // match: (MOVBstore [i] {s} p1 (SHRWconst [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != Op386SHRWconst || v_1.AuxInt != 8 { break } @@ -4541,22 +3911,23 @@ func rewriteValue386_Op386MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w mem) + // match: (MOVBstore [i] {s} p1 (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != Op386SHRLconst || v_1.AuxInt != 8 { break } @@ -4566,74 +3937,71 @@ func rewriteValue386_Op386MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p w x:(MOVBstore {s} [i+1] p (SHRWconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i] {s} p w mem) + // match: (MOVBstore [i] {s} p1 w x:(MOVBstore {s} [i+1] p0 (SHRWconst [8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 w := v_1 x := v_2 if x.Op != Op386MOVBstore || x.AuxInt != i+1 || x.Aux != s { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] x_1 := x.Args[1] - if x_1.Op != Op386SHRWconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) { + if x_1.Op != Op386SHRWconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstore) v.AuxInt = i v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p w x:(MOVBstore {s} [i+1] p (SHRLconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i] {s} p w mem) + // match: (MOVBstore [i] {s} p1 w x:(MOVBstore {s} [i+1] p0 (SHRLconst [8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 w := v_1 x := v_2 if x.Op != Op386MOVBstore || x.AuxInt != i+1 || x.Aux != s { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] x_1 := x.Args[1] - if x_1.Op != Op386SHRLconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) { + if x_1.Op != Op386SHRLconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstore) v.AuxInt = i v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w0 mem) + // match: (MOVBstore [i] {s} p1 (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p0 w0:(SHRLconst [j-8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != Op386SHRLconst { break } @@ -4644,17 +4012,131 @@ func rewriteValue386_Op386MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != Op386SHRLconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != Op386SHRLconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) + return true + } + // match: (MOVBstore [i0] {s0} l:(LEAL1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAL1 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL1 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVBstore [i0] {s0} l:(LEAL2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAL2 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL2 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVBstore [i0] {s0} l:(LEAL4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAL4 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL4 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVBstore [i0] {s0} l:(LEAL8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAL8 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } return false @@ -4707,53 +4189,13 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVBstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVBstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVBstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVBstoreconst [x] {sym} (ADDL ptr idx) mem) - // result: (MOVBstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(Op386MOVBstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) + // match: (MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x) + // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) for { c := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != Op386MOVBstoreconst { break @@ -4763,22 +4205,23 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } - // match: (MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) + // match: (MOVBstoreconst [a] {s} p1 x:(MOVBstoreconst [c] {s} p0 mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x) + // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) for { a := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != Op386MOVBstoreconst { break @@ -4788,308 +4231,18 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVWstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } return false } -func rewriteValue386_Op386MOVBstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) - // result: (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVBstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVBstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) - // result: (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVBstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVBstoreconstidx1 [c] {s} p i x:(MOVBstoreconstidx1 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - // result: (MOVWstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p i mem) - for { - c := v.AuxInt - s := v.Aux - p := v_0 - i := v_1 - x := v_2 - if x.Op != Op386MOVBstoreconstidx1 { - break - } - a := x.AuxInt - if x.Aux != s { - break - } - mem := x.Args[2] - if p != x.Args[0] || i != x.Args[1] || !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { - break - } - v.reset(Op386MOVWstoreconstidx1) - v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) - v.Aux = s - v.AddArg3(p, i, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVBstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != Op386ADDLconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVBstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386ADDLconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVBstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRLconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRLconst || v_2.AuxInt != 8 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRWconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRWconst || v_2.AuxInt != 8 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx w x:(MOVBstoreidx1 [i+1] {s} p idx (SHRLconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - w := v_2 - x := v_3 - if x.Op != Op386MOVBstoreidx1 || x.AuxInt != i+1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - x_2 := x.Args[2] - if x_2.Op != Op386SHRLconst || x_2.AuxInt != 8 || w != x_2.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = i - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx w x:(MOVBstoreidx1 [i+1] {s} p idx (SHRWconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - w := v_2 - x := v_3 - if x.Op != Op386MOVBstoreidx1 || x.AuxInt != i+1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - x_2 := x.Args[2] - if x_2.Op != Op386SHRWconst || x_2.AuxInt != 8 || w != x_2.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = i - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHRLconst [j-8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRLconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != Op386SHRLconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - return false -} func rewriteValue386_Op386MOVLload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -5158,78 +4311,117 @@ func rewriteValue386_Op386MOVLload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVLload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAL1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAL1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(Op386MOVLloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(Op386MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVLload [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAL2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAL2 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL4 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(Op386MOVLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(Op386MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVLload [off] {sym} (ADDL ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVLloadidx1 [off] {sym} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAL4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAL4 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL4 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVLloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(Op386MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVLload [i0] {s0} l:(LEAL8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAL8 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVLload [off] {sym} (SB) _) // cond: symIsRO(sym) @@ -5246,116 +4438,6 @@ func rewriteValue386_Op386MOVLload(v *Value) bool { } return false } -func rewriteValue386_Op386MOVLloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLloadidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) - // result: (MOVLloadidx4 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386SHLLconst || v_1.AuxInt != 2 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVLloadidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != Op386ADDLconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVLloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386ADDLconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVLloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVLloadidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVLloadidx4 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVLloadidx4) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVLloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVLloadidx4) - v.AuxInt = int64(int32(c + 4*d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_Op386MOVLstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -5428,82 +4510,6 @@ func rewriteValue386_Op386MOVLstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVLstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVLstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstore [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL4 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVLstoreidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstore [off] {sym} (ADDL ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVLstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVLstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } // match: (MOVLstore {sym} [off] ptr y:(ADDLload x [off] {sym} ptr mem) mem) // cond: y.Uses==1 && clobber(y) // result: (ADDLmodify [off] {sym} ptr x mem) @@ -5862,6 +4868,122 @@ func rewriteValue386_Op386MOVLstore(v *Value) bool { v.AddArg2(ptr, mem) return true } + // match: (MOVLstore [i0] {s0} l:(LEAL1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAL1 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL1 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVLstore [i0] {s0} l:(LEAL2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAL2 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL2 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVLstore [i0] {s0} l:(LEAL4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAL4 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL4 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVLstore [i0] {s0} l:(LEAL8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAL8 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } return false } func rewriteValue386_Op386MOVLstoreconst(v *Value) bool { @@ -5912,658 +5034,6 @@ func rewriteValue386_Op386MOVLstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVLstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVLstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVLstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconst [x] {sym1} (LEAL4 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVLstoreconstidx4 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL4 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVLstoreconstidx4) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconst [x] {sym} (ADDL ptr idx) mem) - // result: (MOVLstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(Op386MOVLstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVLstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLstoreconstidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) - // result: (MOVLstoreconstidx4 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386SHLLconst || v_1.AuxInt != 2 { - break - } - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVLstoreconstidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) - // result: (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVLstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) - // result: (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVLstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVLstoreconstidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLstoreconstidx4 [x] {sym} (ADDLconst [c] ptr) idx mem) - // result: (MOVLstoreconstidx4 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVLstoreconstidx4) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconstidx4 [x] {sym} ptr (ADDLconst [c] idx) mem) - // result: (MOVLstoreconstidx4 [ValAndOff(x).add(4*c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVLstoreconstidx4) - v.AuxInt = ValAndOff(x).add(4 * c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVLstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLstoreidx1 [c] {sym} ptr (SHLLconst [2] idx) val mem) - // result: (MOVLstoreidx4 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386SHLLconst || v_1.AuxInt != 2 { - continue - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVLstoreidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != Op386ADDLconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVLstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386ADDLconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVLstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVLstoreidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVLstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVLstoreidx4) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVLstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVLstoreidx4) - v.AuxInt = int64(int32(c + 4*d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ADDLloadidx4 x [off] {sym} ptr idx mem) mem) - // cond: y.Uses==1 && clobber(y) - // result: (ADDLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ADDLloadidx4 || y.AuxInt != off || y.Aux != sym { - break - } - mem := y.Args[3] - x := y.Args[0] - if ptr != y.Args[1] || idx != y.Args[2] || mem != v_3 || !(y.Uses == 1 && clobber(y)) { - break - } - v.reset(Op386ADDLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ANDLloadidx4 x [off] {sym} ptr idx mem) mem) - // cond: y.Uses==1 && clobber(y) - // result: (ANDLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ANDLloadidx4 || y.AuxInt != off || y.Aux != sym { - break - } - mem := y.Args[3] - x := y.Args[0] - if ptr != y.Args[1] || idx != y.Args[2] || mem != v_3 || !(y.Uses == 1 && clobber(y)) { - break - } - v.reset(Op386ANDLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ORLloadidx4 x [off] {sym} ptr idx mem) mem) - // cond: y.Uses==1 && clobber(y) - // result: (ORLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ORLloadidx4 || y.AuxInt != off || y.Aux != sym { - break - } - mem := y.Args[3] - x := y.Args[0] - if ptr != y.Args[1] || idx != y.Args[2] || mem != v_3 || !(y.Uses == 1 && clobber(y)) { - break - } - v.reset(Op386ORLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(XORLloadidx4 x [off] {sym} ptr idx mem) mem) - // cond: y.Uses==1 && clobber(y) - // result: (XORLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386XORLloadidx4 || y.AuxInt != off || y.Aux != sym { - break - } - mem := y.Args[3] - x := y.Args[0] - if ptr != y.Args[1] || idx != y.Args[2] || mem != v_3 || !(y.Uses == 1 && clobber(y)) { - break - } - v.reset(Op386XORLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ADDL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) - // result: (ADDLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ADDL { - break - } - _ = y.Args[1] - y_0 := y.Args[0] - y_1 := y.Args[1] - for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 { - l := y_0 - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - continue - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] { - continue - } - x := y_1 - if mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) { - continue - } - v.reset(Op386ADDLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - break - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(SUBL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) - // result: (SUBLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386SUBL { - break - } - x := y.Args[1] - l := y.Args[0] - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - break - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] || mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) { - break - } - v.reset(Op386SUBLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ANDL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) - // result: (ANDLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ANDL { - break - } - _ = y.Args[1] - y_0 := y.Args[0] - y_1 := y.Args[1] - for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 { - l := y_0 - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - continue - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] { - continue - } - x := y_1 - if mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) { - continue - } - v.reset(Op386ANDLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - break - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ORL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) - // result: (ORLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ORL { - break - } - _ = y.Args[1] - y_0 := y.Args[0] - y_1 := y.Args[1] - for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 { - l := y_0 - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - continue - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] { - continue - } - x := y_1 - if mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) { - continue - } - v.reset(Op386ORLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - break - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(XORL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) - // result: (XORLmodifyidx4 [off] {sym} ptr idx x mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386XORL { - break - } - _ = y.Args[1] - y_0 := y.Args[0] - y_1 := y.Args[1] - for _i0 := 0; _i0 <= 1; _i0, y_0, y_1 = _i0+1, y_1, y_0 { - l := y_0 - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - continue - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] { - continue - } - x := y_1 - if mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l)) { - continue - } - v.reset(Op386XORLmodifyidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, x, mem) - return true - } - break - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ADDLconst [c] l:(MOVLloadidx4 [off] {sym} ptr idx mem)) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(c,off) - // result: (ADDLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ADDLconst { - break - } - c := y.AuxInt - l := y.Args[0] - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - break - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] || mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(c, off)) { - break - } - v.reset(Op386ADDLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ANDLconst [c] l:(MOVLloadidx4 [off] {sym} ptr idx mem)) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(c,off) - // result: (ANDLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ANDLconst { - break - } - c := y.AuxInt - l := y.Args[0] - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - break - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] || mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(c, off)) { - break - } - v.reset(Op386ANDLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(ORLconst [c] l:(MOVLloadidx4 [off] {sym} ptr idx mem)) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(c,off) - // result: (ORLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386ORLconst { - break - } - c := y.AuxInt - l := y.Args[0] - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - break - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] || mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(c, off)) { - break - } - v.reset(Op386ORLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreidx4 {sym} [off] ptr idx y:(XORLconst [c] l:(MOVLloadidx4 [off] {sym} ptr idx mem)) mem) - // cond: y.Uses==1 && l.Uses==1 && clobber(y, l) && validValAndOff(c,off) - // result: (XORLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - y := v_2 - if y.Op != Op386XORLconst { - break - } - c := y.AuxInt - l := y.Args[0] - if l.Op != Op386MOVLloadidx4 || l.AuxInt != off || l.Aux != sym { - break - } - mem := l.Args[2] - if ptr != l.Args[0] || idx != l.Args[1] || mem != v_3 || !(y.Uses == 1 && l.Uses == 1 && clobber(y, l) && validValAndOff(c, off)) { - break - } - v.reset(Op386XORLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } return false } func rewriteValue386_Op386MOVSDconst(v *Value) bool { @@ -6634,163 +5104,6 @@ func rewriteValue386_Op386MOVSDload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVSDload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSDloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDload [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL8 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSDloadidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDload [off] {sym} (ADDL ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVSDloadidx1 [off] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVSDloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVSDloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVSDloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVSDloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVSDloadidx8(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVSDloadidx8 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVSDloadidx8) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVSDloadidx8 [int64(int32(c+8*d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVSDloadidx8) - v.AuxInt = int64(int32(c + 8*d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } return false } func rewriteValue386_Op386MOVSDstore(v *Value) bool { @@ -6844,172 +5157,6 @@ func rewriteValue386_Op386MOVSDstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVSDstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSDstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstore [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL8 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSDstoreidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstore [off] {sym} (ADDL ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVSDstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVSDstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVSDstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVSDstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVSDstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVSDstoreidx8(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVSDstoreidx8 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVSDstoreidx8) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVSDstoreidx8) - v.AuxInt = int64(int32(c + 8*d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } return false } func rewriteValue386_Op386MOVSSconst(v *Value) bool { @@ -7080,163 +5227,6 @@ func rewriteValue386_Op386MOVSSload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVSSload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSSloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSload [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL4 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSSloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSload [off] {sym} (ADDL ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVSSloadidx1 [off] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVSSloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVSSloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVSSloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVSSloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVSSloadidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVSSloadidx4 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVSSloadidx4) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVSSloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVSSloadidx4) - v.AuxInt = int64(int32(c + 4*d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } return false } func rewriteValue386_Op386MOVSSstore(v *Value) bool { @@ -7290,172 +5280,6 @@ func rewriteValue386_Op386MOVSSstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVSSstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSSstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstore [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL4 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVSSstoreidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstore [off] {sym} (ADDL ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVSSstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVSSstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVSSstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVSSstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVSSstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVSSstoreidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVSSstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVSSstoreidx4) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVSSstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVSSstoreidx4) - v.AuxInt = int64(int32(c + 4*d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } return false } func rewriteValue386_Op386MOVWLSX(v *Value) bool { @@ -7579,54 +5403,6 @@ func rewriteValue386_Op386MOVWLZX(v *Value) bool { v0.AddArg2(ptr, mem) return true } - // match: (MOVWLZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVWloadidx1 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != Op386MOVWloadidx1 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, Op386MOVWloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWLZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVWloadidx2 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != Op386MOVWloadidx2 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, Op386MOVWloadidx2, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } // match: (MOVWLZX (ANDLconst [c] x)) // result: (ANDLconst [c & 0xffff] x) for { @@ -7711,78 +5487,117 @@ func rewriteValue386_Op386MOVWload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVWload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVWload [i0] {s0} l:(LEAL1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAL1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(Op386MOVWloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(Op386MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVWload [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWloadidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVWload [i0] {s0} l:(LEAL2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAL2 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL2 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(Op386MOVWloadidx2) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(Op386MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVWload [off] {sym} (ADDL ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVWloadidx1 [off] {sym} ptr idx mem) + // match: (MOVWload [i0] {s0} l:(LEAL4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAL4 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL4 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVWloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(Op386MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVWload [i0] {s0} l:(LEAL8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAL8 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVWload [off] {sym} (SB) _) // cond: symIsRO(sym) @@ -7799,116 +5614,6 @@ func rewriteValue386_Op386MOVWload(v *Value) bool { } return false } -func rewriteValue386_Op386MOVWloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWloadidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) - // result: (MOVWloadidx2 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386SHLLconst || v_1.AuxInt != 1 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVWloadidx2) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != Op386ADDLconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVWloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386ADDLconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVWloadidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - return false -} -func rewriteValue386_Op386MOVWloadidx2(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) - // result: (MOVWloadidx2 [int64(int32(c+d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVWloadidx2) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) - // result: (MOVWloadidx2 [int64(int32(c+2*d))] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVWloadidx2) - v.AuxInt = int64(int32(c + 2*d)) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_Op386MOVWstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -8015,89 +5720,13 @@ func rewriteValue386_Op386MOVWstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVWstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVWstore [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWstoreidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL2 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVWstoreidx2) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVWstore [off] {sym} (ADDL ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVWstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(Op386MOVWstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstore [i-2] {s} p w mem) + // match: (MOVWstore [i] {s} p1 (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVLstore [i-2] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != Op386SHRLconst || v_1.AuxInt != 16 { break } @@ -8107,22 +5736,23 @@ func rewriteValue386_Op386MOVWstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVLstore) v.AuxInt = i - 2 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstore [i-2] {s} p w0 mem) + // match: (MOVWstore [i] {s} p1 (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p0 w0:(SHRLconst [j-16] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVLstore [i-2] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != Op386SHRLconst { break } @@ -8133,17 +5763,131 @@ func rewriteValue386_Op386MOVWstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != Op386SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != Op386SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVLstore) v.AuxInt = i - 2 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) + return true + } + // match: (MOVWstore [i0] {s0} l:(LEAL1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAL1 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL1 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVWstore [i0] {s0} l:(LEAL2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAL2 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL2 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVWstore [i0] {s0} l:(LEAL4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAL4 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL4 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVWstore [i0] {s0} l:(LEAL8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAL8 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != Op386LEAL8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, Op386LEAL8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } return false @@ -8196,76 +5940,13 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVWstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVWstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVWstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconst [x] {sym1} (LEAL2 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVWstoreconstidx2 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL2 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MOVWstoreconstidx2) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconst [x] {sym} (ADDL ptr idx) mem) - // result: (MOVWstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDL { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(Op386MOVWstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) + // match: (MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x) + // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) for { c := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != Op386MOVWstoreconst { break @@ -8275,22 +5956,23 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVLstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } - // match: (MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) + // match: (MOVWstoreconst [a] {s} p1 x:(MOVWstoreconst [c] {s} p0 mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x) + // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) for { a := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != Op386MOVWstoreconst { break @@ -8300,422 +5982,14 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && same(p0, p1, 1) && clobber(x)) { break } v.reset(Op386MOVLstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVWstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWstoreconstidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) - // result: (MOVWstoreconstidx2 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386SHLLconst || v_1.AuxInt != 1 { - break - } - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVWstoreconstidx2) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) - // result: (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVWstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) - // result: (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVWstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx1 [c] {s} p i x:(MOVWstoreconstidx1 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p i mem) - for { - c := v.AuxInt - s := v.Aux - p := v_0 - i := v_1 - x := v_2 - if x.Op != Op386MOVWstoreconstidx1 { - break - } - a := x.AuxInt - if x.Aux != s { - break - } - mem := x.Args[2] - if p != x.Args[0] || i != x.Args[1] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { - break - } - v.reset(Op386MOVLstoreconstidx1) - v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) - v.Aux = s - v.AddArg3(p, i, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVWstoreconstidx2(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - // match: (MOVWstoreconstidx2 [x] {sym} (ADDLconst [c] ptr) idx mem) - // result: (MOVWstoreconstidx2 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - v.reset(Op386MOVWstoreconstidx2) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx2 [x] {sym} ptr (ADDLconst [c] idx) mem) - // result: (MOVWstoreconstidx2 [ValAndOff(x).add(2*c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - v.reset(Op386MOVWstoreconstidx2) - v.AuxInt = ValAndOff(x).add(2 * c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx2 [c] {s} p i x:(MOVWstoreconstidx2 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p (SHLLconst [1] i) mem) - for { - c := v.AuxInt - s := v.Aux - p := v_0 - i := v_1 - x := v_2 - if x.Op != Op386MOVWstoreconstidx2 { - break - } - a := x.AuxInt - if x.Aux != s { - break - } - mem := x.Args[2] - if p != x.Args[0] || i != x.Args[1] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { - break - } - v.reset(Op386MOVLstoreconstidx1) - v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) - v.Aux = s - v0 := b.NewValue0(v.Pos, Op386SHLLconst, i.Type) - v0.AuxInt = 1 - v0.AddArg(i) - v.AddArg3(p, v0, mem) - return true - } - return false -} -func rewriteValue386_Op386MOVWstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWstoreidx1 [c] {sym} ptr (SHLLconst [1] idx) val mem) - // result: (MOVWstoreidx2 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386SHLLconst || v_1.AuxInt != 1 { - continue - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVWstoreidx2) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != Op386ADDLconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVWstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != Op386ADDLconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVWstoreidx1) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRLconst || v_2.AuxInt != 16 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVWstoreidx1 || x.AuxInt != i-2 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVWstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRLconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVWstoreidx1 || x.AuxInt != i-2 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != Op386SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(Op386MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - return false -} -func rewriteValue386_Op386MOVWstoreidx2(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - // match: (MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) - // result: (MOVWstoreidx2 [int64(int32(c+d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - v.reset(Op386MOVWstoreidx2) - v.AuxInt = int64(int32(c + d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) - // result: (MOVWstoreidx2 [int64(int32(c+2*d))] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != Op386ADDLconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(Op386MOVWstoreidx2) - v.AuxInt = int64(int32(c + 2*d)) - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVWstoreidx2 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRLconst || v_2.AuxInt != 16 { - break - } - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVWstoreidx2 || x.AuxInt != i-2 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(Op386MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v0 := b.NewValue0(v.Pos, Op386SHLLconst, idx.Type) - v0.AuxInt = 1 - v0.AddArg(idx) - v.AddArg4(p, v0, w, mem) - return true - } - // match: (MOVWstoreidx2 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx2 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w0 mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != Op386SHRLconst { - break - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != Op386MOVWstoreidx2 || x.AuxInt != i-2 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] { - break - } - w0 := x.Args[2] - if w0.Op != Op386SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(Op386MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v0 := b.NewValue0(v.Pos, Op386SHLLconst, idx.Type) - v0.AuxInt = 1 - v0.AddArg(idx) - v.AddArg4(p, v0, w0, mem) + v.AddArg2(p0, mem) return true } return false @@ -8764,32 +6038,6 @@ func rewriteValue386_Op386MULL(v *Value) bool { } break } - // match: (MULL x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: canMergeLoadClobber(v, l, x) && clobber(l) - // result: (MULLloadidx4 x [off] {sym} ptr idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - l := v_1 - if l.Op != Op386MOVLloadidx4 { - continue - } - off := l.AuxInt - sym := l.Aux - mem := l.Args[2] - ptr := l.Args[0] - idx := l.Args[1] - if !(canMergeLoadClobber(v, l, x) && clobber(l)) { - continue - } - v.reset(Op386MULLloadidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(x, ptr, idx, mem) - return true - } - break - } return false } func rewriteValue386_Op386MULLconst(v *Value) bool { @@ -9267,109 +6515,6 @@ func rewriteValue386_Op386MULLload(v *Value) bool { v.AddArg3(val, base, mem) return true } - // match: (MULLload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MULLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL4 { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - idx := v_1.Args[1] - ptr := v_1.Args[0] - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386MULLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386MULLloadidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (MULLloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) - // cond: is32Bit(off1+off2) - // result: (MULLloadidx4 [off1+off2] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386MULLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (MULLloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) - // cond: is32Bit(off1+off2*4) - // result: (MULLloadidx4 [off1+off2*4] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - base := v_1 - if v_2.Op != Op386ADDLconst { - break - } - off2 := v_2.AuxInt - idx := v_2.Args[0] - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386MULLloadidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (MULLloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (MULLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386MULLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, base, idx, mem) - return true - } return false } func rewriteValue386_Op386MULSD(v *Value) bool { @@ -9692,32 +6837,6 @@ func rewriteValue386_Op386ORL(v *Value) bool { } break } - // match: (ORL x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: canMergeLoadClobber(v, l, x) && clobber(l) - // result: (ORLloadidx4 x [off] {sym} ptr idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - l := v_1 - if l.Op != Op386MOVLloadidx4 { - continue - } - off := l.AuxInt - sym := l.Aux - mem := l.Args[2] - ptr := l.Args[0] - idx := l.Args[1] - if !(canMergeLoadClobber(v, l, x) && clobber(l)) { - continue - } - v.reset(Op386ORLloadidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(x, ptr, idx, mem) - return true - } - break - } // match: (ORL x x) // result: x for { @@ -9728,9 +6847,9 @@ func rewriteValue386_Op386ORL(v *Value) bool { v.copyOf(x) return true } - // match: (ORL x0:(MOVBload [i0] {s} p mem) s0:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, s0) - // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem) + // match: (ORL x0:(MOVBload [i0] {s} p0 mem) s0:(SHLLconst [8] x1:(MOVBload [i1] {s} p1 mem))) + // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, s0) + // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x0 := v_0 @@ -9740,7 +6859,7 @@ func rewriteValue386_Op386ORL(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] s0 := v_1 if s0.Op != Op386SHLLconst || s0.AuxInt != 8 { continue @@ -9754,7 +6873,8 @@ func rewriteValue386_Op386ORL(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0)) { + p1 := x1.Args[0] + if mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0)) { continue } b = mergePoint(b, x0, x1) @@ -9762,14 +6882,14 @@ func rewriteValue386_Op386ORL(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } break } - // match: (ORL o0:(ORL x0:(MOVWload [i0] {s} p mem) s0:(SHLLconst [16] x1:(MOVBload [i2] {s} p mem))) s1:(SHLLconst [24] x2:(MOVBload [i3] {s} p mem))) - // cond: i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, s0, s1, o0) - // result: @mergePoint(b,x0,x1,x2) (MOVLload [i0] {s} p mem) + // match: (ORL o0:(ORL x0:(MOVWload [i0] {s} p0 mem) s0:(SHLLconst [16] x1:(MOVBload [i2] {s} p1 mem))) s1:(SHLLconst [24] x2:(MOVBload [i3] {s} p2 mem))) + // cond: i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && same(p0, p1, 1) && same(p1, p2, 1) && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, s0, s1, o0) + // result: @mergePoint(b,x0,x1,x2) (MOVLload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { o0 := v_0 @@ -9787,7 +6907,7 @@ func rewriteValue386_Op386ORL(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] s0 := o0_1 if s0.Op != Op386SHLLconst || s0.AuxInt != 16 { continue @@ -9801,7 +6921,8 @@ func rewriteValue386_Op386ORL(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] { + p1 := x1.Args[0] + if mem != x1.Args[1] { continue } s1 := v_1 @@ -9817,7 +6938,8 @@ func rewriteValue386_Op386ORL(v *Value) bool { continue } _ = x2.Args[1] - if p != x2.Args[0] || mem != x2.Args[1] || !(i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) { + p2 := x2.Args[0] + if mem != x2.Args[1] || !(i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && same(p0, p1, 1) && same(p1, p2, 1) && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) { continue } b = mergePoint(b, x0, x1, x2) @@ -9825,137 +6947,12 @@ func rewriteValue386_Op386ORL(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } } break } - // match: (ORL x0:(MOVBloadidx1 [i0] {s} p idx mem) s0:(SHLLconst [8] x1:(MOVBloadidx1 [i1] {s} p idx mem))) - // cond: i1==i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, s0) - // result: @mergePoint(b,x0,x1) (MOVWloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != Op386MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - s0 := v_1 - if s0.Op != Op386SHLLconst || s0.AuxInt != 8 { - continue - } - x1 := s0.Args[0] - if x1.Op != Op386MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, s0)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, Op386MOVWloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - break - } - // match: (ORL o0:(ORL x0:(MOVWloadidx1 [i0] {s} p idx mem) s0:(SHLLconst [16] x1:(MOVBloadidx1 [i2] {s} p idx mem))) s1:(SHLLconst [24] x2:(MOVBloadidx1 [i3] {s} p idx mem))) - // cond: i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && mergePoint(b,x0,x1,x2) != nil && clobber(x0, x1, x2, s0, s1, o0) - // result: @mergePoint(b,x0,x1,x2) (MOVLloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - o0 := v_0 - if o0.Op != Op386ORL { - continue - } - _ = o0.Args[1] - o0_0 := o0.Args[0] - o0_1 := o0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, o0_0, o0_1 = _i1+1, o0_1, o0_0 { - x0 := o0_0 - if x0.Op != Op386MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x0_0, x0_1 = _i2+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - s0 := o0_1 - if s0.Op != Op386SHLLconst || s0.AuxInt != 16 { - continue - } - x1 := s0.Args[0] - if x1.Op != Op386MOVBloadidx1 { - continue - } - i2 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x1_0, x1_1 = _i3+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] { - continue - } - s1 := v_1 - if s1.Op != Op386SHLLconst || s1.AuxInt != 24 { - continue - } - x2 := s1.Args[0] - if x2.Op != Op386MOVBloadidx1 { - continue - } - i3 := x2.AuxInt - if x2.Aux != s { - continue - } - _ = x2.Args[2] - x2_0 := x2.Args[0] - x2_1 := x2.Args[1] - for _i4 := 0; _i4 <= 1; _i4, x2_0, x2_1 = _i4+1, x2_1, x2_0 { - if p != x2_0 || idx != x2_1 || mem != x2.Args[2] || !(i2 == i0+2 && i3 == i0+3 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && o0.Uses == 1 && mergePoint(b, x0, x1, x2) != nil && clobber(x0, x1, x2, s0, s1, o0)) { - continue - } - b = mergePoint(b, x0, x1, x2) - v0 := b.NewValue0(v.Pos, Op386MOVLloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - } - } - break - } return false } func rewriteValue386_Op386ORLconst(v *Value) bool { @@ -10048,81 +7045,6 @@ func rewriteValue386_Op386ORLconstmodify(v *Value) bool { } return false } -func rewriteValue386_Op386ORLconstmodifyidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ORLconstmodifyidx4 [valoff1] {sym} (ADDLconst [off2] base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) - // result: (ORLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2)) { - break - } - v.reset(Op386ORLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (ORLconstmodifyidx4 [valoff1] {sym} base (ADDLconst [off2] idx) mem) - // cond: ValAndOff(valoff1).canAdd(off2*4) - // result: (ORLconstmodifyidx4 [ValAndOff(valoff1).add(off2*4)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2 * 4)) { - break - } - v.reset(Op386ORLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2 * 4) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (ORLconstmodifyidx4 [valoff1] {sym1} (LEAL [off2] {sym2} base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ORLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base idx mem) - for { - valoff1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ORLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(base, idx, mem) - return true - } - return false -} func rewriteValue386_Op386ORLload(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -10174,109 +7096,6 @@ func rewriteValue386_Op386ORLload(v *Value) bool { v.AddArg3(val, base, mem) return true } - // match: (ORLload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (ORLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL4 { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - idx := v_1.Args[1] - ptr := v_1.Args[0] - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386ORLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386ORLloadidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ORLloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) - // cond: is32Bit(off1+off2) - // result: (ORLloadidx4 [off1+off2] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386ORLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (ORLloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) - // cond: is32Bit(off1+off2*4) - // result: (ORLloadidx4 [off1+off2*4] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - base := v_1 - if v_2.Op != Op386ADDLconst { - break - } - off2 := v_2.AuxInt - idx := v_2.Args[0] - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386ORLloadidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (ORLloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ORLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ORLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, base, idx, mem) - return true - } return false } func rewriteValue386_Op386ORLmodify(v *Value) bool { @@ -10332,107 +7151,6 @@ func rewriteValue386_Op386ORLmodify(v *Value) bool { } return false } -func rewriteValue386_Op386ORLmodifyidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (ORLmodifyidx4 [off1] {sym} (ADDLconst [off2] base) idx val mem) - // cond: is32Bit(off1+off2) - // result: (ORLmodifyidx4 [off1+off2] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386ORLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ORLmodifyidx4 [off1] {sym} base (ADDLconst [off2] idx) val mem) - // cond: is32Bit(off1+off2*4) - // result: (ORLmodifyidx4 [off1+off2*4] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386ORLmodifyidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ORLmodifyidx4 [off1] {sym1} (LEAL [off2] {sym2} base) idx val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (ORLmodifyidx4 [off1+off2] {mergeSym(sym1,sym2)} base idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386ORLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(base, idx, val, mem) - return true - } - // match: (ORLmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(c,off) - // result: (ORLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != Op386MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(c, off)) { - break - } - v.reset(Op386ORLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_Op386ROLBconst(v *Value) bool { v_0 := v.Args[0] // match: (ROLBconst [c] (ROLBconst [d] x)) @@ -11629,29 +8347,6 @@ func rewriteValue386_Op386SUBL(v *Value) bool { v.AddArg3(x, ptr, mem) return true } - // match: (SUBL x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: canMergeLoadClobber(v, l, x) && clobber(l) - // result: (SUBLloadidx4 x [off] {sym} ptr idx mem) - for { - x := v_0 - l := v_1 - if l.Op != Op386MOVLloadidx4 { - break - } - off := l.AuxInt - sym := l.Aux - mem := l.Args[2] - ptr := l.Args[0] - idx := l.Args[1] - if !(canMergeLoadClobber(v, l, x) && clobber(l)) { - break - } - v.reset(Op386SUBLloadidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(x, ptr, idx, mem) - return true - } // match: (SUBL x x) // result: (MOVLconst [0]) for { @@ -11759,109 +8454,6 @@ func rewriteValue386_Op386SUBLload(v *Value) bool { v.AddArg3(val, base, mem) return true } - // match: (SUBLload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (SUBLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL4 { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - idx := v_1.Args[1] - ptr := v_1.Args[0] - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386SUBLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386SUBLloadidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (SUBLloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) - // cond: is32Bit(off1+off2) - // result: (SUBLloadidx4 [off1+off2] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386SUBLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (SUBLloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) - // cond: is32Bit(off1+off2*4) - // result: (SUBLloadidx4 [off1+off2*4] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - base := v_1 - if v_2.Op != Op386ADDLconst { - break - } - off2 := v_2.AuxInt - idx := v_2.Args[0] - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386SUBLloadidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (SUBLloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (SUBLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386SUBLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, base, idx, mem) - return true - } return false } func rewriteValue386_Op386SUBLmodify(v *Value) bool { @@ -11917,107 +8509,6 @@ func rewriteValue386_Op386SUBLmodify(v *Value) bool { } return false } -func rewriteValue386_Op386SUBLmodifyidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (SUBLmodifyidx4 [off1] {sym} (ADDLconst [off2] base) idx val mem) - // cond: is32Bit(off1+off2) - // result: (SUBLmodifyidx4 [off1+off2] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386SUBLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (SUBLmodifyidx4 [off1] {sym} base (ADDLconst [off2] idx) val mem) - // cond: is32Bit(off1+off2*4) - // result: (SUBLmodifyidx4 [off1+off2*4] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386SUBLmodifyidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (SUBLmodifyidx4 [off1] {sym1} (LEAL [off2] {sym2} base) idx val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (SUBLmodifyidx4 [off1+off2] {mergeSym(sym1,sym2)} base idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386SUBLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(base, idx, val, mem) - return true - } - // match: (SUBLmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(-c,off) - // result: (ADDLconstmodifyidx4 [makeValAndOff(-c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != Op386MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(-c, off)) { - break - } - v.reset(Op386ADDLconstmodifyidx4) - v.AuxInt = makeValAndOff(-c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_Op386SUBSD(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -12300,32 +8791,6 @@ func rewriteValue386_Op386XORL(v *Value) bool { } break } - // match: (XORL x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: canMergeLoadClobber(v, l, x) && clobber(l) - // result: (XORLloadidx4 x [off] {sym} ptr idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - l := v_1 - if l.Op != Op386MOVLloadidx4 { - continue - } - off := l.AuxInt - sym := l.Aux - mem := l.Args[2] - ptr := l.Args[0] - idx := l.Args[1] - if !(canMergeLoadClobber(v, l, x) && clobber(l)) { - continue - } - v.reset(Op386XORLloadidx4) - v.AuxInt = off - v.Aux = sym - v.AddArg4(x, ptr, idx, mem) - return true - } - break - } // match: (XORL x x) // result: (MOVLconst [0]) for { @@ -12431,81 +8896,6 @@ func rewriteValue386_Op386XORLconstmodify(v *Value) bool { } return false } -func rewriteValue386_Op386XORLconstmodifyidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (XORLconstmodifyidx4 [valoff1] {sym} (ADDLconst [off2] base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) - // result: (XORLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2)) { - break - } - v.reset(Op386XORLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (XORLconstmodifyidx4 [valoff1] {sym} base (ADDLconst [off2] idx) mem) - // cond: ValAndOff(valoff1).canAdd(off2*4) - // result: (XORLconstmodifyidx4 [ValAndOff(valoff1).add(off2*4)] {sym} base idx mem) - for { - valoff1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2 * 4)) { - break - } - v.reset(Op386XORLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2 * 4) - v.Aux = sym - v.AddArg3(base, idx, mem) - return true - } - // match: (XORLconstmodifyidx4 [valoff1] {sym1} (LEAL [off2] {sym2} base) idx mem) - // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (XORLconstmodifyidx4 [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base idx mem) - for { - valoff1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386XORLconstmodifyidx4) - v.AuxInt = ValAndOff(valoff1).add(off2) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(base, idx, mem) - return true - } - return false -} func rewriteValue386_Op386XORLload(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -12557,109 +8947,6 @@ func rewriteValue386_Op386XORLload(v *Value) bool { v.AddArg3(val, base, mem) return true } - // match: (XORLload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (XORLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL4 { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - idx := v_1.Args[1] - ptr := v_1.Args[0] - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(Op386XORLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, ptr, idx, mem) - return true - } - return false -} -func rewriteValue386_Op386XORLloadidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (XORLloadidx4 [off1] {sym} val (ADDLconst [off2] base) idx mem) - // cond: is32Bit(off1+off2) - // result: (XORLloadidx4 [off1+off2] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386XORLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (XORLloadidx4 [off1] {sym} val base (ADDLconst [off2] idx) mem) - // cond: is32Bit(off1+off2*4) - // result: (XORLloadidx4 [off1+off2*4] {sym} val base idx mem) - for { - off1 := v.AuxInt - sym := v.Aux - val := v_0 - base := v_1 - if v_2.Op != Op386ADDLconst { - break - } - off2 := v_2.AuxInt - idx := v_2.Args[0] - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386XORLloadidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(val, base, idx, mem) - return true - } - // match: (XORLloadidx4 [off1] {sym1} val (LEAL [off2] {sym2} base) idx mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (XORLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val base idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - val := v_0 - if v_1.Op != Op386LEAL { - break - } - off2 := v_1.AuxInt - sym2 := v_1.Aux - base := v_1.Args[0] - idx := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386XORLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(val, base, idx, mem) - return true - } return false } func rewriteValue386_Op386XORLmodify(v *Value) bool { @@ -12715,107 +9002,6 @@ func rewriteValue386_Op386XORLmodify(v *Value) bool { } return false } -func rewriteValue386_Op386XORLmodifyidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (XORLmodifyidx4 [off1] {sym} (ADDLconst [off2] base) idx val mem) - // cond: is32Bit(off1+off2) - // result: (XORLmodifyidx4 [off1+off2] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - if v_0.Op != Op386ADDLconst { - break - } - off2 := v_0.AuxInt - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2)) { - break - } - v.reset(Op386XORLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (XORLmodifyidx4 [off1] {sym} base (ADDLconst [off2] idx) val mem) - // cond: is32Bit(off1+off2*4) - // result: (XORLmodifyidx4 [off1+off2*4] {sym} base idx val mem) - for { - off1 := v.AuxInt - sym := v.Aux - base := v_0 - if v_1.Op != Op386ADDLconst { - break - } - off2 := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(off1 + off2*4)) { - break - } - v.reset(Op386XORLmodifyidx4) - v.AuxInt = off1 + off2*4 - v.Aux = sym - v.AddArg4(base, idx, val, mem) - return true - } - // match: (XORLmodifyidx4 [off1] {sym1} (LEAL [off2] {sym2} base) idx val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) - // result: (XORLmodifyidx4 [off1+off2] {mergeSym(sym1,sym2)} base idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != Op386LEAL { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - base := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) { - break - } - v.reset(Op386XORLmodifyidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(base, idx, val, mem) - return true - } - // match: (XORLmodifyidx4 [off] {sym} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(c,off) - // result: (XORLconstmodifyidx4 [makeValAndOff(c,off)] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != Op386MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(c, off)) { - break - } - v.reset(Op386XORLconstmodifyidx4) - v.AuxInt = makeValAndOff(c, off) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValue386_OpConstNil(v *Value) bool { // match: (ConstNil) // result: (MOVLconst [0]) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index c37bae2c22c..16a3f641589 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -246,16 +246,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64MOVBatomicload(v) case OpAMD64MOVBload: return rewriteValueAMD64_OpAMD64MOVBload(v) - case OpAMD64MOVBloadidx1: - return rewriteValueAMD64_OpAMD64MOVBloadidx1(v) case OpAMD64MOVBstore: return rewriteValueAMD64_OpAMD64MOVBstore(v) case OpAMD64MOVBstoreconst: return rewriteValueAMD64_OpAMD64MOVBstoreconst(v) - case OpAMD64MOVBstoreconstidx1: - return rewriteValueAMD64_OpAMD64MOVBstoreconstidx1(v) - case OpAMD64MOVBstoreidx1: - return rewriteValueAMD64_OpAMD64MOVBstoreidx1(v) case OpAMD64MOVLQSX: return rewriteValueAMD64_OpAMD64MOVLQSX(v) case OpAMD64MOVLQSXload: @@ -270,26 +264,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64MOVLi2f(v) case OpAMD64MOVLload: return rewriteValueAMD64_OpAMD64MOVLload(v) - case OpAMD64MOVLloadidx1: - return rewriteValueAMD64_OpAMD64MOVLloadidx1(v) - case OpAMD64MOVLloadidx4: - return rewriteValueAMD64_OpAMD64MOVLloadidx4(v) - case OpAMD64MOVLloadidx8: - return rewriteValueAMD64_OpAMD64MOVLloadidx8(v) case OpAMD64MOVLstore: return rewriteValueAMD64_OpAMD64MOVLstore(v) case OpAMD64MOVLstoreconst: return rewriteValueAMD64_OpAMD64MOVLstoreconst(v) - case OpAMD64MOVLstoreconstidx1: - return rewriteValueAMD64_OpAMD64MOVLstoreconstidx1(v) - case OpAMD64MOVLstoreconstidx4: - return rewriteValueAMD64_OpAMD64MOVLstoreconstidx4(v) - case OpAMD64MOVLstoreidx1: - return rewriteValueAMD64_OpAMD64MOVLstoreidx1(v) - case OpAMD64MOVLstoreidx4: - return rewriteValueAMD64_OpAMD64MOVLstoreidx4(v) - case OpAMD64MOVLstoreidx8: - return rewriteValueAMD64_OpAMD64MOVLstoreidx8(v) case OpAMD64MOVOload: return rewriteValueAMD64_OpAMD64MOVOload(v) case OpAMD64MOVOstore: @@ -302,46 +280,18 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64MOVQi2f(v) case OpAMD64MOVQload: return rewriteValueAMD64_OpAMD64MOVQload(v) - case OpAMD64MOVQloadidx1: - return rewriteValueAMD64_OpAMD64MOVQloadidx1(v) - case OpAMD64MOVQloadidx8: - return rewriteValueAMD64_OpAMD64MOVQloadidx8(v) case OpAMD64MOVQstore: return rewriteValueAMD64_OpAMD64MOVQstore(v) case OpAMD64MOVQstoreconst: return rewriteValueAMD64_OpAMD64MOVQstoreconst(v) - case OpAMD64MOVQstoreconstidx1: - return rewriteValueAMD64_OpAMD64MOVQstoreconstidx1(v) - case OpAMD64MOVQstoreconstidx8: - return rewriteValueAMD64_OpAMD64MOVQstoreconstidx8(v) - case OpAMD64MOVQstoreidx1: - return rewriteValueAMD64_OpAMD64MOVQstoreidx1(v) - case OpAMD64MOVQstoreidx8: - return rewriteValueAMD64_OpAMD64MOVQstoreidx8(v) case OpAMD64MOVSDload: return rewriteValueAMD64_OpAMD64MOVSDload(v) - case OpAMD64MOVSDloadidx1: - return rewriteValueAMD64_OpAMD64MOVSDloadidx1(v) - case OpAMD64MOVSDloadidx8: - return rewriteValueAMD64_OpAMD64MOVSDloadidx8(v) case OpAMD64MOVSDstore: return rewriteValueAMD64_OpAMD64MOVSDstore(v) - case OpAMD64MOVSDstoreidx1: - return rewriteValueAMD64_OpAMD64MOVSDstoreidx1(v) - case OpAMD64MOVSDstoreidx8: - return rewriteValueAMD64_OpAMD64MOVSDstoreidx8(v) case OpAMD64MOVSSload: return rewriteValueAMD64_OpAMD64MOVSSload(v) - case OpAMD64MOVSSloadidx1: - return rewriteValueAMD64_OpAMD64MOVSSloadidx1(v) - case OpAMD64MOVSSloadidx4: - return rewriteValueAMD64_OpAMD64MOVSSloadidx4(v) case OpAMD64MOVSSstore: return rewriteValueAMD64_OpAMD64MOVSSstore(v) - case OpAMD64MOVSSstoreidx1: - return rewriteValueAMD64_OpAMD64MOVSSstoreidx1(v) - case OpAMD64MOVSSstoreidx4: - return rewriteValueAMD64_OpAMD64MOVSSstoreidx4(v) case OpAMD64MOVWQSX: return rewriteValueAMD64_OpAMD64MOVWQSX(v) case OpAMD64MOVWQSXload: @@ -350,22 +300,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64MOVWQZX(v) case OpAMD64MOVWload: return rewriteValueAMD64_OpAMD64MOVWload(v) - case OpAMD64MOVWloadidx1: - return rewriteValueAMD64_OpAMD64MOVWloadidx1(v) - case OpAMD64MOVWloadidx2: - return rewriteValueAMD64_OpAMD64MOVWloadidx2(v) case OpAMD64MOVWstore: return rewriteValueAMD64_OpAMD64MOVWstore(v) case OpAMD64MOVWstoreconst: return rewriteValueAMD64_OpAMD64MOVWstoreconst(v) - case OpAMD64MOVWstoreconstidx1: - return rewriteValueAMD64_OpAMD64MOVWstoreconstidx1(v) - case OpAMD64MOVWstoreconstidx2: - return rewriteValueAMD64_OpAMD64MOVWstoreconstidx2(v) - case OpAMD64MOVWstoreidx1: - return rewriteValueAMD64_OpAMD64MOVWstoreidx1(v) - case OpAMD64MOVWstoreidx2: - return rewriteValueAMD64_OpAMD64MOVWstoreidx2(v) case OpAMD64MULL: return rewriteValueAMD64_OpAMD64MULL(v) case OpAMD64MULLconst: @@ -9347,6 +9285,64 @@ func rewriteValueAMD64_OpAMD64LEAQ1(v *Value) bool { } break } + // match: (LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64LEAQ1 { + continue + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[1] + if y != v_1.Args[0] || !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + continue + } + v.reset(OpAMD64LEAQ2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg2(x, y) + return true + } + break + } + // match: (LEAQ1 [off1] {sym1} x (LEAQ1 [off2] {sym2} x y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAQ2 [off1+off2] {mergeSym(sym1, sym2)} y x) + for { + off1 := v.AuxInt + sym1 := v.Aux + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64LEAQ1 { + continue + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { + if x != v_1_0 { + continue + } + y := v_1_1 + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + continue + } + v.reset(OpAMD64LEAQ2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg2(y, x) + return true + } + } + break + } // match: (LEAQ1 [0] x y) // cond: v.Aux == nil // result: (ADDQ x y) @@ -9464,6 +9460,28 @@ func rewriteValueAMD64_OpAMD64LEAQ2(v *Value) bool { v.AddArg2(x, y) return true } + // match: (LEAQ2 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) + // cond: is32Bit(off1+2*off2) && sym2 == nil + // result: (LEAQ4 [off1+2*off2] {sym1} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + x := v_0 + if v_1.Op != OpAMD64LEAQ1 { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[1] + if y != v_1.Args[0] || !(is32Bit(off1+2*off2) && sym2 == nil) { + break + } + v.reset(OpAMD64LEAQ4) + v.AuxInt = off1 + 2*off2 + v.Aux = sym1 + v.AddArg2(x, y) + return true + } return false } func rewriteValueAMD64_OpAMD64LEAQ4(v *Value) bool { @@ -9549,6 +9567,28 @@ func rewriteValueAMD64_OpAMD64LEAQ4(v *Value) bool { v.AddArg2(x, y) return true } + // match: (LEAQ4 [off1] {sym1} x (LEAQ1 [off2] {sym2} y y)) + // cond: is32Bit(off1+4*off2) && sym2 == nil + // result: (LEAQ8 [off1+4*off2] {sym1} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + x := v_0 + if v_1.Op != OpAMD64LEAQ1 { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[1] + if y != v_1.Args[0] || !(is32Bit(off1+4*off2) && sym2 == nil) { + break + } + v.reset(OpAMD64LEAQ8) + v.AuxInt = off1 + 4*off2 + v.Aux = sym1 + v.AddArg2(x, y) + return true + } return false } func rewriteValueAMD64_OpAMD64LEAQ8(v *Value) bool { @@ -9899,30 +9939,6 @@ func rewriteValueAMD64_OpAMD64MOVBQZX(v *Value) bool { v.copyOf(x) return true } - // match: (MOVBQZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVBloadidx1 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != OpAMD64MOVBloadidx1 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, OpAMD64MOVBloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } // match: (MOVBQZX (ANDLconst [c] x)) // result: (ANDLconst [c & 0xff] x) for { @@ -10000,6 +10016,7 @@ func rewriteValueAMD64_OpAMD64MOVBatomicload(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVBload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + b := v.Block // match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) // result: (MOVBQZX x) @@ -10064,55 +10081,117 @@ func rewriteValueAMD64_OpAMD64MOVBload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVBload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVBloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVBload [i0] {s0} l:(LEAQ1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAQ1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVBloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVBload [off] {sym} (ADDQ ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVBloadidx1 [off] {sym} ptr idx mem) + // match: (MOVBload [i0] {s0} l:(LEAQ2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAQ2 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVBloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVBload [i0] {s0} l:(LEAQ4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAQ4 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVBload [i0] {s0} l:(LEAQ8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBload [i0+i1] {s0} (LEAQ8 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVBload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem) // cond: canMergeSym(sym1, sym2) && is32Bit(off1+off2) @@ -10172,86 +10251,6 @@ func rewriteValueAMD64_OpAMD64MOVBload(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVBloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVBloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVBloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVBloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+d) - // result: (MOVBloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVBloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVBloadidx1 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+c) - // result: (MOVBload [i+c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVBload) - v.AuxInt = i + c - v.Aux = s - v.AddArg2(p, mem) - return true - } - break - } - return false -} func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -10599,76 +10598,138 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVBstore [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVBstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVBstore [i0] {s0} l:(LEAQ1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAQ1 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVBstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVBstore [off] {sym} (ADDQ ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVBstoreidx1 [off] {sym} ptr idx val mem) + // match: (MOVBstore [i0] {s0} l:(LEAQ2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAQ2 [0] {s1} x y) val mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVBstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true } - // match: (MOVBstore [i] {s} p w x0:(MOVBstore [i-1] {s} p (SHRWconst [8] w) mem)) - // cond: x0.Uses == 1 && clobber(x0) - // result: (MOVWstore [i-1] {s} p (ROLWconst [8] w) mem) + // match: (MOVBstore [i0] {s0} l:(LEAQ4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAQ4 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVBstore [i0] {s0} l:(LEAQ8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVBstore [i0+i1] {s0} (LEAQ8 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVBstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVBstore [i] {s} p1 w x0:(MOVBstore [i-1] {s} p0 (SHRWconst [8] w) mem)) + // cond: x0.Uses == 1 && same(p0, p1, 1) && clobber(x0) + // result: (MOVWstore [i-1] {s} p0 (ROLWconst [8] w) mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 w := v_1 x0 := v_2 if x0.Op != OpAMD64MOVBstore || x0.AuxInt != i-1 || x0.Aux != s { break } mem := x0.Args[2] - if p != x0.Args[0] { - break - } + p0 := x0.Args[0] x0_1 := x0.Args[1] - if x0_1.Op != OpAMD64SHRWconst || x0_1.AuxInt != 8 || w != x0_1.Args[0] || !(x0.Uses == 1 && clobber(x0)) { + if x0_1.Op != OpAMD64SHRWconst || x0_1.AuxInt != 8 || w != x0_1.Args[0] || !(x0.Uses == 1 && same(p0, p1, 1) && clobber(x0)) { break } v.reset(OpAMD64MOVWstore) @@ -10677,25 +10738,23 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { v0 := b.NewValue0(x0.Pos, OpAMD64ROLWconst, w.Type) v0.AuxInt = 8 v0.AddArg(w) - v.AddArg3(p, v0, mem) + v.AddArg3(p0, v0, mem) return true } - // match: (MOVBstore [i] {s} p w x2:(MOVBstore [i-1] {s} p (SHRLconst [8] w) x1:(MOVBstore [i-2] {s} p (SHRLconst [16] w) x0:(MOVBstore [i-3] {s} p (SHRLconst [24] w) mem)))) - // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2) - // result: (MOVLstore [i-3] {s} p (BSWAPL w) mem) + // match: (MOVBstore [i] {s} p3 w x2:(MOVBstore [i-1] {s} p2 (SHRLconst [8] w) x1:(MOVBstore [i-2] {s} p1 (SHRLconst [16] w) x0:(MOVBstore [i-3] {s} p0 (SHRLconst [24] w) mem)))) + // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && same(p0, p1, 1) && same(p1, p2, 1) && same(p2, p3, 1) && clobber(x0, x1, x2) + // result: (MOVLstore [i-3] {s} p0 (BSWAPL w) mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p3 := v_0 w := v_1 x2 := v_2 if x2.Op != OpAMD64MOVBstore || x2.AuxInt != i-1 || x2.Aux != s { break } _ = x2.Args[2] - if p != x2.Args[0] { - break - } + p2 := x2.Args[0] x2_1 := x2.Args[1] if x2_1.Op != OpAMD64SHRLconst || x2_1.AuxInt != 8 || w != x2_1.Args[0] { break @@ -10705,9 +10764,7 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } _ = x1.Args[2] - if p != x1.Args[0] { - break - } + p1 := x1.Args[0] x1_1 := x1.Args[1] if x1_1.Op != OpAMD64SHRLconst || x1_1.AuxInt != 16 || w != x1_1.Args[0] { break @@ -10717,11 +10774,9 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x0.Args[2] - if p != x0.Args[0] { - break - } + p0 := x0.Args[0] x0_1 := x0.Args[1] - if x0_1.Op != OpAMD64SHRLconst || x0_1.AuxInt != 24 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) { + if x0_1.Op != OpAMD64SHRLconst || x0_1.AuxInt != 24 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && same(p0, p1, 1) && same(p1, p2, 1) && same(p2, p3, 1) && clobber(x0, x1, x2)) { break } v.reset(OpAMD64MOVLstore) @@ -10729,25 +10784,23 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { v.Aux = s v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPL, w.Type) v0.AddArg(w) - v.AddArg3(p, v0, mem) + v.AddArg3(p0, v0, mem) return true } - // match: (MOVBstore [i] {s} p w x6:(MOVBstore [i-1] {s} p (SHRQconst [8] w) x5:(MOVBstore [i-2] {s} p (SHRQconst [16] w) x4:(MOVBstore [i-3] {s} p (SHRQconst [24] w) x3:(MOVBstore [i-4] {s} p (SHRQconst [32] w) x2:(MOVBstore [i-5] {s} p (SHRQconst [40] w) x1:(MOVBstore [i-6] {s} p (SHRQconst [48] w) x0:(MOVBstore [i-7] {s} p (SHRQconst [56] w) mem)))))))) - // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6) - // result: (MOVQstore [i-7] {s} p (BSWAPQ w) mem) + // match: (MOVBstore [i] {s} p7 w x6:(MOVBstore [i-1] {s} p6 (SHRQconst [8] w) x5:(MOVBstore [i-2] {s} p5 (SHRQconst [16] w) x4:(MOVBstore [i-3] {s} p4 (SHRQconst [24] w) x3:(MOVBstore [i-4] {s} p3 (SHRQconst [32] w) x2:(MOVBstore [i-5] {s} p2 (SHRQconst [40] w) x1:(MOVBstore [i-6] {s} p1 (SHRQconst [48] w) x0:(MOVBstore [i-7] {s} p0 (SHRQconst [56] w) mem)))))))) + // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && same(p0, p1, 1) && same(p1, p2, 1) && same(p2, p3, 1) && same(p3, p4, 1) && same(p4, p5, 1) && same(p5, p6, 1) && same(p6, p7, 1) && clobber(x0, x1, x2, x3, x4, x5, x6) + // result: (MOVQstore [i-7] {s} p0 (BSWAPQ w) mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p7 := v_0 w := v_1 x6 := v_2 if x6.Op != OpAMD64MOVBstore || x6.AuxInt != i-1 || x6.Aux != s { break } _ = x6.Args[2] - if p != x6.Args[0] { - break - } + p6 := x6.Args[0] x6_1 := x6.Args[1] if x6_1.Op != OpAMD64SHRQconst || x6_1.AuxInt != 8 || w != x6_1.Args[0] { break @@ -10757,9 +10810,7 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } _ = x5.Args[2] - if p != x5.Args[0] { - break - } + p5 := x5.Args[0] x5_1 := x5.Args[1] if x5_1.Op != OpAMD64SHRQconst || x5_1.AuxInt != 16 || w != x5_1.Args[0] { break @@ -10769,9 +10820,7 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } _ = x4.Args[2] - if p != x4.Args[0] { - break - } + p4 := x4.Args[0] x4_1 := x4.Args[1] if x4_1.Op != OpAMD64SHRQconst || x4_1.AuxInt != 24 || w != x4_1.Args[0] { break @@ -10781,9 +10830,7 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } _ = x3.Args[2] - if p != x3.Args[0] { - break - } + p3 := x3.Args[0] x3_1 := x3.Args[1] if x3_1.Op != OpAMD64SHRQconst || x3_1.AuxInt != 32 || w != x3_1.Args[0] { break @@ -10793,9 +10840,7 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } _ = x2.Args[2] - if p != x2.Args[0] { - break - } + p2 := x2.Args[0] x2_1 := x2.Args[1] if x2_1.Op != OpAMD64SHRQconst || x2_1.AuxInt != 40 || w != x2_1.Args[0] { break @@ -10805,9 +10850,7 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } _ = x1.Args[2] - if p != x1.Args[0] { - break - } + p1 := x1.Args[0] x1_1 := x1.Args[1] if x1_1.Op != OpAMD64SHRQconst || x1_1.AuxInt != 48 || w != x1_1.Args[0] { break @@ -10817,11 +10860,9 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x0.Args[2] - if p != x0.Args[0] { - break - } + p0 := x0.Args[0] x0_1 := x0.Args[1] - if x0_1.Op != OpAMD64SHRQconst || x0_1.AuxInt != 56 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6)) { + if x0_1.Op != OpAMD64SHRQconst || x0_1.AuxInt != 56 || w != x0_1.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && same(p0, p1, 1) && same(p1, p2, 1) && same(p2, p3, 1) && same(p3, p4, 1) && same(p4, p5, 1) && same(p5, p6, 1) && same(p6, p7, 1) && clobber(x0, x1, x2, x3, x4, x5, x6)) { break } v.reset(OpAMD64MOVQstore) @@ -10829,16 +10870,16 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { v.Aux = s v0 := b.NewValue0(x0.Pos, OpAMD64BSWAPQ, w.Type) v0.AddArg(w) - v.AddArg3(p, v0, mem) + v.AddArg3(p0, v0, mem) return true } - // match: (MOVBstore [i] {s} p (SHRWconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w mem) + // match: (MOVBstore [i] {s} p1 (SHRWconst [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRWconst || v_1.AuxInt != 8 { break } @@ -10848,22 +10889,23 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w mem) + // match: (MOVBstore [i] {s} p1 (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRLconst || v_1.AuxInt != 8 { break } @@ -10873,22 +10915,23 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p (SHRQconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w mem) + // match: (MOVBstore [i] {s} p1 (SHRQconst [8] w) x:(MOVBstore [i-1] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRQconst || v_1.AuxInt != 8 { break } @@ -10898,100 +10941,95 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHRWconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i] {s} p w mem) + // match: (MOVBstore [i] {s} p1 w x:(MOVBstore [i+1] {s} p0 (SHRWconst [8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 w := v_1 x := v_2 if x.Op != OpAMD64MOVBstore || x.AuxInt != i+1 || x.Aux != s { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] x_1 := x.Args[1] - if x_1.Op != OpAMD64SHRWconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) { + if x_1.Op != OpAMD64SHRWconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHRLconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i] {s} p w mem) + // match: (MOVBstore [i] {s} p1 w x:(MOVBstore [i+1] {s} p0 (SHRLconst [8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 w := v_1 x := v_2 if x.Op != OpAMD64MOVBstore || x.AuxInt != i+1 || x.Aux != s { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] x_1 := x.Args[1] - if x_1.Op != OpAMD64SHRLconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) { + if x_1.Op != OpAMD64SHRLconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p w x:(MOVBstore [i+1] {s} p (SHRQconst [8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i] {s} p w mem) + // match: (MOVBstore [i] {s} p1 w x:(MOVBstore [i+1] {s} p0 (SHRQconst [8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 w := v_1 x := v_2 if x.Op != OpAMD64MOVBstore || x.AuxInt != i+1 || x.Aux != s { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] x_1 := x.Args[1] - if x_1.Op != OpAMD64SHRQconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && clobber(x)) { + if x_1.Op != OpAMD64SHRQconst || x_1.AuxInt != 8 || w != x_1.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w0 mem) + // match: (MOVBstore [i] {s} p1 (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p0 w0:(SHRLconst [j-8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRLconst { break } @@ -11002,26 +11040,24 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != OpAMD64SHRLconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != OpAMD64SHRLconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) return true } - // match: (MOVBstore [i] {s} p (SHRQconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRQconst [j-8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstore [i-1] {s} p w0 mem) + // match: (MOVBstore [i] {s} p1 (SHRQconst [j] w) x:(MOVBstore [i-1] {s} p0 w0:(SHRQconst [j-8] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVWstore [i-1] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRQconst { break } @@ -11032,17 +11068,15 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVWstore) v.AuxInt = i - 1 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) return true } // match: (MOVBstore [i] {s} p x1:(MOVBload [j] {s2} p2 mem) mem2:(MOVBstore [i-1] {s} p x2:(MOVBload [j-1] {s2} p2 mem) mem)) @@ -11179,53 +11213,13 @@ func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVBstoreconst [x] {sym1} (LEAQ1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVBstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVBstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVBstoreconst [x] {sym} (ADDQ ptr idx) mem) - // result: (MOVBstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(OpAMD64MOVBstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) + // match: (MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) + // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) for { c := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVBstoreconst { break @@ -11235,22 +11229,23 @@ func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { break } v.reset(OpAMD64MOVWstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } - // match: (MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) + // match: (MOVBstoreconst [a] {s} p1 x:(MOVBstoreconst [c] {s} p0 mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) + // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p0 mem) for { a := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVBstoreconst { break @@ -11260,13 +11255,14 @@ func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { break } v.reset(OpAMD64MOVWstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } // match: (MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) @@ -11314,614 +11310,6 @@ func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVBstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBstoreconstidx1 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVBstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVBstoreconstidx1 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVBstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVBstoreconstidx1 [c] {s} p i x:(MOVBstoreconstidx1 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) - // result: (MOVWstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p i mem) - for { - c := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - i := v_1 - x := v_2 - if x.Op != OpAMD64MOVBstoreconstidx1 { - continue - } - a := x.AuxInt - if x.Aux != s { - continue - } - mem := x.Args[2] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || i != x_1 || !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { - continue - } - v.reset(OpAMD64MOVWstoreconstidx1) - v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) - v.Aux = s - v.AddArg3(p, i, mem) - return true - } - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVBstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - // match: (MOVBstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVBstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVBstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+d) - // result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVBstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx w x0:(MOVBstoreidx1 [i-1] {s} p idx (SHRWconst [8] w) mem)) - // cond: x0.Uses == 1 && clobber(x0) - // result: (MOVWstoreidx1 [i-1] {s} p idx (ROLWconst [8] w) mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - w := v_2 - x0 := v_3 - if x0.Op != OpAMD64MOVBstoreidx1 || x0.AuxInt != i-1 || x0.Aux != s { - continue - } - mem := x0.Args[3] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 { - continue - } - x0_2 := x0.Args[2] - if x0_2.Op != OpAMD64SHRWconst || x0_2.AuxInt != 8 || w != x0_2.Args[0] || !(x0.Uses == 1 && clobber(x0)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, w.Type) - v0.AuxInt = 8 - v0.AddArg(w) - v.AddArg4(p, idx, v0, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx w x2:(MOVBstoreidx1 [i-1] {s} p idx (SHRLconst [8] w) x1:(MOVBstoreidx1 [i-2] {s} p idx (SHRLconst [16] w) x0:(MOVBstoreidx1 [i-3] {s} p idx (SHRLconst [24] w) mem)))) - // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2) - // result: (MOVLstoreidx1 [i-3] {s} p idx (BSWAPL w) mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - w := v_2 - x2 := v_3 - if x2.Op != OpAMD64MOVBstoreidx1 || x2.AuxInt != i-1 || x2.Aux != s { - continue - } - _ = x2.Args[3] - x2_0 := x2.Args[0] - x2_1 := x2.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x2_0, x2_1 = _i1+1, x2_1, x2_0 { - if p != x2_0 || idx != x2_1 { - continue - } - x2_2 := x2.Args[2] - if x2_2.Op != OpAMD64SHRLconst || x2_2.AuxInt != 8 || w != x2_2.Args[0] { - continue - } - x1 := x2.Args[3] - if x1.Op != OpAMD64MOVBstoreidx1 || x1.AuxInt != i-2 || x1.Aux != s { - continue - } - _ = x1.Args[3] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 { - continue - } - x1_2 := x1.Args[2] - if x1_2.Op != OpAMD64SHRLconst || x1_2.AuxInt != 16 || w != x1_2.Args[0] { - continue - } - x0 := x1.Args[3] - if x0.Op != OpAMD64MOVBstoreidx1 || x0.AuxInt != i-3 || x0.Aux != s { - continue - } - mem := x0.Args[3] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x0_0, x0_1 = _i3+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 { - continue - } - x0_2 := x0.Args[2] - if x0_2.Op != OpAMD64SHRLconst || x0_2.AuxInt != 24 || w != x0_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && clobber(x0, x1, x2)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 3 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64BSWAPL, w.Type) - v0.AddArg(w) - v.AddArg4(p, idx, v0, mem) - return true - } - } - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx w x6:(MOVBstoreidx1 [i-1] {s} p idx (SHRQconst [8] w) x5:(MOVBstoreidx1 [i-2] {s} p idx (SHRQconst [16] w) x4:(MOVBstoreidx1 [i-3] {s} p idx (SHRQconst [24] w) x3:(MOVBstoreidx1 [i-4] {s} p idx (SHRQconst [32] w) x2:(MOVBstoreidx1 [i-5] {s} p idx (SHRQconst [40] w) x1:(MOVBstoreidx1 [i-6] {s} p idx (SHRQconst [48] w) x0:(MOVBstoreidx1 [i-7] {s} p idx (SHRQconst [56] w) mem)))))))) - // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6) - // result: (MOVQstoreidx1 [i-7] {s} p idx (BSWAPQ w) mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - w := v_2 - x6 := v_3 - if x6.Op != OpAMD64MOVBstoreidx1 || x6.AuxInt != i-1 || x6.Aux != s { - continue - } - _ = x6.Args[3] - x6_0 := x6.Args[0] - x6_1 := x6.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x6_0, x6_1 = _i1+1, x6_1, x6_0 { - if p != x6_0 || idx != x6_1 { - continue - } - x6_2 := x6.Args[2] - if x6_2.Op != OpAMD64SHRQconst || x6_2.AuxInt != 8 || w != x6_2.Args[0] { - continue - } - x5 := x6.Args[3] - if x5.Op != OpAMD64MOVBstoreidx1 || x5.AuxInt != i-2 || x5.Aux != s { - continue - } - _ = x5.Args[3] - x5_0 := x5.Args[0] - x5_1 := x5.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x5_0, x5_1 = _i2+1, x5_1, x5_0 { - if p != x5_0 || idx != x5_1 { - continue - } - x5_2 := x5.Args[2] - if x5_2.Op != OpAMD64SHRQconst || x5_2.AuxInt != 16 || w != x5_2.Args[0] { - continue - } - x4 := x5.Args[3] - if x4.Op != OpAMD64MOVBstoreidx1 || x4.AuxInt != i-3 || x4.Aux != s { - continue - } - _ = x4.Args[3] - x4_0 := x4.Args[0] - x4_1 := x4.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x4_0, x4_1 = _i3+1, x4_1, x4_0 { - if p != x4_0 || idx != x4_1 { - continue - } - x4_2 := x4.Args[2] - if x4_2.Op != OpAMD64SHRQconst || x4_2.AuxInt != 24 || w != x4_2.Args[0] { - continue - } - x3 := x4.Args[3] - if x3.Op != OpAMD64MOVBstoreidx1 || x3.AuxInt != i-4 || x3.Aux != s { - continue - } - _ = x3.Args[3] - x3_0 := x3.Args[0] - x3_1 := x3.Args[1] - for _i4 := 0; _i4 <= 1; _i4, x3_0, x3_1 = _i4+1, x3_1, x3_0 { - if p != x3_0 || idx != x3_1 { - continue - } - x3_2 := x3.Args[2] - if x3_2.Op != OpAMD64SHRQconst || x3_2.AuxInt != 32 || w != x3_2.Args[0] { - continue - } - x2 := x3.Args[3] - if x2.Op != OpAMD64MOVBstoreidx1 || x2.AuxInt != i-5 || x2.Aux != s { - continue - } - _ = x2.Args[3] - x2_0 := x2.Args[0] - x2_1 := x2.Args[1] - for _i5 := 0; _i5 <= 1; _i5, x2_0, x2_1 = _i5+1, x2_1, x2_0 { - if p != x2_0 || idx != x2_1 { - continue - } - x2_2 := x2.Args[2] - if x2_2.Op != OpAMD64SHRQconst || x2_2.AuxInt != 40 || w != x2_2.Args[0] { - continue - } - x1 := x2.Args[3] - if x1.Op != OpAMD64MOVBstoreidx1 || x1.AuxInt != i-6 || x1.Aux != s { - continue - } - _ = x1.Args[3] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i6 := 0; _i6 <= 1; _i6, x1_0, x1_1 = _i6+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 { - continue - } - x1_2 := x1.Args[2] - if x1_2.Op != OpAMD64SHRQconst || x1_2.AuxInt != 48 || w != x1_2.Args[0] { - continue - } - x0 := x1.Args[3] - if x0.Op != OpAMD64MOVBstoreidx1 || x0.AuxInt != i-7 || x0.Aux != s { - continue - } - mem := x0.Args[3] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i7 := 0; _i7 <= 1; _i7, x0_0, x0_1 = _i7+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 { - continue - } - x0_2 := x0.Args[2] - if x0_2.Op != OpAMD64SHRQconst || x0_2.AuxInt != 56 || w != x0_2.Args[0] || !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && clobber(x0, x1, x2, x3, x4, x5, x6)) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = i - 7 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64BSWAPQ, w.Type) - v0.AddArg(w) - v.AddArg4(p, idx, v0, mem) - return true - } - } - } - } - } - } - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRWconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRWconst || v_2.AuxInt != 8 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRLconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRLconst || v_2.AuxInt != 8 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRQconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst || v_2.AuxInt != 8 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHRLconst [j-8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRLconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRLconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p idx (SHRQconst [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHRQconst [j-8] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVWstoreidx1 [i-1] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVBstoreidx1 || x.AuxInt != i-1 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-8 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = i - 1 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - // match: (MOVBstoreidx1 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+c) - // result: (MOVBstore [i+c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVBstore) - v.AuxInt = i + c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - break - } - // match: (MOVBstoreidx1 [off] {s} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(int64(int8(c)), off) - // result: (MOVBstoreconstidx1 [makeValAndOff(int64(int8(c)), off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(int64(int8(c)), off)) { - break - } - v.reset(OpAMD64MOVBstoreconstidx1) - v.AuxInt = makeValAndOff(int64(int8(c)), off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVLQSX(v *Value) bool { v_0 := v.Args[0] b := v.Block @@ -12131,54 +11519,6 @@ func rewriteValueAMD64_OpAMD64MOVLQZX(v *Value) bool { v.copyOf(x) return true } - // match: (MOVLQZX x:(MOVLloadidx1 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVLloadidx1 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != OpAMD64MOVLloadidx1 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLQZX x:(MOVLloadidx4 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVLloadidx4 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != OpAMD64MOVLloadidx4 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx4, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } // match: (MOVLQZX (ANDLconst [c] x)) // result: (ANDLconst [c] x) for { @@ -12396,101 +11736,117 @@ func rewriteValueAMD64_OpAMD64MOVLload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVLload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAQ1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAQ1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVLloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVLload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAQ2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAQ2 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ4 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVLloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVLload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAQ4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAQ4 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVLloadidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVLload [off] {sym} (ADDQ ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVLloadidx1 [off] {sym} ptr idx mem) + // match: (MOVLload [i0] {s0} l:(LEAQ8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLload [i0+i1] {s0} (LEAQ8 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVLloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVLload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem) // cond: canMergeSym(sym1, sym2) && is32Bit(off1+off2) @@ -12567,268 +11923,6 @@ func rewriteValueAMD64_OpAMD64MOVLload(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVLloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLloadidx1 [c] {sym} ptr (SHLQconst [2] idx) mem) - // result: (MOVLloadidx4 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 2 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVLloadidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLloadidx1 [c] {sym} ptr (SHLQconst [3] idx) mem) - // result: (MOVLloadidx8 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVLloadidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVLloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVLloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+d) - // result: (MOVLloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVLloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLloadidx1 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+c) - // result: (MOVLload [i+c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVLload) - v.AuxInt = i + c - v.Aux = s - v.AddArg2(p, mem) - return true - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVLloadidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLloadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVLloadidx4 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVLloadidx4) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLloadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+4*d) - // result: (MOVLloadidx4 [c+4*d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + 4*d)) { - break - } - v.reset(OpAMD64MOVLloadidx4) - v.AuxInt = c + 4*d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLloadidx4 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+4*c) - // result: (MOVLload [i+4*c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + 4*c)) { - break - } - v.reset(OpAMD64MOVLload) - v.AuxInt = i + 4*c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVLloadidx8(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVLloadidx8 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVLloadidx8) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+8*d) - // result: (MOVLloadidx8 [c+8*d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + 8*d)) { - break - } - v.reset(OpAMD64MOVLloadidx8) - v.AuxInt = c + 8*d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLloadidx8 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+8*c) - // result: (MOVLload [i+8*c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + 8*c)) { - break - } - v.reset(OpAMD64MOVLload) - v.AuxInt = i + 8*c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -12956,113 +12050,129 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVLstore [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVLstore [i0] {s0} l:(LEAQ1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAQ1 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVLstore [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVLstore [i0] {s0} l:(LEAQ2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAQ2 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ4 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVLstoreidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVLstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVLstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVLstore [i0] {s0} l:(LEAQ4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAQ4 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVLstoreidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVLstore [off] {sym} (ADDQ ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVLstoreidx1 [off] {sym} ptr idx val mem) + // match: (MOVLstore [i0] {s0} l:(LEAQ8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVLstore [i0+i1] {s0} (LEAQ8 [0] {s1} x y) val mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVLstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true } - // match: (MOVLstore [i] {s} p (SHRQconst [32] w) x:(MOVLstore [i-4] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVQstore [i-4] {s} p w mem) + // match: (MOVLstore [i] {s} p1 (SHRQconst [32] w) x:(MOVLstore [i-4] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVQstore [i-4] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRQconst || v_1.AuxInt != 32 { break } @@ -13072,22 +12182,23 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVQstore) v.AuxInt = i - 4 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVLstore [i] {s} p (SHRQconst [j] w) x:(MOVLstore [i-4] {s} p w0:(SHRQconst [j-32] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVQstore [i-4] {s} p w0 mem) + // match: (MOVLstore [i] {s} p1 (SHRQconst [j] w) x:(MOVLstore [i-4] {s} p0 w0:(SHRQconst [j-32] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVQstore [i-4] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRQconst { break } @@ -13098,17 +12209,15 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-32 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-32 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVQstore) v.AuxInt = i - 4 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) return true } // match: (MOVLstore [i] {s} p x1:(MOVLload [j] {s2} p2 mem) mem2:(MOVLstore [i-4] {s} p x2:(MOVLload [j-4] {s2} p2 mem) mem)) @@ -13785,76 +12894,13 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVLstoreconst [x] {sym1} (LEAQ1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVLstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconst [x] {sym1} (LEAQ4 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVLstoreconstidx4 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ4 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx4) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconst [x] {sym} (ADDQ ptr idx) mem) - // result: (MOVLstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconst [c] {s} p x:(MOVLstoreconst [a] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) - // result: (MOVQstore [ValAndOff(a).Off()] {s} p (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) + // match: (MOVLstoreconst [c] {s} p1 x:(MOVLstoreconst [a] {s} p0 mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) + // result: (MOVQstore [ValAndOff(a).Off()] {s} p0 (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) for { c := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVLstoreconst { break @@ -13864,7 +12910,8 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+4 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off()+4 == ValAndOff(c).Off() && clobber(x)) { break } v.reset(OpAMD64MOVQstore) @@ -13872,16 +12919,16 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { v.Aux = s v0 := b.NewValue0(x.Pos, OpAMD64MOVQconst, typ.UInt64) v0.AuxInt = ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32 - v.AddArg3(p, v0, mem) + v.AddArg3(p0, v0, mem) return true } - // match: (MOVLstoreconst [a] {s} p x:(MOVLstoreconst [c] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) - // result: (MOVQstore [ValAndOff(a).Off()] {s} p (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) + // match: (MOVLstoreconst [a] {s} p1 x:(MOVLstoreconst [c] {s} p0 mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) + // result: (MOVQstore [ValAndOff(a).Off()] {s} p0 (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) for { a := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVLstoreconst { break @@ -13891,7 +12938,8 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+4 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off()+4 == ValAndOff(c).Off() && clobber(x)) { break } v.reset(OpAMD64MOVQstore) @@ -13899,7 +12947,7 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { v.Aux = s v0 := b.NewValue0(x.Pos, OpAMD64MOVQconst, typ.UInt64) v0.AuxInt = ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32 - v.AddArg3(p, v0, mem) + v.AddArg3(p0, v0, mem) return true } // match: (MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) @@ -13947,657 +12995,6 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVLstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - typ := &b.Func.Config.Types - // match: (MOVLstoreconstidx1 [c] {sym} ptr (SHLQconst [2] idx) mem) - // result: (MOVLstoreconstidx4 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 2 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVLstoreconstidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLstoreconstidx1 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLstoreconstidx1 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVLstoreconstidx1 [c] {s} p i x:(MOVLstoreconstidx1 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) - // result: (MOVQstoreidx1 [ValAndOff(a).Off()] {s} p i (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) - for { - c := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - i := v_1 - x := v_2 - if x.Op != OpAMD64MOVLstoreconstidx1 { - continue - } - a := x.AuxInt - if x.Aux != s { - continue - } - mem := x.Args[2] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || i != x_1 || !(x.Uses == 1 && ValAndOff(a).Off()+4 == ValAndOff(c).Off() && clobber(x)) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = ValAndOff(a).Off() - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64) - v0.AuxInt = ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32 - v.AddArg4(p, i, v0, mem) - return true - } - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVLstoreconstidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - typ := &b.Func.Config.Types - // match: (MOVLstoreconstidx4 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVLstoreconstidx4 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx4) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconstidx4 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(4*c) - // result: (MOVLstoreconstidx4 [ValAndOff(x).add(4*c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(4 * c)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx4) - v.AuxInt = ValAndOff(x).add(4 * c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVLstoreconstidx4 [c] {s} p i x:(MOVLstoreconstidx4 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 4 == ValAndOff(c).Off() && clobber(x) - // result: (MOVQstoreidx1 [ValAndOff(a).Off()] {s} p (SHLQconst [2] i) (MOVQconst [ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32]) mem) - for { - c := v.AuxInt - s := v.Aux - p := v_0 - i := v_1 - x := v_2 - if x.Op != OpAMD64MOVLstoreconstidx4 { - break - } - a := x.AuxInt - if x.Aux != s { - break - } - mem := x.Args[2] - if p != x.Args[0] || i != x.Args[1] || !(x.Uses == 1 && ValAndOff(a).Off()+4 == ValAndOff(c).Off() && clobber(x)) { - break - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = ValAndOff(a).Off() - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, i.Type) - v0.AuxInt = 2 - v0.AddArg(i) - v1 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64) - v1.AuxInt = ValAndOff(a).Val()&0xffffffff | ValAndOff(c).Val()<<32 - v.AddArg4(p, v0, v1, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVLstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLstoreidx1 [c] {sym} ptr (SHLQconst [2] idx) val mem) - // result: (MOVLstoreidx4 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 2 { - continue - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(OpAMD64MOVLstoreidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [c] {sym} ptr (SHLQconst [3] idx) val mem) - // result: (MOVLstoreidx8 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - continue - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(OpAMD64MOVLstoreidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+d) - // result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [i] {s} p idx (SHRQconst [32] w) x:(MOVLstoreidx1 [i-4] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVQstoreidx1 [i-4] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst || v_2.AuxInt != 32 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVLstoreidx1 || x.AuxInt != i-4 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = i - 4 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVLstoreidx1 [i] {s} p idx (SHRQconst [j] w) x:(MOVLstoreidx1 [i-4] {s} p idx w0:(SHRQconst [j-32] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVQstoreidx1 [i-4] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVLstoreidx1 || x.AuxInt != i-4 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-32 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = i - 4 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - // match: (MOVLstoreidx1 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+c) - // result: (MOVLstore [i+c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVLstore) - v.AuxInt = i + c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - break - } - // match: (MOVLstoreidx1 [off] {s} ptr idx (MOVQconst [c]) mem) - // cond: validValAndOff(int64(int32(c)), off) - // result: (MOVLstoreconstidx1 [makeValAndOff(int64(int32(c)), off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVQconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(int64(int32(c)), off)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = makeValAndOff(int64(int32(c)), off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVLstoreidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - // match: (MOVLstoreidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVLstoreidx4 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVLstoreidx4) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstoreidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+4*d) - // result: (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + 4*d)) { - break - } - v.reset(OpAMD64MOVLstoreidx4) - v.AuxInt = c + 4*d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstoreidx4 [i] {s} p idx (SHRQconst [32] w) x:(MOVLstoreidx4 [i-4] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVQstoreidx1 [i-4] {s} p (SHLQconst [2] idx) w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst || v_2.AuxInt != 32 { - break - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVLstoreidx4 || x.AuxInt != i-4 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = i - 4 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, idx.Type) - v0.AuxInt = 2 - v0.AddArg(idx) - v.AddArg4(p, v0, w, mem) - return true - } - // match: (MOVLstoreidx4 [i] {s} p idx (SHRQconst [j] w) x:(MOVLstoreidx4 [i-4] {s} p idx w0:(SHRQconst [j-32] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVQstoreidx1 [i-4] {s} p (SHLQconst [2] idx) w0 mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst { - break - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVLstoreidx4 || x.AuxInt != i-4 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] { - break - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-32 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = i - 4 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, idx.Type) - v0.AuxInt = 2 - v0.AddArg(idx) - v.AddArg4(p, v0, w0, mem) - return true - } - // match: (MOVLstoreidx4 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+4*c) - // result: (MOVLstore [i+4*c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + 4*c)) { - break - } - v.reset(OpAMD64MOVLstore) - v.AuxInt = i + 4*c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - // match: (MOVLstoreidx4 [off] {s} ptr idx (MOVQconst [c]) mem) - // cond: validValAndOff(int64(int32(c)), off) - // result: (MOVLstoreconstidx4 [makeValAndOff(int64(int32(c)), off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVQconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(int64(int32(c)), off)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx4) - v.AuxInt = makeValAndOff(int64(int32(c)), off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVLstoreidx8(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVLstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVLstoreidx8 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVLstoreidx8) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+8*d) - // result: (MOVLstoreidx8 [c+8*d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + 8*d)) { - break - } - v.reset(OpAMD64MOVLstoreidx8) - v.AuxInt = c + 8*d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVLstoreidx8 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+8*c) - // result: (MOVLstore [i+8*c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + 8*c)) { - break - } - v.reset(OpAMD64MOVLstore) - v.AuxInt = i + 8*c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVOload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -14902,78 +13299,117 @@ func rewriteValueAMD64_OpAMD64MOVQload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVQload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVQloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVQload [i0] {s0} l:(LEAQ1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQload [i0+i1] {s0} (LEAQ1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVQloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVQload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVQload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVQloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVQload [i0] {s0} l:(LEAQ2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQload [i0+i1] {s0} (LEAQ2 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVQloadidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVQload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVQload [off] {sym} (ADDQ ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVQloadidx1 [off] {sym} ptr idx mem) + // match: (MOVQload [i0] {s0} l:(LEAQ4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQload [i0+i1] {s0} (LEAQ4 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVQloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVQload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVQload [i0] {s0} l:(LEAQ8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQload [i0+i1] {s0} (LEAQ8 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVQload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVQload [off1] {sym1} (LEAL [off2] {sym2} base) mem) // cond: canMergeSym(sym1, sym2) && is32Bit(off1+off2) @@ -15050,181 +13486,11 @@ func rewriteValueAMD64_OpAMD64MOVQload(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVQloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVQloadidx1 [c] {sym} ptr (SHLQconst [3] idx) mem) - // result: (MOVQloadidx8 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVQloadidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVQloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVQloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVQloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVQloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+d) - // result: (MOVQloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVQloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVQloadidx1 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+c) - // result: (MOVQload [i+c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVQload) - v.AuxInt = i + c - v.Aux = s - v.AddArg2(p, mem) - return true - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVQloadidx8(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVQloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVQloadidx8 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVQloadidx8) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVQloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+8*d) - // result: (MOVQloadidx8 [c+8*d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + 8*d)) { - break - } - v.reset(OpAMD64MOVQloadidx8) - v.AuxInt = c + 8*d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVQloadidx8 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+8*c) - // result: (MOVQload [i+8*c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + 8*c)) { - break - } - v.reset(OpAMD64MOVQload) - v.AuxInt = i + 8*c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] v_0 := v.Args[0] + b := v.Block // match: (MOVQstore [off1] {sym} (ADDQconst [off2] ptr) val mem) // cond: is32Bit(off1+off2) // result: (MOVQstore [off1+off2] {sym} ptr val mem) @@ -15291,81 +13557,121 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVQstore [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVQstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVQstore [i0] {s0} l:(LEAQ1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQstore [i0+i1] {s0} (LEAQ1 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVQstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVQstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVQstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVQstore [i0] {s0} l:(LEAQ2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQstore [i0+i1] {s0} (LEAQ2 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVQstoreidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVQstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVQstore [off] {sym} (ADDQ ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVQstoreidx1 [off] {sym} ptr idx val mem) + // match: (MOVQstore [i0] {s0} l:(LEAQ4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQstore [i0+i1] {s0} (LEAQ4 [0] {s1} x y) val mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVQstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVQstore [i0] {s0} l:(LEAQ8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVQstore [i0+i1] {s0} (LEAQ8 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVQstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true } // match: (MOVQstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) // cond: canMergeSym(sym1, sym2) && is32Bit(off1+off2) @@ -16000,76 +14306,13 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVQstoreconst [x] {sym1} (LEAQ1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVQstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVQstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVQstoreconst [x] {sym1} (LEAQ8 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVQstoreconstidx8 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVQstoreconstidx8) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVQstoreconst [x] {sym} (ADDQ ptr idx) mem) - // result: (MOVQstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(OpAMD64MOVQstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVQstoreconst [c] {s} p x:(MOVQstoreconst [c2] {s} p mem)) - // cond: config.useSSE && x.Uses == 1 && ValAndOff(c2).Off() + 8 == ValAndOff(c).Off() && ValAndOff(c).Val() == 0 && ValAndOff(c2).Val() == 0 && clobber(x) - // result: (MOVOstore [ValAndOff(c2).Off()] {s} p (MOVOconst [0]) mem) + // match: (MOVQstoreconst [c] {s} p1 x:(MOVQstoreconst [c2] {s} p0 mem)) + // cond: config.useSSE && x.Uses == 1 && same(p0, p1, 1) && ValAndOff(c2).Off() + 8 == ValAndOff(c).Off() && ValAndOff(c).Val() == 0 && ValAndOff(c2).Val() == 0 && clobber(x) + // result: (MOVOstore [ValAndOff(c2).Off()] {s} p0 (MOVOconst [0]) mem) for { c := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVQstoreconst { break @@ -16079,7 +14322,8 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(config.useSSE && x.Uses == 1 && ValAndOff(c2).Off()+8 == ValAndOff(c).Off() && ValAndOff(c).Val() == 0 && ValAndOff(c2).Val() == 0 && clobber(x)) { + p0 := x.Args[0] + if !(config.useSSE && x.Uses == 1 && same(p0, p1, 1) && ValAndOff(c2).Off()+8 == ValAndOff(c).Off() && ValAndOff(c).Val() == 0 && ValAndOff(c2).Val() == 0 && clobber(x)) { break } v.reset(OpAMD64MOVOstore) @@ -16087,7 +14331,7 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { v.Aux = s v0 := b.NewValue0(x.Pos, OpAMD64MOVOconst, types.TypeInt128) v0.AuxInt = 0 - v.AddArg3(p, v0, mem) + v.AddArg3(p0, v0, mem) return true } // match: (MOVQstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) @@ -16135,356 +14379,6 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVQstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVQstoreconstidx1 [c] {sym} ptr (SHLQconst [3] idx) mem) - // result: (MOVQstoreconstidx8 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVQstoreconstidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVQstoreconstidx1 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVQstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVQstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVQstoreconstidx1 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVQstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVQstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVQstoreconstidx8(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVQstoreconstidx8 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVQstoreconstidx8 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - break - } - v.reset(OpAMD64MOVQstoreconstidx8) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVQstoreconstidx8 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(8*c) - // result: (MOVQstoreconstidx8 [ValAndOff(x).add(8*c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(8 * c)) { - break - } - v.reset(OpAMD64MOVQstoreconstidx8) - v.AuxInt = ValAndOff(x).add(8 * c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVQstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVQstoreidx1 [c] {sym} ptr (SHLQconst [3] idx) val mem) - // result: (MOVQstoreidx8 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - continue - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(OpAMD64MOVQstoreidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVQstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVQstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVQstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+d) - // result: (MOVQstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVQstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVQstoreidx1 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+c) - // result: (MOVQstore [i+c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVQstore) - v.AuxInt = i + c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - break - } - // match: (MOVQstoreidx1 [off] {s} ptr idx (MOVQconst [c]) mem) - // cond: validValAndOff(c, off) - // result: (MOVQstoreconstidx1 [makeValAndOff(c, off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVQconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(c, off)) { - break - } - v.reset(OpAMD64MOVQstoreconstidx1) - v.AuxInt = makeValAndOff(c, off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVQstoreidx8(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVQstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVQstoreidx8 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVQstoreidx8) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVQstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+8*d) - // result: (MOVQstoreidx8 [c+8*d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + 8*d)) { - break - } - v.reset(OpAMD64MOVQstoreidx8) - v.AuxInt = c + 8*d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVQstoreidx8 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+8*c) - // result: (MOVQstore [i+8*c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + 8*c)) { - break - } - v.reset(OpAMD64MOVQstore) - v.AuxInt = i + 8*c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - // match: (MOVQstoreidx8 [off] {s} ptr idx (MOVQconst [c]) mem) - // cond: validValAndOff(c, off) - // result: (MOVQstoreconstidx8 [makeValAndOff(c, off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVQconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(c, off)) { - break - } - v.reset(OpAMD64MOVQstoreconstidx8) - v.AuxInt = makeValAndOff(c, off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVSDload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -16531,79 +14425,6 @@ func rewriteValueAMD64_OpAMD64MOVSDload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVSDload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSDloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSDloadidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDload [off] {sym} (ADDQ ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVSDloadidx1 [off] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVSDloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } // match: (MOVSDload [off] {sym} ptr (MOVQstore [off] {sym} ptr val _)) // result: (MOVQi2f val) for { @@ -16623,165 +14444,6 @@ func rewriteValueAMD64_OpAMD64MOVSDload(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVSDloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDloadidx1 [c] {sym} ptr (SHLQconst [3] idx) mem) - // result: (MOVSDloadidx8 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - break - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVSDloadidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSDloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+d) - // result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSDloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx1 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+c) - // result: (MOVSDload [i+c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + c)) { - break - } - v.reset(OpAMD64MOVSDload) - v.AuxInt = i + c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVSDloadidx8(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVSDloadidx8 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSDloadidx8) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+8*d) - // result: (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + 8*d)) { - break - } - v.reset(OpAMD64MOVSDloadidx8) - v.AuxInt = c + 8*d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSDloadidx8 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+8*c) - // result: (MOVSDload [i+8*c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + 8*c)) { - break - } - v.reset(OpAMD64MOVSDload) - v.AuxInt = i + 8*c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVSDstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -16831,82 +14493,6 @@ func rewriteValueAMD64_OpAMD64MOVSDstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVSDstore [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSDstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSDstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ8 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSDstoreidx8) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstore [off] {sym} (ADDQ ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVSDstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVSDstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } // match: (MOVSDstore [off] {sym} ptr (MOVQi2f val) mem) // result: (MOVQstore [off] {sym} ptr val mem) for { @@ -16926,174 +14512,6 @@ func rewriteValueAMD64_OpAMD64MOVSDstore(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVSDstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDstoreidx1 [c] {sym} ptr (SHLQconst [3] idx) val mem) - // result: (MOVSDstoreidx8 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 3 { - break - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(OpAMD64MOVSDstoreidx8) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSDstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+d) - // result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSDstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx1 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+c) - // result: (MOVSDstore [i+c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + c)) { - break - } - v.reset(OpAMD64MOVSDstore) - v.AuxInt = i + c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVSDstoreidx8(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSDstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSDstoreidx8) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+8*d) - // result: (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + 8*d)) { - break - } - v.reset(OpAMD64MOVSDstoreidx8) - v.AuxInt = c + 8*d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSDstoreidx8 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+8*c) - // result: (MOVSDstore [i+8*c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + 8*c)) { - break - } - v.reset(OpAMD64MOVSDstore) - v.AuxInt = i + 8*c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVSSload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -17140,79 +14558,6 @@ func rewriteValueAMD64_OpAMD64MOVSSload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVSSload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSSloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ4 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSSloadidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSload [off] {sym} (ADDQ ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVSSloadidx1 [off] {sym} ptr idx mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVSSloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } // match: (MOVSSload [off] {sym} ptr (MOVLstore [off] {sym} ptr val _)) // result: (MOVLi2f val) for { @@ -17232,165 +14577,6 @@ func rewriteValueAMD64_OpAMD64MOVSSload(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVSSloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSloadidx1 [c] {sym} ptr (SHLQconst [2] idx) mem) - // result: (MOVSSloadidx4 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 2 { - break - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVSSloadidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSSloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+d) - // result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSSloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx1 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+c) - // result: (MOVSSload [i+c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + c)) { - break - } - v.reset(OpAMD64MOVSSload) - v.AuxInt = i + c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVSSloadidx4(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSloadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVSSloadidx4 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSSloadidx4) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+4*d) - // result: (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + 4*d)) { - break - } - v.reset(OpAMD64MOVSSloadidx4) - v.AuxInt = c + 4*d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVSSloadidx4 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+4*c) - // result: (MOVSSload [i+4*c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + 4*c)) { - break - } - v.reset(OpAMD64MOVSSload) - v.AuxInt = i + 4*c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVSSstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -17440,82 +14626,6 @@ func rewriteValueAMD64_OpAMD64MOVSSstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVSSstore [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSSstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstore [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVSSstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) - for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ4 { - break - } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVSSstoreidx4) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstore [off] {sym} (ADDQ ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVSSstoreidx1 [off] {sym} ptr idx val mem) - for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVSSstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } // match: (MOVSSstore [off] {sym} ptr (MOVLi2f val) mem) // result: (MOVLstore [off] {sym} ptr val mem) for { @@ -17535,174 +14645,6 @@ func rewriteValueAMD64_OpAMD64MOVSSstore(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVSSstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSstoreidx1 [c] {sym} ptr (SHLQconst [2] idx) val mem) - // result: (MOVSSstoreidx4 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 2 { - break - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(OpAMD64MOVSSstoreidx4) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSSstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+d) - // result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSSstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx1 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+c) - // result: (MOVSSstore [i+c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + c)) { - break - } - v.reset(OpAMD64MOVSSstore) - v.AuxInt = i + c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVSSstoreidx4(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVSSstoreidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVSSstoreidx4) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+4*d) - // result: (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + 4*d)) { - break - } - v.reset(OpAMD64MOVSSstoreidx4) - v.AuxInt = c + 4*d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVSSstoreidx4 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+4*c) - // result: (MOVSSstore [i+4*c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + 4*c)) { - break - } - v.reset(OpAMD64MOVSSstore) - v.AuxInt = i + 4*c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVWQSX(v *Value) bool { v_0 := v.Args[0] b := v.Block @@ -17947,54 +14889,6 @@ func rewriteValueAMD64_OpAMD64MOVWQZX(v *Value) bool { v.copyOf(x) return true } - // match: (MOVWQZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVWloadidx1 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != OpAMD64MOVWloadidx1 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWQZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) - // cond: x.Uses == 1 && clobber(x) - // result: @x.Block (MOVWloadidx2 [off] {sym} ptr idx mem) - for { - x := v_0 - if x.Op != OpAMD64MOVWloadidx2 { - break - } - off := x.AuxInt - sym := x.Aux - mem := x.Args[2] - ptr := x.Args[0] - idx := x.Args[1] - if !(x.Uses == 1 && clobber(x)) { - break - } - b = x.Block - v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx2, v.Type) - v.copyOf(v0) - v0.AuxInt = off - v0.Aux = sym - v0.AddArg3(ptr, idx, mem) - return true - } // match: (MOVWQZX (ANDLconst [c] x)) // result: (ANDLconst [c & 0xffff] x) for { @@ -18101,78 +14995,117 @@ func rewriteValueAMD64_OpAMD64MOVWload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVWload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVWload [i0] {s0} l:(LEAQ1 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAQ1 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVWloadidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVWload [off1] {sym1} (LEAQ2 [off2] {sym2} ptr idx) mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWloadidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + // match: (MOVWload [i0] {s0} l:(LEAQ2 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAQ2 [0] {s1} x y) mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ2 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] mem := v_1 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVWloadidx2) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) + v.reset(OpAMD64MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) return true } - // match: (MOVWload [off] {sym} (ADDQ ptr idx) mem) - // cond: ptr.Op != OpSB - // result: (MOVWloadidx1 [off] {sym} ptr idx mem) + // match: (MOVWload [i0] {s0} l:(LEAQ4 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAQ4 [0] {s1} x y) mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - mem := v_1 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVWloadidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true + } + // match: (MOVWload [i0] {s0} l:(LEAQ8 [i1] {s1} x y) mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWload [i0+i1] {s0} (LEAQ8 [0] {s1} x y) mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + mem := v_1 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVWload) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg2(v0, mem) + return true } // match: (MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem) // cond: canMergeSym(sym1, sym2) && is32Bit(off1+off2) @@ -18232,177 +15165,6 @@ func rewriteValueAMD64_OpAMD64MOVWload(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVWloadidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWloadidx1 [c] {sym} ptr (SHLQconst [1] idx) mem) - // result: (MOVWloadidx2 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 1 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVWloadidx2) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVWloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVWloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+d) - // result: (MOVWloadidx1 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVWloadidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWloadidx1 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+c) - // result: (MOVWload [i+c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVWload) - v.AuxInt = i + c - v.Aux = s - v.AddArg2(p, mem) - return true - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVWloadidx2(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWloadidx2 [c] {sym} (ADDQconst [d] ptr) idx mem) - // cond: is32Bit(c+d) - // result: (MOVWloadidx2 [c+d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVWloadidx2) - v.AuxInt = c + d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWloadidx2 [c] {sym} ptr (ADDQconst [d] idx) mem) - // cond: is32Bit(c+2*d) - // result: (MOVWloadidx2 [c+2*d] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(is32Bit(c + 2*d)) { - break - } - v.reset(OpAMD64MOVWloadidx2) - v.AuxInt = c + 2*d - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWloadidx2 [i] {s} p (MOVQconst [c]) mem) - // cond: is32Bit(i+2*c) - // result: (MOVWload [i+2*c] {s} p mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - mem := v_2 - if !(is32Bit(i + 2*c)) { - break - } - v.reset(OpAMD64MOVWload) - v.AuxInt = i + 2*c - v.Aux = s - v.AddArg2(p, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -18530,89 +15292,129 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVWstore [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVWstore [i0] {s0} l:(LEAQ1 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAQ1 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ1 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ1, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVWstore [off1] {sym1} (LEAQ2 [off2] {sym2} ptr idx) val mem) - // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) - // result: (MOVWstoreidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + // match: (MOVWstore [i0] {s0} l:(LEAQ2 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAQ2 [0] {s1} x y) val mem) for { - off1 := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ2 { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ2 { break } - off2 := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] val := v_1 mem := v_2 - if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + if !(i1 != 0 && is32Bit(i0+i1)) { break } - v.reset(OpAMD64MOVWstoreidx2) - v.AuxInt = off1 + off2 - v.Aux = mergeSym(sym1, sym2) - v.AddArg4(ptr, idx, val, mem) + v.reset(OpAMD64MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) return true } - // match: (MOVWstore [off] {sym} (ADDQ ptr idx) val mem) - // cond: ptr.Op != OpSB - // result: (MOVWstoreidx1 [off] {sym} ptr idx val mem) + // match: (MOVWstore [i0] {s0} l:(LEAQ4 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAQ4 [0] {s1} x y) val mem) for { - off := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ4 { break } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - ptr := v_0_0 - idx := v_0_1 - val := v_1 - mem := v_2 - if !(ptr.Op != OpSB) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = off - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break } - break + v.reset(OpAMD64MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true } - // match: (MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstore [i-2] {s} p w mem) + // match: (MOVWstore [i0] {s0} l:(LEAQ8 [i1] {s1} x y) val mem) + // cond: i1 != 0 && is32Bit(i0+i1) + // result: (MOVWstore [i0+i1] {s0} (LEAQ8 [0] {s1} x y) val mem) + for { + i0 := v.AuxInt + s0 := v.Aux + l := v_0 + if l.Op != OpAMD64LEAQ8 { + break + } + i1 := l.AuxInt + s1 := l.Aux + y := l.Args[1] + x := l.Args[0] + val := v_1 + mem := v_2 + if !(i1 != 0 && is32Bit(i0+i1)) { + break + } + v.reset(OpAMD64MOVWstore) + v.AuxInt = i0 + i1 + v.Aux = s0 + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, l.Type) + v0.AuxInt = 0 + v0.Aux = s1 + v0.AddArg2(x, y) + v.AddArg3(v0, val, mem) + return true + } + // match: (MOVWstore [i] {s} p1 (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVLstore [i-2] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRLconst || v_1.AuxInt != 16 { break } @@ -18622,22 +15424,23 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVLstore) v.AuxInt = i - 2 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVWstore [i] {s} p (SHRQconst [16] w) x:(MOVWstore [i-2] {s} p w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstore [i-2] {s} p w mem) + // match: (MOVWstore [i] {s} p1 (SHRQconst [16] w) x:(MOVWstore [i-2] {s} p0 w mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVLstore [i-2] {s} p0 w mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRQconst || v_1.AuxInt != 16 { break } @@ -18647,22 +15450,23 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] || w != x.Args[1] || !(x.Uses == 1 && clobber(x)) { + p0 := x.Args[0] + if w != x.Args[1] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVLstore) v.AuxInt = i - 2 v.Aux = s - v.AddArg3(p, w, mem) + v.AddArg3(p0, w, mem) return true } - // match: (MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstore [i-2] {s} p w0 mem) + // match: (MOVWstore [i] {s} p1 (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p0 w0:(SHRLconst [j-16] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVLstore [i-2] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRLconst { break } @@ -18673,26 +15477,24 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != OpAMD64SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != OpAMD64SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVLstore) v.AuxInt = i - 2 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) return true } - // match: (MOVWstore [i] {s} p (SHRQconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRQconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstore [i-2] {s} p w0 mem) + // match: (MOVWstore [i] {s} p1 (SHRQconst [j] w) x:(MOVWstore [i-2] {s} p0 w0:(SHRQconst [j-16] w) mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && clobber(x) + // result: (MOVLstore [i-2] {s} p0 w0 mem) for { i := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 if v_1.Op != OpAMD64SHRQconst { break } @@ -18703,17 +15505,15 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { break } mem := x.Args[2] - if p != x.Args[0] { - break - } + p0 := x.Args[0] w0 := x.Args[1] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { + if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && same(p0, p1, 1) && clobber(x)) { break } v.reset(OpAMD64MOVLstore) v.AuxInt = i - 2 v.Aux = s - v.AddArg3(p, w0, mem) + v.AddArg3(p0, w0, mem) return true } // match: (MOVWstore [i] {s} p x1:(MOVWload [j] {s2} p2 mem) mem2:(MOVWstore [i-2] {s} p x2:(MOVWload [j-2] {s2} p2 mem) mem)) @@ -18850,76 +15650,13 @@ func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVWstoreconst [x] {sym1} (LEAQ1 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVWstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ1 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVWstoreconstidx1) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconst [x] {sym1} (LEAQ2 [off] {sym2} ptr idx) mem) - // cond: canMergeSym(sym1, sym2) - // result: (MOVWstoreconstidx2 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) - for { - x := v.AuxInt - sym1 := v.Aux - if v_0.Op != OpAMD64LEAQ2 { - break - } - off := v_0.AuxInt - sym2 := v_0.Aux - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2)) { - break - } - v.reset(OpAMD64MOVWstoreconstidx2) - v.AuxInt = ValAndOff(x).add(off) - v.Aux = mergeSym(sym1, sym2) - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconst [x] {sym} (ADDQ ptr idx) mem) - // result: (MOVWstoreconstidx1 [x] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQ { - break - } - idx := v_0.Args[1] - ptr := v_0.Args[0] - mem := v_1 - v.reset(OpAMD64MOVWstoreconstidx1) - v.AuxInt = x - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) + // match: (MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) + // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) for { c := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVWstoreconst { break @@ -18929,22 +15666,23 @@ func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { break } v.reset(OpAMD64MOVLstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } - // match: (MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) + // match: (MOVWstoreconst [a] {s} p1 x:(MOVWstoreconst [c] {s} p0 mem)) + // cond: x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) + // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p0 mem) for { a := v.AuxInt s := v.Aux - p := v_0 + p1 := v_0 x := v_1 if x.Op != OpAMD64MOVWstoreconst { break @@ -18954,13 +15692,14 @@ func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { break } mem := x.Args[1] - if p != x.Args[0] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + p0 := x.Args[0] + if !(x.Uses == 1 && same(p0, p1, 1) && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { break } v.reset(OpAMD64MOVLstoreconst) v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) v.Aux = s - v.AddArg2(p, mem) + v.AddArg2(p0, mem) return true } // match: (MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) @@ -19008,654 +15747,6 @@ func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVWstoreconstidx1(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWstoreconstidx1 [c] {sym} ptr (SHLQconst [1] idx) mem) - // result: (MOVWstoreconstidx2 [c] {sym} ptr idx mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 1 { - continue - } - idx := v_1.Args[0] - mem := v_2 - v.reset(OpAMD64MOVWstoreconstidx2) - v.AuxInt = c - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWstoreconstidx1 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVWstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWstoreconstidx1 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - continue - } - v.reset(OpAMD64MOVWstoreconstidx1) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - break - } - // match: (MOVWstoreconstidx1 [c] {s} p i x:(MOVWstoreconstidx1 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p i mem) - for { - c := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - i := v_1 - x := v_2 - if x.Op != OpAMD64MOVWstoreconstidx1 { - continue - } - a := x.AuxInt - if x.Aux != s { - continue - } - mem := x.Args[2] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || i != x_1 || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { - continue - } - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) - v.Aux = s - v.AddArg3(p, i, mem) - return true - } - } - break - } - return false -} -func rewriteValueAMD64_OpAMD64MOVWstoreconstidx2(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - // match: (MOVWstoreconstidx2 [x] {sym} (ADDQconst [c] ptr) idx mem) - // cond: ValAndOff(x).canAdd(c) - // result: (MOVWstoreconstidx2 [ValAndOff(x).add(c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - c := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - mem := v_2 - if !(ValAndOff(x).canAdd(c)) { - break - } - v.reset(OpAMD64MOVWstoreconstidx2) - v.AuxInt = ValAndOff(x).add(c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx2 [x] {sym} ptr (ADDQconst [c] idx) mem) - // cond: ValAndOff(x).canAdd(2*c) - // result: (MOVWstoreconstidx2 [ValAndOff(x).add(2*c)] {sym} ptr idx mem) - for { - x := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - c := v_1.AuxInt - idx := v_1.Args[0] - mem := v_2 - if !(ValAndOff(x).canAdd(2 * c)) { - break - } - v.reset(OpAMD64MOVWstoreconstidx2) - v.AuxInt = ValAndOff(x).add(2 * c) - v.Aux = sym - v.AddArg3(ptr, idx, mem) - return true - } - // match: (MOVWstoreconstidx2 [c] {s} p i x:(MOVWstoreconstidx2 [a] {s} p i mem)) - // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p (SHLQconst [1] i) mem) - for { - c := v.AuxInt - s := v.Aux - p := v_0 - i := v_1 - x := v_2 - if x.Op != OpAMD64MOVWstoreconstidx2 { - break - } - a := x.AuxInt - if x.Aux != s { - break - } - mem := x.Args[2] - if p != x.Args[0] || i != x.Args[1] || !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { - break - } - v.reset(OpAMD64MOVLstoreconstidx1) - v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, i.Type) - v0.AuxInt = 1 - v0.AddArg(i) - v.AddArg3(p, v0, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVWstoreidx1(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVWstoreidx1 [c] {sym} ptr (SHLQconst [1] idx) val mem) - // result: (MOVWstoreidx2 [c] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64SHLQconst || v_1.AuxInt != 1 { - continue - } - idx := v_1.Args[0] - val := v_2 - mem := v_3 - v.reset(OpAMD64MOVWstoreidx2) - v.AuxInt = c - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpAMD64ADDQconst { - continue - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+d) - // result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - continue - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - continue - } - v.reset(OpAMD64MOVWstoreidx1) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRLconst || v_2.AuxInt != 16 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx1 || x.AuxInt != i-2 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVWstoreidx1 [i] {s} p idx (SHRQconst [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p idx w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst || v_2.AuxInt != 16 { - continue - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx1 || x.AuxInt != i-2 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v.AddArg4(p, idx, w, mem) - return true - } - } - break - } - // match: (MOVWstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRLconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx1 || x.AuxInt != i-2 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRLconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - // match: (MOVWstoreidx1 [i] {s} p idx (SHRQconst [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHRQconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p idx w0 mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst { - continue - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx1 || x.AuxInt != i-2 || x.Aux != s { - continue - } - mem := x.Args[3] - x_0 := x.Args[0] - x_1 := x.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x_0, x_1 = _i1+1, x_1, x_0 { - if p != x_0 || idx != x_1 { - continue - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - continue - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v.AddArg4(p, idx, w0, mem) - return true - } - } - break - } - // match: (MOVWstoreidx1 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+c) - // result: (MOVWstore [i+c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + c)) { - continue - } - v.reset(OpAMD64MOVWstore) - v.AuxInt = i + c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - break - } - // match: (MOVWstoreidx1 [off] {s} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(int64(int16(c)), off) - // result: (MOVWstoreconstidx1 [makeValAndOff(int64(int16(c)), off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(int64(int16(c)), off)) { - break - } - v.reset(OpAMD64MOVWstoreconstidx1) - v.AuxInt = makeValAndOff(int64(int16(c)), off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVWstoreidx2(v *Value) bool { - v_3 := v.Args[3] - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - // match: (MOVWstoreidx2 [c] {sym} (ADDQconst [d] ptr) idx val mem) - // cond: is32Bit(c+d) - // result: (MOVWstoreidx2 [c+d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - if v_0.Op != OpAMD64ADDQconst { - break - } - d := v_0.AuxInt - ptr := v_0.Args[0] - idx := v_1 - val := v_2 - mem := v_3 - if !(is32Bit(c + d)) { - break - } - v.reset(OpAMD64MOVWstoreidx2) - v.AuxInt = c + d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVWstoreidx2 [c] {sym} ptr (ADDQconst [d] idx) val mem) - // cond: is32Bit(c+2*d) - // result: (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem) - for { - c := v.AuxInt - sym := v.Aux - ptr := v_0 - if v_1.Op != OpAMD64ADDQconst { - break - } - d := v_1.AuxInt - idx := v_1.Args[0] - val := v_2 - mem := v_3 - if !(is32Bit(c + 2*d)) { - break - } - v.reset(OpAMD64MOVWstoreidx2) - v.AuxInt = c + 2*d - v.Aux = sym - v.AddArg4(ptr, idx, val, mem) - return true - } - // match: (MOVWstoreidx2 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p (SHLQconst [1] idx) w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRLconst || v_2.AuxInt != 16 { - break - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx2 || x.AuxInt != i-2 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, idx.Type) - v0.AuxInt = 1 - v0.AddArg(idx) - v.AddArg4(p, v0, w, mem) - return true - } - // match: (MOVWstoreidx2 [i] {s} p idx (SHRQconst [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p (SHLQconst [1] idx) w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst || v_2.AuxInt != 16 { - break - } - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx2 || x.AuxInt != i-2 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] || w != x.Args[2] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, idx.Type) - v0.AuxInt = 1 - v0.AddArg(idx) - v.AddArg4(p, v0, w, mem) - return true - } - // match: (MOVWstoreidx2 [i] {s} p idx (SHRQconst [j] w) x:(MOVWstoreidx2 [i-2] {s} p idx w0:(SHRQconst [j-16] w) mem)) - // cond: x.Uses == 1 && clobber(x) - // result: (MOVLstoreidx1 [i-2] {s} p (SHLQconst [1] idx) w0 mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - idx := v_1 - if v_2.Op != OpAMD64SHRQconst { - break - } - j := v_2.AuxInt - w := v_2.Args[0] - x := v_3 - if x.Op != OpAMD64MOVWstoreidx2 || x.AuxInt != i-2 || x.Aux != s { - break - } - mem := x.Args[3] - if p != x.Args[0] || idx != x.Args[1] { - break - } - w0 := x.Args[2] - if w0.Op != OpAMD64SHRQconst || w0.AuxInt != j-16 || w != w0.Args[0] || !(x.Uses == 1 && clobber(x)) { - break - } - v.reset(OpAMD64MOVLstoreidx1) - v.AuxInt = i - 2 - v.Aux = s - v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, idx.Type) - v0.AuxInt = 1 - v0.AddArg(idx) - v.AddArg4(p, v0, w0, mem) - return true - } - // match: (MOVWstoreidx2 [i] {s} p (MOVQconst [c]) w mem) - // cond: is32Bit(i+2*c) - // result: (MOVWstore [i+2*c] {s} p w mem) - for { - i := v.AuxInt - s := v.Aux - p := v_0 - if v_1.Op != OpAMD64MOVQconst { - break - } - c := v_1.AuxInt - w := v_2 - mem := v_3 - if !(is32Bit(i + 2*c)) { - break - } - v.reset(OpAMD64MOVWstore) - v.AuxInt = i + 2*c - v.Aux = s - v.AddArg3(p, w, mem) - return true - } - // match: (MOVWstoreidx2 [off] {s} ptr idx (MOVLconst [c]) mem) - // cond: validValAndOff(int64(int16(c)), off) - // result: (MOVWstoreconstidx2 [makeValAndOff(int64(int16(c)), off)] {s} ptr idx mem) - for { - off := v.AuxInt - s := v.Aux - ptr := v_0 - idx := v_1 - if v_2.Op != OpAMD64MOVLconst { - break - } - c := v_2.AuxInt - mem := v_3 - if !(validValAndOff(int64(int16(c)), off)) { - break - } - v.reset(OpAMD64MOVWstoreconstidx2) - v.AuxInt = makeValAndOff(int64(int16(c)), off) - v.Aux = s - v.AddArg3(ptr, idx, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MULL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -21672,9 +17763,9 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v.copyOf(x) return true } - // match: (ORL x0:(MOVBload [i0] {s} p mem) sh:(SHLLconst [8] x1:(MOVBload [i1] {s} p mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem) + // match: (ORL x0:(MOVBload [i0] {s} p0 mem) sh:(SHLLconst [8] x1:(MOVBload [i1] {s} p1 mem))) + // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x0 := v_0 @@ -21684,7 +17775,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] sh := v_1 if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 8 { continue @@ -21698,7 +17789,8 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x1.Args[0] + if mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -21706,14 +17798,14 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } break } - // match: (ORL x0:(MOVWload [i0] {s} p mem) sh:(SHLLconst [16] x1:(MOVWload [i1] {s} p mem))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem) + // match: (ORL x0:(MOVWload [i0] {s} p0 mem) sh:(SHLLconst [16] x1:(MOVWload [i1] {s} p1 mem))) + // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVLload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x0 := v_0 @@ -21723,7 +17815,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] sh := v_1 if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 16 { continue @@ -21737,7 +17829,8 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x1.Args[0] + if mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -21745,14 +17838,14 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } break } - // match: (ORL s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p mem)) or:(ORL s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p mem)) y)) - // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j0] (MOVWload [i0] {s} p mem)) y) + // match: (ORL s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p0 mem)) or:(ORL s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p1 mem)) y)) + // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) + // result: @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j0] (MOVWload [i0] {s} p0 mem)) y) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { s1 := v_0 @@ -21767,7 +17860,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] or := v_1 if or.Op != OpAMD64ORL { continue @@ -21790,11 +17883,12 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] { + p1 := x0.Args[0] + if mem != x0.Args[1] { continue } y := or_1 - if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { + if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { continue } b = mergePoint(b, x0, x1, y) @@ -21805,7 +17899,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v2 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16) v2.AuxInt = i0 v2.Aux = s - v2.AddArg2(p, mem) + v2.AddArg2(p0, mem) v1.AddArg(v2) v0.AddArg2(v1, y) return true @@ -21813,177 +17907,9 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { } break } - // match: (ORL x0:(MOVBloadidx1 [i0] {s} p idx mem) sh:(SHLLconst [8] x1:(MOVBloadidx1 [i1] {s} p idx mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVWloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - sh := v_1 - if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 8 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - break - } - // match: (ORL x0:(MOVWloadidx1 [i0] {s} p idx mem) sh:(SHLLconst [16] x1:(MOVWloadidx1 [i1] {s} p idx mem))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVLloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - sh := v_1 - if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 16 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVWloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - break - } - // match: (ORL s1:(SHLLconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) or:(ORL s0:(SHLLconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) y)) - // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j0] (MOVWloadidx1 [i0] {s} p idx mem)) y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - s1 := v_0 - if s1.Op != OpAMD64SHLLconst { - continue - } - j1 := s1.AuxInt - x1 := s1.Args[0] - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - or := v_1 - if or.Op != OpAMD64ORL { - continue - } - _ = or.Args[1] - or_0 := or.Args[0] - or_1 := or.Args[1] - for _i2 := 0; _i2 <= 1; _i2, or_0, or_1 = _i2+1, or_1, or_0 { - s0 := or_0 - if s0.Op != OpAMD64SHLLconst { - continue - } - j0 := s0.AuxInt - x0 := s0.Args[0] - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x0_0, x0_1 = _i3+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] { - continue - } - y := or_1 - if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { - continue - } - b = mergePoint(b, x0, x1, y) - v0 := b.NewValue0(v.Pos, OpAMD64ORL, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) - v1.AuxInt = j0 - v2 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16) - v2.AuxInt = i0 - v2.Aux = s - v2.AddArg3(p, idx, mem) - v1.AddArg(v2) - v0.AddArg2(v1, y) - return true - } - } - } - } - break - } - // match: (ORL x1:(MOVBload [i1] {s} p mem) sh:(SHLLconst [8] x0:(MOVBload [i0] {s} p mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p mem)) + // match: (ORL x1:(MOVBload [i1] {s} p0 mem) sh:(SHLLconst [8] x0:(MOVBload [i0] {s} p1 mem))) + // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p0 mem)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x1 := v_0 @@ -21993,7 +17919,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] sh := v_1 if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 8 { continue @@ -22007,7 +17933,8 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x0.Args[0] + if mem != x0.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -22017,15 +17944,15 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v1 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16) v1.AuxInt = i0 v1.Aux = s - v1.AddArg2(p, mem) + v1.AddArg2(p0, mem) v0.AddArg(v1) return true } break } - // match: (ORL r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)) sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem)))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - // result: @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p mem)) + // match: (ORL r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p0 mem)) sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p1 mem)))) + // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) + // result: @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p0 mem)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { r1 := v_0 @@ -22039,7 +17966,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] sh := v_1 if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 16 { continue @@ -22057,7 +17984,8 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { + p1 := x0.Args[0] + if mem != x0.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -22066,15 +17994,15 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v1 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32) v1.AuxInt = i0 v1.Aux = s - v1.AddArg2(p, mem) + v1.AddArg2(p0, mem) v0.AddArg(v1) return true } break } - // match: (ORL s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p mem)) or:(ORL s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p mem)) y)) - // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p mem))) y) + // match: (ORL s0:(SHLLconst [j0] x0:(MOVBload [i0] {s} p0 mem)) or:(ORL s1:(SHLLconst [j1] x1:(MOVBload [i1] {s} p1 mem)) y)) + // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) + // result: @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p0 mem))) y) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { s0 := v_0 @@ -22089,7 +18017,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] or := v_1 if or.Op != OpAMD64ORL { continue @@ -22112,11 +18040,12 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] { + p1 := x1.Args[0] + if mem != x1.Args[1] { continue } y := or_1 - if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { + if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { continue } b = mergePoint(b, x0, x1, y) @@ -22129,7 +18058,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { v3 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16) v3.AuxInt = i0 v3.Aux = s - v3.AddArg2(p, mem) + v3.AddArg2(p0, mem) v2.AddArg(v3) v1.AddArg(v2) v0.AddArg2(v1, y) @@ -22138,190 +18067,6 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value) bool { } break } - // match: (ORL x1:(MOVBloadidx1 [i1] {s} p idx mem) sh:(SHLLconst [8] x0:(MOVBloadidx1 [i0] {s} p idx mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x1 := v_0 - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - sh := v_1 - if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 8 { - continue - } - x0 := sh.Args[0] - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x0_0, x0_1 = _i2+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, v.Type) - v.copyOf(v0) - v0.AuxInt = 8 - v1 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16) - v1.AuxInt = i0 - v1.Aux = s - v1.AddArg3(p, idx, mem) - v0.AddArg(v1) - return true - } - } - } - break - } - // match: (ORL r1:(ROLWconst [8] x1:(MOVWloadidx1 [i1] {s} p idx mem)) sh:(SHLLconst [16] r0:(ROLWconst [8] x0:(MOVWloadidx1 [i0] {s} p idx mem)))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - // result: @mergePoint(b,x0,x1) (BSWAPL (MOVLloadidx1 [i0] {s} p idx mem)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - r1 := v_0 - if r1.Op != OpAMD64ROLWconst || r1.AuxInt != 8 { - continue - } - x1 := r1.Args[0] - if x1.Op != OpAMD64MOVWloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - sh := v_1 - if sh.Op != OpAMD64SHLLconst || sh.AuxInt != 16 { - continue - } - r0 := sh.Args[0] - if r0.Op != OpAMD64ROLWconst || r0.AuxInt != 8 { - continue - } - x0 := r0.Args[0] - if x0.Op != OpAMD64MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x0_0, x0_1 = _i2+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64BSWAPL, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32) - v1.AuxInt = i0 - v1.Aux = s - v1.AddArg3(p, idx, mem) - v0.AddArg(v1) - return true - } - } - } - break - } - // match: (ORL s0:(SHLLconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) or:(ORL s1:(SHLLconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) y)) - // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORL (SHLLconst [j1] (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem))) y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - s0 := v_0 - if s0.Op != OpAMD64SHLLconst { - continue - } - j0 := s0.AuxInt - x0 := s0.Args[0] - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - or := v_1 - if or.Op != OpAMD64ORL { - continue - } - _ = or.Args[1] - or_0 := or.Args[0] - or_1 := or.Args[1] - for _i2 := 0; _i2 <= 1; _i2, or_0, or_1 = _i2+1, or_1, or_0 { - s1 := or_0 - if s1.Op != OpAMD64SHLLconst { - continue - } - j1 := s1.AuxInt - x1 := s1.Args[0] - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x1_0, x1_1 = _i3+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] { - continue - } - y := or_1 - if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { - continue - } - b = mergePoint(b, x0, x1, y) - v0 := b.NewValue0(v.Pos, OpAMD64ORL, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) - v1.AuxInt = j1 - v2 := b.NewValue0(v.Pos, OpAMD64ROLWconst, typ.UInt16) - v2.AuxInt = 8 - v3 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16) - v3.AuxInt = i0 - v3.Aux = s - v3.AddArg3(p, idx, mem) - v2.AddArg(v3) - v1.AddArg(v2) - v0.AddArg2(v1, y) - return true - } - } - } - } - break - } // match: (ORL x l:(MOVLload [off] {sym} ptr mem)) // cond: canMergeLoadClobber(v, l, x) && clobber(l) // result: (ORLload x [off] {sym} ptr mem) @@ -22935,9 +18680,9 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v.copyOf(x) return true } - // match: (ORQ x0:(MOVBload [i0] {s} p mem) sh:(SHLQconst [8] x1:(MOVBload [i1] {s} p mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p mem) + // match: (ORQ x0:(MOVBload [i0] {s} p0 mem) sh:(SHLQconst [8] x1:(MOVBload [i1] {s} p1 mem))) + // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVWload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x0 := v_0 @@ -22947,7 +18692,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] sh := v_1 if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 8 { continue @@ -22961,7 +18706,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x1.Args[0] + if mem != x1.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -22969,14 +18715,14 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } break } - // match: (ORQ x0:(MOVWload [i0] {s} p mem) sh:(SHLQconst [16] x1:(MOVWload [i1] {s} p mem))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVLload [i0] {s} p mem) + // match: (ORQ x0:(MOVWload [i0] {s} p0 mem) sh:(SHLQconst [16] x1:(MOVWload [i1] {s} p1 mem))) + // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVLload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x0 := v_0 @@ -22986,7 +18732,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] sh := v_1 if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 16 { continue @@ -23000,7 +18746,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x1.Args[0] + if mem != x1.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -23008,14 +18755,14 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } break } - // match: (ORQ x0:(MOVLload [i0] {s} p mem) sh:(SHLQconst [32] x1:(MOVLload [i1] {s} p mem))) - // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVQload [i0] {s} p mem) + // match: (ORQ x0:(MOVLload [i0] {s} p0 mem) sh:(SHLQconst [32] x1:(MOVLload [i1] {s} p1 mem))) + // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVQload [i0] {s} p0 mem) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x0 := v_0 @@ -23025,7 +18772,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] sh := v_1 if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 32 { continue @@ -23039,7 +18786,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x1.Args[0] + if mem != x1.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -23047,14 +18795,14 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v.copyOf(v0) v0.AuxInt = i0 v0.Aux = s - v0.AddArg2(p, mem) + v0.AddArg2(p0, mem) return true } break } - // match: (ORQ s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p mem)) y)) - // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVWload [i0] {s} p mem)) y) + // match: (ORQ s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p0 mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p1 mem)) y)) + // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) + // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVWload [i0] {s} p0 mem)) y) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { s1 := v_0 @@ -23069,7 +18817,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] or := v_1 if or.Op != OpAMD64ORQ { continue @@ -23092,11 +18840,12 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] { + p1 := x0.Args[0] + if mem != x0.Args[1] { continue } y := or_1 - if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { + if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { continue } b = mergePoint(b, x0, x1, y) @@ -23107,7 +18856,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v2 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16) v2.AuxInt = i0 v2.Aux = s - v2.AddArg2(p, mem) + v2.AddArg2(p0, mem) v1.AddArg(v2) v0.AddArg2(v1, y) return true @@ -23115,9 +18864,9 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } - // match: (ORQ s1:(SHLQconst [j1] x1:(MOVWload [i1] {s} p mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVWload [i0] {s} p mem)) y)) - // cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVLload [i0] {s} p mem)) y) + // match: (ORQ s1:(SHLQconst [j1] x1:(MOVWload [i1] {s} p0 mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVWload [i0] {s} p1 mem)) y)) + // cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) + // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVLload [i0] {s} p0 mem)) y) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { s1 := v_0 @@ -23132,7 +18881,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] or := v_1 if or.Op != OpAMD64ORQ { continue @@ -23155,11 +18904,12 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] { + p1 := x0.Args[0] + if mem != x0.Args[1] { continue } y := or_1 - if !(i1 == i0+2 && j1 == j0+16 && j0%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { + if !(i1 == i0+2 && j1 == j0+16 && j0%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { continue } b = mergePoint(b, x0, x1, y) @@ -23170,7 +18920,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v2 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32) v2.AuxInt = i0 v2.Aux = s - v2.AddArg2(p, mem) + v2.AddArg2(p0, mem) v1.AddArg(v2) v0.AddArg2(v1, y) return true @@ -23178,297 +18928,9 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } - // match: (ORQ x0:(MOVBloadidx1 [i0] {s} p idx mem) sh:(SHLQconst [8] x1:(MOVBloadidx1 [i1] {s} p idx mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVWloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - sh := v_1 - if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 8 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, v.Type) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - break - } - // match: (ORQ x0:(MOVWloadidx1 [i0] {s} p idx mem) sh:(SHLQconst [16] x1:(MOVWloadidx1 [i1] {s} p idx mem))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVLloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - sh := v_1 - if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 16 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVWloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - break - } - // match: (ORQ x0:(MOVLloadidx1 [i0] {s} p idx mem) sh:(SHLQconst [32] x1:(MOVLloadidx1 [i1] {s} p idx mem))) - // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVQloadidx1 [i0] {s} p idx mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVLloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - sh := v_1 - if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 32 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVLloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x1_0, x1_1 = _i2+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64MOVQloadidx1, typ.UInt64) - v.copyOf(v0) - v0.AuxInt = i0 - v0.Aux = s - v0.AddArg3(p, idx, mem) - return true - } - } - } - break - } - // match: (ORQ s1:(SHLQconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) y)) - // cond: i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVWloadidx1 [i0] {s} p idx mem)) y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - s1 := v_0 - if s1.Op != OpAMD64SHLQconst { - continue - } - j1 := s1.AuxInt - x1 := s1.Args[0] - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - or := v_1 - if or.Op != OpAMD64ORQ { - continue - } - _ = or.Args[1] - or_0 := or.Args[0] - or_1 := or.Args[1] - for _i2 := 0; _i2 <= 1; _i2, or_0, or_1 = _i2+1, or_1, or_0 { - s0 := or_0 - if s0.Op != OpAMD64SHLQconst { - continue - } - j0 := s0.AuxInt - x0 := s0.Args[0] - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x0_0, x0_1 = _i3+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] { - continue - } - y := or_1 - if !(i1 == i0+1 && j1 == j0+8 && j0%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { - continue - } - b = mergePoint(b, x0, x1, y) - v0 := b.NewValue0(v.Pos, OpAMD64ORQ, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) - v1.AuxInt = j0 - v2 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16) - v2.AuxInt = i0 - v2.Aux = s - v2.AddArg3(p, idx, mem) - v1.AddArg(v2) - v0.AddArg2(v1, y) - return true - } - } - } - } - break - } - // match: (ORQ s1:(SHLQconst [j1] x1:(MOVWloadidx1 [i1] {s} p idx mem)) or:(ORQ s0:(SHLQconst [j0] x0:(MOVWloadidx1 [i0] {s} p idx mem)) y)) - // cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j0] (MOVLloadidx1 [i0] {s} p idx mem)) y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - s1 := v_0 - if s1.Op != OpAMD64SHLQconst { - continue - } - j1 := s1.AuxInt - x1 := s1.Args[0] - if x1.Op != OpAMD64MOVWloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - or := v_1 - if or.Op != OpAMD64ORQ { - continue - } - _ = or.Args[1] - or_0 := or.Args[0] - or_1 := or.Args[1] - for _i2 := 0; _i2 <= 1; _i2, or_0, or_1 = _i2+1, or_1, or_0 { - s0 := or_0 - if s0.Op != OpAMD64SHLQconst { - continue - } - j0 := s0.AuxInt - x0 := s0.Args[0] - if x0.Op != OpAMD64MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x0_0, x0_1 = _i3+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] { - continue - } - y := or_1 - if !(i1 == i0+2 && j1 == j0+16 && j0%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { - continue - } - b = mergePoint(b, x0, x1, y) - v0 := b.NewValue0(v.Pos, OpAMD64ORQ, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) - v1.AuxInt = j0 - v2 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32) - v2.AuxInt = i0 - v2.Aux = s - v2.AddArg3(p, idx, mem) - v1.AddArg(v2) - v0.AddArg2(v1, y) - return true - } - } - } - } - break - } - // match: (ORQ x1:(MOVBload [i1] {s} p mem) sh:(SHLQconst [8] x0:(MOVBload [i0] {s} p mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p mem)) + // match: (ORQ x1:(MOVBload [i1] {s} p0 mem) sh:(SHLQconst [8] x0:(MOVBload [i0] {s} p1 mem))) + // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWload [i0] {s} p0 mem)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x1 := v_0 @@ -23478,7 +18940,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] sh := v_1 if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 8 { continue @@ -23492,7 +18954,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + p1 := x0.Args[0] + if mem != x0.Args[1] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -23502,15 +18965,15 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v1 := b.NewValue0(x0.Pos, OpAMD64MOVWload, typ.UInt16) v1.AuxInt = i0 v1.Aux = s - v1.AddArg2(p, mem) + v1.AddArg2(p0, mem) v0.AddArg(v1) return true } break } - // match: (ORQ r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem)) sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem)))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - // result: @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p mem)) + // match: (ORQ r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p0 mem)) sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p1 mem)))) + // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) + // result: @mergePoint(b,x0,x1) (BSWAPL (MOVLload [i0] {s} p0 mem)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { r1 := v_0 @@ -23524,7 +18987,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] sh := v_1 if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 16 { continue @@ -23542,7 +19005,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { + p1 := x0.Args[0] + if mem != x0.Args[1] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -23551,15 +19015,15 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v1 := b.NewValue0(x0.Pos, OpAMD64MOVLload, typ.UInt32) v1.AuxInt = i0 v1.Aux = s - v1.AddArg2(p, mem) + v1.AddArg2(p0, mem) v0.AddArg(v1) return true } break } - // match: (ORQ r1:(BSWAPL x1:(MOVLload [i1] {s} p mem)) sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i0] {s} p mem)))) - // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - // result: @mergePoint(b,x0,x1) (BSWAPQ (MOVQload [i0] {s} p mem)) + // match: (ORQ r1:(BSWAPL x1:(MOVLload [i1] {s} p0 mem)) sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLload [i0] {s} p1 mem)))) + // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) + // result: @mergePoint(b,x0,x1) (BSWAPQ (MOVQload [i0] {s} p0 mem)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { r1 := v_0 @@ -23573,7 +19037,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i1 := x1.AuxInt s := x1.Aux mem := x1.Args[1] - p := x1.Args[0] + p0 := x1.Args[0] sh := v_1 if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 32 { continue @@ -23591,7 +19055,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x0.Args[1] - if p != x0.Args[0] || mem != x0.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { + p1 := x0.Args[0] + if mem != x0.Args[1] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { continue } b = mergePoint(b, x0, x1) @@ -23600,15 +19065,15 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v1 := b.NewValue0(x0.Pos, OpAMD64MOVQload, typ.UInt64) v1.AuxInt = i0 v1.Aux = s - v1.AddArg2(p, mem) + v1.AddArg2(p0, mem) v0.AddArg(v1) return true } break } - // match: (ORQ s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p mem)) or:(ORQ s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p mem)) y)) - // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p mem))) y) + // match: (ORQ s0:(SHLQconst [j0] x0:(MOVBload [i0] {s} p0 mem)) or:(ORQ s1:(SHLQconst [j1] x1:(MOVBload [i1] {s} p1 mem)) y)) + // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) + // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (ROLWconst [8] (MOVWload [i0] {s} p0 mem))) y) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { s0 := v_0 @@ -23623,7 +19088,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] or := v_1 if or.Op != OpAMD64ORQ { continue @@ -23646,11 +19111,12 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] { + p1 := x1.Args[0] + if mem != x1.Args[1] { continue } y := or_1 - if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { + if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { continue } b = mergePoint(b, x0, x1, y) @@ -23663,7 +19129,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v3 := b.NewValue0(x1.Pos, OpAMD64MOVWload, typ.UInt16) v3.AuxInt = i0 v3.Aux = s - v3.AddArg2(p, mem) + v3.AddArg2(p0, mem) v2.AddArg(v3) v1.AddArg(v2) v0.AddArg2(v1, y) @@ -23672,9 +19138,9 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } - // match: (ORQ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p mem))) or:(ORQ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p mem))) y)) - // cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (BSWAPL (MOVLload [i0] {s} p mem))) y) + // match: (ORQ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWload [i0] {s} p0 mem))) or:(ORQ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWload [i1] {s} p1 mem))) y)) + // cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or) + // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (BSWAPL (MOVLload [i0] {s} p0 mem))) y) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { s0 := v_0 @@ -23693,7 +19159,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { i0 := x0.AuxInt s := x0.Aux mem := x0.Args[1] - p := x0.Args[0] + p0 := x0.Args[0] or := v_1 if or.Op != OpAMD64ORQ { continue @@ -23720,11 +19186,12 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { continue } _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] { + p1 := x1.Args[0] + if mem != x1.Args[1] { continue } y := or_1 - if !(i1 == i0+2 && j1 == j0-16 && j1%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)) { + if !(i1 == i0+2 && j1 == j0-16 && j1%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && same(p0, p1, 1) && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)) { continue } b = mergePoint(b, x0, x1, y) @@ -23736,7 +19203,7 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { v3 := b.NewValue0(x1.Pos, OpAMD64MOVLload, typ.UInt32) v3.AuxInt = i0 v3.Aux = s - v3.AddArg2(p, mem) + v3.AddArg2(p0, mem) v2.AddArg(v3) v1.AddArg(v2) v0.AddArg2(v1, y) @@ -23745,330 +19212,6 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } - // match: (ORQ x1:(MOVBloadidx1 [i1] {s} p idx mem) sh:(SHLQconst [8] x0:(MOVBloadidx1 [i0] {s} p idx mem))) - // cond: i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x1 := v_0 - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - sh := v_1 - if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 8 { - continue - } - x0 := sh.Args[0] - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x0_0, x0_1 = _i2+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] || !(i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, v.Type) - v.copyOf(v0) - v0.AuxInt = 8 - v1 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16) - v1.AuxInt = i0 - v1.Aux = s - v1.AddArg3(p, idx, mem) - v0.AddArg(v1) - return true - } - } - } - break - } - // match: (ORQ r1:(ROLWconst [8] x1:(MOVWloadidx1 [i1] {s} p idx mem)) sh:(SHLQconst [16] r0:(ROLWconst [8] x0:(MOVWloadidx1 [i0] {s} p idx mem)))) - // cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - // result: @mergePoint(b,x0,x1) (BSWAPL (MOVLloadidx1 [i0] {s} p idx mem)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - r1 := v_0 - if r1.Op != OpAMD64ROLWconst || r1.AuxInt != 8 { - continue - } - x1 := r1.Args[0] - if x1.Op != OpAMD64MOVWloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - sh := v_1 - if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 16 { - continue - } - r0 := sh.Args[0] - if r0.Op != OpAMD64ROLWconst || r0.AuxInt != 8 { - continue - } - x0 := r0.Args[0] - if x0.Op != OpAMD64MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x0_0, x0_1 = _i2+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] || !(i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64BSWAPL, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32) - v1.AuxInt = i0 - v1.Aux = s - v1.AddArg3(p, idx, mem) - v0.AddArg(v1) - return true - } - } - } - break - } - // match: (ORQ r1:(BSWAPL x1:(MOVLloadidx1 [i1] {s} p idx mem)) sh:(SHLQconst [32] r0:(BSWAPL x0:(MOVLloadidx1 [i0] {s} p idx mem)))) - // cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, r0, r1, sh) - // result: @mergePoint(b,x0,x1) (BSWAPQ (MOVQloadidx1 [i0] {s} p idx mem)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - r1 := v_0 - if r1.Op != OpAMD64BSWAPL { - continue - } - x1 := r1.Args[0] - if x1.Op != OpAMD64MOVLloadidx1 { - continue - } - i1 := x1.AuxInt - s := x1.Aux - mem := x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x1_0, x1_1 = _i1+1, x1_1, x1_0 { - p := x1_0 - idx := x1_1 - sh := v_1 - if sh.Op != OpAMD64SHLQconst || sh.AuxInt != 32 { - continue - } - r0 := sh.Args[0] - if r0.Op != OpAMD64BSWAPL { - continue - } - x0 := r0.Args[0] - if x0.Op != OpAMD64MOVLloadidx1 { - continue - } - i0 := x0.AuxInt - if x0.Aux != s { - continue - } - _ = x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i2 := 0; _i2 <= 1; _i2, x0_0, x0_1 = _i2+1, x0_1, x0_0 { - if p != x0_0 || idx != x0_1 || mem != x0.Args[2] || !(i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, r0, r1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(v.Pos, OpAMD64BSWAPQ, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64MOVQloadidx1, typ.UInt64) - v1.AuxInt = i0 - v1.Aux = s - v1.AddArg3(p, idx, mem) - v0.AddArg(v1) - return true - } - } - } - break - } - // match: (ORQ s0:(SHLQconst [j0] x0:(MOVBloadidx1 [i0] {s} p idx mem)) or:(ORQ s1:(SHLQconst [j1] x1:(MOVBloadidx1 [i1] {s} p idx mem)) y)) - // cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (ROLWconst [8] (MOVWloadidx1 [i0] {s} p idx mem))) y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - s0 := v_0 - if s0.Op != OpAMD64SHLQconst { - continue - } - j0 := s0.AuxInt - x0 := s0.Args[0] - if x0.Op != OpAMD64MOVBloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - or := v_1 - if or.Op != OpAMD64ORQ { - continue - } - _ = or.Args[1] - or_0 := or.Args[0] - or_1 := or.Args[1] - for _i2 := 0; _i2 <= 1; _i2, or_0, or_1 = _i2+1, or_1, or_0 { - s1 := or_0 - if s1.Op != OpAMD64SHLQconst { - continue - } - j1 := s1.AuxInt - x1 := s1.Args[0] - if x1.Op != OpAMD64MOVBloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x1_0, x1_1 = _i3+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] { - continue - } - y := or_1 - if !(i1 == i0+1 && j1 == j0-8 && j1%16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, s0, s1, or)) { - continue - } - b = mergePoint(b, x0, x1, y) - v0 := b.NewValue0(v.Pos, OpAMD64ORQ, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) - v1.AuxInt = j1 - v2 := b.NewValue0(v.Pos, OpAMD64ROLWconst, typ.UInt16) - v2.AuxInt = 8 - v3 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, typ.UInt16) - v3.AuxInt = i0 - v3.Aux = s - v3.AddArg3(p, idx, mem) - v2.AddArg(v3) - v1.AddArg(v2) - v0.AddArg2(v1, y) - return true - } - } - } - } - break - } - // match: (ORQ s0:(SHLQconst [j0] r0:(ROLWconst [8] x0:(MOVWloadidx1 [i0] {s} p idx mem))) or:(ORQ s1:(SHLQconst [j1] r1:(ROLWconst [8] x1:(MOVWloadidx1 [i1] {s} p idx mem))) y)) - // cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0, x1, r0, r1, s0, s1, or) - // result: @mergePoint(b,x0,x1,y) (ORQ (SHLQconst [j1] (BSWAPL (MOVLloadidx1 [i0] {s} p idx mem))) y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - s0 := v_0 - if s0.Op != OpAMD64SHLQconst { - continue - } - j0 := s0.AuxInt - r0 := s0.Args[0] - if r0.Op != OpAMD64ROLWconst || r0.AuxInt != 8 { - continue - } - x0 := r0.Args[0] - if x0.Op != OpAMD64MOVWloadidx1 { - continue - } - i0 := x0.AuxInt - s := x0.Aux - mem := x0.Args[2] - x0_0 := x0.Args[0] - x0_1 := x0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, x0_0, x0_1 = _i1+1, x0_1, x0_0 { - p := x0_0 - idx := x0_1 - or := v_1 - if or.Op != OpAMD64ORQ { - continue - } - _ = or.Args[1] - or_0 := or.Args[0] - or_1 := or.Args[1] - for _i2 := 0; _i2 <= 1; _i2, or_0, or_1 = _i2+1, or_1, or_0 { - s1 := or_0 - if s1.Op != OpAMD64SHLQconst { - continue - } - j1 := s1.AuxInt - r1 := s1.Args[0] - if r1.Op != OpAMD64ROLWconst || r1.AuxInt != 8 { - continue - } - x1 := r1.Args[0] - if x1.Op != OpAMD64MOVWloadidx1 { - continue - } - i1 := x1.AuxInt - if x1.Aux != s { - continue - } - _ = x1.Args[2] - x1_0 := x1.Args[0] - x1_1 := x1.Args[1] - for _i3 := 0; _i3 <= 1; _i3, x1_0, x1_1 = _i3+1, x1_1, x1_0 { - if p != x1_0 || idx != x1_1 || mem != x1.Args[2] { - continue - } - y := or_1 - if !(i1 == i0+2 && j1 == j0-16 && j1%32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b, x0, x1, y) != nil && clobber(x0, x1, r0, r1, s0, s1, or)) { - continue - } - b = mergePoint(b, x0, x1, y) - v0 := b.NewValue0(v.Pos, OpAMD64ORQ, v.Type) - v.copyOf(v0) - v1 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) - v1.AuxInt = j1 - v2 := b.NewValue0(v.Pos, OpAMD64BSWAPL, typ.UInt32) - v3 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, typ.UInt32) - v3.AuxInt = i0 - v3.Aux = s - v3.AddArg3(p, idx, mem) - v2.AddArg(v3) - v1.AddArg(v2) - v0.AddArg2(v1, y) - return true - } - } - } - } - break - } // match: (ORQ x l:(MOVQload [off] {sym} ptr mem)) // cond: canMergeLoadClobber(v, l, x) && clobber(l) // result: (ORQload x [off] {sym} ptr mem) @@ -31419,15 +26562,38 @@ func rewriteValueAMD64_OpAMD64TESTL(v *Value) bool { func rewriteValueAMD64_OpAMD64TESTLconst(v *Value) bool { v_0 := v.Args[0] // match: (TESTLconst [c] (MOVLconst [c])) + // cond: c == 0 // result: (FlagEQ) for { c := v.AuxInt - if v_0.Op != OpAMD64MOVLconst || v_0.AuxInt != c { + if v_0.Op != OpAMD64MOVLconst || v_0.AuxInt != c || !(c == 0) { break } v.reset(OpAMD64FlagEQ) return true } + // match: (TESTLconst [c] (MOVLconst [c])) + // cond: c < 0 + // result: (FlagLT_UGT) + for { + c := v.AuxInt + if v_0.Op != OpAMD64MOVLconst || v_0.AuxInt != c || !(c < 0) { + break + } + v.reset(OpAMD64FlagLT_UGT) + return true + } + // match: (TESTLconst [c] (MOVLconst [c])) + // cond: c > 0 + // result: (FlagGT_UGT) + for { + c := v.AuxInt + if v_0.Op != OpAMD64MOVLconst || v_0.AuxInt != c || !(c > 0) { + break + } + v.reset(OpAMD64FlagGT_UGT) + return true + } // match: (TESTLconst [-1] x) // cond: x.Op != OpAMD64MOVLconst // result: (TESTL x x) @@ -31501,15 +26667,38 @@ func rewriteValueAMD64_OpAMD64TESTQ(v *Value) bool { func rewriteValueAMD64_OpAMD64TESTQconst(v *Value) bool { v_0 := v.Args[0] // match: (TESTQconst [c] (MOVQconst [c])) + // cond: c == 0 // result: (FlagEQ) for { c := v.AuxInt - if v_0.Op != OpAMD64MOVQconst || v_0.AuxInt != c { + if v_0.Op != OpAMD64MOVQconst || v_0.AuxInt != c || !(c == 0) { break } v.reset(OpAMD64FlagEQ) return true } + // match: (TESTQconst [c] (MOVQconst [c])) + // cond: c < 0 + // result: (FlagLT_UGT) + for { + c := v.AuxInt + if v_0.Op != OpAMD64MOVQconst || v_0.AuxInt != c || !(c < 0) { + break + } + v.reset(OpAMD64FlagLT_UGT) + return true + } + // match: (TESTQconst [c] (MOVQconst [c])) + // cond: c > 0 + // result: (FlagGT_UGT) + for { + c := v.AuxInt + if v_0.Op != OpAMD64MOVQconst || v_0.AuxInt != c || !(c > 0) { + break + } + v.reset(OpAMD64FlagGT_UGT) + return true + } // match: (TESTQconst [-1] x) // cond: x.Op != OpAMD64MOVQconst // result: (TESTQ x x) diff --git a/src/cmd/compile/internal/syntax/scanner.go b/src/cmd/compile/internal/syntax/scanner.go index fc2efcced26..6cb7ff83a0a 100644 --- a/src/cmd/compile/internal/syntax/scanner.go +++ b/src/cmd/compile/internal/syntax/scanner.go @@ -50,16 +50,23 @@ func (s *scanner) init(src io.Reader, errh func(line, col uint, msg string), mod // errorf reports an error at the most recently read character position. func (s *scanner) errorf(format string, args ...interface{}) { - s.bad = true s.error(fmt.Sprintf(format, args...)) } // errorAtf reports an error at a byte column offset relative to the current token start. func (s *scanner) errorAtf(offset int, format string, args ...interface{}) { - s.bad = true s.errh(s.line, s.col+uint(offset), fmt.Sprintf(format, args...)) } +// setLit sets the scanner state for a recognized _Literal token. +func (s *scanner) setLit(kind LitKind, ok bool) { + s.nlsemi = true + s.tok = _Literal + s.lit = string(s.segment()) + s.bad = !ok + s.kind = kind +} + // next advances the scanner by reading the next token. // // If a read, source encoding, or lexical error occurs, next calls @@ -461,8 +468,8 @@ func (s *scanner) digits(base int, invalid *int) (digsep int) { } func (s *scanner) number(seenPoint bool) { - s.bad = false - + ok := true + kind := IntLit base := 10 // number base prefix := rune(0) // one of 0 (decimal), '0' (0-octal), 'x', 'o', or 'b' digsep := 0 // bit 0: digit present, bit 1: '_' present @@ -470,7 +477,6 @@ func (s *scanner) number(seenPoint bool) { // integer part if !seenPoint { - s.kind = IntLit if s.ch == '0' { s.nextch() switch lower(s.ch) { @@ -491,7 +497,8 @@ func (s *scanner) number(seenPoint bool) { digsep |= s.digits(base, &invalid) if s.ch == '.' { if prefix == 'o' || prefix == 'b' { - s.errorf("invalid radix point in %s", litname(prefix)) + s.errorf("invalid radix point in %s literal", baseName(base)) + ok = false } s.nextch() seenPoint = true @@ -500,68 +507,77 @@ func (s *scanner) number(seenPoint bool) { // fractional part if seenPoint { - s.kind = FloatLit + kind = FloatLit digsep |= s.digits(base, &invalid) } - if digsep&1 == 0 && !s.bad { - s.errorf("%s has no digits", litname(prefix)) + if digsep&1 == 0 && ok { + s.errorf("%s literal has no digits", baseName(base)) + ok = false } // exponent if e := lower(s.ch); e == 'e' || e == 'p' { - if !s.bad { + if ok { switch { case e == 'e' && prefix != 0 && prefix != '0': s.errorf("%q exponent requires decimal mantissa", s.ch) + ok = false case e == 'p' && prefix != 'x': s.errorf("%q exponent requires hexadecimal mantissa", s.ch) + ok = false } } s.nextch() - s.kind = FloatLit + kind = FloatLit if s.ch == '+' || s.ch == '-' { s.nextch() } digsep = s.digits(10, nil) | digsep&2 // don't lose sep bit - if digsep&1 == 0 && !s.bad { + if digsep&1 == 0 && ok { s.errorf("exponent has no digits") + ok = false } - } else if prefix == 'x' && s.kind == FloatLit && !s.bad { + } else if prefix == 'x' && kind == FloatLit && ok { s.errorf("hexadecimal mantissa requires a 'p' exponent") + ok = false } // suffix 'i' if s.ch == 'i' { - s.kind = ImagLit + kind = ImagLit s.nextch() } - s.nlsemi = true - s.lit = string(s.segment()) - s.tok = _Literal + s.setLit(kind, ok) // do this now so we can use s.lit below - if s.kind == IntLit && invalid >= 0 && !s.bad { - s.errorAtf(invalid, "invalid digit %q in %s", s.lit[invalid], litname(prefix)) + if kind == IntLit && invalid >= 0 && ok { + s.errorAtf(invalid, "invalid digit %q in %s literal", s.lit[invalid], baseName(base)) + ok = false } - if digsep&2 != 0 && !s.bad { + if digsep&2 != 0 && ok { if i := invalidSep(s.lit); i >= 0 { s.errorAtf(i, "'_' must separate successive digits") + ok = false } } + + s.bad = !ok // correct s.bad } -func litname(prefix rune) string { - switch prefix { - case 'x': - return "hexadecimal literal" - case 'o', '0': - return "octal literal" - case 'b': - return "binary literal" +func baseName(base int) string { + switch base { + case 2: + return "binary" + case 8: + return "octal" + case 10: + return "decimal" + case 16: + return "hexadecimal" } - return "decimal literal" + panic("invalid base") } // invalidSep returns the index of the first invalid separator in x, or -1. @@ -605,17 +621,19 @@ func invalidSep(x string) int { } func (s *scanner) rune() { - s.bad = false + ok := true s.nextch() n := 0 for ; ; n++ { if s.ch == '\'' { - if !s.bad { + if ok { if n == 0 { s.errorf("empty rune literal or unescaped '") + ok = false } else if n != 1 { s.errorAtf(0, "more than one character in rune literal") + ok = false } } s.nextch() @@ -623,32 +641,33 @@ func (s *scanner) rune() { } if s.ch == '\\' { s.nextch() - s.escape('\'') + if !s.escape('\'') { + ok = false + } continue } if s.ch == '\n' { - if !s.bad { + if ok { s.errorf("newline in rune literal") + ok = false } break } if s.ch < 0 { - if !s.bad { + if ok { s.errorAtf(0, "rune literal not terminated") + ok = false } break } s.nextch() } - s.nlsemi = true - s.lit = string(s.segment()) - s.kind = RuneLit - s.tok = _Literal + s.setLit(RuneLit, ok) } func (s *scanner) stdString() { - s.bad = false + ok := true s.nextch() for { @@ -658,28 +677,29 @@ func (s *scanner) stdString() { } if s.ch == '\\' { s.nextch() - s.escape('"') + if !s.escape('"') { + ok = false + } continue } if s.ch == '\n' { s.errorf("newline in string") + ok = false break } if s.ch < 0 { s.errorAtf(0, "string not terminated") + ok = false break } s.nextch() } - s.nlsemi = true - s.lit = string(s.segment()) - s.kind = StringLit - s.tok = _Literal + s.setLit(StringLit, ok) } func (s *scanner) rawString() { - s.bad = false + ok := true s.nextch() for { @@ -689,6 +709,7 @@ func (s *scanner) rawString() { } if s.ch < 0 { s.errorAtf(0, "string not terminated") + ok = false break } s.nextch() @@ -697,10 +718,7 @@ func (s *scanner) rawString() { // literal (even though they are not part of the literal // value). - s.nlsemi = true - s.lit = string(s.segment()) - s.kind = StringLit - s.tok = _Literal + s.setLit(StringLit, ok) } func (s *scanner) comment(text string) { @@ -797,14 +815,14 @@ func (s *scanner) fullComment() { } } -func (s *scanner) escape(quote rune) { +func (s *scanner) escape(quote rune) bool { var n int var base, max uint32 switch s.ch { case quote, 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\': s.nextch() - return + return true case '0', '1', '2', '3', '4', '5', '6', '7': n, base, max = 3, 8, 255 case 'x': @@ -818,16 +836,16 @@ func (s *scanner) escape(quote rune) { n, base, max = 8, 16, unicode.MaxRune default: if s.ch < 0 { - return // complain in caller about EOF + return true // complain in caller about EOF } s.errorf("unknown escape") - return + return false } var x uint32 for i := n; i > 0; i-- { if s.ch < 0 { - return // complain in caller about EOF + return true // complain in caller about EOF } d := base if isDecimal(s.ch) { @@ -836,12 +854,8 @@ func (s *scanner) escape(quote rune) { d = uint32(lower(s.ch)) - 'a' + 10 } if d >= base { - kind := "hex" - if base == 8 { - kind = "octal" - } - s.errorf("invalid character %q in %s escape", s.ch, kind) - return + s.errorf("invalid character %q in %s escape", s.ch, baseName(int(base))) + return false } // d < base x = x*base + d @@ -850,10 +864,13 @@ func (s *scanner) escape(quote rune) { if x > max && base == 8 { s.errorf("octal escape value %d > 255", x) - return + return false } if x > max || 0xD800 <= x && x < 0xE000 /* surrogate range */ { s.errorf("escape is invalid Unicode code point %#U", x) + return false } + + return true } diff --git a/src/cmd/compile/internal/syntax/scanner_test.go b/src/cmd/compile/internal/syntax/scanner_test.go index 78e470c45ce..04338629d47 100644 --- a/src/cmd/compile/internal/syntax/scanner_test.go +++ b/src/cmd/compile/internal/syntax/scanner_test.go @@ -613,9 +613,9 @@ func TestScanErrors(t *testing.T) { {`'\`, "rune literal not terminated", 0, 0}, {`'\'`, "rune literal not terminated", 0, 0}, {`'\x`, "rune literal not terminated", 0, 0}, - {`'\x'`, "invalid character '\\'' in hex escape", 0, 3}, + {`'\x'`, "invalid character '\\'' in hexadecimal escape", 0, 3}, {`'\y'`, "unknown escape", 0, 2}, - {`'\x0'`, "invalid character '\\'' in hex escape", 0, 4}, + {`'\x0'`, "invalid character '\\'' in hexadecimal escape", 0, 4}, {`'\00'`, "invalid character '\\'' in octal escape", 0, 4}, {`'\377' /*`, "comment not terminated", 0, 7}, // valid octal escape {`'\378`, "invalid character '8' in octal escape", 0, 4}, @@ -633,9 +633,9 @@ func TestScanErrors(t *testing.T) { {`"\`, "string not terminated", 0, 0}, {`"\"`, "string not terminated", 0, 0}, {`"\x`, "string not terminated", 0, 0}, - {`"\x"`, "invalid character '\"' in hex escape", 0, 3}, + {`"\x"`, "invalid character '\"' in hexadecimal escape", 0, 3}, {`"\y"`, "unknown escape", 0, 2}, - {`"\x0"`, "invalid character '\"' in hex escape", 0, 4}, + {`"\x0"`, "invalid character '\"' in hexadecimal escape", 0, 4}, {`"\00"`, "invalid character '\"' in octal escape", 0, 4}, {`"\377" /*`, "comment not terminated", 0, 7}, // valid octal escape {`"\378"`, "invalid character '8' in octal escape", 0, 4}, @@ -644,8 +644,8 @@ func TestScanErrors(t *testing.T) { {`s := "foo\z"`, "unknown escape", 0, 10}, {`s := "foo\z00\nbar"`, "unknown escape", 0, 10}, {`"\x`, "string not terminated", 0, 0}, - {`"\x"`, "invalid character '\"' in hex escape", 0, 3}, - {`var s string = "\x"`, "invalid character '\"' in hex escape", 0, 18}, + {`"\x"`, "invalid character '\"' in hexadecimal escape", 0, 3}, + {`var s string = "\x"`, "invalid character '\"' in hexadecimal escape", 0, 18}, {`return "\Uffffffff"`, "escape is invalid Unicode code point U+FFFFFFFF", 0, 18}, {"0b.0", "invalid radix point in binary literal", 0, 2}, @@ -687,6 +687,48 @@ func TestScanErrors(t *testing.T) { } } +func TestDirectives(t *testing.T) { + for _, src := range []string{ + "line", + "// line", + "//line", + "//line foo", + "//line foo%bar", + + "go", + "// go:", + "//go:", + "//go :foo", + "//go:foo", + "//go:foo%bar", + } { + got := "" + var s scanner + s.init(strings.NewReader(src), func(_, col uint, msg string) { + if col != colbase { + t.Errorf("%s: got col = %d; want %d", src, col, colbase) + } + if msg == "" { + t.Errorf("%s: handler called with empty msg", src) + } + got = msg + }, directives) + + s.next() + if strings.HasPrefix(src, "//line ") || strings.HasPrefix(src, "//go:") { + // handler should have been called + if got != src { + t.Errorf("got %s; want %s", got, src) + } + } else { + // handler should not have been called + if got != "" { + t.Errorf("got %s for %s", got, src) + } + } + } +} + func TestIssue21938(t *testing.T) { s := "/*" + strings.Repeat(" ", 4089) + "*/ .5" diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index e04c8834bd8..360f9aeb06c 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -293,6 +293,11 @@ func (f *File) Visit(node ast.Node) ast.Visitor { ast.Walk(f, n.Assign) return nil } + case *ast.FuncDecl: + // Don't annotate functions with blank names - they cannot be executed. + if n.Name.Name == "_" { + return nil + } } return f } diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 48c36a63fcb..43d8089c65b 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -98,9 +98,11 @@ func (t *tester) run() { os.Setenv("PATH", fmt.Sprintf("%s%c%s", gobin, os.PathListSeparator, os.Getenv("PATH"))) } - slurp, err := exec.Command("go", "env", "CGO_ENABLED").Output() + cmd := exec.Command("go", "env", "CGO_ENABLED") + cmd.Stderr = new(bytes.Buffer) + slurp, err := cmd.Output() if err != nil { - fatalf("Error running go env CGO_ENABLED: %v", err) + fatalf("Error running go env CGO_ENABLED: %v\n%s", err, cmd.Stderr) } t.cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(string(slurp))) if flag.NArg() > 0 && t.runRxStr != "" { diff --git a/src/cmd/go.mod b/src/cmd/go.mod index b59be73fff4..e1e5b34e6ee 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,11 +3,10 @@ module cmd go 1.14 require ( - github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12 + github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3 golang.org/x/arch v0.0.0-20191126211547-368ea8f32fff golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 golang.org/x/mod v0.2.0 golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect - golang.org/x/tools v0.0.0-20200219195521-7c4b6277d74d - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect + golang.org/x/tools v0.0.0-20200309180859-aa4048aca1ca ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index dac64f407cb..73eff83010b 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,8 +1,9 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12 h1:TgXhFz35pKlZuUz1pNlOKk1UCSXPpuUIc144Wd7SxCA= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3 h1:SRgJV+IoxM5MKyFdlSUeNy6/ycRUF2yBAKdAQswoHUk= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= golang.org/x/arch v0.0.0-20191126211547-368ea8f32fff h1:k/MrR0lKiCokRu1JUDDAWhWZinfBAOZRzz3LkPOkFMs= @@ -12,12 +13,13 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg= golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -27,8 +29,8 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200219195521-7c4b6277d74d h1:ZQ18He7VORO2x4IEBuwfdp56K+ftEzRjvL0cFuCGCcM= -golang.org/x/tools v0.0.0-20200219195521-7c4b6277d74d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200309180859-aa4048aca1ca h1:cFQHQhDv9N1vc+64dtXDAyd3exHDGfRTtveOnD0IsLI= +golang.org/x/tools v0.0.0-20200309180859-aa4048aca1ca/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index a5b0f0898b4..53027b7ccb4 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -1044,6 +1044,7 @@ func TestGetGitDefaultBranch(t *testing.T) { func TestAccidentalGitCheckout(t *testing.T) { testenv.MustHaveExternalNetwork(t) testenv.MustHaveExecPath(t, "git") + testenv.MustHaveExecPath(t, "svn") tg := testgo(t) defer tg.cleanup() @@ -2208,15 +2209,10 @@ func testBuildmodePIE(t *testing.T, useCgo bool) { t.Fatal(err) } defer f.Close() - const ( - IMAGE_FILE_RELOCS_STRIPPED = 0x0001 - IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 - IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 - ) if f.Section(".reloc") == nil { t.Error(".reloc section is not present") } - if (f.FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0 { + if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 { t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set") } var dc uint16 @@ -2225,13 +2221,13 @@ func testBuildmodePIE(t *testing.T, useCgo bool) { dc = oh.DllCharacteristics case *pe.OptionalHeader64: dc = oh.DllCharacteristics - if (dc & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 { + if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 { t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set") } default: t.Fatalf("unexpected optional header type of %T", f.OptionalHeader) } - if (dc & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 { + if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 { t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set") } default: diff --git a/src/cmd/go/internal/auth/auth.go b/src/cmd/go/internal/auth/auth.go index 12e3c74dcc7..fe5a89d7271 100644 --- a/src/cmd/go/internal/auth/auth.go +++ b/src/cmd/go/internal/auth/auth.go @@ -10,10 +10,12 @@ import "net/http" // AddCredentials fills in the user's credentials for req, if any. // The return value reports whether any matching credentials were found. func AddCredentials(req *http.Request) (added bool) { + host := req.URL.Hostname() + // TODO(golang.org/issue/26232): Support arbitrary user-provided credentials. netrcOnce.Do(readNetrc) for _, l := range netrc { - if l.machine == req.URL.Host { + if l.machine == host { req.SetBasicAuth(l.login, l.password) return true } diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go index 2831975c0c6..c60a78ed924 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go @@ -13,19 +13,19 @@ // or an F_OFD_SETLK command for 'fcntl', that allows for better concurrency and // does not require per-inode bookkeeping in the application. // -// TODO(bcmills): If we add a build tag for Illumos (see golang.org/issue/20603) -// then Illumos should use F_OFD_SETLK, and the resulting code would be as -// simple as filelock_unix.go. We will still need the code in this file for AIX -// or as long as Oracle Solaris provides only F_SETLK. +// TODO(golang.org/issue/35618): add a syscall.Flock binding for Illumos and +// switch it over to use filelock_unix.go. package filelock import ( "errors" "io" + "math/rand" "os" "sync" "syscall" + "time" ) type lockType int16 @@ -91,7 +91,67 @@ func lock(f File, lt lockType) (err error) { wait <- f } - err = setlkw(f.Fd(), lt) + // Spurious EDEADLK errors arise on platforms that compute deadlock graphs at + // the process, rather than thread, level. Consider processes P and Q, with + // threads P.1, P.2, and Q.3. The following trace is NOT a deadlock, but will be + // reported as a deadlock on systems that consider only process granularity: + // + // P.1 locks file A. + // Q.3 locks file B. + // Q.3 blocks on file A. + // P.2 blocks on file B. (This is erroneously reported as a deadlock.) + // P.1 unlocks file A. + // Q.3 unblocks and locks file A. + // Q.3 unlocks files A and B. + // P.2 unblocks and locks file B. + // P.2 unlocks file B. + // + // These spurious errors were observed in practice on AIX and Solaris in + // cmd/go: see https://golang.org/issue/32817. + // + // We work around this bug by treating EDEADLK as always spurious. If there + // really is a lock-ordering bug between the interacting processes, it will + // become a livelock instead, but that's not appreciably worse than if we had + // a proper flock implementation (which generally does not even attempt to + // diagnose deadlocks). + // + // In the above example, that changes the trace to: + // + // P.1 locks file A. + // Q.3 locks file B. + // Q.3 blocks on file A. + // P.2 spuriously fails to lock file B and goes to sleep. + // P.1 unlocks file A. + // Q.3 unblocks and locks file A. + // Q.3 unlocks files A and B. + // P.2 wakes up and locks file B. + // P.2 unlocks file B. + // + // We know that the retry loop will not introduce a *spurious* livelock + // because, according to the POSIX specification, EDEADLK is only to be + // returned when “the lock is blocked by a lock from another process”. + // If that process is blocked on some lock that we are holding, then the + // resulting livelock is due to a real deadlock (and would manifest as such + // when using, for example, the flock implementation of this package). + // If the other process is *not* blocked on some other lock that we are + // holding, then it will eventually release the requested lock. + + nextSleep := 1 * time.Millisecond + const maxSleep = 500 * time.Millisecond + for { + err = setlkw(f.Fd(), lt) + if err != syscall.EDEADLK { + break + } + time.Sleep(nextSleep) + + nextSleep += nextSleep + if nextSleep > maxSleep { + nextSleep = maxSleep + } + // Apply 10% jitter to avoid synchronizing collisions when we finally unblock. + nextSleep += time.Duration((0.1*rand.Float64() - 0.05) * float64(nextSleep)) + } if err != nil { unlock(f) diff --git a/src/cmd/go/internal/lockedfile/lockedfile_test.go b/src/cmd/go/internal/lockedfile/lockedfile_test.go index 8f7a7d5604a..416c69d83bc 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_test.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_test.go @@ -8,8 +8,11 @@ package lockedfile_test import ( + "fmt" + "internal/testenv" "io/ioutil" "os" + "os/exec" "path/filepath" "testing" "time" @@ -172,3 +175,98 @@ func TestCanLockExistingFile(t *testing.T) { f.Close() wait(t) } + +// TestSpuriousEDEADLK verifies that the spurious EDEADLK reported in +// https://golang.org/issue/32817 no longer occurs. +func TestSpuriousEDEADLK(t *testing.T) { + // P.1 locks file A. + // Q.3 locks file B. + // Q.3 blocks on file A. + // P.2 blocks on file B. (Spurious EDEADLK occurs here.) + // P.1 unlocks file A. + // Q.3 unblocks and locks file A. + // Q.3 unlocks files A and B. + // P.2 unblocks and locks file B. + // P.2 unlocks file B. + + testenv.MustHaveExec(t) + + dirVar := t.Name() + "DIR" + + if dir := os.Getenv(dirVar); dir != "" { + // Q.3 locks file B. + b, err := lockedfile.Edit(filepath.Join(dir, "B")) + if err != nil { + t.Fatal(err) + } + defer b.Close() + + if err := ioutil.WriteFile(filepath.Join(dir, "locked"), []byte("ok"), 0666); err != nil { + t.Fatal(err) + } + + // Q.3 blocks on file A. + a, err := lockedfile.Edit(filepath.Join(dir, "A")) + // Q.3 unblocks and locks file A. + if err != nil { + t.Fatal(err) + } + defer a.Close() + + // Q.3 unlocks files A and B. + return + } + + dir, remove := mustTempDir(t) + defer remove() + + // P.1 locks file A. + a, err := lockedfile.Edit(filepath.Join(dir, "A")) + if err != nil { + t.Fatal(err) + } + + cmd := exec.Command(os.Args[0], "-test.run="+t.Name()) + cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", dirVar, dir)) + + qDone := make(chan struct{}) + waitQ := mustBlock(t, "Edit A and B in subprocess", func() { + out, err := cmd.CombinedOutput() + if err != nil { + t.Errorf("%v:\n%s", err, out) + } + close(qDone) + }) + + // Wait until process Q has either failed or locked file B. + // Otherwise, P.2 might not block on file B as intended. +locked: + for { + if _, err := os.Stat(filepath.Join(dir, "locked")); !os.IsNotExist(err) { + break locked + } + select { + case <-qDone: + break locked + case <-time.After(1 * time.Millisecond): + } + } + + waitP2 := mustBlock(t, "Edit B", func() { + // P.2 blocks on file B. (Spurious EDEADLK occurs here.) + b, err := lockedfile.Edit(filepath.Join(dir, "B")) + // P.2 unblocks and locks file B. + if err != nil { + t.Error(err) + return + } + // P.2 unlocks file B. + b.Close() + }) + + // P.1 unlocks file A. + a.Close() + + waitQ(t) + waitP2(t) +} diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index 831e5cf85bb..ac3f1351c87 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -6,6 +6,7 @@ package modcmd import ( "bytes" + "errors" "fmt" "io/ioutil" "os" @@ -67,12 +68,10 @@ func verifyMod(mod module.Version) bool { _, zipErr = os.Stat(zip) } dir, dirErr := modfetch.DownloadDir(mod) - if dirErr == nil { - _, dirErr = os.Stat(dir) - } data, err := ioutil.ReadFile(zip + "hash") if err != nil { - if zipErr != nil && os.IsNotExist(zipErr) && dirErr != nil && os.IsNotExist(dirErr) { + if zipErr != nil && errors.Is(zipErr, os.ErrNotExist) && + dirErr != nil && errors.Is(dirErr, os.ErrNotExist) { // Nothing downloaded yet. Nothing to verify. return true } @@ -81,7 +80,7 @@ func verifyMod(mod module.Version) bool { } h := string(bytes.TrimSpace(data)) - if zipErr != nil && os.IsNotExist(zipErr) { + if zipErr != nil && errors.Is(zipErr, os.ErrNotExist) { // ok } else { hZ, err := dirhash.HashZip(zip, dirhash.DefaultHash) @@ -93,7 +92,7 @@ func verifyMod(mod module.Version) bool { ok = false } } - if dirErr != nil && os.IsNotExist(dirErr) { + if dirErr != nil && errors.Is(dirErr, os.ErrNotExist) { // ok } else { hD, err := dirhash.HashDir(dir, mod.Path+"@"+mod.Version, dirhash.DefaultHash) diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index 947192bd83e..d6ff068e7bc 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -7,6 +7,7 @@ package modfetch import ( "bytes" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -56,8 +57,11 @@ func CachePath(m module.Version, suffix string) (string, error) { return filepath.Join(dir, encVer+"."+suffix), nil } -// DownloadDir returns the directory to which m should be downloaded. -// Note that the directory may not yet exist. +// DownloadDir returns the directory to which m should have been downloaded. +// An error will be returned if the module path or version cannot be escaped. +// An error satisfying errors.Is(err, os.ErrNotExist) will be returned +// along with the directory if the directory does not exist or if the directory +// is not completely populated. func DownloadDir(m module.Version) (string, error) { if PkgMod == "" { return "", fmt.Errorf("internal error: modfetch.PkgMod not set") @@ -76,9 +80,39 @@ func DownloadDir(m module.Version) (string, error) { if err != nil { return "", err } - return filepath.Join(PkgMod, enc+"@"+encVer), nil + + dir := filepath.Join(PkgMod, enc+"@"+encVer) + if fi, err := os.Stat(dir); os.IsNotExist(err) { + return dir, err + } else if err != nil { + return dir, &DownloadDirPartialError{dir, err} + } else if !fi.IsDir() { + return dir, &DownloadDirPartialError{dir, errors.New("not a directory")} + } + partialPath, err := CachePath(m, "partial") + if err != nil { + return dir, err + } + if _, err := os.Stat(partialPath); err == nil { + return dir, &DownloadDirPartialError{dir, errors.New("not completely extracted")} + } else if !os.IsNotExist(err) { + return dir, err + } + return dir, nil } +// DownloadDirPartialError is returned by DownloadDir if a module directory +// exists but was not completely populated. +// +// DownloadDirPartialError is equivalent to os.ErrNotExist. +type DownloadDirPartialError struct { + Dir string + Err error +} + +func (e *DownloadDirPartialError) Error() string { return fmt.Sprintf("%s: %v", e.Dir, e.Err) } +func (e *DownloadDirPartialError) Is(err error) bool { return err == os.ErrNotExist } + // lockVersion locks a file within the module cache that guards the downloading // and extraction of the zipfile for the given module version. func lockVersion(mod module.Version) (unlock func(), err error) { diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index 753f65b3de4..d043903336c 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -563,7 +563,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) return err } if !t.Equal(info.Time.Truncate(time.Second)) { - return fmt.Errorf("does not match version-control timestamp (%s)", info.Time.UTC().Format(time.RFC3339)) + return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(pseudoVersionTimestampFormat)) } tagPrefix := "" diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index e2c463a6855..187d1745424 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -46,24 +46,26 @@ func Download(mod module.Version) (dir string, err error) { err error } c := downloadCache.Do(mod, func() interface{} { - dir, err := DownloadDir(mod) + dir, err := download(mod) if err != nil { return cached{"", err} } - if err := download(mod, dir); err != nil { - return cached{"", err} - } checkMod(mod) return cached{dir, nil} }).(cached) return c.dir, c.err } -func download(mod module.Version, dir string) (err error) { - // If the directory exists, the module has already been extracted. - fi, err := os.Stat(dir) - if err == nil && fi.IsDir() { - return nil +func download(mod module.Version) (dir string, err error) { + // If the directory exists, and no .partial file exists, the module has + // already been completely extracted. .partial files may be created when a + // module zip directory is extracted in place instead of being extracted to a + // temporary directory and renamed. + dir, err = DownloadDir(mod) + if err == nil { + return dir, nil + } else if dir == "" || !errors.Is(err, os.ErrNotExist) { + return "", err } // To avoid cluttering the cache with extraneous files, @@ -71,22 +73,24 @@ func download(mod module.Version, dir string) (err error) { // Invoke DownloadZip before locking the file. zipfile, err := DownloadZip(mod) if err != nil { - return err + return "", err } unlock, err := lockVersion(mod) if err != nil { - return err + return "", err } defer unlock() // Check whether the directory was populated while we were waiting on the lock. - fi, err = os.Stat(dir) - if err == nil && fi.IsDir() { - return nil + _, dirErr := DownloadDir(mod) + if dirErr == nil { + return dir, nil } + _, dirExists := dirErr.(*DownloadDirPartialError) - // Clean up any remaining temporary directories from previous runs. + // Clean up any remaining temporary directories from previous runs, as well + // as partially extracted diectories created by future versions of cmd/go. // This is only safe to do because the lock file ensures that their writers // are no longer active. parentDir := filepath.Dir(dir) @@ -96,35 +100,75 @@ func download(mod module.Version, dir string) (err error) { RemoveAll(path) // best effort } } - - // Extract the zip file to a temporary directory, then rename it to the - // final path. That way, we can use the existence of the source directory to - // signal that it has been extracted successfully, and if someone deletes - // the entire directory (e.g. as an attempt to prune out file corruption) - // the module cache will still be left in a recoverable state. - // We retry failed renames using robustio.Rename on Windows. Programs that - // open files in the temporary directory (antivirus, search indexers, etc.) - // can cause os.Rename to fail with ERROR_ACCESS_DENIED. - if err := os.MkdirAll(parentDir, 0777); err != nil { - return err - } - tmpDir, err := ioutil.TempDir(parentDir, tmpPrefix) - if err != nil { - return err - } - defer func() { - if err != nil { - RemoveAll(tmpDir) + if dirExists { + if err := RemoveAll(dir); err != nil { + return "", err } - }() - - if err := modzip.Unzip(tmpDir, mod, zipfile); err != nil { - fmt.Fprintf(os.Stderr, "-> %s\n", err) - return err } - if err := robustio.Rename(tmpDir, dir); err != nil { - return err + partialPath, err := CachePath(mod, "partial") + if err != nil { + return "", err + } + if err := os.Remove(partialPath); err != nil && !os.IsNotExist(err) { + return "", err + } + + // Extract the module zip directory. + // + // By default, we extract to a temporary directory, then atomically rename to + // its final location. We use the existence of the source directory to signal + // that it has been extracted successfully (see DownloadDir). If someone + // deletes the entire directory (e.g., as an attempt to prune out file + // corruption), the module cache will still be left in a recoverable + // state. + // + // Unfortunately, os.Rename may fail with ERROR_ACCESS_DENIED on Windows if + // another process opens files in the temporary directory. This is partially + // mitigated by using robustio.Rename, which retries os.Rename for a short + // time. + // + // To avoid this error completely, if unzipInPlace is set, we instead create a + // .partial file (indicating the directory isn't fully extracted), then we + // extract the directory at its final location, then we delete the .partial + // file. This is not the default behavior because older versions of Go may + // simply stat the directory to check whether it exists without looking for a + // .partial file. If multiple versions run concurrently, the older version may + // assume a partially extracted directory is complete. + // TODO(golang.org/issue/36568): when these older versions are no longer + // supported, remove the old default behavior and the unzipInPlace flag. + if err := os.MkdirAll(parentDir, 0777); err != nil { + return "", err + } + + if unzipInPlace { + if err := ioutil.WriteFile(partialPath, nil, 0666); err != nil { + return "", err + } + if err := modzip.Unzip(dir, mod, zipfile); err != nil { + fmt.Fprintf(os.Stderr, "-> %s\n", err) + if rmErr := RemoveAll(dir); rmErr == nil { + os.Remove(partialPath) + } + return "", err + } + if err := os.Remove(partialPath); err != nil { + return "", err + } + } else { + tmpDir, err := ioutil.TempDir(parentDir, tmpPrefix) + if err != nil { + return "", err + } + if err := modzip.Unzip(tmpDir, mod, zipfile); err != nil { + fmt.Fprintf(os.Stderr, "-> %s\n", err) + RemoveAll(tmpDir) + return "", err + } + if err := robustio.Rename(tmpDir, dir); err != nil { + RemoveAll(tmpDir) + return "", err + } } if !cfg.ModCacheRW { @@ -132,7 +176,18 @@ func download(mod module.Version, dir string) (err error) { // os.Rename was observed to fail for read-only directories on macOS. makeDirsReadOnly(dir) } - return nil + return dir, nil +} + +var unzipInPlace bool + +func init() { + for _, f := range strings.Split(os.Getenv("GODEBUG"), ",") { + if f == "modcacheunzipinplace=1" { + unzipInPlace = true + break + } + } } var downloadZipCache par.Cache @@ -306,7 +361,7 @@ func RemoveAll(dir string) error { } return nil }) - return os.RemoveAll(dir) + return robustio.RemoveAll(dir) } var GoSumFile string // path to go.sum; set by package modload diff --git a/src/cmd/go/internal/modfetch/pseudo.go b/src/cmd/go/internal/modfetch/pseudo.go index 57dee11d071..20c0b060ab4 100644 --- a/src/cmd/go/internal/modfetch/pseudo.go +++ b/src/cmd/go/internal/modfetch/pseudo.go @@ -48,6 +48,8 @@ import ( var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`) +const pseudoVersionTimestampFormat = "20060102150405" + // PseudoVersion returns a pseudo-version for the given major version ("v1") // preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time, // and revision identifier (usually a 12-byte commit hash prefix). @@ -55,7 +57,7 @@ func PseudoVersion(major, older string, t time.Time, rev string) string { if major == "" { major = "v0" } - segment := fmt.Sprintf("%s-%s", t.UTC().Format("20060102150405"), rev) + segment := fmt.Sprintf("%s-%s", t.UTC().Format(pseudoVersionTimestampFormat), rev) build := semver.Build(older) older = semver.Canonical(older) if older == "" { diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 454dbf28cfc..5f8a2e7e056 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -148,9 +148,7 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic { } dir, err := modfetch.DownloadDir(mod) if err == nil { - if info, err := os.Stat(dir); err == nil && info.IsDir() { - m.Dir = dir - } + m.Dir = dir } } } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 61cbdf2c543..8b57d8005b2 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -59,27 +59,6 @@ var ( allowMissingModuleImports bool ) -var modFile *modfile.File - -// A modFileIndex is an index of data corresponding to a modFile -// at a specific point in time. -type modFileIndex struct { - data []byte - dataNeedsFix bool // true if fixVersion applied a change while parsing data - module module.Version - goVersion string - require map[module.Version]requireMeta - replace map[module.Version]module.Version - exclude map[module.Version]bool -} - -// index is the index of the go.mod file as of when it was last read or written. -var index *modFileIndex - -type requireMeta struct { - indirect bool -} - // ModFile returns the parsed go.mod file. // // Note that after calling ImportPaths or LoadBuildList, @@ -555,101 +534,6 @@ func setDefaultBuildMod() { } } -// checkVendorConsistency verifies that the vendor/modules.txt file matches (if -// go 1.14) or at least does not contradict (go 1.13 or earlier) the -// requirements and replacements listed in the main module's go.mod file. -func checkVendorConsistency() { - readVendorList() - - pre114 := false - if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 { - // Go versions before 1.14 did not include enough information in - // vendor/modules.txt to check for consistency. - // If we know that we're on an earlier version, relax the consistency check. - pre114 = true - } - - vendErrors := new(strings.Builder) - vendErrorf := func(mod module.Version, format string, args ...interface{}) { - detail := fmt.Sprintf(format, args...) - if mod.Version == "" { - fmt.Fprintf(vendErrors, "\n\t%s: %s", mod.Path, detail) - } else { - fmt.Fprintf(vendErrors, "\n\t%s@%s: %s", mod.Path, mod.Version, detail) - } - } - - for _, r := range modFile.Require { - if !vendorMeta[r.Mod].Explicit { - if pre114 { - // Before 1.14, modules.txt did not indicate whether modules were listed - // explicitly in the main module's go.mod file. - // However, we can at least detect a version mismatch if packages were - // vendored from a non-matching version. - if vv, ok := vendorVersion[r.Mod.Path]; ok && vv != r.Mod.Version { - vendErrorf(r.Mod, fmt.Sprintf("is explicitly required in go.mod, but vendor/modules.txt indicates %s@%s", r.Mod.Path, vv)) - } - } else { - vendErrorf(r.Mod, "is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt") - } - } - } - - describe := func(m module.Version) string { - if m.Version == "" { - return m.Path - } - return m.Path + "@" + m.Version - } - - // We need to verify *all* replacements that occur in modfile: even if they - // don't directly apply to any module in the vendor list, the replacement - // go.mod file can affect the selected versions of other (transitive) - // dependencies - for _, r := range modFile.Replace { - vr := vendorMeta[r.Old].Replacement - if vr == (module.Version{}) { - if pre114 && (r.Old.Version == "" || vendorVersion[r.Old.Path] != r.Old.Version) { - // Before 1.14, modules.txt omitted wildcard replacements and - // replacements for modules that did not have any packages to vendor. - } else { - vendErrorf(r.Old, "is replaced in go.mod, but not marked as replaced in vendor/modules.txt") - } - } else if vr != r.New { - vendErrorf(r.Old, "is replaced by %s in go.mod, but marked as replaced by %s in vendor/modules.txt", describe(r.New), describe(vr)) - } - } - - for _, mod := range vendorList { - meta := vendorMeta[mod] - if meta.Explicit { - if _, inGoMod := index.require[mod]; !inGoMod { - vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in go.mod") - } - } - } - - for _, mod := range vendorReplaced { - r := Replacement(mod) - if r == (module.Version{}) { - vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod") - continue - } - if meta := vendorMeta[mod]; r != meta.Replacement { - vendErrorf(mod, "is marked as replaced by %s in vendor/modules.txt, but replaced by %s in go.mod", describe(meta.Replacement), describe(r)) - } - } - - if vendErrors.Len() > 0 { - base.Fatalf("go: inconsistent vendoring in %s:%s\n\nrun 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory", modRoot, vendErrors) - } -} - -// Allowed reports whether module m is allowed (not excluded) by the main module's go.mod. -func Allowed(m module.Version) bool { - return index == nil || !index.exclude[m] -} - func legacyModInit() { if modFile == nil { path, err := findModulePath(modRoot) @@ -983,113 +867,3 @@ func WriteGoMod() { base.Fatalf("go: updating go.mod: %v", err) } } - -// indexModFile rebuilds the index of modFile. -// If modFile has been changed since it was first read, -// modFile.Cleanup must be called before indexModFile. -func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileIndex { - i := new(modFileIndex) - i.data = data - i.dataNeedsFix = needsFix - - i.module = module.Version{} - if modFile.Module != nil { - i.module = modFile.Module.Mod - } - - i.goVersion = "" - if modFile.Go != nil { - i.goVersion = modFile.Go.Version - } - - i.require = make(map[module.Version]requireMeta, len(modFile.Require)) - for _, r := range modFile.Require { - i.require[r.Mod] = requireMeta{indirect: r.Indirect} - } - - i.replace = make(map[module.Version]module.Version, len(modFile.Replace)) - for _, r := range modFile.Replace { - if prev, dup := i.replace[r.Old]; dup && prev != r.New { - base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New) - } - i.replace[r.Old] = r.New - } - - i.exclude = make(map[module.Version]bool, len(modFile.Exclude)) - for _, x := range modFile.Exclude { - i.exclude[x.Mod] = true - } - - return i -} - -// modFileIsDirty reports whether the go.mod file differs meaningfully -// from what was indexed. -// If modFile has been changed (even cosmetically) since it was first read, -// modFile.Cleanup must be called before modFileIsDirty. -func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool { - if i == nil { - return modFile != nil - } - - if i.dataNeedsFix { - return true - } - - if modFile.Module == nil { - if i.module != (module.Version{}) { - return true - } - } else if modFile.Module.Mod != i.module { - return true - } - - if modFile.Go == nil { - if i.goVersion != "" { - return true - } - } else if modFile.Go.Version != i.goVersion { - if i.goVersion == "" && cfg.BuildMod == "readonly" { - // go.mod files did not always require a 'go' version, so do not error out - // if one is missing — we may be inside an older module in the module - // cache, and should bias toward providing useful behavior. - } else { - return true - } - } - - if len(modFile.Require) != len(i.require) || - len(modFile.Replace) != len(i.replace) || - len(modFile.Exclude) != len(i.exclude) { - return true - } - - for _, r := range modFile.Require { - if meta, ok := i.require[r.Mod]; !ok { - return true - } else if r.Indirect != meta.indirect { - if cfg.BuildMod == "readonly" { - // The module's requirements are consistent; only the "// indirect" - // comments that are wrong. But those are only guaranteed to be accurate - // after a "go mod tidy" — it's a good idea to run those before - // committing a change, but it's certainly not mandatory. - } else { - return true - } - } - } - - for _, r := range modFile.Replace { - if r.New != i.replace[r.Old] { - return true - } - } - - for _, x := range modFile.Exclude { - if !i.exclude[x.Mod] { - return true - } - } - - return false -} diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 6ea7d8c69b3..21601cb13e6 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -9,14 +9,12 @@ import ( "errors" "fmt" "go/build" - "io/ioutil" "os" "path" pathpkg "path" "path/filepath" "sort" "strings" - "sync" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -27,9 +25,7 @@ import ( "cmd/go/internal/search" "cmd/go/internal/str" - "golang.org/x/mod/modfile" "golang.org/x/mod/module" - "golang.org/x/mod/semver" ) // buildList is the list of modules to use for building packages. @@ -1033,354 +1029,3 @@ func WhyDepth(path string) int { } return n } - -// Replacement returns the replacement for mod, if any, from go.mod. -// If there is no replacement for mod, Replacement returns -// a module.Version with Path == "". -func Replacement(mod module.Version) module.Version { - if index != nil { - if r, ok := index.replace[mod]; ok { - return r - } - if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { - return r - } - } - return module.Version{} -} - -// mvsReqs implements mvs.Reqs for module semantic versions, -// with any exclusions or replacements applied internally. -type mvsReqs struct { - buildList []module.Version - cache par.Cache - versions sync.Map -} - -// Reqs returns the current module requirement graph. -// Future calls to SetBuildList do not affect the operation -// of the returned Reqs. -func Reqs() mvs.Reqs { - r := &mvsReqs{ - buildList: buildList, - } - return r -} - -func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { - type cached struct { - list []module.Version - err error - } - - c := r.cache.Do(mod, func() interface{} { - list, err := r.required(mod) - if err != nil { - return cached{nil, err} - } - for i, mv := range list { - if index != nil { - for index.exclude[mv] { - mv1, err := r.next(mv) - if err != nil { - return cached{nil, err} - } - if mv1.Version == "none" { - return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)} - } - mv = mv1 - } - } - list[i] = mv - } - - return cached{list, nil} - }).(cached) - - return c.list, c.err -} - -var vendorOnce sync.Once - -type vendorMetadata struct { - Explicit bool - Replacement module.Version -} - -var ( - vendorList []module.Version // modules that contribute packages to the build, in order of appearance - vendorReplaced []module.Version // all replaced modules; may or may not also contribute packages - vendorVersion map[string]string // module path → selected version (if known) - vendorPkgModule map[string]module.Version // package → containing module - vendorMeta map[module.Version]vendorMetadata -) - -// readVendorList reads the list of vendored modules from vendor/modules.txt. -func readVendorList() { - vendorOnce.Do(func() { - vendorList = nil - vendorPkgModule = make(map[string]module.Version) - vendorVersion = make(map[string]string) - vendorMeta = make(map[module.Version]vendorMetadata) - data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - base.Fatalf("go: %s", err) - } - return - } - - var mod module.Version - for _, line := range strings.Split(string(data), "\n") { - if strings.HasPrefix(line, "# ") { - f := strings.Fields(line) - - if len(f) < 3 { - continue - } - if semver.IsValid(f[2]) { - // A module, but we don't yet know whether it is in the build list or - // only included to indicate a replacement. - mod = module.Version{Path: f[1], Version: f[2]} - f = f[3:] - } else if f[2] == "=>" { - // A wildcard replacement found in the main module's go.mod file. - mod = module.Version{Path: f[1]} - f = f[2:] - } else { - // Not a version or a wildcard replacement. - // We don't know how to interpret this module line, so ignore it. - mod = module.Version{} - continue - } - - if len(f) >= 2 && f[0] == "=>" { - meta := vendorMeta[mod] - if len(f) == 2 { - // File replacement. - meta.Replacement = module.Version{Path: f[1]} - vendorReplaced = append(vendorReplaced, mod) - } else if len(f) == 3 && semver.IsValid(f[2]) { - // Path and version replacement. - meta.Replacement = module.Version{Path: f[1], Version: f[2]} - vendorReplaced = append(vendorReplaced, mod) - } else { - // We don't understand this replacement. Ignore it. - } - vendorMeta[mod] = meta - } - continue - } - - // Not a module line. Must be a package within a module or a metadata - // directive, either of which requires a preceding module line. - if mod.Path == "" { - continue - } - - if strings.HasPrefix(line, "## ") { - // Metadata. Take the union of annotations across multiple lines, if present. - meta := vendorMeta[mod] - for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") { - entry = strings.TrimSpace(entry) - if entry == "explicit" { - meta.Explicit = true - } - // All other tokens are reserved for future use. - } - vendorMeta[mod] = meta - continue - } - - if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil { - // A package within the current module. - vendorPkgModule[f[0]] = mod - - // Since this module provides a package for the build, we know that it - // is in the build list and is the selected version of its path. - // If this information is new, record it. - if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 { - vendorList = append(vendorList, mod) - vendorVersion[mod.Path] = mod.Version - } - } - } - }) -} - -func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { - list := make([]module.Version, 0, len(f.Require)) - for _, r := range f.Require { - list = append(list, r.Mod) - } - return list -} - -// required returns a unique copy of the requirements of mod. -func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { - if mod == Target { - if modFile != nil && modFile.Go != nil { - r.versions.LoadOrStore(mod, modFile.Go.Version) - } - return append([]module.Version(nil), r.buildList[1:]...), nil - } - - if cfg.BuildMod == "vendor" { - // For every module other than the target, - // return the full list of modules from modules.txt. - readVendorList() - return append([]module.Version(nil), vendorList...), nil - } - - origPath := mod.Path - if repl := Replacement(mod); repl.Path != "" { - if repl.Version == "" { - // TODO: need to slip the new version into the tags list etc. - dir := repl.Path - if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) - } - gomod := filepath.Join(dir, "go.mod") - data, err := ioutil.ReadFile(gomod) - if err != nil { - return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) - } - f, err := modfile.ParseLax(gomod, data, nil) - if err != nil { - return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) - } - if f.Go != nil { - r.versions.LoadOrStore(mod, f.Go.Version) - } - return r.modFileToList(f), nil - } - mod = repl - } - - if mod.Version == "none" { - return nil, nil - } - - if !semver.IsValid(mod.Version) { - // Disallow the broader queries supported by fetch.Lookup. - base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) - } - - data, err := modfetch.GoMod(mod.Path, mod.Version) - if err != nil { - return nil, err - } - f, err := modfile.ParseLax("go.mod", data, nil) - if err != nil { - return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err)) - } - - if f.Module == nil { - return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line")) - } - if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { - return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod: - module declares its path as: %s - but was required as: %s`, mpath, mod.Path)) - } - if f.Go != nil { - r.versions.LoadOrStore(mod, f.Go.Version) - } - - return r.modFileToList(f), nil -} - -func (*mvsReqs) Max(v1, v2 string) string { - if v1 != "" && semver.Compare(v1, v2) == -1 { - return v2 - } - return v1 -} - -// Upgrade is a no-op, here to implement mvs.Reqs. -// The upgrade logic for go get -u is in ../modget/get.go. -func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { - return m, nil -} - -func versions(path string) ([]string, error) { - // Note: modfetch.Lookup and repo.Versions are cached, - // so there's no need for us to add extra caching here. - var versions []string - err := modfetch.TryProxies(func(proxy string) error { - repo, err := modfetch.Lookup(proxy, path) - if err == nil { - versions, err = repo.Versions("") - } - return err - }) - return versions, err -} - -// Previous returns the tagged version of m.Path immediately prior to -// m.Version, or version "none" if no prior version is tagged. -func (*mvsReqs) Previous(m module.Version) (module.Version, error) { - list, err := versions(m.Path) - if err != nil { - return module.Version{}, err - } - i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) - if i > 0 { - return module.Version{Path: m.Path, Version: list[i-1]}, nil - } - return module.Version{Path: m.Path, Version: "none"}, nil -} - -// next returns the next version of m.Path after m.Version. -// It is only used by the exclusion processing in the Required method, -// not called directly by MVS. -func (*mvsReqs) next(m module.Version) (module.Version, error) { - list, err := versions(m.Path) - if err != nil { - return module.Version{}, err - } - i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) - if i < len(list) { - return module.Version{Path: m.Path, Version: list[i]}, nil - } - return module.Version{Path: m.Path, Version: "none"}, nil -} - -// fetch downloads the given module (or its replacement) -// and returns its location. -// -// The isLocal return value reports whether the replacement, -// if any, is local to the filesystem. -func fetch(mod module.Version) (dir string, isLocal bool, err error) { - if mod == Target { - return ModRoot(), true, nil - } - if r := Replacement(mod); r.Path != "" { - if r.Version == "" { - dir = r.Path - if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) - } - // Ensure that the replacement directory actually exists: - // dirInModule does not report errors for missing modules, - // so if we don't report the error now, later failures will be - // very mysterious. - if _, err := os.Stat(dir); err != nil { - if os.IsNotExist(err) { - // Semantically the module version itself “exists” — we just don't - // have its source code. Remove the equivalence to os.ErrNotExist, - // and make the message more concise while we're at it. - err = fmt.Errorf("replacement directory %s does not exist", r.Path) - } else { - err = fmt.Errorf("replacement directory %s: %w", r.Path, err) - } - return dir, true, module.VersionError(mod, err) - } - return dir, true, nil - } - mod = r - } - - dir, err = modfetch.Download(mod) - return dir, false, err -} diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go new file mode 100644 index 00000000000..9f4ec5a49fc --- /dev/null +++ b/src/cmd/go/internal/modload/modfile.go @@ -0,0 +1,164 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package modload + +import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" + + "golang.org/x/mod/modfile" + "golang.org/x/mod/module" +) + +var modFile *modfile.File + +// A modFileIndex is an index of data corresponding to a modFile +// at a specific point in time. +type modFileIndex struct { + data []byte + dataNeedsFix bool // true if fixVersion applied a change while parsing data + module module.Version + goVersion string + require map[module.Version]requireMeta + replace map[module.Version]module.Version + exclude map[module.Version]bool +} + +// index is the index of the go.mod file as of when it was last read or written. +var index *modFileIndex + +type requireMeta struct { + indirect bool +} + +// Allowed reports whether module m is allowed (not excluded) by the main module's go.mod. +func Allowed(m module.Version) bool { + return index == nil || !index.exclude[m] +} + +// Replacement returns the replacement for mod, if any, from go.mod. +// If there is no replacement for mod, Replacement returns +// a module.Version with Path == "". +func Replacement(mod module.Version) module.Version { + if index != nil { + if r, ok := index.replace[mod]; ok { + return r + } + if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { + return r + } + } + return module.Version{} +} + +// indexModFile rebuilds the index of modFile. +// If modFile has been changed since it was first read, +// modFile.Cleanup must be called before indexModFile. +func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileIndex { + i := new(modFileIndex) + i.data = data + i.dataNeedsFix = needsFix + + i.module = module.Version{} + if modFile.Module != nil { + i.module = modFile.Module.Mod + } + + i.goVersion = "" + if modFile.Go != nil { + i.goVersion = modFile.Go.Version + } + + i.require = make(map[module.Version]requireMeta, len(modFile.Require)) + for _, r := range modFile.Require { + i.require[r.Mod] = requireMeta{indirect: r.Indirect} + } + + i.replace = make(map[module.Version]module.Version, len(modFile.Replace)) + for _, r := range modFile.Replace { + if prev, dup := i.replace[r.Old]; dup && prev != r.New { + base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New) + } + i.replace[r.Old] = r.New + } + + i.exclude = make(map[module.Version]bool, len(modFile.Exclude)) + for _, x := range modFile.Exclude { + i.exclude[x.Mod] = true + } + + return i +} + +// modFileIsDirty reports whether the go.mod file differs meaningfully +// from what was indexed. +// If modFile has been changed (even cosmetically) since it was first read, +// modFile.Cleanup must be called before modFileIsDirty. +func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool { + if i == nil { + return modFile != nil + } + + if i.dataNeedsFix { + return true + } + + if modFile.Module == nil { + if i.module != (module.Version{}) { + return true + } + } else if modFile.Module.Mod != i.module { + return true + } + + if modFile.Go == nil { + if i.goVersion != "" { + return true + } + } else if modFile.Go.Version != i.goVersion { + if i.goVersion == "" && cfg.BuildMod == "readonly" { + // go.mod files did not always require a 'go' version, so do not error out + // if one is missing — we may be inside an older module in the module + // cache, and should bias toward providing useful behavior. + } else { + return true + } + } + + if len(modFile.Require) != len(i.require) || + len(modFile.Replace) != len(i.replace) || + len(modFile.Exclude) != len(i.exclude) { + return true + } + + for _, r := range modFile.Require { + if meta, ok := i.require[r.Mod]; !ok { + return true + } else if r.Indirect != meta.indirect { + if cfg.BuildMod == "readonly" { + // The module's requirements are consistent; only the "// indirect" + // comments that are wrong. But those are only guaranteed to be accurate + // after a "go mod tidy" — it's a good idea to run those before + // committing a change, but it's certainly not mandatory. + } else { + return true + } + } + } + + for _, r := range modFile.Replace { + if r.New != i.replace[r.Old] { + return true + } + } + + for _, x := range modFile.Exclude { + if !i.exclude[x.Mod] { + return true + } + } + + return false +} diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go new file mode 100644 index 00000000000..50620e30b69 --- /dev/null +++ b/src/cmd/go/internal/modload/mvs.go @@ -0,0 +1,253 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package modload + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sort" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/modfetch" + "cmd/go/internal/mvs" + "cmd/go/internal/par" + + "golang.org/x/mod/modfile" + "golang.org/x/mod/module" + "golang.org/x/mod/semver" +) + +// mvsReqs implements mvs.Reqs for module semantic versions, +// with any exclusions or replacements applied internally. +type mvsReqs struct { + buildList []module.Version + cache par.Cache + versions sync.Map +} + +// Reqs returns the current module requirement graph. +// Future calls to SetBuildList do not affect the operation +// of the returned Reqs. +func Reqs() mvs.Reqs { + r := &mvsReqs{ + buildList: buildList, + } + return r +} + +func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { + type cached struct { + list []module.Version + err error + } + + c := r.cache.Do(mod, func() interface{} { + list, err := r.required(mod) + if err != nil { + return cached{nil, err} + } + for i, mv := range list { + if index != nil { + for index.exclude[mv] { + mv1, err := r.next(mv) + if err != nil { + return cached{nil, err} + } + if mv1.Version == "none" { + return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)} + } + mv = mv1 + } + } + list[i] = mv + } + + return cached{list, nil} + }).(cached) + + return c.list, c.err +} + +func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { + list := make([]module.Version, 0, len(f.Require)) + for _, r := range f.Require { + list = append(list, r.Mod) + } + return list +} + +// required returns a unique copy of the requirements of mod. +func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { + if mod == Target { + if modFile != nil && modFile.Go != nil { + r.versions.LoadOrStore(mod, modFile.Go.Version) + } + return append([]module.Version(nil), r.buildList[1:]...), nil + } + + if cfg.BuildMod == "vendor" { + // For every module other than the target, + // return the full list of modules from modules.txt. + readVendorList() + return append([]module.Version(nil), vendorList...), nil + } + + origPath := mod.Path + if repl := Replacement(mod); repl.Path != "" { + if repl.Version == "" { + // TODO: need to slip the new version into the tags list etc. + dir := repl.Path + if !filepath.IsAbs(dir) { + dir = filepath.Join(ModRoot(), dir) + } + gomod := filepath.Join(dir, "go.mod") + data, err := ioutil.ReadFile(gomod) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) + } + f, err := modfile.ParseLax(gomod, data, nil) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) + } + if f.Go != nil { + r.versions.LoadOrStore(mod, f.Go.Version) + } + return r.modFileToList(f), nil + } + mod = repl + } + + if mod.Version == "none" { + return nil, nil + } + + if !semver.IsValid(mod.Version) { + // Disallow the broader queries supported by fetch.Lookup. + base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) + } + + data, err := modfetch.GoMod(mod.Path, mod.Version) + if err != nil { + return nil, err + } + f, err := modfile.ParseLax("go.mod", data, nil) + if err != nil { + return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err)) + } + + if f.Module == nil { + return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line")) + } + if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { + return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod: + module declares its path as: %s + but was required as: %s`, mpath, mod.Path)) + } + if f.Go != nil { + r.versions.LoadOrStore(mod, f.Go.Version) + } + + return r.modFileToList(f), nil +} + +func (*mvsReqs) Max(v1, v2 string) string { + if v1 != "" && semver.Compare(v1, v2) == -1 { + return v2 + } + return v1 +} + +// Upgrade is a no-op, here to implement mvs.Reqs. +// The upgrade logic for go get -u is in ../modget/get.go. +func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { + return m, nil +} + +func versions(path string) ([]string, error) { + // Note: modfetch.Lookup and repo.Versions are cached, + // so there's no need for us to add extra caching here. + var versions []string + err := modfetch.TryProxies(func(proxy string) error { + repo, err := modfetch.Lookup(proxy, path) + if err == nil { + versions, err = repo.Versions("") + } + return err + }) + return versions, err +} + +// Previous returns the tagged version of m.Path immediately prior to +// m.Version, or version "none" if no prior version is tagged. +func (*mvsReqs) Previous(m module.Version) (module.Version, error) { + list, err := versions(m.Path) + if err != nil { + return module.Version{}, err + } + i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) + if i > 0 { + return module.Version{Path: m.Path, Version: list[i-1]}, nil + } + return module.Version{Path: m.Path, Version: "none"}, nil +} + +// next returns the next version of m.Path after m.Version. +// It is only used by the exclusion processing in the Required method, +// not called directly by MVS. +func (*mvsReqs) next(m module.Version) (module.Version, error) { + list, err := versions(m.Path) + if err != nil { + return module.Version{}, err + } + i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) + if i < len(list) { + return module.Version{Path: m.Path, Version: list[i]}, nil + } + return module.Version{Path: m.Path, Version: "none"}, nil +} + +// fetch downloads the given module (or its replacement) +// and returns its location. +// +// The isLocal return value reports whether the replacement, +// if any, is local to the filesystem. +func fetch(mod module.Version) (dir string, isLocal bool, err error) { + if mod == Target { + return ModRoot(), true, nil + } + if r := Replacement(mod); r.Path != "" { + if r.Version == "" { + dir = r.Path + if !filepath.IsAbs(dir) { + dir = filepath.Join(ModRoot(), dir) + } + // Ensure that the replacement directory actually exists: + // dirInModule does not report errors for missing modules, + // so if we don't report the error now, later failures will be + // very mysterious. + if _, err := os.Stat(dir); err != nil { + if os.IsNotExist(err) { + // Semantically the module version itself “exists” — we just don't + // have its source code. Remove the equivalence to os.ErrNotExist, + // and make the message more concise while we're at it. + err = fmt.Errorf("replacement directory %s does not exist", r.Path) + } else { + err = fmt.Errorf("replacement directory %s: %w", r.Path, err) + } + return dir, true, module.VersionError(mod, err) + } + return dir, true, nil + } + mod = r + } + + dir, err = modfetch.Download(mod) + return dir, false, err +} diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go new file mode 100644 index 00000000000..71f68efbcc1 --- /dev/null +++ b/src/cmd/go/internal/modload/vendor.go @@ -0,0 +1,217 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package modload + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + + "cmd/go/internal/base" + + "golang.org/x/mod/module" + "golang.org/x/mod/semver" +) + +var ( + vendorOnce sync.Once + vendorList []module.Version // modules that contribute packages to the build, in order of appearance + vendorReplaced []module.Version // all replaced modules; may or may not also contribute packages + vendorVersion map[string]string // module path → selected version (if known) + vendorPkgModule map[string]module.Version // package → containing module + vendorMeta map[module.Version]vendorMetadata +) + +type vendorMetadata struct { + Explicit bool + Replacement module.Version +} + +// readVendorList reads the list of vendored modules from vendor/modules.txt. +func readVendorList() { + vendorOnce.Do(func() { + vendorList = nil + vendorPkgModule = make(map[string]module.Version) + vendorVersion = make(map[string]string) + vendorMeta = make(map[module.Version]vendorMetadata) + data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + base.Fatalf("go: %s", err) + } + return + } + + var mod module.Version + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, "# ") { + f := strings.Fields(line) + + if len(f) < 3 { + continue + } + if semver.IsValid(f[2]) { + // A module, but we don't yet know whether it is in the build list or + // only included to indicate a replacement. + mod = module.Version{Path: f[1], Version: f[2]} + f = f[3:] + } else if f[2] == "=>" { + // A wildcard replacement found in the main module's go.mod file. + mod = module.Version{Path: f[1]} + f = f[2:] + } else { + // Not a version or a wildcard replacement. + // We don't know how to interpret this module line, so ignore it. + mod = module.Version{} + continue + } + + if len(f) >= 2 && f[0] == "=>" { + meta := vendorMeta[mod] + if len(f) == 2 { + // File replacement. + meta.Replacement = module.Version{Path: f[1]} + vendorReplaced = append(vendorReplaced, mod) + } else if len(f) == 3 && semver.IsValid(f[2]) { + // Path and version replacement. + meta.Replacement = module.Version{Path: f[1], Version: f[2]} + vendorReplaced = append(vendorReplaced, mod) + } else { + // We don't understand this replacement. Ignore it. + } + vendorMeta[mod] = meta + } + continue + } + + // Not a module line. Must be a package within a module or a metadata + // directive, either of which requires a preceding module line. + if mod.Path == "" { + continue + } + + if strings.HasPrefix(line, "## ") { + // Metadata. Take the union of annotations across multiple lines, if present. + meta := vendorMeta[mod] + for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") { + entry = strings.TrimSpace(entry) + if entry == "explicit" { + meta.Explicit = true + } + // All other tokens are reserved for future use. + } + vendorMeta[mod] = meta + continue + } + + if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil { + // A package within the current module. + vendorPkgModule[f[0]] = mod + + // Since this module provides a package for the build, we know that it + // is in the build list and is the selected version of its path. + // If this information is new, record it. + if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 { + vendorList = append(vendorList, mod) + vendorVersion[mod.Path] = mod.Version + } + } + } + }) +} + +// checkVendorConsistency verifies that the vendor/modules.txt file matches (if +// go 1.14) or at least does not contradict (go 1.13 or earlier) the +// requirements and replacements listed in the main module's go.mod file. +func checkVendorConsistency() { + readVendorList() + + pre114 := false + if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 { + // Go versions before 1.14 did not include enough information in + // vendor/modules.txt to check for consistency. + // If we know that we're on an earlier version, relax the consistency check. + pre114 = true + } + + vendErrors := new(strings.Builder) + vendErrorf := func(mod module.Version, format string, args ...interface{}) { + detail := fmt.Sprintf(format, args...) + if mod.Version == "" { + fmt.Fprintf(vendErrors, "\n\t%s: %s", mod.Path, detail) + } else { + fmt.Fprintf(vendErrors, "\n\t%s@%s: %s", mod.Path, mod.Version, detail) + } + } + + for _, r := range modFile.Require { + if !vendorMeta[r.Mod].Explicit { + if pre114 { + // Before 1.14, modules.txt did not indicate whether modules were listed + // explicitly in the main module's go.mod file. + // However, we can at least detect a version mismatch if packages were + // vendored from a non-matching version. + if vv, ok := vendorVersion[r.Mod.Path]; ok && vv != r.Mod.Version { + vendErrorf(r.Mod, fmt.Sprintf("is explicitly required in go.mod, but vendor/modules.txt indicates %s@%s", r.Mod.Path, vv)) + } + } else { + vendErrorf(r.Mod, "is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt") + } + } + } + + describe := func(m module.Version) string { + if m.Version == "" { + return m.Path + } + return m.Path + "@" + m.Version + } + + // We need to verify *all* replacements that occur in modfile: even if they + // don't directly apply to any module in the vendor list, the replacement + // go.mod file can affect the selected versions of other (transitive) + // dependencies + for _, r := range modFile.Replace { + vr := vendorMeta[r.Old].Replacement + if vr == (module.Version{}) { + if pre114 && (r.Old.Version == "" || vendorVersion[r.Old.Path] != r.Old.Version) { + // Before 1.14, modules.txt omitted wildcard replacements and + // replacements for modules that did not have any packages to vendor. + } else { + vendErrorf(r.Old, "is replaced in go.mod, but not marked as replaced in vendor/modules.txt") + } + } else if vr != r.New { + vendErrorf(r.Old, "is replaced by %s in go.mod, but marked as replaced by %s in vendor/modules.txt", describe(r.New), describe(vr)) + } + } + + for _, mod := range vendorList { + meta := vendorMeta[mod] + if meta.Explicit { + if _, inGoMod := index.require[mod]; !inGoMod { + vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in go.mod") + } + } + } + + for _, mod := range vendorReplaced { + r := Replacement(mod) + if r == (module.Version{}) { + vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod") + continue + } + if meta := vendorMeta[mod]; r != meta.Replacement { + vendErrorf(mod, "is marked as replaced by %s in vendor/modules.txt, but replaced by %s in go.mod", describe(meta.Replacement), describe(r)) + } + } + + if vendErrors.Len() > 0 { + base.Fatalf("go: inconsistent vendoring in %s:%s\n\nrun 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory", modRoot, vendErrors) + } +} diff --git a/src/cmd/go/internal/robustio/robustio_flaky.go b/src/cmd/go/internal/robustio/robustio_flaky.go index e57c8c74c4c..d4cb7e6457f 100644 --- a/src/cmd/go/internal/robustio/robustio_flaky.go +++ b/src/cmd/go/internal/robustio/robustio_flaky.go @@ -15,7 +15,7 @@ import ( "time" ) -const arbitraryTimeout = 500 * time.Millisecond +const arbitraryTimeout = 2000 * time.Millisecond // retry retries ephemeral errors from f up to an arbitrary timeout // to work around filesystem flakiness on Windows and Darwin. diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 70f3c7b27e0..8f2ffee36f9 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -213,6 +213,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { } else if cfg.BuildTrimpath && p.Module != nil { fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) } + if p.Module != nil { + fmt.Fprintf(h, "go %s\n", p.Module.GoVersion) + } fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch) fmt.Fprintf(h, "import %q\n", p.ImportPath) fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 1dca486c917..00c6523cbc6 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -109,6 +109,7 @@ func (ts *testScript) setup() { "CCACHE_DISABLE=1", // ccache breaks with non-existent HOME "GOARCH=" + runtime.GOARCH, "GOCACHE=" + testGOCACHE, + "GODEBUG=" + os.Getenv("GODEBUG"), "GOEXE=" + cfg.ExeSuffix, "GOOS=" + runtime.GOOS, "GOPATH=" + filepath.Join(ts.workdir, "gopath"), diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README index 71d38161d50..65b4c78090f 100644 --- a/src/cmd/go/testdata/script/README +++ b/src/cmd/go/testdata/script/README @@ -36,6 +36,7 @@ Scripts also have access to these other environment variables: HOME=/no-home PATH= TMPDIR=$WORK/tmp + GODEBUG= devnull= goversion= := diff --git a/src/cmd/go/testdata/script/build_gcflags.txt b/src/cmd/go/testdata/script/build_gcflags.txt index e0accb10d50..b47237410d1 100644 --- a/src/cmd/go/testdata/script/build_gcflags.txt +++ b/src/cmd/go/testdata/script/build_gcflags.txt @@ -7,7 +7,8 @@ env GO111MODULE=off [!linux] skip # test only works if c-archive implies -shared [short] skip -go build -x -buildmode=c-archive -gcflags=all=-shared=false ./override.go +env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache. +go build -x -n -buildmode=c-archive -gcflags=all=-shared=false ./override.go stderr '^.*/compile (.* )?-shared (.* )?-shared=false' -- override.go -- diff --git a/src/cmd/go/testdata/script/cgo_flag_contains_space.txt b/src/cmd/go/testdata/script/cgo_flag_contains_space.txt index 940340e98d4..a3372bbbc76 100644 --- a/src/cmd/go/testdata/script/cgo_flag_contains_space.txt +++ b/src/cmd/go/testdata/script/cgo_flag_contains_space.txt @@ -1,15 +1,16 @@ [short] skip [!cgo] skip -go run -x main.go +env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache. +go build -x -n main.go stderr '"-I[^"]+c flags"' # find quoted c flags -! stderr '"-I[^"]+c flags".*"-I[^"]+c flags"' # don't find too many quoted c flags +! stderr '"-I[^"]+c flags".*"-I[^"]+c flags"' # don't find too many quoted c flags per line stderr '"-L[^"]+ld flags"' # find quoted ld flags -! stderr '"-L[^"]+c flags".*"-L[^"]+c flags"' # don't find too many quoted ld flags +! stderr '"-L[^"]+c flags".*"-L[^"]+c flags"' # don't find too many quoted ld flags per line -- main.go -- package main // #cgo CFLAGS: -I"c flags" // #cgo LDFLAGS: -L"ld flags" import "C" -func main() {} \ No newline at end of file +func main() {} diff --git a/src/cmd/go/testdata/script/cover_blank_func_decl.txt b/src/cmd/go/testdata/script/cover_blank_func_decl.txt new file mode 100644 index 00000000000..6fac4f87ea4 --- /dev/null +++ b/src/cmd/go/testdata/script/cover_blank_func_decl.txt @@ -0,0 +1,31 @@ +[short] skip +go test -cover ./coverblank +stdout 'coverage: 100.0% of statements' + + +-- coverblank/a.go -- +package coverblank + +func _() { + println("unreachable") +} + +type X int + +func (x X) Print() { + println(x) +} + +func (x X) _() { + println("unreachable") +} + +-- coverblank/a_test.go -- +package coverblank + +import "testing" + +func TestX(t *testing.T) { + var x X + x.Print() +} diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt index dce8e39715d..5374493a439 100644 --- a/src/cmd/go/testdata/script/gcflags_patterns.txt +++ b/src/cmd/go/testdata/script/gcflags_patterns.txt @@ -3,6 +3,8 @@ env GO111MODULE=off [!gc] skip 'using -gcflags and -ldflags' [short] skip +env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache. + # -gcflags=-e applies to named packages, not dependencies go build -n -v -gcflags=-e z1 z2 stderr 'compile.* -e.* -p z1' diff --git a/src/cmd/go/testdata/script/mod_concurrent_unzipinplace.txt b/src/cmd/go/testdata/script/mod_concurrent_unzipinplace.txt new file mode 100644 index 00000000000..473be71c9c7 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_concurrent_unzipinplace.txt @@ -0,0 +1,17 @@ +# This tests checks the GODEBUG=modcacheunzipinplace=1 flag, used as part of +# a migration in golang.org/issue/36568. +# +# Concurrent downloads with and without GODEBUG=modcacheunzipinplace=1 should +# not conflict. This is meant to simulate an old version and a new version +# of Go accessing the cache concurrently. +go mod download & +env GODEBUG=modcacheunzipinplace=1 +go mod download +wait + +-- go.mod -- +module golang.org/issue/36568 + +go 1.14 + +require rsc.io/quote v1.5.2 diff --git a/src/cmd/go/testdata/script/mod_download_concurrent_read.txt b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt new file mode 100644 index 00000000000..bb9c5888960 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt @@ -0,0 +1,120 @@ +# This test simulates a process watching for changes and reading files in +# module cache as a module is extracted. +# +# By default, we unzip a downloaded module into a temporary directory with a +# random name, then rename the directory into place. On Windows, this fails +# with ERROR_ACCESS_DENIED if another process (e.g., antivirus) opens files +# in the directory. +# +# Setting GODEBUG=modcacheunzipinplace=1 opts into new behavior: a downloaded +# module is unzipped in place. A .partial file is created elsewhere to indicate +# that the extraction is incomplete. +# +# Verifies golang.org/issue/36568. + +[!windows] skip +[short] skip + +# Control case: check that the default behavior fails. +# This is commented out to avoid flakiness. We can't reproduce the failure +# 100% of the time. +# ! go run downloader.go + +# Experiment: check that the new behavior does not fail. +env GODEBUG=modcacheunzipinplace=1 +go run downloader.go + +-- go.mod -- +module example.com/m + +go 1.14 + +-- downloader.go -- +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" +) + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} + +// run repeatedly downloads a module while opening files in the module cache +// in a background goroutine. +// +// run uses a different temporary module cache in each iteration so that we +// don't need to clean the cache or synchronize closing files after each +// iteration. +func run() (err error) { + tmpDir, err := ioutil.TempDir("", "") + if err != nil { + return err + } + defer func() { + if rmErr := os.RemoveAll(tmpDir); err == nil && rmErr != nil { + err = rmErr + } + }() + for i := 0; i < 10; i++ { + gopath := filepath.Join(tmpDir, fmt.Sprintf("gopath%d", i)) + var err error + done := make(chan struct{}) + go func() { + err = download(gopath) + close(done) + }() + readCache(gopath, done) + if err != nil { + return err + } + } + return nil +} + +// download downloads a module into the given cache using 'go mod download'. +func download(gopath string) error { + cmd := exec.Command("go", "mod", "download", "-modcacherw", "rsc.io/quote@v1.5.2") + cmd.Stderr = os.Stderr + cmd.Env = append(os.Environ(), "GOPATH="+gopath) + return cmd.Run() +} + +// readCache repeatedly globs for go.mod files in the given cache, then opens +// those files for reading. When the done chan is closed, readCache closes +// files and returns. +func readCache(gopath string, done <-chan struct{}) { + files := make(map[string]*os.File) + defer func() { + for _, f := range files { + f.Close() + } + }() + + pattern := filepath.Join(gopath, "pkg/mod/rsc.io/quote@v1.5.2*/go.mod") + for { + select { + case <-done: + return + default: + } + + names, _ := filepath.Glob(pattern) + for _, name := range names { + if files[name] != nil { + continue + } + f, _ := os.Open(name) + if f != nil { + files[name] = f + } + } + } +} diff --git a/src/cmd/go/testdata/script/mod_download_partial.txt b/src/cmd/go/testdata/script/mod_download_partial.txt new file mode 100644 index 00000000000..4978982dab2 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_download_partial.txt @@ -0,0 +1,64 @@ +# Download a module +go mod download -modcacherw rsc.io/quote +exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod + +# 'go mod verify' should fail if we delete a file. +go mod verify +rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod +! go mod verify + +# Create a .partial file to simulate an failure extracting the zip file. +cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial + +# 'go mod verify' should not fail, since the module hasn't been completely +# ingested into the cache. +go mod verify + +# 'go list' should not load packages from the directory. +# NOTE: the message "directory $dir outside available modules" is reported +# for directories not in the main module, active modules in the module cache, +# or local replacements. In this case, the directory is in the right place, +# but it's incomplete, so 'go list' acts as if it's not an active module. +! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +stderr 'outside available modules' + +# 'go list -m' should not print the directory. +go list -m -f '{{.Dir}}' rsc.io/quote +! stdout . + +# 'go mod download' should re-extract the module and remove the .partial file. +go mod download -modcacherw rsc.io/quote +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial +exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod + +# 'go list' should succeed. +go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +stdout '^rsc.io/quote$' + +# 'go list -m' should print the directory. +go list -m -f '{{.Dir}}' rsc.io/quote +stdout 'pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2' + +# go mod verify should fail if we delete a file. +go mod verify +rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod +! go mod verify + +# 'go mod download' should not leave behind a directory or a .partial file +# if there is an error extracting the zip file. +env GODEBUG=modcacheunzipinplace=1 +rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +! go mod download +stderr 'not a valid zip file' +! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial + +-- go.mod -- +module m + +go 1.14 + +require rsc.io/quote v1.5.2 + +-- empty -- diff --git a/src/cmd/go/testdata/script/mod_edit_go.txt b/src/cmd/go/testdata/script/mod_edit_go.txt index 3ec8137e2d3..38321d071fb 100644 --- a/src/cmd/go/testdata/script/mod_edit_go.txt +++ b/src/cmd/go/testdata/script/mod_edit_go.txt @@ -7,6 +7,13 @@ go mod edit -go=1.9 grep 'go 1.9' go.mod go build +# Reverting the version should force a rebuild and error instead of using +# the cached 1.9 build. (https://golang.org/issue/37804) +go mod edit -go=1.8 +! go build +stderr 'type aliases only supported as of' + + -- go.mod -- module m go 1.8 diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt index a906babbd5f..d108242c70e 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -14,6 +14,9 @@ go get -d golang.org/x/text@14c0d48 # dropping -d, we should see a build. [short] skip + +env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache. + go get -x golang.org/x/text/language@14c0d48 stderr 'compile|cp|gccgo .*language\.a$' diff --git a/src/cmd/go/testdata/script/mod_get_tags.txt b/src/cmd/go/testdata/script/mod_get_tags.txt index 603c76983f7..e9869e3f023 100644 --- a/src/cmd/go/testdata/script/mod_get_tags.txt +++ b/src/cmd/go/testdata/script/mod_get_tags.txt @@ -14,7 +14,8 @@ stdout 'rsc.io/quote v1.5.2' [short] skip # Packages that are only imported in excluded files should not be built. -go get -x . +env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache. +go get -n -x . stderr 'compile.* -p m ' ! stderr 'compile.* -p example.com/version ' ! stderr 'compile.* -p rsc.io/quote ' diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index 76e0b43a735..7e1bc9ea4f9 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -76,17 +76,17 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(2017-09-15T03:28:32Z\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' cd .. ! go list -m golang.org/x/text -stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(2017-09-15T03:28:32Z\)' +stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' # A 'replace' directive in the main module can replace an invalid timestamp # with a valid one. go mod edit -replace golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c=golang.org/x/text@14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(2017-09-15T03:28:32Z\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.1.1-0.20190915032832-14c0d48ead0c => golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c' diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go index d544a4d8dfa..b6fd92438e2 100644 --- a/src/cmd/internal/moddeps/moddeps_test.go +++ b/src/cmd/internal/moddeps/moddeps_test.go @@ -47,6 +47,7 @@ func findGorootModules(t *testing.T) []gorootModule { // Use 'go list' to describe the module contained in this directory (but // not its dependencies). cmd := exec.Command(goBin, "list", "-json", "-m") + cmd.Env = append(os.Environ(), "GO111MODULE=on") cmd.Dir = dir cmd.Stderr = new(strings.Builder) out, err := cmd.Output() @@ -103,6 +104,7 @@ func TestAllDependenciesVendored(t *testing.T) { // dependencies are vendored. If any imported package is missing, // 'go list -deps' will fail when attempting to load it. cmd := exec.Command(goBin, "list", "-mod=vendor", "-deps", "./...") + cmd.Env = append(os.Environ(), "GO111MODULE=on") cmd.Dir = m.Dir cmd.Stderr = new(strings.Builder) _, err := cmd.Output() @@ -115,7 +117,8 @@ func TestAllDependenciesVendored(t *testing.T) { // There is no vendor directory, so the module must have no dependencies. // Check that the list of active modules contains only the main module. - cmd := exec.Command(goBin, "list", "-m", "all") + cmd := exec.Command(goBin, "list", "-mod=mod", "-m", "all") + cmd.Env = append(os.Environ(), "GO111MODULE=on") cmd.Dir = m.Dir cmd.Stderr = new(strings.Builder) out, err := cmd.Output() diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 55eb1c314b0..59bf776f85b 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -944,22 +944,16 @@ const ( ASTXVW4X ASTXVH8X ASTXVB16X - ALXS ALXSDX - ASTXS ASTXSDX - ALXSI ALXSIWAX ALXSIWZX - ASTXSI ASTXSIWX - AMFVSR AMFVSRD AMFFPRD AMFVRD AMFVSRWZ AMFVSRLD - AMTVSR AMTVSRD AMTFPRD AMTVRD @@ -968,7 +962,6 @@ const ( AMTVSRDD AMTVSRWS AXXLAND - AXXLANDQ AXXLANDC AXXLEQV AXXLNAND @@ -978,34 +971,27 @@ const ( AXXLORQ AXXLXOR AXXSEL - AXXMRG AXXMRGHW AXXMRGLW AXXSPLT AXXSPLTW AXXPERM AXXPERMDI - AXXSI AXXSLDWI - AXSCV AXSCVDPSP AXSCVSPDP AXSCVDPSPN AXSCVSPDPN - AXVCV AXVCVDPSP AXVCVSPDP - AXSCVX AXSCVDPSXDS AXSCVDPSXWS AXSCVDPUXDS AXSCVDPUXWS - AXSCVXP AXSCVSXDDP AXSCVUXDDP AXSCVSXDSP AXSCVUXDSP - AXVCVX AXVCVDPSXDS AXVCVDPSXWS AXVCVDPUXDS @@ -1014,7 +1000,6 @@ const ( AXVCVSPSXWS AXVCVSPUXDS AXVCVSPUXWS - AXVCVXP AXVCVSXDDP AXVCVSXWDP AXVCVUXDDP diff --git a/src/cmd/internal/obj/ppc64/anames.go b/src/cmd/internal/obj/ppc64/anames.go index 9294b3c5fe7..901c9f70377 100644 --- a/src/cmd/internal/obj/ppc64/anames.go +++ b/src/cmd/internal/obj/ppc64/anames.go @@ -532,22 +532,16 @@ var Anames = []string{ "STXVW4X", "STXVH8X", "STXVB16X", - "LXS", "LXSDX", - "STXS", "STXSDX", - "LXSI", "LXSIWAX", "LXSIWZX", - "STXSI", "STXSIWX", - "MFVSR", "MFVSRD", "MFFPRD", "MFVRD", "MFVSRWZ", "MFVSRLD", - "MTVSR", "MTVSRD", "MTFPRD", "MTVRD", @@ -556,7 +550,6 @@ var Anames = []string{ "MTVSRDD", "MTVSRWS", "XXLAND", - "XXLANDQ", "XXLANDC", "XXLEQV", "XXLNAND", @@ -566,34 +559,27 @@ var Anames = []string{ "XXLORQ", "XXLXOR", "XXSEL", - "XXMRG", "XXMRGHW", "XXMRGLW", "XXSPLT", "XXSPLTW", "XXPERM", "XXPERMDI", - "XXSI", "XXSLDWI", - "XSCV", "XSCVDPSP", "XSCVSPDP", "XSCVDPSPN", "XSCVSPDPN", - "XVCV", "XVCVDPSP", "XVCVSPDP", - "XSCVX", "XSCVDPSXDS", "XSCVDPSXWS", "XSCVDPUXDS", "XSCVDPUXWS", - "XSCVXP", "XSCVSXDDP", "XSCVUXDDP", "XSCVSXDSP", "XSCVUXDSP", - "XVCVX", "XVCVDPSXDS", "XVCVDPSXWS", "XVCVDPUXDS", @@ -602,7 +588,6 @@ var Anames = []string{ "XVCVSPSXWS", "XVCVSPUXDS", "XVCVSPUXWS", - "XVCVXP", "XVCVSXDDP", "XVCVSXWDP", "XVCVUXDDP", diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 149604574b1..b62eda8b148 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -462,10 +462,10 @@ var optab = []Optab{ {AVSEL, C_VREG, C_VREG, C_VREG, C_VREG, 83, 4, 0}, /* vector select, va-form */ /* Vector splat */ - {AVSPLT, C_SCON, C_VREG, C_NONE, C_VREG, 82, 4, 0}, /* vector splat, vx-form */ - {AVSPLT, C_ADDCON, C_VREG, C_NONE, C_VREG, 82, 4, 0}, - {AVSPLTI, C_SCON, C_NONE, C_NONE, C_VREG, 82, 4, 0}, /* vector splat immediate, vx-form */ - {AVSPLTI, C_ADDCON, C_NONE, C_NONE, C_VREG, 82, 4, 0}, + {AVSPLTB, C_SCON, C_VREG, C_NONE, C_VREG, 82, 4, 0}, /* vector splat, vx-form */ + {AVSPLTB, C_ADDCON, C_VREG, C_NONE, C_VREG, 82, 4, 0}, + {AVSPLTISB, C_SCON, C_NONE, C_NONE, C_VREG, 82, 4, 0}, /* vector splat immediate, vx-form */ + {AVSPLTISB, C_ADDCON, C_NONE, C_NONE, C_VREG, 82, 4, 0}, /* Vector AES */ {AVCIPH, C_VREG, C_VREG, C_NONE, C_VREG, 82, 4, 0}, /* vector AES cipher, vx-form */ @@ -484,27 +484,27 @@ var optab = []Optab{ {ASTXV, C_VSREG, C_NONE, C_NONE, C_SOREG, 97, 4, 0}, /* vsx vector store, dq-form */ /* VSX scalar load */ - {ALXS, C_SOREG, C_NONE, C_NONE, C_VSREG, 87, 4, 0}, /* vsx scalar load, xx1-form */ + {ALXSDX, C_SOREG, C_NONE, C_NONE, C_VSREG, 87, 4, 0}, /* vsx scalar load, xx1-form */ /* VSX scalar store */ - {ASTXS, C_VSREG, C_NONE, C_NONE, C_SOREG, 86, 4, 0}, /* vsx scalar store, xx1-form */ + {ASTXSDX, C_VSREG, C_NONE, C_NONE, C_SOREG, 86, 4, 0}, /* vsx scalar store, xx1-form */ /* VSX scalar as integer load */ - {ALXSI, C_SOREG, C_NONE, C_NONE, C_VSREG, 87, 4, 0}, /* vsx scalar as integer load, xx1-form */ + {ALXSIWAX, C_SOREG, C_NONE, C_NONE, C_VSREG, 87, 4, 0}, /* vsx scalar as integer load, xx1-form */ /* VSX scalar store as integer */ - {ASTXSI, C_VSREG, C_NONE, C_NONE, C_SOREG, 86, 4, 0}, /* vsx scalar as integer store, xx1-form */ + {ASTXSIWX, C_VSREG, C_NONE, C_NONE, C_SOREG, 86, 4, 0}, /* vsx scalar as integer store, xx1-form */ /* VSX move from VSR */ - {AMFVSR, C_VSREG, C_NONE, C_NONE, C_REG, 88, 4, 0}, /* vsx move from vsr, xx1-form */ - {AMFVSR, C_FREG, C_NONE, C_NONE, C_REG, 88, 4, 0}, - {AMFVSR, C_VREG, C_NONE, C_NONE, C_REG, 88, 4, 0}, + {AMFVSRD, C_VSREG, C_NONE, C_NONE, C_REG, 88, 4, 0}, /* vsx move from vsr, xx1-form */ + {AMFVSRD, C_FREG, C_NONE, C_NONE, C_REG, 88, 4, 0}, + {AMFVSRD, C_VREG, C_NONE, C_NONE, C_REG, 88, 4, 0}, /* VSX move to VSR */ - {AMTVSR, C_REG, C_NONE, C_NONE, C_VSREG, 88, 4, 0}, /* vsx move to vsr, xx1-form */ - {AMTVSR, C_REG, C_REG, C_NONE, C_VSREG, 88, 4, 0}, - {AMTVSR, C_REG, C_NONE, C_NONE, C_FREG, 88, 4, 0}, - {AMTVSR, C_REG, C_NONE, C_NONE, C_VREG, 88, 4, 0}, + {AMTVSRD, C_REG, C_NONE, C_NONE, C_VSREG, 88, 4, 0}, /* vsx move to vsr, xx1-form */ + {AMTVSRD, C_REG, C_REG, C_NONE, C_VSREG, 88, 4, 0}, + {AMTVSRD, C_REG, C_NONE, C_NONE, C_FREG, 88, 4, 0}, + {AMTVSRD, C_REG, C_NONE, C_NONE, C_VREG, 88, 4, 0}, /* VSX logical */ {AXXLAND, C_VSREG, C_VSREG, C_NONE, C_VSREG, 90, 4, 0}, /* vsx and, xx3-form */ @@ -514,34 +514,34 @@ var optab = []Optab{ {AXXSEL, C_VSREG, C_VSREG, C_VSREG, C_VSREG, 91, 4, 0}, /* vsx select, xx4-form */ /* VSX merge */ - {AXXMRG, C_VSREG, C_VSREG, C_NONE, C_VSREG, 90, 4, 0}, /* vsx merge, xx3-form */ + {AXXMRGHW, C_VSREG, C_VSREG, C_NONE, C_VSREG, 90, 4, 0}, /* vsx merge, xx3-form */ /* VSX splat */ - {AXXSPLT, C_VSREG, C_NONE, C_SCON, C_VSREG, 89, 4, 0}, /* vsx splat, xx2-form */ + {AXXSPLTW, C_VSREG, C_NONE, C_SCON, C_VSREG, 89, 4, 0}, /* vsx splat, xx2-form */ /* VSX permute */ - {AXXPERM, C_VSREG, C_VSREG, C_SCON, C_VSREG, 90, 4, 0}, /* vsx permute, xx3-form */ + {AXXPERM, C_VSREG, C_VSREG, C_NONE, C_VSREG, 90, 4, 0}, /* vsx permute, xx3-form */ /* VSX shift */ - {AXXSI, C_VSREG, C_VSREG, C_SCON, C_VSREG, 90, 4, 0}, /* vsx shift immediate, xx3-form */ + {AXXSLDWI, C_VSREG, C_VSREG, C_SCON, C_VSREG, 90, 4, 0}, /* vsx shift immediate, xx3-form */ /* VSX scalar FP-FP conversion */ - {AXSCV, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx scalar fp-fp conversion, xx2-form */ + {AXSCVDPSP, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx scalar fp-fp conversion, xx2-form */ /* VSX vector FP-FP conversion */ - {AXVCV, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx vector fp-fp conversion, xx2-form */ + {AXVCVDPSP, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx vector fp-fp conversion, xx2-form */ /* VSX scalar FP-integer conversion */ - {AXSCVX, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx scalar fp-integer conversion, xx2-form */ + {AXSCVDPSXDS, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx scalar fp-integer conversion, xx2-form */ /* VSX scalar integer-FP conversion */ - {AXSCVXP, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx scalar integer-fp conversion, xx2-form */ + {AXSCVSXDDP, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx scalar integer-fp conversion, xx2-form */ /* VSX vector FP-integer conversion */ - {AXVCVX, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx vector fp-integer conversion, xx2-form */ + {AXVCVDPSXDS, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx vector fp-integer conversion, xx2-form */ /* VSX vector integer-FP conversion */ - {AXVCVXP, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx vector integer-fp conversion, xx2-form */ + {AXVCVSXDDP, C_VSREG, C_NONE, C_NONE, C_VSREG, 89, 4, 0}, /* vsx vector integer-fp conversion, xx2-form */ /* 64-bit special registers */ {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0}, @@ -1519,13 +1519,11 @@ func buildop(ctxt *obj.Link) { case AVSEL: /* vsel */ opset(AVSEL, r0) - case AVSPLT: /* vspltb, vsplth, vspltw */ - opset(AVSPLTB, r0) + case AVSPLTB: /* vspltb, vsplth, vspltw */ opset(AVSPLTH, r0) opset(AVSPLTW, r0) - case AVSPLTI: /* vspltisb, vspltish, vspltisw */ - opset(AVSPLTISB, r0) + case AVSPLTISB: /* vspltisb, vspltish, vspltisw */ opset(AVSPLTISH, r0) opset(AVSPLTISW, r0) @@ -1561,28 +1559,25 @@ func buildop(ctxt *obj.Link) { case ASTXV: /* stxv */ opset(ASTXV, r0) - case ALXS: /* lxsdx */ + case ALXSDX: /* lxsdx */ opset(ALXSDX, r0) - case ASTXS: /* stxsdx */ + case ASTXSDX: /* stxsdx */ opset(ASTXSDX, r0) - case ALXSI: /* lxsiwax, lxsiwzx */ - opset(ALXSIWAX, r0) + case ALXSIWAX: /* lxsiwax, lxsiwzx */ opset(ALXSIWZX, r0) - case ASTXSI: /* stxsiwx */ + case ASTXSIWX: /* stxsiwx */ opset(ASTXSIWX, r0) - case AMFVSR: /* mfvsrd, mfvsrwz (and extended mnemonics), mfvsrld */ - opset(AMFVSRD, r0) + case AMFVSRD: /* mfvsrd, mfvsrwz (and extended mnemonics), mfvsrld */ opset(AMFFPRD, r0) opset(AMFVRD, r0) opset(AMFVSRWZ, r0) opset(AMFVSRLD, r0) - case AMTVSR: /* mtvsrd, mtvsrwa, mtvsrwz (and extended mnemonics), mtvsrdd, mtvsrws */ - opset(AMTVSRD, r0) + case AMTVSRD: /* mtvsrd, mtvsrwa, mtvsrwz (and extended mnemonics), mtvsrdd, mtvsrws */ opset(AMTFPRD, r0) opset(AMTVRD, r0) opset(AMTVSRWA, r0) @@ -1591,7 +1586,6 @@ func buildop(ctxt *obj.Link) { opset(AMTVSRWS, r0) case AXXLAND: /* xxland, xxlandc, xxleqv, xxlnand */ - opset(AXXLANDQ, r0) opset(AXXLANDC, r0) opset(AXXLEQV, r0) opset(AXXLNAND, r0) @@ -1605,42 +1599,38 @@ func buildop(ctxt *obj.Link) { case AXXSEL: /* xxsel */ opset(AXXSEL, r0) - case AXXMRG: /* xxmrghw, xxmrglw */ - opset(AXXMRGHW, r0) + case AXXMRGHW: /* xxmrghw, xxmrglw */ opset(AXXMRGLW, r0) - case AXXSPLT: /* xxspltw */ + case AXXSPLTW: /* xxspltw */ opset(AXXSPLTW, r0) case AXXPERM: /* xxpermdi */ - opset(AXXPERMDI, r0) + opset(AXXPERM, r0) - case AXXSI: /* xxsldwi */ + case AXXSLDWI: /* xxsldwi */ + opset(AXXPERMDI, r0) opset(AXXSLDWI, r0) - case AXSCV: /* xscvdpsp, xscvspdp, xscvdpspn, xscvspdpn */ - opset(AXSCVDPSP, r0) + case AXSCVDPSP: /* xscvdpsp, xscvspdp, xscvdpspn, xscvspdpn */ opset(AXSCVSPDP, r0) opset(AXSCVDPSPN, r0) opset(AXSCVSPDPN, r0) - case AXVCV: /* xvcvdpsp, xvcvspdp */ - opset(AXVCVDPSP, r0) + case AXVCVDPSP: /* xvcvdpsp, xvcvspdp */ opset(AXVCVSPDP, r0) - case AXSCVX: /* xscvdpsxds, xscvdpsxws, xscvdpuxds, xscvdpuxws */ - opset(AXSCVDPSXDS, r0) + case AXSCVDPSXDS: /* xscvdpsxds, xscvdpsxws, xscvdpuxds, xscvdpuxws */ opset(AXSCVDPSXWS, r0) opset(AXSCVDPUXDS, r0) opset(AXSCVDPUXWS, r0) - case AXSCVXP: /* xscvsxddp, xscvuxddp, xscvsxdsp, xscvuxdsp */ - opset(AXSCVSXDDP, r0) + case AXSCVSXDDP: /* xscvsxddp, xscvuxddp, xscvsxdsp, xscvuxdsp */ opset(AXSCVUXDDP, r0) opset(AXSCVSXDSP, r0) opset(AXSCVUXDSP, r0) - case AXVCVX: /* xvcvdpsxds, xvcvdpsxws, xvcvdpuxds, xvcvdpuxws, xvcvspsxds, xvcvspsxws, xvcvspuxds, xvcvspuxws */ + case AXVCVDPSXDS: /* xvcvdpsxds, xvcvdpsxws, xvcvdpuxds, xvcvdpuxws, xvcvspsxds, xvcvspsxws, xvcvspuxds, xvcvspuxws */ opset(AXVCVDPSXDS, r0) opset(AXVCVDPSXWS, r0) opset(AXVCVDPUXDS, r0) @@ -1650,8 +1640,7 @@ func buildop(ctxt *obj.Link) { opset(AXVCVSPUXDS, r0) opset(AXVCVSPUXWS, r0) - case AXVCVXP: /* xvcvsxddp, xvcvsxwdp, xvcvuxddp, xvcvuxwdp, xvcvsxdsp, xvcvsxwsp, xvcvuxdsp, xvcvuxwsp */ - opset(AXVCVSXDDP, r0) + case AXVCVSXDDP: /* xvcvsxddp, xvcvsxwdp, xvcvuxddp, xvcvuxwdp, xvcvsxdsp, xvcvsxwsp, xvcvuxdsp, xvcvuxwsp */ opset(AXVCVSXWDP, r0) opset(AXVCVUXDDP, r0) opset(AXVCVUXWDP, r0) @@ -4616,7 +4605,7 @@ func (c *ctxt9) oprrr(a obj.As) uint32 { case AMTVSRWS: return OPVXX1(31, 403, 0) /* mtvsrws - v3.00 */ - case AXXLANDQ: + case AXXLAND: return OPVXX3(60, 130, 0) /* xxland - v2.06 */ case AXXLANDC: return OPVXX3(60, 138, 0) /* xxlandc - v2.06 */ @@ -4645,6 +4634,8 @@ func (c *ctxt9) oprrr(a obj.As) uint32 { case AXXSPLTW: return OPVXX2(60, 164, 0) /* xxspltw - v2.06 */ + case AXXPERM: + return OPVXX3(60, 26, 0) /* xxperm - v2.06 */ case AXXPERMDI: return OPVXX3(60, 10, 0) /* xxpermdi - v2.06 */ diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go index b979a7f8aa0..35cfd35d37c 100644 --- a/src/cmd/internal/objfile/disasm.go +++ b/src/cmd/internal/objfile/disasm.go @@ -175,6 +175,11 @@ func (fc *FileCache) Line(filename string, line int) ([]byte, error) { fc.files.MoveToFront(e) } + // because //line directives can be out-of-range. (#36683) + if line-1 >= len(cf.Lines) || line-1 < 0 { + return nil, nil + } + return cf.Lines[line-1], nil } diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index c2b6121c003..cf6bec80535 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -1239,6 +1239,7 @@ func TestPackageNameAttr(t *testing.T) { } rdr := d.Reader() + runtimeUnitSeen := false for { e, err := rdr.Next() if err != nil { @@ -1254,11 +1255,25 @@ func TestPackageNameAttr(t *testing.T) { continue } - _, ok := e.Val(dwarfAttrGoPackageName).(string) + pn, ok := e.Val(dwarfAttrGoPackageName).(string) if !ok { name, _ := e.Val(dwarf.AttrName).(string) t.Errorf("found compile unit without package name: %s", name) + } + if pn == "" { + name, _ := e.Val(dwarf.AttrName).(string) + t.Errorf("found compile unit with empty package name: %s", name) + } else { + if pn == "runtime" { + runtimeUnitSeen = true + } + } + } + + // Something is wrong if there's no runtime compilation unit. + if !runtimeUnitSeen { + t.Errorf("no package name for runtime unit") } } diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 5b66deeba2c..fdfb9962e52 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -58,47 +58,15 @@ var ( ) const ( - IMAGE_FILE_MACHINE_I386 = 0x14c - IMAGE_FILE_MACHINE_AMD64 = 0x8664 - IMAGE_FILE_MACHINE_ARM = 0x1c0 - IMAGE_FILE_MACHINE_ARMNT = 0x1c4 - IMAGE_FILE_RELOCS_STRIPPED = 0x0001 - IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 - IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 - IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 - IMAGE_FILE_32BIT_MACHINE = 0x0100 - IMAGE_FILE_DEBUG_STRIPPED = 0x0200 - IMAGE_SCN_CNT_CODE = 0x00000020 - IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 - IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 - IMAGE_SCN_MEM_EXECUTE = 0x20000000 - IMAGE_SCN_MEM_READ = 0x40000000 - IMAGE_SCN_MEM_WRITE = 0x80000000 - IMAGE_SCN_MEM_DISCARDABLE = 0x2000000 - IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000 - IMAGE_SCN_ALIGN_32BYTES = 0x600000 - IMAGE_DIRECTORY_ENTRY_EXPORT = 0 - IMAGE_DIRECTORY_ENTRY_IMPORT = 1 - IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 - IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 - IMAGE_DIRECTORY_ENTRY_SECURITY = 4 - IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 - IMAGE_DIRECTORY_ENTRY_DEBUG = 6 - IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 - IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 - IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 - IMAGE_DIRECTORY_ENTRY_TLS = 9 - IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 - IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 - IMAGE_DIRECTORY_ENTRY_IAT = 12 - IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 - IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 - IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 - IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 - IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 - IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 - IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100 - IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 + IMAGE_SCN_CNT_CODE = 0x00000020 + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 + IMAGE_SCN_MEM_EXECUTE = 0x20000000 + IMAGE_SCN_MEM_READ = 0x40000000 + IMAGE_SCN_MEM_WRITE = 0x80000000 + IMAGE_SCN_MEM_DISCARDABLE = 0x2000000 + IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000 + IMAGE_SCN_ALIGN_32BYTES = 0x600000 ) // TODO(crawshaw): add these constants to debug/pe. @@ -762,11 +730,11 @@ func (f *peFile) writeFileHeader(ctxt *Link) { default: Exitf("unknown PE architecture: %v", ctxt.Arch.Family) case sys.AMD64: - fh.Machine = IMAGE_FILE_MACHINE_AMD64 + fh.Machine = pe.IMAGE_FILE_MACHINE_AMD64 case sys.I386: - fh.Machine = IMAGE_FILE_MACHINE_I386 + fh.Machine = pe.IMAGE_FILE_MACHINE_I386 case sys.ARM: - fh.Machine = IMAGE_FILE_MACHINE_ARMNT + fh.Machine = pe.IMAGE_FILE_MACHINE_ARMNT } fh.NumberOfSections = uint16(len(f.sections)) @@ -776,24 +744,24 @@ func (f *peFile) writeFileHeader(ctxt *Link) { fh.TimeDateStamp = 0 if ctxt.LinkMode == LinkExternal { - fh.Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED + fh.Characteristics = pe.IMAGE_FILE_LINE_NUMS_STRIPPED } else { - fh.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED + fh.Characteristics = pe.IMAGE_FILE_EXECUTABLE_IMAGE | pe.IMAGE_FILE_DEBUG_STRIPPED switch ctxt.Arch.Family { case sys.AMD64, sys.I386: if ctxt.BuildMode != BuildModePIE { - fh.Characteristics |= IMAGE_FILE_RELOCS_STRIPPED + fh.Characteristics |= pe.IMAGE_FILE_RELOCS_STRIPPED } } } if pe64 != 0 { var oh64 pe.OptionalHeader64 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64)) - fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE + fh.Characteristics |= pe.IMAGE_FILE_LARGE_ADDRESS_AWARE } else { var oh pe.OptionalHeader32 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh)) - fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE + fh.Characteristics |= pe.IMAGE_FILE_32BIT_MACHINE } fh.PointerToSymbolTable = uint32(f.symtabOffset) @@ -854,36 +822,36 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) { oh64.SizeOfHeaders = uint32(PEFILEHEADR) oh.SizeOfHeaders = uint32(PEFILEHEADR) if windowsgui { - oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI - oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI + oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI + oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI } else { - oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI - oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI + oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI + oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI } // Mark as having awareness of terminal services, to avoid ancient compatibility hacks. - oh64.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE - oh.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE + oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE + oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE // Enable DEP - oh64.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT - oh.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT + oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT + oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT // The DLL can be relocated at load time. switch ctxt.Arch.Family { case sys.AMD64, sys.I386: if ctxt.BuildMode == BuildModePIE { - oh64.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE - oh.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE + oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE + oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE } case sys.ARM: - oh64.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE - oh.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE + oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE + oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE } // Image can handle a high entropy 64-bit virtual address space. if ctxt.BuildMode == BuildModePIE { - oh64.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA + oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA } // Disable stack growth as we don't want Windows to @@ -1229,10 +1197,10 @@ func addimports(ctxt *Link, datsect *peSection) { out.Write32(0) // update data directory - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE) - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size) + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE) + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size) out.SeekSet(endoff) } @@ -1272,8 +1240,8 @@ func addexports(ctxt *Link) { sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ sect.checkOffset(ctxt.Out.Offset()) va := int(sect.virtualAddress) - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va) - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va) + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize vaName := va + binary.Size(&e) + nexport*4 vaAddr := va + binary.Size(&e) @@ -1481,8 +1449,8 @@ func addPEBaseReloc(ctxt *Link) { rsect.checkOffset(startoff) rsect.pad(ctxt.Out, uint32(size)) - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize } func (ctxt *Link) dope() { @@ -1528,9 +1496,9 @@ func addpersrc(ctxt *Link) { h.pad(ctxt.Out, uint32(size)) // update data directory - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress - pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize } func Asmbpe(ctxt *Link) { diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index 0c2adbdb949..7ed32cf3c27 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -106,8 +106,11 @@ func testDisasm(t *testing.T, printCode bool, flags ...string) { hello := filepath.Join(tmp, fmt.Sprintf("hello-%x.exe", hash)) args := []string{"build", "-o", hello} args = append(args, flags...) - args = append(args, "testdata/fmthello.go") - out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput() + args = append(args, "fmthello.go") + cmd := exec.Command(testenv.GoToolPath(t), args...) + cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory + t.Logf("Running %v", cmd.Args) + out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("go build fmthello.go: %v\n%s", err, out) } @@ -139,7 +142,11 @@ func testDisasm(t *testing.T, printCode bool, flags ...string) { args = append([]string{"-S"}, args...) } - out, err = exec.Command(exe, args...).CombinedOutput() + cmd = exec.Command(exe, args...) + cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory + out, err = cmd.CombinedOutput() + t.Logf("Running %v", cmd.Args) + if err != nil { t.Fatalf("objdump fmthello.exe: %v\n%s", err, out) } diff --git a/src/cmd/objdump/testdata/fmthello.go b/src/cmd/objdump/testdata/fmthello.go index fd16ebee1b0..c8d82466dc9 100644 --- a/src/cmd/objdump/testdata/fmthello.go +++ b/src/cmd/objdump/testdata/fmthello.go @@ -5,6 +5,8 @@ import "fmt" func main() { Println("hello, world") if flag { +//line fmthello.go:999999 + Println("bad line") for { } } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go index 1b555a4e2e7..56083d8abfb 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go @@ -834,10 +834,19 @@ func printTraces(w io.Writer, rpt *Report) error { _, locations := graph.CreateNodes(prof, &graph.Options{}) for _, sample := range prof.Sample { - var stack graph.Nodes + type stk struct { + *graph.NodeInfo + inline bool + } + var stack []stk for _, loc := range sample.Location { - id := loc.ID - stack = append(stack, locations[id]...) + nodes := locations[loc.ID] + for i, n := range nodes { + // The inline flag may be inaccurate if 'show' or 'hide' filter is + // used. See https://github.com/google/pprof/issues/511. + inline := i != len(nodes)-1 + stack = append(stack, stk{&n.Info, inline}) + } } if len(stack) == 0 { @@ -875,10 +884,15 @@ func printTraces(w io.Writer, rpt *Report) error { if d != 0 { v = v / d } - fmt.Fprintf(w, "%10s %s\n", - rpt.formatValue(v), stack[0].Info.PrintableName()) - for _, s := range stack[1:] { - fmt.Fprintf(w, "%10s %s\n", "", s.Info.PrintableName()) + for i, s := range stack { + var vs, inline string + if i == 0 { + vs = rpt.formatValue(v) + } + if s.inline { + inline = " (inline)" + } + fmt.Fprintf(w, "%10s %s%s\n", vs, s.PrintableName(), inline) } } fmt.Fprintln(w, separator) diff --git a/src/cmd/vendor/github.com/google/pprof/profile/proto.go b/src/cmd/vendor/github.com/google/pprof/profile/proto.go index e7df33ac2b8..539ad3ab33f 100644 --- a/src/cmd/vendor/github.com/google/pprof/profile/proto.go +++ b/src/cmd/vendor/github.com/google/pprof/profile/proto.go @@ -33,7 +33,10 @@ package profile -import "errors" +import ( + "errors" + "fmt" +) type buffer struct { field int // field tag @@ -235,7 +238,7 @@ func decodeField(b *buffer, data []byte) ([]byte, error) { b.u64 = uint64(le32(data[:4])) data = data[4:] default: - return nil, errors.New("unknown wire type: " + string(b.typ)) + return nil, fmt.Errorf("unknown wire type: %d", b.typ) } return data, nil diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go index b80271afb95..384f0255704 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go @@ -51,7 +51,7 @@ func run(pass *analysis.Pass) (interface{}, error) { return // not enough arguments, e.g. called with return values of another function } if fn.FullName() == "errors.As" && !pointerToInterfaceOrError(pass, call.Args[1]) { - pass.ReportRangef(call, "second argument to errors.As must be a pointer to an interface or a type implementing error") + pass.ReportRangef(call, "second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type") } }) return nil, nil diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go new file mode 100644 index 00000000000..c5a71a7c570 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go @@ -0,0 +1,101 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ifaceassert defines an Analyzer that flags +// impossible interface-interface type assertions. +package ifaceassert + +import ( + "go/ast" + "go/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const Doc = `detect impossible interface-to-interface type assertions + +This checker flags type assertions v.(T) and corresponding type-switch cases +in which the static type V of v is an interface that cannot possibly implement +the target interface T. This occurs when V and T contain methods with the same +name but different signatures. Example: + + var v interface { + Read() + } + _ = v.(io.Reader) + +The Read method in v has a different signature than the Read method in +io.Reader, so this assertion cannot succeed. +` + +var Analyzer = &analysis.Analyzer{ + Name: "ifaceassert", + Doc: Doc, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: run, +} + +// assertableTo checks whether interface v can be asserted into t. It returns +// nil on success, or the first conflicting method on failure. +func assertableTo(v, t types.Type) *types.Func { + // ensure that v and t are interfaces + V, _ := v.Underlying().(*types.Interface) + T, _ := t.Underlying().(*types.Interface) + if V == nil || T == nil { + return nil + } + if f, wrongType := types.MissingMethod(V, T, false); wrongType { + return f + } + return nil +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + nodeFilter := []ast.Node{ + (*ast.TypeAssertExpr)(nil), + (*ast.TypeSwitchStmt)(nil), + } + inspect.Preorder(nodeFilter, func(n ast.Node) { + var ( + assert *ast.TypeAssertExpr // v.(T) expression + targets []ast.Expr // interfaces T in v.(T) + ) + switch n := n.(type) { + case *ast.TypeAssertExpr: + // take care of v.(type) in *ast.TypeSwitchStmt + if n.Type == nil { + return + } + assert = n + targets = append(targets, n.Type) + case *ast.TypeSwitchStmt: + // retrieve type assertion from type switch's 'assign' field + switch t := n.Assign.(type) { + case *ast.ExprStmt: + assert = t.X.(*ast.TypeAssertExpr) + case *ast.AssignStmt: + assert = t.Rhs[0].(*ast.TypeAssertExpr) + } + // gather target types from case clauses + for _, c := range n.Body.List { + targets = append(targets, c.(*ast.CaseClause).List...) + } + } + V := pass.TypesInfo.TypeOf(assert.X) + for _, target := range targets { + T := pass.TypesInfo.TypeOf(target) + if f := assertableTo(V, T); f != nil { + pass.Reportf( + target.Pos(), + "impossible type assertion: no type can implement both %v and %v (conflicting types for %v method)", + V, T, f.Name(), + ) + } + } + }) + return nil, nil +} diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go new file mode 100644 index 00000000000..ac2cd84ad37 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -0,0 +1,126 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package stringintconv defines an Analyzer that flags type conversions +// from integers to strings. +package stringintconv + +import ( + "fmt" + "go/ast" + "go/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const Doc = `check for string(int) conversions + +This checker flags conversions of the form string(x) where x is an integer +(but not byte or rune) type. Such conversions are discouraged because they +return the UTF-8 representation of the Unicode code point x, and not a decimal +string representation of x as one might expect. Furthermore, if x denotes an +invalid code point, the conversion cannot be statically rejected. + +For conversions that intend on using the code point, consider replacing them +with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the +string representation of the value in the desired base. +` + +var Analyzer = &analysis.Analyzer{ + Name: "stringintconv", + Doc: Doc, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: run, +} + +func typeName(typ types.Type) string { + if v, _ := typ.(interface{ Name() string }); v != nil { + return v.Name() + } + if v, _ := typ.(interface{ Obj() *types.TypeName }); v != nil { + return v.Obj().Name() + } + return "" +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + nodeFilter := []ast.Node{ + (*ast.CallExpr)(nil), + } + inspect.Preorder(nodeFilter, func(n ast.Node) { + call := n.(*ast.CallExpr) + + // Retrieve target type name. + var tname *types.TypeName + switch fun := call.Fun.(type) { + case *ast.Ident: + tname, _ = pass.TypesInfo.Uses[fun].(*types.TypeName) + case *ast.SelectorExpr: + tname, _ = pass.TypesInfo.Uses[fun.Sel].(*types.TypeName) + } + if tname == nil { + return + } + target := tname.Name() + + // Check that target type T in T(v) has an underlying type of string. + T, _ := tname.Type().Underlying().(*types.Basic) + if T == nil || T.Kind() != types.String { + return + } + if s := T.Name(); target != s { + target += " (" + s + ")" + } + + // Check that type V of v has an underlying integral type that is not byte or rune. + if len(call.Args) != 1 { + return + } + v := call.Args[0] + vtyp := pass.TypesInfo.TypeOf(v) + V, _ := vtyp.Underlying().(*types.Basic) + if V == nil || V.Info()&types.IsInteger == 0 { + return + } + switch V.Kind() { + case types.Byte, types.Rune, types.UntypedRune: + return + } + + // Retrieve source type name. + source := typeName(vtyp) + if source == "" { + return + } + if s := V.Name(); source != s { + source += " (" + s + ")" + } + diag := analysis.Diagnostic{ + Pos: n.Pos(), + Message: fmt.Sprintf("conversion from %s to %s yields a string of one rune", source, target), + SuggestedFixes: []analysis.SuggestedFix{ + { + Message: "Did you mean to convert a rune to a string?", + TextEdits: []analysis.TextEdit{ + { + Pos: v.Pos(), + End: v.Pos(), + NewText: []byte("rune("), + }, + { + Pos: v.End(), + End: v.End(), + NewText: []byte(")"), + }, + }, + }, + }, + } + pass.Report(diag) + }) + return nil, nil +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index a7e481801fe..9f4c9985c6c 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12 +# github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3 ## explicit github.com/google/pprof/driver github.com/google/pprof/internal/binutils @@ -43,7 +43,7 @@ golang.org/x/mod/zip ## explicit golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/tools v0.0.0-20200219195521-7c4b6277d74d +# golang.org/x/tools v0.0.0-20200309180859-aa4048aca1ca ## explicit golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/internal/analysisflags @@ -59,6 +59,7 @@ golang.org/x/tools/go/analysis/passes/copylock golang.org/x/tools/go/analysis/passes/ctrlflow golang.org/x/tools/go/analysis/passes/errorsas golang.org/x/tools/go/analysis/passes/httpresponse +golang.org/x/tools/go/analysis/passes/ifaceassert golang.org/x/tools/go/analysis/passes/inspect golang.org/x/tools/go/analysis/passes/internal/analysisutil golang.org/x/tools/go/analysis/passes/loopclosure @@ -67,6 +68,7 @@ golang.org/x/tools/go/analysis/passes/nilfunc golang.org/x/tools/go/analysis/passes/printf golang.org/x/tools/go/analysis/passes/shift golang.org/x/tools/go/analysis/passes/stdmethods +golang.org/x/tools/go/analysis/passes/stringintconv golang.org/x/tools/go/analysis/passes/structtag golang.org/x/tools/go/analysis/passes/tests golang.org/x/tools/go/analysis/passes/unmarshal @@ -80,6 +82,5 @@ golang.org/x/tools/go/cfg golang.org/x/tools/go/types/objectpath golang.org/x/tools/go/types/typeutil # golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 -## explicit golang.org/x/xerrors golang.org/x/xerrors/internal diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go index 2a4f929d609..6381de840c0 100644 --- a/src/cmd/vet/main.go +++ b/src/cmd/vet/main.go @@ -15,12 +15,14 @@ import ( "golang.org/x/tools/go/analysis/passes/copylock" "golang.org/x/tools/go/analysis/passes/errorsas" "golang.org/x/tools/go/analysis/passes/httpresponse" + "golang.org/x/tools/go/analysis/passes/ifaceassert" "golang.org/x/tools/go/analysis/passes/loopclosure" "golang.org/x/tools/go/analysis/passes/lostcancel" "golang.org/x/tools/go/analysis/passes/nilfunc" "golang.org/x/tools/go/analysis/passes/printf" "golang.org/x/tools/go/analysis/passes/shift" "golang.org/x/tools/go/analysis/passes/stdmethods" + "golang.org/x/tools/go/analysis/passes/stringintconv" "golang.org/x/tools/go/analysis/passes/structtag" "golang.org/x/tools/go/analysis/passes/tests" "golang.org/x/tools/go/analysis/passes/unmarshal" @@ -43,12 +45,14 @@ func main() { copylock.Analyzer, errorsas.Analyzer, httpresponse.Analyzer, + ifaceassert.Analyzer, loopclosure.Analyzer, lostcancel.Analyzer, nilfunc.Analyzer, printf.Analyzer, shift.Analyzer, stdmethods.Analyzer, + stringintconv.Analyzer, structtag.Analyzer, tests.Analyzer, unmarshal.Analyzer, diff --git a/src/crypto/tls/auth.go b/src/crypto/tls/auth.go index d87f7bdd512..ad5f9a2e439 100644 --- a/src/crypto/tls/auth.go +++ b/src/crypto/tls/auth.go @@ -106,7 +106,7 @@ func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType case Ed25519: sigType = signatureEd25519 default: - return 0, 0, fmt.Errorf("unsupported signature algorithm: %#04x", signatureAlgorithm) + return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) } switch signatureAlgorithm { case PKCS1WithSHA1, ECDSAWithSHA1: @@ -120,7 +120,7 @@ func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType case Ed25519: hash = directSigning default: - return 0, 0, fmt.Errorf("unsupported signature algorithm: %#04x", signatureAlgorithm) + return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) } return sigType, hash, nil } diff --git a/src/crypto/tls/auth_test.go b/src/crypto/tls/auth_test.go index c8d8c8fe4e0..c42e3491e46 100644 --- a/src/crypto/tls/auth_test.go +++ b/src/crypto/tls/auth_test.go @@ -62,7 +62,7 @@ func TestSignatureSelection(t *testing.T) { t.Errorf("test[%d]: unexpected selectSignatureScheme error: %v", testNo, err) } if test.expectedSigAlg != sigAlg { - t.Errorf("test[%d]: expected signature scheme %#x, got %#x", testNo, test.expectedSigAlg, sigAlg) + t.Errorf("test[%d]: expected signature scheme %v, got %v", testNo, test.expectedSigAlg, sigAlg) } sigType, hashFunc, err := typeAndHashFromSignatureScheme(sigAlg) if err != nil { @@ -115,7 +115,7 @@ func TestSignatureSelection(t *testing.T) { for testNo, test := range badTests { sigAlg, err := selectSignatureScheme(test.tlsVersion, test.cert, test.peerSigAlgs) if err == nil { - t.Errorf("test[%d]: unexpected success, got %#x", testNo, sigAlg) + t.Errorf("test[%d]: unexpected success, got %v", testNo, sigAlg) } } } @@ -129,7 +129,7 @@ func TestLegacyTypeAndHash(t *testing.T) { t.Errorf("RSA: expected signature type %#x, got %#x", expectedSigType, sigType) } if expectedHashFunc := crypto.MD5SHA1; expectedHashFunc != hashFunc { - t.Errorf("RSA: expected hash %#x, got %#x", expectedHashFunc, sigType) + t.Errorf("RSA: expected hash %#x, got %#x", expectedHashFunc, hashFunc) } sigType, hashFunc, err = legacyTypeAndHashFromPublicKey(testECDSAPrivateKey.Public()) @@ -140,7 +140,7 @@ func TestLegacyTypeAndHash(t *testing.T) { t.Errorf("ECDSA: expected signature type %#x, got %#x", expectedSigType, sigType) } if expectedHashFunc := crypto.SHA1; expectedHashFunc != hashFunc { - t.Errorf("ECDSA: expected hash %#x, got %#x", expectedHashFunc, sigType) + t.Errorf("ECDSA: expected hash %#x, got %#x", expectedHashFunc, hashFunc) } // Ed25519 is not supported by TLS 1.0 and 1.1. @@ -156,13 +156,13 @@ func TestSupportedSignatureAlgorithms(t *testing.T) { for _, sigAlg := range supportedSignatureAlgorithms { sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg) if err != nil { - t.Errorf("%#04x: unexpected error: %v", sigAlg, err) + t.Errorf("%v: unexpected error: %v", sigAlg, err) } if sigType == 0 { - t.Errorf("%#04x: missing signature type", sigAlg) + t.Errorf("%v: missing signature type", sigAlg) } if hash == 0 && sigAlg != Ed25519 { - t.Errorf("%#04x: missing hash", sigAlg) + t.Errorf("%v: missing hash", sigAlg) } } } diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 53719c48df5..ef95e9bf9cd 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -299,6 +299,8 @@ type ClientSessionCache interface { Put(sessionKey string, cs *ClientSessionState) } +//go:generate stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go + // SignatureScheme identifies a signature algorithm supported by TLS. See // RFC 8446, Section 4.2.3. type SignatureScheme uint16 diff --git a/src/crypto/tls/common_string.go b/src/crypto/tls/common_string.go new file mode 100644 index 00000000000..238108811f2 --- /dev/null +++ b/src/crypto/tls/common_string.go @@ -0,0 +1,116 @@ +// Code generated by "stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go"; DO NOT EDIT. + +package tls + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[PKCS1WithSHA256-1025] + _ = x[PKCS1WithSHA384-1281] + _ = x[PKCS1WithSHA512-1537] + _ = x[PSSWithSHA256-2052] + _ = x[PSSWithSHA384-2053] + _ = x[PSSWithSHA512-2054] + _ = x[ECDSAWithP256AndSHA256-1027] + _ = x[ECDSAWithP384AndSHA384-1283] + _ = x[ECDSAWithP521AndSHA512-1539] + _ = x[Ed25519-2055] + _ = x[PKCS1WithSHA1-513] + _ = x[ECDSAWithSHA1-515] +} + +const ( + _SignatureScheme_name_0 = "PKCS1WithSHA1" + _SignatureScheme_name_1 = "ECDSAWithSHA1" + _SignatureScheme_name_2 = "PKCS1WithSHA256" + _SignatureScheme_name_3 = "ECDSAWithP256AndSHA256" + _SignatureScheme_name_4 = "PKCS1WithSHA384" + _SignatureScheme_name_5 = "ECDSAWithP384AndSHA384" + _SignatureScheme_name_6 = "PKCS1WithSHA512" + _SignatureScheme_name_7 = "ECDSAWithP521AndSHA512" + _SignatureScheme_name_8 = "PSSWithSHA256PSSWithSHA384PSSWithSHA512Ed25519" +) + +var ( + _SignatureScheme_index_8 = [...]uint8{0, 13, 26, 39, 46} +) + +func (i SignatureScheme) String() string { + switch { + case i == 513: + return _SignatureScheme_name_0 + case i == 515: + return _SignatureScheme_name_1 + case i == 1025: + return _SignatureScheme_name_2 + case i == 1027: + return _SignatureScheme_name_3 + case i == 1281: + return _SignatureScheme_name_4 + case i == 1283: + return _SignatureScheme_name_5 + case i == 1537: + return _SignatureScheme_name_6 + case i == 1539: + return _SignatureScheme_name_7 + case 2052 <= i && i <= 2055: + i -= 2052 + return _SignatureScheme_name_8[_SignatureScheme_index_8[i]:_SignatureScheme_index_8[i+1]] + default: + return "SignatureScheme(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[CurveP256-23] + _ = x[CurveP384-24] + _ = x[CurveP521-25] + _ = x[X25519-29] +} + +const ( + _CurveID_name_0 = "CurveP256CurveP384CurveP521" + _CurveID_name_1 = "X25519" +) + +var ( + _CurveID_index_0 = [...]uint8{0, 9, 18, 27} +) + +func (i CurveID) String() string { + switch { + case 23 <= i && i <= 25: + i -= 23 + return _CurveID_name_0[_CurveID_index_0[i]:_CurveID_index_0[i+1]] + case i == 29: + return _CurveID_name_1 + default: + return "CurveID(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NoClientCert-0] + _ = x[RequestClientCert-1] + _ = x[RequireAnyClientCert-2] + _ = x[VerifyClientCertIfGiven-3] + _ = x[RequireAndVerifyClientCert-4] +} + +const _ClientAuthType_name = "NoClientCertRequestClientCertRequireAnyClientCertVerifyClientCertIfGivenRequireAndVerifyClientCert" + +var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98} + +func (i ClientAuthType) String() string { + if i < 0 || i >= ClientAuthType(len(_ClientAuthType_index)-1) { + return "ClientAuthType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ClientAuthType_name[_ClientAuthType_index[i]:_ClientAuthType_index[i+1]] +} diff --git a/src/debug/pe/file_test.go b/src/debug/pe/file_test.go index bc41be26691..26a65941e14 100644 --- a/src/debug/pe/file_test.go +++ b/src/debug/pe/file_test.go @@ -621,16 +621,14 @@ func TestBuildingWindowsGUI(t *testing.T) { } defer f.Close() - const _IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 - switch oh := f.OptionalHeader.(type) { case *OptionalHeader32: - if oh.Subsystem != _IMAGE_SUBSYSTEM_WINDOWS_GUI { - t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, _IMAGE_SUBSYSTEM_WINDOWS_GUI) + if oh.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI { + t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, IMAGE_SUBSYSTEM_WINDOWS_GUI) } case *OptionalHeader64: - if oh.Subsystem != _IMAGE_SUBSYSTEM_WINDOWS_GUI { - t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, _IMAGE_SUBSYSTEM_WINDOWS_GUI) + if oh.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI { + t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, IMAGE_SUBSYSTEM_WINDOWS_GUI) } default: t.Fatalf("unexpected OptionalHeader type: have %T, but want *pe.OptionalHeader32 or *pe.OptionalHeader64", oh) diff --git a/src/debug/pe/pe.go b/src/debug/pe/pe.go index 3f8099dfab1..db112fe7ad6 100644 --- a/src/debug/pe/pe.go +++ b/src/debug/pe/pe.go @@ -129,3 +129,56 @@ const ( IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 ) + +// Values of IMAGE_FILE_HEADER.Characteristics. These can be combined together. +const ( + IMAGE_FILE_RELOCS_STRIPPED = 0x0001 + IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 + IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 + IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 + IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 + IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 + IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 + IMAGE_FILE_32BIT_MACHINE = 0x0100 + IMAGE_FILE_DEBUG_STRIPPED = 0x0200 + IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 + IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 + IMAGE_FILE_SYSTEM = 0x1000 + IMAGE_FILE_DLL = 0x2000 + IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 + IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 +) + +// OptionalHeader64.Subsystem and OptionalHeader32.Subsystem values. +const ( + IMAGE_SUBSYSTEM_UNKNOWN = 0 + IMAGE_SUBSYSTEM_NATIVE = 1 + IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 + IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 + IMAGE_SUBSYSTEM_OS2_CUI = 5 + IMAGE_SUBSYSTEM_POSIX_CUI = 7 + IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8 + IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9 + IMAGE_SUBSYSTEM_EFI_APPLICATION = 10 + IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11 + IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12 + IMAGE_SUBSYSTEM_EFI_ROM = 13 + IMAGE_SUBSYSTEM_XBOX = 14 + IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 +) + +// OptionalHeader64.DllCharacteristics and OptionalHeader32.DllCharacteristics +// values. These can be combined together. +const ( + IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 + IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 + IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080 + IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100 + IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200 + IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 + IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800 + IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000 + IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000 + IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000 + IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 +) diff --git a/src/errors/wrap.go b/src/errors/wrap.go index 272d056b318..b82ca34b46f 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -70,7 +70,7 @@ func Is(err, target error) bool { // setting target. // // An error type might provide an As method so it can be treated as if it were a -// a different error type. +// different error type. // // As panics if target is not a non-nil pointer to either a type that implements // error, or to any interface type. diff --git a/src/go.mod b/src/go.mod index c1741d25051..ab791642788 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.14 require ( golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 - golang.org/x/net v0.0.0-20200219183655-46282727080f + golang.org/x/net v0.0.0-20200301022130-244492dfa37a golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect golang.org/x/text v0.3.3-0.20191031172631-4b67af870c6f // indirect ) diff --git a/src/go.sum b/src/go.sum index 75a94ac89b9..3f8e5d40b9f 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg= golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200219183655-46282727080f h1:dB42wwhNuwPvh8f+5zZWNcU+F2Xs/B9wXXwvUCOH7r8= -golang.org/x/net v0.0.0-20200219183655-46282727080f/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c h1:jceGD5YNJGgGMkJz79agzOln1K9TaZUjv5ird16qniQ= diff --git a/src/internal/bytealg/bytealg.go b/src/internal/bytealg/bytealg.go index 4c90cd3671e..6fd93083694 100644 --- a/src/internal/bytealg/bytealg.go +++ b/src/internal/bytealg/bytealg.go @@ -20,6 +20,7 @@ const ( ) // MaxLen is the maximum length of the string to be searched for (argument b) in Index. +// If MaxLen is not 0, make sure MaxLen >= 4. var MaxLen int // FIXME: the logic of HashStrBytes, HashStrRevBytes, IndexRabinKarpBytes and HashStr, HashStrRev, diff --git a/src/internal/bytealg/index_generic.go b/src/internal/bytealg/index_generic.go index 98e859f9255..83345f10134 100644 --- a/src/internal/bytealg/index_generic.go +++ b/src/internal/bytealg/index_generic.go @@ -16,8 +16,42 @@ func Index(a, b []byte) int { // IndexString returns the index of the first instance of b in a, or -1 if b is not present in a. // Requires 2 <= len(b) <= MaxLen. -func IndexString(a, b string) int { - panic("unimplemented") +func IndexString(s, substr string) int { + // This is a partial copy of strings.Index, here because bytes.IndexAny and bytes.LastIndexAny + // call bytealg.IndexString. Some platforms have an optimized assembly version of this function. + // This implementation is used for those that do not. Although the pure Go implementation here + // works for the case of len(b) > MaxLen, we do not require that its assembly implementation also + // supports the case of len(b) > MaxLen. And we do not guarantee that this function supports the + // case of len(b) > MaxLen. + n := len(substr) + c0 := substr[0] + c1 := substr[1] + i := 0 + t := len(s) - n + 1 + fails := 0 + for i < t { + if s[i] != c0 { + o := IndexByteString(s[i:t], c0) + if o < 0 { + return -1 + } + i += o + } + if s[i+1] == c1 && s[i:i+n] == substr { + return i + } + i++ + fails++ + if fails >= 4+i>>4 && i < t { + // See comment in src/bytes/bytes.go. + j := IndexRabinKarp(s[i:], substr) + if j < 0 { + return -1 + } + return i + j + } + } + return -1 } // Cutover reports the number of failures of IndexByte we should tolerate diff --git a/src/internal/xcoff/file.go b/src/internal/xcoff/file.go index 66b5391d583..05e4fd555cc 100644 --- a/src/internal/xcoff/file.go +++ b/src/internal/xcoff/file.go @@ -412,10 +412,10 @@ func NewFile(r io.ReaderAt) (*File, error) { sect.Relocs[i].Type = rel.Rtype sect.Relocs[i].Length = rel.Rsize&0x3F + 1 - if rel.Rsize&0x80 == 1 { + if rel.Rsize&0x80 != 0 { sect.Relocs[i].Signed = true } - if rel.Rsize&0x40 == 1 { + if rel.Rsize&0x40 != 0 { sect.Relocs[i].InstructionFixed = true } @@ -428,10 +428,10 @@ func NewFile(r io.ReaderAt) (*File, error) { sect.Relocs[i].Symbol = idxToSym[int(rel.Rsymndx)] sect.Relocs[i].Type = rel.Rtype sect.Relocs[i].Length = rel.Rsize&0x3F + 1 - if rel.Rsize&0x80 == 1 { + if rel.Rsize&0x80 != 0 { sect.Relocs[i].Signed = true } - if rel.Rsize&0x40 == 1 { + if rel.Rsize&0x40 != 0 { sect.Relocs[i].InstructionFixed = true } } diff --git a/src/io/io.go b/src/io/io.go index 9cc3086c19b..3dea70b947b 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -236,6 +236,10 @@ type WriterAt interface { // ReadByte reads and returns the next byte from the input or // any error encountered. If ReadByte returns an error, no input // byte was consumed, and the returned byte value is undefined. +// +// ReadByte provides an efficient interface for byte-at-time +// processing. A Reader that does not implement ByteReader +// can be wrapped using bufio.NewReader to add this method. type ByteReader interface { ReadByte() (byte, error) } diff --git a/src/mime/type.go b/src/mime/type.go index 260c535af05..6d2b89e4059 100644 --- a/src/mime/type.go +++ b/src/mime/type.go @@ -65,6 +65,7 @@ var builtinTypesLower = map[string]string{ ".jpeg": "image/jpeg", ".jpg": "image/jpeg", ".js": "text/javascript; charset=utf-8", + ".json": "application/json", ".mjs": "text/javascript; charset=utf-8", ".pdf": "application/pdf", ".png": "image/png", diff --git a/src/net/dial_test.go b/src/net/dial_test.go index 493cdfc6481..78feaae7f46 100644 --- a/src/net/dial_test.go +++ b/src/net/dial_test.go @@ -441,6 +441,14 @@ func TestDialParallelSpuriousConnection(t *testing.T) { t.Skip("both IPv4 and IPv6 are required") } + var readDeadline time.Time + if td, ok := t.Deadline(); ok { + const arbitraryCleanupMargin = 1 * time.Second + readDeadline = td.Add(-arbitraryCleanupMargin) + } else { + readDeadline = time.Now().Add(5 * time.Second) + } + var wg sync.WaitGroup wg.Add(2) handler := func(dss *dualStackServer, ln Listener) { @@ -450,7 +458,7 @@ func TestDialParallelSpuriousConnection(t *testing.T) { t.Fatal(err) } // The client should close itself, without sending data. - c.SetReadDeadline(time.Now().Add(1 * time.Second)) + c.SetReadDeadline(readDeadline) var b [1]byte if _, err := c.Read(b[:]); err != io.EOF { t.Errorf("got %v; want %v", err, io.EOF) diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go index cb140f8f2f6..9474175f179 100644 --- a/src/net/http/cgi/child.go +++ b/src/net/http/cgi/child.go @@ -89,8 +89,6 @@ func RequestFromMap(params map[string]string) (*http.Request, error) { r.Header.Add(strings.ReplaceAll(k[5:], "_", "-"), v) } - // TODO: cookies. parsing them isn't exported, though. - uriStr := params["REQUEST_URI"] if uriStr == "" { // Fallback to SCRIPT_NAME, PATH_INFO and QUERY_STRING. diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index aa6d87251d0..21ee7f33c8b 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -4135,10 +4135,19 @@ func TestServerConnState(t *testing.T) { doRequests() - timer := time.NewTimer(5 * time.Second) + stateDelay := 5 * time.Second + if deadline, ok := t.Deadline(); ok { + // Allow an arbitrarily long delay. + // This test was observed to be flaky on the darwin-arm64-corellium builder, + // so we're increasing the deadline to see if it starts passing. + // See https://golang.org/issue/37322. + const arbitraryCleanupMargin = 1 * time.Second + stateDelay = time.Until(deadline) - arbitraryCleanupMargin + } + timer := time.NewTimer(stateDelay) select { case <-timer.C: - t.Errorf("Timed out waiting for connection to change state.") + t.Errorf("Timed out after %v waiting for connection to change state.", stateDelay) case <-complete: timer.Stop() } diff --git a/src/runtime/alg.go b/src/runtime/alg.go index 5a0656513d0..0af48ab25cc 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -158,6 +158,8 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr { // is slower but more general and is used for hashing interface types // (called from interhash or nilinterhash, above) or for hashing in // maps generated by reflect.MapOf (reflect_typehash, below). +// Note: this function must match the compiler generated +// functions exactly. See issue 37716. func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { if t.tflag&tflagRegularMemory != 0 { // Handle ptr sizes specially, see issue 37086. @@ -195,12 +197,28 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { return h case kindStruct: s := (*structtype)(unsafe.Pointer(t)) + memStart := uintptr(0) + memEnd := uintptr(0) for _, f := range s.fields { - // TODO: maybe we could hash several contiguous fields all at once. + if memEnd > memStart && (f.name.isBlank() || f.offset() != memEnd || f.typ.tflag&tflagRegularMemory == 0) { + // flush any pending regular memory hashing + h = memhash(add(p, memStart), h, memEnd-memStart) + memStart = memEnd + } if f.name.isBlank() { continue } - h = typehash(f.typ, add(p, f.offset()), h) + if f.typ.tflag&tflagRegularMemory == 0 { + h = typehash(f.typ, add(p, f.offset()), h) + continue + } + if memStart == memEnd { + memStart = f.offset() + } + memEnd = f.offset() + f.typ.size + } + if memEnd > memStart { + h = memhash(add(p, memStart), h, memEnd-memStart) } return h default: diff --git a/src/runtime/checkptr.go b/src/runtime/checkptr.go index ddbc8168afc..8e401e87635 100644 --- a/src/runtime/checkptr.go +++ b/src/runtime/checkptr.go @@ -10,18 +10,18 @@ func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) { // Check that (*[n]elem)(p) is appropriately aligned. // TODO(mdempsky): What about fieldAlign? if uintptr(p)&(uintptr(elem.align)-1) != 0 { - throw("checkptr: unsafe pointer conversion") + throw("checkptr: misaligned pointer conversion") } // Check that (*[n]elem)(p) doesn't straddle multiple heap objects. if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) { - throw("checkptr: unsafe pointer conversion") + throw("checkptr: converted pointer straddles multiple allocations") } } func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) { if 0 < uintptr(p) && uintptr(p) < minLegalPointer { - throw("checkptr: unsafe pointer arithmetic") + throw("checkptr: pointer arithmetic computed bad pointer value") } // Check that if the computed pointer p points into a heap @@ -38,7 +38,7 @@ func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) { } } - throw("checkptr: unsafe pointer arithmetic") + throw("checkptr: pointer arithmetic result points to invalid allocation") } // checkptrBase returns the base address for the allocation containing diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go index c5f22cc1015..1a7c253733d 100644 --- a/src/runtime/checkptr_test.go +++ b/src/runtime/checkptr_test.go @@ -24,10 +24,10 @@ func TestCheckPtr(t *testing.T) { cmd string want string }{ - {"CheckPtrAlignment", "fatal error: checkptr: unsafe pointer conversion\n"}, - {"CheckPtrArithmetic", "fatal error: checkptr: unsafe pointer arithmetic\n"}, - {"CheckPtrSize", "fatal error: checkptr: unsafe pointer conversion\n"}, - {"CheckPtrSmall", "fatal error: checkptr: unsafe pointer arithmetic\n"}, + {"CheckPtrAlignment", "fatal error: checkptr: misaligned pointer conversion\n"}, + {"CheckPtrArithmetic", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"}, + {"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"}, + {"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"}, } for _, tc := range testCases { diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 1420b3206ac..8ef52aba48f 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -15,6 +15,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "sync" "syscall" "testing" @@ -288,6 +289,12 @@ func TestSignalExitStatus(t *testing.T) { } func TestSignalIgnoreSIGTRAP(t *testing.T) { + if runtime.GOOS == "openbsd" { + if bn := testenv.Builder(); strings.HasSuffix(bn, "-62") || strings.HasSuffix(bn, "-64") { + testenv.SkipFlaky(t, 17496) + } + } + output := runTestProg(t, "testprognet", "SignalIgnoreSIGTRAP") want := "OK\n" if output != want { diff --git a/src/runtime/defer_test.go b/src/runtime/defer_test.go index 3d8f81277f3..f35535e773d 100644 --- a/src/runtime/defer_test.go +++ b/src/runtime/defer_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "fmt" + "os" "reflect" "runtime" "testing" @@ -281,3 +282,56 @@ func TestDeferForFuncWithNoExit(t *testing.T) { for { } } + +// Test case approximating issue #37664, where a recursive function (interpreter) +// may do repeated recovers/re-panics until it reaches the frame where the panic +// can actually be handled. The recurseFnPanicRec() function is testing that there +// are no stale defer structs on the defer chain after the interpreter() sequence, +// by writing a bunch of 0xffffffffs into several recursive stack frames, and then +// doing a single panic-recover which would invoke any such stale defer structs. +func TestDeferWithRepeatedRepanics(t *testing.T) { + interpreter(0, 6, 2) + recurseFnPanicRec(0, 10) + interpreter(0, 5, 1) + recurseFnPanicRec(0, 10) + interpreter(0, 6, 3) + recurseFnPanicRec(0, 10) +} + +func interpreter(level int, maxlevel int, rec int) { + defer func() { + e := recover() + if e == nil { + return + } + if level != e.(int) { + //fmt.Fprintln(os.Stderr, "re-panicing, level", level) + panic(e) + } + //fmt.Fprintln(os.Stderr, "Recovered, level", level) + }() + if level+1 < maxlevel { + interpreter(level+1, maxlevel, rec) + } else { + //fmt.Fprintln(os.Stderr, "Initiating panic") + panic(rec) + } +} + +func recurseFnPanicRec(level int, maxlevel int) { + defer func() { + recover() + }() + recurseFn(level, maxlevel) +} + +func recurseFn(level int, maxlevel int) { + a := [40]uint32{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff} + if level+1 < maxlevel { + // Need this print statement to keep a around. '_ = a[4]' doesn't do it. + fmt.Fprintln(os.Stderr, "recurseFn", level, a[4]) + recurseFn(level+1, maxlevel) + } else { + panic("recurseFn panic") + } +} diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 88cb1acc5b7..6a8d00c60dd 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -950,3 +950,28 @@ func SemNwait(addr *uint32) uint32 { root := semroot(addr) return atomic.Load(&root.nwait) } + +// MapHashCheck computes the hash of the key k for the map m, twice. +// Method 1 uses the built-in hasher for the map. +// Method 2 uses the typehash function (the one used by reflect). +// Returns the two hash values, which should always be equal. +func MapHashCheck(m interface{}, k interface{}) (uintptr, uintptr) { + // Unpack m. + mt := (*maptype)(unsafe.Pointer(efaceOf(&m)._type)) + mh := (*hmap)(efaceOf(&m).data) + + // Unpack k. + kt := efaceOf(&k)._type + var p unsafe.Pointer + if isDirectIface(kt) { + q := efaceOf(&k).data + p = unsafe.Pointer(&q) + } else { + p = efaceOf(&k).data + } + + // Compute the hash functions. + x := mt.hasher(noescape(p), uintptr(mh.hash0)) + y := typehash(kt, noescape(p), uintptr(mh.hash0)) + return x, y +} diff --git a/src/runtime/hash_test.go b/src/runtime/hash_test.go index fe25a7f84be..655ca18f115 100644 --- a/src/runtime/hash_test.go +++ b/src/runtime/hash_test.go @@ -8,6 +8,7 @@ import ( "fmt" "math" "math/rand" + "reflect" . "runtime" "strings" "testing" @@ -48,6 +49,54 @@ func TestMemHash64Equality(t *testing.T) { } } +func TestCompilerVsRuntimeHash(t *testing.T) { + // Test to make sure the compiler's hash function and the runtime's hash function agree. + // See issue 37716. + for _, m := range []interface{}{ + map[bool]int{}, + map[int8]int{}, + map[uint8]int{}, + map[int16]int{}, + map[uint16]int{}, + map[int32]int{}, + map[uint32]int{}, + map[int64]int{}, + map[uint64]int{}, + map[int]int{}, + map[uint]int{}, + map[uintptr]int{}, + map[*byte]int{}, + map[chan int]int{}, + map[unsafe.Pointer]int{}, + map[float32]int{}, + map[float64]int{}, + map[complex64]int{}, + map[complex128]int{}, + map[string]int{}, + //map[interface{}]int{}, + //map[interface{F()}]int{}, + map[[8]uint64]int{}, + map[[8]string]int{}, + map[struct{ a, b, c, d int32 }]int{}, // Note: tests AMEM128 + map[struct{ a, b, _, d int32 }]int{}, + map[struct { + a, b int32 + c float32 + d, e [8]byte + }]int{}, + map[struct { + a int16 + b int64 + }]int{}, + } { + k := reflect.New(reflect.TypeOf(m).Key()).Elem().Interface() // the zero key + x, y := MapHashCheck(m, k) + if x != y { + t.Errorf("hashes did not match (%x vs %x) for map %T", x, y, m) + } + } +} + // Smhasher is a torture test for hash functions. // https://code.google.com/p/smhasher/ // This code is a port of some of the Smhasher tests to Go. diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 4cb6c8a3604..c6ab1bac3fe 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -1003,11 +1003,12 @@ func gopanic(e interface{}) { atomic.Xadd(&runningPanicDefers, -1) if done { - // Remove any remaining non-started, open-coded defer - // entry after a recover (there's at most one, if we just - // ran a non-open-coded defer), since the entry will - // become out-dated and the defer will be executed - // normally. + // Remove any remaining non-started, open-coded + // defer entries after a recover, since the + // corresponding defers will be executed normally + // (inline). Any such entry will become stale once + // we run the corresponding defers inline and exit + // the associated stack frame. d := gp._defer var prev *_defer for d != nil { @@ -1025,8 +1026,9 @@ func gopanic(e interface{}) { } else { prev.link = d.link } + newd := d.link freedefer(d) - break + d = newd } else { prev = d d = d.link diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index a7916bf6fb9..bbdc432eec4 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -313,9 +313,11 @@ func (p *Profile) Remove(value interface{}) { // Otherwise, WriteTo returns nil. // // The debug parameter enables additional output. -// Passing debug=0 prints only the hexadecimal addresses that pprof needs. -// Passing debug=1 adds comments translating addresses to function names -// and line numbers, so that a programmer can read the profile without tools. +// Passing debug=0 writes the gzip-compressed protocol buffer described +// in https://github.com/google/pprof/tree/master/proto#overview. +// Passing debug=1 writes the legacy text format with comments +// translating addresses to function names and line numbers, so that a +// programmer can read the profile without tools. // // The predefined profiles may assign meaning to other debug values; // for example, when printing the "goroutine" profile, debug=2 means to diff --git a/src/runtime/time.go b/src/runtime/time.go index 155e0501fe6..c62207d7f7b 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -499,10 +499,20 @@ func resettimer(t *timer, when int64) { // slows down addtimer. Reports whether no timer problems were found. // The caller must have locked the timers for pp. func cleantimers(pp *p) { + gp := getg() for { if len(pp.timers) == 0 { return } + + // This loop can theoretically run for a while, and because + // it is holding timersLock it cannot be preempted. + // If someone is trying to preempt us, just return. + // We can clean the timers later. + if gp.preemptStop { + return + } + t := pp.timers[0] if t.pp.ptr() != pp { throw("cleantimers: bad p") diff --git a/src/strings/strings.go b/src/strings/strings.go index 7fb05b7d0eb..2789f5fb25a 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -143,6 +143,14 @@ func IndexAny(s, chars string) int { // Avoid scanning all of s. return -1 } + if len(chars) == 1 { + // Avoid scanning all of s. + r := rune(chars[0]) + if r >= utf8.RuneSelf { + r = utf8.RuneError + } + return IndexRune(s, r) + } if len(s) > 8 { if as, isASCII := makeASCIISet(chars); isASCII { for i := 0; i < len(s); i++ { @@ -154,10 +162,8 @@ func IndexAny(s, chars string) int { } } for i, c := range s { - for _, m := range chars { - if c == m { - return i - } + if IndexRune(chars, c) >= 0 { + return i } } return -1 @@ -171,6 +177,16 @@ func LastIndexAny(s, chars string) int { // Avoid scanning all of s. return -1 } + if len(s) == 1 { + rc := rune(s[0]) + if rc >= utf8.RuneSelf { + rc = utf8.RuneError + } + if IndexRune(chars, rc) >= 0 { + return 0 + } + return -1 + } if len(s) > 8 { if as, isASCII := makeASCIISet(chars); isASCII { for i := len(s) - 1; i >= 0; i-- { @@ -181,13 +197,25 @@ func LastIndexAny(s, chars string) int { return -1 } } + if len(chars) == 1 { + rc := rune(chars[0]) + if rc >= utf8.RuneSelf { + rc = utf8.RuneError + } + for i := len(s); i > 0; { + r, size := utf8.DecodeLastRuneInString(s[:i]) + i -= size + if rc == r { + return i + } + } + return -1 + } for i := len(s); i > 0; { r, size := utf8.DecodeLastRuneInString(s[:i]) i -= size - for _, c := range chars { - if r == c { - return i - } + if IndexRune(chars, r) >= 0 { + return i } } return -1 diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index 984fecfa8d4..c01c4dabc53 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -153,6 +153,7 @@ var indexAnyTests = []IndexTest{ {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, + {"\x80", "\xffb", 0}, {"aaa", "a", 0}, {"abc", "xyz", -1}, {"abc", "xcz", 2}, @@ -163,6 +164,7 @@ var indexAnyTests = []IndexTest{ {dots + dots + dots, " ", -1}, {"012abcba210", "\xffb", 4}, {"012\x80bcb\x80210", "\xffb", 3}, + {"0123456\xcf\x80abc", "\xcfb\x80", 10}, } var lastIndexAnyTests = []IndexTest{ @@ -171,6 +173,7 @@ var lastIndexAnyTests = []IndexTest{ {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, + {"\x80", "\xffb", 0}, {"aaa", "a", 2}, {"abc", "xyz", -1}, {"abc", "ab", 1}, @@ -181,6 +184,7 @@ var lastIndexAnyTests = []IndexTest{ {dots + dots + dots, " ", -1}, {"012abcba210", "\xffb", 6}, {"012\x80bcb\x80210", "\xffb", 7}, + {"0123456\xcf\x80abc", "\xcfb\x80", 10}, } // Execute f on each test case. funcName should be the name of f; it's used @@ -1787,10 +1791,10 @@ func BenchmarkRepeat(b *testing.B) { } func BenchmarkIndexAnyASCII(b *testing.B) { - x := Repeat("#", 4096) // Never matches set - cs := "0123456789abcdef" - for k := 1; k <= 4096; k <<= 4 { - for j := 1; j <= 16; j <<= 1 { + x := Repeat("#", 2048) // Never matches set + cs := "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { for i := 0; i < b.N; i++ { IndexAny(x[:k], cs[:j]) @@ -1800,6 +1804,48 @@ func BenchmarkIndexAnyASCII(b *testing.B) { } } +func BenchmarkIndexAnyUTF8(b *testing.B) { + x := Repeat("#", 2048) // Never matches set + cs := "你好世界, hello world. 你好世界, hello world. 你好世界, hello world." + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { + b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { + for i := 0; i < b.N; i++ { + IndexAny(x[:k], cs[:j]) + } + }) + } + } +} + +func BenchmarkLastIndexAnyASCII(b *testing.B) { + x := Repeat("#", 2048) // Never matches set + cs := "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { + b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { + for i := 0; i < b.N; i++ { + LastIndexAny(x[:k], cs[:j]) + } + }) + } + } +} + +func BenchmarkLastIndexAnyUTF8(b *testing.B) { + x := Repeat("#", 2048) // Never matches set + cs := "你好世界, hello world. 你好世界, hello world. 你好世界, hello world." + for k := 1; k <= 2048; k <<= 4 { + for j := 1; j <= 64; j <<= 1 { + b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { + for i := 0; i < b.N; i++ { + LastIndexAny(x[:k], cs[:j]) + } + }) + } + } +} + func BenchmarkTrimASCII(b *testing.B) { cs := "0123456789abcdef" for k := 1; k <= 4096; k <<= 4 { diff --git a/src/time/internal_test.go b/src/time/internal_test.go index 3bca88e2b99..35ce69b2282 100644 --- a/src/time/internal_test.go +++ b/src/time/internal_test.go @@ -67,12 +67,13 @@ func CheckRuntimeTimerOverflow() { resetTimer(r, 0) }() - // If the test fails, we will hang here until the timeout in the testing package - // fires, which is 10 minutes. It would be nice to catch the problem sooner, - // but there is no reliable way to guarantee that timerproc schedules without - // doing something involving timerproc itself. Previous failed attempts have - // tried calling runtime.Gosched and runtime.GC, but neither is reliable. - // So we fall back to hope: We hope we don't hang here. + // If the test fails, we will hang here until the timeout in the + // testing package fires, which is 10 minutes. It would be nice to + // catch the problem sooner, but there is no reliable way to guarantee + // that timers are run without doing something involving the scheduler. + // Previous failed attempts have tried calling runtime.Gosched and + // runtime.GC, but neither is reliable. So we fall back to hope: + // We hope we don't hang here. <-t.C } diff --git a/src/vendor/golang.org/x/net/dns/dnsmessage/message.go b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go index 82bcdcc838c..da8bafd9218 100644 --- a/src/vendor/golang.org/x/net/dns/dnsmessage/message.go +++ b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go @@ -14,6 +14,7 @@ package dnsmessage import ( "errors" + "fmt" ) // Message formats @@ -1819,17 +1820,6 @@ func unpackText(msg []byte, off int) (string, int, error) { return string(msg[beginOff:endOff]), endOff, nil } -func skipText(msg []byte, off int) (int, error) { - if off >= len(msg) { - return off, errBaseLen - } - endOff := off + 1 + int(msg[off]) - if endOff > len(msg) { - return off, errCalcLen - } - return endOff, nil -} - // packBytes appends the wire format of field to msg. func packBytes(msg []byte, field []byte) []byte { return append(msg, field...) @@ -1844,14 +1834,6 @@ func unpackBytes(msg []byte, off int, field []byte) (int, error) { return newOff, nil } -func skipBytes(msg []byte, off int, field []byte) (int, error) { - newOff := off + len(field) - if newOff > len(msg) { - return off, errBaseLen - } - return newOff, nil -} - const nameLen = 255 // A Name is a non-encoded domain name. It is used instead of strings to avoid @@ -2159,7 +2141,7 @@ func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, return nil, off, &nestedError{name + " record", err} } if r == nil { - return nil, off, errors.New("invalid resource type: " + string(hdr.Type+'0')) + return nil, off, fmt.Errorf("invalid resource type: %d", hdr.Type) } return r, off + int(hdr.Length), nil } diff --git a/src/vendor/golang.org/x/net/route/address.go b/src/vendor/golang.org/x/net/route/address.go index b71528191f6..e3125a473bc 100644 --- a/src/vendor/golang.org/x/net/route/address.go +++ b/src/vendor/golang.org/x/net/route/address.go @@ -46,12 +46,12 @@ func (a *LinkAddr) marshal(b []byte) (int, error) { data := b[8:] if nlen > 0 { b[5] = byte(nlen) - copy(data[:nlen], a.Addr) + copy(data[:nlen], a.Name) data = data[nlen:] } if alen > 0 { b[6] = byte(alen) - copy(data[:alen], a.Name) + copy(data[:alen], a.Addr) data = data[alen:] } return ll, nil diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 1c56a340195..6feb23d65d1 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20200219183655-46282727080f +# golang.org/x/net v0.0.0-20200301022130-244492dfa37a ## explicit golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts diff --git a/test/codegen/README b/test/codegen/README index d6b8cf5b32f..b803fe585fa 100644 --- a/test/codegen/README +++ b/test/codegen/README @@ -16,8 +16,10 @@ step of the top-level test/run.go suite, called "asmcheck". The codegen harness is part of the all.bash test suite, but for performance reasons only the codegen tests for the host machine's -GOARCH are enabled by default. To perform comprehensive tests for all -the supported architectures, one can run the following command +GOARCH are enabled by default, and only on GOOS=linux. + +To perform comprehensive tests for all the supported architectures +(even on a non-Linux system), one can run the following command $ ../bin/go run run.go -all_codegen -v codegen diff --git a/test/codegen/memops.go b/test/codegen/memops.go index dcf58636665..0df191480d0 100644 --- a/test/codegen/memops.go +++ b/test/codegen/memops.go @@ -93,3 +93,153 @@ func compMem3(x, y *int) (int, bool) { // 386:`CMPL\t\(` return r, r < *y } + +// The following functions test that indexed load/store operations get generated. + +func idxInt8(x, y []int8, i int) { + var t int8 + // amd64: `MOVBL[SZ]X\t1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\), [A-Z]+[0-9]*` + // 386: `MOVBL[SZ]X\t1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\), [A-Z]+[0-9]*` + t = x[i+1] + // amd64: `MOVB\t[A-Z]+[0-9]*, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)` + // 386: `MOVB\t[A-Z]+[0-9]*, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)` + y[i+1] = t + // amd64: `MOVB\t[$]77, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)` + // 386: `MOVB\t[$]77, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)` + x[i+1] = 77 +} + +func idxInt16(x, y []int16, i int) { + var t int16 + // amd64: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\), [A-Z]+[0-9]*` + // 386: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\), [A-Z]+[0-9]*` + t = x[i+1] + // amd64: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)` + // 386: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)` + y[i+1] = t + // amd64: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\), [A-Z]+[0-9]*` + // 386: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\), [A-Z]+[0-9]*` + t = x[16*i+1] + // amd64: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)` + // 386: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)` + y[16*i+1] = t + // amd64: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)` + // 386: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)` + x[i+1] = 77 + // amd64: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)` + // 386: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)` + x[16*i+1] = 77 +} + +func idxInt32(x, y []int32, i int) { + var t int32 + // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*` + // 386: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*` + t = x[i+1] + // amd64: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)` + // 386: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)` + y[i+1] = t + // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*` + t = x[2*i+1] + // amd64: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)` + y[2*i+1] = t + // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), [A-Z]+[0-9]*` + // 386: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), [A-Z]+[0-9]*` + t = x[16*i+1] + // amd64: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)` + // 386: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)` + y[16*i+1] = t + // amd64: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)` + // 386: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)` + x[i+1] = 77 + // amd64: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)` + // 386: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)` + x[16*i+1] = 77 +} + +func idxInt64(x, y []int64, i int) { + var t int64 + // amd64: `MOVQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*` + t = x[i+1] + // amd64: `MOVQ\t[A-Z]+[0-9]*, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)` + y[i+1] = t + // amd64: `MOVQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), [A-Z]+[0-9]*` + t = x[16*i+1] + // amd64: `MOVQ\t[A-Z]+[0-9]*, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)` + y[16*i+1] = t + // amd64: `MOVQ\t[$]77, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)` + x[i+1] = 77 + // amd64: `MOVQ\t[$]77, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)` + x[16*i+1] = 77 +} + +func idxFloat32(x, y []float32, i int) { + var t float32 + // amd64: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+` + // 386/sse2: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+` + t = x[i+1] + // amd64: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)` + // 386/sse2: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)` + y[i+1] = t + // amd64: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), X[0-9]+` + // 386/sse2: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), X[0-9]+` + t = x[16*i+1] + // amd64: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)` + // 386/sse2: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)` + y[16*i+1] = t +} + +func idxFloat64(x, y []float64, i int) { + var t float64 + // amd64: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+` + // 386/sse2: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+` + t = x[i+1] + // amd64: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)` + // 386/sse2: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)` + y[i+1] = t + // amd64: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), X[0-9]+` + // 386/sse2: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), X[0-9]+` + t = x[16*i+1] + // amd64: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)` + // 386/sse2: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)` + y[16*i+1] = t +} + +func idxLoadPlusOp(x []int32, i int) int32 { + s := x[0] + // 386: `ADDL\t4\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+` + s += x[i+1] + // 386: `SUBL\t8\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+` + s -= x[i+2] + // 386: `IMULL\t12\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+` + s *= x[i+3] + // 386: `ANDL\t16\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+` + s &= x[i+4] + // 386: `ORL\t20\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+` + s |= x[i+5] + // 386: `XORL\t24\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+` + s ^= x[i+6] + return s +} + +func idxStorePlusOp(x []int32, i int, v int32) { + // 386: `ADDL\t[A-Z]+, 4\([A-Z]+\)\([A-Z]+\*4\)` + x[i+1] += v + // 386: `SUBL\t[A-Z]+, 8\([A-Z]+\)\([A-Z]+\*4\)` + x[i+2] -= v + // 386: `ANDL\t[A-Z]+, 12\([A-Z]+\)\([A-Z]+\*4\)` + x[i+3] &= v + // 386: `ORL\t[A-Z]+, 16\([A-Z]+\)\([A-Z]+\*4\)` + x[i+4] |= v + // 386: `XORL\t[A-Z]+, 20\([A-Z]+\)\([A-Z]+\*4\)` + x[i+5] ^= v + + // 386: `ADDL\t[$]77, 24\([A-Z]+\)\([A-Z]+\*4\)` + x[i+6] += 77 + // 386: `ANDL\t[$]77, 28\([A-Z]+\)\([A-Z]+\*4\)` + x[i+7] &= 77 + // 386: `ORL\t[$]77, 32\([A-Z]+\)\([A-Z]+\*4\)` + x[i+8] |= 77 + // 386: `XORL\t[$]77, 36\([A-Z]+\)\([A-Z]+\*4\)` + x[i+9] ^= 77 +} diff --git a/test/fixedbugs/issue15992.go b/test/fixedbugs/issue15992.go index 957bb89facd..cda5527c67e 100644 --- a/test/fixedbugs/issue15992.go +++ b/test/fixedbugs/issue15992.go @@ -28,7 +28,7 @@ func main() { fmt.Println(n, a) b := []byte{1, 2, 3} - n = copy(f(b)) + n = copy(g(b)) fmt.Println(n, b) m := map[int]int{0: 0} diff --git a/test/fixedbugs/issue37716.go b/test/fixedbugs/issue37716.go new file mode 100644 index 00000000000..42d66dff1bd --- /dev/null +++ b/test/fixedbugs/issue37716.go @@ -0,0 +1,32 @@ +// run + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "reflect" + +// complicated enough to require a compile-generated hash function +type K struct { + a, b int32 // these get merged by the compiler into a single field, something typehash doesn't do + c float64 +} + +func main() { + k := K{a: 1, b: 2, c: 3} + + // Make a reflect map. + m := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(K{}), reflect.TypeOf(true))) + m.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(true)) + + // The binary must not contain the type map[K]bool anywhere, or reflect.MapOf + // will use that type instead of making a new one. So use an equivalent named type. + type M map[K]bool + var x M + reflect.ValueOf(&x).Elem().Set(m) + if !x[k] { + panic("key not found") + } +} diff --git a/test/fixedbugs/issue37753.go b/test/fixedbugs/issue37753.go new file mode 100644 index 00000000000..ac311e37153 --- /dev/null +++ b/test/fixedbugs/issue37753.go @@ -0,0 +1,18 @@ +// run + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +//go:noinline +func f(a, b uint) int { + return int(a-b) / 8 +} + +func main() { + if x := f(1, 2); x != 0 { + panic(x) + } +} diff --git a/test/run.go b/test/run.go index 85dc51d1ddd..bd63d7142bc 100644 --- a/test/run.go +++ b/test/run.go @@ -459,7 +459,11 @@ func init() { checkShouldTest() } // or else the commands will rebuild any needed packages (like runtime) // over and over. func goGcflags() string { - return "-gcflags=" + os.Getenv("GO_GCFLAGS") + return "-gcflags=all=" + os.Getenv("GO_GCFLAGS") +} + +func goGcflagsIsEmpty() bool { + return "" == os.Getenv("GO_GCFLAGS") } // run runs a test. @@ -667,7 +671,25 @@ func (t *test) run() { } // -S=2 forces outermost line numbers when disassembling inlined code. cmdline := []string{"build", "-gcflags", "-S=2"} - cmdline = append(cmdline, flags...) + + // Append flags, but don't override -gcflags=-S=2; add to it instead. + for i := 0; i < len(flags); i++ { + flag := flags[i] + switch { + case strings.HasPrefix(flag, "-gcflags="): + cmdline[2] += " " + strings.TrimPrefix(flag, "-gcflags=") + case strings.HasPrefix(flag, "--gcflags="): + cmdline[2] += " " + strings.TrimPrefix(flag, "--gcflags=") + case flag == "-gcflags", flag == "--gcflags": + i++ + if i < len(flags) { + cmdline[2] += " " + flags[i] + } + default: + cmdline = append(cmdline, flag) + } + } + cmdline = append(cmdline, long) cmd := exec.Command(goTool(), cmdline...) cmd.Env = append(os.Environ(), env.Environ()...) @@ -984,7 +1006,7 @@ func (t *test) run() { useTmp = false var out []byte var err error - if len(flags)+len(args) == 0 && goGcflags() == "" && !*linkshared { + if len(flags)+len(args) == 0 && goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS { // If we're not using special go command flags, // skip all the go command machinery. // This avoids any time the go command would