From e9eb66da307ec2da922a05b890b13363ea4e830e Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 25 Oct 2021 12:18:40 -0400 Subject: [PATCH] cmd/internal/obj/riscv: don't split ADD to SP to two adds 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 Run-TryBot: Cherry Mui Reviewed-by: Joel Sing TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/obj.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index d98806edb5..c27ad99b2d 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -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 -- 2.50.0