public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-8078] phiopt: Optimize (x != cst1 ? x : cst2) != cst3 [PR104639]
@ 2022-04-11 8:45 Jakub Jelinek
0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-04-11 8:45 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:a42aa68bf1ad745a6b36ab9beed1fc2e77ac3f88
commit r12-8078-ga42aa68bf1ad745a6b36ab9beed1fc2e77ac3f88
Author: Jakub Jelinek <jakub@redhat.com>
Date: Mon Apr 11 10:44:28 2022 +0200
phiopt: Optimize (x != cst1 ? x : cst2) != cst3 [PR104639]
Here is an attempt to resolve a P1 regression, where due to threading
changes we no longer optimize
bool foo(int i) {
while (i == 4)
i += 2;
return i;
}
to just return i != 0; by enhancing the phiopt value_replacement
optimization. Normally it will optimize x != cst1 ? x : cst1 to x.
Here we extend it to also optimize x != cst1 ? x : cst2 to x if
it (phi result) has a single immediate use which is a comparison
with some INTEGER_CST cst3 and we can prove that we don't care
whether x is cst1 or cst2 because both compare the same against cst3.
2022-04-11 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/104639
* tree-ssa-phiopt.cc: Include tree-ssa-propagate.h.
(value_replacement): Optimize (x != cst1 ? x : cst2) != cst3
into x != cst3.
* gcc.dg/tree-ssa/pr104639-1.c: New test.
* gcc.dg/tree-ssa/pr104639-2.c: New test.
Diff:
---
gcc/testsuite/gcc.dg/tree-ssa/pr104639-1.c | 13 +++
gcc/testsuite/gcc.dg/tree-ssa/pr104639-2.c | 54 ++++++++++++
gcc/tree-ssa-phiopt.cc | 133 +++++++++++++++++++++++++++--
3 files changed, 195 insertions(+), 5 deletions(-)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr104639-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr104639-1.c
new file mode 100644
index 00000000000..183fa374afc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr104639-1.c
@@ -0,0 +1,13 @@
+/* PR tree-optimization/104639 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "PHI <" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "i_\[0-9]*\\\(D\\\) != 0;" 1 "optimized" } } */
+
+_Bool
+foo (int i)
+{
+ while (i == 4)
+ i += 2;
+ return i;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr104639-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr104639-2.c
new file mode 100644
index 00000000000..e2511470675
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr104639-2.c
@@ -0,0 +1,54 @@
+/* PR tree-optimization/104639 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-pre -g -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "PHI <" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "x_\[0-9]*\\\(D\\\) != 42;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "y_\[0-9]*\\\(D\\\) > 6;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "z_\[0-9]*\\\(D\\\) > 9;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "u_\[0-9]*\\\(D\\\) <= 7;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "v_\[0-9]*\\\(D\\\) <= 42;" 1 "optimized" } } */
+
+int
+f1 (int x)
+{
+ if (x == 4)
+ x = 6;
+ int xd = x;
+ return x != 42;
+}
+
+int
+f2 (int y)
+{
+ if (y == 4)
+ y = 6;
+ int yd = y;
+ return y > 6;
+}
+
+int
+f3 (int z)
+{
+ if (z == 4)
+ z = 6;
+ int zd = z;
+ return z >= 10;
+}
+
+int
+f4 (int u)
+{
+ if (u == 4)
+ u = 6;
+ int ud = u;
+ return u < 8;
+}
+
+int
+f5 (int v)
+{
+ if (v == 4)
+ v = 6;
+ int vd = v;
+ return v <= 42;
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 4a0c9dd656d..00c8f399e4c 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-range.h"
#include "gimple-match.h"
#include "dbgcnt.h"
+#include "tree-ssa-propagate.h"
static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
@@ -1327,7 +1328,17 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
We now need to verify that the two arguments in the PHI node match
the two arguments to the equality comparison. */
- if (operand_equal_for_value_replacement (arg0, arg1, &code, cond))
+ bool equal_p = operand_equal_for_value_replacement (arg0, arg1, &code, cond);
+ bool maybe_equal_p = false;
+ if (!equal_p
+ && empty_or_with_defined_p
+ && TREE_CODE (gimple_cond_rhs (cond)) == INTEGER_CST
+ && (operand_equal_for_phi_arg_p (gimple_cond_lhs (cond), arg0)
+ ? TREE_CODE (arg1) == INTEGER_CST
+ : (operand_equal_for_phi_arg_p (gimple_cond_lhs (cond), arg1)
+ && TREE_CODE (arg0) == INTEGER_CST)))
+ maybe_equal_p = true;
+ if (equal_p || maybe_equal_p)
{
edge e;
tree arg;
@@ -1358,11 +1369,123 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
&& single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)),
e0, e1) == phi)
{
- replace_phi_edge_with_variable (cond_bb, e1, phi, arg);
- /* Note that we optimized this PHI. */
- return 2;
+ use_operand_p use_p;
+ gimple *use_stmt;
+
+ /* Even if arg0/arg1 isn't equal to second operand of cond, we
+ can optimize away the bb if we can prove it doesn't care whether
+ phi result is arg0/arg1 or second operand of cond. Consider:
+ <bb 2> [local count: 118111600]:
+ if (i_2(D) == 4)
+ goto <bb 4>; [97.00%]
+ else
+ goto <bb 3>; [3.00%]
+
+ <bb 3> [local count: 3540129]:
+
+ <bb 4> [local count: 118111600]:
+ # i_6 = PHI <i_2(D)(3), 6(2)>
+ _3 = i_6 != 0;
+ Here, carg is 4, oarg is 6, crhs is 0, and because
+ (4 != 0) == (6 != 0), we don't care if i_6 is 4 or 6, both
+ have the same outcome. So, can can optimize this to:
+ _3 = i_2(D) != 0;
+ If the single imm use of phi result >, >=, < or <=, similarly
+ we can check if both carg and oarg compare the same against
+ crhs using ccode. */
+ if (maybe_equal_p
+ && TREE_CODE (arg) != INTEGER_CST
+ && single_imm_use (gimple_phi_result (phi), &use_p, &use_stmt))
+ {
+ enum tree_code ccode = ERROR_MARK;
+ tree clhs = NULL_TREE, crhs = NULL_TREE;
+ tree carg = gimple_cond_rhs (cond);
+ tree oarg = e0 == e ? arg1 : arg0;
+ if (is_gimple_assign (use_stmt)
+ && (TREE_CODE_CLASS (gimple_assign_rhs_code (use_stmt))
+ == tcc_comparison))
+ {
+ ccode = gimple_assign_rhs_code (use_stmt);
+ clhs = gimple_assign_rhs1 (use_stmt);
+ crhs = gimple_assign_rhs2 (use_stmt);
+ }
+ else if (gimple_code (use_stmt) == GIMPLE_COND)
+ {
+ ccode = gimple_cond_code (use_stmt);
+ clhs = gimple_cond_lhs (use_stmt);
+ crhs = gimple_cond_rhs (use_stmt);
+ }
+ if (ccode != ERROR_MARK
+ && clhs == gimple_phi_result (phi)
+ && TREE_CODE (crhs) == INTEGER_CST)
+ switch (ccode)
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ if (!tree_int_cst_equal (crhs, carg)
+ && !tree_int_cst_equal (crhs, oarg))
+ equal_p = true;
+ break;
+ case GT_EXPR:
+ if (tree_int_cst_lt (crhs, carg)
+ == tree_int_cst_lt (crhs, oarg))
+ equal_p = true;
+ break;
+ case GE_EXPR:
+ if (tree_int_cst_le (crhs, carg)
+ == tree_int_cst_le (crhs, oarg))
+ equal_p = true;
+ break;
+ case LT_EXPR:
+ if (tree_int_cst_lt (carg, crhs)
+ == tree_int_cst_lt (oarg, crhs))
+ equal_p = true;
+ break;
+ case LE_EXPR:
+ if (tree_int_cst_le (carg, crhs)
+ == tree_int_cst_le (oarg, crhs))
+ equal_p = true;
+ break;
+ default:
+ break;
+ }
+ if (equal_p && MAY_HAVE_DEBUG_BIND_STMTS)
+ {
+ imm_use_iterator imm_iter;
+ tree phires = gimple_phi_result (phi);
+ tree temp = NULL_TREE;
+
+ /* Add # DEBUG D#1 => arg != carg ? arg : oarg. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, phires)
+ {
+ if (!is_gimple_debug (use_stmt))
+ continue;
+ if (temp == NULL_TREE)
+ {
+ gimple_stmt_iterator gsi
+ = gsi_after_labels (gimple_bb (phi));
+ tree type = TREE_TYPE (phires);
+ temp = build_debug_expr_decl (type);
+ tree t = build2 (NE_EXPR, boolean_type_node,
+ arg, carg);
+ t = build3 (COND_EXPR, type, t, arg, oarg);
+ gimple *g = gimple_build_debug_bind (temp, t, phi);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
+ replace_exp (use_p, temp);
+ update_stmt (use_stmt);
+ }
+ }
+ }
+ if (equal_p)
+ {
+ replace_phi_edge_with_variable (cond_bb, e1, phi, arg);
+ /* Note that we optimized this PHI. */
+ return 2;
+ }
}
- else
+ else if (equal_p)
{
if (!single_pred_p (middle_bb))
return 0;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-04-11 8:45 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-11 8:45 [gcc r12-8078] phiopt: Optimize (x != cst1 ? x : cst2) != cst3 [PR104639] Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).