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]

[PATCH v2] 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.
---
 gas/config/tc-riscv.c          | 38 +++++++++++++++++++++++++++++++-----
 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, 108 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..12047d7 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -928,6 +928,29 @@ 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 = 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
    unset.  */
 static void
@@ -1013,6 +1036,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 +1056,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 ("addi x%d, x%d, %" BFD_VMA_FMT "d", reg, reg,
+		      lower.X_add_number);
     }
   else
     {
@@ -1043,13 +1068,16 @@ load_const (int reg, expressionS *ep)
 
       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;
 	}
 
       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..5421303
--- /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
+[^:]+:[ 	]+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
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]