summaryrefslogtreecommitdiff
path: root/gcc/config/epiphany/epiphany.c
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-13 00:29:36 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-13 00:29:36 +0000
commit4af825f31b7216ac31dbc0397771219881e61be4 (patch)
treee3ecbeedf510584b706045b1f77909c17261de6c /gcc/config/epiphany/epiphany.c
parent25bbd2a1db86ab58645225128a727c1c0bd702c3 (diff)
downloadgcc-4af825f31b7216ac31dbc0397771219881e61be4.tar.gz
Fix EH handling issue in last change:
* config/epiphany/epiphany.c (epiphany_init): Check size of NUM_MODES_FOR_MODE_SWITCHING. (epiphany_expand_prologue): Remove CONFIG_REGNUM initial value handling code. (epiphany_optimize_mode_switching): Handle EPIPHANY_MSW_ENTITY_CONFIG. (epiphany_mode_needed, epiphany_mode_entry_exit): Likewise. (emit_set_fp_mode, epiphany_mode_after): Likewise. (epiphany_mode_needed) <Handle EPIPHANY_MSW_ENTITY_AND>: Don't return 1 for FP_MODE_NONE. * config/epiphany/epiphany.h (NUM_MODES_FOR_MODE_SWITCHING): Add value for EPIPHANY_MSW_ENTITY_CONFIG. (EPIPHANY_MSW_ENTITY_CONFIG, EPIPHANY_MSW_ENTITY_NUM): Define. * config/epiphany/epiphany.md (save_config): New pattern. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198811 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/epiphany/epiphany.c')
-rw-r--r--gcc/config/epiphany/epiphany.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index 74192bf4621..3b6f63ab975 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -2328,7 +2328,15 @@ epiphany_mode_needed (int entity, rtx insn)
just unchanged from the function start.
Because of the nature of the mode switching optimization,
a restore will be dominated by a clobber. */
- return mode != FP_MODE_NONE && mode != FP_MODE_CALLER ? 1 : 2;
+ if (mode != FP_MODE_NONE && mode != FP_MODE_CALLER)
+ return 1;
+ /* A cpecial case are abnormal edges, which are deemed to clobber
+ the mode as well. We need to pin this effect on a actually
+ dominating insn, and one where the frame can be accessed, too, in
+ case the pseudo used to save CONFIG doesn't get a hard register. */
+ if (CALL_P (insn) && find_reg_note (insn, REG_EH_REGION, NULL_RTX))
+ return 1;
+ return 2;
case EPIPHANY_MSW_ENTITY_ROUND_KNOWN:
if (recog_memoized (insn) == CODE_FOR_set_fp_mode)
mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn);
@@ -2402,6 +2410,18 @@ epiphany_mode_after (int entity, int last_mode, rtx insn)
return 0;
return last_mode;
}
+ /* If there is an abnormal edge, we don't want the config register to
+ be 'saved' again at the destination.
+ The frame pointer adjustment is inside a PARALLEL because of the
+ flags clobber. */
+ if (entity == EPIPHANY_MSW_ENTITY_CONFIG && NONJUMP_INSN_P (insn)
+ && GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET
+ && SET_DEST (XVECEXP (PATTERN (insn), 0, 0)) == frame_pointer_rtx)
+ {
+ gcc_assert (cfun->has_nonlocal_label);
+ return 1;
+ }
if (recog_memoized (insn) < 0)
return last_mode;
if (get_attr_fp_mode (insn) == FP_MODE_ROUND_UNKNOWN