mips.md (JOIN_MODE): New mode iterator.
authorPrachi Godbole <prachigodbole@gcc.gnu.org>
Tue, 19 May 2015 05:06:03 +0000 (05:06 +0000)
committerPrachi Godbole <prachigodbole@gcc.gnu.org>
Tue, 19 May 2015 05:06:03 +0000 (05:06 +0000)
gcc/
* config/mips/mips.md (JOIN_MODE): New mode iterator.
(join2_load_Store<JOIN_MODE:mode>): New pattern.
(join2_loadhi): Likewise.
(define_peehole2): Add peephole2 patterns to join 2 HI/SI/SF/DF-mode
load-load and store-stores.
* config/mips/mips.opt (mload-store-pairs): New option.
(TARGET_LOAD_STORE_PAIRS): New macro.
* config/mips/mips.h (ENABLE_LD_ST_PAIRS): Likewise.
* config/mips/mips-protos.h (mips_load_store_bonding_p): New prototype.
* config/mips/mips.c (mips_load_store_bonding_p): New function.

gcc/testsuite/
* gcc.target/mips/p5600-bonding.c : New file.

From-SVN: r223334

gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/mips.opt
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/p5600-bonding.c [new file with mode: 0644]

index 44017c1806770306cf34fe3956b112e621ffc33e..b36ce1d9593066981a6ddfe8c3bc4e76c6b19bec 100644 (file)
@@ -1,3 +1,16 @@
+2015-05-19  Sameera Deshpande  <Sameera.Deshpande@imgtec.com>
+
+       * config/mips/mips.md (JOIN_MODE): New mode iterator.
+       (join2_load_Store<JOIN_MODE:mode>): New pattern.
+       (join2_loadhi): Likewise.
+       (define_peehole2): Add peephole2 patterns to join 2 HI/SI/SF/DF-mode
+       load-load and store-stores.
+       * config/mips/mips.opt (mload-store-pairs): New option.
+       (TARGET_LOAD_STORE_PAIRS): New macro.
+       * config/mips/mips.h (ENABLE_LD_ST_PAIRS): Likewise.
+       * config/mips/mips-protos.h (mips_load_store_bonding_p): New prototype.
+       * config/mips/mips.c (mips_load_store_bonding_p): New function.
+
 2015-05-19  Mikhail Maltsev  <maltsevm@gmail.com>
 
        * bb-reorder.c (fix_up_fall_thru_edges): Use std::swap instead of
index b48e04fdee63af44e599c99f6656bb9466f52568..244eb8d51cba0fb8bfcfb69316769ceae0903491 100644 (file)
@@ -360,6 +360,7 @@ extern bool mips_epilogue_uses (unsigned int);
 extern void mips_final_prescan_insn (rtx_insn *, rtx *, int);
 extern int mips_trampoline_code_size (void);
 extern void mips_function_profiler (FILE *);
+extern bool mips_load_store_bonding_p (rtx *, machine_mode, bool);
 
 typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
 #ifdef RTX_CODE
index e619baadae880348210b8404ea2ab63d91cac159..a3165cad8c69643e9e2e291ca49f462ac2ecc4de 100644 (file)
@@ -18231,6 +18231,66 @@ umips_load_store_pair_p_1 (bool load_p, bool swap_p,
   return true;
 }
 
+bool
+mips_load_store_bonding_p (rtx *operands, machine_mode mode, bool load_p)
+{
+  rtx reg1, reg2, mem1, mem2, base1, base2;
+  enum reg_class rc1, rc2;
+  HOST_WIDE_INT offset1, offset2;
+
+  if (load_p)
+    {
+      reg1 = operands[0];
+      reg2 = operands[2];
+      mem1 = operands[1];
+      mem2 = operands[3];
+    }
+  else
+    {
+      reg1 = operands[1];
+      reg2 = operands[3];
+      mem1 = operands[0];
+      mem2 = operands[2];
+    }
+
+  if (mips_address_insns (XEXP (mem1, 0), mode, false) == 0
+      || mips_address_insns (XEXP (mem2, 0), mode, false) == 0)
+    return false;
+
+  mips_split_plus (XEXP (mem1, 0), &base1, &offset1);
+  mips_split_plus (XEXP (mem2, 0), &base2, &offset2);
+
+  /* Base regs do not match.  */
+  if (!REG_P (base1) || !rtx_equal_p (base1, base2))
+    return false;
+
+  /* Either of the loads is clobbering base register.  It is legitimate to bond
+     loads if second load clobbers base register.  However, hardware does not
+     support such bonding.  */
+  if (load_p
+      && (REGNO (reg1) == REGNO (base1)
+         || (REGNO (reg2) == REGNO (base1))))
+    return false;
+
+  /* Loading in same registers.  */
+  if (load_p
+      && REGNO (reg1) == REGNO (reg2))
+    return false;
+
+  /* The loads/stores are not of same type.  */
+  rc1 = REGNO_REG_CLASS (REGNO (reg1));
+  rc2 = REGNO_REG_CLASS (REGNO (reg2));
+  if (rc1 != rc2
+      && !reg_class_subset_p (rc1, rc2)
+      && !reg_class_subset_p (rc2, rc1))
+    return false;
+
+  if (abs (offset1 - offset2) != GET_MODE_SIZE (mode))
+    return false;
+
+  return true;
+}
+
 /* OPERANDS describes the operands to a pair of SETs, in the order
    dest1, src1, dest2, src2.  Return true if the operands can be used
    in an LWP or SWP instruction; LOAD_P says which.  */
index 0ea4e6db693524ba72b91b5d69a3c73f7a6968be..2fa47249b5463cfbcc747a2c0a9732d1a1f787d2 100644 (file)
@@ -3162,3 +3162,10 @@ extern GTY(()) struct target_globals *mips16_globals;
 #define STANDARD_STARTFILE_PREFIX_1 "/lib64/"
 #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib64/"
 #endif
+
+/* Load store bonding is not supported by micromips and fix_24k.  The
+   performance can be degraded for those targets.  Hence, do not bond for
+   micromips or fix_24k.  */
+#define ENABLE_LD_ST_PAIRS \
+  (TARGET_LOAD_STORE_PAIRS && TUNE_P5600 \
+   && !TARGET_MICROMIPS && !TARGET_FIX_24K)
index f6921c691b6f6d73a82a4677d2712e27aea6373f..0a23fa214b0ef489ef138bd8dda989f7b2511c1a 100644 (file)
 
 (define_mode_iterator MOVEP1 [SI SF])
 (define_mode_iterator MOVEP2 [SI SF])
+(define_mode_iterator JOIN_MODE [HI
+                                SI
+                                (SF "TARGET_HARD_FLOAT")
+                                (DF "TARGET_HARD_FLOAT
+                                     && TARGET_DOUBLE_FLOAT")])
 
 ;; This mode iterator allows :HILO to be used as the mode of the
 ;; concatenated HI and LO registers.
   { return MIPS_CALL ("jal", operands, 0, -1); }
   [(set_attr "type" "call")
    (set_attr "insn_count" "3")])
+
+;; Match paired HI/SI/SF/DFmode load/stores.
+(define_insn "*join2_load_store<JOIN_MODE:mode>"
+  [(set (match_operand:JOIN_MODE 0 "nonimmediate_operand" "=d,f,m,m")
+       (match_operand:JOIN_MODE 1 "nonimmediate_operand" "m,m,d,f"))
+   (set (match_operand:JOIN_MODE 2 "nonimmediate_operand" "=d,f,m,m")
+       (match_operand:JOIN_MODE 3 "nonimmediate_operand" "m,m,d,f"))]
+  "ENABLE_LD_ST_PAIRS && reload_completed"
+  {
+    bool load_p = (which_alternative == 0 || which_alternative == 1);
+    /* Reg-renaming pass reuses base register if it is dead after bonded loads.
+       Hardware does not bond those loads, even when they are consecutive.
+       However, order of the loads need to be checked for correctness.  */
+    if (!load_p || !reg_overlap_mentioned_p (operands[0], operands[1]))
+      {
+       output_asm_insn (mips_output_move (operands[0], operands[1]),
+                        operands);
+       output_asm_insn (mips_output_move (operands[2], operands[3]),
+                        &operands[2]);
+      }
+    else
+      {
+       output_asm_insn (mips_output_move (operands[2], operands[3]),
+                        &operands[2]);
+       output_asm_insn (mips_output_move (operands[0], operands[1]),
+                        operands);
+      }
+    return "";
+  }
+  [(set_attr "move_type" "load,fpload,store,fpstore")
+   (set_attr "insn_count" "2,2,2,2")])
+
+;; 2 HI/SI/SF/DF loads are joined.
+;; P5600 does not support bonding of two LBs, hence QI mode is not included.
+;; The loads must be non-volatile as they might be reordered at the time of asm
+;; generation.
+(define_peephole2
+  [(set (match_operand:JOIN_MODE 0 "register_operand")
+       (match_operand:JOIN_MODE 1 "non_volatile_mem_operand"))
+   (set (match_operand:JOIN_MODE 2 "register_operand")
+       (match_operand:JOIN_MODE 3 "non_volatile_mem_operand"))]
+  "ENABLE_LD_ST_PAIRS
+   && mips_load_store_bonding_p (operands, <JOIN_MODE:MODE>mode, true)"
+  [(parallel [(set (match_dup 0)
+                  (match_dup 1))
+             (set (match_dup 2)
+                  (match_dup 3))])]
+  "")
+
+;; 2 HI/SI/SF/DF stores are joined.
+;; P5600 does not support bonding of two SBs, hence QI mode is not included.
+(define_peephole2
+  [(set (match_operand:JOIN_MODE 0 "memory_operand")
+       (match_operand:JOIN_MODE 1 "register_operand"))
+   (set (match_operand:JOIN_MODE 2 "memory_operand")
+       (match_operand:JOIN_MODE 3 "register_operand"))]
+  "ENABLE_LD_ST_PAIRS
+   && mips_load_store_bonding_p (operands, <JOIN_MODE:MODE>mode, false)"
+  [(parallel [(set (match_dup 0)
+                  (match_dup 1))
+             (set (match_dup 2)
+                  (match_dup 3))])]
+  "")
+
+;; Match paired HImode loads.
+(define_insn "*join2_loadhi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (any_extend:SI (match_operand:HI 1 "non_volatile_mem_operand" "m")))
+   (set (match_operand:SI 2 "register_operand" "=r")
+       (any_extend:SI (match_operand:HI 3 "non_volatile_mem_operand" "m")))]
+  "ENABLE_LD_ST_PAIRS && reload_completed"
+  {
+    /* Reg-renaming pass reuses base register if it is dead after bonded loads.
+       Hardware does not bond those loads, even when they are consecutive.
+       However, order of the loads need to be checked for correctness.  */
+    if (!reg_overlap_mentioned_p (operands[0], operands[1]))
+      {
+       output_asm_insn ("lh<u>\t%0,%1", operands);
+       output_asm_insn ("lh<u>\t%2,%3", operands);
+      }
+    else
+      {
+       output_asm_insn ("lh<u>\t%2,%3", operands);
+       output_asm_insn ("lh<u>\t%0,%1", operands);
+      }
+
+    return "";
+  }
+  [(set_attr "move_type" "load")
+   (set_attr "insn_count" "2")])
+
+
+;; 2 HI loads are joined.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand")
+       (any_extend:SI (match_operand:HI 1 "non_volatile_mem_operand")))
+   (set (match_operand:SI 2 "register_operand")
+       (any_extend:SI (match_operand:HI 3 "non_volatile_mem_operand")))]
+  "ENABLE_LD_ST_PAIRS
+   && mips_load_store_bonding_p (operands, HImode, true)"
+  [(parallel [(set (match_dup 0)
+                  (any_extend:SI (match_dup 1)))
+             (set (match_dup 2)
+                  (any_extend:SI (match_dup 3)))])]
+  "")
+
 \f
 ;; Synchronization instructions.
 
index 9e89aa9abe3350b95b8abf803969991ac4bbedb7..a9baebe6a44d6e79064ba18a624c6e5b038d69cc 100644 (file)
@@ -418,3 +418,7 @@ Enable use of odd-numbered single-precision registers
 
 noasmopt
 Driver
+
+mload-store-pairs
+Target Report Var(TARGET_LOAD_STORE_PAIRS) Init(1)
+Enable load/store bonding.
index a5c147be13a9efd75b000e2665f11465800316af..7987859653e68c34fedc45daebf2cc45db8a9770 100644 (file)
@@ -1,3 +1,7 @@
+2015-05-19  Sameera Deshpande  <sameera.deshpande@imgtec.com>
+
+       * gcc.target/mips/p5600-bonding.c : New file.
+
 2015-05-18  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/66106
diff --git a/gcc/testsuite/gcc.target/mips/p5600-bonding.c b/gcc/testsuite/gcc.target/mips/p5600-bonding.c
new file mode 100644 (file)
index 0000000..0890ffa
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-dp -mtune=p5600  -mno-micromips -mno-mips16" } */
+/* { dg-skip-if "Bonding needs peephole optimization." { *-*-* } { "-O0" "-O1" } { "" } } */
+typedef int VINT32 __attribute__ ((vector_size((16))));
+
+void
+memory_operation (void * __restrict src, void * __restrict dest, int num)
+{
+  VINT32 *vsrc = (VINT32 *) src;
+  VINT32 *vdest = (VINT32 *) dest;
+  int i;
+
+  for (i = 0; i < num - 1; i += 2)
+  {
+    vdest[i] = vdest[i] + vsrc[i];
+    vdest[i + 1] = vdest[i + 1] + vsrc[i + 1];
+  }
+}
+/* { dg-final { scan-assembler "join2_" } }  */
+