This makes us treat &a == &a in operand_equal_p in case the addresses have TREE_CONSTANT set, even in the case if a has TREE_SIDE_EFFECTS set (such as for volatile vars). Simply special-casing DECLs in the ADDR_EXPR case wouldn't handle &a.b == &a.b.
I think it's important that operand_equal_p (a, a, 0) holds if a holds is_gimple_min_invariant (), as we generally compare constants using it. We could devise some other solution, for example introducing a possibly cheaper gimple_val_equal_p () predicate that only handles operands that satisfy is_gimple_val (). Any comments? The testcase is too large, I didn't sofar try to construct one artificially. The issue is latent at least on the 4.6 branch. Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2011-04-20 Richard Guenther <rguent...@suse.de> * tree.h (OEP_CONSTANT_ADDRESS_OF): New operand_equal_flag. * fold-const.c (operand_equal_p): For TREE_CONSTANT ADDR_EXPRs compare the operands with OEP_CONSTANT_ADDRESS_OF. Treat trees with TREE_SIDE_EFFECTS equal when OEP_CONSTANT_ADDRESS_OF is set. Index: gcc/tree.h =================================================================== *** gcc/tree.h (revision 172759) --- gcc/tree.h (working copy) *************** extern tree fold_fma (location_t, tree, *** 5118,5124 **** enum operand_equal_flag { OEP_ONLY_CONST = 1, ! OEP_PURE_SAME = 2 }; extern int operand_equal_p (const_tree, const_tree, unsigned int); --- 5118,5125 ---- enum operand_equal_flag { OEP_ONLY_CONST = 1, ! OEP_PURE_SAME = 2, ! OEP_CONSTANT_ADDRESS_OF = 4 }; extern int operand_equal_p (const_tree, const_tree, unsigned int); Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 172759) --- gcc/fold-const.c (working copy) *************** operand_equal_p (const_tree arg0, const_ *** 2475,2483 **** equal if they have no side effects. If we have two identical expressions with side effects that should be treated the same due to the only side effects being identical SAVE_EXPR's, that will ! be detected in the recursive calls below. */ if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST) && (TREE_CODE (arg0) == SAVE_EXPR || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1)))) return 1; --- 2475,2486 ---- equal if they have no side effects. If we have two identical expressions with side effects that should be treated the same due to the only side effects being identical SAVE_EXPR's, that will ! be detected in the recursive calls below. ! If we are taking an invariant address of two identical objects ! they are necessarily equal as well. */ if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST) && (TREE_CODE (arg0) == SAVE_EXPR + || (flags & OEP_CONSTANT_ADDRESS_OF) || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1)))) return 1; *************** operand_equal_p (const_tree arg0, const_ *** 2540,2546 **** case ADDR_EXPR: return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), ! 0); default: break; } --- 2543,2550 ---- case ADDR_EXPR: return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), ! TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1) ! ? OEP_CONSTANT_ADDRESS_OF : 0); default: break; }