diff options
author | Andrew Hsieh <andrewhsieh@google.com> | 2014-06-18 13:00:04 -0700 |
---|---|---|
committer | Pavel Chupin <pavel.v.chupin@intel.com> | 2014-06-19 22:38:42 +0400 |
commit | f190d6284359da8ae8694b2d2e14b01602a959ed (patch) | |
tree | d4e0548e7cec02d60b1082368032e66a1c509a02 /gcc-4.8/gcc/tree-ssa-loop-im.c | |
parent | 4ff2f42147bc128ce38789071d98e55844cd3a5e (diff) | |
download | toolchain_gcc-f190d6284359da8ae8694b2d2e14b01602a959ed.tar.gz toolchain_gcc-f190d6284359da8ae8694b2d2e14b01602a959ed.tar.bz2 toolchain_gcc-f190d6284359da8ae8694b2d2e14b01602a959ed.zip |
Merge GCC 4.8.3
Change-Id: I0abe59f7705b3eccc6b2f123af75b2e30917696a
Diffstat (limited to 'gcc-4.8/gcc/tree-ssa-loop-im.c')
-rw-r--r-- | gcc-4.8/gcc/tree-ssa-loop-im.c | 88 |
1 files changed, 84 insertions, 4 deletions
diff --git a/gcc-4.8/gcc/tree-ssa-loop-im.c b/gcc-4.8/gcc/tree-ssa-loop-im.c index 78ad07330..0ae6cdb7e 100644 --- a/gcc-4.8/gcc/tree-ssa-loop-im.c +++ b/gcc-4.8/gcc/tree-ssa-loop-im.c @@ -1190,6 +1190,67 @@ determine_invariantness (void) fini_walk_dominator_tree (&walk_data); } +/* Return true if CODE is an operation that when operating on signed + integer types involves undefined behavior on overflow and the + operation can be expressed with unsigned arithmetic. */ + +static bool +arith_code_with_undefined_signed_overflow (tree_code code) +{ + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case NEGATE_EXPR: + case POINTER_PLUS_EXPR: + return true; + default: + return false; + } +} + +/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic + operation that can be transformed to unsigned arithmetic by converting + its operand, carrying out the operation in the corresponding unsigned + type and converting the result back to the original type. + + Returns a sequence of statements that replace STMT and also contain + a modified form of STMT itself. */ + +static gimple_seq +rewrite_to_defined_overflow (gimple stmt) +{ + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "rewriting stmt with undefined signed " + "overflow "); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); + } + + tree lhs = gimple_assign_lhs (stmt); + tree type = unsigned_type_for (TREE_TYPE (lhs)); + gimple_seq stmts = NULL; + for (unsigned i = 1; i < gimple_num_ops (stmt); ++i) + { + gimple_seq stmts2 = NULL; + gimple_set_op (stmt, i, + force_gimple_operand (fold_convert (type, + gimple_op (stmt, i)), + &stmts2, true, NULL_TREE)); + gimple_seq_add_seq (&stmts, stmts2); + } + gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt)); + if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) + gimple_assign_set_rhs_code (stmt, PLUS_EXPR); + gimple_seq_add_stmt (&stmts, stmt); + gimple cvt = gimple_build_assign_with_ops + (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE); + gimple_seq_add_stmt (&stmts, cvt); + + return stmts; +} + /* Hoist the statements in basic block BB out of the loops prescribed by data stored in LIM_DATA structures associated with each statement. Callback for walk_dominator_tree. */ @@ -1321,6 +1382,20 @@ move_computations_stmt (struct dom_walk_data *dw_data, } } gsi_remove (&bsi, false); + /* In case this is a stmt that is not unconditionally executed + when the target loop header is executed and the stmt may + invoke undefined integer or pointer overflow rewrite it to + unsigned arithmetic. */ + if (is_gimple_assign (stmt) + && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt))) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt))) + && arith_code_with_undefined_signed_overflow + (gimple_assign_rhs_code (stmt)) + && (!ALWAYS_EXECUTED_IN (bb) + || !(ALWAYS_EXECUTED_IN (bb) == level + || flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level)))) + gsi_insert_seq_on_edge (e, rewrite_to_defined_overflow (stmt)); + else gsi_insert_on_edge (e, stmt); } } @@ -1992,6 +2067,7 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag) gimple_stmt_iterator gsi; gimple stmt; struct prev_flag_edges *prev_edges = (struct prev_flag_edges *) ex->aux; + bool irr = ex->flags & EDGE_IRREDUCIBLE_LOOP; /* ?? Insert store after previous store if applicable. See note below. */ @@ -2006,7 +2082,8 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag) old_dest = ex->dest; new_bb = split_edge (ex); then_bb = create_empty_bb (new_bb); - if (current_loops && new_bb->loop_father) + if (irr) + then_bb->flags = BB_IRREDUCIBLE_LOOP; add_bb_to_loop (then_bb, new_bb->loop_father); gsi = gsi_start_bb (new_bb); @@ -2019,9 +2096,12 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag) stmt = gimple_build_assign (unshare_expr (mem), tmp_var); gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); - make_edge (new_bb, then_bb, EDGE_TRUE_VALUE); - make_edge (new_bb, old_dest, EDGE_FALSE_VALUE); - then_old_edge = make_edge (then_bb, old_dest, EDGE_FALLTHRU); + make_edge (new_bb, then_bb, + EDGE_TRUE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0)); + make_edge (new_bb, old_dest, + EDGE_FALSE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0)); + then_old_edge = make_edge (then_bb, old_dest, + EDGE_FALLTHRU | (irr ? EDGE_IRREDUCIBLE_LOOP : 0)); set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb); |