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.