]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: don't split ADD to SP to two adds
authorCherry Mui <cherryyz@google.com>
Mon, 25 Oct 2021 16:18:40 +0000 (12:18 -0400)
committerCherry Mui <cherryyz@google.com>
Mon, 25 Oct 2021 23:28:03 +0000 (23:28 +0000)
When adding a large constant to a register we generate two adds,
we may generate two ADD instructions if the constant does not fit
in one ADD but does fit in two. This is generally fine except that
if the target register is SP (such as in function prologues or
epilogues for functions with large frames), this creates an
intermediate state that the SP is not 0 nor the full frame size.
For signal safety (preemption signal and profiling signal) we
require that the frame is either not created at all or fully
created, meaning that the SP must be written in a single
instruction. Splitting to two adds breaks the requirement. So not
splitting it.

(We could mark such instructions not async-preemptible. But
profiling signal can still cause problems.)

(We could generate "ADD $c1, SP, Rtmp; ADD $c2; Rtmp; SP" to save
an instruction if that is desired, while still ensuring that SP
is written in a single instruction.)

May fix flaky failures like https://build.golang.org/log/11537ec020a902b0ec0fc065f61161b729eb9880

Change-Id: I5cf38a6a028afe01aa3b6eeb163487bbd504b64f
Reviewed-on: https://go-review.googlesource.com/c/go/+/358436
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Joel Sing <joel@sing.id.au>
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/internal/obj/riscv/obj.go

index d98806edb5d61f22f11c103e9ef0e529a51dbb88..c27ad99b2d20de492c6841cbaebea7394fe4fae7 100644 (file)
@@ -1610,7 +1610,8 @@ func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction
        }
 
        // Split into two additions, if possible.
-       if ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
+       // Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
+       if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
                imm0 := ins.imm / 2
                imm1 := ins.imm - imm0