/* Build a tuple with operands. CODE is the statement to build (which
must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the sub-code
- for the new tuple. NUM_OPS is the number of operands to allocate. */
+ for the new tuple. NUM_OPS is the number of operands to allocate. */
#define gimple_build_with_ops(c, s, n) \
gimple_build_with_ops_stat (c, s, n MEM_STAT_INFO)
/* 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);
gimple_assign_set_lhs (p, lhs);
gimple
gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
-{
+{
tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
gimplify_and_add (t, seq_p);
ggc_free (t);
/* Build a GIMPLE_NOP statement. */
-gimple
+gimple
gimple_build_nop (void)
{
return gimple_alloc (GIMPLE_NOP, 0);
*/
static inline gimple
-gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
+gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
unsigned nclobbers, unsigned nlabels)
{
gimple p;
#ifdef GATHER_STATISTICS
gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
#endif
-
+
return p;
}
LABELS is a vector of destination labels. */
gimple
-gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs,
+gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs,
VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers,
VEC(tree,gc)* labels)
{
p = gimple_build_asm_1 (string,
VEC_length (tree, inputs),
- VEC_length (tree, outputs),
+ VEC_length (tree, outputs),
VEC_length (tree, clobbers),
VEC_length (tree, labels));
-
+
for (i = 0; i < VEC_length (tree, inputs); i++)
gimple_asm_set_input_op (p, i, VEC_index (tree, inputs, i));
for (i = 0; i < VEC_length (tree, clobbers); i++)
gimple_asm_set_clobber_op (p, i, VEC_index (tree, clobbers, i));
-
+
for (i = 0; i < VEC_length (tree, labels); i++)
gimple_asm_set_label_op (p, i, VEC_index (tree, labels, i));
-
+
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
+gimple
gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
{
/* nlabels + 1 default label + 1 index. */
/* Build a GIMPLE_SWITCH statement.
INDEX is the switch's index.
- NLABELS is the number of labels in the switch excluding the DEFAULT_LABEL.
+ NLABELS is the number of labels in the switch excluding the DEFAULT_LABEL.
... are the labels excluding the default. */
-gimple
+gimple
gimple_build_switch (unsigned nlabels, tree index, tree default_label, ...)
{
va_list al;
BODY is the sequence of statements for which only one thread can execute.
NAME is optional identifier for this critical block. */
-gimple
+gimple
gimple_build_omp_critical (gimple_seq body, tree name)
{
gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0);
/* Build a GIMPLE_OMP_FOR statement.
BODY is sequence of statements inside the for loop.
- CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate,
+ CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate,
lastprivate, reductions, ordered, schedule, and nowait.
COLLAPSE is the collapse count.
PRE_BODY is the sequence of statements that are loop invariant. */
CHILD_FN is the function created for the parallel threads to execute.
DATA_ARG are the shared data argument(s). */
-gimple
-gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
+gimple
+gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
tree data_arg)
{
gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL, 0);
COPY_FN is the optional function for firstprivate initialization.
ARG_SIZE and ARG_ALIGN are size and alignment of the data block. */
-gimple
+gimple
gimple_build_omp_task (gimple_seq body, tree clauses, tree child_fn,
tree data_arg, tree copy_fn, tree arg_size,
tree arg_align)
BODY is the sequence of statements to be executed by just the master. */
-gimple
+gimple
gimple_build_omp_master (gimple_seq body)
{
gimple p = gimple_alloc (GIMPLE_OMP_MASTER, 0);
CONTROL_DEF is the definition of the control variable.
CONTROL_USE is the use of the control variable. */
-gimple
+gimple
gimple_build_omp_continue (tree control_def, tree control_use)
{
gimple p = gimple_alloc (GIMPLE_OMP_CONTINUE, 0);
BODY is the sequence of statements inside a loop that will executed in
sequence. */
-gimple
+gimple
gimple_build_omp_ordered (gimple_seq body)
{
gimple p = gimple_alloc (GIMPLE_OMP_ORDERED, 0);
/* Build a GIMPLE_OMP_RETURN statement.
WAIT_P is true if this is a non-waiting return. */
-gimple
+gimple
gimple_build_omp_return (bool wait_p)
{
gimple p = gimple_alloc (GIMPLE_OMP_RETURN, 0);
CLAUSES are any of the OMP sections contsruct's clauses: private,
firstprivate, lastprivate, reduction, and nowait. */
-gimple
+gimple
gimple_build_omp_sections (gimple_seq body, tree clauses)
{
gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS, 0);
CLAUSES are any of the OMP single construct's clauses: private, firstprivate,
copyprivate, nowait. */
-gimple
+gimple
gimple_build_omp_single (gimple_seq body, tree clauses)
{
gimple p = gimple_alloc (GIMPLE_OMP_SINGLE, 0);
/* If this triggers, it's a sign that the same list is being freed
twice. */
gcc_assert (seq != gimple_seq_cache || gimple_seq_cache == NULL);
-
+
/* Add SEQ to the pool of free sequences. */
seq->next_free = gimple_seq_cache;
gimple_seq_cache = seq;
/* Walk all the statements in the sequence SEQ calling walk_gimple_stmt
on each one. WI is as in walk_gimple_stmt.
-
+
If walk_gimple_stmt returns non-NULL, the walk is stopped, the
value is stored in WI->CALLBACK_RESULT and the statement that
produced the value is returned.
assignment. I suspect there may be cases where gimple_assign_copy_p,
gimple_assign_single_p, or equivalent logic is used where a similar
treatment of unary NOPs is appropriate. */
-
+
bool
gimple_assign_unary_nop_p (gimple gs)
{
gcc_unreachable();
}
+/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a
+ GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an
+ expression with a different value.
+
+ This will update any annotations (say debug bind stmts) referring
+ to the original LHS, so that they use the RHS instead. This is
+ done even if NLHS and LHS are the same, for it is understood that
+ the RHS will be modified afterwards, and NLHS will not be assigned
+ an equivalent value.
+
+ Adjusting any non-annotation uses of the LHS, if needed, is a
+ responsibility of the caller.
+
+ The effect of this call should be pretty much the same as that of
+ inserting a copy of STMT before STMT, and then removing the
+ original stmt, at which time gsi_remove() would have update
+ annotations, but using this function saves all the inserting,
+ copying and removing. */
+
+void
+gimple_replace_lhs (gimple stmt, tree nlhs)
+{
+ if (MAY_HAVE_DEBUG_STMTS)
+ {
+ tree lhs = gimple_get_lhs (stmt);
+
+ gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt);
+
+ insert_debug_temp_for_var_def (NULL, lhs);
+ }
+
+ gimple_set_lhs (stmt, nlhs);
+}
/* Return a deep copy of statement STMT. All the operands from STMT
are reallocated and copied using unshare_expr. The DEF, USE, VDEF
{
while (handled_component_p (t))
t = TREE_OPERAND (t, 0);
-
+
if (SSA_VAR_P (t)
|| TREE_CODE (t) == STRING_CST
|| TREE_CODE (t) == CONSTRUCTOR
tree
canonicalize_cond_expr_cond (tree t)
{
+ /* Strip conversions around boolean operations. */
+ if (CONVERT_EXPR_P (t)
+ && truth_value_p (TREE_CODE (TREE_OPERAND (t, 0))))
+ t = TREE_OPERAND (t, 0);
+
/* For (bool)x use x != 0. */
- if (TREE_CODE (t) == NOP_EXPR
- && TREE_TYPE (t) == boolean_type_node)
+ if (CONVERT_EXPR_P (t)
+ && TREE_CODE (TREE_TYPE (t)) == BOOLEAN_TYPE)
{
tree top0 = TREE_OPERAND (t, 0);
t = build2 (NE_EXPR, TREE_TYPE (t),
/* Return true if the field decls F1 and F2 are at the same offset. */
-static bool
+bool
compare_field_offset (tree f1, tree f2)
{
if (DECL_OFFSET_ALIGN (f1) == DECL_OFFSET_ALIGN (f2))
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
&& (!COMPLETE_TYPE_P (TREE_TYPE (t1))
|| !COMPLETE_TYPE_P (TREE_TYPE (t2)))
- && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2), true))
+ && compare_type_names_p (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (t2)), true))
{
/* Replace the pointed-to incomplete type with the
complete one. */