{
EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- EDGE_SUCC (cond_block, 0)->probability = REG_BR_PROB_BASE;
- EDGE_SUCC (cond_block, 0)->count += EDGE_SUCC (cond_block, 1)->count;
+ EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
}
EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
EDGE_SUCC (cond_block, 1)->flags
&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- EDGE_SUCC (cond_block, 1)->probability = REG_BR_PROB_BASE;
- EDGE_SUCC (cond_block, 1)->count += EDGE_SUCC (cond_block, 0)->count;
+ EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
}
}
replace_phi_edge_with_variable (cond_bb, e1, phi, new_var);
- reset_flow_sensitive_info_in_bb (cond_bb);
/* Note that we optimized this PHI. */
return true;
{
/* For arg = &p->i transform it to p, if possible. */
tree rhs1 = gimple_assign_rhs1 (stmt);
- HOST_WIDE_INT offset;
+ poly_int64 offset;
tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0),
&offset);
if (tem
&& TREE_CODE (tem) == MEM_REF
- && (mem_ref_offset (tem) + offset) == 0)
+ && known_eq (mem_ref_offset (tem) + offset, 0))
{
*arg = TREE_OPERAND (tem, 0);
return true;
}
- /* Now optimize (x != 0) ? x + y : y to just y.
- The following condition is too restrictive, there can easily be another
- stmt in middle_bb, for instance a CONVERT_EXPR for the second argument. */
- gimple *assign = last_and_only_stmt (middle_bb);
- if (!assign || gimple_code (assign) != GIMPLE_ASSIGN
+ /* Now optimize (x != 0) ? x + y : y to just x + y. */
+ gsi = gsi_last_nondebug_bb (middle_bb);
+ if (gsi_end_p (gsi))
+ return 0;
+
+ gimple *assign = gsi_stmt (gsi);
+ if (!is_gimple_assign (assign)
|| gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS
|| (!INTEGRAL_TYPE_P (TREE_TYPE (arg0))
&& !POINTER_TYPE_P (TREE_TYPE (arg0))))
if (!gimple_seq_empty_p (phi_nodes (middle_bb)))
return 0;
+ /* Allow up to 2 cheap preparation statements that prepare argument
+ for assign, e.g.:
+ if (y_4 != 0)
+ goto <bb 3>;
+ else
+ goto <bb 4>;
+ <bb 3>:
+ _1 = (int) y_4;
+ iftmp.0_6 = x_5(D) r<< _1;
+ <bb 4>:
+ # iftmp.0_2 = PHI <iftmp.0_6(3), x_5(D)(2)>
+ or:
+ if (y_3(D) == 0)
+ goto <bb 4>;
+ else
+ goto <bb 3>;
+ <bb 3>:
+ y_4 = y_3(D) & 31;
+ _1 = (int) y_4;
+ _6 = x_5(D) r<< _1;
+ <bb 4>:
+ # _2 = PHI <x_5(D)(2), _6(3)> */
+ gimple *prep_stmt[2] = { NULL, NULL };
+ int prep_cnt;
+ for (prep_cnt = 0; ; prep_cnt++)
+ {
+ gsi_prev_nondebug (&gsi);
+ if (gsi_end_p (gsi))
+ break;
+
+ gimple *g = gsi_stmt (gsi);
+ if (gimple_code (g) == GIMPLE_LABEL)
+ break;
+
+ if (prep_cnt == 2 || !is_gimple_assign (g))
+ return 0;
+
+ tree lhs = gimple_assign_lhs (g);
+ tree rhs1 = gimple_assign_rhs1 (g);
+ use_operand_p use_p;
+ gimple *use_stmt;
+ if (TREE_CODE (lhs) != SSA_NAME
+ || TREE_CODE (rhs1) != SSA_NAME
+ || !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
+ || !single_imm_use (lhs, &use_p, &use_stmt)
+ || use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign))
+ return 0;
+ switch (gimple_assign_rhs_code (g))
+ {
+ CASE_CONVERT:
+ break;
+ case PLUS_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (TREE_CODE (gimple_assign_rhs2 (g)) != INTEGER_CST)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ prep_stmt[prep_cnt] = g;
+ }
+
/* Only transform if it removes the condition. */
if (!single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)), e0, e1))
return 0;
if (optimize_bb_for_speed_p (cond_bb)
/* The special case is useless if it has a low probability. */
&& profile_status_for_fn (cfun) != PROFILE_ABSENT
- && EDGE_PRED (middle_bb, 0)->probability < PROB_EVEN
+ && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even ()
/* If assign is cheap, there is no point avoiding it. */
- && estimate_num_insns (assign, &eni_time_weights)
+ && estimate_num_insns (bb_seq (middle_bb), &eni_time_weights)
>= 3 * estimate_num_insns (cond, &eni_time_weights))
return 0;
tree cond_lhs = gimple_cond_lhs (cond);
tree cond_rhs = gimple_cond_rhs (cond);
+ /* Propagate the cond_rhs constant through preparation stmts,
+ make sure UB isn't invoked while doing that. */
+ for (int i = prep_cnt - 1; i >= 0; --i)
+ {
+ gimple *g = prep_stmt[i];
+ tree grhs1 = gimple_assign_rhs1 (g);
+ if (!operand_equal_for_phi_arg_p (cond_lhs, grhs1))
+ return 0;
+ cond_lhs = gimple_assign_lhs (g);
+ cond_rhs = fold_convert (TREE_TYPE (grhs1), cond_rhs);
+ if (TREE_CODE (cond_rhs) != INTEGER_CST
+ || TREE_OVERFLOW (cond_rhs))
+ return 0;
+ if (gimple_assign_rhs_class (g) == GIMPLE_BINARY_RHS)
+ {
+ cond_rhs = int_const_binop (gimple_assign_rhs_code (g), cond_rhs,
+ gimple_assign_rhs2 (g));
+ if (TREE_OVERFLOW (cond_rhs))
+ return 0;
+ }
+ cond_rhs = fold_convert (TREE_TYPE (cond_lhs), cond_rhs);
+ if (TREE_CODE (cond_rhs) != INTEGER_CST
+ || TREE_OVERFLOW (cond_rhs))
+ return 0;
+ }
+
if (((code == NE_EXPR && e1 == false_edge)
|| (code == EQ_EXPR && e1 == true_edge))
&& arg0 == lhs
cond_rhs, false, rhs2))))))
{
gsi = gsi_for_stmt (cond);
+ /* Moving ASSIGN might change VR of lhs, e.g. when moving u_6
+ def-stmt in:
+ if (n_5 != 0)
+ goto <bb 3>;
+ else
+ goto <bb 4>;
+
+ <bb 3>:
+ # RANGE [0, 4294967294]
+ u_6 = n_5 + 4294967295;
+
+ <bb 4>:
+ # u_3 = PHI <u_6(3), 4294967295(2)> */
+ reset_flow_sensitive_info (lhs);
if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
{
- /* Moving ASSIGN might change VR of lhs, e.g. when moving u_6
- def-stmt in:
- if (n_5 != 0)
- goto <bb 3>;
- else
- goto <bb 4>;
-
- <bb 3>:
- # RANGE [0, 4294967294]
- u_6 = n_5 + 4294967295;
-
- <bb 4>:
- # u_3 = PHI <u_6(3), 4294967295(2)> */
- SSA_NAME_RANGE_INFO (lhs) = NULL;
/* If available, we can use VR of phi result at least. */
tree phires = gimple_phi_result (phi);
struct range_info_def *phires_range_info
duplicate_ssa_name_range_info (lhs, SSA_NAME_RANGE_TYPE (phires),
phires_range_info);
}
- gimple_stmt_iterator gsi_from = gsi_for_stmt (assign);
+ gimple_stmt_iterator gsi_from;
+ for (int i = prep_cnt - 1; i >= 0; --i)
+ {
+ tree plhs = gimple_assign_lhs (prep_stmt[i]);
+ reset_flow_sensitive_info (plhs);
+ gsi_from = gsi_for_stmt (prep_stmt[i]);
+ gsi_move_before (&gsi_from, &gsi);
+ }
+ gsi_from = gsi_for_stmt (assign);
gsi_move_before (&gsi_from, &gsi);
replace_phi_edge_with_variable (cond_bb, e1, phi, lhs);
return 2;
if (cmp == LT_EXPR)
{
bool overflow;
- wide_int alt = wi::sub (larger, 1, TYPE_SIGN (TREE_TYPE (larger)),
+ wide_int alt = wi::sub (wi::to_wide (larger), 1,
+ TYPE_SIGN (TREE_TYPE (larger)),
&overflow);
if (! overflow)
alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt);
else
{
bool overflow;
- wide_int alt = wi::add (larger, 1, TYPE_SIGN (TREE_TYPE (larger)),
+ wide_int alt = wi::add (wi::to_wide (larger), 1,
+ TYPE_SIGN (TREE_TYPE (larger)),
&overflow);
if (! overflow)
alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt);
if (cmp == GT_EXPR)
{
bool overflow;
- wide_int alt = wi::add (smaller, 1, TYPE_SIGN (TREE_TYPE (smaller)),
+ wide_int alt = wi::add (wi::to_wide (smaller), 1,
+ TYPE_SIGN (TREE_TYPE (smaller)),
&overflow);
if (! overflow)
alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt);
else
{
bool overflow;
- wide_int alt = wi::sub (smaller, 1, TYPE_SIGN (TREE_TYPE (smaller)),
+ wide_int alt = wi::sub (wi::to_wide (smaller), 1,
+ TYPE_SIGN (TREE_TYPE (smaller)),
&overflow);
if (! overflow)
alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt);
/* Move the statement from the middle block. */
gsi = gsi_last_bb (cond_bb);
gsi_from = gsi_last_nondebug_bb (middle_bb);
+ reset_flow_sensitive_info (SINGLE_SSA_TREE_OPERAND (gsi_stmt (gsi_from),
+ SSA_OP_DEF));
gsi_move_before (&gsi_from, &gsi);
}
gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
replace_phi_edge_with_variable (cond_bb, e1, phi, result);
- reset_flow_sensitive_info_in_bb (cond_bb);
return true;
}
}
replace_phi_edge_with_variable (cond_bb, e1, phi, result);
- reset_flow_sensitive_info_in_bb (cond_bb);
/* Note that we optimized this PHI. */
return true;
gsi_remove (&gsi, true);
release_defs (assign);
+ /* Make both store and load use alias-set zero as we have to
+ deal with the case of the store being a conditional change
+ of the dynamic type. */
+ lhs = unshare_expr (lhs);
+ tree *basep = &lhs;
+ while (handled_component_p (*basep))
+ basep = &TREE_OPERAND (*basep, 0);
+ if (TREE_CODE (*basep) == MEM_REF
+ || TREE_CODE (*basep) == TARGET_MEM_REF)
+ TREE_OPERAND (*basep, 1)
+ = fold_convert (ptr_type_node, TREE_OPERAND (*basep, 1));
+ else
+ *basep = build2 (MEM_REF, TREE_TYPE (*basep),
+ build_fold_addr_expr (*basep),
+ build_zero_cst (ptr_type_node));
+
/* 2) Insert a load from the memory of the store to the temporary
on the edge which did not contain the store. */
- lhs = unshare_expr (lhs);
name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
new_stmt = gimple_build_assign (name, lhs);
gimple_set_location (new_stmt, locus);