RISC-V: Promode modes of constant loads for store insns.
authorJim Wilson <jimw@sifive.com>
Sat, 27 Apr 2019 00:46:20 +0000 (00:46 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Sat, 27 Apr 2019 00:46:20 +0000 (17:46 -0700)
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

gcc/ChangeLog
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv.c
gcc/config/riscv/riscv.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/riscv/load-immediate.c [new file with mode: 0644]

index 4434ba5648328ecfb1f0d202db1478a5e0c3d37c..e5de2dfaac3f2559db6bc6466b6a586105b2a186 100644 (file)
@@ -1,3 +1,17 @@
+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>
 
        * gdbhooks.py: Fix UnicodeDecodeErrors when printing trees with
index 8b510f87df87b0d17d011243f8108e4bb310c5b0..5c1002bbc291550d5f5066d1d9215a723e84df34 100644 (file)
@@ -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_type (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 rtx riscv_subword (rtx, bool);
 extern bool riscv_split_64bit_move_p (rtx, rtx);
index e7440f3909510882c013f30f4d03e1a11636dd8a..6fb6c6ad3728af95edd32b089feb2eae6549b6b7 100644 (file)
@@ -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);
   rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode);
 
-  riscv_move_integer (hi, hi, hival);
-  riscv_move_integer (lo, lo, loval);
+  riscv_move_integer (hi, hi, hival, mode);
+  riscv_move_integer (lo, lo, loval, mode);
 
   hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32));
   hi = force_reg (mode, hi);
@@ -1334,10 +1334,12 @@ riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   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
-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];
   machine_mode mode;
@@ -1345,7 +1347,9 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value)
   rtx x;
 
   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 */
       && num_ops >= riscv_split_integer_cost (value))
@@ -1381,7 +1385,7 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
   /* Split moves of big integers into smaller pieces.  */
   if (splittable_const_int_operand (src, mode))
     {
-      riscv_move_integer (dest, dest, INTVAL (src));
+      riscv_move_integer (dest, dest, INTVAL (src), mode);
       return;
     }
 
@@ -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))
     {
-      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;
     }
 
index e3799a5bdd8b6efed7ab457ac5ef9ed6fa35b393..fc81daa43eff5dffafae5b65ca5dd1b46d28daff 100644 (file)
   ""
   [(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;
 })
 
index 9322205f0f51a33292e5c91380c2894a91f3c487..4c68148e67be177e1b9dbba2ee7e4fb2358e10be 100644 (file)
@@ -1,3 +1,7 @@
+2019-04-26  Jim Wilson  <jimw@sifive.com>
+
+       * gcc.target/riscv/load-immediate.c: New.
+
 2019-04-26  Jonathan Wakely  <jwakely@redhat.com>
 
        PR c++/90243
diff --git a/gcc/testsuite/gcc.target/riscv/load-immediate.c b/gcc/testsuite/gcc.target/riscv/load-immediate.c
new file mode 100644 (file)
index 0000000..f8fe747
--- /dev/null
@@ -0,0 +1,32 @@
+/* { 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 } } */