/* Expands front end tree to back end RTL for GCC
- Copyright (C) 1987-2015 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
-#include "hard-reg-set.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
#include "tree.h"
+#include "gimple.h"
+#include "predict.h"
+#include "alloc-pool.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "optabs.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "pretty-print.h"
+#include "diagnostic-core.h"
+
#include "fold-const.h"
#include "varasm.h"
#include "stor-layout.h"
-#include "tm_p.h"
-#include "flags.h"
-#include "except.h"
-#include "function.h"
-#include "insn-config.h"
-#include "hashtab.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
-#include "expmed.h"
#include "dojump.h"
#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
#include "stmt.h"
#include "expr.h"
-#include "libfuncs.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "output.h"
#include "langhooks.h"
-#include "predict.h"
-#include "insn-codes.h"
-#include "optabs.h"
-#include "target.h"
#include "cfganal.h"
-#include "basic-block.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
-#include "gimple-expr.h"
-#include "is-a.h"
-#include "gimple.h"
-#include "regs.h"
-#include "alloc-pool.h"
-#include "pretty-print.h"
#include "params.h"
#include "dumpfile.h"
#include "builtins.h"
int subtree_prob;
};
-typedef struct case_node case_node;
typedef struct case_node *case_node_ptr;
extern basic_block label_to_block_fn (struct function *, tree);
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);
+static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *, int, tree);
\f
/* Return the rtx-label that corresponds to a LABEL_DECL,
creating it if necessary. */
-rtx
+rtx_insn *
label_rtx (tree label)
{
gcc_assert (TREE_CODE (label) == LABEL_DECL);
LABEL_PRESERVE_P (r) = 1;
}
- return DECL_RTL (label);
+ return as_a <rtx_insn *> (DECL_RTL (label));
}
/* As above, but also put it on the forced-reference list of the
function that contains it. */
-rtx
+rtx_insn *
force_label_rtx (tree label)
{
- rtx_insn *ref = as_a <rtx_insn *> (label_rtx (label));
+ rtx_insn *ref = label_rtx (label);
tree function = decl_function_context (label);
gcc_assert (function);
- forced_labels = gen_rtx_INSN_LIST (VOIDmode, ref, forced_labels);
+ vec_safe_push (forced_labels, ref);
return ref;
}
+/* As label_rtx, but ensures (in check build), that returned value is
+ an existing label (i.e. rtx with code CODE_LABEL). */
+rtx_code_label *
+jump_target_rtx (tree label)
+{
+ return as_a <rtx_code_label *> (label_rtx (label));
+}
+
/* Add an unconditional jump to LABEL as the next sequential instruction. */
void
emit_jump (rtx label)
{
do_pending_stack_adjust ();
- emit_jump_insn (gen_jump (label));
+ emit_jump_insn (targetm.gen_jump (label));
emit_barrier ();
}
\f
void
expand_label (tree label)
{
- rtx_insn *label_r = as_a <rtx_insn *> (label_rtx (label));
+ rtx_code_label *label_r = jump_target_rtx (label);
do_pending_stack_adjust ();
emit_label (label_r);
}
if (FORCED_LABEL (label))
- forced_labels = gen_rtx_INSN_LIST (VOIDmode, label_r, forced_labels);
+ vec_safe_push<rtx_insn *> (forced_labels, label_r);
if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
maybe_set_first_label_num (label_r);
if (reg_class_for_constraint (cn) != NO_REGS
|| insn_extra_address_constraint (cn))
*allows_reg = true;
- else if (insn_extra_memory_constraint (cn))
+ else if (insn_extra_memory_constraint (cn)
+ || insn_extra_special_memory_constraint (cn))
*allows_mem = true;
else
insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
tree decl = *declp;
const HARD_REG_SET *const regs = (const HARD_REG_SET *) data;
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
if (DECL_HARD_REGISTER (decl)
&& REG_P (DECL_RTL (decl))
void
expand_naked_return (void)
{
- rtx end_label;
+ rtx_code_label *end_label;
clear_pending_stack_adjust ();
do_pending_stack_adjust ();
/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. PROB
is the probability of jumping to LABEL. */
static void
-do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx label,
+do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label,
int unsignedp, int prob)
{
gcc_assert (prob <= REG_BR_PROB_BASE);
do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
- NULL_RTX, NULL_RTX, label, prob);
+ NULL_RTX, NULL, label, prob);
}
\f
/* Do the insertion of a case label into case_list. The labels are
static struct case_node *
add_case_node (struct case_node *head, tree low, tree high,
- tree label, int prob, alloc_pool case_node_pool)
+ tree label, int prob,
+ object_allocator<case_node> &case_node_pool)
{
struct case_node *r;
gcc_checking_assert (high && (TREE_TYPE (low) == TREE_TYPE (high)));
/* Add this label to the chain. */
- r = (struct case_node *) pool_alloc (case_node_pool);
+ r = case_node_pool.allocate ();
r->low = low;
r->high = high;
r->code_label = label;
dump_case_nodes (f, root->right, indent_step, indent_level);
}
\f
-#ifndef HAVE_casesi
-#define HAVE_casesi 0
-#endif
-
-#ifndef HAVE_tablejump
-#define HAVE_tablejump 0
-#endif
-
/* Return the smallest number of different values for which it is best to use a
jump-table instead of a tree of conditional branches. */
/* If neither casesi or tablejump is available, or flag_jump_tables
over-ruled us, we really have no choice. */
- if (!HAVE_casesi && !HAVE_tablejump)
+ if (!targetm.have_casesi () && !targetm.have_tablejump ())
return true;
if (!flag_jump_tables)
return true;
static void
emit_case_decision_tree (tree index_expr, tree index_type,
- struct case_node *case_list, rtx default_label,
- int default_prob)
+ case_node_ptr case_list, rtx_code_label *default_label,
+ int default_prob)
{
rtx index = expand_normal (index_expr);
{
index = copy_to_reg (index);
if (TREE_CODE (index_expr) == SSA_NAME)
- set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (index_expr), index);
+ set_reg_attrs_for_decl_rtl (index_expr, index);
}
balance_case_nodes (&case_list, NULL);
int i, ncases;
struct case_node *n;
rtx *labelvec;
- rtx fallback_label = label_rtx (case_list->code_label);
+ rtx_insn *fallback_label = label_rtx (case_list->code_label);
rtx_code_label *table_label = gen_label_rtx ();
bool has_gaps = false;
edge default_edge = stmt_bb ? EDGE_SUCC (stmt_bb, 0) : NULL;
expand_case (gswitch *stmt)
{
tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
- rtx default_label = NULL_RTX;
+ rtx_code_label *default_label = NULL;
unsigned int count, uniq;
int i;
int ncases = gimple_switch_num_labels (stmt);
struct case_node *case_list = 0;
/* A pool for case nodes. */
- alloc_pool case_node_pool;
+ object_allocator<case_node> case_node_pool ("struct case_node pool");
/* An ERROR_MARK occurs for various reasons including invalid data type.
??? Can this still happen, with GIMPLE and all? */
expressions being INTEGER_CST. */
gcc_assert (TREE_CODE (index_expr) != INTEGER_CST);
- case_node_pool = create_alloc_pool ("struct case_node pool",
- sizeof (struct case_node),
- 100);
do_pending_stack_adjust ();
/* Find the default case target label. */
- default_label = label_rtx (CASE_LABEL (gimple_switch_default_label (stmt)));
+ default_label = jump_target_rtx
+ (CASE_LABEL (gimple_switch_default_label (stmt)));
edge default_edge = EDGE_SUCC (bb, 0);
int default_prob = default_edge->probability;
reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case);
free_temp_slots ();
- free_alloc_pool (case_node_pool);
}
/* Expand the dispatch to a short decrement chain if there are few cases
of expanding as a decision tree or dispatch table vs. the "new
way" with decrement chain or dispatch table. */
if (dispatch_table.length () <= 5
- || (!HAVE_casesi && !HAVE_tablejump)
+ || (!targetm.have_casesi () && !targetm.have_tablejump ())
|| !flag_jump_tables)
{
/* Expand the dispatch as a decrement chain:
for (int i = 0; i < ncases; i++)
{
tree elt = dispatch_table[i];
- rtx lab = label_rtx (CASE_LABEL (elt));
+ rtx_code_label *lab = jump_target_rtx (CASE_LABEL (elt));
do_jump_if_equal (index_mode, index, zero, lab, 0, -1);
force_expand_binop (index_mode, sub_optab,
index, CONST1_RTX (index_mode),
{
/* Similar to expand_case, but much simpler. */
struct case_node *case_list = 0;
- alloc_pool case_node_pool = create_alloc_pool ("struct sjlj_case pool",
- sizeof (struct case_node),
- ncases);
+ object_allocator<case_node> case_node_pool ("struct sjlj_case pool");
tree index_expr = make_tree (index_type, dispatch_index);
tree minval = build_int_cst (index_type, 0);
tree maxval = CASE_LOW (dispatch_table.last ());
minval, maxval, range,
BLOCK_FOR_INSN (before_case));
emit_label (default_label);
- free_alloc_pool (case_node_pool);
}
/* Dispatching something not handled? Trap! */
tests for the value 50, then this node need not test anything. */
static void
-emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
+emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
int default_prob, tree index_type)
{
/* If INDEX has an unsigned type, we must make unsigned branches. */
convert_modes (mode, imode,
expand_normal (node->low),
unsignedp),
- label_rtx (node->code_label), unsignedp, probability);
+ jump_target_rtx (node->code_label),
+ unsignedp, probability);
/* Since this case is taken at this point, reduce its weight from
subtree_weight. */
subtree_prob -= prob;
LT, NULL_RTX, mode, unsignedp,
label_rtx (node->left->code_label),
probability);
- emit_case_nodes (index, node->right, default_label, default_prob, index_type);
+ emit_case_nodes (index, node->right, default_label, default_prob,
+ index_type);
}
/* If both children are single-valued cases with no
convert_modes (mode, imode,
expand_normal (node->right->low),
unsignedp),
- label_rtx (node->right->code_label),
+ jump_target_rtx (node->right->code_label),
unsignedp, probability);
/* See if the value matches what the left hand side
convert_modes (mode, imode,
expand_normal (node->left->low),
unsignedp),
- label_rtx (node->left->code_label),
+ jump_target_rtx (node->left->code_label),
unsignedp, probability);
}
(mode, imode,
expand_normal (node->right->low),
unsignedp),
- label_rtx (node->right->code_label), unsignedp, probability);
+ jump_target_rtx (node->right->code_label),
+ unsignedp, probability);
}
}
(mode, imode,
expand_normal (node->left->low),
unsignedp),
- label_rtx (node->left->code_label), unsignedp, probability);
+ jump_target_rtx (node->left->code_label),
+ unsignedp, probability);
}
}
}
mode, 1, default_label, probability);
}
- emit_jump (label_rtx (node->code_label));
+ emit_jump (jump_target_rtx (node->code_label));
}
}
}