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
This commit is contained in:
Kugan Vivekanandarajah 2015-07-12 11:22:42 +00:00 committed by Kugan Vivekanandarajah
parent 7f7379f6f4
commit 9844173510
6 changed files with 246 additions and 0 deletions

View File

@ -1,3 +1,9 @@
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.

View File

@ -1,3 +1,11 @@
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>
PR c++/58734

View File

@ -0,0 +1,36 @@
/* { 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 ();
}

View File

@ -0,0 +1,19 @@
/* { 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" } } */

View File

@ -0,0 +1,15 @@
/* { 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" } } */

View File

@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
static unsigned int tree_ssa_phiopt_worker (bool, bool);
static bool conditional_replacement (basic_block, basic_block,
edge, edge, gphi *, tree, tree);
static bool factor_out_conditional_conversion (edge, edge, gphi *, tree, tree);
static int value_replacement (basic_block, basic_block,
edge, edge, gimple, tree, tree);
static bool minmax_replacement (basic_block, basic_block,
@ -323,6 +324,19 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
node. */
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. */
if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true;
@ -398,6 +412,134 @@ replace_phi_edge_with_variable (basic_block cond_block,
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
conditional replacement. Return true if the replacement is done.
Otherwise return false.
@ -2130,6 +2272,26 @@ gate_hoist_loads (void)
This pass also performs a fifth transformation of a slightly different
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
----------------------