#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
#include "gimple.h"
#include "tree-iterator.h"
#include "tree-inline.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
#include "langhooks.h"
-#include "langhooks-def.h"
#include "tree-flow.h"
#include "cgraph.h"
#include "timevar.h"
-#include "except.h"
#include "hashtab.h"
#include "flags.h"
#include "function.h"
#include "output.h"
-#include "expr.h"
#include "ggc.h"
#include "toplev.h"
#include "target.h"
-#include "optabs.h"
#include "pointer-set.h"
#include "splay-tree.h"
#include "vec.h"
#include "gimple.h"
#include "tree-pass.h"
+#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name. */
+#include "expr.h" /* FIXME: for can_move_by_pieces
+ and STACK_CHECK_MAX_VAR_SIZE. */
enum gimplify_omp_var_data
{
{
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;
}
/* Return true if T is a CALL_EXPR or an expression that can be
- assignmed to a temporary. Note that this predicate should only be
+ assigned to a temporary. Note that this predicate should only be
used during gimplification. See the rationale for this in
gimplify_modify_expr. */
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))
;
/* 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;
}
/* Preliminarily mark non-addressed complex variables as eligible
for promotion to gimple registers. We'll transform their uses
- as we find them.
- We exclude complex types if not optimizing because they can be
- subject to partial stores in GNU C by means of the __real__ and
- __imag__ operators and we cannot promote them to total stores
- (see gimplify_modify_expr_complex_part). */
- if (optimize
- && (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
- || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+ as we find them. */
+ if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+ || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
&& !TREE_THIS_VOLATILE (t)
&& (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
&& !needs_to_live_in_memory (t))
&& !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
&& decl_function_context (decl) == current_function_decl)
{
- gcc_assert (errorcount || sorrycount);
+ gcc_assert (seen_error ());
return GS_ERROR;
}
tree copy = copy_node (decl), block;
lang_hooks.dup_lang_specific_decl (copy);
- SET_DECL_RTL (copy, NULL_RTX);
+ SET_DECL_RTL (copy, 0);
TREE_USED (copy) = 1;
block = DECL_INITIAL (current_function_decl);
TREE_CHAIN (copy) = BLOCK_VARS (block);
= 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
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;
}
/* 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)));
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;
}
}
- /* ((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] */
{
/* Note that gsi_insert_seq_before and gsi_remove do not
scan operands, unlike some other sequence mutators. */
- gsi_insert_seq_before_without_update (&iter,
- gimple_wce_cleanup (wce),
- GSI_SAME_STMT);
+ if (!gimple_wce_cleanup_eh_only (wce))
+ gsi_insert_seq_before_without_update (&iter,
+ gimple_wce_cleanup (wce),
+ GSI_SAME_STMT);
gsi_remove (&iter, true);
break;
}
/* Errors can result in improperly nested cleanups. Which results in
confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
- if (errorcount || sorrycount)
+ if (seen_error ())
return;
if (gimple_conditional_context ())
{
case OMP_CLAUSE_DEFAULT_NONE:
error ("%qE not specified in enclosing parallel",
- DECL_NAME (decl));
+ DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
if ((ctx->region_type & ORT_TASK) != 0)
error_at (ctx->location, "enclosing task");
else
GIMPLE_TEST_F points to a function that takes a tree T and
returns nonzero if T is in the GIMPLE form requested by the
- caller. The GIMPLE predicates are in tree-gimple.c.
+ caller. The GIMPLE predicates are in gimple.c.
FALLBACK tells the function what sort of a temporary we want if
gimplification cannot produce an expression that complies with
|| 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)
recalculate_side_effects (*expr_p);
break;
+ case ALIGN_INDIRECT_REF:
+ 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. */
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))
{
gcc_assert (gimplify_ctxp == NULL);
#ifdef ENABLE_TYPES_CHECKING
- if (!errorcount && !sorrycount)
+ if (!seen_error ())
verify_types_in_gimple_seq (gimple_bind_body (outer_bind));
#endif