https://gcc.gnu.org/g:99eabac750e3e9a65b59e1a2e4466e135a028bb3

commit 99eabac750e3e9a65b59e1a2e4466e135a028bb3
Author: Alexandre Oliva <ol...@adacore.com>
Date:   Tue Dec 17 03:09:10 2024 -0300

    ifcombine field merge: do not follow a second conversion [PR118046]
    
    The testcase shows that conversions that would impact negatively the
    ifcombine field merging implementation won't always have been
    optimized out by the time we reach ifcombine.
    
    There's probably room to support multiple conversions with extra
    logic, but this workaround should avoid codegen errors until that
    logic is figured out.
    
    
    for  gcc/ChangeLog
    
            PR tree-optimization/118046
            * gimple-fold.cc (decode_field_reference): Don't follow more
            than one conversion.
    
    for  gcc/testsuite/ChangeLog
    
            PR tree-optimization/118046
            * gcc.dg/field-merge-14.c: New.

Diff:
---
 gcc/gimple-fold.cc                    | 27 +++++++++------------------
 gcc/testsuite/gcc.dg/field-merge-14.c | 26 ++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 92f02ddd7740..06913d57f8ae 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7554,13 +7554,10 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT 
*pbitsize,
      narrowing then widening casts, or vice-versa, for those that are not
      essential for the compare have already been optimized out at this
      point.  */
-  if (gimple_convert_def_p (exp, res_ops))
+  if (!outer_type && gimple_convert_def_p (exp, res_ops))
     {
-      if (!outer_type)
-       {
-         outer_type = TREE_TYPE (exp);
-         loc[0] = gimple_location (SSA_NAME_DEF_STMT (exp));
-       }
+      outer_type = TREE_TYPE (exp);
+      loc[0] = gimple_location (SSA_NAME_DEF_STMT (exp));
       exp = res_ops[0];
     }
 
@@ -7597,13 +7594,10 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT 
*pbitsize,
     }
 
   /* Another chance to drop conversions.  */
-  if (gimple_convert_def_p (exp, res_ops))
+  if (!outer_type && gimple_convert_def_p (exp, res_ops))
     {
-      if (!outer_type)
-       {
-         outer_type = TREE_TYPE (exp);
-         loc[0] = gimple_location (SSA_NAME_DEF_STMT (exp));
-       }
+      outer_type = TREE_TYPE (exp);
+      loc[0] = gimple_location (SSA_NAME_DEF_STMT (exp));
       exp = res_ops[0];
     }
 
@@ -7623,13 +7617,10 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT 
*pbitsize,
   /* Yet another chance to drop conversions.  This one is allowed to
      match a converting load, subsuming the load identification block
      below.  */
-  if (gimple_convert_def_p (exp, res_ops, load))
+  if (!outer_type && gimple_convert_def_p (exp, res_ops, load))
     {
-      if (!outer_type)
-       {
-         outer_type = TREE_TYPE (exp);
-         loc[0] = gimple_location (SSA_NAME_DEF_STMT (exp));
-       }
+      outer_type = TREE_TYPE (exp);
+      loc[0] = gimple_location (SSA_NAME_DEF_STMT (exp));
       if (*load)
        loc[3] = gimple_location (*load);
       exp = res_ops[0];
diff --git a/gcc/testsuite/gcc.dg/field-merge-14.c 
b/gcc/testsuite/gcc.dg/field-merge-14.c
new file mode 100644
index 000000000000..91d84cfebf19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/field-merge-14.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-ifcombine-details" } */
+
+/* Check that we don't get confused by multiple conversions.  */
+
+__attribute__((noipa))
+int f(int *a,int *d)
+{
+  signed char b = *a;
+  int c = b;
+  *d = c; // This store is important even if otherwise unused
+  if (c < 0 && (b&1))
+    return 1;
+  return 0;
+}
+
+int main()
+{
+  unsigned char t = 0x81;
+  int x = t, y;
+  int tt = f(&x, &y);
+  if (!tt)
+    __builtin_abort();
+}
+
+/* { dg-final { scan-tree-dump-not "optimizing" "ifcombine" } } */

Reply via email to