RISC-V: Improve li expansion for better code density.
li is a pseudo instruction in RISC-V, it might expand to more than one instructions if the immediate value can't fit addi or lui, but the assembler will always using 4-byte instructions during expansion. For example: li a0, 0x12345001 will expand into 12345537 lui a0,0x12345 00150513 addi a0,a0,1 but addi could be compress into 0505 addi a0,a0,1 It because load_const use macro_build to emit instructions, and macro_build call append_insn, and expect it will compress it if possible, but the fact is append_insn never compress anything, So this patch redirect the li expansion flow to normal instruction emission flow via md_assemble, added md_assemblef as an wrapper for that for easier emit instruction with printf-style argument to build instruction. gas/ChangeLog: * tc-riscv.c (md_assemblef): New. (load_const) Use md_assemblef instead of macro_build to emit instructions. * testsuite/gas/riscv/li32.d: New. * testsuite/gas/riscv/li32.s: Ditto. * testsuite/gas/riscv/li64.d: Ditto. * testsuite/gas/riscv/li64.s: Ditto.
This commit is contained in:
parent
23c13d4299
commit
db3b6ecc28
@ -928,6 +928,29 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
|
|||||||
append_insn (&insn, ep, r);
|
append_insn (&insn, ep, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build an instruction created by a macro expansion. Like md_assemble but
|
||||||
|
accept a printf-style format string and arguments. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
md_assemblef (const char *format, ...)
|
||||||
|
{
|
||||||
|
char *buf = NULL;
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
va_start (ap, format);
|
||||||
|
|
||||||
|
r = vasprintf (&buf, format, ap);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
as_fatal (_("internal error: vasprintf failed"));
|
||||||
|
|
||||||
|
md_assemble (buf);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
/* Sign-extend 32-bit mode constants that have bit 31 set and all higher bits
|
/* Sign-extend 32-bit mode constants that have bit 31 set and all higher bits
|
||||||
unset. */
|
unset. */
|
||||||
static void
|
static void
|
||||||
@ -1013,6 +1036,7 @@ static void
|
|||||||
load_const (int reg, expressionS *ep)
|
load_const (int reg, expressionS *ep)
|
||||||
{
|
{
|
||||||
int shift = RISCV_IMM_BITS;
|
int shift = RISCV_IMM_BITS;
|
||||||
|
bfd_vma upper_imm;
|
||||||
expressionS upper = *ep, lower = *ep;
|
expressionS upper = *ep, lower = *ep;
|
||||||
lower.X_add_number = (int32_t) ep->X_add_number << (32-shift) >> (32-shift);
|
lower.X_add_number = (int32_t) ep->X_add_number << (32-shift) >> (32-shift);
|
||||||
upper.X_add_number -= lower.X_add_number;
|
upper.X_add_number -= lower.X_add_number;
|
||||||
@ -1032,9 +1056,10 @@ load_const (int reg, expressionS *ep)
|
|||||||
upper.X_add_number = (int64_t) upper.X_add_number >> shift;
|
upper.X_add_number = (int64_t) upper.X_add_number >> shift;
|
||||||
load_const (reg, &upper);
|
load_const (reg, &upper);
|
||||||
|
|
||||||
macro_build (NULL, "slli", "d,s,>", reg, reg, shift);
|
md_assemblef ("slli x%d, x%d, 0x%x", reg, reg, shift);
|
||||||
if (lower.X_add_number != 0)
|
if (lower.X_add_number != 0)
|
||||||
macro_build (&lower, "addi", "d,s,j", reg, reg, BFD_RELOC_RISCV_LO12_I);
|
md_assemblef ("addi x%d, x%d, %" BFD_VMA_FMT "d", reg, reg,
|
||||||
|
lower.X_add_number);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1043,13 +1068,16 @@ load_const (int reg, expressionS *ep)
|
|||||||
|
|
||||||
if (upper.X_add_number != 0)
|
if (upper.X_add_number != 0)
|
||||||
{
|
{
|
||||||
macro_build (ep, "lui", "d,u", reg, BFD_RELOC_RISCV_HI20);
|
/* Discard low part and zero-extend upper immediate. */
|
||||||
|
upper_imm = ((uint32_t)upper.X_add_number >> shift);
|
||||||
|
|
||||||
|
md_assemblef ("lui x%d, 0x%" BFD_VMA_FMT "x", reg, upper_imm);
|
||||||
hi_reg = reg;
|
hi_reg = reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lower.X_add_number != 0 || hi_reg == 0)
|
if (lower.X_add_number != 0 || hi_reg == 0)
|
||||||
macro_build (ep, ADD32_INSN, "d,s,j", reg, hi_reg,
|
md_assemblef ("%s x%d, x%d, %" BFD_VMA_FMT "d", ADD32_INSN, reg, hi_reg,
|
||||||
BFD_RELOC_RISCV_LO12_I);
|
lower.X_add_number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
gas/testsuite/gas/riscv/li32.d
Normal file
17
gas/testsuite/gas/riscv/li32.d
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#as: -march=rv32ic -mabi=ilp32
|
||||||
|
#objdump: -dr
|
||||||
|
|
||||||
|
.*: file format elf32-littleriscv
|
||||||
|
|
||||||
|
|
||||||
|
Disassembly of section .text:
|
||||||
|
|
||||||
|
0+000 <target>:
|
||||||
|
[^:]+:[ ]+6521[ ]+lui[ ]+a0,0x8
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+6509[ ]+lui[ ]+a0,0x2
|
||||||
|
[^:]+:[ ]+f0150513[ ]+addi[ ]+a0,a0,-255 # .*
|
||||||
|
[^:]+:[ ]+12345537[ ]+lui[ ]+a0,0x12345
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+f2345537[ ]+lui[ ]+a0,0xf2345
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
5
gas/testsuite/gas/riscv/li32.s
Normal file
5
gas/testsuite/gas/riscv/li32.s
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
target:
|
||||||
|
li a0, 0x8001
|
||||||
|
li a0, 0x1f01
|
||||||
|
li a0, 0x12345001
|
||||||
|
li a0, 0xf2345001
|
44
gas/testsuite/gas/riscv/li64.d
Normal file
44
gas/testsuite/gas/riscv/li64.d
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#as: -march=rv64ic -mabi=lp64
|
||||||
|
#objdump: -dr
|
||||||
|
|
||||||
|
.*: file format elf64-littleriscv
|
||||||
|
|
||||||
|
|
||||||
|
Disassembly of section .text:
|
||||||
|
|
||||||
|
0000000000000000 <target>:
|
||||||
|
[^:]+:[ ]+6521[ ]+lui[ ]+a0,0x8
|
||||||
|
[^:]+:[ ]+2505[ ]+addiw[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+6509[ ]+lui[ ]+a0,0x2
|
||||||
|
[^:]+:[ ]+f015051b[ ]+addiw[ ]+a0,a0,-255
|
||||||
|
[^:]+:[ ]+12345537[ ]+lui[ ]+a0,0x12345
|
||||||
|
[^:]+:[ ]+2505[ ]+addiw[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+000f2537[ ]+lui[ ]+a0,0xf2
|
||||||
|
[^:]+:[ ]+3455051b[ ]+addiw[ ]+a0,a0,837
|
||||||
|
[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+00f12537[ ]+lui[ ]+a0,0xf12
|
||||||
|
[^:]+:[ ]+3455051b[ ]+addiw[ ]+a0,a0,837
|
||||||
|
[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+ff010537[ ]+lui[ ]+a0,0xff010
|
||||||
|
[^:]+:[ ]+f015051b[ ]+addiw[ ]+a0,a0,-255
|
||||||
|
[^:]+:[ ]+054e[ ]+slli[ ]+a0,a0,0x13
|
||||||
|
[^:]+:[ ]+80150513[ ]+addi[ ]+a0,a0,-2047 # .*
|
||||||
|
[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
|
||||||
|
[^:]+:[ ]+f0150513[ ]+addi[ ]+a0,a0,-255
|
||||||
|
[^:]+:[ ]+0010051b[ ]+addiw[ ]+a0,zero,1
|
||||||
|
[^:]+:[ ]+151a[ ]+slli[ ]+a0,a0,0x26
|
||||||
|
[^:]+:[ ]+1565[ ]+addi[ ]+a0,a0,-7
|
||||||
|
[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
|
||||||
|
[^:]+:[ ]+34550513[ ]+addi[ ]+a0,a0,837
|
||||||
|
[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
||||||
|
[^:]+:[ ]+01fc4537[ ]+lui[ ]+a0,0x1fc4
|
||||||
|
[^:]+:[ ]+c915051b[ ]+addiw[ ]+a0,a0,-879
|
||||||
|
[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
|
||||||
|
[^:]+:[ ]+1565[ ]+addi[ ]+a0,a0,-7
|
||||||
|
[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
|
||||||
|
[^:]+:[ ]+34550513[ ]+addi[ ]+a0,a0,837 # .*
|
||||||
|
[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
|
||||||
|
[^:]+:[ ]+0505[ ]+addi[ ]+a0,a0,1
|
9
gas/testsuite/gas/riscv/li64.s
Normal file
9
gas/testsuite/gas/riscv/li64.s
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
target:
|
||||||
|
li a0, 0x8001
|
||||||
|
li a0, 0x1f01
|
||||||
|
li a0, 0x12345001
|
||||||
|
li a0, 0xf2345001
|
||||||
|
li a0, 0xf12345001
|
||||||
|
li a0, 0xff00ff00ff001f01
|
||||||
|
li a0, 0x7ffffffff2345001
|
||||||
|
li a0, 0x7f0f243ff2345001
|
Loading…
Reference in New Issue
Block a user