diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 325 |
1 files changed, 32 insertions, 293 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 3253f861958..4e6f44898ba 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -23,8 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" #include "tree.h" +#include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" #include "tree-iterator.h" @@ -37,24 +37,15 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfg.h" #include "tree-ssanames.h" #include "tree-ssa.h" -#include "timevar.h" -#include "hashtab.h" -#include "flags.h" -#include "function.h" -#include "ggc.h" #include "diagnostic-core.h" #include "target.h" -#include "pointer-set.h" #include "splay-tree.h" -#include "vec.h" #include "omp-low.h" #include "gimple-low.h" #include "cilk.h" #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */ #include "tree-pass.h" /* FIXME: only for PROP_gimple_any */ -#include "expr.h" -#include "tm_p.h" enum gimplify_omp_var_data { @@ -102,7 +93,7 @@ struct gimplify_omp_ctx bool combined_loop; }; -static struct gimplify_ctx *gimplify_ctxp; +struct gimplify_ctx *gimplify_ctxp; static struct gimplify_omp_ctx *gimplify_omp_ctxp; @@ -3393,7 +3384,7 @@ gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts, /* Return the appropriate RHS predicate for this LHS. */ -static gimple_predicate +gimple_predicate rhs_predicate_for (tree lhs) { if (is_gimple_reg (lhs)) @@ -8590,287 +8581,6 @@ gimplify_function_tree (tree fndecl) pop_cfun (); } -/* Some transformations like inlining may invalidate the GIMPLE form - for operands. This function traverses all the operands in STMT and - gimplifies anything that is not a valid gimple operand. Any new - GIMPLE statements are inserted before *GSI_P. */ - -void -gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) -{ - size_t i, num_ops; - tree lhs; - gimple_seq pre = NULL; - gimple post_stmt = NULL; - struct gimplify_ctx gctx; - - push_gimplify_context (&gctx); - gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun); - - switch (gimple_code (stmt)) - { - case GIMPLE_COND: - gimplify_expr (gimple_cond_lhs_ptr (stmt), &pre, NULL, - is_gimple_val, fb_rvalue); - gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL, - is_gimple_val, fb_rvalue); - break; - case GIMPLE_SWITCH: - gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL, - is_gimple_val, fb_rvalue); - break; - case GIMPLE_OMP_ATOMIC_LOAD: - gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL, - is_gimple_val, fb_rvalue); - break; - case GIMPLE_ASM: - { - size_t i, noutputs = gimple_asm_noutputs (stmt); - const char *constraint, **oconstraints; - bool allows_mem, allows_reg, is_inout; - - oconstraints - = (const char **) alloca ((noutputs) * sizeof (const char *)); - for (i = 0; i < noutputs; i++) - { - tree op = gimple_asm_output_op (stmt, i); - constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op))); - oconstraints[i] = constraint; - parse_output_constraint (&constraint, i, 0, 0, &allows_mem, - &allows_reg, &is_inout); - gimplify_expr (&TREE_VALUE (op), &pre, NULL, - is_inout ? is_gimple_min_lval : is_gimple_lvalue, - fb_lvalue | fb_mayfail); - } - for (i = 0; i < gimple_asm_ninputs (stmt); i++) - { - tree op = gimple_asm_input_op (stmt, i); - constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op))); - parse_input_constraint (&constraint, 0, 0, noutputs, 0, - oconstraints, &allows_mem, &allows_reg); - if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem) - allows_reg = 0; - if (!allows_reg && allows_mem) - gimplify_expr (&TREE_VALUE (op), &pre, NULL, - is_gimple_lvalue, fb_lvalue | fb_mayfail); - else - gimplify_expr (&TREE_VALUE (op), &pre, NULL, - is_gimple_asm_val, fb_rvalue); - } - } - break; - default: - /* NOTE: We start gimplifying operands from last to first to - make sure that side-effects on the RHS of calls, assignments - and ASMs are executed before the LHS. The ordering is not - important for other statements. */ - num_ops = gimple_num_ops (stmt); - for (i = num_ops; i > 0; i--) - { - tree op = gimple_op (stmt, i - 1); - if (op == NULL_TREE) - continue; - if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt))) - gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue); - else if (i == 2 - && is_gimple_assign (stmt) - && num_ops == 2 - && get_gimple_rhs_class (gimple_expr_code (stmt)) - == GIMPLE_SINGLE_RHS) - gimplify_expr (&op, &pre, NULL, - rhs_predicate_for (gimple_assign_lhs (stmt)), - fb_rvalue); - else if (i == 2 && is_gimple_call (stmt)) - { - if (TREE_CODE (op) == FUNCTION_DECL) - continue; - gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue); - } - else - gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue); - gimple_set_op (stmt, i - 1, op); - } - - lhs = gimple_get_lhs (stmt); - /* If the LHS changed it in a way that requires a simple RHS, - create temporary. */ - if (lhs && !is_gimple_reg (lhs)) - { - bool need_temp = false; - - if (is_gimple_assign (stmt) - && num_ops == 2 - && get_gimple_rhs_class (gimple_expr_code (stmt)) - == GIMPLE_SINGLE_RHS) - gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL, - rhs_predicate_for (gimple_assign_lhs (stmt)), - fb_rvalue); - else if (is_gimple_reg (lhs)) - { - if (is_gimple_reg_type (TREE_TYPE (lhs))) - { - if (is_gimple_call (stmt)) - { - i = gimple_call_flags (stmt); - if ((i & ECF_LOOPING_CONST_OR_PURE) - || !(i & (ECF_CONST | ECF_PURE))) - need_temp = true; - } - if (stmt_can_throw_internal (stmt)) - need_temp = true; - } - } - else - { - if (is_gimple_reg_type (TREE_TYPE (lhs))) - need_temp = true; - else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode) - { - if (is_gimple_call (stmt)) - { - tree fndecl = gimple_call_fndecl (stmt); - - if (!aggregate_value_p (TREE_TYPE (lhs), fndecl) - && !(fndecl && DECL_RESULT (fndecl) - && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))) - need_temp = true; - } - else - need_temp = true; - } - } - if (need_temp) - { - tree temp = create_tmp_reg (TREE_TYPE (lhs), NULL); - if (gimple_in_ssa_p (cfun)) - temp = make_ssa_name (temp, NULL); - gimple_set_lhs (stmt, temp); - post_stmt = gimple_build_assign (lhs, temp); - } - } - break; - } - - if (!gimple_seq_empty_p (pre)) - gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT); - if (post_stmt) - gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT); - - pop_gimplify_context (NULL); -} - -/* Expand EXPR to list of gimple statements STMTS. GIMPLE_TEST_F specifies - the predicate that will hold for the result. If VAR is not NULL, make the - base variable of the final destination be VAR if suitable. */ - -tree -force_gimple_operand_1 (tree expr, gimple_seq *stmts, - gimple_predicate gimple_test_f, tree var) -{ - enum gimplify_status ret; - struct gimplify_ctx gctx; - location_t saved_location; - - *stmts = NULL; - - /* gimple_test_f might be more strict than is_gimple_val, make - sure we pass both. Just checking gimple_test_f doesn't work - because most gimple predicates do not work recursively. */ - if (is_gimple_val (expr) - && (*gimple_test_f) (expr)) - return expr; - - push_gimplify_context (&gctx); - gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun); - gimplify_ctxp->allow_rhs_cond_expr = true; - saved_location = input_location; - input_location = UNKNOWN_LOCATION; - - if (var) - { - if (gimplify_ctxp->into_ssa - && is_gimple_reg (var)) - var = make_ssa_name (var, NULL); - expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr); - } - - if (TREE_CODE (expr) != MODIFY_EXPR - && TREE_TYPE (expr) == void_type_node) - { - gimplify_and_add (expr, stmts); - expr = NULL_TREE; - } - else - { - ret = gimplify_expr (&expr, stmts, NULL, gimple_test_f, fb_rvalue); - gcc_assert (ret != GS_ERROR); - } - - input_location = saved_location; - pop_gimplify_context (NULL); - - return expr; -} - -/* Expand EXPR to list of gimple statements STMTS. If SIMPLE is true, - force the result to be either ssa_name or an invariant, otherwise - just force it to be a rhs expression. If VAR is not NULL, make the - base variable of the final destination be VAR if suitable. */ - -tree -force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var) -{ - return force_gimple_operand_1 (expr, stmts, - simple ? is_gimple_val : is_gimple_reg_rhs, - var); -} - -/* Invoke force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F - and VAR. If some statements are produced, emits them at GSI. - If BEFORE is true. the statements are appended before GSI, otherwise - they are appended after it. M specifies the way GSI moves after - insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values). */ - -tree -force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr, - gimple_predicate gimple_test_f, - tree var, bool before, - enum gsi_iterator_update m) -{ - gimple_seq stmts; - - expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var); - - if (!gimple_seq_empty_p (stmts)) - { - if (before) - gsi_insert_seq_before (gsi, stmts, m); - else - gsi_insert_seq_after (gsi, stmts, m); - } - - return expr; -} - -/* Invoke force_gimple_operand_1 for EXPR with parameter VAR. - If SIMPLE is true, force the result to be either ssa_name or an invariant, - otherwise just force it to be a rhs expression. If some statements are - produced, emits them at GSI. If BEFORE is true, the statements are - appended before GSI, otherwise they are appended after it. M specifies - the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING - are the usual values). */ - -tree -force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr, - bool simple_p, tree var, bool before, - enum gsi_iterator_update m) -{ - return force_gimple_operand_gsi_1 (gsi, expr, - simple_p - ? is_gimple_val : is_gimple_reg_rhs, - var, before, m); -} - /* Return a dummy expression of type TYPE in order to keep going after an error. */ @@ -8991,3 +8701,32 @@ gimplify_assign (tree dst, tree src, gimple_seq *seq_p) return gimple_seq_last_stmt (*seq_p); } +inline hashval_t +gimplify_hasher::hash (const value_type *p) +{ + tree t = p->val; + return iterative_hash_expr (t, 0); +} + +inline bool +gimplify_hasher::equal (const value_type *p1, const compare_type *p2) +{ + tree t1 = p1->val; + tree t2 = p2->val; + enum tree_code code = TREE_CODE (t1); + + if (TREE_CODE (t2) != code + || TREE_TYPE (t1) != TREE_TYPE (t2)) + return false; + + if (!operand_equal_p (t1, t2, 0)) + return false; + +#ifdef ENABLE_CHECKING + /* Only allow them to compare equal if they also hash equal; otherwise + results are nondeterminate, and we fail bootstrap comparison. */ + gcc_assert (hash (p1) == hash (p2)); +#endif + + return true; +} |