Commit a3368b8e by Paul Koning Committed by Paul Koning

Fix ICE on block move when using LRA.

    * 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
parent a3927ffb
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> 2018-10-08 Robin Dapp <rdapp@linux.ibm.com>
* config/s390/2827.md: Increase latencies for some FP instructions. * config/s390/2827.md: Increase latencies for some FP instructions.
...@@ -26,7 +26,7 @@ extern int legitimate_const_double_p (rtx); ...@@ -26,7 +26,7 @@ extern int legitimate_const_double_p (rtx);
extern void notice_update_cc_on_set (rtx, rtx); extern void notice_update_cc_on_set (rtx, rtx);
extern void output_addr_const_pdp11 (FILE *, rtx); extern void output_addr_const_pdp11 (FILE *, rtx);
extern const char *output_move_multiple (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 const char *output_jump (rtx *, int, int);
extern void print_operand_address (FILE *, rtx); extern void print_operand_address (FILE *, rtx);
typedef enum { no_action, dec_before, inc_after } pdp11_action; typedef enum { no_action, dec_before, inc_after } pdp11_action;
......
...@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h" #include "expr.h"
#include "builtins.h" #include "builtins.h"
#include "dbxout.h" #include "dbxout.h"
#include "explow.h"
#include "expmed.h" #include "expmed.h"
/* This file should be included last. */ /* This file should be included last. */
...@@ -1513,173 +1514,48 @@ no_side_effect_operand(rtx op, machine_mode mode ATTRIBUTE_UNUSED) ...@@ -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[0] ... to
* operands[1] ... from * operands[1] ... from
* operands[2] ... length * operands[2] ... length
* operands[3] ... alignment * operands[3] ... alignment
* operands[4] ... scratch register
*/ */
void
const char * expand_block_move(rtx *operands)
output_block_move(rtx *operands)
{ {
static int count = 0; rtx lb, test;
char buf[200]; rtx fromop, toop, counter;
int unroll; int count;
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 /* Transform BLKmode MEM reference into a (reg)+ operand. */
bytes and handle those by unrolling the move loop. That toop = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
makes for a lot of code if done at run time, but it's ok toop = gen_rtx_POST_INC (Pmode, toop);
for constant counts. Also, for variable counts we have fromop = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
to worry about odd byte count with even aligned pointers. fromop = gen_rtx_POST_INC (Pmode, fromop);
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]) ) count = INTVAL (operands[2]);
{ if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
if (INTVAL (operands[3]) < 2)
unroll = 0;
else
{ {
lastbyte = INTVAL (operands[2]) & 1; count >>= 1;
toop = gen_rtx_MEM (HImode, toop);
if (optimize_size || INTVAL (operands[2]) & 2) fromop = gen_rtx_MEM (HImode, fromop);
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 else
{ {
/* Variable byte count; use the input register toop = gen_rtx_MEM (QImode, toop);
as the scratch. */ fromop = gen_rtx_MEM (QImode, fromop);
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);
} }
counter = copy_to_mode_reg (HImode, gen_rtx_CONST_INT (HImode, count));
/* Output the loop label. */ /* Label at top of loop */
sprintf (buf, "\nmovestrhi%d:", count); lb = gen_label_rtx ();
output_asm_insn (buf, NULL); emit_label (lb);
emit_move_insn (toop, fromop);
/* Output the appropriate move instructions. */ emit_insn (gen_subhi3 (counter, counter, const1_rtx));
switch (unroll) test = gen_rtx_NE (HImode, counter, const0_rtx);
{ emit_jump_insn (gen_cbranchhi4 (test, counter, const0_rtx, lb));
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)
{
sprintf (buf, "sob\t%%4, movestrhi%d", count);
output_asm_insn (buf, operands);
}
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++;
}
}
return "";
} }
/* This function checks whether a real value can be encoded as /* This function checks whether a real value can be encoded as
......
...@@ -439,9 +439,12 @@ extern int may_call_alloca; ...@@ -439,9 +439,12 @@ extern int may_call_alloca;
/* Max number of bytes we can move from memory to memory /* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. in one reasonably fast instruction.
*/ */
#define MOVE_MAX 2 #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. */ /* Nonzero if access to memory by byte is no faster than by word. */
#define SLOW_BYTE_ACCESS 1 #define SLOW_BYTE_ACCESS 1
......
...@@ -570,49 +570,21 @@ ...@@ -570,49 +570,21 @@
clrf\t%0" clrf\t%0"
[(set_attr "length" "2,2,4,4,2")]) [(set_attr "length" "2,2,4,4,2")])
;; maybe fiddle a bit with move_ratio, then ;; Expand a block move. We turn this into a move loop.
;; let constraints only accept a register ...
(define_expand "movmemhi" (define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g") [(match_operand:BLK 0 "general_operand" "=g")
(match_operand:BLK 1 "general_operand" "g,g")) (match_operand:BLK 1 "general_operand" "g")
(use (match_operand:HI 2 "general_operand" "n,mr")) (match_operand:HI 2 "immediate_operand" "i")
(use (match_operand:HI 3 "immediate_operand" "i,i")) (match_operand:HI 3 "immediate_operand" "i")]
(clobber (match_scratch:HI 6 "=&r,X"))
(clobber (match_dup 4))
(clobber (match_dup 5))
(clobber (match_dup 2))])]
"" ""
" "
{ {
operands[0] if (INTVAL (operands[2]) != 0)
= replace_equiv_address (operands[0], expand_block_move (operands);
copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); DONE;
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);
}") }")
(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 ;;- truncation instructions
;; We sometimes end up doing a register to register truncate, ;; We sometimes end up doing a register to register truncate,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment