summaryrefslogtreecommitdiff
path: root/gcc/gimple.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r--gcc/gimple.c126
1 files changed, 87 insertions, 39 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f4c57b2861c..2359e0e954a 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -145,7 +145,7 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
}
#endif
- stmt = (gimple) ggc_alloc_cleared_stat (size PASS_MEM_STAT);
+ stmt = ggc_alloc_cleared_gimple_statement_d_stat (size PASS_MEM_STAT);
gimple_set_code (stmt, code);
gimple_set_num_ops (stmt, num_ops);
@@ -305,31 +305,40 @@ gimple_build_call_from_tree (tree t)
/* Extract the operands and code for expression EXPR into *SUBCODE_P,
- *OP1_P and *OP2_P respectively. */
+ *OP1_P, *OP2_P and *OP3_P respectively. */
void
-extract_ops_from_tree (tree expr, enum tree_code *subcode_p, tree *op1_p,
- tree *op2_p)
+extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p,
+ tree *op2_p, tree *op3_p)
{
enum gimple_rhs_class grhs_class;
*subcode_p = TREE_CODE (expr);
grhs_class = get_gimple_rhs_class (*subcode_p);
- if (grhs_class == GIMPLE_BINARY_RHS)
+ if (grhs_class == GIMPLE_TERNARY_RHS)
{
*op1_p = TREE_OPERAND (expr, 0);
*op2_p = TREE_OPERAND (expr, 1);
+ *op3_p = TREE_OPERAND (expr, 2);
+ }
+ else if (grhs_class == GIMPLE_BINARY_RHS)
+ {
+ *op1_p = TREE_OPERAND (expr, 0);
+ *op2_p = TREE_OPERAND (expr, 1);
+ *op3_p = NULL_TREE;
}
else if (grhs_class == GIMPLE_UNARY_RHS)
{
*op1_p = TREE_OPERAND (expr, 0);
*op2_p = NULL_TREE;
+ *op3_p = NULL_TREE;
}
else if (grhs_class == GIMPLE_SINGLE_RHS)
{
*op1_p = expr;
*op2_p = NULL_TREE;
+ *op3_p = NULL_TREE;
}
else
gcc_unreachable ();
@@ -345,10 +354,10 @@ gimple
gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
{
enum tree_code subcode;
- tree op1, op2;
+ tree op1, op2, op3;
- extract_ops_from_tree (rhs, &subcode, &op1, &op2);
- return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2
+ extract_ops_from_tree_1 (rhs, &subcode, &op1, &op2, &op3);
+ return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2, op3
PASS_MEM_STAT);
}
@@ -359,7 +368,7 @@ gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
gimple
gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
- tree op2 MEM_STAT_DECL)
+ tree op2, tree op3 MEM_STAT_DECL)
{
unsigned num_ops;
gimple p;
@@ -378,6 +387,12 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
gimple_assign_set_rhs2 (p, op2);
}
+ if (op3)
+ {
+ gcc_assert (num_ops > 3);
+ gimple_assign_set_rhs3 (p, op3);
+ }
+
return p;
}
@@ -824,7 +839,8 @@ gimple_build_omp_for (gimple_seq body, tree clauses, size_t collapse,
gimple_omp_set_body (p, body);
gimple_omp_for_set_clauses (p, clauses);
p->gimple_omp_for.collapse = collapse;
- p->gimple_omp_for.iter = GGC_CNEWVEC (struct gimple_omp_for_iter, collapse);
+ p->gimple_omp_for.iter
+ = ggc_alloc_cleared_vec_gimple_omp_for_iter (collapse);
if (pre_body)
gimple_omp_for_set_pre_body (p, pre_body);
@@ -1074,7 +1090,7 @@ gimple_seq_alloc (void)
}
else
{
- seq = (gimple_seq) ggc_alloc_cleared (sizeof (*seq));
+ seq = ggc_alloc_cleared_gimple_seq_d ();
#ifdef GATHER_STATISTICS
gimple_alloc_counts[(int) gimple_alloc_kind_seq]++;
gimple_alloc_sizes[(int) gimple_alloc_kind_seq] += sizeof (*seq);
@@ -1954,22 +1970,22 @@ void
gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr)
{
enum tree_code subcode;
- tree op1, op2;
+ tree op1, op2, op3;
- extract_ops_from_tree (expr, &subcode, &op1, &op2);
- gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2);
+ extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3);
+ gimple_assign_set_rhs_with_ops_1 (gsi, subcode, op1, op2, op3);
}
/* Set the RHS of assignment statement pointed-to by GSI to CODE with
- operands OP1 and OP2.
+ operands OP1, OP2 and OP3.
NOTE: The statement pointed-to by GSI may be reallocated if it
did not have enough operand slots. */
void
-gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
- tree op1, tree op2)
+gimple_assign_set_rhs_with_ops_1 (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);
@@ -1993,6 +2009,8 @@ gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
gimple_assign_set_rhs1 (stmt, op1);
if (new_rhs_ops > 1)
gimple_assign_set_rhs2 (stmt, op2);
+ if (new_rhs_ops > 2)
+ gimple_assign_set_rhs3 (stmt, op3);
}
@@ -2122,8 +2140,8 @@ gimple_copy (gimple stmt)
t = unshare_expr (gimple_omp_for_clauses (stmt));
gimple_omp_for_set_clauses (copy, t);
copy->gimple_omp_for.iter
- = GGC_NEWVEC (struct gimple_omp_for_iter,
- gimple_omp_for_collapse (stmt));
+ = ggc_alloc_vec_gimple_omp_for_iter
+ (gimple_omp_for_collapse (stmt));
for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
{
gimple_omp_for_set_cond (copy, i,
@@ -2472,6 +2490,8 @@ get_gimple_rhs_num_ops (enum tree_code code)
return 1;
else if (rhs_class == GIMPLE_BINARY_RHS)
return 2;
+ else if (rhs_class == GIMPLE_TERNARY_RHS)
+ return 3;
else
gcc_unreachable ();
}
@@ -2488,6 +2508,8 @@ get_gimple_rhs_num_ops (enum tree_code code)
|| (SYM) == TRUTH_OR_EXPR \
|| (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \
: (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \
+ : ((SYM) == WIDEN_MULT_PLUS_EXPR \
+ || (SYM) == WIDEN_MULT_MINUS_EXPR) ? GIMPLE_TERNARY_RHS \
: ((SYM) == COND_EXPR \
|| (SYM) == CONSTRUCTOR \
|| (SYM) == OBJ_TYPE_REF \
@@ -2573,7 +2595,8 @@ is_gimple_condexpr (tree t)
bool
is_gimple_addressable (tree t)
{
- return (is_gimple_id (t) || handled_component_p (t) || INDIRECT_REF_P (t));
+ return (is_gimple_id (t) || handled_component_p (t)
+ || TREE_CODE (t) == MEM_REF);
}
/* Return true if T is a valid gimple constant. */
@@ -2624,7 +2647,7 @@ is_gimple_address (const_tree t)
op = TREE_OPERAND (op, 0);
}
- if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
+ if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
return true;
switch (TREE_CODE (op))
@@ -2684,8 +2707,18 @@ is_gimple_invariant_address (const_tree t)
return false;
op = strip_invariant_refs (TREE_OPERAND (t, 0));
+ if (!op)
+ return false;
+
+ if (TREE_CODE (op) == MEM_REF)
+ {
+ const_tree op0 = TREE_OPERAND (op, 0);
+ return (TREE_CODE (op0) == ADDR_EXPR
+ && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
+ || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
+ }
- return op && (CONSTANT_CLASS_P (op) || decl_address_invariant_p (op));
+ return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
}
/* Return true if T is a gimple invariant address at IPA level
@@ -2902,7 +2935,7 @@ is_gimple_min_lval (tree t)
{
if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
return false;
- return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF);
+ return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
}
/* Return true if T is a typecast operation. */
@@ -2922,6 +2955,18 @@ is_gimple_call_addr (tree t)
return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
}
+/* Return true if T is a valid address operand of a MEM_REF. */
+
+bool
+is_gimple_mem_ref_addr (tree t)
+{
+ return (is_gimple_reg (t)
+ || TREE_CODE (t) == INTEGER_CST
+ || (TREE_CODE (t) == ADDR_EXPR
+ && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
+ || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
+}
+
/* If T makes a function call, return the corresponding CALL_EXPR operand.
Otherwise, return NULL_TREE. */
@@ -2953,10 +2998,15 @@ get_base_address (tree t)
while (handled_component_p (t))
t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
+ t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+
if (SSA_VAR_P (t)
|| TREE_CODE (t) == STRING_CST
|| TREE_CODE (t) == CONSTRUCTOR
- || INDIRECT_REF_P (t))
+ || INDIRECT_REF_P (t)
+ || TREE_CODE (t) == MEM_REF)
return t;
else
return NULL_TREE;
@@ -3084,14 +3134,8 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
gimple_set_block (new_stmt, gimple_block (stmt));
if (gimple_has_location (stmt))
gimple_set_location (new_stmt, gimple_location (stmt));
-
- /* Carry all the flags to the new GIMPLE_CALL. */
+ gimple_call_copy_flags (new_stmt, stmt);
gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
- gimple_call_set_tail (new_stmt, gimple_call_tail_p (stmt));
- gimple_call_set_cannot_inline (new_stmt, gimple_call_cannot_inline_p (stmt));
- gimple_call_set_return_slot_opt (new_stmt, gimple_call_return_slot_opt_p (stmt));
- gimple_call_set_from_thunk (new_stmt, gimple_call_from_thunk_p (stmt));
- gimple_call_set_va_arg_pack (new_stmt, gimple_call_va_arg_pack_p (stmt));
gimple_set_modified (new_stmt, true);
@@ -3592,12 +3636,6 @@ gimple_types_compatible_p (tree t1, tree t2)
{
tree f1, f2;
- /* If one type requires structural equality checks and the
- other doesn't, do not merge the types. */
- if (TYPE_STRUCTURAL_EQUALITY_P (t1)
- != TYPE_STRUCTURAL_EQUALITY_P (t2))
- goto different_types;
-
/* The struct tags shall compare equal. */
if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2), false))
@@ -3954,6 +3992,11 @@ gimple_register_type (tree t)
gcc_assert (TYPE_P (t));
+ /* In TYPE_CANONICAL we cache the result of gimple_register_type.
+ It is initially set to NULL during LTO streaming. */
+ if (TYPE_CANONICAL (t))
+ return TYPE_CANONICAL (t);
+
/* Always register the main variant first. This is important so we
pick up the non-typedef variants as canonical, otherwise we'll end
up taking typedef ids for structure tags during comparison. */
@@ -4017,10 +4060,14 @@ gimple_register_type (tree t)
TYPE_NEXT_REF_TO (t) = NULL_TREE;
}
+ TYPE_CANONICAL (t) = new_type;
t = new_type;
}
else
- *slot = (void *) t;
+ {
+ TYPE_CANONICAL (t) = t;
+ *slot = (void *) t;
+ }
return t;
}
@@ -4399,7 +4446,7 @@ count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
- if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
+ if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
{
if (wi_p->is_lhs)
count_p->num_stores++;
@@ -4472,6 +4519,7 @@ get_base_loadstore (tree op)
op = TREE_OPERAND (op, 0);
if (DECL_P (op)
|| INDIRECT_REF_P (op)
+ || TREE_CODE (op) == MEM_REF
|| TREE_CODE (op) == TARGET_MEM_REF)
return op;
return NULL_TREE;