Fix ICE on block move when using LRA.
authorPaul Koning <ni1d@arrl.net>
Mon, 8 Oct 2018 14:16:13 +0000 (10:16 -0400)
committerPaul Koning <pkoning@gcc.gnu.org>
Mon, 8 Oct 2018 14:16:13 +0000 (10:16 -0400)
    * config/pdp11/pdp11-protos.h (output_block_move): Remove.
    (expand_block_move): New function.
    * config/pdp11/pdp11.c (output_block_move): Remove.
    (expand_block_move): New function.
    * config/pdp11/pdp11.h (MOVE_RATIO): New definition.
    * config/pdp11/pdp11.md (movmemhi): Use expand_block_move.
    (*movmemhi1): Remove.

From-SVN: r264930

gcc/ChangeLog
gcc/config/pdp11/pdp11-protos.h
gcc/config/pdp11/pdp11.c
gcc/config/pdp11/pdp11.h
gcc/config/pdp11/pdp11.md

index 1ee5edde975eeaf48874072aab5f8f79076ac830..0e10c559e3bfefd31d6dd0f3abaf8b60a11fcedc 100644 (file)
@@ -1,3 +1,13 @@
+2018-10-08  Paul Koning  <ni1d@arrl.net>
+
+       * config/pdp11/pdp11-protos.h (output_block_move): Remove.
+       (expand_block_move): New function.
+       * config/pdp11/pdp11.c (output_block_move): Remove.
+       (expand_block_move): New function.
+       * config/pdp11/pdp11.h (MOVE_RATIO): New definition.
+       * config/pdp11/pdp11.md (movmemhi): Use expand_block_move.
+       (*movmemhi1): Remove.
+
 2018-10-08  Robin Dapp  <rdapp@linux.ibm.com>
 
        * config/s390/2827.md: Increase latencies for some FP instructions.
index 0ce72fdc3f7d3729f2ffc8579b6cbd90bd85c37d..0ed61ea6106fe4037eac7a3a33f095723dfac850 100644 (file)
@@ -26,7 +26,7 @@ extern int legitimate_const_double_p (rtx);
 extern void notice_update_cc_on_set (rtx, rtx);
 extern void output_addr_const_pdp11 (FILE *, rtx);
 extern const char *output_move_multiple (rtx *);
-extern const char *output_block_move (rtx *);
+extern void expand_block_move (rtx *);
 extern const char *output_jump (rtx *, int, int);
 extern void print_operand_address (FILE *, rtx);
 typedef enum { no_action, dec_before, inc_after } pdp11_action;
index b3b7ced9e07b8cf4aa7a95ce374ed7e6dcd7bbd6..06129f1d2d9db5257845cfc9beac55bcbec86ec5 100644 (file)
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "builtins.h"
 #include "dbxout.h"
+#include "explow.h"
 #include "expmed.h"
 
 /* This file should be included last.  */
@@ -1513,173 +1514,48 @@ no_side_effect_operand(rtx op, machine_mode mode ATTRIBUTE_UNUSED)
 
 
 /*
- * output a block move:
+ * expand a block move:
  *
  * operands[0] ... to
  * operands[1]  ... from
  * operands[2]  ... length
  * operands[3]  ... alignment
- * operands[4]  ... scratch register
  */
 
-const char *
-output_block_move(rtx *operands)
+void
+expand_block_move(rtx *operands)
 {
-    static int count = 0;
-    char buf[200];
-    int unroll;
-    int lastbyte = 0;
-    
-    /* Move of zero bytes is a NOP.  */
-    if (operands[2] == const0_rtx)
-      return "";
-    
-    /* Look for moves by small constant byte counts, those we'll
-       expand to straight line code.  */
-    if (CONSTANT_P (operands[2]))
-    {
-       if (INTVAL (operands[2]) < 16
-           && (!optimize_size || INTVAL (operands[2]) < 5)
-           && INTVAL (operands[3]) == 1)
-       {
-           register int i;
-           
-           for (i = 1; i <= INTVAL (operands[2]); i++)
-               output_asm_insn("movb\t(%1)+,(%0)+", operands);
-
-           return "";
-       }
-       else if (INTVAL(operands[2]) < 32
-                && (!optimize_size || INTVAL (operands[2]) < 9)
-                && INTVAL (operands[3]) >= 2)
-       {
-           register int i;
-           
-           for (i = 1; i <= INTVAL (operands[2]) / 2; i++)
-               output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-           if (INTVAL (operands[2]) & 1)
-             output_asm_insn ("movb\t(%1),(%0)", operands);
-           
-           return "";
-       }
-    }
-
-    /* Ideally we'd look for moves that are multiples of 4 or 8
-       bytes and handle those by unrolling the move loop.  That
-       makes for a lot of code if done at run time, but it's ok
-       for constant counts.  Also, for variable counts we have
-       to worry about odd byte count with even aligned pointers.
-       On 11/40 and up we handle that case; on older machines
-       we don't and just use byte-wise moves all the time.  */
-
-    if (CONSTANT_P (operands[2]) )
-    {
-      if (INTVAL (operands[3]) < 2)
-       unroll = 0;
-      else
-       {
-         lastbyte = INTVAL (operands[2]) & 1;
-
-         if (optimize_size || INTVAL (operands[2]) & 2)
-           unroll = 1;
-         else if (INTVAL (operands[2]) & 4)
-           unroll = 2;
-         else
-           unroll = 3;
-       }
-      
-      /* Loop count is byte count scaled by unroll.  */
-      operands[2] = GEN_INT (INTVAL (operands[2]) >> unroll);
-      output_asm_insn ("mov\t%2,%4", operands);
-    }
-    else
-    {
-       /* Variable byte count; use the input register
-          as the scratch.  */
-       operands[4] = operands[2];
-
-       /* Decide whether to move by words, and check
-          the byte count for zero.  */
-       if (TARGET_40_PLUS && INTVAL (operands[3]) > 1)
-         {
-           unroll = 1;
-           output_asm_insn ("asr\t%4", operands);
-         }
-       else
-         {
-           unroll = 0;
-           output_asm_insn ("tst\t%4", operands);
-         }
-       sprintf (buf, "beq movestrhi%d", count + 1);
-       output_asm_insn (buf, NULL);
-    }
+    rtx lb, test;
+    rtx fromop, toop, counter;
+    int count;
 
-    /* Output the loop label.  */
-    sprintf (buf, "\nmovestrhi%d:", count);
-    output_asm_insn (buf, NULL);
+    /* Transform BLKmode MEM reference into a (reg)+ operand.  */
+    toop = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+    toop = gen_rtx_POST_INC (Pmode, toop);
+    fromop = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+    fromop = gen_rtx_POST_INC (Pmode, fromop);
 
-    /* Output the appropriate move instructions.  */
-    switch (unroll)
-    {
-      case 0:
-       output_asm_insn ("movb\t(%1)+,(%0)+", operands);
-       break;
-       
-      case 1:
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       break;
-       
-      case 2:
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       break;
-       
-      default:
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       output_asm_insn ("mov\t(%1)+,(%0)+", operands);
-       break;
-    }
-
-    /* Output the decrement and test.  */
-    if (TARGET_40_PLUS)
+    count = INTVAL (operands[2]);
+    if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
       {
-       sprintf (buf, "sob\t%%4, movestrhi%d", count);
-       output_asm_insn (buf, operands);
+       count >>= 1;
+       toop = gen_rtx_MEM (HImode, toop);
+       fromop = gen_rtx_MEM (HImode, fromop);
       }
     else
       {
-       output_asm_insn ("dec\t%4", operands);
-       sprintf (buf, "bgt movestrhi%d", count);
-       output_asm_insn (buf, NULL);
-      }
-    count ++;
-
-    /* If constant odd byte count, move the last byte.  */
-    if (lastbyte)
-      output_asm_insn ("movb\t(%1),(%0)", operands);
-    else if (!CONSTANT_P (operands[2]))
-      {
-       /* Output the destination label for the zero byte count check.  */
-       sprintf (buf, "\nmovestrhi%d:", count);
-       output_asm_insn (buf, NULL);
-       count++;
-    
-       /* If we did word moves, check for trailing last byte. */
-       if (unroll)
-         {
-           sprintf (buf, "bcc movestrhi%d", count);
-           output_asm_insn (buf, NULL);
-           output_asm_insn ("movb\t(%1),(%0)", operands);
-           sprintf (buf, "\nmovestrhi%d:", count);
-           output_asm_insn (buf, NULL);
-           count++;
-         }
+       toop = gen_rtx_MEM (QImode, toop);
+       fromop = gen_rtx_MEM (QImode, fromop);
       }
-            
-    return "";
+    counter = copy_to_mode_reg (HImode, gen_rtx_CONST_INT (HImode, count));
+
+    /* Label at top of loop */
+    lb = gen_label_rtx ();
+    emit_label (lb);
+    emit_move_insn (toop, fromop);
+    emit_insn (gen_subhi3 (counter, counter, const1_rtx));
+    test = gen_rtx_NE (HImode, counter, const0_rtx);
+    emit_jump_insn (gen_cbranchhi4 (test, counter, const0_rtx, lb));
 }
 
 /* This function checks whether a real value can be encoded as
index c68a74d91a0448db3e0d8bbd4300da4ac3db4229..d65d8f5b8a241bff66816bbd309c01130ac1137c 100644 (file)
@@ -439,9 +439,12 @@ extern int may_call_alloca;
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  
 */
-
 #define MOVE_MAX 2
 
+/* Max number of insns to use for inline move rather than library
+   call.  */
+#define MOVE_RATIO(speed) 6
+
 /* Nonzero if access to memory by byte is no faster than by word.  */
 #define SLOW_BYTE_ACCESS 1
 
index e51f5381967e1a76e9e5eac42fc922832b53084d..a41e159012ebfae1be0dc51d3688190a9391c26d 100644 (file)
   clrf\t%0"
   [(set_attr "length" "2,2,4,4,2")])
 
-;; maybe fiddle a bit with move_ratio, then 
-;; let constraints only accept a register ...
-
+;; Expand a block move.  We turn this into a move loop.
 (define_expand "movmemhi"
-  [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
-                  (match_operand:BLK 1 "general_operand" "g,g"))
-             (use (match_operand:HI 2 "general_operand" "n,mr"))
-             (use (match_operand:HI 3 "immediate_operand" "i,i"))
-             (clobber (match_scratch:HI 6 "=&r,X"))
-             (clobber (match_dup 4))
-             (clobber (match_dup 5))
-             (clobber (match_dup 2))])]
+  [(match_operand:BLK 0 "general_operand" "=g")
+   (match_operand:BLK 1 "general_operand" "g")
+   (match_operand:HI 2 "immediate_operand" "i")
+   (match_operand:HI 3 "immediate_operand" "i")]
   ""
   "
 {
-  operands[0]
-    = replace_equiv_address (operands[0],
-                            copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
-  operands[1]
-    = replace_equiv_address (operands[1],
-                            copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
-
-  operands[4] = XEXP (operands[0], 0);
-  operands[5] = XEXP (operands[1], 0);
+  if (INTVAL (operands[2]) != 0)
+    expand_block_move (operands);
+  DONE;
 }")
 
-
-(define_insn "*movmemhi1"
-  [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
-       (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
-   (use (match_operand:HI 2 "general_operand" "n,r"))
-   (use (match_operand:HI 3 "immediate_operand" "i,i"))
-   (clobber (match_scratch:HI 4 "=&r,X"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
-   (clobber (match_dup 2))]
-  ""
-  "* return output_block_move (operands);"
-;;; just a guess
-  [(set_attr "length" "80")])
-   
-
 \f
 ;;- truncation instructions