+2009-10-27 Wei Guozhi <carrot@google.com>
+
+ PR target/41705
+ * target.h (have_conditional_execution): Add a new target hook function.
+ * target-def.h (TARGET_HAVE_CONDITIONAL_EXECUTION): Likewise.
+ * targhooks.h (default_have_conditional_execution): Likewise.
+ * targhooks.c (default_have_conditional_execution): Likewise.
+ * doc/tm.texi (TARGET_HAVE_CONDITIONAL_EXECUTION): Document it.
+ * config/arm/arm.c (TARGET_HAVE_CONDITIONAL_EXECUTION): Define it.
+ (arm_have_conditional_execution): New function.
+ * ifcvt.c (noce_process_if_block, find_if_header,
+ cond_exec_find_if_block, dead_or_predicable): Change the usage of macro
+ HAVE_conditional_execution to a target hook call.
+ * recog.c (peephole2_optimize): Likewise.
+ * sched-rgn.c (add_branch_dependences): Likewise.
+ * final.c (asm_insn_count, final_scan_insn): Likewise.
+ * bb-reorder.c (HAVE_conditional_execution): Remove it.
+
2009-10-26 Ben Elliston <bje@au.ibm.com>
Michael Meissner <meissner@linux.vnet.ibm.com>
Ulrich Weigand <uweigand@de.ibm.com>
#include "tree-pass.h"
#include "df.h"
-#ifndef HAVE_conditional_execution
-#define HAVE_conditional_execution 0
-#endif
-
/* The number of rounds. In most cases there will only be 4 rounds, but
when partitioning hot and cold basic blocks into separate sections of
the .o file there will be an extra round.*/
TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */
}
};
-
-
static void arm_internal_label (FILE *, const char *, unsigned long);
static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
tree);
+static bool arm_have_conditional_execution (void);
static bool arm_rtx_costs_1 (rtx, enum rtx_code, int*, bool);
static bool arm_size_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *);
static bool arm_slowmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
#define TARGET_HAVE_TLS true
#endif
+#undef TARGET_HAVE_CONDITIONAL_EXECUTION
+#define TARGET_HAVE_CONDITIONAL_EXECUTION arm_have_conditional_execution
+
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM arm_cannot_force_const_mem
|| (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()));
}
+/* Only thumb1 can't support conditional execution, so return true if
+ the target is not thumb1. */
+static bool
+arm_have_conditional_execution (void)
+{
+ return !TARGET_THUMB1;
+}
+
#include "gt-arm.h"
to reserve space for caller-saved target registers.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_HAVE_CONDITIONAL_EXECUTION (void)
+This target hook returns true if the target supports conditional execution.
+This target hook is required only when the target has several different
+modes and they have different conditional execution capability, such as ARM.
+@end deftypefn
+
@defmac POWI_MAX_MULTS
If defined, this macro is interpreted as a signed integer C expression
that specifies the maximum number of floating point multiplications
static int dialect_number;
#endif
-#ifdef HAVE_conditional_execution
/* Nonnull if the insn currently being emitted was a COND_EXEC pattern. */
rtx current_insn_predicate;
-#endif
#ifdef HAVE_ATTR_length
static int asm_insn_count (rtx);
const char *templ;
bool is_stmt;
-#ifdef HAVE_conditional_execution
/* Reset this early so it is correct for ASM statements. */
current_insn_predicate = NULL_RTX;
-#endif
+
/* An INSN, JUMP_INSN or CALL_INSN.
First check for special kinds that recog doesn't recognize. */
FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
#endif
-#ifdef HAVE_conditional_execution
- if (GET_CODE (PATTERN (insn)) == COND_EXEC)
+ if (targetm.have_conditional_execution ()
+ && GET_CODE (PATTERN (insn)) == COND_EXEC)
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
-#endif
#ifdef HAVE_cc0
cc_prev_status = cc_status;
#include "vecprim.h"
#include "dbgcnt.h"
-#ifndef HAVE_conditional_execution
-#define HAVE_conditional_execution 0
-#endif
#ifndef HAVE_conditional_move
#define HAVE_conditional_move 0
#endif
if (HAVE_conditional_move
&& noce_try_cmove (if_info))
goto success;
- if (! HAVE_conditional_execution)
+ if (! targetm.have_conditional_execution ())
{
if (noce_try_store_flag_constants (if_info))
goto success;
&& noce_find_if_block (test_bb, then_edge, else_edge, pass))
goto success;
- if (HAVE_conditional_execution && reload_completed
+ if (targetm.have_conditional_execution () && reload_completed
&& cond_exec_find_if_block (&ce_info))
goto success;
goto success;
if (dom_info_state (CDI_POST_DOMINATORS) >= DOM_NO_FAST_QUERY
- && (! HAVE_conditional_execution || reload_completed))
+ && (! targetm.have_conditional_execution () || reload_completed))
{
if (find_if_case_1 (test_bb, then_edge, else_edge))
goto success;
/* We only ever should get here after reload,
and only if we have conditional execution. */
- gcc_assert (HAVE_conditional_execution && reload_completed);
+ gcc_assert (targetm.have_conditional_execution () && reload_completed);
/* Discover if any fall through predecessors of the current test basic block
were && tests (which jump to the else block) or || tests (which jump to
/* Disable handling dead code by conditional execution if the machine needs
to do anything funny with the tests, etc. */
#ifndef IFCVT_MODIFY_TESTS
- if (HAVE_conditional_execution)
+ if (targetm.have_conditional_execution ())
{
/* In the conditional execution case, we have things easy. We know
the condition is reversible. We don't have to check life info
do_cleanup_cfg |= purge_dead_edges (bb);
}
-#ifdef HAVE_conditional_execution
- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
- peep2_insn_data[i].insn = NULL_RTX;
- peep2_insn_data[peep2_current].insn = PEEP2_EOB;
- peep2_current_count = 0;
-#else
- /* Back up lifetime information past the end of the
- newly created sequence. */
- if (++i >= MAX_INSNS_PER_PEEP2 + 1)
- i = 0;
- bitmap_copy (live, peep2_insn_data[i].live_before);
-
- /* Update life information for the new sequence. */
- x = attempt;
- do
+ if (targetm.have_conditional_execution ())
{
- if (INSN_P (x))
+ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+ peep2_insn_data[i].insn = NULL_RTX;
+ peep2_insn_data[peep2_current].insn = PEEP2_EOB;
+ peep2_current_count = 0;
+ }
+ else
+ {
+ /* Back up lifetime information past the end of the
+ newly created sequence. */
+ if (++i >= MAX_INSNS_PER_PEEP2 + 1)
+ i = 0;
+ bitmap_copy (live, peep2_insn_data[i].live_before);
+
+ /* Update life information for the new sequence. */
+ x = attempt;
+ do
{
- if (--i < 0)
- i = MAX_INSNS_PER_PEEP2;
- if (peep2_current_count < MAX_INSNS_PER_PEEP2
- && peep2_insn_data[i].insn == NULL_RTX)
- peep2_current_count++;
- peep2_insn_data[i].insn = x;
- df_insn_rescan (x);
- df_simulate_one_insn_backwards (bb, x, live);
- bitmap_copy (peep2_insn_data[i].live_before, live);
+ if (INSN_P (x))
+ {
+ if (--i < 0)
+ i = MAX_INSNS_PER_PEEP2;
+ if (peep2_current_count < MAX_INSNS_PER_PEEP2
+ && peep2_insn_data[i].insn == NULL_RTX)
+ peep2_current_count++;
+ peep2_insn_data[i].insn = x;
+ df_insn_rescan (x);
+ df_simulate_one_insn_backwards (bb, x, live);
+ bitmap_copy (peep2_insn_data[i].live_before,
+ live);
+ }
+ x = PREV_INSN (x);
}
- x = PREV_INSN (x);
- }
- while (x != prev);
+ while (x != prev);
- peep2_current = i;
-#endif
+ peep2_current = i;
+ }
/* If we generated a jump instruction, it won't have
JUMP_LABEL set. Recompute after we're done. */
add_dependence (last, insn, REG_DEP_ANTI);
}
-#ifdef HAVE_conditional_execution
+ if (!targetm.have_conditional_execution ())
+ return;
+
/* Finally, if the block ends in a jump, and we are doing intra-block
scheduling, make sure that the branch depends on any COND_EXEC insns
inside the block to avoid moving the COND_EXECs past the branch insn.
if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == COND_EXEC)
add_dependence (tail, insn, REG_DEP_ANTI);
}
-#endif
}
/* Data structures for the computation of data dependences in a regions. We
TODO_ggc_collect /* todo_flags_finish */
}
};
-
#define TARGET_BRANCH_TARGET_REGISTER_CLASS \
default_branch_target_register_class
#define TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED hook_bool_bool_false
+#define TARGET_HAVE_CONDITIONAL_EXECUTION default_have_conditional_execution
#define TARGET_CANNOT_FORCE_CONST_MEM hook_bool_rtx_false
#define TARGET_CANNOT_COPY_INSN_P NULL
#define TARGET_COMMUTATIVE_P hook_bool_const_rtx_commutative_p
TARGET_CANNOT_MODIFY_JUMPS_P, \
TARGET_BRANCH_TARGET_REGISTER_CLASS, \
TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED, \
+ TARGET_HAVE_CONDITIONAL_EXECUTION, \
TARGET_CANNOT_FORCE_CONST_MEM, \
TARGET_CANNOT_COPY_INSN_P, \
TARGET_COMMUTATIVE_P, \
already been generated. */
bool (* branch_target_register_callee_saved) (bool after_pe_gen);
+ /* Return true if the target supports conditional execution. */
+ bool (* have_conditional_execution) (void);
+
/* True if the constant X cannot be placed in the constant pool. */
bool (* cannot_force_const_mem) (rtx);
return (HAVE_casesi ? 4 : 5);
}
+bool
+default_have_conditional_execution (void)
+{
+#ifdef HAVE_conditional_execution
+ return HAVE_conditional_execution;
+#else
+ return false;
+#endif
+}
+
#include "gt-targhooks.h"
extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
extern rtx default_addr_space_convert (rtx, tree, tree);
extern unsigned int default_case_values_threshold (void);
+extern bool default_have_conditional_execution (void);