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
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. */ /* Transform BLKmode MEM reference into a (reg)+ operand. */
sprintf (buf, "\nmovestrhi%d:", count); toop = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
output_asm_insn (buf, NULL); 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. */ count = INTVAL (operands[2]);
switch (unroll) if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
{
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); count >>= 1;
output_asm_insn (buf, operands); toop = gen_rtx_MEM (HImode, toop);
fromop = gen_rtx_MEM (HImode, fromop);
} }
else else
{ {
output_asm_insn ("dec\t%4", operands); toop = gen_rtx_MEM (QImode, toop);
sprintf (buf, "bgt movestrhi%d", count); fromop = gen_rtx_MEM (QImode, fromop);
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++;
}
} }
counter = copy_to_mode_reg (HImode, gen_rtx_CONST_INT (HImode, 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 /* 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,48 +570,20 @@ ...@@ -570,48 +570,20 @@
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
......
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