From a3368b8ea1bda5edd41900096b10514bcf7c6de7 Mon Sep 17 00:00:00 2001 From: Paul Koning Date: Mon, 8 Oct 2018 10:16:13 -0400 Subject: [PATCH] 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 --- gcc/ChangeLog | 10 ++ gcc/config/pdp11/pdp11-protos.h | 2 +- gcc/config/pdp11/pdp11.c | 180 +++++--------------------------- gcc/config/pdp11/pdp11.h | 5 +- gcc/config/pdp11/pdp11.md | 44 ++------ 5 files changed, 51 insertions(+), 190 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1ee5edde975..0e10c559e3b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2018-10-08 Paul Koning + + * 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 * config/s390/2827.md: Increase latencies for some FP instructions. diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h index 0ce72fdc3f7..0ed61ea6106 100644 --- a/gcc/config/pdp11/pdp11-protos.h +++ b/gcc/config/pdp11/pdp11-protos.h @@ -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; diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index b3b7ced9e07..06129f1d2d9 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -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 diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h index c68a74d91a0..d65d8f5b8a2 100644 --- a/gcc/config/pdp11/pdp11.h +++ b/gcc/config/pdp11/pdp11.h @@ -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 diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md index e51f5381967..a41e159012e 100644 --- a/gcc/config/pdp11/pdp11.md +++ b/gcc/config/pdp11/pdp11.md @@ -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 -- 2.30.2