2015-01-19 14:34:58 -05:00
// Inferno utils/6l/pass.c
2020-06-03 13:17:17 +02:00
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/pass.c
2015-01-19 14:34:58 -05:00
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
2016-04-10 14:32:26 -07:00
// Portions Copyright © 2009 The Go Authors. All rights reserved.
2015-01-19 14:34:58 -05:00
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package x86
import (
"cmd/internal/obj"
2017-04-18 12:53:25 -07:00
"cmd/internal/objabi"
2018-04-30 23:52:14 -04:00
"cmd/internal/src"
2016-04-06 12:01:40 -07:00
"cmd/internal/sys"
2023-04-17 15:58:47 -04:00
"internal/abi"
cmd/asm, cmd/link, runtime: introduce FuncInfo flag bits
The runtime traceback code has its own definition of which functions
mark the top frame of a stack, separate from the TOPFRAME bits that
exist in the assembly and are passed along in DWARF information.
It's error-prone and redundant to have two different sources of truth.
This CL provides the actual TOPFRAME bits to the runtime, so that
the runtime can use those bits instead of reinventing its own category.
This CL also adds a new bit, SPWRITE, which marks functions that
write directly to SP (anything but adding and subtracting constants).
Such functions must stop a traceback, because the traceback has no
way to rederive the SP on entry. Again, the runtime has its own definition
which is mostly correct, but also missing some functions. During ordinary
goroutine context switches, such functions do not appear on the stack,
so the incompleteness in the runtime usually doesn't matter.
But profiling signals can arrive at any moment, and the runtime may
crash during traceback if it attempts to unwind an SP-writing frame
and gets out-of-sync with the actual stack. The runtime contains code
to try to detect likely candidates but again it is incomplete.
Deriving the SPWRITE bit automatically from the actual assembly code
provides the complete truth, and passing it to the runtime lets the
runtime use it.
This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
This CL is, however, not windows/arm64-specific.
It is cleanup meant to make the port (and future ports) easier.
Change-Id: I227f53b23ac5b3dabfcc5e8ee3f00df4e113cf58
Reviewed-on: https://go-review.googlesource.com/c/go/+/288800
Trust: Russ Cox <rsc@golang.org>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-28 15:21:33 -05:00
"log"
2015-01-19 14:34:58 -05:00
"math"
2021-01-13 15:45:28 -08:00
"path"
[dev.ssa] cmd/compile: fix PIC for SSA-generated code
Access to globals requires a 2-instruction sequence on PIC 386.
MOVL foo(SB), AX
is translated by the obj package into:
CALL getPCofNextInstructionInTempRegister(SB)
MOVL (&foo-&thisInstruction)(tmpReg), AX
The call returns the PC of the next instruction in a register.
The next instruction then offsets from that register to get the
address required. The tricky part is the allocation of the
temp register. The legacy compiler always used CX, and forbid
the register allocator from allocating CX when in PIC mode.
We can't easily do that in SSA because CX is actually a required
register for shift instructions. (I think the old backend got away
with this because the register allocator never uses CX, only
codegen knows that shifts must use CX.)
Instead, we allow the temp register to be anything. When the
destination of the MOV (or LEA) is an integer register, we can
use that register. Otherwise, we make sure to compile the
operation using an LEA to reference the global. So
MOVL AX, foo(SB)
is never generated directly. Instead, SSA generates:
LEAL foo(SB), DX
MOVL AX, (DX)
which is then rewritten by the obj package to:
CALL getPcInDX(SB)
LEAL (&foo-&thisInstruction)(DX), AX
MOVL AX, (DX)
So this CL modifies the obj package to use different thunks
to materialize the pc into different registers. We use the
registers that regalloc chose so that SSA can still allocate
the full set of registers.
Change-Id: Ie095644f7164a026c62e95baf9d18a8bcaed0bba
Reviewed-on: https://go-review.googlesource.com/25442
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-08-03 13:00:49 -07:00
"strings"
2015-01-19 14:34:58 -05:00
)
2015-08-12 11:22:16 -07:00
func CanUse1InsnTLS ( ctxt * obj . Link ) bool {
2015-10-16 14:04:29 -04:00
if isAndroid {
2019-03-28 13:11:53 +01:00
// Android uses a global variable for the tls offset.
return false
2015-10-16 14:04:29 -04:00
}
2017-03-26 08:05:40 -07:00
if ctxt . Arch . Family == sys . I386 {
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
switch ctxt . Headtype {
2017-04-18 12:53:25 -07:00
case objabi . Hlinux ,
objabi . Hplan9 ,
objabi . Hwindows :
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
return false
}
return true
}
2015-01-19 14:34:58 -05:00
switch ctxt . Headtype {
2017-04-18 12:53:25 -07:00
case objabi . Hplan9 , objabi . Hwindows :
2015-02-17 22:13:49 -05:00
return false
2018-02-13 19:00:17 -08:00
case objabi . Hlinux , objabi . Hfreebsd :
2016-04-13 18:41:59 -07:00
return ! ctxt . Flag_shared
2015-01-19 14:34:58 -05:00
}
2015-02-17 22:13:49 -05:00
return true
2015-01-19 14:34:58 -05:00
}
2017-04-04 14:31:55 -07:00
func progedit ( ctxt * obj . Link , p * obj . Prog , newprog obj . ProgAlloc ) {
2015-01-19 14:34:58 -05:00
// Thread-local storage references use the TLS pseudo-register.
// As a register, TLS refers to the thread-local storage base, and it
// can only be loaded into another register:
//
// MOVQ TLS, AX
//
// An offset from the thread-local storage base is written off(reg)(TLS*1).
// Semantically it is off(reg), but the (TLS*1) annotation marks this as
// indexing from the loaded TLS base. This emits a relocation so that
// if the linker needs to adjust the offset, it can. For example:
//
// MOVQ TLS, AX
2015-04-23 21:53:48 +12:00
// MOVQ 0(AX)(TLS*1), CX // load g into CX
2015-01-19 14:34:58 -05:00
//
// On systems that support direct access to the TLS memory, this
// pair of instructions can be reduced to a direct TLS memory reference:
//
2015-04-23 21:53:48 +12:00
// MOVQ 0(TLS), CX // load g into CX
2015-01-19 14:34:58 -05:00
//
2015-04-23 21:53:48 +12:00
// The 2-instruction and 1-instruction forms correspond to the two code
// sequences for loading a TLS variable in the local exec model given in "ELF
// Handling For Thread-Local Storage".
2015-01-19 14:34:58 -05:00
//
2015-04-23 21:53:48 +12:00
// We apply this rewrite on systems that support the 1-instruction form.
// The decision is made using only the operating system and the -shared flag,
// not the link mode. If some link modes on a particular operating system
// require the 2-instruction form, then all builds for that operating system
// will use the 2-instruction form, so that the link mode decision can be
// delayed to link time.
2015-01-19 14:34:58 -05:00
//
// In this way, all supported systems use identical instructions to
// access TLS, and they are rewritten appropriately first here in
// liblink and then finally using relocations in the linker.
2015-04-23 21:53:48 +12:00
//
// When -shared is passed, we leave the code in the 2-instruction form but
// assemble (and relocate) them in different ways to generate the initial
// exec code sequence. It's a bit of a fluke that this is possible without
// rewriting the instructions more comprehensively, and it only does because
// we only support a single TLS variable (g).
2015-01-19 14:34:58 -05:00
2015-08-12 11:22:16 -07:00
if CanUse1InsnTLS ( ctxt ) {
2015-04-23 21:53:48 +12:00
// Reduce 2-instruction sequence to 1-instruction sequence.
2015-01-19 14:34:58 -05:00
// Sequences like
// MOVQ TLS, BX
// ... off(BX)(TLS*1) ...
// become
// NOP
// ... off(TLS) ...
//
// TODO(rsc): Remove the Hsolaris special case. It exists only to
// guarantee we are producing byte-identical binaries as before this code.
// But it should be unnecessary.
2017-04-18 12:53:25 -07:00
if ( p . As == AMOVQ || p . As == AMOVL ) && p . From . Type == obj . TYPE_REG && p . From . Reg == REG_TLS && p . To . Type == obj . TYPE_REG && REG_AX <= p . To . Reg && p . To . Reg <= REG_R15 && ctxt . Headtype != objabi . Hsolaris {
2015-02-13 14:40:36 -05:00
obj . Nopout ( p )
2015-01-19 14:34:58 -05:00
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Type == obj . TYPE_MEM && p . From . Index == REG_TLS && REG_AX <= p . From . Reg && p . From . Reg <= REG_R15 {
p . From . Reg = REG_TLS
2015-01-19 14:34:58 -05:00
p . From . Scale = 0
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Index = REG_NONE
2015-01-19 14:34:58 -05:00
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . To . Type == obj . TYPE_MEM && p . To . Index == REG_TLS && REG_AX <= p . To . Reg && p . To . Reg <= REG_R15 {
p . To . Reg = REG_TLS
2015-01-19 14:34:58 -05:00
p . To . Scale = 0
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Index = REG_NONE
2015-01-19 14:34:58 -05:00
}
} else {
2021-02-19 17:11:40 -05:00
// load_g, below, always inserts the 1-instruction sequence. Rewrite it
2015-04-23 21:53:48 +12:00
// as the 2-instruction sequence if necessary.
// MOVQ 0(TLS), BX
// becomes
2015-01-19 14:34:58 -05:00
// MOVQ TLS, BX
2015-04-23 21:53:48 +12:00
// MOVQ 0(BX)(TLS*1), BX
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if ( p . As == AMOVQ || p . As == AMOVL ) && p . From . Type == obj . TYPE_MEM && p . From . Reg == REG_TLS && p . To . Type == obj . TYPE_REG && REG_AX <= p . To . Reg && p . To . Reg <= REG_R15 {
2017-04-04 14:31:55 -07:00
q := obj . Appendp ( p , newprog )
2015-01-19 14:34:58 -05:00
q . As = p . As
q . From = p . From
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
q . From . Type = obj . TYPE_MEM
q . From . Reg = p . To . Reg
q . From . Index = REG_TLS
2015-01-19 14:34:58 -05:00
q . From . Scale = 2 // TODO: use 1
q . To = p . To
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_REG
p . From . Reg = REG_TLS
p . From . Index = REG_NONE
2015-01-19 14:34:58 -05:00
p . From . Offset = 0
}
}
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/i386
This CL redesign how we get the TLS pointer on windows/i386.
It applies the same changes as done in CL 431775 for windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x14(FS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0xE10(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0xE10 + index*4.
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(FS), AX
Notice that this approach will now be implemented in all the supported
windows arches.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Change-Id: If4550b0d44694ee6480d4093b851f4991a088b32
Reviewed-on: https://go-review.googlesource.com/c/go/+/454675
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-12-02 09:25:26 +01:00
// Android and Windows use a tls offset determined at runtime. Rewrite
2019-03-28 13:11:53 +01:00
// MOVQ TLS, BX
// to
// MOVQ runtime.tls_g(SB), BX
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/i386
This CL redesign how we get the TLS pointer on windows/i386.
It applies the same changes as done in CL 431775 for windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x14(FS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0xE10(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0xE10 + index*4.
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(FS), AX
Notice that this approach will now be implemented in all the supported
windows arches.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Change-Id: If4550b0d44694ee6480d4093b851f4991a088b32
Reviewed-on: https://go-review.googlesource.com/c/go/+/454675
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-12-02 09:25:26 +01:00
if ( isAndroid || ctxt . Headtype == objabi . Hwindows ) &&
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/amd64
This CL redesign how we get the TLS pointer on windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x28(GS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0x1480(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0x1480 + index*8
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(GS), AX
Notice that this approach is also implemented on windows/arm64.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Updates #22192
Change-Id: Idea7119fd76a3cd083979a4d57ed64b552fa101b
Reviewed-on: https://go-review.googlesource.com/c/go/+/431775
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2022-09-19 12:19:38 +02:00
( p . As == AMOVQ || p . As == AMOVL ) && p . From . Type == obj . TYPE_REG && p . From . Reg == REG_TLS && p . To . Type == obj . TYPE_REG && REG_AX <= p . To . Reg && p . To . Reg <= REG_R15 {
2019-03-28 13:11:53 +01:00
p . From . Type = obj . TYPE_MEM
p . From . Name = obj . NAME_EXTERN
p . From . Reg = REG_NONE
p . From . Sym = ctxt . Lookup ( "runtime.tls_g" )
p . From . Index = REG_NONE
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/amd64
This CL redesign how we get the TLS pointer on windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x28(GS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0x1480(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0x1480 + index*8
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(GS), AX
Notice that this approach is also implemented on windows/arm64.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Updates #22192
Change-Id: Idea7119fd76a3cd083979a4d57ed64b552fa101b
Reviewed-on: https://go-review.googlesource.com/c/go/+/431775
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2022-09-19 12:19:38 +02:00
if ctxt . Headtype == objabi . Hwindows {
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/i386
This CL redesign how we get the TLS pointer on windows/i386.
It applies the same changes as done in CL 431775 for windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x14(FS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0xE10(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0xE10 + index*4.
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(FS), AX
Notice that this approach will now be implemented in all the supported
windows arches.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Change-Id: If4550b0d44694ee6480d4093b851f4991a088b32
Reviewed-on: https://go-review.googlesource.com/c/go/+/454675
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-12-02 09:25:26 +01:00
// Windows requires an additional indirection
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/amd64
This CL redesign how we get the TLS pointer on windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x28(GS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0x1480(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0x1480 + index*8
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(GS), AX
Notice that this approach is also implemented on windows/arm64.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Updates #22192
Change-Id: Idea7119fd76a3cd083979a4d57ed64b552fa101b
Reviewed-on: https://go-review.googlesource.com/c/go/+/431775
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2022-09-19 12:19:38 +02:00
// to retrieve the TLS pointer,
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/i386
This CL redesign how we get the TLS pointer on windows/i386.
It applies the same changes as done in CL 431775 for windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x14(FS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0xE10(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0xE10 + index*4.
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(FS), AX
Notice that this approach will now be implemented in all the supported
windows arches.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Change-Id: If4550b0d44694ee6480d4093b851f4991a088b32
Reviewed-on: https://go-review.googlesource.com/c/go/+/454675
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-12-02 09:25:26 +01:00
// as runtime.tls_g contains the TLS offset from GS or FS.
// on AMD64 add
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/amd64
This CL redesign how we get the TLS pointer on windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x28(GS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0x1480(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0x1480 + index*8
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(GS), AX
Notice that this approach is also implemented on windows/arm64.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Updates #22192
Change-Id: Idea7119fd76a3cd083979a4d57ed64b552fa101b
Reviewed-on: https://go-review.googlesource.com/c/go/+/431775
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2022-09-19 12:19:38 +02:00
// MOVQ 0(BX)(GS*1), BX
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/i386
This CL redesign how we get the TLS pointer on windows/i386.
It applies the same changes as done in CL 431775 for windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x14(FS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0xE10(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0xE10 + index*4.
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(FS), AX
Notice that this approach will now be implemented in all the supported
windows arches.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Change-Id: If4550b0d44694ee6480d4093b851f4991a088b32
Reviewed-on: https://go-review.googlesource.com/c/go/+/454675
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-12-02 09:25:26 +01:00
// on 386 add
// MOVQ 0(BX)(FS*1), BX4
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/amd64
This CL redesign how we get the TLS pointer on windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x28(GS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0x1480(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0x1480 + index*8
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(GS), AX
Notice that this approach is also implemented on windows/arm64.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Updates #22192
Change-Id: Idea7119fd76a3cd083979a4d57ed64b552fa101b
Reviewed-on: https://go-review.googlesource.com/c/go/+/431775
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2022-09-19 12:19:38 +02:00
q := obj . Appendp ( p , newprog )
q . As = p . As
q . From = obj . Addr { }
q . From . Type = obj . TYPE_MEM
q . From . Reg = p . To . Reg
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/i386
This CL redesign how we get the TLS pointer on windows/i386.
It applies the same changes as done in CL 431775 for windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x14(FS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0xE10(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0xE10 + index*4.
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(FS), AX
Notice that this approach will now be implemented in all the supported
windows arches.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Change-Id: If4550b0d44694ee6480d4093b851f4991a088b32
Reviewed-on: https://go-review.googlesource.com/c/go/+/454675
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-12-02 09:25:26 +01:00
if ctxt . Arch . Family == sys . AMD64 {
q . From . Index = REG_GS
} else {
q . From . Index = REG_FS
}
runtime,cmd/internal/obj/x86: use TEB TLS slots on windows/amd64
This CL redesign how we get the TLS pointer on windows/amd64.
We were previously reading it from the [TEB] arbitrary data slot,
located at 0x28(GS), which can only hold 1 TLS pointer.
With this CL, we will read the TLS pointer from the TEB TLS slot array,
located at 0x1480(GS). The TLS slot array can hold multiple
TLS pointers, up to 64, so multiple Go runtimes running on the
same thread can coexists with different TLS.
Each new TLS slot has to be allocated via [TlsAlloc],
which returns the slot index. This index can then be used to get the
slot offset from GS with the following formula: 0x1480 + index*8
The slot index is fixed per Go runtime, so we can store it
in runtime.tls_g and use it latter on to read/update the TLS pointer.
Loading the TLS pointer requires the following asm instructions:
MOVQ runtime.tls_g, AX
MOVQ AX(GS), AX
Notice that this approach is also implemented on windows/arm64.
[TEB]: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
[TlsAlloc]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
Updates #22192
Change-Id: Idea7119fd76a3cd083979a4d57ed64b552fa101b
Reviewed-on: https://go-review.googlesource.com/c/go/+/431775
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2022-09-19 12:19:38 +02:00
q . From . Scale = 1
q . From . Offset = 0
q . To = p . To
}
2019-03-28 13:11:53 +01:00
}
2015-01-19 14:34:58 -05:00
// TODO: Remove.
2017-04-18 12:53:25 -07:00
if ctxt . Headtype == objabi . Hwindows && ctxt . Arch . Family == sys . AMD64 || ctxt . Headtype == objabi . Hplan9 {
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Scale == 1 && p . From . Index == REG_TLS {
2015-01-19 14:34:58 -05:00
p . From . Scale = 2
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . To . Scale == 1 && p . To . Index == REG_TLS {
2015-01-19 14:34:58 -05:00
p . To . Scale = 2
}
}
2016-02-24 11:55:20 +01:00
// Rewrite 0 to $0 in 3rd argument to CMPPS etc.
2015-03-05 00:43:21 -05:00
// That's what the tables expect.
switch p . As {
case ACMPPD , ACMPPS , ACMPSD , ACMPSS :
if p . To . Type == obj . TYPE_MEM && p . To . Name == obj . NAME_NONE && p . To . Reg == REG_NONE && p . To . Index == REG_NONE && p . To . Sym == nil {
p . To . Type = obj . TYPE_CONST
}
2015-01-19 14:34:58 -05:00
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
// Rewrite CALL/JMP/RET to symbol as TYPE_BRANCH.
2015-01-19 14:34:58 -05:00
switch p . As {
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
case obj . ACALL , obj . AJMP , obj . ARET :
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . To . Type == obj . TYPE_MEM && ( p . To . Name == obj . NAME_EXTERN || p . To . Name == obj . NAME_STATIC ) && p . To . Sym != nil {
p . To . Type = obj . TYPE_BRANCH
2015-01-19 14:34:58 -05:00
}
}
2015-03-18 17:26:36 -04:00
// Rewrite MOVL/MOVQ $XXX(FP/SP) as LEAL/LEAQ.
2016-04-06 12:01:40 -07:00
if p . From . Type == obj . TYPE_ADDR && ( ctxt . Arch . Family == sys . AMD64 || p . From . Name != obj . NAME_EXTERN && p . From . Name != obj . NAME_STATIC ) {
2015-03-18 17:26:36 -04:00
switch p . As {
case AMOVL :
p . As = ALEAL
p . From . Type = obj . TYPE_MEM
case AMOVQ :
p . As = ALEAQ
p . From . Type = obj . TYPE_MEM
}
}
2015-01-19 14:34:58 -05:00
// Rewrite float constants to values stored in memory.
switch p . As {
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
case AMOVSS :
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Type == obj . TYPE_FCONST {
2015-09-01 21:25:24 -05:00
// f == 0 can't be used here due to -0, so use Float64bits
if f := p . From . Val . ( float64 ) ; math . Float64bits ( f ) == 0 {
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . To . Type == obj . TYPE_REG && REG_X0 <= p . To . Reg && p . To . Reg <= REG_X15 {
p . As = AXORPS
p . From = p . To
break
2015-01-19 14:34:58 -05:00
}
}
}
fallthrough
case AFMOVF ,
AFADDF ,
AFSUBF ,
AFSUBRF ,
AFMULF ,
AFDIVF ,
AFDIVRF ,
AFCOMF ,
AFCOMFP ,
AADDSS ,
ASUBSS ,
AMULSS ,
ADIVSS ,
ACOMISS ,
AUCOMISS :
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Type == obj . TYPE_FCONST {
2015-03-16 15:54:44 -04:00
f32 := float32 ( p . From . Val . ( float64 ) )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_MEM
p . From . Name = obj . NAME_EXTERN
2017-04-06 10:29:29 -07:00
p . From . Sym = ctxt . Float32Sym ( f32 )
2015-01-19 14:34:58 -05:00
p . From . Offset = 0
}
case AMOVSD :
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Type == obj . TYPE_FCONST {
2015-09-01 21:25:24 -05:00
// f == 0 can't be used here due to -0, so use Float64bits
if f := p . From . Val . ( float64 ) ; math . Float64bits ( f ) == 0 {
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . To . Type == obj . TYPE_REG && REG_X0 <= p . To . Reg && p . To . Reg <= REG_X15 {
p . As = AXORPS
p . From = p . To
break
2015-01-19 14:34:58 -05:00
}
}
}
fallthrough
case AFMOVD ,
AFADDD ,
AFSUBD ,
AFSUBRD ,
AFMULD ,
AFDIVD ,
AFDIVRD ,
AFCOMD ,
AFCOMDP ,
AADDSD ,
ASUBSD ,
AMULSD ,
ADIVSD ,
ACOMISD ,
AUCOMISD :
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Type == obj . TYPE_FCONST {
2017-04-06 10:29:29 -07:00
f64 := p . From . Val . ( float64 )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_MEM
p . From . Name = obj . NAME_EXTERN
2017-04-06 10:29:29 -07:00
p . From . Sym = ctxt . Float64Sym ( f64 )
2015-01-19 14:34:58 -05:00
p . From . Offset = 0
}
}
2015-03-30 00:49:25 +00:00
2015-11-11 15:57:42 +13:00
if ctxt . Flag_dynlink {
2017-04-04 14:31:55 -07:00
rewriteToUseGot ( ctxt , p , newprog )
2015-11-11 15:57:42 +13:00
}
2015-11-18 12:14:07 +13:00
2017-03-26 08:05:40 -07:00
if ctxt . Flag_shared && ctxt . Arch . Family == sys . I386 {
2017-04-04 14:31:55 -07:00
rewriteToPcrel ( ctxt , p , newprog )
2015-11-18 12:14:07 +13:00
}
2015-11-11 15:57:42 +13:00
}
// Rewrite p, if necessary, to access global data via the global offset table.
2017-04-04 14:31:55 -07:00
func rewriteToUseGot ( ctxt * obj . Link , p * obj . Prog , newprog obj . ProgAlloc ) {
2017-04-27 11:56:42 +12:00
var lea , mov obj . As
2016-03-07 18:00:08 -08:00
var reg int16
2017-03-26 08:05:40 -07:00
if ctxt . Arch . Family == sys . AMD64 {
2015-11-18 12:30:23 +13:00
lea = ALEAQ
mov = AMOVQ
reg = REG_R15
} else {
lea = ALEAL
mov = AMOVL
reg = REG_CX
2016-08-11 12:56:36 -07:00
if p . As == ALEAL && p . To . Reg != p . From . Reg && p . To . Reg != p . From . Index {
// Special case: clobber the destination register with
// the PC so we don't have to clobber CX.
// The SSA backend depends on CX not being clobbered across LEAL.
// See cmd/compile/internal/ssa/gen/386.rules (search for Flag_shared).
reg = p . To . Reg
2016-08-09 13:58:06 -07:00
}
2015-11-18 12:30:23 +13:00
}
2015-11-11 15:57:42 +13:00
if p . As == obj . ADUFFCOPY || p . As == obj . ADUFFZERO {
// ADUFFxxx $offset
// becomes
2015-11-18 12:30:23 +13:00
// $MOV runtime.duffxxx@GOT, $reg
2017-04-27 11:56:42 +12:00
// $LEA $offset($reg), $reg
2015-11-18 12:30:23 +13:00
// CALL $reg
2017-04-27 11:56:42 +12:00
// (we use LEAx rather than ADDx because ADDx clobbers
2017-11-15 13:45:31 -05:00
// flags and duffzero on 386 does not otherwise do so).
2015-03-30 01:54:49 +00:00
var sym * obj . LSym
if p . As == obj . ADUFFZERO {
2020-10-14 08:36:11 -04:00
sym = ctxt . LookupABI ( "runtime.duffzero" , obj . ABIInternal )
2015-03-30 01:54:49 +00:00
} else {
2020-10-14 08:36:11 -04:00
sym = ctxt . LookupABI ( "runtime.duffcopy" , obj . ABIInternal )
2015-03-30 01:54:49 +00:00
}
offset := p . To . Offset
2015-11-18 12:30:23 +13:00
p . As = mov
2015-03-30 01:54:49 +00:00
p . From . Type = obj . TYPE_MEM
p . From . Name = obj . NAME_GOTREF
p . From . Sym = sym
p . To . Type = obj . TYPE_REG
2015-11-18 12:30:23 +13:00
p . To . Reg = reg
2015-03-30 01:54:49 +00:00
p . To . Offset = 0
p . To . Sym = nil
2017-04-04 14:31:55 -07:00
p1 := obj . Appendp ( p , newprog )
2017-04-27 11:56:42 +12:00
p1 . As = lea
p1 . From . Type = obj . TYPE_MEM
2015-03-30 01:54:49 +00:00
p1 . From . Offset = offset
2017-04-27 11:56:42 +12:00
p1 . From . Reg = reg
2015-03-30 01:54:49 +00:00
p1 . To . Type = obj . TYPE_REG
2015-11-18 12:30:23 +13:00
p1 . To . Reg = reg
2017-04-04 14:31:55 -07:00
p2 := obj . Appendp ( p1 , newprog )
2015-03-30 01:54:49 +00:00
p2 . As = obj . ACALL
p2 . To . Type = obj . TYPE_REG
2015-11-18 12:30:23 +13:00
p2 . To . Reg = reg
2015-03-30 01:54:49 +00:00
}
2015-11-11 15:57:42 +13:00
// We only care about global data: NAME_EXTERN means a global
// symbol in the Go sense, and p.Sym.Local is true for a few
// internally defined symbols.
2016-10-24 23:15:41 +03:00
if p . As == lea && p . From . Type == obj . TYPE_MEM && p . From . Name == obj . NAME_EXTERN && ! p . From . Sym . Local ( ) {
2015-11-18 12:30:23 +13:00
// $LEA sym, Rx becomes $MOV $sym, Rx which will be rewritten below
p . As = mov
2015-11-11 15:57:42 +13:00
p . From . Type = obj . TYPE_ADDR
}
2016-10-24 23:15:41 +03:00
if p . From . Type == obj . TYPE_ADDR && p . From . Name == obj . NAME_EXTERN && ! p . From . Sym . Local ( ) {
2015-11-18 12:30:23 +13:00
// $MOV $sym, Rx becomes $MOV sym@GOT, Rx
2016-02-04 11:21:31 -08:00
// $MOV $sym+<off>, Rx becomes $MOV sym@GOT, Rx; $LEA <off>(Rx), Rx
2015-11-18 12:30:23 +13:00
// On 386 only, more complicated things like PUSHL $sym become $MOV sym@GOT, CX; PUSHL CX
cmplxdest := false
pAs := p . As
var dest obj . Addr
if p . To . Type != obj . TYPE_REG || pAs != mov {
2017-03-26 08:05:40 -07:00
if ctxt . Arch . Family == sys . AMD64 {
2015-11-18 12:30:23 +13:00
ctxt . Diag ( "do not know how to handle LEA-type insn to non-register in %v with -dynlink" , p )
2015-03-30 00:49:25 +00:00
}
2015-11-18 12:30:23 +13:00
cmplxdest = true
dest = p . To
p . As = mov
p . To . Type = obj . TYPE_REG
2016-08-09 13:58:06 -07:00
p . To . Reg = reg
2015-11-18 12:30:23 +13:00
p . To . Sym = nil
p . To . Name = obj . NAME_NONE
2015-03-30 00:49:25 +00:00
}
2015-11-11 15:57:42 +13:00
p . From . Type = obj . TYPE_MEM
p . From . Name = obj . NAME_GOTREF
2015-11-18 12:30:23 +13:00
q := p
2015-11-11 15:57:42 +13:00
if p . From . Offset != 0 {
2017-04-04 14:31:55 -07:00
q = obj . Appendp ( p , newprog )
2016-02-04 11:21:31 -08:00
q . As = lea
q . From . Type = obj . TYPE_MEM
q . From . Reg = p . To . Reg
2015-11-11 15:57:42 +13:00
q . From . Offset = p . From . Offset
q . To = p . To
p . From . Offset = 0
2015-03-30 00:49:25 +00:00
}
2015-11-18 12:30:23 +13:00
if cmplxdest {
2017-04-04 14:31:55 -07:00
q = obj . Appendp ( q , newprog )
2015-11-18 12:30:23 +13:00
q . As = pAs
q . To = dest
q . From . Type = obj . TYPE_REG
2016-08-09 13:58:06 -07:00
q . From . Reg = reg
2015-03-30 00:49:25 +00:00
}
2015-11-11 15:57:42 +13:00
}
2017-09-13 14:32:08 +03:00
if p . GetFrom3 ( ) != nil && p . GetFrom3 ( ) . Name == obj . NAME_EXTERN {
2015-11-11 15:57:42 +13:00
ctxt . Diag ( "don't know how to handle %v with -dynlink" , p )
}
var source * obj . Addr
2015-11-18 12:30:23 +13:00
// MOVx sym, Ry becomes $MOV sym@GOT, R15; MOVx (R15), Ry
// MOVx Ry, sym becomes $MOV sym@GOT, R15; MOVx Ry, (R15)
2015-11-11 15:57:42 +13:00
// An addition may be inserted between the two MOVs if there is an offset.
2016-10-24 23:15:41 +03:00
if p . From . Name == obj . NAME_EXTERN && ! p . From . Sym . Local ( ) {
if p . To . Name == obj . NAME_EXTERN && ! p . To . Sym . Local ( ) {
2015-11-11 15:57:42 +13:00
ctxt . Diag ( "cannot handle NAME_EXTERN on both sides in %v with -dynlink" , p )
2015-03-30 00:49:25 +00:00
}
2015-11-11 15:57:42 +13:00
source = & p . From
2016-10-24 23:15:41 +03:00
} else if p . To . Name == obj . NAME_EXTERN && ! p . To . Sym . Local ( ) {
2015-11-11 15:57:42 +13:00
source = & p . To
} else {
return
}
2015-11-18 12:30:23 +13:00
if p . As == obj . ACALL {
// When dynlinking on 386, almost any call might end up being a call
// to a PLT, so make sure the GOT pointer is loaded into BX.
// RegTo2 is set on the replacement call insn to stop it being
// processed when it is in turn passed to progedit.
cmd/compile, cmd/link, runtime: make defers low-cost through inline code and extra funcdata
Generate inline code at defer time to save the args of defer calls to unique
(autotmp) stack slots, and generate inline code at exit time to check which defer
calls were made and make the associated function/method/interface calls. We
remember that a particular defer statement was reached by storing in the deferBits
variable (always stored on the stack). At exit time, we check the bits of the
deferBits variable to determine which defer function calls to make (in reverse
order). These low-cost defers are only used for functions where no defers
appear in loops. In addition, we don't do these low-cost defers if there are too
many defer statements or too many exits in a function (to limit code increase).
When a function uses open-coded defers, we produce extra
FUNCDATA_OpenCodedDeferInfo information that specifies the number of defers, and
for each defer, the stack slots where the closure and associated args have been
stored. The funcdata also includes the location of the deferBits variable.
Therefore, for panics, we can use this funcdata to determine exactly which defers
are active, and call the appropriate functions/methods/closures with the correct
arguments for each active defer.
In order to unwind the stack correctly after a recover(), we need to add an extra
code segment to functions with open-coded defers that simply calls deferreturn()
and returns. This segment is not reachable by the normal function, but is returned
to by the runtime during recovery. We set the liveness information of this
deferreturn() to be the same as the liveness at the first function call during the
last defer exit code (so all return values and all stack slots needed by the defer
calls will be live).
I needed to increase the stackguard constant from 880 to 896, because of a small
amount of new code in deferreturn().
The -N flag disables open-coded defers. '-d defer' prints out the kind of defer
being used at each defer statement (heap-allocated, stack-allocated, or
open-coded).
Cost of defer statement [ go test -run NONE -bench BenchmarkDefer$ runtime ]
With normal (stack-allocated) defers only: 35.4 ns/op
With open-coded defers: 5.6 ns/op
Cost of function call alone (remove defer keyword): 4.4 ns/op
Text size increase (including funcdata) for go binary without/with open-coded defers: 0.09%
The average size increase (including funcdata) for only the functions that use
open-coded defers is 1.1%.
The cost of a panic followed by a recover got noticeably slower, since panic
processing now requires a scan of the stack for open-coded defer frames. This scan
is required, even if no frames are using open-coded defers:
Cost of panic and recover [ go test -run NONE -bench BenchmarkPanicRecover runtime ]
Without open-coded defers: 62.0 ns/op
With open-coded defers: 255 ns/op
A CGO Go-to-C-to-Go benchmark got noticeably faster because of open-coded defers:
CGO Go-to-C-to-Go benchmark [cd misc/cgo/test; go test -run NONE -bench BenchmarkCGoCallback ]
Without open-coded defers: 443 ns/op
With open-coded defers: 347 ns/op
Updates #14939 (defer performance)
Updates #34481 (design doc)
Change-Id: I63b1a60d1ebf28126f55ee9fd7ecffe9cb23d1ff
Reviewed-on: https://go-review.googlesource.com/c/go/+/202340
Reviewed-by: Austin Clements <austin@google.com>
2019-06-24 12:59:22 -07:00
//
// We disable open-coded defers in buildssa() on 386 ONLY with shared
// libraries because of this extra code added before deferreturn calls.
2025-02-19 16:47:31 -05:00
//
// computeDeferReturn in cmd/link/internal/ld/pcln.go depends
// on the size of these instructions.
2017-03-26 08:05:40 -07:00
if ctxt . Arch . Family == sys . AMD64 || ( p . To . Sym != nil && p . To . Sym . Local ( ) ) || p . RegTo2 != 0 {
2015-11-18 12:30:23 +13:00
return
2015-03-30 00:49:25 +00:00
}
2017-04-04 14:31:55 -07:00
p1 := obj . Appendp ( p , newprog )
p2 := obj . Appendp ( p1 , newprog )
2015-03-30 00:49:25 +00:00
2015-11-18 12:30:23 +13:00
p1 . As = ALEAL
2015-03-30 00:49:25 +00:00
p1 . From . Type = obj . TYPE_MEM
2015-11-18 12:30:23 +13:00
p1 . From . Name = obj . NAME_STATIC
2017-04-20 07:13:02 -07:00
p1 . From . Sym = ctxt . Lookup ( "_GLOBAL_OFFSET_TABLE_" )
2015-03-30 00:49:25 +00:00
p1 . To . Type = obj . TYPE_REG
2015-11-18 12:30:23 +13:00
p1 . To . Reg = REG_BX
2015-03-30 00:49:25 +00:00
p2 . As = p . As
2015-11-18 12:30:23 +13:00
p2 . Scond = p . Scond
2015-03-30 00:49:25 +00:00
p2 . From = p . From
2017-09-13 14:32:08 +03:00
if p . RestArgs != nil {
p2 . RestArgs = append ( p2 . RestArgs , p . RestArgs ... )
}
2015-11-18 12:30:23 +13:00
p2 . Reg = p . Reg
2015-03-30 00:49:25 +00:00
p2 . To = p . To
2015-11-18 12:30:23 +13:00
// p.To.Type was set to TYPE_BRANCH above, but that makes checkaddr
// in ../pass.go complain, so set it back to TYPE_MEM here, until p2
// itself gets passed to progedit.
p2 . To . Type = obj . TYPE_MEM
p2 . RegTo2 = 1
obj . Nopout ( p )
return
}
if p . As == obj . ATEXT || p . As == obj . AFUNCDATA || p . As == obj . ARET || p . As == obj . AJMP {
2015-11-11 15:57:42 +13:00
return
}
if source . Type != obj . TYPE_MEM {
ctxt . Diag ( "don't know how to handle %v with -dynlink" , p )
}
2017-04-04 14:31:55 -07:00
p1 := obj . Appendp ( p , newprog )
p2 := obj . Appendp ( p1 , newprog )
2015-03-30 00:49:25 +00:00
2015-11-18 12:30:23 +13:00
p1 . As = mov
2015-11-11 15:57:42 +13:00
p1 . From . Type = obj . TYPE_MEM
p1 . From . Sym = source . Sym
p1 . From . Name = obj . NAME_GOTREF
p1 . To . Type = obj . TYPE_REG
2015-11-18 12:30:23 +13:00
p1 . To . Reg = reg
2015-03-30 00:49:25 +00:00
2015-11-11 15:57:42 +13:00
p2 . As = p . As
p2 . From = p . From
p2 . To = p . To
2023-02-27 08:53:34 -08:00
if from3 := p . GetFrom3 ( ) ; from3 != nil {
2023-04-12 11:23:13 +08:00
p2 . AddRestSource ( * from3 )
2023-02-27 08:53:34 -08:00
}
2015-11-11 15:57:42 +13:00
if p . From . Name == obj . NAME_EXTERN {
2015-11-18 12:30:23 +13:00
p2 . From . Reg = reg
2015-11-11 15:57:42 +13:00
p2 . From . Name = obj . NAME_NONE
p2 . From . Sym = nil
} else if p . To . Name == obj . NAME_EXTERN {
2015-11-18 12:30:23 +13:00
p2 . To . Reg = reg
2015-11-11 15:57:42 +13:00
p2 . To . Name = obj . NAME_NONE
p2 . To . Sym = nil
} else {
return
2015-03-30 00:49:25 +00:00
}
2015-11-11 15:57:42 +13:00
obj . Nopout ( p )
2015-01-19 14:34:58 -05:00
}
2017-04-04 14:31:55 -07:00
func rewriteToPcrel ( ctxt * obj . Link , p * obj . Prog , newprog obj . ProgAlloc ) {
2015-11-18 12:14:07 +13:00
// RegTo2 is set on the instructions we insert here so they don't get
// processed twice.
if p . RegTo2 != 0 {
return
}
if p . As == obj . ATEXT || p . As == obj . AFUNCDATA || p . As == obj . ACALL || p . As == obj . ARET || p . As == obj . AJMP {
return
}
// Any Prog (aside from the above special cases) with an Addr with Name ==
[dev.ssa] cmd/compile: fix PIC for SSA-generated code
Access to globals requires a 2-instruction sequence on PIC 386.
MOVL foo(SB), AX
is translated by the obj package into:
CALL getPCofNextInstructionInTempRegister(SB)
MOVL (&foo-&thisInstruction)(tmpReg), AX
The call returns the PC of the next instruction in a register.
The next instruction then offsets from that register to get the
address required. The tricky part is the allocation of the
temp register. The legacy compiler always used CX, and forbid
the register allocator from allocating CX when in PIC mode.
We can't easily do that in SSA because CX is actually a required
register for shift instructions. (I think the old backend got away
with this because the register allocator never uses CX, only
codegen knows that shifts must use CX.)
Instead, we allow the temp register to be anything. When the
destination of the MOV (or LEA) is an integer register, we can
use that register. Otherwise, we make sure to compile the
operation using an LEA to reference the global. So
MOVL AX, foo(SB)
is never generated directly. Instead, SSA generates:
LEAL foo(SB), DX
MOVL AX, (DX)
which is then rewritten by the obj package to:
CALL getPcInDX(SB)
LEAL (&foo-&thisInstruction)(DX), AX
MOVL AX, (DX)
So this CL modifies the obj package to use different thunks
to materialize the pc into different registers. We use the
registers that regalloc chose so that SSA can still allocate
the full set of registers.
Change-Id: Ie095644f7164a026c62e95baf9d18a8bcaed0bba
Reviewed-on: https://go-review.googlesource.com/25442
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-08-03 13:00:49 -07:00
// NAME_EXTERN, NAME_STATIC or NAME_GOTREF has a CALL __x86.get_pc_thunk.XX
2015-11-18 12:14:07 +13:00
// inserted before it.
isName := func ( a * obj . Addr ) bool {
if a . Sym == nil || ( a . Type != obj . TYPE_MEM && a . Type != obj . TYPE_ADDR ) || a . Reg != 0 {
return false
}
2017-04-18 12:53:25 -07:00
if a . Sym . Type == objabi . STLSBSS {
2015-11-18 12:14:07 +13:00
return false
}
return a . Name == obj . NAME_EXTERN || a . Name == obj . NAME_STATIC || a . Name == obj . NAME_GOTREF
}
if isName ( & p . From ) && p . From . Type == obj . TYPE_ADDR {
// Handle things like "MOVL $sym, (SP)" or "PUSHL $sym" by rewriting
// to "MOVL $sym, CX; MOVL CX, (SP)" or "MOVL $sym, CX; PUSHL CX"
// respectively.
if p . To . Type != obj . TYPE_REG {
2017-04-04 14:31:55 -07:00
q := obj . Appendp ( p , newprog )
2015-11-18 12:14:07 +13:00
q . As = p . As
q . From . Type = obj . TYPE_REG
q . From . Reg = REG_CX
q . To = p . To
p . As = AMOVL
p . To . Type = obj . TYPE_REG
p . To . Reg = REG_CX
p . To . Sym = nil
p . To . Name = obj . NAME_NONE
2015-03-30 00:49:25 +00:00
}
}
2015-11-18 12:14:07 +13:00
2017-09-13 14:32:08 +03:00
if ! isName ( & p . From ) && ! isName ( & p . To ) && ( p . GetFrom3 ( ) == nil || ! isName ( p . GetFrom3 ( ) ) ) {
2015-11-18 12:14:07 +13:00
return
}
[dev.ssa] cmd/compile: fix PIC for SSA-generated code
Access to globals requires a 2-instruction sequence on PIC 386.
MOVL foo(SB), AX
is translated by the obj package into:
CALL getPCofNextInstructionInTempRegister(SB)
MOVL (&foo-&thisInstruction)(tmpReg), AX
The call returns the PC of the next instruction in a register.
The next instruction then offsets from that register to get the
address required. The tricky part is the allocation of the
temp register. The legacy compiler always used CX, and forbid
the register allocator from allocating CX when in PIC mode.
We can't easily do that in SSA because CX is actually a required
register for shift instructions. (I think the old backend got away
with this because the register allocator never uses CX, only
codegen knows that shifts must use CX.)
Instead, we allow the temp register to be anything. When the
destination of the MOV (or LEA) is an integer register, we can
use that register. Otherwise, we make sure to compile the
operation using an LEA to reference the global. So
MOVL AX, foo(SB)
is never generated directly. Instead, SSA generates:
LEAL foo(SB), DX
MOVL AX, (DX)
which is then rewritten by the obj package to:
CALL getPcInDX(SB)
LEAL (&foo-&thisInstruction)(DX), AX
MOVL AX, (DX)
So this CL modifies the obj package to use different thunks
to materialize the pc into different registers. We use the
registers that regalloc chose so that SSA can still allocate
the full set of registers.
Change-Id: Ie095644f7164a026c62e95baf9d18a8bcaed0bba
Reviewed-on: https://go-review.googlesource.com/25442
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-08-03 13:00:49 -07:00
var dst int16 = REG_CX
2016-08-11 12:56:36 -07:00
if ( p . As == ALEAL || p . As == AMOVL ) && p . To . Reg != p . From . Reg && p . To . Reg != p . From . Index {
dst = p . To . Reg
2017-08-19 22:33:51 +02:00
// Why? See the comment near the top of rewriteToUseGot above.
2016-08-11 12:56:36 -07:00
// AMOVLs might be introduced by the GOT rewrites.
[dev.ssa] cmd/compile: fix PIC for SSA-generated code
Access to globals requires a 2-instruction sequence on PIC 386.
MOVL foo(SB), AX
is translated by the obj package into:
CALL getPCofNextInstructionInTempRegister(SB)
MOVL (&foo-&thisInstruction)(tmpReg), AX
The call returns the PC of the next instruction in a register.
The next instruction then offsets from that register to get the
address required. The tricky part is the allocation of the
temp register. The legacy compiler always used CX, and forbid
the register allocator from allocating CX when in PIC mode.
We can't easily do that in SSA because CX is actually a required
register for shift instructions. (I think the old backend got away
with this because the register allocator never uses CX, only
codegen knows that shifts must use CX.)
Instead, we allow the temp register to be anything. When the
destination of the MOV (or LEA) is an integer register, we can
use that register. Otherwise, we make sure to compile the
operation using an LEA to reference the global. So
MOVL AX, foo(SB)
is never generated directly. Instead, SSA generates:
LEAL foo(SB), DX
MOVL AX, (DX)
which is then rewritten by the obj package to:
CALL getPcInDX(SB)
LEAL (&foo-&thisInstruction)(DX), AX
MOVL AX, (DX)
So this CL modifies the obj package to use different thunks
to materialize the pc into different registers. We use the
registers that regalloc chose so that SSA can still allocate
the full set of registers.
Change-Id: Ie095644f7164a026c62e95baf9d18a8bcaed0bba
Reviewed-on: https://go-review.googlesource.com/25442
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-08-03 13:00:49 -07:00
}
2017-04-04 14:31:55 -07:00
q := obj . Appendp ( p , newprog )
2015-11-18 12:14:07 +13:00
q . RegTo2 = 1
2017-04-04 14:31:55 -07:00
r := obj . Appendp ( q , newprog )
2015-11-18 12:14:07 +13:00
r . RegTo2 = 1
q . As = obj . ACALL
2017-04-06 11:47:33 -07:00
thunkname := "__x86.get_pc_thunk." + strings . ToLower ( rconv ( int ( dst ) ) )
2017-04-20 07:13:02 -07:00
q . To . Sym = ctxt . LookupInit ( thunkname , func ( s * obj . LSym ) { s . Set ( obj . AttrLocal , true ) } )
2015-11-18 12:14:07 +13:00
q . To . Type = obj . TYPE_MEM
q . To . Name = obj . NAME_EXTERN
r . As = p . As
r . Scond = p . Scond
r . From = p . From
2017-09-13 14:32:08 +03:00
r . RestArgs = p . RestArgs
2015-11-18 12:14:07 +13:00
r . Reg = p . Reg
r . To = p . To
[dev.ssa] cmd/compile: fix PIC for SSA-generated code
Access to globals requires a 2-instruction sequence on PIC 386.
MOVL foo(SB), AX
is translated by the obj package into:
CALL getPCofNextInstructionInTempRegister(SB)
MOVL (&foo-&thisInstruction)(tmpReg), AX
The call returns the PC of the next instruction in a register.
The next instruction then offsets from that register to get the
address required. The tricky part is the allocation of the
temp register. The legacy compiler always used CX, and forbid
the register allocator from allocating CX when in PIC mode.
We can't easily do that in SSA because CX is actually a required
register for shift instructions. (I think the old backend got away
with this because the register allocator never uses CX, only
codegen knows that shifts must use CX.)
Instead, we allow the temp register to be anything. When the
destination of the MOV (or LEA) is an integer register, we can
use that register. Otherwise, we make sure to compile the
operation using an LEA to reference the global. So
MOVL AX, foo(SB)
is never generated directly. Instead, SSA generates:
LEAL foo(SB), DX
MOVL AX, (DX)
which is then rewritten by the obj package to:
CALL getPcInDX(SB)
LEAL (&foo-&thisInstruction)(DX), AX
MOVL AX, (DX)
So this CL modifies the obj package to use different thunks
to materialize the pc into different registers. We use the
registers that regalloc chose so that SSA can still allocate
the full set of registers.
Change-Id: Ie095644f7164a026c62e95baf9d18a8bcaed0bba
Reviewed-on: https://go-review.googlesource.com/25442
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-08-03 13:00:49 -07:00
if isName ( & p . From ) {
r . From . Reg = dst
}
if isName ( & p . To ) {
r . To . Reg = dst
}
2017-09-13 14:32:08 +03:00
if p . GetFrom3 ( ) != nil && isName ( p . GetFrom3 ( ) ) {
r . GetFrom3 ( ) . Reg = dst
[dev.ssa] cmd/compile: fix PIC for SSA-generated code
Access to globals requires a 2-instruction sequence on PIC 386.
MOVL foo(SB), AX
is translated by the obj package into:
CALL getPCofNextInstructionInTempRegister(SB)
MOVL (&foo-&thisInstruction)(tmpReg), AX
The call returns the PC of the next instruction in a register.
The next instruction then offsets from that register to get the
address required. The tricky part is the allocation of the
temp register. The legacy compiler always used CX, and forbid
the register allocator from allocating CX when in PIC mode.
We can't easily do that in SSA because CX is actually a required
register for shift instructions. (I think the old backend got away
with this because the register allocator never uses CX, only
codegen knows that shifts must use CX.)
Instead, we allow the temp register to be anything. When the
destination of the MOV (or LEA) is an integer register, we can
use that register. Otherwise, we make sure to compile the
operation using an LEA to reference the global. So
MOVL AX, foo(SB)
is never generated directly. Instead, SSA generates:
LEAL foo(SB), DX
MOVL AX, (DX)
which is then rewritten by the obj package to:
CALL getPcInDX(SB)
LEAL (&foo-&thisInstruction)(DX), AX
MOVL AX, (DX)
So this CL modifies the obj package to use different thunks
to materialize the pc into different registers. We use the
registers that regalloc chose so that SSA can still allocate
the full set of registers.
Change-Id: Ie095644f7164a026c62e95baf9d18a8bcaed0bba
Reviewed-on: https://go-review.googlesource.com/25442
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-08-03 13:00:49 -07:00
}
2015-11-18 12:14:07 +13:00
obj . Nopout ( p )
2015-01-19 14:34:58 -05:00
}
2021-01-13 15:45:28 -08:00
// Prog.mark
const (
markBit = 1 << 0 // used in errorCheck to avoid duplicate work
)
2017-04-04 14:31:55 -07:00
func preprocess ( ctxt * obj . Link , cursym * obj . LSym , newprog obj . ProgAlloc ) {
2020-07-19 00:30:12 -04:00
if cursym . Func ( ) . Text == nil || cursym . Func ( ) . Text . Link == nil {
2015-01-19 14:34:58 -05:00
return
}
2020-07-19 00:30:12 -04:00
p := cursym . Func ( ) . Text
2015-03-02 12:35:15 -05:00
autoffset := int32 ( p . To . Offset )
2015-01-19 14:34:58 -05:00
if autoffset < 0 {
autoffset = 0
}
2016-11-30 16:15:32 -08:00
hasCall := false
for q := p ; q != nil ; q = q . Link {
if q . As == obj . ACALL || q . As == obj . ADUFFCOPY || q . As == obj . ADUFFZERO {
hasCall = true
break
}
}
2015-03-02 12:35:15 -05:00
var bpsize int
2020-08-21 11:09:45 -07:00
if ctxt . Arch . Family == sys . AMD64 &&
cmd/internal/obj: stop storing Text flags in From3
Prior to this CL, flags such as NOSPLIT
on ATEXT Progs were stored in From3.Offset.
Some but not all of those flags were also
duplicated into From.Sym.Attribute.
This CL migrates all of those flags into
From.Sym.Attribute and stops creating a From3.
A side-effect of this is that printing an
ATEXT Prog can no longer simply dump From3.Offset.
That's kind of good, since the raw flag value
wasn't very informative anyway, but it did
necessitate a bunch of updates to the cmd/asm tests.
The reason I'm doing this work now is that
avoiding storing flags in both From.Sym and From3.Offset
simplifies some other changes to fix the data
race first described in CL 40254.
This CL almost passes toolstash-check -all.
The only changes are in cases where the assembler
has decided that a function's flags may be altered,
e.g. to make a function with no calls in it NOSPLIT.
Prior to this CL, that information was not printed.
Sample before:
"".Ctz64 t=1 size=63 args=0x10 locals=0x0
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) TEXT "".Ctz64(SB), $0-16
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) FUNCDATA $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
Sample after:
"".Ctz64 t=1 nosplit size=63 args=0x10 locals=0x0
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) TEXT "".Ctz64(SB), NOSPLIT, $0-16
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) FUNCDATA $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
Observe the additional "nosplit" in the first line
and the additional "NOSPLIT" in the second line.
Updates #15756
Change-Id: I5c59bd8f3bdc7c780361f801d94a261f0aef3d13
Reviewed-on: https://go-review.googlesource.com/40495
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-04-11 15:15:04 -07:00
! p . From . Sym . NoFrame ( ) && // (1) below
2023-02-08 16:51:34 +01:00
! ( autoffset == 0 && ! hasCall ) { // (2) below
2016-11-30 16:15:32 -08:00
// Make room to save a base pointer.
// There are 2 cases we must avoid:
// 1) If noframe is set (which we do for functions which tail call).
// For performance, we also want to avoid:
2023-02-08 16:51:34 +01:00
// 2) Frameless leaf functions
2016-04-06 12:01:40 -07:00
bpsize = ctxt . Arch . PtrSize
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
autoffset += int32 ( bpsize )
p . To . Offset += int64 ( bpsize )
} else {
bpsize = 0
2023-01-16 16:21:48 +01:00
p . From . Sym . Set ( obj . AttrNoFrame , true )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
}
2015-03-16 15:54:44 -04:00
textarg := int64 ( p . To . Val . ( int32 ) )
2020-07-19 00:30:12 -04:00
cursym . Func ( ) . Args = int32 ( textarg )
cursym . Func ( ) . Locals = int32 ( p . To . Offset )
2015-01-19 14:34:58 -05:00
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
// TODO(rsc): Remove.
2020-07-19 00:30:12 -04:00
if ctxt . Arch . Family == sys . I386 && cursym . Func ( ) . Locals < 0 {
cursym . Func ( ) . Locals = 0
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
}
2017-03-26 08:05:40 -07:00
// TODO(rsc): Remove 'ctxt.Arch.Family == sys.AMD64 &&'.
2023-04-19 13:21:02 -04:00
if ctxt . Arch . Family == sys . AMD64 && autoffset < abi . StackSmall && ! p . From . Sym . NoSplit ( ) {
2016-07-07 16:21:53 -07:00
leaf := true
LeafSearch :
2015-03-02 12:35:15 -05:00
for q := p ; q != nil ; q = q . Link {
2016-07-07 16:21:53 -07:00
switch q . As {
case obj . ACALL :
cmd/compile/internal/obj/x86: eliminate some function prologues
The standard sort swap method
func (t T) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
uses no stack space on architectures for which
FixedFrameSize == 0, currently 386 and amd64.
Nevertheless, we insert a stack check prologue.
This is because it contains a call to
runtime.panicindex.
However, for a few common runtime functions,
we know at compile time that they require
no arguments. Allow them to pass unnoticed.
Triggers for 380 functions during make.bash.
Cuts 4k off cmd/go.
encoding/binary benchmarks:
ReadSlice1000Int32s-8 9.49µs ± 3% 9.41µs ± 5% ~ (p=0.075 n=29+27)
ReadStruct-8 1.50µs ± 3% 1.48µs ± 2% -1.49% (p=0.000 n=30+28)
ReadInts-8 599ns ± 3% 600ns ± 3% ~ (p=0.471 n=30+29)
WriteInts-8 836ns ± 4% 841ns ± 3% ~ (p=0.371 n=30+29)
WriteSlice1000Int32s-8 8.84µs ± 3% 8.69µs ± 5% -1.71% (p=0.001 n=30+30)
PutUvarint32-8 29.6ns ± 1% 28.1ns ± 3% -5.21% (p=0.000 n=28+28)
PutUvarint64-8 82.6ns ± 5% 82.3ns ±10% -0.43% (p=0.014 n=27+30)
Swap assembly before:
"".T.Swap t=1 size=74 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) MOVQ (TLS), CX
0x0009 00009 (swap.go:5) CMPQ SP, 16(CX)
0x000d 00013 (swap.go:5) JLS 67
0x000f 00015 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x000f 00015 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x000f 00015 (swap.go:5) MOVQ "".i+32(FP), AX
0x0014 00020 (swap.go:5) MOVQ "".t+16(FP), CX
0x0019 00025 (swap.go:5) CMPQ AX, CX
0x001c 00028 (swap.go:5) JCC $0, 60
0x001e 00030 (swap.go:5) MOVQ "".t+8(FP), DX
0x0023 00035 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0027 00039 (swap.go:5) MOVQ "".j+40(FP), SI
0x002c 00044 (swap.go:5) CMPQ SI, CX
0x002f 00047 (swap.go:5) JCC $0, 60
0x0031 00049 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0035 00053 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0038 00056 (swap.go:5) MOVB BL, (DX)(SI*1)
0x003b 00059 (swap.go:5) RET
0x003c 00060 (swap.go:5) PCDATA $0, $1
0x003c 00060 (swap.go:5) CALL runtime.panicindex(SB)
0x0041 00065 (swap.go:5) UNDEF
0x0043 00067 (swap.go:5) NOP
0x0043 00067 (swap.go:5) CALL runtime.morestack_noctxt(SB)
0x0048 00072 (swap.go:5) JMP 0
Swap assembly after:
"".T.Swap t=1 size=52 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x0000 00000 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x0000 00000 (swap.go:5) MOVQ "".i+32(FP), AX
0x0005 00005 (swap.go:5) MOVQ "".t+16(FP), CX
0x000a 00010 (swap.go:5) CMPQ AX, CX
0x000d 00013 (swap.go:5) JCC $0, 45
0x000f 00015 (swap.go:5) MOVQ "".t+8(FP), DX
0x0014 00020 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0018 00024 (swap.go:5) MOVQ "".j+40(FP), SI
0x001d 00029 (swap.go:5) CMPQ SI, CX
0x0020 00032 (swap.go:5) JCC $0, 45
0x0022 00034 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0026 00038 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0029 00041 (swap.go:5) MOVB BL, (DX)(SI*1)
0x002c 00044 (swap.go:5) RET
0x002d 00045 (swap.go:5) PCDATA $0, $1
0x002d 00045 (swap.go:5) CALL runtime.panicindex(SB)
0x0032 00050 (swap.go:5) UNDEF
Change-Id: I57dad14af8aaa5e6112deac407cfadc2bfaf1f54
Reviewed-on: https://go-review.googlesource.com/24814
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-07 16:50:46 -07:00
// Treat common runtime calls that take no arguments
// the same as duffcopy and duffzero.
2025-06-18 15:14:00 -07:00
// Note that of these functions, panicBounds does
// use some stack, but its stack together with the
// < StackSmall used by this function is still
// less than stackNosplit. See issue 31219.
cmd/compile/internal/obj/x86: eliminate some function prologues
The standard sort swap method
func (t T) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
uses no stack space on architectures for which
FixedFrameSize == 0, currently 386 and amd64.
Nevertheless, we insert a stack check prologue.
This is because it contains a call to
runtime.panicindex.
However, for a few common runtime functions,
we know at compile time that they require
no arguments. Allow them to pass unnoticed.
Triggers for 380 functions during make.bash.
Cuts 4k off cmd/go.
encoding/binary benchmarks:
ReadSlice1000Int32s-8 9.49µs ± 3% 9.41µs ± 5% ~ (p=0.075 n=29+27)
ReadStruct-8 1.50µs ± 3% 1.48µs ± 2% -1.49% (p=0.000 n=30+28)
ReadInts-8 599ns ± 3% 600ns ± 3% ~ (p=0.471 n=30+29)
WriteInts-8 836ns ± 4% 841ns ± 3% ~ (p=0.371 n=30+29)
WriteSlice1000Int32s-8 8.84µs ± 3% 8.69µs ± 5% -1.71% (p=0.001 n=30+30)
PutUvarint32-8 29.6ns ± 1% 28.1ns ± 3% -5.21% (p=0.000 n=28+28)
PutUvarint64-8 82.6ns ± 5% 82.3ns ±10% -0.43% (p=0.014 n=27+30)
Swap assembly before:
"".T.Swap t=1 size=74 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) MOVQ (TLS), CX
0x0009 00009 (swap.go:5) CMPQ SP, 16(CX)
0x000d 00013 (swap.go:5) JLS 67
0x000f 00015 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x000f 00015 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x000f 00015 (swap.go:5) MOVQ "".i+32(FP), AX
0x0014 00020 (swap.go:5) MOVQ "".t+16(FP), CX
0x0019 00025 (swap.go:5) CMPQ AX, CX
0x001c 00028 (swap.go:5) JCC $0, 60
0x001e 00030 (swap.go:5) MOVQ "".t+8(FP), DX
0x0023 00035 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0027 00039 (swap.go:5) MOVQ "".j+40(FP), SI
0x002c 00044 (swap.go:5) CMPQ SI, CX
0x002f 00047 (swap.go:5) JCC $0, 60
0x0031 00049 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0035 00053 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0038 00056 (swap.go:5) MOVB BL, (DX)(SI*1)
0x003b 00059 (swap.go:5) RET
0x003c 00060 (swap.go:5) PCDATA $0, $1
0x003c 00060 (swap.go:5) CALL runtime.panicindex(SB)
0x0041 00065 (swap.go:5) UNDEF
0x0043 00067 (swap.go:5) NOP
0x0043 00067 (swap.go:5) CALL runtime.morestack_noctxt(SB)
0x0048 00072 (swap.go:5) JMP 0
Swap assembly after:
"".T.Swap t=1 size=52 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x0000 00000 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x0000 00000 (swap.go:5) MOVQ "".i+32(FP), AX
0x0005 00005 (swap.go:5) MOVQ "".t+16(FP), CX
0x000a 00010 (swap.go:5) CMPQ AX, CX
0x000d 00013 (swap.go:5) JCC $0, 45
0x000f 00015 (swap.go:5) MOVQ "".t+8(FP), DX
0x0014 00020 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0018 00024 (swap.go:5) MOVQ "".j+40(FP), SI
0x001d 00029 (swap.go:5) CMPQ SI, CX
0x0020 00032 (swap.go:5) JCC $0, 45
0x0022 00034 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0026 00038 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0029 00041 (swap.go:5) MOVB BL, (DX)(SI*1)
0x002c 00044 (swap.go:5) RET
0x002d 00045 (swap.go:5) PCDATA $0, $1
0x002d 00045 (swap.go:5) CALL runtime.panicindex(SB)
0x0032 00050 (swap.go:5) UNDEF
Change-Id: I57dad14af8aaa5e6112deac407cfadc2bfaf1f54
Reviewed-on: https://go-review.googlesource.com/24814
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-07 16:50:46 -07:00
if ! isZeroArgRuntimeCall ( q . To . Sym ) {
leaf = false
break LeafSearch
}
fallthrough
2016-07-07 16:21:53 -07:00
case obj . ADUFFCOPY , obj . ADUFFZERO :
2023-04-19 13:21:02 -04:00
if autoffset >= abi . StackSmall - 8 {
2016-07-07 16:21:53 -07:00
leaf = false
break LeafSearch
}
2015-01-19 14:34:58 -05:00
}
}
2016-07-07 16:21:53 -07:00
if leaf {
cmd/internal/obj: stop storing Text flags in From3
Prior to this CL, flags such as NOSPLIT
on ATEXT Progs were stored in From3.Offset.
Some but not all of those flags were also
duplicated into From.Sym.Attribute.
This CL migrates all of those flags into
From.Sym.Attribute and stops creating a From3.
A side-effect of this is that printing an
ATEXT Prog can no longer simply dump From3.Offset.
That's kind of good, since the raw flag value
wasn't very informative anyway, but it did
necessitate a bunch of updates to the cmd/asm tests.
The reason I'm doing this work now is that
avoiding storing flags in both From.Sym and From3.Offset
simplifies some other changes to fix the data
race first described in CL 40254.
This CL almost passes toolstash-check -all.
The only changes are in cases where the assembler
has decided that a function's flags may be altered,
e.g. to make a function with no calls in it NOSPLIT.
Prior to this CL, that information was not printed.
Sample before:
"".Ctz64 t=1 size=63 args=0x10 locals=0x0
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) TEXT "".Ctz64(SB), $0-16
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) FUNCDATA $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
Sample after:
"".Ctz64 t=1 nosplit size=63 args=0x10 locals=0x0
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) TEXT "".Ctz64(SB), NOSPLIT, $0-16
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) FUNCDATA $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
Observe the additional "nosplit" in the first line
and the additional "NOSPLIT" in the second line.
Updates #15756
Change-Id: I5c59bd8f3bdc7c780361f801d94a261f0aef3d13
Reviewed-on: https://go-review.googlesource.com/40495
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-04-11 15:15:04 -07:00
p . From . Sym . Set ( obj . AttrNoSplit , true )
2016-07-07 16:21:53 -07:00
}
2015-01-19 14:34:58 -05:00
}
2019-08-20 17:39:09 -04:00
if ! p . From . Sym . NoSplit ( ) {
2025-07-01 15:00:13 -07:00
// Emit split check.
p = stacksplit ( ctxt , cursym , p , newprog , autoffset , int32 ( textarg ) )
2015-01-19 14:34:58 -05:00
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if bpsize > 0 {
// Save caller's BP
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
cmd/internal/obj/x86: use push/pop instead of mov to store/load FP
This CL changes how the x86 compiler stores and loads the frame pointer
on each function prologue and epilogue, with the goal to reduce the
final binary size without affecting performance.
The compiler is currently using MOV instructions to load and store BP,
which can take from 5 to 8 bytes each.
This CL changes this approach so it emits PUSH/POP instructions instead,
which always take only 1 byte each (when operating with BP). It can also
avoid using the SUBQ/ADDQ to grow the stack for functions that have
frame pointer but does not have local variables.
On Windows, this CL reduces the go toolchain size from 15,697,920 bytes
to 15,584,768 bytes, a reduction of 0.7%.
Example of epilog and prologue for a function with 0x10 bytes of
local variables:
Before
===
SUBQ $0x18, SP
MOVQ BP, 0x10(SP)
LEAQ 0x10(SP), BP
... function body ...
MOVQ 0x10(SP), BP
ADDQ $0x18, SP
RET
===
After
===
PUSHQ BP
LEAQ 0(SP), BP
SUBQ $0x10, SP
... function body ...
MOVQ ADDQ $0x10, SP
POPQ BP
RET
===
Updates #6853
Change-Id: Ice9e14bbf8dff083c5f69feb97e9a764c3ca7785
Reviewed-on: https://go-review.googlesource.com/c/go/+/462300
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
2023-01-19 16:17:56 +01:00
p . As = APUSHQ
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_REG
p . From . Reg = REG_BP
// Move current frame to BP
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
2023-01-31 17:04:08 +01:00
p . As = AMOVQ
p . From . Type = obj . TYPE_REG
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Reg = REG_SP
p . To . Type = obj . TYPE_REG
p . To . Reg = REG_BP
}
cmd/internal/obj/x86: use push/pop instead of mov to store/load FP
This CL changes how the x86 compiler stores and loads the frame pointer
on each function prologue and epilogue, with the goal to reduce the
final binary size without affecting performance.
The compiler is currently using MOV instructions to load and store BP,
which can take from 5 to 8 bytes each.
This CL changes this approach so it emits PUSH/POP instructions instead,
which always take only 1 byte each (when operating with BP). It can also
avoid using the SUBQ/ADDQ to grow the stack for functions that have
frame pointer but does not have local variables.
On Windows, this CL reduces the go toolchain size from 15,697,920 bytes
to 15,584,768 bytes, a reduction of 0.7%.
Example of epilog and prologue for a function with 0x10 bytes of
local variables:
Before
===
SUBQ $0x18, SP
MOVQ BP, 0x10(SP)
LEAQ 0x10(SP), BP
... function body ...
MOVQ 0x10(SP), BP
ADDQ $0x18, SP
RET
===
After
===
PUSHQ BP
LEAQ 0(SP), BP
SUBQ $0x10, SP
... function body ...
MOVQ ADDQ $0x10, SP
POPQ BP
RET
===
Updates #6853
Change-Id: Ice9e14bbf8dff083c5f69feb97e9a764c3ca7785
Reviewed-on: https://go-review.googlesource.com/c/go/+/462300
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
2023-01-19 16:17:56 +01:00
if autoffset % int32 ( ctxt . Arch . RegSize ) != 0 {
ctxt . Diag ( "unaligned stack size %d" , autoffset )
}
// localoffset is autoffset discounting the frame pointer,
// which has already been allocated in the stack.
localoffset := autoffset - int32 ( bpsize )
if localoffset != 0 {
p = obj . Appendp ( p , newprog )
p . As = AADJSP
p . From . Type = obj . TYPE_CONST
p . From . Offset = int64 ( localoffset )
p . Spadj = localoffset
}
// Delve debugger would like the next instruction to be noted as the end of the function prologue.
// TODO: are there other cases (e.g., wrapper functions) that need marking?
if autoffset != 0 {
p . Pos = p . Pos . WithXlogue ( src . PosPrologueEnd )
}
cmd/internal/obj/x86: correct pcsp for ADJSP
The x86 assembler supports an "ADJSP" pseudo-op that compiles to an
ADD/SUB from SP. Unfortunately, while this seems perfect for an
instruction that would allow obj to continue to track the SP/FP delta,
obj currently doesn't do that. As a result, FP-relative references
won't work and, perhaps worse, the pcsp table will have the wrong
frame size.
We don't currently use this instruction in any assembly or generate it
in the compiler, but this is a perfect instruction for solving a
problem in #24543.
This CL makes ADJSP useful by incorporating it into the SP delta
logic.
One subtlety is that we do generate ADJSP in obj itself to open a
function's stack frame. Currently, when preprocess enters the loop to
compute the SP delta, it may or may not start at this ADJSP
instruction depending on various factors. We clean this up by instead
always starting the SP delta at 0 and always starting this loop at the
entry to the function.
Why not just recognize ADD/SUB of SP? The danger is that could change
the meaning of existing code. For example, walltime1 in
sys_linux_amd64.s saves SP, SUBs from it, and aligns it. Later, it
restores the saved copy and then does a few FP-relative references.
Currently obj doesn't know any of this is happening, but that's fine
once it gets to the FP-relative references. If we taught obj to
recognize the SUB, it would start to miscompile this code. An
alternative would be to recognize unknown instructions that write to
SP and refuse subsequent FP-relative references, but that's kind of
annoying.
This passes toolstash -cmp for std on both amd64 and 386.
Change-Id: Ic6c6a7cbf980bca904576676c07b44c0aaa9c82d
Reviewed-on: https://go-review.googlesource.com/c/go/+/200877
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2019-10-12 18:35:49 -04:00
var deltasp int32
2020-07-19 00:30:12 -04:00
for p = cursym . Func ( ) . Text ; p != nil ; p = p . Link {
2017-03-26 08:05:40 -07:00
pcsize := ctxt . Arch . RegSize
2016-07-20 10:18:23 -07:00
switch p . From . Name {
case obj . NAME_AUTO :
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Offset += int64 ( deltasp ) - int64 ( bpsize )
2016-07-20 10:18:23 -07:00
case obj . NAME_PARAM :
2015-01-19 14:34:58 -05:00
p . From . Offset += int64 ( deltasp ) + int64 ( pcsize )
}
2017-09-13 14:32:08 +03:00
if p . GetFrom3 ( ) != nil {
switch p . GetFrom3 ( ) . Name {
2016-07-20 10:18:23 -07:00
case obj . NAME_AUTO :
2017-09-13 14:32:08 +03:00
p . GetFrom3 ( ) . Offset += int64 ( deltasp ) - int64 ( bpsize )
2016-07-20 10:18:23 -07:00
case obj . NAME_PARAM :
2017-09-13 14:32:08 +03:00
p . GetFrom3 ( ) . Offset += int64 ( deltasp ) + int64 ( pcsize )
2015-05-27 15:01:44 -04:00
}
2015-03-05 00:50:38 -05:00
}
2016-07-20 10:18:23 -07:00
switch p . To . Name {
case obj . NAME_AUTO :
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Offset += int64 ( deltasp ) - int64 ( bpsize )
2016-07-20 10:18:23 -07:00
case obj . NAME_PARAM :
2015-01-19 14:34:58 -05:00
p . To . Offset += int64 ( deltasp ) + int64 ( pcsize )
}
switch p . As {
default :
cmd/asm, cmd/link, runtime: introduce FuncInfo flag bits
The runtime traceback code has its own definition of which functions
mark the top frame of a stack, separate from the TOPFRAME bits that
exist in the assembly and are passed along in DWARF information.
It's error-prone and redundant to have two different sources of truth.
This CL provides the actual TOPFRAME bits to the runtime, so that
the runtime can use those bits instead of reinventing its own category.
This CL also adds a new bit, SPWRITE, which marks functions that
write directly to SP (anything but adding and subtracting constants).
Such functions must stop a traceback, because the traceback has no
way to rederive the SP on entry. Again, the runtime has its own definition
which is mostly correct, but also missing some functions. During ordinary
goroutine context switches, such functions do not appear on the stack,
so the incompleteness in the runtime usually doesn't matter.
But profiling signals can arrive at any moment, and the runtime may
crash during traceback if it attempts to unwind an SP-writing frame
and gets out-of-sync with the actual stack. The runtime contains code
to try to detect likely candidates but again it is incomplete.
Deriving the SPWRITE bit automatically from the actual assembly code
provides the complete truth, and passing it to the runtime lets the
runtime use it.
This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
This CL is, however, not windows/arm64-specific.
It is cleanup meant to make the port (and future ports) easier.
Change-Id: I227f53b23ac5b3dabfcc5e8ee3f00df4e113cf58
Reviewed-on: https://go-review.googlesource.com/c/go/+/288800
Trust: Russ Cox <rsc@golang.org>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-28 15:21:33 -05:00
if p . To . Type == obj . TYPE_REG && p . To . Reg == REG_SP && p . As != ACMPL && p . As != ACMPQ {
f := cursym . Func ( )
2023-04-17 15:58:47 -04:00
if f . FuncFlag & abi . FuncFlagSPWrite == 0 {
f . FuncFlag |= abi . FuncFlagSPWrite
cmd/asm, cmd/link, runtime: introduce FuncInfo flag bits
The runtime traceback code has its own definition of which functions
mark the top frame of a stack, separate from the TOPFRAME bits that
exist in the assembly and are passed along in DWARF information.
It's error-prone and redundant to have two different sources of truth.
This CL provides the actual TOPFRAME bits to the runtime, so that
the runtime can use those bits instead of reinventing its own category.
This CL also adds a new bit, SPWRITE, which marks functions that
write directly to SP (anything but adding and subtracting constants).
Such functions must stop a traceback, because the traceback has no
way to rederive the SP on entry. Again, the runtime has its own definition
which is mostly correct, but also missing some functions. During ordinary
goroutine context switches, such functions do not appear on the stack,
so the incompleteness in the runtime usually doesn't matter.
But profiling signals can arrive at any moment, and the runtime may
crash during traceback if it attempts to unwind an SP-writing frame
and gets out-of-sync with the actual stack. The runtime contains code
to try to detect likely candidates but again it is incomplete.
Deriving the SPWRITE bit automatically from the actual assembly code
provides the complete truth, and passing it to the runtime lets the
runtime use it.
This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
This CL is, however, not windows/arm64-specific.
It is cleanup meant to make the port (and future ports) easier.
Change-Id: I227f53b23ac5b3dabfcc5e8ee3f00df4e113cf58
Reviewed-on: https://go-review.googlesource.com/c/go/+/288800
Trust: Russ Cox <rsc@golang.org>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-28 15:21:33 -05:00
if ctxt . Debugvlog || ! ctxt . IsAsm {
ctxt . Logf ( "auto-SPWRITE: %s %v\n" , cursym . Name , p )
if ! ctxt . IsAsm {
ctxt . Diag ( "invalid auto-SPWRITE in non-assembly" )
ctxt . DiagFlush ( )
log . Fatalf ( "bad SPWRITE" )
}
}
}
}
2015-01-19 14:34:58 -05:00
continue
2015-04-01 09:38:44 -07:00
case APUSHL , APUSHFL :
2015-01-19 14:34:58 -05:00
deltasp += 4
p . Spadj = 4
continue
2015-04-01 09:38:44 -07:00
case APUSHQ , APUSHFQ :
2015-01-19 14:34:58 -05:00
deltasp += 8
p . Spadj = 8
continue
2015-04-01 09:38:44 -07:00
case APUSHW , APUSHFW :
2015-01-19 14:34:58 -05:00
deltasp += 2
p . Spadj = 2
continue
2015-04-01 09:38:44 -07:00
case APOPL , APOPFL :
2015-01-19 14:34:58 -05:00
deltasp -= 4
p . Spadj = - 4
continue
2015-04-01 09:38:44 -07:00
case APOPQ , APOPFQ :
2015-01-19 14:34:58 -05:00
deltasp -= 8
p . Spadj = - 8
continue
2015-04-01 09:38:44 -07:00
case APOPW , APOPFW :
2015-01-19 14:34:58 -05:00
deltasp -= 2
p . Spadj = - 2
continue
cmd/internal/obj/x86: correct pcsp for ADJSP
The x86 assembler supports an "ADJSP" pseudo-op that compiles to an
ADD/SUB from SP. Unfortunately, while this seems perfect for an
instruction that would allow obj to continue to track the SP/FP delta,
obj currently doesn't do that. As a result, FP-relative references
won't work and, perhaps worse, the pcsp table will have the wrong
frame size.
We don't currently use this instruction in any assembly or generate it
in the compiler, but this is a perfect instruction for solving a
problem in #24543.
This CL makes ADJSP useful by incorporating it into the SP delta
logic.
One subtlety is that we do generate ADJSP in obj itself to open a
function's stack frame. Currently, when preprocess enters the loop to
compute the SP delta, it may or may not start at this ADJSP
instruction depending on various factors. We clean this up by instead
always starting the SP delta at 0 and always starting this loop at the
entry to the function.
Why not just recognize ADD/SUB of SP? The danger is that could change
the meaning of existing code. For example, walltime1 in
sys_linux_amd64.s saves SP, SUBs from it, and aligns it. Later, it
restores the saved copy and then does a few FP-relative references.
Currently obj doesn't know any of this is happening, but that's fine
once it gets to the FP-relative references. If we taught obj to
recognize the SUB, it would start to miscompile this code. An
alternative would be to recognize unknown instructions that write to
SP and refuse subsequent FP-relative references, but that's kind of
annoying.
This passes toolstash -cmp for std on both amd64 and 386.
Change-Id: Ic6c6a7cbf980bca904576676c07b44c0aaa9c82d
Reviewed-on: https://go-review.googlesource.com/c/go/+/200877
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2019-10-12 18:35:49 -04:00
case AADJSP :
p . Spadj = int32 ( p . From . Offset )
deltasp += int32 ( p . From . Offset )
continue
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
case obj . ARET :
2016-07-20 10:18:23 -07:00
// do nothing
2015-01-19 14:34:58 -05:00
}
if autoffset != deltasp {
2021-04-13 09:06:50 -04:00
ctxt . Diag ( "%s: unbalanced PUSH/POP" , cursym )
2015-01-19 14:34:58 -05:00
}
if autoffset != 0 {
cmd/internal/obj/x86: adjust SP correctly for tail calls
Currently, tail calls on x86 don't adjust the SP on return, so it's
important that the compiler produce a zero-sized frame and disable the
frame pointer. However, these constraints aren't necessary. For
example, on other architectures it's generally necessary to restore
the saved LR before a tail call, so obj simply makes this work.
Likewise, on x86, there's no reason we can't simply make this work.
Hence, this CL adjusts the compiler to use the same tail call
convention for x86 that we use on LR machines by producing a RET with
a target, rather than a JMP with a target. In fact, obj already
understands this convention for x86 except that it's buggy with
non-zero frame sizes. So we also fix this bug obj. As a result of
these fixes, the compiler no longer needs to mark wrappers as
NoFramePointer since it's now perfectly fine to save the frame
pointer.
In fact, this eliminates the only use of NoFramePointer in the
compiler, which will enable further cleanups.
This also fixes what is very nearly, but not quite, a code generation
bug. NoFramePointer becomes obj.NOFRAME in the object file, which on
ppc64 and s390x means to omit the saved LR. Hence, on these
architectures, NoFramePointer (and NOFRAME) is only safe to set on
leaf functions. However, on *most* architectures, wrappers aren't
necessarily leaf functions because they may call DUFFZERO. We're saved
on ppc64 and s390x only because the compiler doesn't have the rules to
produce DUFFZERO calls on these architectures. Hence, this only works
because the set of LR architectures that implement NOFRAME is disjoint
from the set where the compiler produces DUFFZERO operations. (I
discovered this whole mess when I attempted to add NOFRAME support to
arm.)
Change-Id: Icc589aeb86beacb850d0a6a80bd3024974a33947
Reviewed-on: https://go-review.googlesource.com/92035
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2018-01-25 11:35:27 -05:00
to := p . To // Keep To attached to RET for retjmp below
p . To = obj . Addr { }
cmd/internal/obj/x86: use push/pop instead of mov to store/load FP
This CL changes how the x86 compiler stores and loads the frame pointer
on each function prologue and epilogue, with the goal to reduce the
final binary size without affecting performance.
The compiler is currently using MOV instructions to load and store BP,
which can take from 5 to 8 bytes each.
This CL changes this approach so it emits PUSH/POP instructions instead,
which always take only 1 byte each (when operating with BP). It can also
avoid using the SUBQ/ADDQ to grow the stack for functions that have
frame pointer but does not have local variables.
On Windows, this CL reduces the go toolchain size from 15,697,920 bytes
to 15,584,768 bytes, a reduction of 0.7%.
Example of epilog and prologue for a function with 0x10 bytes of
local variables:
Before
===
SUBQ $0x18, SP
MOVQ BP, 0x10(SP)
LEAQ 0x10(SP), BP
... function body ...
MOVQ 0x10(SP), BP
ADDQ $0x18, SP
RET
===
After
===
PUSHQ BP
LEAQ 0(SP), BP
SUBQ $0x10, SP
... function body ...
MOVQ ADDQ $0x10, SP
POPQ BP
RET
===
Updates #6853
Change-Id: Ice9e14bbf8dff083c5f69feb97e9a764c3ca7785
Reviewed-on: https://go-review.googlesource.com/c/go/+/462300
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
2023-01-19 16:17:56 +01:00
if localoffset != 0 {
p . As = AADJSP
p . From . Type = obj . TYPE_CONST
p . From . Offset = int64 ( - localoffset )
p . Spadj = - localoffset
p = obj . Appendp ( p , newprog )
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if bpsize > 0 {
// Restore caller's BP
cmd/internal/obj/x86: use push/pop instead of mov to store/load FP
This CL changes how the x86 compiler stores and loads the frame pointer
on each function prologue and epilogue, with the goal to reduce the
final binary size without affecting performance.
The compiler is currently using MOV instructions to load and store BP,
which can take from 5 to 8 bytes each.
This CL changes this approach so it emits PUSH/POP instructions instead,
which always take only 1 byte each (when operating with BP). It can also
avoid using the SUBQ/ADDQ to grow the stack for functions that have
frame pointer but does not have local variables.
On Windows, this CL reduces the go toolchain size from 15,697,920 bytes
to 15,584,768 bytes, a reduction of 0.7%.
Example of epilog and prologue for a function with 0x10 bytes of
local variables:
Before
===
SUBQ $0x18, SP
MOVQ BP, 0x10(SP)
LEAQ 0x10(SP), BP
... function body ...
MOVQ 0x10(SP), BP
ADDQ $0x18, SP
RET
===
After
===
PUSHQ BP
LEAQ 0(SP), BP
SUBQ $0x10, SP
... function body ...
MOVQ ADDQ $0x10, SP
POPQ BP
RET
===
Updates #6853
Change-Id: Ice9e14bbf8dff083c5f69feb97e9a764c3ca7785
Reviewed-on: https://go-review.googlesource.com/c/go/+/462300
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
2023-01-19 16:17:56 +01:00
p . As = APOPQ
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Type = obj . TYPE_REG
p . To . Reg = REG_BP
cmd/internal/obj/x86: use push/pop instead of mov to store/load FP
This CL changes how the x86 compiler stores and loads the frame pointer
on each function prologue and epilogue, with the goal to reduce the
final binary size without affecting performance.
The compiler is currently using MOV instructions to load and store BP,
which can take from 5 to 8 bytes each.
This CL changes this approach so it emits PUSH/POP instructions instead,
which always take only 1 byte each (when operating with BP). It can also
avoid using the SUBQ/ADDQ to grow the stack for functions that have
frame pointer but does not have local variables.
On Windows, this CL reduces the go toolchain size from 15,697,920 bytes
to 15,584,768 bytes, a reduction of 0.7%.
Example of epilog and prologue for a function with 0x10 bytes of
local variables:
Before
===
SUBQ $0x18, SP
MOVQ BP, 0x10(SP)
LEAQ 0x10(SP), BP
... function body ...
MOVQ 0x10(SP), BP
ADDQ $0x18, SP
RET
===
After
===
PUSHQ BP
LEAQ 0(SP), BP
SUBQ $0x10, SP
... function body ...
MOVQ ADDQ $0x10, SP
POPQ BP
RET
===
Updates #6853
Change-Id: Ice9e14bbf8dff083c5f69feb97e9a764c3ca7785
Reviewed-on: https://go-review.googlesource.com/c/go/+/462300
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
2023-01-19 16:17:56 +01:00
p . Spadj = - int32 ( bpsize )
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
}
p . As = obj . ARET
cmd/internal/obj/x86: adjust SP correctly for tail calls
Currently, tail calls on x86 don't adjust the SP on return, so it's
important that the compiler produce a zero-sized frame and disable the
frame pointer. However, these constraints aren't necessary. For
example, on other architectures it's generally necessary to restore
the saved LR before a tail call, so obj simply makes this work.
Likewise, on x86, there's no reason we can't simply make this work.
Hence, this CL adjusts the compiler to use the same tail call
convention for x86 that we use on LR machines by producing a RET with
a target, rather than a JMP with a target. In fact, obj already
understands this convention for x86 except that it's buggy with
non-zero frame sizes. So we also fix this bug obj. As a result of
these fixes, the compiler no longer needs to mark wrappers as
NoFramePointer since it's now perfectly fine to save the frame
pointer.
In fact, this eliminates the only use of NoFramePointer in the
compiler, which will enable further cleanups.
This also fixes what is very nearly, but not quite, a code generation
bug. NoFramePointer becomes obj.NOFRAME in the object file, which on
ppc64 and s390x means to omit the saved LR. Hence, on these
architectures, NoFramePointer (and NOFRAME) is only safe to set on
leaf functions. However, on *most* architectures, wrappers aren't
necessarily leaf functions because they may call DUFFZERO. We're saved
on ppc64 and s390x only because the compiler doesn't have the rules to
produce DUFFZERO calls on these architectures. Hence, this only works
because the set of LR architectures that implement NOFRAME is disjoint
from the set where the compiler produces DUFFZERO operations. (I
discovered this whole mess when I attempted to add NOFRAME support to
arm.)
Change-Id: Icc589aeb86beacb850d0a6a80bd3024974a33947
Reviewed-on: https://go-review.googlesource.com/92035
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2018-01-25 11:35:27 -05:00
p . To = to
2015-01-19 14:34:58 -05:00
// If there are instructions following
// this ARET, they come from a branch
// with the same stackframe, so undo
// the cleanup.
p . Spadj = + autoffset
}
if p . To . Sym != nil { // retjmp
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . As = obj . AJMP
2015-01-19 14:34:58 -05:00
}
}
}
cmd/compile/internal/obj/x86: eliminate some function prologues
The standard sort swap method
func (t T) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
uses no stack space on architectures for which
FixedFrameSize == 0, currently 386 and amd64.
Nevertheless, we insert a stack check prologue.
This is because it contains a call to
runtime.panicindex.
However, for a few common runtime functions,
we know at compile time that they require
no arguments. Allow them to pass unnoticed.
Triggers for 380 functions during make.bash.
Cuts 4k off cmd/go.
encoding/binary benchmarks:
ReadSlice1000Int32s-8 9.49µs ± 3% 9.41µs ± 5% ~ (p=0.075 n=29+27)
ReadStruct-8 1.50µs ± 3% 1.48µs ± 2% -1.49% (p=0.000 n=30+28)
ReadInts-8 599ns ± 3% 600ns ± 3% ~ (p=0.471 n=30+29)
WriteInts-8 836ns ± 4% 841ns ± 3% ~ (p=0.371 n=30+29)
WriteSlice1000Int32s-8 8.84µs ± 3% 8.69µs ± 5% -1.71% (p=0.001 n=30+30)
PutUvarint32-8 29.6ns ± 1% 28.1ns ± 3% -5.21% (p=0.000 n=28+28)
PutUvarint64-8 82.6ns ± 5% 82.3ns ±10% -0.43% (p=0.014 n=27+30)
Swap assembly before:
"".T.Swap t=1 size=74 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) MOVQ (TLS), CX
0x0009 00009 (swap.go:5) CMPQ SP, 16(CX)
0x000d 00013 (swap.go:5) JLS 67
0x000f 00015 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x000f 00015 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x000f 00015 (swap.go:5) MOVQ "".i+32(FP), AX
0x0014 00020 (swap.go:5) MOVQ "".t+16(FP), CX
0x0019 00025 (swap.go:5) CMPQ AX, CX
0x001c 00028 (swap.go:5) JCC $0, 60
0x001e 00030 (swap.go:5) MOVQ "".t+8(FP), DX
0x0023 00035 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0027 00039 (swap.go:5) MOVQ "".j+40(FP), SI
0x002c 00044 (swap.go:5) CMPQ SI, CX
0x002f 00047 (swap.go:5) JCC $0, 60
0x0031 00049 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0035 00053 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0038 00056 (swap.go:5) MOVB BL, (DX)(SI*1)
0x003b 00059 (swap.go:5) RET
0x003c 00060 (swap.go:5) PCDATA $0, $1
0x003c 00060 (swap.go:5) CALL runtime.panicindex(SB)
0x0041 00065 (swap.go:5) UNDEF
0x0043 00067 (swap.go:5) NOP
0x0043 00067 (swap.go:5) CALL runtime.morestack_noctxt(SB)
0x0048 00072 (swap.go:5) JMP 0
Swap assembly after:
"".T.Swap t=1 size=52 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x0000 00000 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x0000 00000 (swap.go:5) MOVQ "".i+32(FP), AX
0x0005 00005 (swap.go:5) MOVQ "".t+16(FP), CX
0x000a 00010 (swap.go:5) CMPQ AX, CX
0x000d 00013 (swap.go:5) JCC $0, 45
0x000f 00015 (swap.go:5) MOVQ "".t+8(FP), DX
0x0014 00020 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0018 00024 (swap.go:5) MOVQ "".j+40(FP), SI
0x001d 00029 (swap.go:5) CMPQ SI, CX
0x0020 00032 (swap.go:5) JCC $0, 45
0x0022 00034 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0026 00038 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0029 00041 (swap.go:5) MOVB BL, (DX)(SI*1)
0x002c 00044 (swap.go:5) RET
0x002d 00045 (swap.go:5) PCDATA $0, $1
0x002d 00045 (swap.go:5) CALL runtime.panicindex(SB)
0x0032 00050 (swap.go:5) UNDEF
Change-Id: I57dad14af8aaa5e6112deac407cfadc2bfaf1f54
Reviewed-on: https://go-review.googlesource.com/24814
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-07 16:50:46 -07:00
func isZeroArgRuntimeCall ( s * obj . LSym ) bool {
if s == nil {
return false
}
switch s . Name {
2025-06-18 15:14:00 -07:00
case "runtime.panicdivide" , "runtime.panicwrap" , "runtime.panicshift" , "runtime.panicBounds" , "runtime.panicExtend" :
cmd/compile/internal/obj/x86: eliminate some function prologues
The standard sort swap method
func (t T) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
uses no stack space on architectures for which
FixedFrameSize == 0, currently 386 and amd64.
Nevertheless, we insert a stack check prologue.
This is because it contains a call to
runtime.panicindex.
However, for a few common runtime functions,
we know at compile time that they require
no arguments. Allow them to pass unnoticed.
Triggers for 380 functions during make.bash.
Cuts 4k off cmd/go.
encoding/binary benchmarks:
ReadSlice1000Int32s-8 9.49µs ± 3% 9.41µs ± 5% ~ (p=0.075 n=29+27)
ReadStruct-8 1.50µs ± 3% 1.48µs ± 2% -1.49% (p=0.000 n=30+28)
ReadInts-8 599ns ± 3% 600ns ± 3% ~ (p=0.471 n=30+29)
WriteInts-8 836ns ± 4% 841ns ± 3% ~ (p=0.371 n=30+29)
WriteSlice1000Int32s-8 8.84µs ± 3% 8.69µs ± 5% -1.71% (p=0.001 n=30+30)
PutUvarint32-8 29.6ns ± 1% 28.1ns ± 3% -5.21% (p=0.000 n=28+28)
PutUvarint64-8 82.6ns ± 5% 82.3ns ±10% -0.43% (p=0.014 n=27+30)
Swap assembly before:
"".T.Swap t=1 size=74 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) MOVQ (TLS), CX
0x0009 00009 (swap.go:5) CMPQ SP, 16(CX)
0x000d 00013 (swap.go:5) JLS 67
0x000f 00015 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x000f 00015 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x000f 00015 (swap.go:5) MOVQ "".i+32(FP), AX
0x0014 00020 (swap.go:5) MOVQ "".t+16(FP), CX
0x0019 00025 (swap.go:5) CMPQ AX, CX
0x001c 00028 (swap.go:5) JCC $0, 60
0x001e 00030 (swap.go:5) MOVQ "".t+8(FP), DX
0x0023 00035 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0027 00039 (swap.go:5) MOVQ "".j+40(FP), SI
0x002c 00044 (swap.go:5) CMPQ SI, CX
0x002f 00047 (swap.go:5) JCC $0, 60
0x0031 00049 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0035 00053 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0038 00056 (swap.go:5) MOVB BL, (DX)(SI*1)
0x003b 00059 (swap.go:5) RET
0x003c 00060 (swap.go:5) PCDATA $0, $1
0x003c 00060 (swap.go:5) CALL runtime.panicindex(SB)
0x0041 00065 (swap.go:5) UNDEF
0x0043 00067 (swap.go:5) NOP
0x0043 00067 (swap.go:5) CALL runtime.morestack_noctxt(SB)
0x0048 00072 (swap.go:5) JMP 0
Swap assembly after:
"".T.Swap t=1 size=52 args=0x28 locals=0x0
0x0000 00000 (swap.go:5) TEXT "".T.Swap(SB), $0-40
0x0000 00000 (swap.go:5) FUNCDATA $0, gclocals·3cadd97b66f25a3a642be35e9362338f(SB)
0x0000 00000 (swap.go:5) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x0000 00000 (swap.go:5) MOVQ "".i+32(FP), AX
0x0005 00005 (swap.go:5) MOVQ "".t+16(FP), CX
0x000a 00010 (swap.go:5) CMPQ AX, CX
0x000d 00013 (swap.go:5) JCC $0, 45
0x000f 00015 (swap.go:5) MOVQ "".t+8(FP), DX
0x0014 00020 (swap.go:5) MOVBLZX (DX)(AX*1), BX
0x0018 00024 (swap.go:5) MOVQ "".j+40(FP), SI
0x001d 00029 (swap.go:5) CMPQ SI, CX
0x0020 00032 (swap.go:5) JCC $0, 45
0x0022 00034 (swap.go:5) MOVBLZX (DX)(SI*1), CX
0x0026 00038 (swap.go:5) MOVB CL, (DX)(AX*1)
0x0029 00041 (swap.go:5) MOVB BL, (DX)(SI*1)
0x002c 00044 (swap.go:5) RET
0x002d 00045 (swap.go:5) PCDATA $0, $1
0x002d 00045 (swap.go:5) CALL runtime.panicindex(SB)
0x0032 00050 (swap.go:5) UNDEF
Change-Id: I57dad14af8aaa5e6112deac407cfadc2bfaf1f54
Reviewed-on: https://go-review.googlesource.com/24814
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-07 16:50:46 -07:00
return true
}
return false
}
2018-03-23 22:02:03 +00:00
func indir_cx ( ctxt * obj . Link , a * obj . Addr ) {
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
a . Type = obj . TYPE_MEM
a . Reg = REG_CX
2015-01-19 14:34:58 -05:00
}
2019-08-20 17:39:09 -04:00
// loadG ensures the G is loaded into a register (either CX or REGG),
// appending instructions to p if necessary. It returns the new last
// instruction and the G register.
func loadG ( ctxt * obj . Link , cursym * obj . LSym , p * obj . Prog , newprog obj . ProgAlloc ) ( * obj . Prog , int16 ) {
if ctxt . Arch . Family == sys . AMD64 && cursym . ABI ( ) == obj . ABIInternal {
// Use the G register directly in ABIInternal
return p , REGG
}
var regg int16 = REG_CX
if ctxt . Arch . Family == sys . AMD64 {
regg = REGG // == REG_R14
}
p = obj . Appendp ( p , newprog )
2015-01-19 14:34:58 -05:00
p . As = AMOVQ
2016-04-06 12:01:40 -07:00
if ctxt . Arch . PtrSize == 4 {
2015-01-19 14:34:58 -05:00
p . As = AMOVL
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_MEM
p . From . Reg = REG_TLS
2015-01-19 14:34:58 -05:00
p . From . Offset = 0
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Type = obj . TYPE_REG
2019-08-20 17:39:09 -04:00
p . To . Reg = regg
2015-01-19 14:34:58 -05:00
2019-08-20 17:39:09 -04:00
// Rewrite TLS instruction if necessary.
2015-03-02 12:35:15 -05:00
next := p . Link
2017-04-04 14:31:55 -07:00
progedit ( ctxt , p , newprog )
2015-01-19 14:34:58 -05:00
for p . Link != next {
p = p . Link
2019-03-28 13:11:53 +01:00
progedit ( ctxt , p , newprog )
2015-01-19 14:34:58 -05:00
}
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
if p . From . Index == REG_TLS {
2015-01-19 14:34:58 -05:00
p . From . Scale = 2
}
2019-08-20 17:39:09 -04:00
return p , regg
2015-01-19 14:34:58 -05:00
}
// Append code to p to check for stack split.
// Appends to (does not overwrite) p.
2021-02-04 11:43:24 -05:00
// Assumes g is in rg.
2025-07-01 15:00:13 -07:00
// Returns last new instruction.
func stacksplit ( ctxt * obj . Link , cursym * obj . LSym , p * obj . Prog , newprog obj . ProgAlloc , framesize int32 , textarg int32 ) * obj . Prog {
2015-03-02 12:35:15 -05:00
cmp := ACMPQ
lea := ALEAQ
mov := AMOVQ
sub := ASUBQ
2019-08-20 17:39:09 -04:00
push , pop := APUSHQ , APOPQ
2015-01-19 14:34:58 -05:00
2019-10-09 16:22:47 +00:00
if ctxt . Arch . Family == sys . I386 {
2015-01-19 14:34:58 -05:00
cmp = ACMPL
lea = ALEAL
mov = AMOVL
sub = ASUBL
2019-08-20 17:39:09 -04:00
push , pop = APUSHL , APOPL
2015-01-19 14:34:58 -05:00
}
2021-04-02 15:57:46 -04:00
tmp := int16 ( REG_AX ) // use AX for 32-bit
if ctxt . Arch . Family == sys . AMD64 {
// Avoid register parameters.
tmp = int16 ( REGENTRYTMP0 )
}
2019-08-20 17:39:09 -04:00
if ctxt . Flag_maymorestack != "" {
p = cursym . Func ( ) . SpillRegisterArgs ( p , newprog )
if cursym . Func ( ) . Text . From . Sym . NeedCtxt ( ) {
p = obj . Appendp ( p , newprog )
p . As = push
p . From . Type = obj . TYPE_REG
p . From . Reg = REGCTXT
}
// We call maymorestack with an ABI matching the
// caller's ABI. Since this is the first thing that
// happens in the function, we have to be consistent
// with the caller about CPU state (notably,
// fixed-meaning registers).
p = obj . Appendp ( p , newprog )
p . As = obj . ACALL
p . To . Type = obj . TYPE_BRANCH
p . To . Name = obj . NAME_EXTERN
p . To . Sym = ctxt . LookupABI ( ctxt . Flag_maymorestack , cursym . ABI ( ) )
if cursym . Func ( ) . Text . From . Sym . NeedCtxt ( ) {
p = obj . Appendp ( p , newprog )
p . As = pop
p . To . Type = obj . TYPE_REG
p . To . Reg = REGCTXT
}
p = cursym . Func ( ) . UnspillRegisterArgs ( p , newprog )
}
// Jump back to here after morestack returns.
startPred := p
// Load G register
var rg int16
p , rg = loadG ( ctxt , cursym , p , newprog )
2015-03-02 14:22:05 -05:00
var q1 * obj . Prog
2023-04-19 13:21:02 -04:00
if framesize <= abi . StackSmall {
2015-01-19 14:34:58 -05:00
// small stack: SP <= stackguard
// CMPQ SP, stackguard
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2015-01-19 14:34:58 -05:00
2016-03-07 18:00:08 -08:00
p . As = cmp
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_REG
p . From . Reg = REG_SP
2021-02-04 11:43:24 -05:00
p . To . Type = obj . TYPE_MEM
p . To . Reg = rg
2016-04-06 12:01:40 -07:00
p . To . Offset = 2 * int64 ( ctxt . Arch . PtrSize ) // G.stackguard0
2017-03-26 07:46:30 -07:00
if cursym . CFunc ( ) {
2016-04-06 12:01:40 -07:00
p . To . Offset = 3 * int64 ( ctxt . Arch . PtrSize ) // G.stackguard1
2015-01-19 14:34:58 -05:00
}
cmd/internal/obj: mark split-stack prologue nonpreemptible
When there are both a synchronous preemption request (by
clobbering the stack guard) and an asynchronous one (by signal),
the running goroutine may observe the synchronous request first
in stack bounds check, and go to the path of calling morestack.
If the preemption signal arrives at this point before the call to
morestack, the goroutine will be asynchronously preempted,
entering the scheduler. When it is resumed, the scheduler clears
the preemption request, unclobbers the stack guard. But the
resumed goroutine will still call morestack, as it is already on
its way. morestack will, as there is no preemption request,
double the stack unnecessarily. If this happens multiple times,
the stack may grow too big, although only a small amount is
actually used.
To fix this, we mark the stack bounds check and the call to
morestack async-nonpreemptible, starting after the memory
instruction (mostly a load, on x86 CMP with memory).
Not done for Wasm as it does not support async preemption.
Fixes #35470.
Change-Id: Ibd7f3d935a3649b80f47539116ec9b9556680cf2
Reviewed-on: https://go-review.googlesource.com/c/go/+/207350
Reviewed-by: David Chase <drchase@google.com>
2019-11-14 20:23:17 -05:00
2025-05-05 10:51:52 -07:00
// Mark the stack bound check and morestack call async nonpreemptible.
// If we get preempted here, when resumed the preemption request is
// cleared, but we'll still call morestack, which will double the stack
// unnecessarily. See issue #35470.
p = ctxt . StartUnsafePoint ( p , newprog )
2023-04-19 13:21:02 -04:00
} else if framesize <= abi . StackBig {
2015-01-19 14:34:58 -05:00
// large stack: SP-framesize <= stackguard-StackSmall
2021-02-19 17:11:40 -05:00
// LEAQ -xxx(SP), tmp
// CMPQ tmp, stackguard
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2015-01-19 14:34:58 -05:00
2016-03-07 18:00:08 -08:00
p . As = lea
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_MEM
p . From . Reg = REG_SP
2023-04-19 13:21:02 -04:00
p . From . Offset = - ( int64 ( framesize ) - abi . StackSmall )
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Type = obj . TYPE_REG
2021-02-19 17:11:40 -05:00
p . To . Reg = tmp
2015-01-19 14:34:58 -05:00
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2016-03-07 18:00:08 -08:00
p . As = cmp
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_REG
2021-02-19 17:11:40 -05:00
p . From . Reg = tmp
2021-02-04 11:43:24 -05:00
p . To . Type = obj . TYPE_MEM
p . To . Reg = rg
2016-04-06 12:01:40 -07:00
p . To . Offset = 2 * int64 ( ctxt . Arch . PtrSize ) // G.stackguard0
2017-03-26 07:46:30 -07:00
if cursym . CFunc ( ) {
2016-04-06 12:01:40 -07:00
p . To . Offset = 3 * int64 ( ctxt . Arch . PtrSize ) // G.stackguard1
2015-01-19 14:34:58 -05:00
}
cmd/internal/obj: mark split-stack prologue nonpreemptible
When there are both a synchronous preemption request (by
clobbering the stack guard) and an asynchronous one (by signal),
the running goroutine may observe the synchronous request first
in stack bounds check, and go to the path of calling morestack.
If the preemption signal arrives at this point before the call to
morestack, the goroutine will be asynchronously preempted,
entering the scheduler. When it is resumed, the scheduler clears
the preemption request, unclobbers the stack guard. But the
resumed goroutine will still call morestack, as it is already on
its way. morestack will, as there is no preemption request,
double the stack unnecessarily. If this happens multiple times,
the stack may grow too big, although only a small amount is
actually used.
To fix this, we mark the stack bounds check and the call to
morestack async-nonpreemptible, starting after the memory
instruction (mostly a load, on x86 CMP with memory).
Not done for Wasm as it does not support async preemption.
Fixes #35470.
Change-Id: Ibd7f3d935a3649b80f47539116ec9b9556680cf2
Reviewed-on: https://go-review.googlesource.com/c/go/+/207350
Reviewed-by: David Chase <drchase@google.com>
2019-11-14 20:23:17 -05:00
2025-05-05 10:51:52 -07:00
p = ctxt . StartUnsafePoint ( p , newprog ) // see the comment above
2015-01-19 14:34:58 -05:00
} else {
2021-04-02 15:57:46 -04:00
// Such a large stack we need to protect against underflow.
// The runtime guarantees SP > objabi.StackBig, but
// framesize is large enough that SP-framesize may
// underflow, causing a direct comparison with the
// stack guard to incorrectly succeed. We explicitly
// guard against underflow.
2015-01-19 14:34:58 -05:00
//
2021-04-02 15:57:46 -04:00
// MOVQ SP, tmp
// SUBQ $(framesize - StackSmall), tmp
// // If subtraction wrapped (carry set), morestack.
// JCS label-of-call-to-morestack
// CMPQ tmp, stackguard
2015-01-19 14:34:58 -05:00
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2015-01-19 14:34:58 -05:00
2016-03-07 18:00:08 -08:00
p . As = mov
2021-04-02 15:57:46 -04:00
p . From . Type = obj . TYPE_REG
p . From . Reg = REG_SP
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Type = obj . TYPE_REG
2021-04-02 15:57:46 -04:00
p . To . Reg = tmp
2015-01-19 14:34:58 -05:00
2025-05-05 10:51:52 -07:00
p = ctxt . StartUnsafePoint ( p , newprog ) // see the comment above
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2021-04-02 15:57:46 -04:00
p . As = sub
p . From . Type = obj . TYPE_CONST
2023-04-19 13:21:02 -04:00
p . From . Offset = int64 ( framesize ) - abi . StackSmall
2021-04-02 15:57:46 -04:00
p . To . Type = obj . TYPE_REG
p . To . Reg = tmp
2015-01-19 14:34:58 -05:00
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2021-04-02 15:57:46 -04:00
p . As = AJCS
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . To . Type = obj . TYPE_BRANCH
2015-01-19 14:34:58 -05:00
q1 = p
2017-04-04 14:31:55 -07:00
p = obj . Appendp ( p , newprog )
2016-03-07 18:00:08 -08:00
p . As = cmp
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
p . From . Type = obj . TYPE_REG
2021-04-02 15:57:46 -04:00
p . From . Reg = tmp
p . To . Type = obj . TYPE_MEM
p . To . Reg = rg
p . To . Offset = 2 * int64 ( ctxt . Arch . PtrSize ) // G.stackguard0
if cursym . CFunc ( ) {
p . To . Offset = 3 * int64 ( ctxt . Arch . PtrSize ) // G.stackguard1
}
2015-01-19 14:34:58 -05:00
}
// common
2017-04-04 14:31:55 -07:00
jls := obj . Appendp ( p , newprog )
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
jls . As = AJLS
jls . To . Type = obj . TYPE_BRANCH
2025-05-05 10:51:52 -07:00
end := ctxt . EndUnsafePoint ( jls , newprog , - 1 )
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
var last * obj . Prog
2020-07-19 00:30:12 -04:00
for last = cursym . Func ( ) . Text ; last . Link != nil ; last = last . Link {
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
}
2016-10-02 17:10:13 -04:00
// Now we are at the end of the function, but logically
// we are still in function prologue. We need to fix the
// SP data and PCDATA.
2017-04-04 14:31:55 -07:00
spfix := obj . Appendp ( last , newprog )
2015-12-30 15:19:54 -08:00
spfix . As = obj . ANOP
spfix . Spadj = - framesize
2025-05-05 10:51:52 -07:00
pcdata := ctxt . EmitEntryStackMap ( cursym , spfix , newprog )
spill := ctxt . StartUnsafePoint ( pcdata , newprog )
pcdata = cursym . Func ( ) . SpillRegisterArgs ( spill , newprog )
2016-10-02 17:10:13 -04:00
2017-04-04 14:31:55 -07:00
call := obj . Appendp ( pcdata , newprog )
2020-07-19 00:30:12 -04:00
call . Pos = cursym . Func ( ) . Text . Pos
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
call . As = obj . ACALL
call . To . Type = obj . TYPE_BRANCH
2016-06-02 11:07:55 +12:00
call . To . Name = obj . NAME_EXTERN
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
morestack := "runtime.morestack"
switch {
2017-03-26 07:46:30 -07:00
case cursym . CFunc ( ) :
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
morestack = "runtime.morestackc"
2020-07-19 00:30:12 -04:00
case ! cursym . Func ( ) . Text . From . Sym . NeedCtxt ( ) :
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
morestack = "runtime.morestack_noctxt"
}
2017-04-20 07:13:02 -07:00
call . To . Sym = ctxt . Lookup ( morestack )
2016-06-02 11:07:55 +12:00
// When compiling 386 code for dynamic linking, the call needs to be adjusted
// to follow PIC rules. This in turn can insert more instructions, so we need
// to keep track of the start of the call (where the jump will be to) and the
// end (which following instructions are appended to).
callend := call
2017-04-04 14:31:55 -07:00
progedit ( ctxt , callend , newprog )
2016-06-02 11:07:55 +12:00
for ; callend . Link != nil ; callend = callend . Link {
2017-04-04 14:31:55 -07:00
progedit ( ctxt , callend . Link , newprog )
2016-06-02 11:07:55 +12:00
}
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
2025-05-05 10:51:52 -07:00
// The instructions which unspill regs should be preemptible.
pcdata = ctxt . EndUnsafePoint ( callend , newprog , - 1 )
unspill := cursym . Func ( ) . UnspillRegisterArgs ( pcdata , newprog )
cmd/internal/obj: mark split-stack prologue nonpreemptible
When there are both a synchronous preemption request (by
clobbering the stack guard) and an asynchronous one (by signal),
the running goroutine may observe the synchronous request first
in stack bounds check, and go to the path of calling morestack.
If the preemption signal arrives at this point before the call to
morestack, the goroutine will be asynchronously preempted,
entering the scheduler. When it is resumed, the scheduler clears
the preemption request, unclobbers the stack guard. But the
resumed goroutine will still call morestack, as it is already on
its way. morestack will, as there is no preemption request,
double the stack unnecessarily. If this happens multiple times,
the stack may grow too big, although only a small amount is
actually used.
To fix this, we mark the stack bounds check and the call to
morestack async-nonpreemptible, starting after the memory
instruction (mostly a load, on x86 CMP with memory).
Not done for Wasm as it does not support async preemption.
Fixes #35470.
Change-Id: Ibd7f3d935a3649b80f47539116ec9b9556680cf2
Reviewed-on: https://go-review.googlesource.com/c/go/+/207350
Reviewed-by: David Chase <drchase@google.com>
2019-11-14 20:23:17 -05:00
2023-09-07 00:09:31 +08:00
jmp := obj . Appendp ( unspill , newprog )
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
jmp . As = obj . AJMP
jmp . To . Type = obj . TYPE_BRANCH
2019-08-20 17:39:09 -04:00
jmp . To . SetTarget ( startPred . Link )
2015-12-30 15:19:54 -08:00
jmp . Spadj = + framesize
cmd/internal/obj/x86: make function prologue more predictable
Static branch prediction guesses that forward branches aren't taken.
Since stacks are rarely grown, make the forward branch mean grow.
Sample disassembly for
func f() {
_ = [128]byte{}
}
Before:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 7707 JA 0x2016
x.go:3 0x200f e88c410400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x2014 ebea JMP main.f(SB)
x.go:3 0x2016 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x201d 488d3c24 LEAQ 0(SP), DI
x.go:4 0x2021 31c0 XORL AX, AX
x.go:4 0x2023 e8cc640400 CALL 0x484f4
x.go:5 0x2028 4881c480000000 ADDQ $0x80, SP
x.go:5 0x202f c3 RET
After:
TEXT main.f(SB) x.go
x.go:3 0x2000 65488b0c25a0080000 GS MOVQ GS:0x8a0, CX
x.go:3 0x2009 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x200d 761a JBE 0x2029
x.go:3 0x200f 4881ec80000000 SUBQ $0x80, SP
x.go:4 0x2016 488d3c24 LEAQ 0(SP), DI
x.go:4 0x201a 31c0 XORL AX, AX
x.go:4 0x201c e813740400 CALL 0x49434
x.go:5 0x2021 4881c480000000 ADDQ $0x80, SP
x.go:5 0x2028 c3 RET
x.go:3 0x2029 e8224f0400 CALL runtime.morestack_noctxt(SB)
x.go:3 0x202e ebd0 JMP main.f(SB)
Updates #10587.
Sample benchmarks on a 2.8 GHz Intel Core i7:
package sort
name old mean new mean delta
SearchWrappers 134ns × (0.99,1.01) 132ns × (0.99,1.01) -1.73% (p=0.000 n=15+14)
SortString1K 215µs × (0.99,1.01) 213µs × (0.99,1.01) -0.61% (p=0.020 n=14+15)
StableString1K 311µs × (0.99,1.02) 309µs × (0.99,1.02) ~ (p=0.077 n=14+15)
SortInt1K 103µs × (0.99,1.02) 100µs × (0.98,1.01) -3.34% (p=0.000 n=15+15)
StableInt1K 102µs × (0.99,1.01) 98µs × (0.97,1.04) -3.53% (p=0.000 n=15+15)
SortInt64K 10.1ms × (0.98,1.02) 9.7ms × (0.99,1.01) -3.86% (p=0.000 n=14+15)
StableInt64K 8.70ms × (0.99,1.01) 8.44ms × (0.99,1.03) -2.93% (p=0.000 n=14+15)
Sort1e2 51.2µs × (1.00,1.01) 48.9µs × (0.99,1.02) -4.48% (p=0.000 n=13+15)
Stable1e2 100µs × (0.99,1.02) 99µs × (0.99,1.01) -1.15% (p=0.000 n=14+13)
Sort1e4 11.1ms × (0.99,1.02) 10.4ms × (0.99,1.01) -6.02% (p=0.000 n=15+14)
Stable1e4 30.6ms × (0.99,1.01) 30.3ms × (0.99,1.02) -1.02% (p=0.001 n=15+14)
Sort1e6 1.75s × (0.99,1.02) 1.66s × (0.98,1.03) -4.95% (p=0.000 n=14+15)
Stable1e6 6.31s × (0.99,1.01) 6.26s × (0.99,1.01) -0.79% (p=0.002 n=15+15)
package regexp
name old mean new mean delta
Literal 131ns × (0.99,1.01) 130ns × (0.99,1.03) -1.07% (p=0.004 n=14+15)
NotLiteral 2.13µs × (0.99,1.01) 2.01µs × (0.99,1.03) -5.71% (p=0.000 n=14+14)
MatchClass 3.15µs × (0.99,1.01) 3.04µs × (0.99,1.02) -3.40% (p=0.000 n=15+15)
MatchClass_InRange 2.92µs × (0.99,1.01) 2.77µs × (0.99,1.02) -5.05% (p=0.000 n=13+15)
ReplaceAll 2.17µs × (0.99,1.02) 2.06µs × (0.99,1.01) -5.19% (p=0.000 n=15+13)
AnchoredLiteralShortNonMatch 116ns × (0.99,1.02) 113ns × (0.99,1.01) -2.75% (p=0.000 n=15+14)
AnchoredLiteralLongNonMatch 125ns × (0.99,1.01) 127ns × (0.98,1.02) +1.49% (p=0.000 n=15+15)
AnchoredShortMatch 178ns × (0.99,1.02) 175ns × (0.99,1.01) -1.62% (p=0.000 n=15+13)
AnchoredLongMatch 328ns × (0.99,1.00) 341ns × (0.99,1.01) +3.73% (p=0.000 n=12+15)
OnePassShortA 773ns × (0.99,1.02) 752ns × (0.99,1.01) -2.78% (p=0.000 n=15+13)
NotOnePassShortA 794ns × (0.99,1.03) 780ns × (0.99,1.02) -1.75% (p=0.001 n=15+15)
OnePassShortB 608ns × (0.99,1.01) 591ns × (0.99,1.02) -2.86% (p=0.000 n=15+14)
NotOnePassShortB 576ns × (0.99,1.01) 571ns × (0.99,1.02) -0.74% (p=0.035 n=15+15)
OnePassLongPrefix 131ns × (0.99,1.02) 130ns × (0.99,1.02) -1.32% (p=0.003 n=15+15)
OnePassLongNotPrefix 503ns × (0.99,1.02) 481ns × (0.99,1.01) -4.34% (p=0.000 n=15+13)
MatchEasy0_32 102ns × (0.98,1.01) 101ns × (0.99,1.02) ~ (p=0.907 n=15+14)
MatchEasy0_1K 617ns × (0.99,1.02) 634ns × (0.98,1.02) +2.77% (p=0.000 n=15+15)
MatchEasy0_32K 10.9µs × (0.99,1.01) 11.1µs × (0.99,1.01) +1.59% (p=0.000 n=15+15)
MatchEasy0_1M 406µs × (0.99,1.02) 410µs × (0.99,1.02) +1.01% (p=0.000 n=14+15)
MatchEasy0_32M 13.4ms × (0.99,1.01) 13.7ms × (0.99,1.02) +1.64% (p=0.000 n=12+15)
MatchEasy1_32 83.7ns × (0.98,1.02) 83.0ns × (0.98,1.02) ~ (p=0.190 n=15+15)
MatchEasy1_1K 1.46µs × (0.99,1.02) 1.39µs × (0.99,1.02) -4.83% (p=0.000 n=15+15)
MatchEasy1_32K 49.4µs × (0.99,1.01) 49.4µs × (0.99,1.01) ~ (p=0.205 n=15+15)
MatchEasy1_1M 1.72ms × (0.99,1.02) 1.75ms × (0.99,1.01) +1.34% (p=0.000 n=15+15)
MatchEasy1_32M 55.5ms × (0.99,1.01) 56.1ms × (0.99,1.02) +1.10% (p=0.002 n=15+15)
MatchMedium_32 1.37µs × (0.99,1.04) 1.33µs × (0.99,1.01) -2.87% (p=0.000 n=15+15)
MatchMedium_1K 41.1µs × (0.99,1.02) 40.4µs × (0.99,1.02) -1.59% (p=0.000 n=15+15)
MatchMedium_32K 1.71ms × (0.99,1.01) 1.75ms × (0.99,1.02) +2.36% (p=0.000 n=14+15)
MatchMedium_1M 54.5ms × (0.99,1.01) 56.1ms × (0.99,1.01) +2.94% (p=0.000 n=13+15)
MatchMedium_32M 1.75s × (0.99,1.01) 1.80s × (0.99,1.01) +2.77% (p=0.000 n=15+15)
MatchHard_32 2.12µs × (0.99,1.02) 2.06µs × (0.99,1.01) -2.60% (p=0.000 n=15+14)
MatchHard_1K 64.4µs × (0.98,1.02) 62.2µs × (0.99,1.01) -3.33% (p=0.000 n=15+15)
MatchHard_32K 2.74ms × (0.99,1.01) 2.75ms × (0.99,1.01) ~ (p=0.310 n=15+14)
MatchHard_1M 87.1ms × (0.99,1.02) 88.2ms × (0.99,1.01) +1.36% (p=0.000 n=14+15)
MatchHard_32M 2.79s × (0.99,1.02) 2.83s × (0.99,1.02) +1.26% (p=0.004 n=15+14)
go1 benchmarks
name old time/op new time/op delta
BinaryTree17 3.34s ± 3% 3.28s ± 2% -1.86% (p=0.000 n=67+66)
Fannkuch11 2.50s ± 1% 2.51s ± 1% +0.24% (p=0.016 n=63+66)
FmtFprintfEmpty 50.3ns ± 1% 50.2ns ± 2% -0.30% (p=0.001 n=62+67)
FmtFprintfString 178ns ± 1% 166ns ± 1% -7.10% (p=0.000 n=62+59)
FmtFprintfInt 168ns ± 1% 161ns ± 2% -4.41% (p=0.000 n=66+64)
FmtFprintfIntInt 292ns ± 1% 282ns ± 2% -3.55% (p=0.000 n=62+60)
FmtFprintfPrefixedInt 245ns ± 2% 239ns ± 2% -2.24% (p=0.000 n=66+65)
FmtFprintfFloat 338ns ± 2% 326ns ± 1% -3.42% (p=0.000 n=64+59)
FmtManyArgs 1.14µs ± 1% 1.10µs ± 2% -3.55% (p=0.000 n=62+62)
GobDecode 8.88ms ± 2% 8.74ms ± 1% -1.55% (p=0.000 n=66+62)
GobEncode 6.84ms ± 2% 6.61ms ± 2% -3.32% (p=0.000 n=61+67)
Gzip 356ms ± 2% 352ms ± 2% -1.07% (p=0.000 n=67+66)
Gunzip 90.6ms ± 2% 89.8ms ± 1% -0.83% (p=0.000 n=65+64)
HTTPClientServer 82.6µs ± 2% 82.5µs ± 2% ~ (p=0.832 n=65+63)
JSONEncode 17.5ms ± 2% 16.8ms ± 2% -3.77% (p=0.000 n=63+63)
JSONDecode 63.3ms ± 2% 59.0ms ± 2% -6.85% (p=0.000 n=64+63)
Mandelbrot200 3.85ms ± 1% 3.85ms ± 1% ~ (p=0.127 n=65+62)
GoParse 3.75ms ± 2% 3.66ms ± 2% -2.39% (p=0.000 n=66+64)
RegexpMatchEasy0_32 100ns ± 2% 100ns ± 1% -0.65% (p=0.000 n=62+64)
RegexpMatchEasy0_1K 342ns ± 1% 341ns ± 1% -0.43% (p=0.000 n=65+64)
RegexpMatchEasy1_32 82.8ns ± 2% 82.8ns ± 2% ~ (p=0.977 n=63+64)
RegexpMatchEasy1_1K 511ns ± 2% 506ns ± 2% -1.01% (p=0.000 n=63+64)
RegexpMatchMedium_32 139ns ± 1% 134ns ± 3% -3.27% (p=0.000 n=59+60)
RegexpMatchMedium_1K 41.8µs ± 2% 40.5µs ± 2% -3.05% (p=0.000 n=62+64)
RegexpMatchHard_32 2.13µs ± 1% 2.09µs ± 1% -2.22% (p=0.000 n=60+65)
RegexpMatchHard_1K 64.4µs ± 3% 62.8µs ± 2% -2.58% (p=0.000 n=65+59)
Revcomp 531ms ± 2% 529ms ± 1% -0.28% (p=0.022 n=61+61)
Template 73.2ms ± 1% 73.1ms ± 1% ~ (p=0.794 n=66+63)
TimeParse 369ns ± 1% 352ns ± 1% -4.68% (p=0.000 n=65+66)
TimeFormat 374ns ± 2% 348ns ± 2% -7.01% (p=0.000 n=66+64)
Change-Id: Ib190b5bb48a3e9087711d9e3383621d3103dd342
Reviewed-on: https://go-review.googlesource.com/10367
Reviewed-by: Russ Cox <rsc@golang.org>
2015-05-28 17:31:24 -07:00
2020-09-28 17:42:30 -04:00
jls . To . SetTarget ( spill )
2015-01-19 14:34:58 -05:00
if q1 != nil {
2020-09-28 17:42:30 -04:00
q1 . To . SetTarget ( spill )
2015-01-19 14:34:58 -05:00
}
2025-07-01 15:00:13 -07:00
return end
2015-01-19 14:34:58 -05:00
}
2021-01-13 15:45:28 -08:00
func isR15 ( r int16 ) bool {
return r == REG_R15 || r == REG_R15B
}
func addrMentionsR15 ( a * obj . Addr ) bool {
if a == nil {
return false
}
return isR15 ( a . Reg ) || isR15 ( a . Index )
}
func progMentionsR15 ( p * obj . Prog ) bool {
return addrMentionsR15 ( & p . From ) || addrMentionsR15 ( & p . To ) || isR15 ( p . Reg ) || addrMentionsR15 ( p . GetFrom3 ( ) )
}
func addrUsesGlobal ( a * obj . Addr ) bool {
if a == nil {
return false
}
return a . Name == obj . NAME_EXTERN && ! a . Sym . Local ( )
}
func progUsesGlobal ( p * obj . Prog ) bool {
if p . As == obj . ACALL || p . As == obj . ATEXT || p . As == obj . AFUNCDATA || p . As == obj . ARET || p . As == obj . AJMP {
// These opcodes don't use a GOT to access their argument (see rewriteToUseGot),
// or R15 would be dead at them anyway.
return false
}
if p . As == ALEAQ {
// The GOT entry is placed directly in the destination register; R15 is not used.
return false
}
return addrUsesGlobal ( & p . From ) || addrUsesGlobal ( & p . To ) || addrUsesGlobal ( p . GetFrom3 ( ) )
}
2023-03-14 11:34:51 -07:00
type rwMask int
const (
readFrom rwMask = 1 << iota
readTo
readReg
readFrom3
writeFrom
writeTo
writeReg
writeFrom3
)
// progRW returns a mask describing the effects of the instruction p.
// Note: this isn't exhaustively accurate. It is only currently used for detecting
// reads/writes to R15, so SSE register behavior isn't fully correct, and
// other weird cases (e.g. writes to DX by CLD) also aren't captured.
func progRW ( p * obj . Prog ) rwMask {
var m rwMask
// Default for most instructions
if p . From . Type != obj . TYPE_NONE {
m |= readFrom
}
if p . To . Type != obj . TYPE_NONE {
// Most x86 instructions update the To value
m |= readTo | writeTo
}
if p . Reg != 0 {
m |= readReg
}
if p . GetFrom3 ( ) != nil {
m |= readFrom3
}
// Lots of exceptions to the above defaults.
name := p . As . String ( )
if strings . HasPrefix ( name , "MOV" ) || strings . HasPrefix ( name , "PMOV" ) {
// MOV instructions don't read To.
m &^= readTo
}
switch p . As {
case APOPW , APOPL , APOPQ ,
ALEAL , ALEAQ ,
AIMUL3W , AIMUL3L , AIMUL3Q ,
APEXTRB , APEXTRW , APEXTRD , APEXTRQ , AVPEXTRB , AVPEXTRW , AVPEXTRD , AVPEXTRQ , AEXTRACTPS ,
ABSFW , ABSFL , ABSFQ , ABSRW , ABSRL , ABSRQ , APOPCNTW , APOPCNTL , APOPCNTQ , ALZCNTW , ALZCNTL , ALZCNTQ ,
ASHLXL , ASHLXQ , ASHRXL , ASHRXQ , ASARXL , ASARXQ :
// These instructions are pure writes to To. They don't use its old value.
m &^= readTo
case AXORL , AXORQ :
// Register-clearing idiom doesn't read previous value.
if p . From . Type == obj . TYPE_REG && p . To . Type == obj . TYPE_REG && p . From . Reg == p . To . Reg {
m &^= readFrom | readTo
}
case AMULXL , AMULXQ :
// These are write-only to both To and From3.
m &^= readTo | readFrom3
m |= writeFrom3
}
return m
}
// progReadsR15 reports whether p reads the register R15.
func progReadsR15 ( p * obj . Prog ) bool {
m := progRW ( p )
if m & readFrom != 0 && p . From . Type == obj . TYPE_REG && isR15 ( p . From . Reg ) {
return true
}
if m & readTo != 0 && p . To . Type == obj . TYPE_REG && isR15 ( p . To . Reg ) {
return true
}
if m & readReg != 0 && isR15 ( p . Reg ) {
return true
}
if m & readFrom3 != 0 && p . GetFrom3 ( ) . Type == obj . TYPE_REG && isR15 ( p . GetFrom3 ( ) . Reg ) {
return true
}
// reads of the index registers
if p . From . Type == obj . TYPE_MEM && ( isR15 ( p . From . Reg ) || isR15 ( p . From . Index ) ) {
return true
}
if p . To . Type == obj . TYPE_MEM && ( isR15 ( p . To . Reg ) || isR15 ( p . To . Index ) ) {
return true
}
if f3 := p . GetFrom3 ( ) ; f3 != nil && f3 . Type == obj . TYPE_MEM && ( isR15 ( f3 . Reg ) || isR15 ( f3 . Index ) ) {
return true
}
return false
}
// progWritesR15 reports whether p writes the register R15.
func progWritesR15 ( p * obj . Prog ) bool {
m := progRW ( p )
if m & writeFrom != 0 && p . From . Type == obj . TYPE_REG && isR15 ( p . From . Reg ) {
return true
}
if m & writeTo != 0 && p . To . Type == obj . TYPE_REG && isR15 ( p . To . Reg ) {
return true
}
if m & writeReg != 0 && isR15 ( p . Reg ) {
return true
}
if m & writeFrom3 != 0 && p . GetFrom3 ( ) . Type == obj . TYPE_REG && isR15 ( p . GetFrom3 ( ) . Reg ) {
return true
}
return false
}
2021-01-13 15:45:28 -08:00
func errorCheck ( ctxt * obj . Link , s * obj . LSym ) {
// When dynamic linking, R15 is used to access globals. Reject code that
// uses R15 after a global variable access.
if ! ctxt . Flag_dynlink {
return
}
// Flood fill all the instructions where R15's value is junk.
// If there are any uses of R15 in that set, report an error.
var work [ ] * obj . Prog
var mentionsR15 bool
for p := s . Func ( ) . Text ; p != nil ; p = p . Link {
if progUsesGlobal ( p ) {
work = append ( work , p )
p . Mark |= markBit
}
if progMentionsR15 ( p ) {
mentionsR15 = true
}
}
if mentionsR15 {
for len ( work ) > 0 {
p := work [ len ( work ) - 1 ]
work = work [ : len ( work ) - 1 ]
2023-03-14 11:34:51 -07:00
if progReadsR15 ( p ) {
pos := ctxt . PosTable . Pos ( p . Pos )
ctxt . Diag ( "%s:%s: when dynamic linking, R15 is clobbered by a global variable access and is used here: %v" , path . Base ( pos . Filename ( ) ) , pos . LineNumber ( ) , p )
break // only report one error
}
if progWritesR15 ( p ) {
// R15 is overwritten by this instruction. Its value is not junk any more.
continue
}
2021-01-13 15:45:28 -08:00
if q := p . To . Target ( ) ; q != nil && q . Mark & markBit == 0 {
q . Mark |= markBit
work = append ( work , q )
}
if p . As == obj . AJMP || p . As == obj . ARET {
continue // no fallthrough
}
if q := p . Link ; q != nil && q . Mark & markBit == 0 {
q . Mark |= markBit
work = append ( work , q )
}
}
}
// Clean up.
for p := s . Func ( ) . Text ; p != nil ; p = p . Link {
p . Mark &^= markBit
}
}
2016-03-07 18:00:08 -08:00
var unaryDst = map [ obj . As ] bool {
cmd/internal/obj/x86: add missing legacy insts
Minimizes the amount of "TODO" stuff in test suite
of cmd/asm/internal/asm/testdata/amd64enc.s.
Some instructions were already implemented, but
test cases for them were commented-out.
Does not enable MMX instructions, calls/jumps and some
segment registers instructions.
-- Affected instructions --
BLENDVPD, BLENDVPS
BSWAPW
CBW
CDQE
CLAC
CLFLUSHOPT
CMPXCHG16B
CRC32B, CRC32L, CRC32W
CWDE
FBLD
FBSTP
FCMOVB
FCMOVBE
FCMOVE
FCMOVNB
FCMOVNBE
FCMOVU
FCOMI
FCOMIP
IMUL3L, IMUL3Q, IMUL3W
ICEBP, INT
INVPCID
LARQ
LGDT, LIDT, LLDT
LMSW
LTR
LZCNTL, LZCNTQ, LZCNTW
MONITOR
MOVBELL, MOVBEQQ, MOVBEWW
MOVBQZX
MOVQ
MOVSWW, MOVZWW
MWAIT
NOPL, NOPW
PBLENDVB
PEXTRW
RDPKRU
RDRANDL, RDRANDQ, RDRANDW
RDSEEDL, RDSEEDQ, RDSEEDW
RDTSCP
SAHF
SGDT, SIDT
SLDTL, SLDTQ, SLDTW
SMSWL, SMSWQ, SMSWW
STAC
STRL, STRQ, STRW
SYSENTER, SYSENTER64
SYSEXIT, SYSEXIT64
SHA256RNDS2
TZCNTL, TZCNTQ, TZCNTW
UD1, UD2
WRPKRU
XRSTOR, XRSTOR64
XRSTORS, XRSTORS64
XSAVE, XSAVE64
XSAVEC, XSAVEC64
XSAVEOPT, XSAVEOPT64
XSAVES, XSAVES64
XSETBV
Fixes #6739
Change-Id: I8b125d9a5ea39bb4b9da7e66a63a16f609cef376
Reviewed-on: https://go-review.googlesource.com/97235
Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-02-26 22:23:37 +03:00
ABSWAPL : true ,
ABSWAPQ : true ,
2019-06-21 11:15:21 +03:00
ACLDEMOTE : true ,
cmd/internal/obj/x86: add missing legacy insts
Minimizes the amount of "TODO" stuff in test suite
of cmd/asm/internal/asm/testdata/amd64enc.s.
Some instructions were already implemented, but
test cases for them were commented-out.
Does not enable MMX instructions, calls/jumps and some
segment registers instructions.
-- Affected instructions --
BLENDVPD, BLENDVPS
BSWAPW
CBW
CDQE
CLAC
CLFLUSHOPT
CMPXCHG16B
CRC32B, CRC32L, CRC32W
CWDE
FBLD
FBSTP
FCMOVB
FCMOVBE
FCMOVE
FCMOVNB
FCMOVNBE
FCMOVU
FCOMI
FCOMIP
IMUL3L, IMUL3Q, IMUL3W
ICEBP, INT
INVPCID
LARQ
LGDT, LIDT, LLDT
LMSW
LTR
LZCNTL, LZCNTQ, LZCNTW
MONITOR
MOVBELL, MOVBEQQ, MOVBEWW
MOVBQZX
MOVQ
MOVSWW, MOVZWW
MWAIT
NOPL, NOPW
PBLENDVB
PEXTRW
RDPKRU
RDRANDL, RDRANDQ, RDRANDW
RDSEEDL, RDSEEDQ, RDSEEDW
RDTSCP
SAHF
SGDT, SIDT
SLDTL, SLDTQ, SLDTW
SMSWL, SMSWQ, SMSWW
STAC
STRL, STRQ, STRW
SYSENTER, SYSENTER64
SYSEXIT, SYSEXIT64
SHA256RNDS2
TZCNTL, TZCNTQ, TZCNTW
UD1, UD2
WRPKRU
XRSTOR, XRSTOR64
XRSTORS, XRSTORS64
XSAVE, XSAVE64
XSAVEC, XSAVEC64
XSAVEOPT, XSAVEOPT64
XSAVES, XSAVES64
XSETBV
Fixes #6739
Change-Id: I8b125d9a5ea39bb4b9da7e66a63a16f609cef376
Reviewed-on: https://go-review.googlesource.com/97235
Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-02-26 22:23:37 +03:00
ACLFLUSH : true ,
ACLFLUSHOPT : true ,
2019-06-21 11:15:21 +03:00
ACLWB : true ,
cmd/internal/obj/x86: add missing legacy insts
Minimizes the amount of "TODO" stuff in test suite
of cmd/asm/internal/asm/testdata/amd64enc.s.
Some instructions were already implemented, but
test cases for them were commented-out.
Does not enable MMX instructions, calls/jumps and some
segment registers instructions.
-- Affected instructions --
BLENDVPD, BLENDVPS
BSWAPW
CBW
CDQE
CLAC
CLFLUSHOPT
CMPXCHG16B
CRC32B, CRC32L, CRC32W
CWDE
FBLD
FBSTP
FCMOVB
FCMOVBE
FCMOVE
FCMOVNB
FCMOVNBE
FCMOVU
FCOMI
FCOMIP
IMUL3L, IMUL3Q, IMUL3W
ICEBP, INT
INVPCID
LARQ
LGDT, LIDT, LLDT
LMSW
LTR
LZCNTL, LZCNTQ, LZCNTW
MONITOR
MOVBELL, MOVBEQQ, MOVBEWW
MOVBQZX
MOVQ
MOVSWW, MOVZWW
MWAIT
NOPL, NOPW
PBLENDVB
PEXTRW
RDPKRU
RDRANDL, RDRANDQ, RDRANDW
RDSEEDL, RDSEEDQ, RDSEEDW
RDTSCP
SAHF
SGDT, SIDT
SLDTL, SLDTQ, SLDTW
SMSWL, SMSWQ, SMSWW
STAC
STRL, STRQ, STRW
SYSENTER, SYSENTER64
SYSEXIT, SYSEXIT64
SHA256RNDS2
TZCNTL, TZCNTQ, TZCNTW
UD1, UD2
WRPKRU
XRSTOR, XRSTOR64
XRSTORS, XRSTORS64
XSAVE, XSAVE64
XSAVEC, XSAVEC64
XSAVEOPT, XSAVEOPT64
XSAVES, XSAVES64
XSETBV
Fixes #6739
Change-Id: I8b125d9a5ea39bb4b9da7e66a63a16f609cef376
Reviewed-on: https://go-review.googlesource.com/97235
Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-02-26 22:23:37 +03:00
ACMPXCHG16B : true ,
ACMPXCHG8B : true ,
ADECB : true ,
ADECL : true ,
ADECQ : true ,
ADECW : true ,
AFBSTP : true ,
AFFREE : true ,
AFLDENV : true ,
AFSAVE : true ,
AFSTCW : true ,
AFSTENV : true ,
AFSTSW : true ,
AFXSAVE64 : true ,
AFXSAVE : true ,
AINCB : true ,
AINCL : true ,
AINCQ : true ,
AINCW : true ,
ANEGB : true ,
ANEGL : true ,
ANEGQ : true ,
ANEGW : true ,
ANOTB : true ,
ANOTL : true ,
ANOTQ : true ,
ANOTW : true ,
APOPL : true ,
APOPQ : true ,
APOPW : true ,
ARDFSBASEL : true ,
ARDFSBASEQ : true ,
ARDGSBASEL : true ,
ARDGSBASEQ : true ,
2023-04-07 06:15:59 +10:00
ARDPID : true ,
cmd/internal/obj/x86: add missing legacy insts
Minimizes the amount of "TODO" stuff in test suite
of cmd/asm/internal/asm/testdata/amd64enc.s.
Some instructions were already implemented, but
test cases for them were commented-out.
Does not enable MMX instructions, calls/jumps and some
segment registers instructions.
-- Affected instructions --
BLENDVPD, BLENDVPS
BSWAPW
CBW
CDQE
CLAC
CLFLUSHOPT
CMPXCHG16B
CRC32B, CRC32L, CRC32W
CWDE
FBLD
FBSTP
FCMOVB
FCMOVBE
FCMOVE
FCMOVNB
FCMOVNBE
FCMOVU
FCOMI
FCOMIP
IMUL3L, IMUL3Q, IMUL3W
ICEBP, INT
INVPCID
LARQ
LGDT, LIDT, LLDT
LMSW
LTR
LZCNTL, LZCNTQ, LZCNTW
MONITOR
MOVBELL, MOVBEQQ, MOVBEWW
MOVBQZX
MOVQ
MOVSWW, MOVZWW
MWAIT
NOPL, NOPW
PBLENDVB
PEXTRW
RDPKRU
RDRANDL, RDRANDQ, RDRANDW
RDSEEDL, RDSEEDQ, RDSEEDW
RDTSCP
SAHF
SGDT, SIDT
SLDTL, SLDTQ, SLDTW
SMSWL, SMSWQ, SMSWW
STAC
STRL, STRQ, STRW
SYSENTER, SYSENTER64
SYSEXIT, SYSEXIT64
SHA256RNDS2
TZCNTL, TZCNTQ, TZCNTW
UD1, UD2
WRPKRU
XRSTOR, XRSTOR64
XRSTORS, XRSTORS64
XSAVE, XSAVE64
XSAVEC, XSAVEC64
XSAVEOPT, XSAVEOPT64
XSAVES, XSAVES64
XSETBV
Fixes #6739
Change-Id: I8b125d9a5ea39bb4b9da7e66a63a16f609cef376
Reviewed-on: https://go-review.googlesource.com/97235
Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-02-26 22:23:37 +03:00
ARDRANDL : true ,
ARDRANDQ : true ,
ARDRANDW : true ,
ARDSEEDL : true ,
ARDSEEDQ : true ,
ARDSEEDW : true ,
ASETCC : true ,
ASETCS : true ,
ASETEQ : true ,
ASETGE : true ,
ASETGT : true ,
ASETHI : true ,
ASETLE : true ,
ASETLS : true ,
ASETLT : true ,
ASETMI : true ,
ASETNE : true ,
ASETOC : true ,
ASETOS : true ,
ASETPC : true ,
ASETPL : true ,
ASETPS : true ,
ASGDT : true ,
ASIDT : true ,
ASLDTL : true ,
ASLDTQ : true ,
ASLDTW : true ,
ASMSWL : true ,
ASMSWQ : true ,
ASMSWW : true ,
ASTMXCSR : true ,
ASTRL : true ,
ASTRQ : true ,
ASTRW : true ,
AXSAVE64 : true ,
AXSAVE : true ,
AXSAVEC64 : true ,
AXSAVEC : true ,
AXSAVEOPT64 : true ,
AXSAVEOPT : true ,
AXSAVES64 : true ,
AXSAVES : true ,
2015-03-02 11:04:06 -08:00
}
2015-01-19 14:34:58 -05:00
var Linkamd64 = obj . LinkArch {
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
Arch : sys . ArchAMD64 ,
Init : instinit ,
2021-01-13 15:45:28 -08:00
ErrorCheck : errorCheck ,
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
Preprocess : preprocess ,
Assemble : span6 ,
Progedit : progedit ,
2023-01-16 16:21:48 +01:00
SEH : populateSeh ,
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
UnaryDst : unaryDst ,
DWARFRegisters : AMD64DWARFRegisters ,
2015-01-19 14:34:58 -05:00
}
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
var Link386 = obj . LinkArch {
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
Arch : sys . Arch386 ,
Init : instinit ,
Preprocess : preprocess ,
Assemble : span6 ,
Progedit : progedit ,
UnaryDst : unaryDst ,
2017-11-15 13:45:31 -05:00
DWARFRegisters : X86DWARFRegisters ,
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
}