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:
parent
7f7379f6f4
commit
9844173510
6 changed files with 246 additions and 0 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
36
gcc/testsuite/g++.dg/tree-ssa/pr66726.c
Normal file
36
gcc/testsuite/g++.dg/tree-ssa/pr66726.c
Normal 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 ();
|
||||
}
|
19
gcc/testsuite/gcc.dg/tree-ssa/pr66726-2.c
Normal file
19
gcc/testsuite/gcc.dg/tree-ssa/pr66726-2.c
Normal 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" } } */
|
15
gcc/testsuite/gcc.dg/tree-ssa/pr66726.c
Normal file
15
gcc/testsuite/gcc.dg/tree-ssa/pr66726.c
Normal 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" } } */
|
||||
|
|
@ -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
|
||||
----------------------
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue