Functions |
basic_block | label_to_block_fn (struct function *, tree) |
static int | n_occurrences (int, const char *) |
static bool | tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *) |
static bool | check_operand_nalternatives (tree, tree) |
static bool | check_unique_operand_names (tree, tree, tree) |
static char * | resolve_operand_name_1 (char *, tree, tree, tree) |
static void | expand_null_return_1 (void) |
static void | expand_value_return (rtx) |
static void | balance_case_nodes (case_node_ptr *, case_node_ptr) |
static int | node_has_low_bound (case_node_ptr, tree) |
static int | node_has_high_bound (case_node_ptr, tree) |
static int | node_is_bounded (case_node_ptr, tree) |
static void | emit_case_nodes (rtx, case_node_ptr, rtx, int, tree) |
rtx | label_rtx () |
rtx | force_label_rtx () |
void | emit_jump () |
void | expand_computed_goto () |
void | expand_label () |
void | expand_goto () |
static int | n_occurrences () |
static void | expand_asm_loc () |
bool | parse_output_constraint (const char **constraint_p, int operand_num, int ninputs, int noutputs, bool *allows_mem, bool *allows_reg, bool *is_inout) |
bool | parse_input_constraint (const char **constraint_p, int input_num, int ninputs, int noutputs, int ninout, const char *const *constraints, bool *allows_mem, bool *allows_reg) |
static tree | decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees, void *data) |
tree | tree_overlaps_hard_reg_set () |
static bool | tree_conflicts_with_clobbers_p () |
static void | expand_asm_operands (tree string, tree outputs, tree inputs, tree clobbers, tree labels, int vol, location_t locus) |
void | expand_asm_stmt () |
static bool | check_operand_nalternatives () |
static bool | check_unique_operand_names () |
tree | resolve_asm_operand_names () |
static char * | resolve_operand_name_1 () |
void | expand_null_return () |
void | expand_naked_return () |
static void | expand_value_return () |
void | expand_return () |
rtx | expand_stack_save () |
void | expand_stack_restore () |
static void | do_jump_if_equal (enum machine_mode mode, rtx op0, rtx op1, rtx label, int unsignedp, int prob) |
static struct case_node * | add_case_node (struct case_node *head, tree low, tree high, tree label, int prob, alloc_pool case_node_pool) |
static void | dump_case_nodes (FILE *f, struct case_node *root, int indent_step, int indent_level) |
static unsigned int | case_values_threshold () |
static bool | expand_switch_as_decision_tree_p (tree range, unsigned int uniq, unsigned int count) |
static void | emit_case_decision_tree (tree index_expr, tree index_type, struct case_node *case_list, rtx default_label, int default_prob) |
static int | get_outgoing_edge_probs () |
static int | conditional_probability () |
static void | emit_case_dispatch_table (tree index_expr, tree index_type, struct case_node *case_list, rtx default_label, tree minval, tree maxval, tree range, basic_block stmt_bb) |
static void | reset_out_edges_aux () |
static void | compute_cases_per_edge () |
void | expand_case () |
void | expand_sjlj_dispatch_table (rtx dispatch_index, vec< tree > dispatch_table) |
static void | balance_case_nodes () |
static int | node_has_low_bound () |
static int | node_has_high_bound () |
static int | node_is_bounded () |
Do the insertion of a case label into case_list. The labels are
fed to us in descending order from the sorted vector of case labels used
in the tree part of the middle end. So the list we construct is
sorted in ascending order.
LABEL is the case label to be inserted. LOW and HIGH are the bounds
against which the index is compared to jump to LABEL and PROB is the
estimated probability LABEL is reached from the switch statement.
References case_node::code_label, case_node::high, case_node::left, case_node::low, case_node::parent, pool_alloc(), case_node::prob, prob, case_node::right, and case_node::subtree_prob.
Referenced by expand_case(), and expand_sjlj_dispatch_table().
static void balance_case_nodes |
( |
| ) |
|
|
static |
static void emit_case_decision_tree |
( |
tree |
index_expr, |
|
|
tree |
index_type, |
|
|
struct case_node * |
case_list, |
|
|
rtx |
default_label, |
|
|
int |
default_prob |
|
) |
| |
|
static |
Generate a decision tree, switching on INDEX_EXPR and jumping to
one of the labels in CASE_LIST or to the DEFAULT_LABEL.
DEFAULT_PROB is the estimated probability that it jumps to
DEFAULT_LABEL.
We generate a binary decision tree to select the appropriate target
code. This is done as follows:
If the index is a short or char that we do not have
an insn to handle comparisons directly, convert it to
a full integer now, rather than letting each comparison
generate the conversion.
Load the index into a register.
The list of cases is rearranged into a binary tree,
nearly optimal assuming equal probability for each case.
The tree is transformed into RTL, eliminating redundant
test conditions at the same time.
If program flow could reach the end of the decision tree
an unconditional jump to the default code is emitted.
The above process is unaware of the CFG. The caller has to fix up
the CFG itself. This is done in cfgexpand.c.
References balance_case_nodes(), ceil_log2(), convert_to_mode(), copy_to_reg(), do_pending_stack_adjust(), dump_case_nodes(), dump_file, dump_flags, emit_case_nodes(), emit_jump(), expand_normal(), have_insn_for(), and set_reg_attrs_for_decl_rtl().
Referenced by expand_case().
Generate a dispatch tabler, switching on INDEX_EXPR and jumping to
one of the labels in CASE_LIST or to the DEFAULT_LABEL.
MINVAL, MAXVAL, and RANGE are the extrema and range of the case
labels in CASE_LIST. STMT_BB is the basic block containing the statement.
First, a jump insn is emitted. First we try "casesi". If that
fails, try "tablejump". A target *must* have one of them (or both).
Then, a table with the target labels is emitted.
The process is unaware of the CFG. The caller has to fix up
the CFG itself. This is done in cfgexpand.c.
References build_int_cst(), case_node::code_label, compare_tree_int(), conditional_probability(), emit_barrier(), emit_jump_table_data(), emit_label(), gen_label_rtx(), gen_rtvec_v(), get_outgoing_edge_probs(), case_node::high, HOST_WIDE_INT, label_rtx(), case_node::low, memset(), optimize_insn_for_speed_p(), edge_def::probability, case_node::right, basic_block_def::succs, tree_low_cst(), try_casesi(), and try_tablejump().
Referenced by expand_case(), and expand_sjlj_dispatch_table().
static void emit_case_nodes |
( |
rtx |
index, |
|
|
case_node_ptr |
node, |
|
|
rtx |
default_label, |
|
|
int |
default_prob, |
|
|
tree |
index_type |
|
) |
| |
|
static |
Emit step-by-step code to select a case for the value of INDEX.
The thus generated decision tree follows the form of the
case-node binary tree NODE, whose nodes represent test conditions.
INDEX_TYPE is the type of the index of the switch.
Care is taken to prune redundant tests from the decision tree
by detecting any boundary conditions already checked by
emitted rtx. (See node_has_high_bound, node_has_low_bound
and node_is_bounded, above.)
Where the test conditions can be shown to be redundant we emit
an unconditional jump to the target code. As a further
optimization, the subordinates of a tree node are examined to
check for bounded nodes. In this case conditional and/or
unconditional jumps as a result of the boundary check for the
current node are arranged to target the subordinates associated
code for out of bound conditions on the current node.
We can assume that when control reaches the code generated here,
the index value has already been compared with the parents
of this node, and determined to be on the same side of each parent
as this node is. Thus, if this node tests for the value 51,
and a parent tested for 52, we don't need to consider
the possibility of a value greater than 51. If another parent
tests for the value 50, then this node need not test anything.
References case_node::code_label, conditional_probability(), convert_modes(), curr_insn_location(), do_jump_if_equal(), emit_cmp_and_jump_insns(), emit_jump(), expand_expr(), expand_label(), EXPAND_NORMAL, expand_normal(), expand_simple_binop(), case_node::high, label_rtx(), case_node::left, case_node::low, node_has_high_bound(), node_has_low_bound(), node_is_bounded(), OPTAB_WIDEN, case_node::prob, prob, case_node::right, case_node::subtree_prob, tree_int_cst_equal(), lang_hooks_for_types::type_for_mode, and lang_hooks::types.
Referenced by emit_case_decision_tree().
Generate RTL for an asm statement with arguments.
STRING is the instruction template.
OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
Each output or input has an expression in the TREE_VALUE and
a tree list in TREE_PURPOSE which in turn contains a constraint
name in TREE_VALUE (or NULL_TREE) and a constraint string
in TREE_PURPOSE.
CLOBBERS is a list of STRING_CST nodes each naming a hard register
that is clobbered by this insn.
Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.
Some elements of OUTPUTS may be replaced with trees representing temporary
values. The caller should copy those temporary values to the originally
specified lvalues.
VOL nonzero means the insn is volatile; don't optimize it.
References asm_operand_ok(), assign_temp(), buffer, check_operand_nalternatives(), constraints, decode_reg_name_and_count(), do_pending_stack_adjust(), emit_insn(), emit_jump_insn(), emit_move_insn(), empty_string, error(), expand_expr(), EXPAND_INITIALIZER, EXPAND_MEMORY, EXPAND_NORMAL, EXPAND_WRITE, force_reg(), free_temp_slots(), gen_reg_rtx(), gen_rtx_MEM(), gen_rtx_REG(), generating_concat_p, internal_error(), label_rtx(), list_length(), make_tree(), mark_addressable(), parse_input_constraint(), parse_output_constraint(), reg_overlap_mentioned_p(), resolve_asm_operand_names(), rtvec_alloc(), set_reg_attrs_for_decl_rtl(), targetm, tree_conflicts_with_clobbers_p(), type(), validize_mem(), and warning().
Referenced by expand_asm_stmt().
Handle goto statements and the labels that they can go to.
Specify the location in the RTL code of a label LABEL,
which is a LABEL_DECL tree node.
This is used for the kind of label that the user can jump to with a
goto statement, and for alternatives of a switch or case statement.
RTL labels generated for loops and conditionals don't go through here;
they are generated directly at the RTL level, by other functions below.
Note that this has nothing to do with defining label *names*.
Languages vary in how they do that and what that even means.
References do_pending_stack_adjust(), emit_label(), expand_builtin_setjmp_receiver(), label_rtx(), and maybe_set_first_label_num().
Referenced by emit_case_nodes(), and expand_gimple_stmt_1().
void expand_sjlj_dispatch_table |
( |
rtx |
dispatch_index, |
|
|
vec< tree > |
dispatch_table |
|
) |
| |
Expand the dispatch to a short decrement chain if there are few cases
to dispatch to. Likewise if neither casesi nor tablejump is available,
or if flag_jump_tables is set. Otherwise, expand as a casesi or a
tablejump. The index mode is always the mode of integer_type_node.
Trap if no case matches the index.
DISPATCH_INDEX is the index expression to switch on. It should be a
memory or register operand.
DISPATCH_TABLE is a set of case labels. The set should be sorted in
ascending order, be contiguous, starting with value 0, and contain only
single-valued case labels.
References add_case_node(), build_int_cst(), copy_to_mode_reg(), create_alloc_pool(), do_jump_if_equal(), do_pending_stack_adjust(), emit_case_dispatch_table(), emit_label(), expand_builtin_trap(), force_expand_binop(), free_alloc_pool(), free_temp_slots(), gen_label_rtx(), get_last_insn(), label_rtx(), case_node::low, make_tree(), OPTAB_DIRECT, and reorder_insns().
Referenced by sjlj_emit_dispatch_table().
static bool expand_switch_as_decision_tree_p |
( |
tree |
range, |
|
|
unsigned int |
uniq, |
|
|
unsigned int |
count |
|
) |
| |
|
static |
bool parse_output_constraint |
( |
const char ** |
constraint_p, |
|
|
int |
operand_num, |
|
|
int |
ninputs, |
|
|
int |
noutputs, |
|
|
bool * |
allows_mem, |
|
|
bool * |
allows_reg, |
|
|
bool * |
is_inout |
|
) |
| |
Parse the output constraint pointed to by *CONSTRAINT_P. It is the
OPERAND_NUMth output operand, indexed from zero. There are NINPUTS
inputs and NOUTPUTS outputs to this extended-asm. Upon return,
*ALLOWS_MEM will be TRUE iff the constraint allows the use of a
memory operand. Similarly, *ALLOWS_REG will be TRUE iff the
constraint allows the use of a register operand. And, *IS_INOUT
will be true if the operand is read-write, i.e., if it is used as
an input as well as an output. If *CONSTRAINT_P is not in
canonical form, it will be made canonical. (Note that `+' will be
replaced with `=' as part of this process.)
Returns TRUE if all went well; FALSE if an error occurred.
References error(), strlen(), and warning().
Referenced by expand_asm_operands(), find_func_aliases(), get_asm_expr_operands(), gimple_regimplify_operands(), gimplify_asm_expr(), walk_gimple_asm(), and walk_stmt_load_store_addr_ops().