This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] RISC-V: Improve li expansion for better code density.


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
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]