aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/riscv/obj.go22
-rw-r--r--src/cmd/internal/obj/riscv/obj_test.go7
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
}