aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c181
1 files changed, 112 insertions, 69 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 567f304fe1f..db28dcd853c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "output.h"
#include "ggc.h"
+#include "diagnostic-core.h"
#include "toplev.h"
#include "target.h"
#include "pointer-set.h"
@@ -110,10 +111,13 @@ mark_addressable (tree x)
{
while (handled_component_p (x))
x = TREE_OPERAND (x, 0);
+ if (TREE_CODE (x) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
+ x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
if (TREE_CODE (x) != VAR_DECL
&& TREE_CODE (x) != PARM_DECL
&& TREE_CODE (x) != RESULT_DECL)
- return ;
+ return;
TREE_ADDRESSABLE (x) = 1;
}
@@ -649,7 +653,7 @@ declare_vars (tree vars, gimple scope, bool debug_info)
gcc_assert (!block || TREE_CODE (block) == BLOCK);
if (!block || !debug_info)
{
- TREE_CHAIN (last) = gimple_bind_vars (scope);
+ DECL_CHAIN (last) = gimple_bind_vars (scope);
gimple_bind_set_vars (scope, temps);
}
else
@@ -697,7 +701,7 @@ force_constant_size (tree var)
void
gimple_add_tmp_var (tree tmp)
{
- gcc_assert (!TREE_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
+ gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
/* Later processing assumes that the object size is constant, which might
not be true at this point. Force the use of a constant upper bound in
@@ -710,7 +714,7 @@ gimple_add_tmp_var (tree tmp)
if (gimplify_ctxp)
{
- TREE_CHAIN (tmp) = gimplify_ctxp->temps;
+ DECL_CHAIN (tmp) = gimplify_ctxp->temps;
gimplify_ctxp->temps = tmp;
/* Mark temporaries local within the nearest enclosing parallel. */
@@ -865,9 +869,9 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
tree t = *tp;
enum tree_code code = TREE_CODE (t);
- /* Do not copy SAVE_EXPR or TARGET_EXPR nodes themselves, but copy
- their subtrees if we can make sure to do it only once. */
- if (code == SAVE_EXPR || code == TARGET_EXPR)
+ /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
+ copy their subtrees if we can make sure to do it only once. */
+ if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
{
if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
;
@@ -892,10 +896,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
/* Leave the bulk of the work to copy_tree_r itself. */
else
- {
- gcc_assert (code != BIND_EXPR);
- copy_tree_r (tp, walk_subtrees, NULL);
- }
+ copy_tree_r (tp, walk_subtrees, NULL);
return NULL_TREE;
}
@@ -1132,7 +1133,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
tree temp = voidify_wrapper_expr (bind_expr, NULL);
/* Mark variables seen in this bind expr. */
- for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t))
+ for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
{
if (TREE_CODE (t) == VAR_DECL)
{
@@ -1901,7 +1902,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
SET_DECL_RTL (copy, 0);
TREE_USED (copy) = 1;
block = DECL_INITIAL (current_function_decl);
- TREE_CHAIN (copy) = BLOCK_VARS (block);
+ DECL_CHAIN (copy) = BLOCK_VARS (block);
BLOCK_VARS (block) = copy;
SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
DECL_HAS_VALUE_EXPR_P (copy) = 1;
@@ -2961,7 +2962,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
= build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
tmp = create_tmp_var (type, "iftmp");
- result = build_fold_indirect_ref_loc (loc, tmp);
+ result = build_simple_mem_ref_loc (loc, tmp);
}
/* Build the new then clause, `tmp = then_;'. But don't build the
@@ -3185,7 +3186,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
gimple_call_set_lhs (gs, t);
gimplify_seq_add_stmt (seq_p, gs);
- *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+ *expr_p = build_simple_mem_ref (t);
return GS_ALL_DONE;
}
@@ -3269,13 +3270,16 @@ gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
/* If the constructor component is indirect, determine if we have a
potential overlap with the lhs. The only bits of information we
have to go on at this point are addressability and alias sets. */
- if (TREE_CODE (t) == INDIRECT_REF
+ if ((INDIRECT_REF_P (t)
+ || TREE_CODE (t) == MEM_REF)
&& (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
&& alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
return t;
/* If the constructor component is a call, determine if it can hide a
- potential overlap with the lhs through an INDIRECT_REF like above. */
+ potential overlap with the lhs through an INDIRECT_REF like above.
+ ??? Ugh - this is completely broken. In fact this whole analysis
+ doesn't look conservative. */
if (TREE_CODE (t) == CALL_EXPR)
{
tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
@@ -4004,7 +4008,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
tree
gimple_fold_indirect_ref (tree t)
{
- tree type = TREE_TYPE (TREE_TYPE (t));
+ tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
tree sub = t;
tree subtype;
@@ -4047,51 +4051,52 @@ gimple_fold_indirect_ref (tree t)
}
}
- /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+ /* *(p + CST) -> ... */
if (TREE_CODE (sub) == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
{
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
+ tree addr = TREE_OPERAND (sub, 0);
+ tree off = TREE_OPERAND (sub, 1);
+ tree addrtype;
+
+ STRIP_NOPS (addr);
+ addrtype = TREE_TYPE (addr);
- STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
+ /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
{
- HOST_WIDE_INT offset = tree_low_cst (op01, 0);
- tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi
- = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
- if (offset / part_widthi
- <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
- return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
- part_width, index);
+ HOST_WIDE_INT offset = tree_low_cst (off, 0);
+ tree part_width = TYPE_SIZE (type);
+ unsigned HOST_WIDE_INT part_widthi
+ = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+ tree index = bitsize_int (indexi);
+ if (offset / part_widthi
+ <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
+ return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
+ part_width, index);
}
- }
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
- if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
- {
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
+ /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
+ {
+ tree size = TYPE_SIZE_UNIT (type);
+ if (tree_int_cst_equal (size, off))
+ return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
+ }
- STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
- {
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, op01))
- return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
- }
+ /* *(p + CST) -> MEM_REF <p, CST>. */
+ if (TREE_CODE (addr) != ADDR_EXPR
+ || DECL_P (TREE_OPERAND (addr, 0)))
+ return fold_build2 (MEM_REF, type,
+ addr,
+ build_int_cst_wide (ptype,
+ TREE_INT_CST_LOW (off),
+ TREE_INT_CST_HIGH (off)));
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -4555,7 +4560,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
/* Try to alleviate the effects of the gimplification creating artificial
temporaries (see for example is_gimple_reg_rhs) on the debug info. */
if (!gimplify_ctxp->into_ssa
- && DECL_P (*from_p)
+ && TREE_CODE (*from_p) == VAR_DECL
&& DECL_IGNORED_P (*from_p)
&& DECL_P (*to_p)
&& !DECL_IGNORED_P (*to_p))
@@ -5387,7 +5392,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
case QUAL_UNION_TYPE:
{
tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
@@ -6558,7 +6563,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|| gimple_test_f == is_gimple_mem_rhs_or_call
|| gimple_test_f == is_gimple_reg_rhs
|| gimple_test_f == is_gimple_reg_rhs_or_call
- || gimple_test_f == is_gimple_asm_val)
+ || gimple_test_f == is_gimple_asm_val
+ || gimple_test_f == is_gimple_mem_ref_addr)
gcc_assert (fallback & fb_rvalue);
else if (gimple_test_f == is_gimple_min_lval
|| gimple_test_f == is_gimple_lvalue)
@@ -6764,19 +6770,56 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
recalculate_side_effects (*expr_p);
break;
+ case MISALIGNED_INDIRECT_REF:
+ /* We can only reach this through re-gimplification from
+ tree optimizers. */
+ ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ recalculate_side_effects (*expr_p);
+ break;
+
case INDIRECT_REF:
- *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
- if (*expr_p != save_expr)
+ {
+ bool volatilep = TREE_THIS_VOLATILE (*expr_p);
+ tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
+
+ *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
+ if (*expr_p != save_expr)
+ {
+ ret = GS_OK;
+ break;
+ }
+
+ ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ recalculate_side_effects (*expr_p);
+
+ *expr_p = fold_build2_loc (input_location, MEM_REF,
+ TREE_TYPE (*expr_p),
+ TREE_OPERAND (*expr_p, 0),
+ build_int_cst (saved_ptr_type, 0));
+ TREE_THIS_VOLATILE (*expr_p) = volatilep;
+ ret = GS_OK;
+ break;
+ }
+
+ /* We arrive here through the various re-gimplifcation paths. */
+ case MEM_REF:
+ /* First try re-folding the whole thing. */
+ tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
+ TREE_OPERAND (*expr_p, 0),
+ TREE_OPERAND (*expr_p, 1));
+ if (tmp)
{
+ *expr_p = tmp;
+ recalculate_side_effects (*expr_p);
ret = GS_OK;
break;
}
- /* else fall through. */
- case ALIGN_INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
- is_gimple_reg, fb_rvalue);
+ is_gimple_mem_ref_addr, fb_rvalue);
recalculate_side_effects (*expr_p);
+ ret = GS_ALL_DONE;
break;
/* Constants need not be gimplified. */
@@ -7373,7 +7416,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
that temporary. */
tmp = build_fold_addr_expr_loc (input_location, *expr_p);
gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
- *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
+ *expr_p = build_simple_mem_ref (tmp);
}
else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
{
@@ -7489,7 +7532,7 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
@@ -7648,7 +7691,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
gimple_bind_set_body (outer_bind, parm_stmts);
for (parm = DECL_ARGUMENTS (current_function_decl);
- parm; parm = TREE_CHAIN (parm))
+ parm; parm = DECL_CHAIN (parm))
if (DECL_HAS_VALUE_EXPR_P (parm))
{
DECL_HAS_VALUE_EXPR_P (parm) = 0;
@@ -7698,7 +7741,7 @@ gimplify_function_tree (tree fndecl)
else
push_struct_function (fndecl);
- for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = TREE_CHAIN (parm))
+ for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
{
/* Preliminarily mark non-addressed complex variables as eligible
for promotion to gimple registers. We'll transform their uses
@@ -7994,7 +8037,7 @@ force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
}
if (gimple_referenced_vars (cfun))
- for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+ for (t = gimplify_ctxp->temps; t ; t = DECL_CHAIN (t))
add_referenced_var (t);
pop_gimplify_context (NULL);