From: Richard Sandiford Date: Sun, 31 Jul 2005 08:35:15 +0000 (+0000) Subject: re PR target/20621 (ICE: in change_address_1, at emit-rtl.c:1886) X-Git-Tag: releases/gcc-3.4.5~290 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=259e858fffe4f65b14dca0c66841fb8d02474757;p=thirdparty%2Fgcc.git re PR target/20621 (ICE: in change_address_1, at emit-rtl.c:1886) PR target/20621 Backport from mainline: 2004-08-01 Richard Sandiford * config/mips/mips.md (cprestore): Provide two alternatives, one for an in-range offset and one for an out-of-range offset. Wrap the latter in .set macro/.set nomacro if it's inside a .set nomacro block. 2004-08-01 Richard Sandiford * config/mips/mips-protos.h (mips_gp_save_slot): Remove. (mips_restore_gp): Declare. * config/mips/mips.c (mips_add_offset): Add a scratch register argument. Reimplement in rtl only, reusing MIPS16 logic from mips_output_mi_thunk. (mips_legitimize_address, mips_legitimize_const_move): Adjust calls to mips_add_offset. (mips_gp_save_slot): Delete. (mips_restore_gp): New function. (mips_set_return_address, mips_output_mi_thunk): Use mips_add_offset. * config/mips/mips.md (exception_receiver): Turn into a define_insn_and_split. Use mips_restore_gp to do the split. (call_internal, call_value_internal, call_value_multiple_internal): Use mips_restore_gp to restore $gp. From-SVN: r102605 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45cb9249f849..12753f374724 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2005-07-31 Richard Sandiford + + PR target/20621 + Backport from mainline: + + 2004-08-01 Richard Sandiford + * config/mips/mips.md (cprestore): Provide two alternatives, one for + an in-range offset and one for an out-of-range offset. Wrap the latter + in .set macro/.set nomacro if it's inside a .set nomacro block. + + 2004-08-01 Richard Sandiford + * config/mips/mips-protos.h (mips_gp_save_slot): Remove. + (mips_restore_gp): Declare. + * config/mips/mips.c (mips_add_offset): Add a scratch register + argument. Reimplement in rtl only, reusing MIPS16 logic from + mips_output_mi_thunk. + (mips_legitimize_address, mips_legitimize_const_move): Adjust calls + to mips_add_offset. + (mips_gp_save_slot): Delete. + (mips_restore_gp): New function. + (mips_set_return_address, mips_output_mi_thunk): Use mips_add_offset. + * config/mips/mips.md (exception_receiver): Turn into a + define_insn_and_split. Use mips_restore_gp to do the split. + (call_internal, call_value_internal, call_value_multiple_internal): Use + mips_restore_gp to restore $gp. + 2005-07-29 Alan Modra * config/rs6000/sysv4.h (TARGET_ASM_EXCEPTION_SECTION): Delete. diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 2045f2e48a0b..bca8f3b449a1 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -62,7 +62,7 @@ extern rtx mips_subword (rtx, int); extern bool mips_split_64bit_move_p (rtx, rtx); extern void mips_split_64bit_move (rtx, rtx); extern const char *mips_output_move (rtx, rtx); -extern rtx mips_gp_save_slot (void); +extern void mips_restore_gp (void); #ifdef RTX_CODE extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *); extern void gen_conditional_branch (rtx *, enum rtx_code); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index bb4359e49bf9..0aa24f6a3c1e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -206,7 +206,7 @@ static rtx mips_split_symbol (rtx, rtx); static rtx mips_unspec_address (rtx, enum mips_symbol_type); static rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type); static rtx mips_load_got (rtx, rtx, enum mips_symbol_type); -static rtx mips_add_offset (rtx, HOST_WIDE_INT); +static rtx mips_add_offset (rtx, rtx, HOST_WIDE_INT); static unsigned int mips_build_shift (struct mips_integer_op *, HOST_WIDE_INT); static unsigned int mips_build_lower (struct mips_integer_op *, unsigned HOST_WIDE_INT); @@ -1787,18 +1787,33 @@ mips_load_got_global (rtx base, rtx addr) } -/* Return a legitimate address for REG + OFFSET. This function will - create a temporary register if OFFSET is not a SMALL_OPERAND. */ +/* Return a legitimate address for REG + OFFSET. TEMP is as for + mips_force_temporary; it is only needed when OFFSET is not a + SMALL_OPERAND. */ static rtx -mips_add_offset (rtx reg, HOST_WIDE_INT offset) +mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) { if (!SMALL_OPERAND (offset)) - reg = expand_simple_binop (GET_MODE (reg), PLUS, - GEN_INT (CONST_HIGH_PART (offset)), - reg, NULL, 0, OPTAB_WIDEN); - - return plus_constant (reg, CONST_LOW_PART (offset)); + { + rtx high; + if (TARGET_MIPS16) + { + /* Load the full offset into a register so that we can use + an unextended instruction for the address itself. */ + high = GEN_INT (offset); + offset = 0; + } + else + { + /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. */ + high = GEN_INT (CONST_HIGH_PART (offset)); + offset = CONST_LOW_PART (offset); + } + high = mips_force_temporary (temp, high); + reg = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); + } + return plus_constant (reg, offset); } @@ -1829,7 +1844,7 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode) reg = XEXP (*xloc, 0); if (!mips_valid_base_register_p (reg, mode, 0)) reg = copy_to_mode_reg (Pmode, reg); - *xloc = mips_add_offset (reg, INTVAL (XEXP (*xloc, 1))); + *xloc = mips_add_offset (0, reg, INTVAL (XEXP (*xloc, 1))); return true; } @@ -2007,7 +2022,7 @@ mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) && (!no_new_pseudos || SMALL_OPERAND (offset))) { base = mips_force_temporary (dest, base); - emit_move_insn (dest, mips_add_offset (base, offset)); + emit_move_insn (dest, mips_add_offset (0, base, offset)); return; } @@ -2772,25 +2787,28 @@ mips_output_move (rtx dest, rtx src) abort (); } -/* Return an rtx for the gp save slot. Valid only when using o32 or +/* Restore $gp from its save slot. Valid only when using o32 or o64 abicalls. */ -rtx -mips_gp_save_slot (void) +void +mips_restore_gp (void) { - rtx loc; + rtx address, slot; if (!TARGET_ABICALLS || TARGET_NEWABI) abort (); - if (frame_pointer_needed) - loc = hard_frame_pointer_rtx; - else - loc = stack_pointer_rtx; - loc = plus_constant (loc, current_function_outgoing_args_size); - loc = gen_rtx_MEM (Pmode, loc); - RTX_UNCHANGING_P (loc) = 1; - return loc; + address = mips_add_offset (pic_offset_table_rtx, + frame_pointer_needed + ? hard_frame_pointer_rtx + : stack_pointer_rtx, + current_function_outgoing_args_size); + slot = gen_rtx_MEM (Pmode, address); + RTX_UNCHANGING_P (slot) = 1; + + emit_move_insn (pic_offset_table_rtx, slot); + if (!TARGET_EXPLICIT_RELOCS) + emit_insn (gen_blockage ()); } /* Make normal rtx_code into something we can index from an array */ @@ -3403,26 +3421,15 @@ mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch) void mips_set_return_address (rtx address, rtx scratch) { - HOST_WIDE_INT gp_offset; + rtx slot_address; compute_frame_size (get_frame_size ()); if (((cfun->machine->frame.mask >> 31) & 1) == 0) abort (); - gp_offset = cfun->machine->frame.gp_sp_offset; - - /* Reduce SP + GP_OFSET to a legitimate address and put it in SCRATCH. */ - if (gp_offset < 32768) - scratch = plus_constant (stack_pointer_rtx, gp_offset); - else - { - emit_move_insn (scratch, GEN_INT (gp_offset)); - if (Pmode == DImode) - emit_insn (gen_adddi3 (scratch, scratch, stack_pointer_rtx)); - else - emit_insn (gen_addsi3 (scratch, scratch, stack_pointer_rtx)); - } + slot_address = mips_add_offset (scratch, stack_pointer_rtx, + cfun->machine->frame.gp_sp_offset); - emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address); + emit_move_insn (gen_rtx_MEM (GET_MODE (address), slot_address), address); } /* Emit straight-line code to move LENGTH bytes from SRC to DEST. @@ -7190,25 +7197,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, emit_move_insn (temp1, gen_rtx_MEM (Pmode, this)); /* Set ADDR to a legitimate address for *THIS + VCALL_OFFSET. */ - if (SMALL_OPERAND (vcall_offset)) - addr = gen_rtx_PLUS (Pmode, temp1, GEN_INT (vcall_offset)); - else if (TARGET_MIPS16) - { - /* Load the full offset into a register so that we can use - an unextended instruction for the load itself. */ - emit_move_insn (temp2, GEN_INT (vcall_offset)); - emit_insn (gen_add3_insn (temp1, temp1, temp2)); - addr = temp1; - } - else - { - /* Load the high part of the offset into a register and - leave the low part for the address. */ - emit_move_insn (temp2, GEN_INT (CONST_HIGH_PART (vcall_offset))); - emit_insn (gen_add3_insn (temp1, temp1, temp2)); - addr = gen_rtx_PLUS (Pmode, temp1, - GEN_INT (CONST_LOW_PART (vcall_offset))); - } + addr = mips_add_offset (temp2, temp1, vcall_offset); /* Load the offset and add it to THIS. */ emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr)); diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 35f89f0a1b43..505454235604 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -5160,16 +5160,21 @@ dsrl\t%3,%3,1\n\ (set_attr "mode" "none") (set_attr "length" "0")]) -;; Emit a .cprestore directive, which expands to a single store instruction. -;; Note that we continue to use .cprestore for explicit reloc code so that -;; jals inside inlines asms will work correctly. +;; Emit a .cprestore directive, which normally expands to a single store +;; instruction. Note that we continue to use .cprestore for explicit reloc +;; code so that jals inside inline asms will work correctly. (define_insn "cprestore" - [(unspec_volatile [(match_operand 0 "const_int_operand" "")] + [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")] UNSPEC_CPRESTORE)] "" - ".cprestore\t%0" +{ + if (set_nomacro && which_alternative == 1) + return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro"; + else + return ".cprestore\t%0"; +} [(set_attr "type" "store") - (set_attr "length" "4")]) + (set_attr "length" "4,12")]) ;; Block moves, see mips.c for more details. ;; Argument 0 is the destination @@ -8367,17 +8372,19 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" DONE; }) -(define_insn "exception_receiver" +(define_insn_and_split "exception_receiver" [(set (reg:SI 28) (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))] "TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)" + "#" + "&& reload_completed" + [(const_int 0)] { - operands[0] = pic_offset_table_rtx; - operands[1] = mips_gp_save_slot (); - return mips_output_move (operands[0], operands[1]); + mips_restore_gp (); + DONE; } [(set_attr "type" "load") - (set_attr "length" "8")]) + (set_attr "length" "12")]) ;; ;; .................... @@ -8548,7 +8555,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" { emit_call_insn (gen_call_split (operands[0], operands[1])); if (!find_reg_note (operands[2], REG_NORETURN, 0)) - emit_move_insn (pic_offset_table_rtx, mips_gp_save_slot ()); + mips_restore_gp (); DONE; } [(set_attr "jal" "indirect,direct") @@ -8589,7 +8596,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" emit_call_insn (gen_call_value_split (operands[0], operands[1], operands[2])); if (!find_reg_note (operands[3], REG_NORETURN, 0)) - emit_move_insn (pic_offset_table_rtx, mips_gp_save_slot ()); + mips_restore_gp (); DONE; } [(set_attr "jal" "indirect,direct") @@ -8622,7 +8629,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1], operands[2], operands[3])); if (!find_reg_note (operands[4], REG_NORETURN, 0)) - emit_move_insn (pic_offset_table_rtx, mips_gp_save_slot ()); + mips_restore_gp (); DONE; } [(set_attr "jal" "indirect,direct") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6612dedf20c1..53396fba8c57 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-07-31 Richard Sandiford + + PR target/20621 + * gcc.c-torture/execute/pr20621-1.c: New test. + 2005-07-28 Joseph S. Myers PR c/17188