gimple-vr-values:Add constraint for gimple-cond optimization

Message ID 20231123054758.28829-1-wangfeng@eswincomputing.com
State Unresolved
Headers
Series gimple-vr-values:Add constraint for gimple-cond optimization |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Feng Wang Nov. 23, 2023, 5:47 a.m. UTC
  This patch add another condition for gimple-cond optimization. Refer to
the following test case.
int foo1 (int data, int res)
{
  res = data & 0xf;
  res |= res << 4;
  if (res < 0x22)
    return 0x22;
  return res;
}
with the compilation flag "-march=rv64gc_zba_zbb -mabi=lp64d -O2",
before this patch the compilation result is
foo1:
        andi    a0,a0,15
        slliw   a5,a0,4
        addw    a3,a5,a0
        li      a4,33
        add     a0,a5,a0
        bleu    a3,a4,.L5
        ret
.L5:
        li      a0,34
        ret
after this patch the compilation result is
foo1:
        andi    a0,a0,15
        slliw   a5,a0,4
        add     a5,a5,a0
        li      a0,34
        max     a0,a5,a0
        ret
The reason is in the pass_early_vrp, the arg0 of gimple_cond
is replaced,but the PHI node still use the arg0.
The some of evrp pass logs are as follows
 gimple_assign <mult_expr, _9, _7, 17, NULL>
  gimple_assign <nop_expr, res_5, _9, NULL, NULL>
  gimple_cond <le_expr, _9, 33, NULL, NULL>
    goto <bb 3>; [INV]
  else
    goto <bb 4>; [INV]

  <bb 3> :
  // predicted unlikely by early return (on trees) predictor.

  <bb 4> :
  # gimple_phi <_2, 34(3), res_5(2)>
The arg0 of gimple_cond is replaced by _9,but the gimple_phi still
uses res_5,it will cause optimization fail of PHI node to MAX_EXPR.
So the next_use_is_phi is added to control the replacement.

gcc/ChangeLog:

        * vr-values.cc (next_use_is_phi):
        (simplify_using_ranges::simplify_casted_compare):
            add new function next_use_is_phi to control the replacement.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/zbb-min-max-04.c: New test.
---
 gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c | 14 ++++++++++++++
 gcc/vr-values.cc                                | 15 ++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c
  

Patch

diff --git a/gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c b/gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c
new file mode 100644
index 00000000000..8c3e87a35e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+int foo1 (int data, int res)
+{
+  res = data & 0xf;
+  res |= res << 4;
+  if (res < 0x22)
+    return 0x22;
+  return res;
+}
+
+/* { dg-final { scan-assembler-times "max\t" 1 } } */
\ No newline at end of file
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index ecb294131b0..1f7a727c638 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -1263,6 +1263,18 @@  simplify_using_ranges::simplify_compare_using_ranges_1 (tree_code &cond_code, tr
   return happened;
 }
 
+/* Return true if the next use of SSA_NAME is PHI node */
+bool
+next_use_is_phi (tree arg)
+{
+  use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (arg));
+  use_operand_p next = imm->next;
+  if (next && next->loc.stmt
+      && (gimple_code (next->loc.stmt) == GIMPLE_PHI))
+    return true;
+  return false;
+}
+
 /* Simplify OP0 code OP1 when OP1 is a constant and OP0 was a SSA_NAME
    defined by a type conversion. Replacing OP0 with RHS of the type conversion.
    Doing so makes the conversion dead which helps subsequent passes.  */
@@ -1305,7 +1317,8 @@  simplify_using_ranges::simplify_casted_compare (tree_code &, tree &op0, tree &op
       if (TREE_CODE (innerop) == SSA_NAME
 	  && !POINTER_TYPE_P (TREE_TYPE (innerop))
 	  && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
-	  && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
+	  && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0))
+          && !next_use_is_phi (op0))
 	{
 	  value_range vr;