rs6000-protos.h (expand_block_move): Change prototype.
authorAaron Sawdey <acsawdey@linux.ibm.com>
Wed, 2 Oct 2019 14:26:09 +0000 (14:26 +0000)
committerAaron Sawdey <acsawdey@gcc.gnu.org>
Wed, 2 Oct 2019 14:26:09 +0000 (09:26 -0500)
2019-10-02  Aaron Sawdey <acsawdey@linux.ibm.com>

* config/rs6000/rs6000-protos.h (expand_block_move): Change prototype.
* config/rs6000/rs6000-string.c (expand_block_move): Add
might_overlap parm.
* config/rs6000/rs6000.md (movmemsi): Add new pattern.
(cpymemsi): Add might_overlap parm to expand_block_move() call.

From-SVN: r276462

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000-string.c
gcc/config/rs6000/rs6000.md

index fe1457769db452d7c35d01fc2f60d48b1e76a9a6..5dc53312b671db3021bb76d8f757b77fd0700419 100644 (file)
@@ -1,3 +1,11 @@
+2019-10-02  Aaron Sawdey <acsawdey@linux.ibm.com>
+
+       * config/rs6000/rs6000-protos.h (expand_block_move): Change prototype.
+       * config/rs6000/rs6000-string.c (expand_block_move): Add
+       might_overlap parm.
+       * config/rs6000/rs6000.md (movmemsi): Add new pattern.
+       (cpymemsi): Add might_overlap parm to expand_block_move() call.
+
 2019-10-02  Aaron Sawdey <acsawdey@linux.ibm.com>
 
        * builtins.c (expand_builtin_memory_copy_args): Add might_overlap parm.
index c51b768d96475c8bc4ff1507815b608e69ca6272..08dd88c3e4d6ca40a33d82cc15bc97a07dd8d9dd 100644 (file)
@@ -69,7 +69,7 @@ extern void rs6000_generate_float2_code (bool, rtx, rtx, rtx);
 extern void rs6000_generate_float2_double_code (rtx, rtx, rtx);
 extern void rs6000_generate_vsigned2_code (bool, rtx, rtx, rtx);
 extern int expand_block_clear (rtx[]);
-extern int expand_block_move (rtx[]);
+extern int expand_block_move (rtx[], bool);
 extern bool expand_block_compare (rtx[]);
 extern bool expand_strn_compare (rtx[], int);
 extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode);
index b9391855e16100a154acefb267673030ee47a108..3bc359e33cc62e38879f34a6e9c4c6cfd87c47e2 100644 (file)
@@ -2719,7 +2719,7 @@ gen_lvx_v4si_move (rtx dest, rtx src)
 #define MAX_MOVE_REG 4
 
 int
-expand_block_move (rtx operands[])
+expand_block_move (rtx operands[], bool might_overlap)
 {
   rtx orig_dest = operands[0];
   rtx orig_src = operands[1];
@@ -2730,6 +2730,7 @@ expand_block_move (rtx operands[])
   int bytes;
   int offset;
   int move_bytes;
+  rtx loads[MAX_MOVE_REG];
   rtx stores[MAX_MOVE_REG];
   int num_reg = 0;
 
@@ -2817,47 +2818,35 @@ expand_block_move (rtx operands[])
          gen_func.mov = gen_movqi;
        }
 
+      /* Mode is always set to something other than BLKmode by one of the 
+        cases of the if statement above.  */
+      gcc_assert (mode != BLKmode);
+
       src = adjust_address (orig_src, mode, offset);
       dest = adjust_address (orig_dest, mode, offset);
 
-      if (mode != BLKmode)
-       {
-         rtx tmp_reg = gen_reg_rtx (mode);
+      rtx tmp_reg = gen_reg_rtx (mode);
+      
+      loads[num_reg]    = (*gen_func.mov) (tmp_reg, src);
+      stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
 
-         emit_insn ((*gen_func.mov) (tmp_reg, src));
-         stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
-       }
+      /* If we didn't succeed in doing it in one pass, we can't do it in the 
+        might_overlap case.  Bail out and return failure.  */
+      if (might_overlap && num_reg >= MAX_MOVE_REG
+         && bytes > move_bytes)
+       return 0;
 
-      if (mode == BLKmode || num_reg >= MAX_MOVE_REG || bytes == move_bytes)
+      /* Emit loads and stores saved up.  */
+      if (num_reg >= MAX_MOVE_REG || bytes == move_bytes)
        {
          int i;
+         for (i = 0; i < num_reg; i++)
+           emit_insn (loads[i]);
          for (i = 0; i < num_reg; i++)
            emit_insn (stores[i]);
          num_reg = 0;
        }
-
-      if (mode == BLKmode)
-       {
-         /* Move the address into scratch registers.  The movmemsi
-            patterns require zero offset.  */
-         if (!REG_P (XEXP (src, 0)))
-           {
-             rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
-             src = replace_equiv_address (src, src_reg);
-           }
-         set_mem_size (src, move_bytes);
-
-         if (!REG_P (XEXP (dest, 0)))
-           {
-             rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
-             dest = replace_equiv_address (dest, dest_reg);
-           }
-         set_mem_size (dest, move_bytes);
-
-         emit_insn ((*gen_func.movmemsi) (dest, src,
-                                          GEN_INT (move_bytes & 31),
-                                          align_rtx));
-       }
+       
     }
 
   return 1;
index 4f27f13772bdba570bfa7b03e7532b7fcaabbd7e..2dca269744f77c18d11687e9751c8e3903c4b369 100644 (file)
     FAIL;
 })
 
-;; String/block move insn.
+;; String/block copy insn (source and destination must not overlap).
 ;; Argument 0 is the destination
 ;; Argument 1 is the source
 ;; Argument 2 is the length
              (use (match_operand:SI 3 ""))])]
   ""
 {
-  if (expand_block_move (operands))
+  if (expand_block_move (operands, false))
     DONE;
   else
     FAIL;
 })
+
+;; String/block move insn (source and destination may overlap).
+;; Argument 0 is the destination
+;; Argument 1 is the source
+;; Argument 2 is the length
+;; Argument 3 is the alignment
+
+(define_expand "movmemsi"
+  [(parallel [(set (match_operand:BLK 0 "")
+                  (match_operand:BLK 1 ""))
+             (use (match_operand:SI 2 ""))
+             (use (match_operand:SI 3 ""))])]
+  ""
+{
+  if (expand_block_move (operands, true))
+    DONE;
+  else
+    FAIL;
+})
+
 \f
 ;; Define insns that do load or store with update.  Some of these we can
 ;; get by using pre-decrement or pre-increment, but the hardware can also