Commit 98441735 by Kugan Vivekanandarajah Committed by Kugan Vivekanandarajah

re PR tree-optimization/66726 (missed optimization, factor conversion out of COND_EXPR)

gcc/testsuite/ChangeLog:

2015-07-12  Kugan Vivekanandarajah  <kuganv@linaro.org>
	    Jeff Law  <law@redhat.com>

	PR middle-end/66726
	* g++.dg/tree-ssa/pr66726.c: New test.
	* gcc.dg/tree-ssa/pr66726-2.c: New test.
	* gcc.dg/tree-ssa/pr66726.c: New test.


gcc/ChangeLog:

2015-07-12  Kugan Vivekanandarajah  <kuganv@linaro.org>

	PR middle-end/66726
	* tree-ssa-phiopt.c(factor_out_conditional_conversion): New function.
	tree_ssa_phiopt_worker): Call it.



Co-Authored-By: Jeff Law <law@redhat.com>

From-SVN: r225722
parent 7f7379f6
2015-07-12 Kugan Vivekanandarajah <kuganv@linaro.org> 2015-07-12 Kugan Vivekanandarajah <kuganv@linaro.org>
PR middle-end/66726
* tree-ssa-phiopt.c(factor_out_conditional_conversion): New function.
tree_ssa_phiopt_worker): Call it.
2015-07-12 Kugan Vivekanandarajah <kuganv@linaro.org>
* cse.c (cse_insn): Calculate src_eqv for ZERO_EXTRACT. * cse.c (cse_insn): Calculate src_eqv for ZERO_EXTRACT.
* emit-rtl.c (set_for_reg_notes): Allow ZERO_EXTRACT to set * emit-rtl.c (set_for_reg_notes): Allow ZERO_EXTRACT to set
REG_EQUAL note. REG_EQUAL note.
......
2015-07-12 Kugan Vivekanandarajah <kuganv@linaro.org>
Jeff Law <law@redhat.com>
PR middle-end/66726
* g++.dg/tree-ssa/pr66726.c: New test.
* gcc.dg/tree-ssa/pr66726-2.c: New test.
* gcc.dg/tree-ssa/pr66726.c: New test.
2015-07-11 Paolo Carlini <paolo.carlini@oracle.com> 2015-07-11 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58734 PR c++/58734
......
/* { dg-do run } */
/* { dg-options "-O2" } */
/* Execution test for converting VIEW_CONVERT_EXPR. */
struct cpp_num {
bool f;
};
extern cpp_num __attribute__((noinline))
foo (cpp_num lhs,
cpp_num rhs)
{
lhs.f = lhs.f || rhs.f;
return lhs;
}
cpp_num lhs, rhs, r;
int main ()
{
lhs.f = false;
rhs.f = false;
r = foo (lhs, rhs);
if (r.f)
__builtin_abort ();
lhs.f = false;
rhs.f = true;
r = foo (lhs, rhs);
if (!r.f)
__builtin_abort ();
}
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-phiopt1-details" } */
extern void bar (char, char);
int
foo (char b)
{
char a;
a = b;
b = 'b';
bar (a, b);
b = a;
if (b == 0)
a++;
return a + b;
}
/* { dg-final { scan-tree-dump-times "factor conversion out" 0 "phiopt1" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-phiopt1-details" } */
extern unsigned short mode_size[];
int
oof (int mode)
{
return (64 < mode_size[mode] ? 64 : mode_size[mode]);
}
/* { dg-final { scan-tree-dump-times "factor conversion out" 1 "phiopt1" } } */
/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */
...@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
static unsigned int tree_ssa_phiopt_worker (bool, bool); static unsigned int tree_ssa_phiopt_worker (bool, bool);
static bool conditional_replacement (basic_block, basic_block, static bool conditional_replacement (basic_block, basic_block,
edge, edge, gphi *, tree, tree); edge, edge, gphi *, tree, tree);
static bool factor_out_conditional_conversion (edge, edge, gphi *, tree, tree);
static int value_replacement (basic_block, basic_block, static int value_replacement (basic_block, basic_block,
edge, edge, gimple, tree, tree); edge, edge, gimple, tree, tree);
static bool minmax_replacement (basic_block, basic_block, static bool minmax_replacement (basic_block, basic_block,
...@@ -323,6 +324,19 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads) ...@@ -323,6 +324,19 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
node. */ node. */
gcc_assert (arg0 != NULL && arg1 != NULL); gcc_assert (arg0 != NULL && arg1 != NULL);
if (factor_out_conditional_conversion (e1, e2, phi, arg0, arg1))
{
/* factor_out_conditional_conversion may create a new PHI in
BB2 and eliminate an existing PHI in BB2. Recompute values
that may be affected by that change. */
phis = phi_nodes (bb2);
phi = single_non_singleton_phi_for_edges (phis, e1, e2);
gcc_assert (phi);
arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
gcc_assert (arg0 != NULL && arg1 != NULL);
}
/* Do the replacement of conditional if it can be done. */ /* Do the replacement of conditional if it can be done. */
if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true; cfgchanged = true;
...@@ -398,6 +412,134 @@ replace_phi_edge_with_variable (basic_block cond_block, ...@@ -398,6 +412,134 @@ replace_phi_edge_with_variable (basic_block cond_block,
bb->index); bb->index);
} }
/* PR66726: Factor conversion out of COND_EXPR. If the arguments of the PHI
stmt are CONVERT_STMT, factor out the conversion and perform the conversion
to the result of PHI stmt. */
static bool
factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
tree arg0, tree arg1)
{
gimple arg0_def_stmt = NULL, arg1_def_stmt = NULL, new_stmt;
tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE;
tree temp, result;
gphi *newphi;
gimple_stmt_iterator gsi, gsi_for_def;
source_location locus = gimple_location (phi);
enum tree_code convert_code;
/* Handle only PHI statements with two arguments. TODO: If all
other arguments to PHI are INTEGER_CST or if their defining
statement have the same unary operation, we can handle more
than two arguments too. */
if (gimple_phi_num_args (phi) != 2)
return false;
/* First canonicalize to simplify tests. */
if (TREE_CODE (arg0) != SSA_NAME)
{
std::swap (arg0, arg1);
std::swap (e0, e1);
}
if (TREE_CODE (arg0) != SSA_NAME
|| (TREE_CODE (arg1) != SSA_NAME
&& TREE_CODE (arg1) != INTEGER_CST))
return false;
/* Check if arg0 is an SSA_NAME and the stmt which defines arg0 is
a conversion. */
arg0_def_stmt = SSA_NAME_DEF_STMT (arg0);
if (!is_gimple_assign (arg0_def_stmt)
|| !gimple_assign_cast_p (arg0_def_stmt))
return false;
/* Use the RHS as new_arg0. */
convert_code = gimple_assign_rhs_code (arg0_def_stmt);
new_arg0 = gimple_assign_rhs1 (arg0_def_stmt);
if (convert_code == VIEW_CONVERT_EXPR)
new_arg0 = TREE_OPERAND (new_arg0, 0);
if (TREE_CODE (arg1) == SSA_NAME)
{
/* Check if arg1 is an SSA_NAME and the stmt which defines arg1
is a conversion. */
arg1_def_stmt = SSA_NAME_DEF_STMT (arg1);
if (!is_gimple_assign (arg1_def_stmt)
|| gimple_assign_rhs_code (arg1_def_stmt) != convert_code)
return false;
/* Use the RHS as new_arg1. */
new_arg1 = gimple_assign_rhs1 (arg1_def_stmt);
if (convert_code == VIEW_CONVERT_EXPR)
new_arg1 = TREE_OPERAND (new_arg1, 0);
}
else
{
/* If arg1 is an INTEGER_CST, fold it to new type. */
if (INTEGRAL_TYPE_P (TREE_TYPE (new_arg0))
&& int_fits_type_p (arg1, TREE_TYPE (new_arg0)))
{
if (gimple_assign_cast_p (arg0_def_stmt))
new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1);
else
return false;
}
else
return false;
}
/* If arg0/arg1 have > 1 use, then this transformation actually increases
the number of expressions evaluated at runtime. */
if (!has_single_use (arg0)
|| (arg1_def_stmt && !has_single_use (arg1)))
return false;
/* If types of new_arg0 and new_arg1 are different bailout. */
if (!types_compatible_p (TREE_TYPE (new_arg0), TREE_TYPE (new_arg1)))
return false;
/* Create a new PHI stmt. */
result = PHI_RESULT (phi);
temp = make_ssa_name (TREE_TYPE (new_arg0), NULL);
newphi = create_phi_node (temp, gimple_bb (phi));
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "PHI ");
print_generic_expr (dump_file, gimple_phi_result (phi), 0);
fprintf (dump_file,
" changed to factor conversion out from COND_EXPR.\n");
fprintf (dump_file, "New stmt with CAST that defines ");
print_generic_expr (dump_file, result, 0);
fprintf (dump_file, ".\n");
}
/* Remove the old cast(s) that has single use. */
gsi_for_def = gsi_for_stmt (arg0_def_stmt);
gsi_remove (&gsi_for_def, true);
if (arg1_def_stmt)
{
gsi_for_def = gsi_for_stmt (arg1_def_stmt);
gsi_remove (&gsi_for_def, true);
}
add_phi_arg (newphi, new_arg0, e0, locus);
add_phi_arg (newphi, new_arg1, e1, locus);
/* Create the conversion stmt and insert it. */
if (convert_code == VIEW_CONVERT_EXPR)
temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
new_stmt = gimple_build_assign (result, convert_code, temp);
gsi = gsi_after_labels (gimple_bb (phi));
gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
/* Remove he original PHI stmt. */
gsi = gsi_for_stmt (phi);
gsi_remove (&gsi, true);
return true;
}
/* The function conditional_replacement does the main work of doing the /* The function conditional_replacement does the main work of doing the
conditional replacement. Return true if the replacement is done. conditional replacement. Return true if the replacement is done.
Otherwise return false. Otherwise return false.
...@@ -2130,6 +2272,26 @@ gate_hoist_loads (void) ...@@ -2130,6 +2272,26 @@ gate_hoist_loads (void)
This pass also performs a fifth transformation of a slightly different This pass also performs a fifth transformation of a slightly different
flavor. flavor.
Factor conversion in COND_EXPR
------------------------------
This transformation factors the conversion out of COND_EXPR with
factor_out_conditional_conversion.
For example:
if (a <= CST) goto <bb 3>; else goto <bb 4>;
<bb 3>:
tmp = (int) a;
<bb 4>:
tmp = PHI <tmp, CST>
Into:
if (a <= CST) goto <bb 3>; else goto <bb 4>;
<bb 3>:
<bb 4>:
a = PHI <a, CST>
tmp = (int) a;
Adjacent Load Hoisting Adjacent Load Hoisting
---------------------- ----------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment