X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Frecog.c;h=32ed021bb9798bbedb6505f6f29b43286cf13f79;hb=0958a641e614f832728291f512df7a293137f784;hp=933168149a870302575b5e4926bbc16b5eef2439;hpb=eb2457b02629ace37401c3e8df2b74ca769ef865;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/recog.c b/gcc/recog.c index 933168149a8..32ed021bb97 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -118,6 +118,25 @@ init_recog (void) } +/* Return true if labels in asm operands BODY are LABEL_REFs. */ + +static bool +asm_labels_ok (rtx body) +{ + rtx asmop; + int i; + + asmop = extract_asm_operands (body); + if (asmop == NULL_RTX) + return true; + + for (i = 0; i < ASM_OPERANDS_LABEL_LENGTH (asmop); i++) + if (GET_CODE (ASM_OPERANDS_LABEL (asmop, i)) != LABEL_REF) + return false; + + return true; +} + /* Check that X is an insn-body for an `asm' with operands and that the operands mentioned in it are legitimate. */ @@ -129,6 +148,9 @@ check_asm_operands (rtx x) const char **constraints; int i; + if (!asm_labels_ok (x)) + return 0; + /* Post-reload, be more strict with things. */ if (reload_completed) { @@ -903,10 +925,7 @@ next_insn_tests_no_inequality (rtx insn) it has. The main use of this function is as a predicate in match_operand - expressions in the machine description. - - For an explanation of this function's behavior for registers of - class NO_REGS, see the comment for `register_operand'. */ + expressions in the machine description. */ int general_operand (rtx op, enum machine_mode mode) @@ -976,9 +995,8 @@ general_operand (rtx op, enum machine_mode mode) } if (code == REG) - /* A register whose class is NO_REGS is not a general operand. */ return (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) != NO_REGS); + || in_hard_reg_set_p (operand_reg_set, GET_MODE (op), REGNO (op))); if (code == MEM) { @@ -1011,15 +1029,7 @@ address_operand (rtx op, enum machine_mode mode) If MODE is VOIDmode, accept a register in any mode. The main use of this function is as a predicate in match_operand - expressions in the machine description. - - As a special exception, registers whose class is NO_REGS are - not accepted by `register_operand'. The reason for this change - is to allow the representation of special architecture artifacts - (such as a condition code register) without extending the rtl - definitions. Since registers of class NO_REGS cannot be used - as registers in any case where register classes are examined, - it is most consistent to keep this function from accepting them. */ + expressions in the machine description. */ int register_operand (rtx op, enum machine_mode mode) @@ -1058,11 +1068,10 @@ register_operand (rtx op, enum machine_mode mode) op = sub; } - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ return (REG_P (op) && (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); + || in_hard_reg_set_p (operand_reg_set, + GET_MODE (op), REGNO (op)))); } /* Return 1 for a register in Pmode; ignore the tested mode. */ @@ -1181,11 +1190,10 @@ nonmemory_operand (rtx op, enum machine_mode mode) op = SUBREG_REG (op); } - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ return (REG_P (op) && (REGNO (op) >= FIRST_PSEUDO_REGISTER - || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); + || in_hard_reg_set_p (operand_reg_set, + GET_MODE (op), REGNO (op)))); } /* Return 1 if OP is a valid operand that stands for pushing a @@ -2259,7 +2267,8 @@ preprocess_constraints (void) case 'p': op_alt[j].is_address = 1; op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl] - [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; + [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, + ADDRESS, SCRATCH)]; break; case 'g': @@ -2280,8 +2289,8 @@ preprocess_constraints (void) op_alt[j].cl = (reg_class_subunion [(int) op_alt[j].cl] - [(int) base_reg_class (VOIDmode, ADDRESS, - SCRATCH)]); + [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, + ADDRESS, SCRATCH)]); break; } @@ -2664,6 +2673,16 @@ constrain_operands (int strict) /* Every address operand can be reloaded to fit. */ && strict < 0) win = 1; + /* Cater to architectures like IA-64 that define extra memory + constraints without using define_memory_constraint. */ + else if (reload_in_progress + && REG_P (op) + && REGNO (op) >= FIRST_PSEUDO_REGISTER + && reg_renumber[REGNO (op)] < 0 + && reg_equiv_mem (REGNO (op)) != 0 + && EXTRA_CONSTRAINT_STR + (reg_equiv_mem (REGNO (op)), c, p)) + win = 1; #endif break; } @@ -3011,6 +3030,9 @@ peep2_reg_dead_p (int ofs, rtx reg) return 1; } +/* Regno offset to be used in the register search. */ +static int search_ofs; + /* Try to find a hard register of mode MODE, matching the register class in CLASS_STR, which is available at the beginning of insn CURRENT_INSN and remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX, @@ -3026,9 +3048,9 @@ rtx peep2_find_free_register (int from, int to, const char *class_str, enum machine_mode mode, HARD_REG_SET *reg_set) { - static int search_ofs; enum reg_class cl; HARD_REG_SET live; + df_ref *def_rec; int i; gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1); @@ -3042,12 +3064,14 @@ peep2_find_free_register (int from, int to, const char *class_str, while (from != to) { - HARD_REG_SET this_live; + gcc_assert (peep2_insn_data[from].insn != NULL_RTX); + + /* Don't use registers set or clobbered by the insn. */ + for (def_rec = DF_INSN_DEFS (peep2_insn_data[from].insn); + *def_rec; def_rec++) + SET_HARD_REG_BIT (live, DF_REF_REGNO (*def_rec)); from = peep2_buf_position (from + 1); - gcc_assert (peep2_insn_data[from].insn != NULL_RTX); - REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before); - IOR_HARD_REG_SET (live, this_live); } cl = (class_str[0] == 'r' ? GENERAL_REGS @@ -3146,16 +3170,17 @@ static rtx peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) { int i; - rtx last, note, before_try, x; + rtx last, eh_note, as_note, before_try, x; rtx old_insn, new_insn; bool was_call = false; - /* If we are splittind an RTX_FRAME_RELATED_P insn, do not allow it to + /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to match more than one insn, or to be split into more than one insn. */ old_insn = peep2_insn_data[peep2_current].insn; if (RTX_FRAME_RELATED_P (old_insn)) { bool any_note = false; + rtx note; if (match_len != 0) return NULL; @@ -3236,6 +3261,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) for (i = 0; i <= match_len; ++i) { int j; + rtx note; j = peep2_buf_position (peep2_current + i); old_insn = peep2_insn_data[j].insn; @@ -3263,6 +3289,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) { case REG_NORETURN: case REG_SETJMP: + case REG_TM: add_reg_note (new_insn, REG_NOTE_KIND (note), XEXP (note, 0)); break; @@ -3281,9 +3308,21 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) break; } - i = peep2_buf_position (peep2_current + match_len); + /* If we matched any instruction that had a REG_ARGS_SIZE, then + move those notes over to the new sequence. */ + as_note = NULL; + for (i = match_len; i >= 0; --i) + { + int j = peep2_buf_position (peep2_current + i); + old_insn = peep2_insn_data[j].insn; + + as_note = find_reg_note (old_insn, REG_ARGS_SIZE, NULL); + if (as_note) + break; + } - note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX); + i = peep2_buf_position (peep2_current + match_len); + eh_note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX); /* Replace the old sequence with the new. */ last = emit_insn_after_setloc (attempt, @@ -3293,7 +3332,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) delete_insn_chain (insn, peep2_insn_data[i].insn, false); /* Re-insert the EH_REGION notes. */ - if (note || (was_call && nonlocal_goto_handler_labels)) + if (eh_note || (was_call && nonlocal_goto_handler_labels)) { edge eh_edge; edge_iterator ei; @@ -3302,8 +3341,8 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) break; - if (note) - copy_reg_eh_region_note_backward (note, last, before_try); + if (eh_note) + copy_reg_eh_region_note_backward (eh_note, last, before_try); if (eh_edge) for (x = last; x != before_try; x = PREV_INSN (x)) @@ -3336,6 +3375,10 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) peep2_do_cleanup_cfg |= purge_dead_edges (bb); } + /* Re-insert the ARGS_SIZE notes. */ + if (as_note) + fixup_args_size_notes (before_try, last, INTVAL (XEXP (as_note, 0))); + /* If we generated a jump instruction, it won't have JUMP_LABEL set. Recompute after we're done. */ for (x = last; x != before_try; x = PREV_INSN (x)) @@ -3447,6 +3490,7 @@ peephole2_optimize (void) /* Initialize the regsets we're going to use. */ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) peep2_insn_data[i].live_before = BITMAP_ALLOC (®_obstack); + search_ofs = 0; live = BITMAP_ALLOC (®_obstack); FOR_EACH_BB_REVERSE (bb)