From: Kazu Hirata Date: Thu, 1 Jan 2004 00:24:24 +0000 (+0000) Subject: backport: re PR target/13373 (optimization with -frerun-cse-after-loop -fexpensive... X-Git-Tag: releases/gcc-3.3.3~136 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86696c44f2373ca91bd3b525c89982cc9dfa1e73;p=thirdparty%2Fgcc.git backport: re PR target/13373 (optimization with -frerun-cse-after-loop -fexpensive-optimizations produces wrong code on mcore) Backport from mainline: 2003-09-12 Richard Sandiford PR target/13373 * config/mcore/mcore-protos.h (mcore_r15_operand_p): Declare. (mcore_secondary_reload_class): Declare. (mcore_output_inline_const_forced): Remove. * config/mcore/mcore.md (movsi): Remove the code that forced non-inlineable constants into a register if the target was r15 or the stack pointer. Remove constant restrictions from the main define_insn. Remove r <- I, r <- M and r <- N alternatives in favor of an r <- P alternative. Remove fallback define_insn for reload. (movhi, movqi): Use gen_lowpart rather than gen_SUBREG. Remove reload define_insn. Use mcore_output_move in the remaining define_insn. Adjust condition and constraints in the way as for movsi. (movdi): Always split unacceptable constants into two. Use simplify_gen_subreg instead of operand_subword{,_force}. * config/mcore/mcore.c (mcore_output_inline_const_forced): Remove. (mcore_output_move): Support HImode and QImode moves as well. (mcore_m15_operand_p): New function. (mcore_reload_class): Use it to detect cases where LRW_REGS are better. (mcore_secondary_reload_class): New function. * config/mcore/mcore.h (SECONDARY_RELOAD_CLASS): Redefine in terms of mcore_secondary_reload_class. From-SVN: r75288 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b0ebb10b5304..10c31ad4ffe8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2003-12-31 Kazu Hirata + + Backport from mainline: + + 2003-09-12 Richard Sandiford + + PR target/13373 + * config/mcore/mcore-protos.h (mcore_r15_operand_p): Declare. + (mcore_secondary_reload_class): Declare. + (mcore_output_inline_const_forced): Remove. + * config/mcore/mcore.md (movsi): Remove the code that forced + non-inlineable constants into a register if the target was r15 + or the stack pointer. Remove constant restrictions from the main + define_insn. Remove r <- I, r <- M and r <- N alternatives in favor + of an r <- P alternative. Remove fallback define_insn for reload. + (movhi, movqi): Use gen_lowpart rather than gen_SUBREG. Remove reload + define_insn. Use mcore_output_move in the remaining define_insn. + Adjust condition and constraints in the way as for movsi. + (movdi): Always split unacceptable constants into two. Use + simplify_gen_subreg instead of operand_subword{,_force}. + * config/mcore/mcore.c (mcore_output_inline_const_forced): Remove. + (mcore_output_move): Support HImode and QImode moves as well. + (mcore_m15_operand_p): New function. + (mcore_reload_class): Use it to detect cases where LRW_REGS are better. + (mcore_secondary_reload_class): New function. + * config/mcore/mcore.h (SECONDARY_RELOAD_CLASS): Redefine in + terms of mcore_secondary_reload_class. + 2003-12-31 Zack Weinberg * config/ia64/ia64.c (ia64_va_arg): Pass pointer for diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h index 9910c3a5ec0f..fdf52207b93d 100644 --- a/gcc/config/mcore/mcore-protos.h +++ b/gcc/config/mcore/mcore-protos.h @@ -69,6 +69,8 @@ extern void mcore_print_operand_address PARAMS ((FILE *, rtx)); extern void mcore_print_operand PARAMS ((FILE *, rtx, int)); extern rtx mcore_gen_compare_reg PARAMS ((RTX_CODE)); extern int mcore_symbolic_address_p PARAMS ((rtx)); +extern bool mcore_r15_operand_p PARAMS ((rtx)); +extern enum reg_class mcore_secondary_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx)); extern enum reg_class mcore_reload_class PARAMS ((rtx, enum reg_class)); extern int mcore_is_same_reg PARAMS ((rtx, rtx)); extern int mcore_arith_S_operand PARAMS ((rtx)); @@ -76,7 +78,6 @@ extern int mcore_arith_S_operand PARAMS ((rtx)); #ifdef HAVE_MACHINE_MODES extern const char * mcore_output_move PARAMS ((rtx, rtx *, enum machine_mode)); extern const char * mcore_output_movedouble PARAMS ((rtx *, enum machine_mode)); -extern const char * mcore_output_inline_const_forced PARAMS ((rtx, rtx *, enum machine_mode)); extern int mcore_arith_reg_operand PARAMS ((rtx, enum machine_mode)); extern int mcore_general_movsrc_operand PARAMS ((rtx, enum machine_mode)); extern int mcore_general_movdst_operand PARAMS ((rtx, enum machine_mode)); diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index 7068ca696e10..473dec418d3a 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -1213,7 +1213,17 @@ mcore_output_move (insn, operands, mode) if (GET_CODE (XEXP (src, 0)) == LABEL_REF) return "lrw\t%0,[%1]"; /* a-R */ else - return "ldw\t%0,%1"; /* r-m */ + switch (GET_MODE (src)) /* r-m */ + { + case SImode: + return "ldw\t%0,%1"; + case HImode: + return "ld.h\t%0,%1"; + case QImode: + return "ld.b\t%0,%1"; + default: + abort (); + } } else if (GET_CODE (src) == CONST_INT) { @@ -1234,100 +1244,21 @@ mcore_output_move (insn, operands, mode) return "lrw\t%0, %1"; /* Into the literal pool. */ } else if (GET_CODE (dst) == MEM) /* m-r */ - return "stw\t%1,%0"; + switch (GET_MODE (dst)) + { + case SImode: + return "stw\t%1,%0"; + case HImode: + return "st.h\t%1,%0"; + case QImode: + return "st.b\t%1,%0"; + default: + abort (); + } abort (); } -/* Outputs a constant inline -- regardless of the cost. - Useful for things where we've gotten into trouble and think we'd - be doing an lrw into r15 (forbidden). This lets us get out of - that pickle even after register allocation. */ - -const char * -mcore_output_inline_const_forced (insn, operands, mode) - rtx insn ATTRIBUTE_UNUSED; - rtx operands[]; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - unsigned long value = INTVAL (operands[1]); - unsigned long ovalue = value; - struct piece - { - int low; - int shift; - } - part[6]; - int i; - - if (mcore_const_ok_for_inline (value)) - return output_inline_const (SImode, operands); - - for (i = 0; (unsigned) i < ARRAY_SIZE (part); i++) - { - part[i].shift = 0; - part[i].low = (value & 0x1F); - value -= part[i].low; - - if (mcore_const_ok_for_inline (value)) - break; - else - { - value >>= 5; - part[i].shift = 5; - - while ((value & 1) == 0) - { - part[i].shift++; - value >>= 1; - } - - if (mcore_const_ok_for_inline (value)) - break; - } - } - - /* 5 bits per iteration, a maximum of 5 times == 25 bits and leaves - 7 bits left in the constant -- which we know we can cover with - a movi. The final value can't be zero otherwise we'd have stopped - in the previous iteration. */ - if (value == 0 || ! mcore_const_ok_for_inline (value)) - abort (); - - /* Now, work our way backwards emitting the constant. */ - - /* Emit the value that remains -- it will be nonzero. */ - operands[1] = GEN_INT (value); - output_asm_insn (output_inline_const (SImode, operands), operands); - - while (i >= 0) - { - /* Shift anything we've already loaded. */ - if (part[i].shift) - { - operands[2] = GEN_INT (part[i].shift); - output_asm_insn ("lsli %0,%2", operands); - value <<= part[i].shift; - } - - /* Add anything we need into the low 5 bits. */ - if (part[i].low != 0) - { - operands[2] = GEN_INT (part[i].low); - output_asm_insn ("addi %0,%2", operands); - value += part[i].low; - } - - i--; - } - - if (value != ovalue) /* sanity */ - abort (); - - /* We've output all the instructions. */ - return ""; -} - /* Return a sequence of instructions to perform DI or DF move. Since the MCORE cannot move a DI or DF in one instruction, we have to take care when we see overlapping source and dest registers. */ @@ -3009,36 +2940,53 @@ mcore_dependent_reorg (first) } -/* Return the reg_class to use when reloading the rtx X into the class - CLASS. */ +/* Return true if X is something that can be moved directly into r15. */ -/* If the input is (PLUS REG CONSTANT) representing a stack slot address, - then we want to restrict the class to LRW_REGS since that ensures that - will be able to safely load the constant. +bool +mcore_r15_operand_p (x) + rtx x; +{ + switch (GET_CODE (x)) + { + case CONST_INT: + return mcore_const_ok_for_inline (INTVAL (x)); - If the input is a constant that should be loaded with mvir1, then use - ONLYR1_REGS. + case REG: + case SUBREG: + case MEM: + return 1; + + default: + return 0; + } +} + +/* Implement SECONDARY_RELOAD_CLASS. If CLASS contains r15, and we can't + directly move X into it, use r1-r14 as a temporary. */ +enum reg_class +mcore_secondary_reload_class (class, mode, x) + enum reg_class class; + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx x; +{ + if (TEST_HARD_REG_BIT (reg_class_contents[class], 15) + && !mcore_r15_operand_p (x)) + return LRW_REGS; + return NO_REGS; +} - ??? We don't handle the case where we have (PLUS REG CONSTANT) and - the constant should be loaded with mvir1, because that can lead to cases - where an instruction needs two ONLYR1_REGS reloads. */ +/* Return the reg_class to use when reloading the rtx X into the class + CLASS. If X is too complex to move directly into r15, prefer to + use LRW_REGS instead. */ enum reg_class mcore_reload_class (x, class) rtx x; enum reg_class class; { - enum reg_class new_class; - - if (class == GENERAL_REGS && CONSTANT_P (x) - && (GET_CODE (x) != CONST_INT - || ( ! CONST_OK_FOR_I (INTVAL (x)) - && ! CONST_OK_FOR_M (INTVAL (x)) - && ! CONST_OK_FOR_N (INTVAL (x))))) - new_class = LRW_REGS; - else - new_class = class; + if (reg_class_subset_p (LRW_REGS, class) && !mcore_r15_operand_p (x)) + return LRW_REGS; - return new_class; + return class; } /* Tell me if a pair of reg/subreg rtx's actually refer to the same diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h index cf808b4baaab..4e729972f310 100644 --- a/gcc/config/mcore/mcore.h +++ b/gcc/config/mcore/mcore.h @@ -610,7 +610,8 @@ extern const enum reg_class reg_class_from_letter[]; /* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */ -#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) NO_REGS +#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ + mcore_secondary_reload_class (CLASS, MODE, X) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. diff --git a/gcc/config/mcore/mcore.md b/gcc/config/mcore/mcore.md index 895e7aa216a8..6d121f01f4c5 100644 --- a/gcc/config/mcore/mcore.md +++ b/gcc/config/mcore/mcore.md @@ -1226,101 +1226,20 @@ { if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (SImode, operands[1]); - else if (CONSTANT_P (operands[1]) - && (GET_CODE (operands[1]) != CONST_INT - || ( ! CONST_OK_FOR_I (INTVAL (operands[1])) - && ! CONST_OK_FOR_M (INTVAL (operands[1])) - && ! CONST_OK_FOR_N (INTVAL (operands[1])) - && (! TARGET_HARDLIT || - ! mcore_const_ok_for_inline (INTVAL (operands[1]))))) - && ! reload_completed - && ! reload_in_progress - && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER - && (REGNO (operands[0]) == STACK_POINTER_REGNUM - || REGNO (operands[0]) == LK_REG)) - operands[1] = force_reg (SImode, operands[1]); }") -;;; Must put a/i before r/r so that it will be preferred when the dest is -;;; a hard register. Must put a/R before r/m. -;;; DO WE NEED a/i ANYMORE? - (define_insn "" - [(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,r,a,r,r,a,r,m") - (match_operand:SI 1 "mcore_general_movsrc_operand" "I,M,N,i,r,c,R,m,r"))] + [(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,a,r,a,r,m") + (match_operand:SI 1 "mcore_general_movsrc_operand" "r,P,i,c,R,m,r"))] "(register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)) - && ! (CONSTANT_P (operands[1]) - && (GET_CODE (operands[1]) != CONST_INT - || ( ! CONST_OK_FOR_I (INTVAL (operands[1])) - && ! CONST_OK_FOR_M (INTVAL (operands[1])) - && ! CONST_OK_FOR_N (INTVAL (operands[1])))) - && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER - && (REGNO (operands[0]) == STACK_POINTER_REGNUM - || REGNO (operands[0]) == LK_REG))" + || register_operand (operands[1], SImode))" "* return mcore_output_move (insn, operands, SImode);" - [(set_attr "type" "move,move,move,move,move,move,load,load,store")]) + [(set_attr "type" "move,move,move,move,load,load,store")]) -;; This is to work around a bug in reload. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "immediate_operand" "i"))] - "((reload_in_progress || reload_completed) - && CONSTANT_P (operands[1]) - && GET_CODE (operands[1]) == CONST_INT - && ! CONST_OK_FOR_I (INTVAL (operands[1])) - && ! CONST_OK_FOR_M (INTVAL (operands[1])) - && ! CONST_OK_FOR_N (INTVAL (operands[1])) - && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) == LK_REG)" - "* return mcore_output_inline_const_forced (insn, operands, SImode);" - [(set_attr "type" "load")]) - -;; (define_expand "reload_insi" -;; [(parallel [(match_operand:SI 0 "register_operand" "=r") -;; (match_operand:SI 1 "general_operand" "") -;; (match_operand:DI 2 "register_operand" "=&r")])] -;; "" -;; " -;; { -;; if (CONSTANT_P (operands[1]) -;; && GET_CODE (operands[1]) == CONST_INT -;; && ! CONST_OK_FOR_I (INTVAL (operands[1])) -;; && ! CONST_OK_FOR_M (INTVAL (operands[1])) -;; && ! CONST_OK_FOR_N (INTVAL (operands[1])) -;; && GET_CODE (operands[0]) == REG -;; && (REGNO (operands[0]) == STACK_POINTER_REGNUM -;; || REGNO (operands[0]) == LK_REG)) -;; { -;; rtx tmp; -;; -;; if ( REGNO (operands[2]) == REGNO (operands[0]) -;; || REGNO (operands[2]) == STACK_POINTER_REGNUM -;; || REGNO (operands[2]) == LK_REG) -;; tmp = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); -;; else -;; tmp = gen_rtx_REG (SImode, REGNO (operands[2])); -;; -;; emit_insn (gen_movsi (tmp, operands[1])); -;; emit_insn (gen_movsi (operands[0], tmp)); -;; DONE; -;; } -;; emit_insn (gen_movsi (operands[0], operands[1])); -;; DONE; -;; }" -;; ) - - - ;; ;; HImode ;; -;;; ??? This isn't guaranteed to work. It should be more like the SImode -;;; patterns. - (define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] @@ -1338,73 +1257,17 @@ { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_movsi (reg, operands[1])); - operands[1] = gen_rtx (SUBREG, HImode, reg, 0); + operands[1] = gen_lowpart (HImode, reg); } }") (define_insn "" - [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,r,r,r,r,m") - (match_operand:HI 1 "mcore_general_movsrc_operand" "r,I,M,N,c,m,r"))] + [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m") + (match_operand:HI 1 "mcore_general_movsrc_operand" "r,P,i,c,m,r"))] "(register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)) - && (GET_CODE (operands[1]) != CONST_INT - || CONST_OK_FOR_M (INTVAL (operands[1])) - || CONST_OK_FOR_N (INTVAL (operands[1])) - || CONST_OK_FOR_I (INTVAL (operands[1])))" - "@ - mov %0,%1 - movi %0,%1 - bgeni %0,%P1 - bmaski %0,%N1 - mvc %0 - ld.h %0,%1 - st.h %1,%0" - [(set_attr "type" "move,move,move,move,move,load,store")]) - -;; Like movhi, but the const_int source can't be synthesized in -;; a single-instruction. Fall back to the same things that -;; are done for movsi in such cases. Presumes that we can -;; modify any parts of the register that we wish. - -(define_insn "" - [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,a") - (match_operand:HI 1 "const_int_operand" "P,i"))] - "GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) > 127 && INTVAL (operands[1]) < 65536" - "* -{ - if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15 - && !mcore_const_ok_for_inline (INTVAL (operands[1]))) - { - /* mcore_output_move would generate lrw r15 -- a forbidden combo */ - return mcore_output_inline_const_forced (insn, operands, SImode); - } - else - return mcore_output_move (insn, operands, SImode); -}" - [(set_attr "type" "move")]) - - -;; if we're still looking around for things to use, here's a last -;; ditch effort that just calls the move. We only let this happen -;; if we're in the reload pass. -;; -(define_insn "" - [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,a") - (match_operand:HI 1 "const_int_operand" "P,i"))] - "reload_in_progress || reload_completed" - "* -{ - if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15 - && !mcore_const_ok_for_inline (INTVAL (operands[1]))) - { - /* mcore_output_move would generate lrw r15 -- a forbidden combo */ - return mcore_output_inline_const_forced (insn, operands, SImode); - } - else - return mcore_output_move (insn, operands, HImode); -}" - [(set_attr "type" "move")]) + || register_operand (operands[1], HImode))" + "* return mcore_output_move (insn, operands, HImode);" + [(set_attr "type" "move,move,move,move,load,store")]) ;; ;; QImode @@ -1427,67 +1290,18 @@ { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_movsi (reg, operands[1])); - operands[1] = gen_rtx (SUBREG, QImode, reg, 0); + operands[1] = gen_lowpart (QImode, reg); } }") (define_insn "" - [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,r,r,r,r,m") - (match_operand:QI 1 "mcore_general_movsrc_operand" "r,I,M,N,c,m,r"))] + [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m") + (match_operand:QI 1 "mcore_general_movsrc_operand" "r,P,i,c,m,r"))] "(register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)) - && (GET_CODE (operands[1]) != CONST_INT - || CONST_OK_FOR_M (INTVAL (operands[1])) - || CONST_OK_FOR_N (INTVAL (operands[1])) - || CONST_OK_FOR_I (INTVAL (operands[1])))" - "@ - mov %0,%1 - movi %0,%1 - bgeni %0,%P1 - bmaski %0,%N1 - mvc %0 - ld.b %0,%1 - st.b %1,%0" - [(set_attr "type" "move,move,move,move,move,load,store")]) - -;; cover the case where the constant is 128..255; this isn't handled -;; in the above case. We could if we wanted to mess with adding a -;; new constraint class like M,N,I. -(define_insn "" - [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r") - (match_operand:QI 1 "const_int_operand" ""))] - "GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) > 127 && INTVAL (operands[1]) < 256" - "* -{ - /* have a constant in range 128..255; have to do 2 insns; we can - * do this with a movi followed by a bseti - */ - operands[2] = GEN_INT (INTVAL (operands[1]) & 0x7f); - return \"movi\\t%0,%2\;bseti\\t%0,7\"; -}" - [(set_attr "type" "move")]) + || register_operand (operands[1], QImode))" + "* return mcore_output_move (insn, operands, QImode);" + [(set_attr "type" "move,move,move,move,load,store")]) -;; if we're still looking around for things to use, here's a last -;; ditch effort that just calls the move. We only let this happen -;; if we're in the reload pass. -;; -(define_insn "" - [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,a") - (match_operand:QI 1 "const_int_operand" "P,i"))] - "(reload_in_progress || reload_completed)" - "* -{ - if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15 - && ! mcore_const_ok_for_inline (INTVAL (operands[1]))) - { - /* mcore_output_move would generate lrw r15 -- a forbidden combo */ - return mcore_output_inline_const_forced (insn, operands, SImode); - } - else - return mcore_output_move (insn, operands, QImode); -}" - [(set_attr "type" "move")]) ;; DImode @@ -1502,15 +1316,12 @@ else if (GET_CODE (operands[1]) == CONST_INT && ! CONST_OK_FOR_I (INTVAL (operands[1])) && ! CONST_OK_FOR_M (INTVAL (operands[1])) - && ! CONST_OK_FOR_N (INTVAL (operands[1])) - && ! reload_completed - && ! reload_in_progress - && GET_CODE (operands[0]) == REG) + && ! CONST_OK_FOR_N (INTVAL (operands[1]))) { - emit_move_insn (operand_subword (operands[0], 0, 1, DImode), - operand_subword_force (operands[1], 0, DImode)); - emit_move_insn (operand_subword (operands[0], 1, 1, DImode), - operand_subword_force (operands[1], 1, DImode)); + int i; + for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD) + emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i), + simplify_gen_subreg (SImode, operands[1], DImode, i)); DONE; } }")