Skip to content

Commit 28dae3d

Browse files
committed
cmd/internal/obj/riscv: improve code generation for loading of constants
Loading of constants that are 12 bits or smaller is currently performed using a single ADDIW instruction, while constants between 13 bits and 32 bits are loaded using a LUI+ADDIW pair. Instead, use a single ADDI instruction for the 12 bits or smaller case - this translates to the LI pseudo-instruction, making objdump more readable and giving: 11c7c: fff00293 li t0,-1 11c80: 00000313 li t1,0 Rather than: 11c7c: fff0029b addiw t0,zero,-1 11c80: 0000031b sext.w t1,zero In the case where a constant exceeds 12 bits, an LUI instruction is required, however if the lower 12 bits are zero, the ADDIW instruction can be omitted. The same applies to the case where immediate splitting is performed for other immediate instructions. This removes around 900 instructions from the Go binary. Change-Id: Id6c77774b3b429fa525da018a6926b85df838a2f Reviewed-on: https://go-review.googlesource.com/c/go/+/344457 Trust: Joel Sing <[email protected]> Run-TryBot: Joel Sing <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 37e9c1d commit 28dae3d

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

src/cmd/asm/internal/asm/testdata/riscv64.s

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,14 @@ start:
295295

296296
// MOV pseudo-instructions
297297
MOV X5, X6 // 13830200
298-
MOV $2047, X5 // 9b02f07f
299-
MOV $-2048, X5 // 9b020080
298+
MOV $2047, X5 // 9302f07f
299+
MOV $-2048, X5 // 93020080
300300
MOV $2048, X5 // b71200009b820280
301301
MOV $-2049, X5 // b7f2ffff9b82f27f
302+
MOV $4096, X5 // b7120000
303+
MOV $2147479552, X5 // b7f2ff7f
304+
MOV $2147483647, X5 // b70200809b82f2ff
305+
MOV $-2147483647, X5 // b70200809b821200
302306

303307
// Converted to load of symbol (AUIPC + LD)
304308
MOV $4294967296, X5 // 9702000083b20200

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,9 @@ func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction
16691669
return nil
16701670
}
16711671
ins.rs2 = REG_TMP
1672+
if low == 0 {
1673+
return []*instruction{insLUI, ins}
1674+
}
16721675
return []*instruction{insLUI, insADDIW, ins}
16731676
}
16741677

@@ -1768,7 +1771,7 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
17681771
}
17691772

17701773
// MOV $c, R -> ADD $c, ZERO, R
1771-
ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, REG_ZERO, obj.REG_NONE, low
1774+
ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
17721775

17731776
// LUI is only necessary if the constant does not fit in 12 bits.
17741777
if high == 0 {
@@ -1778,8 +1781,11 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
17781781
// LUI top20bits(c), R
17791782
// ADD bottom12bits(c), R, R
17801783
insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
1781-
ins.rs1 = ins.rd
1782-
inss = []*instruction{insLUI, ins}
1784+
inss = []*instruction{insLUI}
1785+
if low != 0 {
1786+
ins.as, ins.rs1 = AADDIW, ins.rd
1787+
inss = append(inss, ins)
1788+
}
17831789

17841790
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
17851791
// Handle register to register moves.

0 commit comments

Comments
 (0)