Index: gcc/ChangeLog from Alexandre Oliva * config/h8300/h8300.c (h8300_reg_class_from_letter): Map 'D' to GENERAL_REGS, always. (h8300_swap_into_er6, h8300_swap_into_er6): Handle the case of getting the stack pointer as addr. * config/h8300/h8300.h (PREDICATE_CODES): Remove constant rtxes from general_operand_dst. (movmd_internal_normal): New, normal-mode variant of... (movmd_internal): ... this. Add modes to operands. Disparage `D' instead of requiring it to match only before reload. (stpcpy_internal_normal): New, normal-mode variant of... (stpcpy_internal): ... this. Add modes to operands. Disparage `D' instead of requiring it to match only before reload. Index: gcc/config/h8300/h8300.c =================================================================== RCS file: /cvs/cvsfiles/gnupro/gcc/config/h8300/h8300.c,v retrieving revision 1.6 diff -u -p -r1.6 h8300.c --- gcc/config/h8300/h8300.c 21 Jun 2004 19:20:15 -0000 1.6 +++ gcc/config/h8300/h8300.c 27 Jun 2004 03:42:35 -0000 @@ -454,12 +454,16 @@ h8300_init_once (void) before reload so that register allocator will pick the second alternative. - - 'D' should be NO_REGS when the frame pointer isn't live. - The idea is to *make* it live by restricting the register allocator - to the first alternative. This isn't needed for correctness - but it produces better code for small functions: it's more - efficient to save and restore er6 in the prologue & epilogue - than to do it in a define_split. */ + - we would like 'D' to be be NO_REGS when the frame pointer isn't + live, but we the frame pointer may turn out to be needed after + we start reload, and then we may have already decided we don't + have a choice, so we can't do that. Forcing the register + allocator to use er6 if possible might produce better code for + small functions: it's more efficient to save and restore er6 in + the prologue & epilogue than to do it in a define_split. + Hopefully disparaging 'D' will have a similar effect, without + forcing a reload failure if the frame pointer is found to be + needed too late. */ enum reg_class h8300_reg_class_from_letter (int c) @@ -480,8 +484,8 @@ h8300_reg_class_from_letter (int c) return DESTINATION_REGS; case 'D': - if (!regs_ever_live[FP_REG]) - return NO_REGS; + /* The meaning of a constraint shouldn't change dynamically, so + we can't make this NO_REGS. */ return GENERAL_REGS; case 'f': @@ -3005,6 +3009,10 @@ h8300_swap_into_er6 (rtx addr) { push (HARD_FRAME_POINTER_REGNUM); emit_move_insn (hard_frame_pointer_rtx, addr); + if (REGNO (addr) == SP_REG) + emit_move_insn (hard_frame_pointer_rtx, + plus_constant (hard_frame_pointer_rtx, + GET_MODE_SIZE (word_mode))); } /* Move the current value of er6 into ADDR and pop its old value @@ -3013,7 +3021,8 @@ h8300_swap_into_er6 (rtx addr) void h8300_swap_out_of_er6 (rtx addr) { - emit_move_insn (addr, hard_frame_pointer_rtx); + if (REGNO (addr) != SP_REG) + emit_move_insn (addr, hard_frame_pointer_rtx); pop (HARD_FRAME_POINTER_REGNUM); } Index: gcc/config/h8300/h8300.h =================================================================== RCS file: /cvs/cvsfiles/gnupro/gcc/config/h8300/h8300.h,v retrieving revision 1.5 diff -u -p -r1.5 h8300.h --- gcc/config/h8300/h8300.h 21 Jun 2004 12:16:04 -0000 1.5 +++ gcc/config/h8300/h8300.h 27 Jun 2004 03:42:36 -0000 @@ -1335,8 +1335,7 @@ extern int h8300_move_ratio; #define PREDICATE_CODES \ {"general_operand_src", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}}, \ - {"general_operand_dst", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}}, \ + {"general_operand_dst", {SUBREG, REG, MEM, ADDRESSOF}}, \ {"h8300_src_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}}, \ {"h8300_dst_operand", {SUBREG, REG, MEM, ADDRESSOF}}, \ Index: gcc/config/h8300/h8300.md =================================================================== RCS file: /cvs/cvsfiles/gnupro/gcc/config/h8300/h8300.md,v retrieving revision 1.6 diff -u -p -r1.6 h8300.md --- gcc/config/h8300/h8300.md 21 Jun 2004 19:20:15 -0000 1.6 +++ gcc/config/h8300/h8300.md 27 Jun 2004 03:42:37 -0000 @@ -508,16 +508,33 @@ ;; This is a difficult instruction to reload since operand 0 must be the ;; frame pointer. See h8300_reg_class_from_letter for an explanation. +(define_insn "movmd_internal_normal" + [(set (mem:BLK (match_operand:HI 3 "register_operand" "0,r")) + (mem:BLK (match_operand:HI 4 "register_operand" "1,1"))) + (unspec [(match_operand:HI 5 "register_operand" "2,2") + (match_operand:HI 6 "const_int_operand" "n,n")] UNSPEC_MOVMD) + (clobber (match_operand:HI 0 "register_operand" "=d,??D")) + (clobber (match_operand:HI 1 "register_operand" "=f,f")) + (set (match_operand:HI 2 "register_operand" "=c,c") + (const_int 0))] + "TARGET_H8300SX && TARGET_NORMAL_MODE" + "@ + movmd%m6 + #" + [(set_attr "length" "2,14") + (set_attr "can_delay" "no") + (set_attr "cc" "none,clobber")]) + (define_insn "movmd_internal" - [(set (mem:BLK (match_operand 3 "register_operand" "0,r")) - (mem:BLK (match_operand 4 "register_operand" "1,1"))) + [(set (mem:BLK (match_operand:SI 3 "register_operand" "0,r")) + (mem:BLK (match_operand:SI 4 "register_operand" "1,1"))) (unspec [(match_operand:HI 5 "register_operand" "2,2") (match_operand:HI 6 "const_int_operand" "n,n")] UNSPEC_MOVMD) - (clobber (match_operand 0 "register_operand" "=d,!D")) - (clobber (match_operand 1 "register_operand" "=f,f")) + (clobber (match_operand:SI 0 "register_operand" "=d,??D")) + (clobber (match_operand:SI 1 "register_operand" "=f,f")) (set (match_operand:HI 2 "register_operand" "=c,c") (const_int 0))] - "TARGET_H8300SX" + "TARGET_H8300SX && !TARGET_NORMAL_MODE" "@ movmd%m6 #" @@ -541,11 +558,34 @@ (match_operand:BLK 1 "memory_operand" "")) (unspec [(match_operand:HI 2 "register_operand" "") (match_operand:HI 3 "const_int_operand" "")] UNSPEC_MOVMD) - (clobber (match_operand 4 "register_operand" "")) - (clobber (match_operand 5 "register_operand" "")) + (clobber (match_operand:HI 4 "register_operand" "")) + (clobber (match_operand:HI 5 "register_operand" "")) (set (match_dup 2) (const_int 0))] - "TARGET_H8300SX + "TARGET_H8300SX && TARGET_NORMAL_MODE + && reload_completed + && REGNO (operands[4]) != DESTINATION_REG" + [(const_int 0)] + { + rtx dest; + + h8300_swap_into_er6 (XEXP (operands[0], 0)); + dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx); + emit_insn (gen_movmd (dest, operands[1], operands[2], operands[3])); + h8300_swap_out_of_er6 (operands[4]); + DONE; + }) + +(define_split + [(set (match_operand:BLK 0 "memory_operand" "") + (match_operand:BLK 1 "memory_operand" "")) + (unspec [(match_operand:HI 2 "register_operand" "") + (match_operand:HI 3 "const_int_operand" "")] UNSPEC_MOVMD) + (clobber (match_operand:SI 4 "register_operand" "")) + (clobber (match_operand:SI 5 "register_operand" "")) + (set (match_dup 2) + (const_int 0))] + "TARGET_H8300SX && !TARGET_NORMAL_MODE && reload_completed && REGNO (operands[4]) != DESTINATION_REG" [(const_int 0)] @@ -594,14 +634,28 @@ }) ;; See comments above memcpy_internal(). +(define_insn "stpcpy_internal_normal" + [(set (mem:BLK (match_operand:HI 3 "register_operand" "0,r")) + (unspec [(mem:BLK (match_operand:HI 4 "register_operand" "1,1"))] + UNSPEC_STPCPY)) + (clobber (match_operand:HI 0 "register_operand" "=d,??D")) + (clobber (match_operand:HI 1 "register_operand" "=f,f")) + (clobber (match_operand:HI 2 "register_operand" "=c,c"))] + "TARGET_H8300SX && TARGET_NORMAL_MODE" + "@ + \n1:\tmovsd\t2f\;bra\t1b\n2: + #" + [(set_attr "length" "6,18") + (set_attr "cc" "none,clobber")]) + (define_insn "stpcpy_internal" - [(set (mem:BLK (match_operand 3 "register_operand" "0,r")) - (unspec [(mem:BLK (match_operand 4 "register_operand" "1,1"))] + [(set (mem:BLK (match_operand:SI 3 "register_operand" "0,r")) + (unspec [(mem:BLK (match_operand:SI 4 "register_operand" "1,1"))] UNSPEC_STPCPY)) - (clobber (match_operand 0 "register_operand" "=d,!D")) - (clobber (match_operand 1 "register_operand" "=f,f")) - (clobber (match_operand 2 "register_operand" "=c,c"))] - "TARGET_H8300SX" + (clobber (match_operand:SI 0 "register_operand" "=d,??D")) + (clobber (match_operand:SI 1 "register_operand" "=f,f")) + (clobber (match_operand:SI 2 "register_operand" "=c,c"))] + "TARGET_H8300SX && !TARGET_NORMAL_MODE" "@ \n1:\tmovsd\t2f\;bra\t1b\n2: #" @@ -613,10 +667,30 @@ (define_split [(set (match_operand:BLK 0 "memory_operand" "") (unspec [(match_operand:BLK 1 "memory_operand" "")] UNSPEC_STPCPY)) - (clobber (match_operand 2 "register_operand" "")) - (clobber (match_operand 3 "register_operand" "")) - (clobber (match_operand 4 "register_operand" ""))] - "TARGET_H8300SX + (clobber (match_operand:HI 2 "register_operand" "")) + (clobber (match_operand:HI 3 "register_operand" "")) + (clobber (match_operand:HI 4 "register_operand" ""))] + "TARGET_H8300SX && TARGET_NORMAL_MODE + && reload_completed + && REGNO (operands[2]) != DESTINATION_REG" + [(const_int 0)] + { + rtx dest; + + h8300_swap_into_er6 (XEXP (operands[0], 0)); + dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx); + emit_insn (gen_movsd (dest, operands[1], operands[4])); + h8300_swap_out_of_er6 (operands[2]); + DONE; + }) + +(define_split + [(set (match_operand:BLK 0 "memory_operand" "") + (unspec [(match_operand:BLK 1 "memory_operand" "")] UNSPEC_STPCPY)) + (clobber (match_operand:SI 2 "register_operand" "")) + (clobber (match_operand:SI 3 "register_operand" "")) + (clobber (match_operand:SI 4 "register_operand" ""))] + "TARGET_H8300SX && !TARGET_NORMAL_MODE && reload_completed && REGNO (operands[2]) != DESTINATION_REG" [(const_int 0)]