diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-03-13 09:02:51 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-03-13 09:02:51 +0000 |
commit | e13693ec52ef71840ac067e53d83229b472c0f49 (patch) | |
tree | 6924a196edd1c1f5127f1d9ebb210b51d1624930 /gcc/emit-rtl.c | |
parent | 13efad58f26bec3886694b5fef7cb7b36e07b58b (diff) | |
download | gcc-e13693ec52ef71840ac067e53d83229b472c0f49.tar.gz |
* emit-rtl.c (try_split): Handle 1-1 splits of call insns properly.
* config/ia64/ia64.c (TARGET_FUNCTION_OK_FOR_SIBCALL): New.
(ia64_gp_save_reg): Remove.
(struct ia64_frame_info): Move to the beginning of the file;
add reg_save_gp.
(ia64_expand_call): Rearrange for new call patterns.
(ia64_reload_gp): New.
(ia64_split_call): New.
(ia64_compute_frame_size): Allocate reg_save_gp.
(ia64_expand_prologue): Save reg_save_gp.
(ia64_expand_epilogue): Don't restore gp.
(ia64_hard_regno_rename_ok): Remove R4 hack.
(ia64_function_ok_for_sibcall): New.
(ia64_output_mi_thunk): Set reload_completed, no_new_pseudos;
call try_split on sibcall pattern.
* config/ia64/ia64-protos.h: Update.
* config/ia64/ia64.md (call_nogp, call_value_nogp, sibcall_nogp):
Rename from nopic versions. Confiscate 2nd argument to call as
a marker.
(call_pic, call_value_pic, sibcall_pic): Remove.
(call_gp, call_value_gp, sibcall_gp): New.
(builtin_setjmp_setup): Remove.
(builtin_setjmp_receiver): Call ia64_reload_gp.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@64303 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r-- | gcc/emit-rtl.c | 265 |
1 files changed, 121 insertions, 144 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 9ba85396901..ad30637ee0a 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -3375,6 +3375,8 @@ try_split (pat, trial, last) rtx tem; rtx note, seq; int probability; + rtx insn_last, insn; + int njumps = 0; if (any_condjump_p (trial) && (note = find_reg_note (trial, REG_BR_PROB, 0))) @@ -3393,172 +3395,147 @@ try_split (pat, trial, last) after = NEXT_INSN (after); } - if (seq) + if (!seq) + return trial; + + /* Avoid infinite loop if any insn of the result matches + the original pattern. */ + insn_last = seq; + while (1) { - /* Sometimes there will be only one insn in that list, this case will - normally arise only when we want it in turn to be split (SFmode on - the 29k is an example). */ - if (NEXT_INSN (seq) != NULL_RTX) - { - rtx insn_last, insn; - int njumps = 0; + if (INSN_P (insn_last) + && rtx_equal_p (PATTERN (insn_last), pat)) + return trial; + if (!NEXT_INSN (insn_last)) + break; + insn_last = NEXT_INSN (insn_last); + } - /* Avoid infinite loop if any insn of the result matches - the original pattern. */ - insn_last = seq; - while (1) + /* Mark labels. */ + for (insn = insn_last; insn ; insn = PREV_INSN (insn)) + { + if (GET_CODE (insn) == JUMP_INSN) + { + mark_jump_label (PATTERN (insn), insn, 0); + njumps++; + if (probability != -1 + && any_condjump_p (insn) + && !find_reg_note (insn, REG_BR_PROB, 0)) { - if (INSN_P (insn_last) - && rtx_equal_p (PATTERN (insn_last), pat)) - return trial; - if (NEXT_INSN (insn_last) == NULL_RTX) - break; - insn_last = NEXT_INSN (insn_last); + /* We can preserve the REG_BR_PROB notes only if exactly + one jump is created, otherwise the machine description + is responsible for this step using + split_branch_probability variable. */ + if (njumps != 1) + abort (); + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_BR_PROB, + GEN_INT (probability), + REG_NOTES (insn)); } + } + } - /* Mark labels. */ + /* If we are splitting a CALL_INSN, look for the CALL_INSN + in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */ + if (GET_CODE (trial) == CALL_INSN) + { + for (insn = insn_last; insn ; insn = PREV_INSN (insn)) + if (GET_CODE (insn) == CALL_INSN) + { + CALL_INSN_FUNCTION_USAGE (insn) + = CALL_INSN_FUNCTION_USAGE (trial); + SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial); + } + } + + /* Copy notes, particularly those related to the CFG. */ + for (note = REG_NOTES (trial); note; note = XEXP (note, 1)) + { + switch (REG_NOTE_KIND (note)) + { + case REG_EH_REGION: insn = insn_last; while (insn != NULL_RTX) { - if (GET_CODE (insn) == JUMP_INSN) - { - mark_jump_label (PATTERN (insn), insn, 0); - njumps++; - if (probability != -1 - && any_condjump_p (insn) - && !find_reg_note (insn, REG_BR_PROB, 0)) - { - /* We can preserve the REG_BR_PROB notes only if exactly - one jump is created, otherwise the machine description - is responsible for this step using - split_branch_probability variable. */ - if (njumps != 1) - abort (); - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (probability), - REG_NOTES (insn)); - } - } - + if (GET_CODE (insn) == CALL_INSN + || (flag_non_call_exceptions + && may_trap_p (PATTERN (insn)))) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_EH_REGION, + XEXP (note, 0), + REG_NOTES (insn)); insn = PREV_INSN (insn); } + break; - /* If we are splitting a CALL_INSN, look for the CALL_INSN - in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */ - if (GET_CODE (trial) == CALL_INSN) - { - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == CALL_INSN) - CALL_INSN_FUNCTION_USAGE (insn) - = CALL_INSN_FUNCTION_USAGE (trial); - - insn = PREV_INSN (insn); - } - } - - /* Copy notes, particularly those related to the CFG. */ - for (note = REG_NOTES (trial); note; note = XEXP (note, 1)) + case REG_NORETURN: + case REG_SETJMP: + case REG_ALWAYS_RETURN: + insn = insn_last; + while (insn != NULL_RTX) { - switch (REG_NOTE_KIND (note)) - { - case REG_EH_REGION: - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == CALL_INSN - || (flag_non_call_exceptions - && may_trap_p (PATTERN (insn)))) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_EH_REGION, - XEXP (note, 0), - REG_NOTES (insn)); - insn = PREV_INSN (insn); - } - break; - - case REG_NORETURN: - case REG_SETJMP: - case REG_ALWAYS_RETURN: - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == CALL_INSN) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); - insn = PREV_INSN (insn); - } - break; - - case REG_NON_LOCAL_GOTO: - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == JUMP_INSN) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); - insn = PREV_INSN (insn); - } - break; - - default: - break; - } + if (GET_CODE (insn) == CALL_INSN) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); } + break; - /* If there are LABELS inside the split insns increment the - usage count so we don't delete the label. */ - if (GET_CODE (trial) == INSN) + case REG_NON_LOCAL_GOTO: + insn = insn_last; + while (insn != NULL_RTX) { - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == INSN) - mark_label_nuses (PATTERN (insn)); - - insn = PREV_INSN (insn); - } + if (GET_CODE (insn) == JUMP_INSN) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); } + break; - tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial)); - - delete_insn (trial); - if (has_barrier) - emit_barrier_after (tem); - - /* Recursively call try_split for each new insn created; by the - time control returns here that insn will be fully split, so - set LAST and continue from the insn after the one returned. - We can't use next_active_insn here since AFTER may be a note. - Ignore deleted insns, which can be occur if not optimizing. */ - for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) - if (! INSN_DELETED_P (tem) && INSN_P (tem)) - tem = try_split (PATTERN (tem), tem, 1); + default: + break; } - /* Avoid infinite loop if the result matches the original pattern. */ - else if (rtx_equal_p (PATTERN (seq), pat)) - return trial; - else + } + + /* If there are LABELS inside the split insns increment the + usage count so we don't delete the label. */ + if (GET_CODE (trial) == INSN) + { + insn = insn_last; + while (insn != NULL_RTX) { - PATTERN (trial) = PATTERN (seq); - INSN_CODE (trial) = -1; - try_split (PATTERN (trial), trial, last); - } + if (GET_CODE (insn) == INSN) + mark_label_nuses (PATTERN (insn)); - /* Return either the first or the last insn, depending on which was - requested. */ - return last - ? (after ? PREV_INSN (after) : last_insn) - : NEXT_INSN (before); + insn = PREV_INSN (insn); + } } - return trial; + tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial)); + + delete_insn (trial); + if (has_barrier) + emit_barrier_after (tem); + + /* Recursively call try_split for each new insn created; by the + time control returns here that insn will be fully split, so + set LAST and continue from the insn after the one returned. + We can't use next_active_insn here since AFTER may be a note. + Ignore deleted insns, which can be occur if not optimizing. */ + for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) + if (! INSN_DELETED_P (tem) && INSN_P (tem)) + tem = try_split (PATTERN (tem), tem, 1); + + /* Return either the first or the last insn, depending on which was + requested. */ + return last + ? (after ? PREV_INSN (after) : last_insn) + : NEXT_INSN (before); } /* Make and return an INSN rtx, initializing all its slots. |