This moves &X ==/!= ptr comparison folding which triggers surprisingly often.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2015-06-29 Richard Biener <rguent...@suse.de> * genmatch.c (add_operator): Treat ADDR_EXPR as atom. * fold-const.c (fold_binary_loc): Move &A - &B simplification via ptr_difference_const ... * match.pd: ... here. When matching (X ^ Y) == Y also match with swapped operands. Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 225007) +++ gcc/genmatch.c (working copy) @@ -324,6 +324,9 @@ add_operator (enum tree_code code, const /* And allow CONSTRUCTOR for vector initializers. */ && !(code == CONSTRUCTOR)) return; + /* Treat ADDR_EXPR as atom, thus don't allow matching its operand. */ + if (code == ADDR_EXPR) + nargs = 0; operator_id *op = new operator_id (code, id, nargs, tcc); id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); if (*slot) Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 225007) +++ gcc/fold-const.c (working copy) @@ -10618,16 +10562,6 @@ fold_binary_loc (location_t loc, fold_convert_loc (loc, type, negate_expr (arg1))); - /* Try folding difference of addresses. */ - { - HOST_WIDE_INT diff; - - if ((TREE_CODE (arg0) == ADDR_EXPR - || TREE_CODE (arg1) == ADDR_EXPR) - && ptr_difference_const (arg0, arg1, &diff)) - return build_int_cst_type (type, diff); - } - /* Fold &a[i] - &a[j] to i-j. */ if (TREE_CODE (arg0) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF Index: gcc/match.pd =================================================================== *** gcc/match.pd (revision 225007) --- gcc/match.pd (working copy) *************** (define_operator_list swapped_tcc_compar *** 545,550 **** --- 545,565 ---- (with { tree algn = wide_int_to_tree (TREE_TYPE (@0), wi::bit_not (@1)); } (bit_and @0 { algn; }))) + /* Try folding difference of addresses. */ + (simplify + (minus (convert ADDR_EXPR@0) (convert @1)) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (with { HOST_WIDE_INT diff; } + (if (ptr_difference_const (@0, @1, &diff)) + { build_int_cst_type (type, diff); })))) + (simplify + (minus (convert @0) (convert ADDR_EXPR@1)) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (with { HOST_WIDE_INT diff; } + (if (ptr_difference_const (@0, @1, &diff)) + { build_int_cst_type (type, diff); })))) + + /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) *************** (define_operator_list swapped_tcc_compar *** 1229,1235 **** /* (X ^ Y) == Y becomes X == 0. Likewise (X ^ Y) == X becomes Y == 0. */ (simplify ! (cmp (bit_xor:c @0 @1) @0) (cmp @1 { build_zero_cst (TREE_TYPE (@1)); })) /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */ --- 1244,1250 ---- /* (X ^ Y) == Y becomes X == 0. Likewise (X ^ Y) == X becomes Y == 0. */ (simplify ! (cmp:c (bit_xor:c @0 @1) @0) (cmp @1 { build_zero_cst (TREE_TYPE (@1)); })) /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */