diff options
Diffstat (limited to 'src/cmd/internal/obj')
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 22 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj_test.go | 7 |
2 files changed, 23 insertions, 6 deletions
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 } |
