RISC-V: Change sp subtracts so prologue stores can compress.

Message ID 20180215011512.23603-1-jimw@sifive.com
State New
Headers show
Series
  • RISC-V: Change sp subtracts so prologue stores can compress.
Related show

Commit Message

Jim Wilson Feb. 15, 2018, 1:15 a.m.
This patch changes the initial stack pointer subtraction when we need two
subtracts, so that the first stack pointer subtraction allows the register
save stores to compress.  This is only done for RVC targets, and only when
it doesn't change the number of instructions required.  A follow on patch
may change this further when -Os is used, to allow an extra instruction or two
if it results in smaller code in the end.

This initial patch doesn't affect many functions, but is useful when it can
trigger.  For instance, in the newlib vfwscanf file, text size reduces from
4006 to 3954.

This was tested with rv32/rv64 newlib/linux builds.  There were no regressions.

Committed.

Jim

	gcc/
	* config/riscv/riscv.c (riscv_first_stack_step): Move locals after
	first SMALL_OPERAND check.  New local min_second_step.  Move assert
	to where locals are set.  Add TARGET_RVC support.
	* config/riscv/riscv.h (C_SxSP_BITS, SWSP_REACH, SDSP_REACH): New.
---
 gcc/config/riscv/riscv.c | 30 ++++++++++++++++++++++++------
 gcc/config/riscv/riscv.h |  4 ++++
 2 files changed, 28 insertions(+), 6 deletions(-)

-- 
2.14.1

Patch

diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 4ef7a1774c4..c38f6c394d5 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -3495,25 +3495,43 @@  riscv_output_gpr_save (unsigned mask)
 
 /* For stack frames that can't be allocated with a single ADDI instruction,
    compute the best value to initially allocate.  It must at a minimum
-   allocate enough space to spill the callee-saved registers.  */
+   allocate enough space to spill the callee-saved registers.  If TARGET_RVC,
+   try to pick a value that will allow compression of the register saves
+   without adding extra instructions.  */
 
 static HOST_WIDE_INT
 riscv_first_stack_step (struct riscv_frame_info *frame)
 {
-  HOST_WIDE_INT min_first_step = frame->total_size - frame->fp_sp_offset;
-  HOST_WIDE_INT max_first_step = IMM_REACH / 2 - STACK_BOUNDARY / 8;
-
   if (SMALL_OPERAND (frame->total_size))
     return frame->total_size;
 
+  HOST_WIDE_INT min_first_step = frame->total_size - frame->fp_sp_offset;
+  HOST_WIDE_INT max_first_step = IMM_REACH / 2 - STACK_BOUNDARY / 8;
+  HOST_WIDE_INT min_second_step = frame->total_size - max_first_step;
+  gcc_assert (min_first_step <= max_first_step);
+
   /* As an optimization, use the least-significant bits of the total frame
      size, so that the second adjustment step is just LUI + ADD.  */
-  if (!SMALL_OPERAND (frame->total_size - max_first_step)
+  if (!SMALL_OPERAND (min_second_step)
       && frame->total_size % IMM_REACH < IMM_REACH / 2
       && frame->total_size % IMM_REACH >= min_first_step)
     return frame->total_size % IMM_REACH;
 
-  gcc_assert (min_first_step <= max_first_step);
+  if (TARGET_RVC)
+    {
+      /* If we need two subtracts, and one is small enough to allow compressed
+	 loads and stores, then put that one first.  */
+      if (IN_RANGE (min_second_step, 0,
+		    (TARGET_64BIT ? SDSP_REACH : SWSP_REACH)))
+	return MAX (min_second_step, min_first_step);
+
+      /* If we need LUI + ADDI + ADD for the second adjustment step, then start
+	 with the minimum first step, so that we can get compressed loads and
+	 stores.  */
+      else if (!SMALL_OPERAND (min_second_step))
+	return min_first_step;
+    }
+
   return max_first_step;
 }
 
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 1c1c3431119..6144e267727 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -891,9 +891,13 @@  extern unsigned riscv_stack_boundary;
 #define SHIFT_RS1 15
 #define SHIFT_IMM 20
 #define IMM_BITS 12
+#define C_SxSP_BITS 6
 
 #define IMM_REACH (1LL << IMM_BITS)
 #define CONST_HIGH_PART(VALUE) (((VALUE) + (IMM_REACH/2)) & ~(IMM_REACH-1))
 #define CONST_LOW_PART(VALUE) ((VALUE) - CONST_HIGH_PART (VALUE))
 
+#define SWSP_REACH (4LL << C_SxSP_BITS)
+#define SDSP_REACH (8LL << C_SxSP_BITS)
+
 #endif /* ! GCC_RISCV_H */