From dfd2e8027c77363d7b8fa7fb23e9979ba6c1b167 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 29 Nov 2025 03:27:05 +1100 Subject: cmd/internal/obj/riscv: materialise 32 bit unsigned constants Currently, we only materialise 32 bit signed constants - a 32 unsigned value that exceeds the 32 bit signed maximum value is loaded from rodata. A 32 bit unsigned value can be materialized by loading and zero extending, which requires four instructions on rva20u64 - on rva22u64 and above only three instructions are required. Change-Id: I874a457f329ac75c2a0fb59b453cf8ef17df2972 Reviewed-on: https://go-review.googlesource.com/c/go/+/748962 Reviewed-by: Mark Ryan Reviewed-by: David Chase Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/cmd/internal/obj/riscv/obj.go | 22 +++++++++++++++++++--- src/cmd/internal/obj/riscv/obj_test.go | 7 ++++--- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 28bba008f7..5bab0ff419 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -3461,19 +3461,28 @@ func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) { // See if we can reconstruct this value from a small negative constant. rsh = bits.LeadingZeros64(uint64(v)) ones := bits.OnesCount64((uint64(v) >> lsh) >> 11) - c = signExtend(1<<11|((v>>lsh)&0x7ff), 12) if rsh+ones+lsh+11 == 64 { + c = signExtend(1<<11|((v>>lsh)&0x7ff), 12) if lsh > 0 || c != -1 { lsh += rsh } return c, lsh, rsh, true } + // See if we can reconstruct this value from a zero extended signed + // 32 bit integer. This will require four instructions on rva20u64 + // and three instructions on rva22u64 or higher. + if int64(uint32(c)) == c { + c = int64(int32(c)) + lsh, rsh = 32, 32-lsh + return c, lsh, rsh, true + } + return 0, 0, 0, false } // isShiftConst indicates whether a constant can be represented as a signed -// 32 bit integer that is left shifted. +// 32 bit integer that is left and/or right shifted. func isShiftConst(v int64) bool { _, lsh, rsh, ok := splitShiftConst(v) return ok && (lsh > 0 || rsh > 0) @@ -3908,10 +3917,14 @@ func instructionsForMOVConst(p *obj.Prog) []*instruction { // SLLI $13, X10 // SRLI $12, X10 // - var insSLLI, insSRLI *instruction + var insSLLI, insSRLI, insMOVWU *instruction if err := immIFits(ins.imm, 32); err != nil { if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok { ins.imm = c + if buildcfg.GORISCV64 >= 22 && lsh == 32 && rsh == 32 { + insMOVWU = &instruction{as: AADDUW, rd: ins.rd, rs1: ins.rd, rs2: REG_ZERO} + lsh, rsh = 0, 0 + } if lsh > 0 { insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)} } @@ -3941,6 +3954,9 @@ func instructionsForMOVConst(p *obj.Prog) []*instruction { inss = append(inss, ins) } } + if insMOVWU != nil { + inss = append(inss, insMOVWU) + } if insSLLI != nil { inss = append(inss, insSLLI) } diff --git a/src/cmd/internal/obj/riscv/obj_test.go b/src/cmd/internal/obj/riscv/obj_test.go index 87b31e5a89..d4e7e14db6 100644 --- a/src/cmd/internal/obj/riscv/obj_test.go +++ b/src/cmd/internal/obj/riscv/obj_test.go @@ -17,12 +17,13 @@ func TestSplitShiftConst(t *testing.T) { wantRsh int wantOk bool }{ - {0x100000000, 1, 32, 0, true}, - {0xfffff001, 0, 0, 0, false}, + {0xfffff001, -4095, 32, 32, true}, {0xfffff801, -2047, 32, 32, true}, {0xfffffff1, -15, 32, 32, true}, {0xffffffff, -1, 0, 32, true}, {0xfffffffe, 0x7fffffff, 1, 0, true}, + {0x80a9b553, -2136361645, 32, 32, true}, + {0x100000000, 1, 32, 0, true}, {0xfffffffffffda, -19, 13, 12, true}, {0xfffffffffffde, -17, 13, 12, true}, {0x000003ffffffffff, -1, 0, 22, true}, @@ -31,7 +32,7 @@ func TestSplitShiftConst(t *testing.T) { {0x7fffffffffffffff, -1, 0, 1, true}, {0x7f7f7f7f7f7f7f7f, 0, 0, 0, false}, {0x0080000010000000, 0x8000001, 28, 0, true}, - {0x0abcdabcd0000000, 0, 0, 0, false}, + {0x0abcdabcd0000000, -1412584499, 32, 4, true}, {-4503599610593281, 0, 0, 0, false}, // 0x8abcdabcd0000000 {-7543254330000000, 0, 0, 0, false}, // 0xfff0000000ffffff } -- cgit v1.3