This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, pdp11] Fix LRA failure


This patch fixes a failure handling block moves when the LRA register allocator is used. 

Committed.

	paul

ChangeLog:

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.

Index: config/pdp11/pdp11-protos.h
===================================================================
--- config/pdp11/pdp11-protos.h	(revision 264929)
+++ config/pdp11/pdp11-protos.h	(revision 264930)
@@ -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: config/pdp11/pdp11.md
===================================================================
--- config/pdp11/pdp11.md	(revision 264929)
+++ config/pdp11/pdp11.md	(revision 264930)
@@ -570,48 +570,20 @@
   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")])
-   
-
 

 ;;- truncation instructions
 
Index: config/pdp11/pdp11.c
===================================================================
--- config/pdp11/pdp11.c	(revision 264929)
+++ config/pdp11/pdp11.c	(revision 264930)
@@ -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 A
 
 
 /*
- * 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);
+    rtx lb, test;
+    rtx fromop, toop, counter;
+    int count;
 
-	    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 "";
-	}
-    }
+    /* 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);
 
-    /* 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);
-    }
-
-    /* Output the loop label.  */
-    sprintf (buf, "\nmovestrhi%d:", count);
-    output_asm_insn (buf, NULL);
-
-    /* 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);
+	toop = gen_rtx_MEM (QImode, toop);
+	fromop = gen_rtx_MEM (QImode, fromop);
       }
-    count ++;
+    counter = copy_to_mode_reg (HImode, gen_rtx_CONST_INT (HImode, 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++;
-	  }
-      }
-	     
-    return "";
+    /* 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: config/pdp11/pdp11.h
===================================================================
--- config/pdp11/pdp11.h	(revision 264929)
+++ config/pdp11/pdp11.h	(revision 264930)
@@ -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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]