From cfd719e7769fd43fbfecfc0c8f69d5f05e54169b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 5 Jan 2017 22:14:19 +0100 Subject: [PATCH] re PR tree-optimization/71016 (Redundant sign extension with conditional __builtin_clzl) PR tree-optimization/71016 * tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Pass cond_stmt to factor_out_conditional_conversion. Formatting fix. (factor_out_conditional_conversion): Add cond_stmt argument. If arg1 is INTEGER_CST, punt if new_arg0 is not any operand of cond_stmt and if arg0_def_stmt is not the only stmt in its bb. Formatting fix. * gcc.target/i386/pr71016.c: New test. * gcc.target/aarch64/pr71016.c: New test. * gcc.dg/tree-ssa/pr66726-3.c: New test. From-SVN: r244114 --- gcc/ChangeLog | 10 ++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c | 16 +++++++++ gcc/testsuite/gcc.target/aarch64/pr71016.c | 10 ++++++ gcc/testsuite/gcc.target/i386/pr71016.c | 10 ++++++ gcc/tree-ssa-phiopt.c | 41 ++++++++++++++++++---- 6 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c create mode 100644 gcc/testsuite/gcc.target/aarch64/pr71016.c create mode 100644 gcc/testsuite/gcc.target/i386/pr71016.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1114d8a5f39..8e51cee930b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2017-01-05 Jakub Jelinek + + PR tree-optimization/71016 + * tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Pass cond_stmt to + factor_out_conditional_conversion. Formatting fix. + (factor_out_conditional_conversion): Add cond_stmt argument. + If arg1 is INTEGER_CST, punt if new_arg0 is not any operand of + cond_stmt and if arg0_def_stmt is not the only stmt in its bb. + Formatting fix. + 2017-01-05 David Malcolm * Makefile.in (OBJS): Add read-md.o, read-rtl.o, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cd205bd7dd4..e99e399278d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2017-01-05 Jakub Jelinek + PR tree-optimization/71016 + * gcc.target/i386/pr71016.c: New test. + * gcc.target/aarch64/pr71016.c: New test. + * gcc.dg/tree-ssa/pr66726-3.c: New test. + PR c++/78931 * g++.dg/cpp1z/decomp19.C: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c new file mode 100644 index 00000000000..55c7a14ad19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ + +extern unsigned short mode_size[]; + +int +oof (int mode) +{ + int tem; + if (64 < mode_size[mode]) + tem = 64; + else + tem = mode_size[mode]; + return tem; +} diff --git a/gcc/testsuite/gcc.target/aarch64/pr71016.c b/gcc/testsuite/gcc.target/aarch64/pr71016.c new file mode 100644 index 00000000000..f50d69395ce --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr71016.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/71016 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not "sxtw" } } */ + +long int +foo (long int i) +{ + return i == 0 ? 17 : __builtin_clzl (i); +} diff --git a/gcc/testsuite/gcc.target/i386/pr71016.c b/gcc/testsuite/gcc.target/i386/pr71016.c new file mode 100644 index 00000000000..d5a89ebd393 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr71016.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/71016 */ +/* { dg-do compile { target lp64 } } */ +/* { dg-options "-O2 -mlzcnt" } */ +/* { dg-final { scan-assembler-not "cltq" } } */ + +long int +foo (long int i) +{ + return i == 0 ? 17 : __builtin_clzl (i); +} diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 259f6fe3e39..07a226e149c 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -49,7 +49,8 @@ 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 gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree); +static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, + gimple *); static int value_replacement (basic_block, basic_block, edge, edge, gimple *, tree, tree); static bool minmax_replacement (basic_block, basic_block, @@ -233,7 +234,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads) continue; } else if (do_hoist_loads - && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest) + && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest) { basic_block bb3 = EDGE_SUCC (bb1, 0)->dest; @@ -313,7 +314,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads) gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); gphi *newphi = factor_out_conditional_conversion (e1, e2, phi, - arg0, arg1); + arg0, arg1, + cond_stmt); if (newphi != NULL) { phi = newphi; @@ -402,11 +404,12 @@ replace_phi_edge_with_variable (basic_block cond_block, /* 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. Return the newly-created PHI, if any. */ + to the result of PHI stmt. COND_STMT is the controlling predicate. + Return the newly-created PHI, if any. */ static gphi * factor_out_conditional_conversion (edge e0, edge e1, gphi *phi, - tree arg0, tree arg1) + tree arg0, tree arg1, gimple *cond_stmt) { gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt; tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE; @@ -472,7 +475,31 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi, && 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); + { + /* For the INTEGER_CST case, we are just moving the + conversion from one place to another, which can often + hurt as the conversion moves further away from the + statement that computes the value. So, perform this + only if new_arg0 is an operand of COND_STMT, or + if arg0_def_stmt is the only non-debug stmt in + its basic block, because then it is possible this + could enable further optimizations (minmax replacement + etc.). See PR71016. */ + if (new_arg0 != gimple_cond_lhs (cond_stmt) + && new_arg0 != gimple_cond_rhs (cond_stmt) + && gimple_bb (arg0_def_stmt) == e0->src) + { + gsi = gsi_for_stmt (arg0_def_stmt); + gsi_prev_nondebug (&gsi); + if (!gsi_end_p (gsi)) + return NULL; + gsi = gsi_for_stmt (arg0_def_stmt); + gsi_next_nondebug (&gsi); + if (!gsi_end_p (gsi)) + return NULL; + } + new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1); + } else return NULL; } @@ -524,7 +551,7 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi, /* 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); + 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); -- 2.30.2