/* Gimple IR support functions.
- Copyright (C) 2007-2014 Free Software Foundation, Inc.
+ Copyright (C) 2007-2015 Free Software Foundation, Inc.
Contributed by Aldy Hernandez <aldyh@redhat.com>
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "target.h"
+#include "backend.h"
#include "tree.h"
+#include "gimple.h"
+#include "hard-reg-set.h"
+#include "ssa.h"
+#include "target.h"
+#include "alias.h"
+#include "fold-const.h"
#include "calls.h"
#include "stmt.h"
#include "stor-layout.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "tree-eh.h"
-#include "gimple-expr.h"
-#include "is-a.h"
-#include "gimple.h"
#include "gimple-iterator.h"
#include "gimple-walk.h"
-#include "gimple.h"
#include "gimplify.h"
#include "diagnostic.h"
#include "value-prof.h"
#include "alias.h"
#include "demangle.h"
#include "langhooks.h"
-#include "bitmap.h"
+#include "cgraph.h"
/* All the tuples have their operand vector (if present) at the very bottom
"everything else"
};
+/* Static gimple tuple members. */
+const enum gimple_code gassign::code_;
+const enum gimple_code gcall::code_;
+const enum gimple_code gcond::code_;
+
+
/* Gimple tuple constructors.
Note: Any constructor taking a ``gimple_seq'' as a parameter, can
be passed a NULL to start with an empty sequence. */
/* Build a GIMPLE_RETURN statement returning RETVAL. */
-gimple
+greturn *
gimple_build_return (tree retval)
{
- gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1);
+ greturn *s
+ = as_a <greturn *> (gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK,
+ 2));
if (retval)
gimple_return_set_retval (s, retval);
return s;
/* Reset alias information on call S. */
void
-gimple_call_reset_alias_info (gimple s)
+gimple_call_reset_alias_info (gcall *s)
{
if (gimple_call_flags (s) & ECF_CONST)
memset (gimple_call_use_set (s), 0, sizeof (struct pt_solution));
components of a GIMPLE_CALL statement to function FN with NARGS
arguments. */
-static inline gimple
+static inline gcall *
gimple_build_call_1 (tree fn, unsigned nargs)
{
- gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
+ gcall *s
+ = as_a <gcall *> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
+ nargs + 3));
if (TREE_CODE (fn) == FUNCTION_DECL)
fn = build_fold_addr_expr (fn);
gimple_set_op (s, 1, fn);
/* Build a GIMPLE_CALL statement to function FN with the arguments
specified in vector ARGS. */
-gimple
+gcall *
gimple_build_call_vec (tree fn, vec<tree> args)
{
unsigned i;
unsigned nargs = args.length ();
- gimple call = gimple_build_call_1 (fn, nargs);
+ gcall *call = gimple_build_call_1 (fn, nargs);
for (i = 0; i < nargs; i++)
gimple_call_set_arg (call, i, args[i]);
/* Build a GIMPLE_CALL statement to function FN. NARGS is the number of
arguments. The ... are the arguments. */
-gimple
+gcall *
gimple_build_call (tree fn, unsigned nargs, ...)
{
va_list ap;
- gimple call;
+ gcall *call;
unsigned i;
gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
/* Build a GIMPLE_CALL statement to function FN. NARGS is the number of
arguments. AP contains the arguments. */
-gimple
+gcall *
gimple_build_call_valist (tree fn, unsigned nargs, va_list ap)
{
- gimple call;
+ gcall *call;
unsigned i;
gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
Build the basic components of a GIMPLE_CALL statement to internal
function FN with NARGS arguments. */
-static inline gimple
+static inline gcall *
gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
{
- gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
+ gcall *s
+ = as_a <gcall *> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
+ nargs + 3));
s->subcode |= GF_CALL_INTERNAL;
gimple_call_set_internal_fn (s, fn);
gimple_call_reset_alias_info (s);
/* Build a GIMPLE_CALL statement to internal function FN. NARGS is
the number of arguments. The ... are the arguments. */
-gimple
+gcall *
gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
{
va_list ap;
- gimple call;
+ gcall *call;
unsigned i;
call = gimple_build_call_internal_1 (fn, nargs);
/* Build a GIMPLE_CALL statement to internal function FN with the arguments
specified in vector ARGS. */
-gimple
+gcall *
gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
{
unsigned i, nargs;
- gimple call;
+ gcall *call;
nargs = args.length ();
call = gimple_build_call_internal_1 (fn, nargs);
assumed to be in GIMPLE form already. Minimal checking is done of
this fact. */
-gimple
+gcall *
gimple_build_call_from_tree (tree t)
{
unsigned i, nargs;
- gimple call;
+ gcall *call;
tree fndecl = get_callee_fndecl (t);
gcc_assert (TREE_CODE (t) == CALL_EXPR);
gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
gimple_call_set_nothrow (call, TREE_NOTHROW (t));
gimple_set_no_warning (call, TREE_NO_WARNING (t));
+ gimple_call_set_with_bounds (call, CALL_WITH_BOUNDS_P (t));
return call;
}
LHS of the assignment.
RHS of the assignment which can be unary or binary. */
-gimple
-gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
+gassign *
+gimple_build_assign (tree lhs, tree rhs MEM_STAT_DECL)
{
enum tree_code subcode;
tree op1, op2, op3;
extract_ops_from_tree_1 (rhs, &subcode, &op1, &op2, &op3);
- return gimple_build_assign_with_ops (subcode, lhs, op1, op2, op3
- PASS_MEM_STAT);
+ return gimple_build_assign (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
}
/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
- OP1 and OP2. If OP2 is NULL then SUBCODE must be of class
- GIMPLE_UNARY_RHS or GIMPLE_SINGLE_RHS. */
+ OP1, OP2 and OP3. */
-gimple
-gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
- tree op2, tree op3 MEM_STAT_DECL)
+static inline gassign *
+gimple_build_assign_1 (tree lhs, enum tree_code subcode, tree op1,
+ tree op2, tree op3 MEM_STAT_DECL)
{
unsigned num_ops;
- gimple p;
+ gassign *p;
/* Need 1 operand for LHS and 1 or 2 for the RHS (depending on the
code). */
num_ops = get_gimple_rhs_num_ops (subcode) + 1;
- p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
- PASS_MEM_STAT);
+ p = as_a <gassign *> (
+ gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
+ PASS_MEM_STAT));
gimple_assign_set_lhs (p, lhs);
gimple_assign_set_rhs1 (p, op1);
if (op2)
return p;
}
-gimple
-gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
- tree op2 MEM_STAT_DECL)
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+ OP1, OP2 and OP3. */
+
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
+ tree op2, tree op3 MEM_STAT_DECL)
+{
+ return gimple_build_assign_1 (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
+}
+
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+ OP1 and OP2. */
+
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
+ tree op2 MEM_STAT_DECL)
{
- return gimple_build_assign_with_ops (subcode, lhs, op1, op2, NULL_TREE
- PASS_MEM_STAT);
+ return gimple_build_assign_1 (lhs, subcode, op1, op2, NULL_TREE
+ PASS_MEM_STAT);
+}
+
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operand OP1. */
+
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1 MEM_STAT_DECL)
+{
+ return gimple_build_assign_1 (lhs, subcode, op1, NULL_TREE, NULL_TREE
+ PASS_MEM_STAT);
}
T_LABEL is the label to jump to if the condition is true.
F_LABEL is the label to jump to otherwise. */
-gimple
+gcond *
gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
tree t_label, tree f_label)
{
- gimple p;
+ gcond *p;
gcc_assert (TREE_CODE_CLASS (pred_code) == tcc_comparison);
- p = gimple_build_with_ops (GIMPLE_COND, pred_code, 4);
+ p = as_a <gcond *> (gimple_build_with_ops (GIMPLE_COND, pred_code, 4));
gimple_cond_set_lhs (p, lhs);
gimple_cond_set_rhs (p, rhs);
gimple_cond_set_true_label (p, t_label);
/* Build a GIMPLE_COND statement from the conditional expression tree
COND. T_LABEL and F_LABEL are as in gimple_build_cond. */
-gimple
+gcond *
gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label)
{
enum tree_code code;
boolean expression tree COND. */
void
-gimple_cond_set_condition_from_tree (gimple stmt, tree cond)
+gimple_cond_set_condition_from_tree (gcond *stmt, tree cond)
{
enum tree_code code;
tree lhs, rhs;
/* Build a GIMPLE_LABEL statement for LABEL. */
-gimple
+glabel *
gimple_build_label (tree label)
{
- gimple p = gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1);
+ glabel *p
+ = as_a <glabel *> (gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1));
gimple_label_set_label (p, label);
return p;
}
/* Build a GIMPLE_GOTO statement to label DEST. */
-gimple
+ggoto *
gimple_build_goto (tree dest)
{
- gimple p = gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1);
+ ggoto *p
+ = as_a <ggoto *> (gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1));
gimple_goto_set_dest (p, dest);
return p;
}
VARS are the variables in BODY.
BLOCK is the containing block. */
-gimple
+gbind *
gimple_build_bind (tree vars, gimple_seq body, tree block)
{
- gimple p = gimple_alloc (GIMPLE_BIND, 0);
+ gbind *p = as_a <gbind *> (gimple_alloc (GIMPLE_BIND, 0));
gimple_bind_set_vars (p, vars);
if (body)
gimple_bind_set_body (p, body);
NCLOBBERS is the number of clobbered registers.
*/
-static inline gimple
+static inline gasm *
gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
unsigned nclobbers, unsigned nlabels)
{
- gimple_statement_asm *p;
+ gasm *p;
int size = strlen (string);
/* ASMs with labels cannot have outputs. This should have been
enforced by the front end. */
gcc_assert (nlabels == 0 || noutputs == 0);
- p = as_a <gimple_statement_asm> (
+ p = as_a <gasm *> (
gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
ninputs + noutputs + nclobbers + nlabels));
CLOBBERS is a vector of the clobbered register parameters.
LABELS is a vector of destination labels. */
-gimple
+gasm *
gimple_build_asm_vec (const char *string, vec<tree, va_gc> *inputs,
vec<tree, va_gc> *outputs, vec<tree, va_gc> *clobbers,
vec<tree, va_gc> *labels)
{
- gimple p;
+ gasm *p;
unsigned i;
p = gimple_build_asm_1 (string,
TYPES are the catch types.
HANDLER is the exception handler. */
-gimple
+gcatch *
gimple_build_catch (tree types, gimple_seq handler)
{
- gimple p = gimple_alloc (GIMPLE_CATCH, 0);
+ gcatch *p = as_a <gcatch *> (gimple_alloc (GIMPLE_CATCH, 0));
gimple_catch_set_types (p, types);
if (handler)
gimple_catch_set_handler (p, handler);
TYPES are the filter's types.
FAILURE is the filter's failure action. */
-gimple
+geh_filter *
gimple_build_eh_filter (tree types, gimple_seq failure)
{
- gimple p = gimple_alloc (GIMPLE_EH_FILTER, 0);
+ geh_filter *p = as_a <geh_filter *> (gimple_alloc (GIMPLE_EH_FILTER, 0));
gimple_eh_filter_set_types (p, types);
if (failure)
gimple_eh_filter_set_failure (p, failure);
/* Build a GIMPLE_EH_MUST_NOT_THROW statement. */
-gimple
+geh_mnt *
gimple_build_eh_must_not_throw (tree decl)
{
- gimple p = gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 0);
+ geh_mnt *p = as_a <geh_mnt *> (gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 0));
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
gcc_assert (flags_from_decl_or_type (decl) & ECF_NORETURN);
/* Build a GIMPLE_EH_ELSE statement. */
-gimple
+geh_else *
gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
{
- gimple p = gimple_alloc (GIMPLE_EH_ELSE, 0);
+ geh_else *p = as_a <geh_else *> (gimple_alloc (GIMPLE_EH_ELSE, 0));
gimple_eh_else_set_n_body (p, n_body);
gimple_eh_else_set_e_body (p, e_body);
return p;
KIND is either GIMPLE_TRY_CATCH or GIMPLE_TRY_FINALLY depending on
whether this is a try/catch or a try/finally respectively. */
-gimple_statement_try *
+gtry *
gimple_build_try (gimple_seq eval, gimple_seq cleanup,
enum gimple_try_flags kind)
{
- gimple_statement_try *p;
+ gtry *p;
gcc_assert (kind == GIMPLE_TRY_CATCH || kind == GIMPLE_TRY_FINALLY);
- p = as_a <gimple_statement_try> (gimple_alloc (GIMPLE_TRY, 0));
+ p = as_a <gtry *> (gimple_alloc (GIMPLE_TRY, 0));
gimple_set_subcode (p, kind);
if (eval)
gimple_try_set_eval (p, eval);
/* Build a GIMPLE_RESX statement. */
-gimple
+gresx *
gimple_build_resx (int region)
{
- gimple_statement_resx *p =
- as_a <gimple_statement_resx> (
- gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
+ gresx *p
+ = as_a <gresx *> (gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
p->region = region;
return p;
}
NLABELS is the number of labels in the switch excluding the default.
DEFAULT_LABEL is the default label for the switch statement. */
-gimple
+gswitch *
gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
{
/* nlabels + 1 default label + 1 index. */
gcc_checking_assert (default_label);
- gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
- 1 + 1 + nlabels);
+ gswitch *p = as_a <gswitch *> (gimple_build_with_ops (GIMPLE_SWITCH,
+ ERROR_MARK,
+ 1 + 1 + nlabels));
gimple_switch_set_index (p, index);
gimple_switch_set_default_label (p, default_label);
return p;
DEFAULT_LABEL is the default label
ARGS is a vector of labels excluding the default. */
-gimple
+gswitch *
gimple_build_switch (tree index, tree default_label, vec<tree> args)
{
unsigned i, nlabels = args.length ();
- gimple p = gimple_build_switch_nlabels (nlabels, index, default_label);
+ gswitch *p = gimple_build_switch_nlabels (nlabels, index, default_label);
/* Copy the labels from the vector to the switch statement. */
for (i = 0; i < nlabels; i++)
/* Build a GIMPLE_EH_DISPATCH statement. */
-gimple
+geh_dispatch *
gimple_build_eh_dispatch (int region)
{
- gimple_statement_eh_dispatch *p =
- as_a <gimple_statement_eh_dispatch> (
- gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
+ geh_dispatch *p
+ = as_a <geh_dispatch *> (
+ gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
p->region = region;
return p;
}
VAR is bound to VALUE; block and location are taken from STMT. */
-gimple
+gdebug *
gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
{
- gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
- (unsigned)GIMPLE_DEBUG_BIND, 2
- PASS_MEM_STAT);
-
+ gdebug *p
+ = as_a <gdebug *> (gimple_build_with_ops_stat (GIMPLE_DEBUG,
+ (unsigned)GIMPLE_DEBUG_BIND, 2
+ PASS_MEM_STAT));
gimple_debug_bind_set_var (p, var);
gimple_debug_bind_set_value (p, value);
if (stmt)
VAR is bound to VALUE; block and location are taken from STMT. */
-gimple
+gdebug *
gimple_build_debug_source_bind_stat (tree var, tree value,
gimple stmt MEM_STAT_DECL)
{
- gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
- (unsigned)GIMPLE_DEBUG_SOURCE_BIND, 2
- PASS_MEM_STAT);
+ gdebug *p
+ = as_a <gdebug *> (
+ gimple_build_with_ops_stat (GIMPLE_DEBUG,
+ (unsigned)GIMPLE_DEBUG_SOURCE_BIND, 2
+ PASS_MEM_STAT));
gimple_debug_source_bind_set_var (p, var);
gimple_debug_source_bind_set_value (p, value);
BODY is the sequence of statements for which only one thread can execute.
NAME is optional identifier for this critical block. */
-gimple
+gomp_critical *
gimple_build_omp_critical (gimple_seq body, tree name)
{
- gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0);
+ gomp_critical *p
+ = as_a <gomp_critical *> (gimple_alloc (GIMPLE_OMP_CRITICAL, 0));
gimple_omp_critical_set_name (p, name);
if (body)
gimple_omp_set_body (p, body);
BODY is sequence of statements inside the for loop.
KIND is the `for' variant.
- CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate,
- lastprivate, reductions, ordered, schedule, and nowait.
+ CLAUSES, are any of the construct's clauses.
COLLAPSE is the collapse count.
PRE_BODY is the sequence of statements that are loop invariant. */
-gimple
+gomp_for *
gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
gimple_seq pre_body)
{
- gimple_statement_omp_for *p =
- as_a <gimple_statement_omp_for> (gimple_alloc (GIMPLE_OMP_FOR, 0));
+ gomp_for *p = as_a <gomp_for *> (gimple_alloc (GIMPLE_OMP_FOR, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_for_set_clauses (p, clauses);
gimple_omp_for_set_kind (p, kind);
p->collapse = collapse;
- p->iter = static_cast <struct gimple_omp_for_iter *> (
- ggc_internal_cleared_vec_alloc_stat (sizeof (*p->iter),
- collapse MEM_STAT_INFO));
+ p->iter = ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
if (pre_body)
gimple_omp_for_set_pre_body (p, pre_body);
CHILD_FN is the function created for the parallel threads to execute.
DATA_ARG are the shared data argument(s). */
-gimple
+gomp_parallel *
gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
tree data_arg)
{
- gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL, 0);
+ gomp_parallel *p
+ = as_a <gomp_parallel *> (gimple_alloc (GIMPLE_OMP_PARALLEL, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_parallel_set_clauses (p, clauses);
COPY_FN is the optional function for firstprivate initialization.
ARG_SIZE and ARG_ALIGN are size and alignment of the data block. */
-gimple
+gomp_task *
gimple_build_omp_task (gimple_seq body, tree clauses, tree child_fn,
tree data_arg, tree copy_fn, tree arg_size,
tree arg_align)
{
- gimple p = gimple_alloc (GIMPLE_OMP_TASK, 0);
+ gomp_task *p = as_a <gomp_task *> (gimple_alloc (GIMPLE_OMP_TASK, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_task_set_clauses (p, clauses);
CONTROL_DEF is the definition of the control variable.
CONTROL_USE is the use of the control variable. */
-gimple
+gomp_continue *
gimple_build_omp_continue (tree control_def, tree control_use)
{
- gimple p = gimple_alloc (GIMPLE_OMP_CONTINUE, 0);
+ gomp_continue *p
+ = as_a <gomp_continue *> (gimple_alloc (GIMPLE_OMP_CONTINUE, 0));
gimple_omp_continue_set_control_def (p, control_def);
gimple_omp_continue_set_control_use (p, control_use);
return p;
CLAUSES are any of the OMP sections contsruct's clauses: private,
firstprivate, lastprivate, reduction, and nowait. */
-gimple
+gomp_sections *
gimple_build_omp_sections (gimple_seq body, tree clauses)
{
- gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS, 0);
+ gomp_sections *p
+ = as_a <gomp_sections *> (gimple_alloc (GIMPLE_OMP_SECTIONS, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_sections_set_clauses (p, clauses);
CLAUSES are any of the OMP single construct's clauses: private, firstprivate,
copyprivate, nowait. */
-gimple
+gomp_single *
gimple_build_omp_single (gimple_seq body, tree clauses)
{
- gimple p = gimple_alloc (GIMPLE_OMP_SINGLE, 0);
+ gomp_single *p
+ = as_a <gomp_single *> (gimple_alloc (GIMPLE_OMP_SINGLE, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_single_set_clauses (p, clauses);
/* Build a GIMPLE_OMP_TARGET statement.
BODY is the sequence of statements that will be executed.
- CLAUSES are any of the OMP target construct's clauses. */
+ KIND is the kind of the region.
+ CLAUSES are any of the construct's clauses. */
-gimple
+gomp_target *
gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
{
- gimple p = gimple_alloc (GIMPLE_OMP_TARGET, 0);
+ gomp_target *p
+ = as_a <gomp_target *> (gimple_alloc (GIMPLE_OMP_TARGET, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_target_set_clauses (p, clauses);
BODY is the sequence of statements that will be executed.
CLAUSES are any of the OMP teams construct's clauses. */
-gimple
+gomp_teams *
gimple_build_omp_teams (gimple_seq body, tree clauses)
{
- gimple p = gimple_alloc (GIMPLE_OMP_TEAMS, 0);
+ gomp_teams *p = as_a <gomp_teams *> (gimple_alloc (GIMPLE_OMP_TEAMS, 0));
if (body)
gimple_omp_set_body (p, body);
gimple_omp_teams_set_clauses (p, clauses);
/* Build a GIMPLE_OMP_ATOMIC_LOAD statement. */
-gimple
+gomp_atomic_load *
gimple_build_omp_atomic_load (tree lhs, tree rhs)
{
- gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0);
+ gomp_atomic_load *p
+ = as_a <gomp_atomic_load *> (gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0));
gimple_omp_atomic_load_set_lhs (p, lhs);
gimple_omp_atomic_load_set_rhs (p, rhs);
return p;
VAL is the value we are storing. */
-gimple
+gomp_atomic_store *
gimple_build_omp_atomic_store (tree val)
{
- gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0);
+ gomp_atomic_store *p
+ = as_a <gomp_atomic_store *> (gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0));
gimple_omp_atomic_store_set_val (p, val);
return p;
}
/* Build a GIMPLE_TRANSACTION statement. */
-gimple
+gtransaction *
gimple_build_transaction (gimple_seq body, tree label)
{
- gimple p = gimple_alloc (GIMPLE_TRANSACTION, 0);
+ gtransaction *p
+ = as_a <gtransaction *> (gimple_alloc (GIMPLE_TRANSACTION, 0));
gimple_transaction_set_body (p, body);
gimple_transaction_set_label (p, label);
return p;
}
-/* Build a GIMPLE_PREDICT statement. PREDICT is one of the predictors from
- predict.def, OUTCOME is NOT_TAKEN or TAKEN. */
-
-gimple
-gimple_build_predict (enum br_predictor predictor, enum prediction outcome)
-{
- gimple p = gimple_alloc (GIMPLE_PREDICT, 0);
- /* Ensure all the predictors fit into the lower bits of the subcode. */
- gcc_assert ((int) END_PREDICTORS <= GF_PREDICT_TAKEN);
- gimple_predict_set_predictor (p, predictor);
- gimple_predict_set_outcome (p, outcome);
- return p;
-}
-
#if defined ENABLE_GIMPLE_CHECKING
/* Complain of a gimple type mismatch and die. */
gsi_insert_seq_after (&si, src, GSI_NEW_STMT);
}
+/* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
+ NULL, a new sequence is allocated. This function is
+ similar to gimple_seq_add_seq, but does not scan the operands. */
+
+void
+gimple_seq_add_seq_without_update (gimple_seq *dst_p, gimple_seq src)
+{
+ gimple_stmt_iterator si;
+ if (src == NULL)
+ return;
+
+ si = gsi_last (*dst_p);
+ gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
+}
+
/* Determine whether to assign a location to the statement GS. */
static bool
{
if (gimple_code (stmt) == GIMPLE_NOP)
return true;
- if (gimple_code (stmt) == GIMPLE_BIND)
- return empty_body_p (gimple_bind_body (stmt));
+ if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
+ return empty_body_p (gimple_bind_body (bind_stmt));
return false;
}
/* Return the "fn spec" string for call STMT. */
-static tree
-gimple_call_fnspec (const_gimple stmt)
+static const_tree
+gimple_call_fnspec (const gcall *stmt)
{
tree type, attr;
+ if (gimple_call_internal_p (stmt))
+ return internal_fn_fnspec (gimple_call_internal_fn (stmt));
+
type = gimple_call_fntype (stmt);
if (!type)
return NULL_TREE;
/* Detects argument flags for argument number ARG on call STMT. */
int
-gimple_call_arg_flags (const_gimple stmt, unsigned arg)
+gimple_call_arg_flags (const gcall *stmt, unsigned arg)
{
- tree attr = gimple_call_fnspec (stmt);
+ const_tree attr = gimple_call_fnspec (stmt);
if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
return 0;
/* Detects return flags for the call STMT. */
int
-gimple_call_return_flags (const_gimple stmt)
+gimple_call_return_flags (const gcall *stmt)
{
- tree attr;
+ const_tree attr;
if (gimple_call_flags (stmt) & ECF_MALLOC)
return ERF_NOALIAS;
tree t;
int uid;
- t = gimple_label_label (stmt);
+ t = gimple_label_label (as_a <glabel *> (stmt));
uid = LABEL_DECL_UID (t);
if (uid == -1)
{
tree op1, op2, op3;
extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3);
- gimple_assign_set_rhs_with_ops_1 (gsi, subcode, op1, op2, op3);
+ gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2, op3);
}
did not have enough operand slots. */
void
-gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code,
- tree op1, tree op2, tree op3)
+gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
+ tree op1, tree op2, tree op3)
{
unsigned new_rhs_ops = get_gimple_rhs_num_ops (code);
gimple stmt = gsi_stmt (*gsi);
switch (gimple_code (stmt))
{
case GIMPLE_BIND:
- new_seq = gimple_seq_copy (gimple_bind_body (stmt));
- gimple_bind_set_body (copy, new_seq);
- gimple_bind_set_vars (copy, unshare_expr (gimple_bind_vars (stmt)));
- gimple_bind_set_block (copy, gimple_bind_block (stmt));
+ {
+ gbind *bind_stmt = as_a <gbind *> (stmt);
+ gbind *bind_copy = as_a <gbind *> (copy);
+ new_seq = gimple_seq_copy (gimple_bind_body (bind_stmt));
+ gimple_bind_set_body (bind_copy, new_seq);
+ gimple_bind_set_vars (bind_copy,
+ unshare_expr (gimple_bind_vars (bind_stmt)));
+ gimple_bind_set_block (bind_copy, gimple_bind_block (bind_stmt));
+ }
break;
case GIMPLE_CATCH:
- new_seq = gimple_seq_copy (gimple_catch_handler (stmt));
- gimple_catch_set_handler (copy, new_seq);
- t = unshare_expr (gimple_catch_types (stmt));
- gimple_catch_set_types (copy, t);
+ {
+ gcatch *catch_stmt = as_a <gcatch *> (stmt);
+ gcatch *catch_copy = as_a <gcatch *> (copy);
+ new_seq = gimple_seq_copy (gimple_catch_handler (catch_stmt));
+ gimple_catch_set_handler (catch_copy, new_seq);
+ t = unshare_expr (gimple_catch_types (catch_stmt));
+ gimple_catch_set_types (catch_copy, t);
+ }
break;
case GIMPLE_EH_FILTER:
- new_seq = gimple_seq_copy (gimple_eh_filter_failure (stmt));
- gimple_eh_filter_set_failure (copy, new_seq);
- t = unshare_expr (gimple_eh_filter_types (stmt));
- gimple_eh_filter_set_types (copy, t);
+ {
+ geh_filter *eh_filter_stmt = as_a <geh_filter *> (stmt);
+ geh_filter *eh_filter_copy = as_a <geh_filter *> (copy);
+ new_seq
+ = gimple_seq_copy (gimple_eh_filter_failure (eh_filter_stmt));
+ gimple_eh_filter_set_failure (eh_filter_copy, new_seq);
+ t = unshare_expr (gimple_eh_filter_types (eh_filter_stmt));
+ gimple_eh_filter_set_types (eh_filter_copy, t);
+ }
break;
case GIMPLE_EH_ELSE:
- new_seq = gimple_seq_copy (gimple_eh_else_n_body (stmt));
- gimple_eh_else_set_n_body (copy, new_seq);
- new_seq = gimple_seq_copy (gimple_eh_else_e_body (stmt));
- gimple_eh_else_set_e_body (copy, new_seq);
+ {
+ geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
+ geh_else *eh_else_copy = as_a <geh_else *> (copy);
+ new_seq = gimple_seq_copy (gimple_eh_else_n_body (eh_else_stmt));
+ gimple_eh_else_set_n_body (eh_else_copy, new_seq);
+ new_seq = gimple_seq_copy (gimple_eh_else_e_body (eh_else_stmt));
+ gimple_eh_else_set_e_body (eh_else_copy, new_seq);
+ }
break;
case GIMPLE_TRY:
- new_seq = gimple_seq_copy (gimple_try_eval (stmt));
- gimple_try_set_eval (copy, new_seq);
- new_seq = gimple_seq_copy (gimple_try_cleanup (stmt));
- gimple_try_set_cleanup (copy, new_seq);
+ {
+ gtry *try_stmt = as_a <gtry *> (stmt);
+ gtry *try_copy = as_a <gtry *> (copy);
+ new_seq = gimple_seq_copy (gimple_try_eval (try_stmt));
+ gimple_try_set_eval (try_copy, new_seq);
+ new_seq = gimple_seq_copy (gimple_try_cleanup (try_stmt));
+ gimple_try_set_cleanup (try_copy, new_seq);
+ }
break;
case GIMPLE_OMP_FOR:
t = unshare_expr (gimple_omp_for_clauses (stmt));
gimple_omp_for_set_clauses (copy, t);
{
- gimple_statement_omp_for *omp_for_copy =
- as_a <gimple_statement_omp_for> (copy);
- omp_for_copy->iter =
- static_cast <struct gimple_omp_for_iter *> (
- ggc_internal_vec_alloc_stat (sizeof (struct gimple_omp_for_iter),
- gimple_omp_for_collapse (stmt)
- MEM_STAT_INFO));
+ gomp_for *omp_for_copy = as_a <gomp_for *> (copy);
+ omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
+ ( gimple_omp_for_collapse (stmt));
}
for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
{
goto copy_omp_body;
case GIMPLE_OMP_PARALLEL:
- t = unshare_expr (gimple_omp_parallel_clauses (stmt));
- gimple_omp_parallel_set_clauses (copy, t);
- t = unshare_expr (gimple_omp_parallel_child_fn (stmt));
- gimple_omp_parallel_set_child_fn (copy, t);
- t = unshare_expr (gimple_omp_parallel_data_arg (stmt));
- gimple_omp_parallel_set_data_arg (copy, t);
+ {
+ gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
+ gomp_parallel *omp_par_copy = as_a <gomp_parallel *> (copy);
+ t = unshare_expr (gimple_omp_parallel_clauses (omp_par_stmt));
+ gimple_omp_parallel_set_clauses (omp_par_copy, t);
+ t = unshare_expr (gimple_omp_parallel_child_fn (omp_par_stmt));
+ gimple_omp_parallel_set_child_fn (omp_par_copy, t);
+ t = unshare_expr (gimple_omp_parallel_data_arg (omp_par_stmt));
+ gimple_omp_parallel_set_data_arg (omp_par_copy, t);
+ }
goto copy_omp_body;
case GIMPLE_OMP_TASK:
goto copy_omp_body;
case GIMPLE_OMP_CRITICAL:
- t = unshare_expr (gimple_omp_critical_name (stmt));
- gimple_omp_critical_set_name (copy, t);
+ t = unshare_expr (gimple_omp_critical_name (
+ as_a <gomp_critical *> (stmt)));
+ gimple_omp_critical_set_name (as_a <gomp_critical *> (copy), t);
goto copy_omp_body;
case GIMPLE_OMP_SECTIONS:
break;
case GIMPLE_TRANSACTION:
- new_seq = gimple_seq_copy (gimple_transaction_body (stmt));
- gimple_transaction_set_body (copy, new_seq);
+ new_seq = gimple_seq_copy (gimple_transaction_body (
+ as_a <gtransaction *> (stmt)));
+ gimple_transaction_set_body (as_a <gtransaction *> (copy),
+ new_seq);
break;
case GIMPLE_WITH_CLEANUP_EXPR:
return true;
if (gimple_code (s) == GIMPLE_ASM
- && gimple_asm_volatile_p (s))
+ && gimple_asm_volatile_p (as_a <const gasm *> (s)))
return true;
if (is_gimple_call (s))
switch (gimple_code (s))
{
case GIMPLE_ASM:
- return gimple_asm_volatile_p (s);
+ return gimple_asm_volatile_p (as_a <gasm *> (s));
case GIMPLE_CALL:
t = gimple_call_fndecl (s);
|| (SYM) == WIDEN_MULT_PLUS_EXPR \
|| (SYM) == WIDEN_MULT_MINUS_EXPR \
|| (SYM) == DOT_PROD_EXPR \
+ || (SYM) == SAD_EXPR \
|| (SYM) == REALIGN_LOAD_EXPR \
|| (SYM) == VEC_COND_EXPR \
|| (SYM) == VEC_PERM_EXPR \
/* Build a GIMPLE_CALL identical to STMT but skipping the arguments in
the positions marked by the set ARGS_TO_SKIP. */
-gimple
-gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
+gcall *
+gimple_call_copy_skip_args (gcall *stmt, bitmap args_to_skip)
{
int i;
int nargs = gimple_call_num_args (stmt);
auto_vec<tree> vargs (nargs);
- gimple new_stmt;
+ gcall *new_stmt;
for (i = 0; i < nargs; i++)
if (!bitmap_bit_p (args_to_skip, i))
gimple_signed_or_unsigned_type (bool unsignedp, tree type)
{
tree type1;
+ int i;
type1 = TYPE_MAIN_VARIANT (type);
if (type1 == signed_char_type_node
return unsignedp
? long_long_unsigned_type_node
: long_long_integer_type_node;
- if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
- return unsignedp
- ? int128_unsigned_type_node
- : int128_integer_type_node;
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && (type1 == int_n_trees[i].unsigned_type
+ || type1 == int_n_trees[i].signed_type))
+ return unsignedp
+ ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type;
+
#if HOST_BITS_PER_WIDE_INT >= 64
if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
return (unsignedp
? long_long_unsigned_type_node
: long_long_integer_type_node);
- if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
- return (unsignedp
- ? int128_unsigned_type_node
- : int128_integer_type_node);
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && TYPE_MODE (type) == int_n_data[i].m
+ && TYPE_PRECISION (type) == int_n_data[i].bitsize)
+ return unsignedp
+ ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type;
#if HOST_BITS_PER_WIDE_INT >= 64
if (TYPE_OK (intTI_type_node))
a decl of a builtin function. */
bool
-gimple_builtin_call_types_compatible_p (gimple stmt, tree fndecl)
+gimple_builtin_call_types_compatible_p (const_gimple stmt, tree fndecl)
{
gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
/* Return true when STMT is builtins call. */
bool
-gimple_call_builtin_p (gimple stmt)
+gimple_call_builtin_p (const_gimple stmt)
{
tree fndecl;
if (is_gimple_call (stmt)
/* Return true when STMT is builtins call to CLASS. */
bool
-gimple_call_builtin_p (gimple stmt, enum built_in_class klass)
+gimple_call_builtin_p (const_gimple stmt, enum built_in_class klass)
{
tree fndecl;
if (is_gimple_call (stmt)
/* Return true when STMT is builtins call to CODE of CLASS. */
bool
-gimple_call_builtin_p (gimple stmt, enum built_in_function code)
+gimple_call_builtin_p (const_gimple stmt, enum built_in_function code)
{
tree fndecl;
if (is_gimple_call (stmt)
GIMPLE_ASM. */
bool
-gimple_asm_clobbers_memory_p (const_gimple stmt)
+gimple_asm_clobbers_memory_p (const gasm *stmt)
{
unsigned i;
default:
return true;
}
+ else if (gimple_call_internal_p (call))
+ switch (gimple_call_internal_fn (call))
+ {
+ case IFN_ABNORMAL_DISPATCHER:
+ return true;
+ default:
+ if (gimple_call_flags (call) & ECF_LEAF)
+ return true;
+ return false;
+ }
- return false;
+ tree fndecl = gimple_call_fndecl (call);
+ if (!fndecl)
+ return false;
+ struct cgraph_node *n = cgraph_node::get (fndecl);
+ if (!n)
+ return false;
+ enum availability availability;
+ n = n->function_symbol (&availability);
+ if (!n || availability <= AVAIL_INTERPOSABLE)
+ return false;
+ return n->nonfreeing_fn;
}
/* Callback for walk_stmt_load_store_ops.
return false;
}
-/* If OP can be inferred to be non-NULL after STMT executes, return true.
- DEREFERENCE is TRUE if we can use a pointer dereference to infer a
- non-NULL range, FALSE otherwise.
-
- ATTRIBUTE is TRUE if we can use attributes to infer a non-NULL range
- for function arguments and return values. FALSE otherwise. */
+/* Return true if OP can be inferred to be non-NULL after STMT executes,
+ either by using a pointer dereference or attributes. */
+bool
+infer_nonnull_range (gimple stmt, tree op)
+{
+ return infer_nonnull_range_by_dereference (stmt, op)
+ || infer_nonnull_range_by_attribute (stmt, op);
+}
+/* Return true if OP can be inferred to be non-NULL after STMT
+ executes by using a pointer dereference. */
bool
-infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
+infer_nonnull_range_by_dereference (gimple stmt, tree op)
{
/* We can only assume that a pointer dereference will yield
non-NULL if -fdelete-null-pointer-checks is enabled. */
|| gimple_code (stmt) == GIMPLE_ASM)
return false;
- if (dereference
- && walk_stmt_load_store_ops (stmt, (void *)op,
- check_loadstore, check_loadstore))
+ if (walk_stmt_load_store_ops (stmt, (void *)op,
+ check_loadstore, check_loadstore))
return true;
- if (attribute
- && is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
+ return false;
+}
+
+/* Return true if OP can be inferred to be a non-NULL after STMT
+ executes by using attributes. */
+bool
+infer_nonnull_range_by_attribute (gimple stmt, tree op)
+{
+ /* We can only assume that a pointer dereference will yield
+ non-NULL if -fdelete-null-pointer-checks is enabled. */
+ if (!flag_delete_null_pointer_checks
+ || !POINTER_TYPE_P (TREE_TYPE (op))
+ || gimple_code (stmt) == GIMPLE_ASM)
+ return false;
+
+ if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
{
tree fntype = gimple_call_fntype (stmt);
tree attrs = TYPE_ATTRIBUTES (fntype);
{
for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
{
- if (operand_equal_p (op, gimple_call_arg (stmt, i), 0)
- && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i))))
+ if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i)))
+ && operand_equal_p (op, gimple_call_arg (stmt, i), 0))
return true;
}
return false;
/* Now see if op appears in the nonnull list. */
for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
{
- int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
- tree arg = gimple_call_arg (stmt, idx);
- if (operand_equal_p (op, arg, 0))
- return true;
+ unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
+ if (idx < gimple_call_num_args (stmt))
+ {
+ tree arg = gimple_call_arg (stmt, idx);
+ if (operand_equal_p (op, arg, 0))
+ return true;
+ }
}
}
}
/* If this function is marked as returning non-null, then we can
infer OP is non-null if it is used in the return statement. */
- if (attribute
- && gimple_code (stmt) == GIMPLE_RETURN
- && gimple_return_retval (stmt)
- && operand_equal_p (gimple_return_retval (stmt), op, 0)
- && lookup_attribute ("returns_nonnull",
- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
- return true;
+ if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
+ if (gimple_return_retval (return_stmt)
+ && operand_equal_p (gimple_return_retval (return_stmt), op, 0)
+ && lookup_attribute ("returns_nonnull",
+ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+ return true;
return false;
}
low = CASE_HIGH (labels[i - 1]);
if (!low)
low = CASE_LOW (labels[i - 1]);
- if ((TREE_INT_CST_LOW (low) + 1
- != TREE_INT_CST_LOW (high))
- || (TREE_INT_CST_HIGH (low)
- + (TREE_INT_CST_LOW (high) == 0)
- != TREE_INT_CST_HIGH (high)))
+ if (wi::add (low, 1) != high)
break;
}
if (i == len)
for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
gimple_set_location (gsi_stmt (i), loc);
}
+
+/* Release SSA_NAMEs in SEQ as well as the GIMPLE statements. */
+
+void
+gimple_seq_discard (gimple_seq seq)
+{
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
+ {
+ gimple stmt = gsi_stmt (gsi);
+ gsi_remove (&gsi, true);
+ release_defs (stmt);
+ ggc_free (stmt);
+ }
+}
+
+/* See if STMT now calls function that takes no parameters and if so, drop
+ call arguments. This is used when devirtualization machinery redirects
+ to __builtiln_unreacahble or __cxa_pure_virutal. */
+
+void
+maybe_remove_unused_call_args (struct function *fn, gimple stmt)
+{
+ tree decl = gimple_call_fndecl (stmt);
+ if (TYPE_ARG_TYPES (TREE_TYPE (decl))
+ && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))) == void_type_node
+ && gimple_call_num_args (stmt))
+ {
+ gimple_set_num_ops (stmt, 3);
+ update_stmt_fn (fn, stmt);
+ }
+}