summaryrefslogtreecommitdiff
path: root/gcc/config/riscv
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2018-02-23 22:36:54 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2018-02-23 22:36:54 +0000
commit88a3ea34080ad3087a8191fbf479543153175d59 (patch)
tree34eaec34d3588e09f9a77abba776266f124dc823 /gcc/config/riscv
parent25e15aaed275cdfef34b3ee6eb3cb4b43a48d44f (diff)
parente65055a558093bd4fc0b1b0024b7814cc187b8e8 (diff)
downloadgcc-88a3ea34080ad3087a8191fbf479543153175d59.tar.gz
Merge from trunk revision 257954.gccgo
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gccgo@257955 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/riscv')
-rw-r--r--gcc/config/riscv/riscv.c30
-rw-r--r--gcc/config/riscv/riscv.h4
2 files changed, 28 insertions, 6 deletions
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 */