This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] RISC-V: Improve li expansion for better code density.
Hi Andrew:
Oh, thanks, I've used aspell to check commit log but not check comment :P
On Thu, Aug 22, 2019 at 4:35 PM Andrew Waterman <andrew@sifive.com> wrote:
> Thank you, Kito!
>
> There's a typo in a comment: "Dicard" should be "Discard".
>
> On Wed, Aug 21, 2019 at 11:40 PM Kito Cheng <kito.cheng@sifive.com> wrote:
>
>> 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.
>> ---
>> gas/config/tc-riscv.c | 47
>> +++++++++++++++++++++++++++++++++++++-----
>> gas/testsuite/gas/riscv/li32.d | 17 +++++++++++++++
>> gas/testsuite/gas/riscv/li32.s | 5 +++++
>> gas/testsuite/gas/riscv/li64.d | 44
>> +++++++++++++++++++++++++++++++++++++++
>> gas/testsuite/gas/riscv/li64.s | 9 ++++++++
>> 5 files changed, 117 insertions(+), 5 deletions(-)
>> create mode 100644 gas/testsuite/gas/riscv/li32.d
>> create mode 100644 gas/testsuite/gas/riscv/li32.s
>> create mode 100644 gas/testsuite/gas/riscv/li64.d
>> create mode 100644 gas/testsuite/gas/riscv/li64.s
>>
>> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
>> index f0c1f4c..fb4ce5c 100644
>> --- a/gas/config/tc-riscv.c
>> +++ b/gas/config/tc-riscv.c
>> @@ -928,6 +928,38 @@ macro_build (expressionS *ep, const char *name,
>> const char *fmt, ...)
>> 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[1024];
>> + char *dynbuf;
>> + int dynbuf_len;
>> + va_list ap;
>> + int r;
>> +
>> + va_start (ap, format);
>> +
>> + r = vsnprintf (buf, sizeof (buf), format, ap);
>> +
>> + if (r < sizeof (buf))
>> + md_assemble (buf);
>> + else
>> + {
>> + /* In case buf is not enough, malloc a large enough buffer
>> + and try again. */
>> + dynbuf_len = r + 1;
>> + dynbuf = (char *) xmalloc (dynbuf_len);
>> + r = vsnprintf (dynbuf, dynbuf_len, format, ap);
>> + md_assemble (dynbuf);
>> + xfree (dynbuf);
>> + }
>> +
>> + va_end (ap);
>> +}
>> +
>> /* Sign-extend 32-bit mode constants that have bit 31 set and all higher
>> bits
>> unset. */
>> static void
>> @@ -1013,6 +1045,7 @@ static void
>> load_const (int reg, expressionS *ep)
>> {
>> int shift = RISCV_IMM_BITS;
>> + bfd_vma upper_imm;
>> expressionS upper = *ep, lower = *ep;
>> lower.X_add_number = (int32_t) ep->X_add_number << (32-shift) >>
>> (32-shift);
>> upper.X_add_number -= lower.X_add_number;
>> @@ -1032,9 +1065,10 @@ load_const (int reg, expressionS *ep)
>> upper.X_add_number = (int64_t) upper.X_add_number >> shift;
>> 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)
>> - macro_build (&lower, "addi", "d,s,j", reg, reg,
>> BFD_RELOC_RISCV_LO12_I);
>> + md_assemblef ("%s x%d, x%d, %" BFD_VMA_FMT "d", ADD32_INSN, reg,
>> reg,
>> + lower.X_add_number);
>> }
>> else
>> {
>> @@ -1043,13 +1077,16 @@ load_const (int reg, expressionS *ep)
>>
>> if (upper.X_add_number != 0)
>> {
>> - macro_build (ep, "lui", "d,u", reg, BFD_RELOC_RISCV_HI20);
>> + /* Dicard low part and zero-extend uppper 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;
>> }
>>
>> if (lower.X_add_number != 0 || hi_reg == 0)
>> - macro_build (ep, ADD32_INSN, "d,s,j", reg, hi_reg,
>> - BFD_RELOC_RISCV_LO12_I);
>> + md_assemblef ("%s x%d, x%d, %" BFD_VMA_FMT "d", ADD32_INSN, reg,
>> hi_reg,
>> + lower.X_add_number);
>> }
>> }
>>
>> diff --git a/gas/testsuite/gas/riscv/li32.d
>> b/gas/testsuite/gas/riscv/li32.d
>> new file mode 100644
>> index 0000000..ff0827d
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/li32.d
>> @@ -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
>> diff --git a/gas/testsuite/gas/riscv/li32.s
>> b/gas/testsuite/gas/riscv/li32.s
>> new file mode 100644
>> index 0000000..1930cd8
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/li32.s
>> @@ -0,0 +1,5 @@
>> +target:
>> + li a0, 0x8001
>> + li a0, 0x1f01
>> + li a0, 0x12345001
>> + li a0, 0xf2345001
>> diff --git a/gas/testsuite/gas/riscv/li64.d
>> b/gas/testsuite/gas/riscv/li64.d
>> new file mode 100644
>> index 0000000..1aca62d
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/li64.d
>> @@ -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
>> +[^:]+:[ ]+2505[ ]+addiw[ ]+a0,a0,1
>> +[^:]+:[ ]+00f12537[ ]+lui[ ]+a0,0xf12
>> +[^:]+:[ ]+3455051b[ ]+addiw[ ]+a0,a0,837
>> +[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
>> +[^:]+:[ ]+2505[ ]+addiw[ ]+a0,a0,1
>> +[^:]+:[ ]+ff010537[ ]+lui[ ]+a0,0xff010
>> +[^:]+:[ ]+f015051b[ ]+addiw[ ]+a0,a0,-255
>> +[^:]+:[ ]+054e[ ]+slli[ ]+a0,a0,0x13
>> +[^:]+:[ ]+8015051b[ ]+addiw[ ]+a0,a0,-2047
>> +[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
>> +[^:]+:[ ]+f015051b[ ]+addiw[ ]+a0,a0,-255
>> +[^:]+:[ ]+0010051b[ ]+addiw[ ]+a0,zero,1
>> +[^:]+:[ ]+151a[ ]+slli[ ]+a0,a0,0x26
>> +[^:]+:[ ]+3565[ ]+addiw[ ]+a0,a0,-7
>> +[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
>> +[^:]+:[ ]+3455051b[ ]+addiw[ ]+a0,a0,837
>> +[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
>> +[^:]+:[ ]+2505[ ]+addiw[ ]+a0,a0,1
>> +[^:]+:[ ]+01fc4537[ ]+lui[ ]+a0,0x1fc4
>> +[^:]+:[ ]+c915051b[ ]+addiw[ ]+a0,a0,-879
>> +[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
>> +[^:]+:[ ]+3565[ ]+addiw[ ]+a0,a0,-7
>> +[^:]+:[ ]+0536[ ]+slli[ ]+a0,a0,0xd
>> +[^:]+:[ ]+3455051b[ ]+addiw[ ]+a0,a0,837
>> +[^:]+:[ ]+0532[ ]+slli[ ]+a0,a0,0xc
>> +[^:]+:[ ]+2505[ ]+addiw[ ]+a0,a0,1
>> diff --git a/gas/testsuite/gas/riscv/li64.s
>> b/gas/testsuite/gas/riscv/li64.s
>> new file mode 100644
>> index 0000000..aab19eb
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/li64.s
>> @@ -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
>> --
>> 2.7.4
>>
>>