diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 170 |
1 files changed, 106 insertions, 64 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index cb4358ca9bd..a9c93ac972d 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -110,10 +110,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; } @@ -534,7 +537,7 @@ lookup_tmp_var (tree val, bool is_formal) /* 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. */ @@ -1153,14 +1156,9 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) /* 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)) @@ -2966,7 +2964,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 @@ -3190,7 +3188,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; } @@ -3274,13 +3272,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))); @@ -4009,7 +4010,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; @@ -4052,51 +4053,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] */ @@ -5140,9 +5142,10 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p) { /* 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; } @@ -5585,7 +5588,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) { 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 @@ -6513,7 +6516,7 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) 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 @@ -6562,7 +6565,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) @@ -6768,19 +6772,57 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, 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. */ |