#define OPTIMIZE_MODE_SWITCHING(ENTITY) TARGET_SH4
-#define MODE_USES_IN_EXIT_BLOCK gen_rtx_USE (VOIDmode, get_fpscr_rtx ())
+#define NORMAL_MODE(ENTITY) \
+ (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
+
+#define EPILOGUE_USES(REGNO) (TARGET_SH4 && (REGNO) == FPSCR_REG)
#define MODE_NEEDED(ENTITY, INSN) \
(recog_memoized (INSN) >= 0 \
? get_attr_fp_mode (INSN) \
- : (GET_CODE (PATTERN (INSN)) == USE \
- && rtx_equal_p (XEXP (PATTERN (INSN), 0), get_fpscr_rtx ())) \
- ? (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE) \
: FP_MODE_NONE)
-#define MODE_AT_ENTRY(ENTITY) \
- (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
-
#define MODE_PRIORITY_TO_MODE(ENTITY, N) \
((TARGET_FPU_SINGLE != 0) ^ (N) ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
static sbitmap *delete;
static sbitmap *insert;
-static struct seginfo * new_seginfo PARAMS ((int, rtx, int, HARD_REG_SET));;
+static struct seginfo * new_seginfo PARAMS ((int, rtx, int, HARD_REG_SET));
static void add_seginfo PARAMS ((struct bb_info *, struct seginfo *));
static void reg_dies PARAMS ((rtx, HARD_REG_SET));
static void reg_becomes_live PARAMS ((rtx, rtx, void *));
#ifdef OPTIMIZE_MODE_SWITCHING
/* This function will allocate a new BBINFO structure, initialized
- with the FP_MODE, INSN, and basic block BB parameters. */
+ with the MODE, INSN, and basic block BB parameters. */
static struct seginfo *
new_seginfo (mode, insn, bb, regs_live)
if (! n_entities)
return 0;
-#ifdef MODE_USES_IN_EXIT_BLOCK
- /* For some ABIs a particular mode setting is required at function exit. */
-
- for (eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
- {
- int bb = eg->src->index;
- rtx insn = BLOCK_END (bb);
- rtx use = MODE_USES_IN_EXIT_BLOCK;
-
- /* If the block ends with the use of the return value
- and / or a return, insert the new use(s) in front of them. */
- while ((GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE)
- || GET_CODE (insn) == JUMP_INSN)
- insn = PREV_INSN (insn);
-
- use = emit_insn_after (use, insn);
- if (insn == BLOCK_END (bb))
- BLOCK_END (bb) = use;
- else if (NEXT_INSN (use) == BLOCK_HEAD (bb))
- BLOCK_HEAD (bb) = NEXT_INSN (insn);
- }
-#endif /* MODE_USES_IN_EXIT_BLOCK */
-
/* Create the bitmap vectors. */
antic = sbitmap_vector_alloc (n_basic_blocks, n_entities);
}
}
+ /* If this is a predecessor of the exit block, and we must
+ force a mode on exit, make note of that. */
+#ifdef NORMAL_MODE
+ if (NORMAL_MODE (e) != no_mode && last_mode != NORMAL_MODE (e))
+ for (eg = BASIC_BLOCK (bb)->succ; eg; eg = eg->succ_next)
+ if (eg->dest == EXIT_BLOCK_PTR)
+ {
+ rtx insn = BLOCK_END (bb);
+
+ /* Find the last insn before a USE and/or JUMP. */
+ while ((GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == USE)
+ || GET_CODE (insn) == JUMP_INSN)
+ insn = PREV_INSN (insn);
+ if (insn != BLOCK_END (bb) && NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ last_mode = NORMAL_MODE (e);
+ add_seginfo (info + bb,
+ new_seginfo (last_mode, insn, bb, live_now));
+ RESET_BIT (transp[bb], j);
+ }
+#endif
+
info[bb].computing = last_mode;
/* Check for blocks without ANY mode requirements. */
if (last_mode == no_mode)
add_seginfo (info + bb, ptr);
}
}
-#ifdef MODE_AT_ENTRY
+#ifdef NORMAL_MODE
{
- int mode = MODE_AT_ENTRY (e);
+ int mode = NORMAL_MODE (e);
if (mode != no_mode)
{
}
}
}
-#endif /* MODE_AT_ENTRY */
+#endif /* NORMAL_MODE */
}
kill = sbitmap_vector_alloc (n_basic_blocks, n_entities);
/* Now output the remaining mode sets in all the segments. */
for (j = n_entities - 1; j >= 0; j--)
{
+ int no_mode = num_modes[entity_map[j]];
+
for (bb = n_basic_blocks - 1; bb >= 0; bb--)
{
struct seginfo *ptr, *next;
for (ptr = bb_info[j][bb].seginfo; ptr; ptr = next)
{
next = ptr->next;
- if (ptr->mode != FP_MODE_NONE)
+ if (ptr->mode != no_mode)
{
rtx mode_set;
mode_set = gen_sequence ();
end_sequence ();
- emit_block_insn_before (mode_set, ptr->insn_ptr,
- BASIC_BLOCK (ptr->bbnum));
+ if (NOTE_LINE_NUMBER (ptr->insn_ptr) == NOTE_INSN_BASIC_BLOCK)
+ emit_block_insn_after (mode_set, ptr->insn_ptr,
+ BASIC_BLOCK (ptr->bbnum));
+ else
+ emit_block_insn_before (mode_set, ptr->insn_ptr,
+ BASIC_BLOCK (ptr->bbnum));
}
free (ptr);
If you define this macro, you also have to define
@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{MODE_NEEDED},
@code{MODE_PRIORITY_TO_MODE} and @code{EMIT_MODE_SET}.
-@code{MODE_AT_ENTRY} and @code{MODE_USES_IN_EXIT_BLOCK} are optional.
+@code{NORMAL_MODE} is optional.
@findex NUM_MODES_FOR_MODE_SWITCHING
@item NUM_MODES_FOR_MODE_SWITCHING
represented as numbers 0 .. N - 1. N is used to specify that no mode
switch is needed / supplied.
-@findex MODE_USES_IN_EXIT_BLOCK
-@item MODE_USES_IN_EXIT_BLOCK
-If this macro is defined, it is called for each exit block when mode switching
-optimization is performed. Its return value should be the pattern of an insn,
-or a sequence of insns. It is emitted before the return insn / use insns at
-the end of the exit block.
-
-This is done before insns are examined for their need of any mode switching.
-
@findex MODE_NEEDED
@item MODE_NEEDED (@var{entity}, @var{insn})
@var{entity} is an integer specifying a mode-switched entity. If
NUM_MODES_FOR_MODE_SWITCHING, to denote the mode that @var{entity} must
be switched into prior to the execution of INSN.
-@findex MODE_AT_ENTRY
-@item MODE_AT_ENTRY (@var{entity})
+@findex NORMAL_MODE
+@item NORMAL_MODE (@var{entity})
If this macro is defined, it is evaluated for every @var{entity} that needs
mode switching. It should evaluate to an integer, which is a mode that
-@var{entity} is assumed to be switched to at function entry.
+@var{entity} is assumed to be switched to at function entry and exit.
@findex MODE_PRIORITY_TO_MODE
@item MODE_PRIORITY_TO_MODE (@var{entity}, @var{n})