Commit 51175507 by Jim Wilson Committed by Jim Wilson

RISC-V: Promode modes of constant loads for store insns.

This improves optimization of code storing constants to memory.  Given this
testcase:
    void sub1 (int *a, long long *b) { *a = 1; *b = 1; }
an unpatched rv64 compiler emits two li instructions, one for an SImode pseudo
and one for a DImode pseudo.  With the patch, we get a single DImode li insn.

	gcc/
	* config/riscv/riscv-protos.h (riscv_move_integer): Add machine_mode
	parameter.
	* config/riscv/riscv.c (riscv_move_integer): New parameter orig_mode.
	Pass orig_mode to riscv_build_integer.
	(riscv_split_integer): Pass mode to riscv_move_integer.
	(riscv_legitimize_const_move): Likewise.
	(riscv_legitimize_move): For MEM dest and CONST_INT src case, new local
	promoted_mode.  Replace force_reg call with code to load constant into
	promoted reg and then subreg it for the store.
	* config/riscv/riscv.md (low<mode>+1): Pass <GPR:MODE>mode to
	riscv_move_integer.

	gcc/testsuite/
	* gcc.target/riscv/load-immediate.c: New.

From-SVN: r270621
parent 0d056d03
2019-04-26 Jim Wilson <jimw@sifive.com>
* config/riscv/riscv-protos.h (riscv_move_integer): Add machine_mode
parameter.
* config/riscv/riscv.c (riscv_move_integer): New parameter orig_mode.
Pass orig_mode to riscv_build_integer.
(riscv_split_integer): Pass mode to riscv_move_integer.
(riscv_legitimize_const_move): Likewise.
(riscv_legitimize_move): For MEM dest and CONST_INT src case, new local
promoted_mode. Replace force_reg call with code to load constant into
promoted reg and then subreg it for the store.
* config/riscv/riscv.md (low<mode>+1): Pass <GPR:MODE>mode to
riscv_move_integer.
2018-04-26 Eugene Sharygin <eush@ispras.ru> 2018-04-26 Eugene Sharygin <eush@ispras.ru>
* gdbhooks.py: Fix UnicodeDecodeErrors when printing trees with * gdbhooks.py: Fix UnicodeDecodeErrors when printing trees with
......
...@@ -47,7 +47,7 @@ extern rtx riscv_emit_move (rtx, rtx); ...@@ -47,7 +47,7 @@ extern rtx riscv_emit_move (rtx, rtx);
extern bool riscv_split_symbol (rtx, rtx, machine_mode, rtx *); extern bool riscv_split_symbol (rtx, rtx, machine_mode, rtx *);
extern bool riscv_split_symbol_type (enum riscv_symbol_type); extern bool riscv_split_symbol_type (enum riscv_symbol_type);
extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type); extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type);
extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT); extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT, machine_mode);
extern bool riscv_legitimize_move (machine_mode, rtx, rtx); extern bool riscv_legitimize_move (machine_mode, rtx, rtx);
extern rtx riscv_subword (rtx, bool); extern rtx riscv_subword (rtx, bool);
extern bool riscv_split_64bit_move_p (rtx, rtx); extern bool riscv_split_64bit_move_p (rtx, rtx);
......
...@@ -508,8 +508,8 @@ riscv_split_integer (HOST_WIDE_INT val, machine_mode mode) ...@@ -508,8 +508,8 @@ riscv_split_integer (HOST_WIDE_INT val, machine_mode mode)
unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32);
rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode); rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode);
riscv_move_integer (hi, hi, hival); riscv_move_integer (hi, hi, hival, mode);
riscv_move_integer (lo, lo, loval); riscv_move_integer (lo, lo, loval, mode);
hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32)); hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32));
hi = force_reg (mode, hi); hi = force_reg (mode, hi);
...@@ -1334,10 +1334,12 @@ riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1334,10 +1334,12 @@ riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return x; return x;
} }
/* Load VALUE into DEST. TEMP is as for riscv_force_temporary. */ /* Load VALUE into DEST. TEMP is as for riscv_force_temporary. ORIG_MODE
is the original src mode before promotion. */
void void
riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value) riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value,
machine_mode orig_mode)
{ {
struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS];
machine_mode mode; machine_mode mode;
...@@ -1345,7 +1347,9 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value) ...@@ -1345,7 +1347,9 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value)
rtx x; rtx x;
mode = GET_MODE (dest); mode = GET_MODE (dest);
num_ops = riscv_build_integer (codes, value, mode); /* We use the original mode for the riscv_build_integer call, because HImode
values are given special treatment. */
num_ops = riscv_build_integer (codes, value, orig_mode);
if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */ if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */
&& num_ops >= riscv_split_integer_cost (value)) && num_ops >= riscv_split_integer_cost (value))
...@@ -1381,7 +1385,7 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src) ...@@ -1381,7 +1385,7 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
/* Split moves of big integers into smaller pieces. */ /* Split moves of big integers into smaller pieces. */
if (splittable_const_int_operand (src, mode)) if (splittable_const_int_operand (src, mode))
{ {
riscv_move_integer (dest, dest, INTVAL (src)); riscv_move_integer (dest, dest, INTVAL (src), mode);
return; return;
} }
...@@ -1428,7 +1432,31 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) ...@@ -1428,7 +1432,31 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
{ {
if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
{ {
riscv_emit_move (dest, force_reg (mode, src)); rtx reg;
if (GET_CODE (src) == CONST_INT)
{
/* Apply the equivalent of PROMOTE_MODE here for constants to
improve cse. */
machine_mode promoted_mode = mode;
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
promoted_mode = word_mode;
if (splittable_const_int_operand (src, mode))
{
reg = gen_reg_rtx (promoted_mode);
riscv_move_integer (reg, reg, INTVAL (src), mode);
}
else
reg = force_reg (promoted_mode, src);
if (promoted_mode != mode)
reg = gen_lowpart (mode, reg);
}
else
reg = force_reg (mode, src);
riscv_emit_move (dest, reg);
return true; return true;
} }
......
...@@ -1278,7 +1278,8 @@ ...@@ -1278,7 +1278,8 @@
"" ""
[(const_int 0)] [(const_int 0)]
{ {
riscv_move_integer (operands[2], operands[0], INTVAL (operands[1])); riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
<GPR:MODE>mode);
DONE; DONE;
}) })
......
2019-04-26 Jim Wilson <jimw@sifive.com>
* gcc.target/riscv/load-immediate.c: New.
2019-04-26 Jonathan Wakely <jwakely@redhat.com> 2019-04-26 Jonathan Wakely <jwakely@redhat.com>
PR c++/90243 PR c++/90243
......
/* { dg-do compile } */
/* { dg-options "-march=rv64gc -mabi=lp64d -O2" } */
/* Check that we don't have unnecessary load immediate instructions. */
void
sub1 (int *a, long long *b)
{
*a = 1;
*b = 1;
}
void
sub2 (short *a, short *b)
{
*a = -32768;
*b = 32767;
}
void
sub3 (int *a, long long *b)
{
*a = 10000;
*b = 10000;
}
void
sub4 (int *a, short *b)
{
*a = 1;
*b = 1;
}
/* { dg-final { scan-assembler-times "\tli\t" 4 } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment