Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0a6ccc5
cmd/compile: on amd64 optimize x + carry and x - carry into ADC and SBB
Jorropo Jul 14, 2026
bc4eb9a
go/build/constraint: match "go1." only as a tag prefix in GoVersion
goto1134 Jul 14, 2026
607cfce
cmd/compile: prevent arm[64] noov InvertFlags miscompilation at min int
josharian Jun 3, 2026
ed5e615
cmd/compile: fix typo in arm64 ssa comment
StephenJarso Jul 11, 2026
77a63bd
cmd/compile: fix typographical errors in Midway comment
StephenJarso Jul 11, 2026
26fd8f1
cmd/link: resolve crt0_64.o the same way as the other AIX startup files.
pgimalac Jul 15, 2026
12a1a35
cmd/compile: fix bug in convertIntWithBitsize
Jorropo Jun 28, 2026
ff88405
net/url: add MustParse
sfllaw Jul 11, 2026
9fb7b20
cmd/go: do not pass -mthreads to C compiler on Windows
cherrymui Jul 13, 2026
aa5fc60
cmd/compile/internal/arm64: fuse adjacent spill/reload STR/LDR into S…
gaul Jun 24, 2026
0948ed6
cmd/compile: remove LEA splitting
randall77 Jul 8, 2026
f23bcc2
cmd/compile: remove write barrier wbMove ABI optimization
randall77 Jun 29, 2026
553ac45
cmd/compile: cleanup PPC64 atomics ssa asm generation
Jorropo Jun 6, 2026
56d7cfd
cmd/compile: on AMD64 use leave instruction for go compiled functions
Jorropo May 12, 2023
f192b5b
cmd/compile/internal/ir: handle RHS = nil in static value
cuonglm May 28, 2026
2a95a61
net/http: reject userinfo in CrossOriginProtection
jub0bs May 31, 2026
f0c7811
cmd/compile/internal/types: store SIMD flags in Type.flags bitset
jakebailey Jun 8, 2026
4472de4
cmd/internal/obj/riscv: document rva23u64 feature macros
Jul 3, 2026
cff6172
reflect: extract potentially embedded reflect types before use
dr2chase Jul 10, 2026
58e8638
cmd/compile: require alignment for memcombine on riscv64
Jun 29, 2026
a6351c9
encoding/xml: reject invalid comment tokens
harjothkhara Jul 13, 2026
c78af9d
reflect: improve escape analysis for Value.Set
cherrymui Jul 10, 2026
d060863
cmd/compile: avoid temporaries for float division call args
bobu-putheeckal May 24, 2026
59468eb
html/template: test JavaScript escaping of cyclic values
cuishuang Jul 1, 2026
e75c0ec
crypto: clarify allowed overlap for AEAD
seankhliao Oct 24, 2025
86eb9af
cmd/compile: optimize abi.Type.TFlag loads
jakebailey Jun 8, 2026
d3c5179
cmd/compile: avoid heap-allocating LocalSlot in addNamedValue
siutsin Jun 12, 2026
1e28d9f
encoding/base64, encoding/base32: panic when encoded length overflows…
soreavis Jul 11, 2026
10981ef
cmd/go: avoid a blank line before ok when discarded output lacks a ne…
soreavis Jul 11, 2026
940c49c
debug/elf: use bytes.IndexByte in getString
tklauser Jun 11, 2026
f28114c
bytes: add example for Buffer.Peek
cuishuang Apr 15, 2026
dd9e8d9
reflect: add example for TypeAssert
cuishuang Jul 14, 2026
6bb1bf7
bytes, strings: add example for CutLast
cuishuang Jun 13, 2026
9b1a726
text/template, html/template: correct the documentation for IsTrue
soreavis Jul 11, 2026
e7d8668
cmd/compile: use a value slice for SSA Func.Names
siutsin Jun 15, 2026
4bbe275
cmd/go: retry ETXTBSY when running a cached builtin tool
NeitrinoK Jun 15, 2026
9f1012d
go/doc/comment: never rewrite into smart quotes
seankhliao Dec 23, 2025
d31e2b6
cmd/go/internal/doc: always return cached executable
h9jiang Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/next/79946.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg net/url, func MustParse(string) *URL #79946
2 changes: 2 additions & 0 deletions doc/next/6-stdlib/99-minor/encoding/base32/20235.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Encoding.EncodedLen] now panics if the encoded length overflows int,
rather than returning a negative number.
2 changes: 2 additions & 0 deletions doc/next/6-stdlib/99-minor/encoding/base64/20235.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Encoding.EncodedLen] now panics if the encoded length overflows int,
rather than returning a negative number.
5 changes: 5 additions & 0 deletions doc/next/6-stdlib/99-minor/net/url/79946.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- go.dev/issue/79946 -->
The new [MustParse] function returns the parsed [URL]
or panics on error.
It can simplify some common uses of [Parse].
For instance, initializing variables with valid URL string constants.
41 changes: 41 additions & 0 deletions src/bytes/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,35 @@ func ExampleBuffer_ReadByte() {
// bcde
}

func ExampleBuffer_Peek() {
var b bytes.Buffer
b.WriteString("Hello, Gophers!")

data, err := b.Peek(5)
if err != nil {
panic(err)
}
fmt.Printf("First peek: %s\n", data)

fmt.Printf("Buffer: %s\n", b.String())

// Advance past "Hello, ".
if _, err := b.Read(make([]byte, 7)); err != nil {
panic(err)
}

data, err = b.Peek(7)
if err != nil {
panic(err)
}
fmt.Printf("Second peek: %s\n", data)

// Output:
// First peek: Hello
// Buffer: Hello, Gophers!
// Second peek: Gophers
}

func ExampleClone() {
b := []byte("abc")
clone := bytes.Clone(b)
Expand Down Expand Up @@ -244,6 +273,18 @@ func ExampleCut() {
// Cut("Gopher", "Badger") = "Gopher", "", false
}

func ExampleCutLast() {
show := func(s, sep string) {
before, after, found := bytes.CutLast([]byte(s), []byte(sep))
fmt.Printf("CutLast(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
}
show("root/user/docs", "/")
show("Gopher", "/")
// Output:
// CutLast("root/user/docs", "/") = "root/user", "docs", true
// CutLast("Gopher", "/") = "Gopher", "", false
}

func ExampleCutPrefix() {
show := func(s, prefix string) {
after, found := bytes.CutPrefix([]byte(s), []byte(prefix))
Expand Down
20 changes: 2 additions & 18 deletions src/cmd/compile/internal/amd64/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -739,25 +739,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
p := s.Prog(v.Op.Asm())
memIdx(&p.From, v)
o := v.Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = o
if v.AuxInt != 0 && v.Aux == nil {
// Emit an additional LEA to add the displacement instead of creating a slow 3 operand LEA.
switch v.Op {
case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8:
p = s.Prog(x86.ALEAQ)
case ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8:
p = s.Prog(x86.ALEAL)
case ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
p = s.Prog(x86.ALEAW)
}
p.From.Type = obj.TYPE_MEM
p.From.Reg = o
p.To.Type = obj.TYPE_REG
p.To.Reg = o
}
ssagen.AddAux(&p.From, v)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpAMD64LEAQ, ssa.OpAMD64LEAL, ssa.OpAMD64LEAW:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/arm64/galign.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ func Init(arch *ssagen.ArchInfo) {
arch.SSAGenBlock = ssaGenBlock
arch.LoadRegResult = loadRegResult
arch.SpillArgReg = spillArgReg
arch.SSAGenFinish = ssaGenFinish
}
194 changes: 194 additions & 0 deletions src/cmd/compile/internal/arm64/pair.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// Copyright 2026 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 arm64

import (
"cmd/compile/internal/base"
"cmd/compile/internal/objw"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"cmd/internal/src"
)

// movdImmMemInfo describes a plain "MOVD reg, off(base)" or "MOVD off(base), reg"
// instruction. base, off, name, and sym record the memory operand's base
// register, offset, addressing class (NAME_AUTO or NAME_PARAM), and symbol;
// reg is the register stored or loaded, and isLoad distinguishes the two
// forms.
type movdImmMemInfo struct {
base, reg int16
off int64
name obj.AddrName
sym *obj.LSym
isLoad bool
}

// movdImmMem decodes p into a movdImmMemInfo. ok reports whether p is a
// plain MOVD load or store using an immediate-offset addressing form
// suitable for LDP/STP coalescing.
func movdImmMem(p *obj.Prog) (info movdImmMemInfo, ok bool) {
if p.As != arm64.AMOVD || p.Scond != 0 || p.Reg != 0 {
return movdImmMemInfo{}, false
}
var a *obj.Addr
switch {
case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
// Plain load: MOVD mem, reg.
a = &p.From
info.reg = p.To.Reg
info.isLoad = true
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
// Plain store: MOVD reg, mem.
a = &p.To
info.reg = p.From.Reg
default:
return movdImmMemInfo{}, false
}
if a.Index != 0 || (a.Name != obj.NAME_AUTO && a.Name != obj.NAME_PARAM) {
return movdImmMemInfo{}, false
}
info.base, info.off, info.name, info.sym = a.Reg, a.Offset, a.Name, a.Sym
return info, true
}

// ssaGenFinish runs after genssa has emitted all of a function's Progs,
// resolved its branch and jump-table targets, and finalized the frame size
// in defframe.
func ssaGenFinish(pp *objw.Progs) {
if base.Flag.N != 0 {
// Keep unoptimized builds unoptimized.
return
}
pairSpills(pp.Text, pp.Text.To.Offset, pp.CurFunc.LSym.Func().JumpTables)
}

// pairSpills fuses strictly-adjacent MOVD load or store pairs that target the
// same base register at consecutive 8-byte offsets into a single LDP or STP.
// text is the function's first Prog, framesize its final frame size, and
// jumpTables its resolved jump tables.
//
// This recovers spill/reload pairings that the SSA-level pair pass
// (cmd/compile/internal/ssa/pair.go) cannot perform: that pass runs before
// regalloc and only sees source-level loads/stores, so the STR/LDR pairs that
// regalloc later inserts for OpStoreReg/OpLoadReg never get a chance to be
// paired. Doing the fusion here, as the last step of code generation, keeps the
// optimization in the compiler so the assembler can stay a simple translator.
func pairSpills(text *obj.Prog, framesize int64, jumpTables []obj.JumpTable) {
// Branch and jump-table targets, collected lazily once a candidate pair
// survives the cheaper checks; most functions have no candidates.
// Fusing into the first of a pair whose second instruction is a target
// would silently change control flow: paths that jump directly to the
// second instruction would skip the work the LDP/STP now does at the
// first instruction's position.
var isTarget map[*obj.Prog]bool
targets := func() map[*obj.Prog]bool {
if isTarget == nil {
isTarget = map[*obj.Prog]bool{}
for p := text; p != nil; p = p.Link {
if t := p.To.Target(); t != nil {
isTarget[t] = true
}
}
for _, jt := range jumpTables {
for _, t := range jt.Targets {
isTarget[t] = true
}
}
}
return isTarget
}
for p := text; p != nil; p = p.Link {
q := p.Link
if q == nil {
continue
}
a, ok := movdImmMem(p)
if !ok {
continue
}
b, ok := movdImmMem(q)
if !ok || a.isLoad != b.isLoad {
continue
}
if a.base != b.base || a.name != b.name {
continue
}
if a.reg == b.reg {
// LDP with Rt1 == Rt2 is CONSTRAINED UNPREDICTABLE. (STP with
// identical source registers would be fine, but spills never
// store the same register twice, so don't bother.)
continue
}
if a.isLoad && a.reg == a.base {
// The first load overwrites the base register: executed
// sequentially, the second load computes its address from the
// just-loaded value, while LDP computes both addresses from
// the original base. (The second load overwriting the base is
// fine; no address depends on it.)
continue
}
if q.Pos.IsStmt() == src.PosIsStmt {
// q carries a statement boundary, and may also be registered
// as an inline mark: genssa promotes instructions it reuses
// as inline marks to statements. Reducing q to a 0-byte ANOP
// would drop the statement from the line tables and violate
// the invariant that inline marks are never zero-sized (they
// are identified by PC).
continue
}
lo, hi := a, b
if lo.off > hi.off {
lo, hi = hi, lo
}
if hi.off != lo.off+8 {
continue
}
// Fuse only when the result will encode as a single LDP/STP, whose
// signed 7-bit immediate scaled by 8 covers offsets [-512, 504].
// The assembler resolves a NAME_AUTO offset to off+framesize+8
// (the 8 is the saved LR) and a NAME_PARAM offset to
// off+framesize+24 or +32 depending on frame alignment padding —
// or off+8 in a frameless leaf, which is not decided until
// assembly, so a frameless PARAM must fit both. An out-of-range
// LDP/STP needs an assembler-synthesized address (ADD + LDP),
// which is no smaller than the original pair and serializes the
// accesses through REGTMP.
var biasLo, biasHi int64
switch {
case lo.name == obj.NAME_AUTO:
// Autos exist only in functions with a frame, and their offsets
// are negative from FP, so framesize+8 rebases them onto the
// non-negative SP-relative range the LDP/STP immediate must reach.
biasLo = framesize + 8
biasHi = biasLo
case framesize == 0:
biasLo, biasHi = 8, 24
case framesize%16 == 0:
biasLo = framesize + 24
biasHi = biasLo
default:
biasLo = framesize + 32
biasHi = biasLo
}
if lo.off%8 != 0 || lo.off+biasLo < -512 || lo.off+biasHi > 504 {
continue
}
if targets()[q] {
continue
}
mem := obj.Addr{Type: obj.TYPE_MEM, Reg: lo.base, Offset: lo.off, Name: lo.name, Sym: lo.sym}
regs := obj.Addr{Type: obj.TYPE_REGREG, Reg: lo.reg, Offset: int64(hi.reg)}
if a.isLoad {
p.As = arm64.ALDP
p.From, p.To = mem, regs
} else {
p.As = arm64.ASTP
p.From, p.To = regs, mem
}
// Reduce q to a 0-byte ANOP rather than unlinking it so that
// branch targets referencing q remain valid.
obj.Nopout(q)
}
}
Loading
Loading