https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119006

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
--- gcc/ipa-icf-gimple.cc.jj    2025-02-01 00:50:02.080774328 +0100
+++ gcc/ipa-icf-gimple.cc       2025-02-27 14:13:27.446426589 +0100
@@ -437,12 +437,23 @@ func_checker::compare_operand (tree t1,
                 ("compare_ao_refs failed (dependence clique difference)");
       gcc_unreachable ();
     }
+  else if (TREE_CODE (t1) == ADDR_EXPR && TREE_CODE (t2) == ADDR_EXPR)
+    {
+      /* For ADDR_EXPR compare the operands of the ADDR_EXPR rather than
+        the ADDR_EXPRs themselves.  operand_equal_p will compare the
+        operands with OEP_ADDRESS_OF and only care about the value
+        of the ADDR_EXPR, rather than e.g. types of MEM_REFs in there.
+        Some optimizations use such details though, see PR119006.  */
+      if (operand_equal_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0),
+                          OEP_MATCH_SIDE_EFFECTS))
+       return true;
+      return return_false_with_msg ("operand_equal_p failed");
+    }
   else
     {
       if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
        return true;
-      return return_false_with_msg
-                ("operand_equal_p failed");
+      return return_false_with_msg ("operand_equal_p failed");
     }
 }

fixes this.  And so does
--- gcc/ipa-icf-gimple.cc.jj    2025-02-01 00:50:02.080774328 +0100
+++ gcc/ipa-icf-gimple.cc       2025-02-27 14:24:20.815358621 +0100
@@ -440,9 +440,39 @@ func_checker::compare_operand (tree t1,
   else
     {
       if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
-       return true;
-      return return_false_with_msg
-                ("operand_equal_p failed");
+       {
+         if (TREE_CODE (t1) == ADDR_EXPR && TREE_CODE (t2) == ADDR_EXPR)
+           {
+             /* For ADDR_EXPR operand_equal_p compares the operands of
+                it using OEP_ADDRESS_OF and only care about the value
+                of the ADDR_EXPR, rather than e.g. types of MEM_REFs in
+                there.  Some optimizations use such details though, see
+                PR119006.  */
+             tree base1 = TREE_OPERAND (t1, 0);
+             tree base2 = TREE_OPERAND (t2, 0);
+             do
+               {
+                 while (handled_component_p (base1))
+                   base1 = TREE_OPERAND (base1, 0);
+                 while (handled_component_p (base2))
+                   base2 = TREE_OPERAND (base2, 0);
+                 if (!compatible_types_p (TREE_TYPE (base1),
+                                          TREE_TYPE (base2)))
+                   return return_false_with_msg ("ADDR_EXPR base type "
+                                                 "difference");
+                 if (TREE_CODE (base1) != MEM_REF
+                     || TREE_CODE (TREE_OPERAND (base1, 0)) != ADDR_EXPR
+                     || TREE_CODE (base2) != MEM_REF
+                     || TREE_CODE (TREE_OPERAND (base2, 0)) != ADDR_EXPR)
+                   break;
+                 base1 = TREE_OPERAND (TREE_OPERAND (base1, 0), 0);
+                 base2 = TREE_OPERAND (TREE_OPERAND (base2, 0), 0);
+               }
+             while (1);
+           }
+         return true;
+       }
+      return return_false_with_msg ("operand_equal_p failed");
     }
 }


Any preference between the two?  The first one is certainly safer, on the other
side might punt even e.g. on alias set differences etc. which the strlen opts
in gimple-fold.cc don't care about.

Reply via email to