On Wed, 6 Aug 2014, Marek Polacek wrote: > As discussed in the other thread, I can't just remove folding from the > C FE and implement it on GIMPLE level, because that regressed some of > those not-really-kosher static initializers. Instead, fold-const.c > has to be taught how to fold PTR0 - (PTR1 p+ A). (Now it sounds so > obvious.) I added some test to that effect. And sorry - I'm clueless > about the PSImode targets :(. > > Bootstrapped/regtested on x86_64-linux, ok for trunk?
Ok. Thanks, Richard. > 2014-08-06 Marek Polacek <pola...@redhat.com> > > * fold-const.c (fold_binary_loc): Add folding of > (PTR0 - (PTR1 p+ A) -> (PTR0 - PTR1) - A. > c/ > * c-typeck.c (pointer_diff): Remove P - (P + CST) optimization. > testsuite/ > * gcc.dg/fold-reassoc-3.c: New test. > > diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c > index 1b664bd..998e386 100644 > --- gcc/c/c-typeck.c > +++ gcc/c/c-typeck.c > @@ -3460,7 +3460,6 @@ pointer_diff (location_t loc, tree op0, tree op1) > addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0))); > addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1))); > tree target_type = TREE_TYPE (TREE_TYPE (op0)); > - tree con0, con1, lit0, lit1; > tree orig_op1 = op1; > > /* If the operands point into different address spaces, we need to > @@ -3490,7 +3489,6 @@ pointer_diff (location_t loc, tree op0, tree op1) > else > inttype = restype; > > - > if (TREE_CODE (target_type) == VOID_TYPE) > pedwarn (loc, OPT_Wpointer_arith, > "pointer of type %<void *%> used in subtraction"); > @@ -3498,50 +3496,6 @@ pointer_diff (location_t loc, tree op0, tree op1) > pedwarn (loc, OPT_Wpointer_arith, > "pointer to a function used in subtraction"); > > - /* If the conversion to ptrdiff_type does anything like widening or > - converting a partial to an integral mode, we get a convert_expression > - that is in the way to do any simplifications. > - (fold-const.c doesn't know that the extra bits won't be needed. > - split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a > - different mode in place.) > - So first try to find a common term here 'by hand'; we want to cover > - at least the cases that occur in legal static initializers. */ > - if (CONVERT_EXPR_P (op0) > - && (TYPE_PRECISION (TREE_TYPE (op0)) > - == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0))))) > - con0 = TREE_OPERAND (op0, 0); > - else > - con0 = op0; > - if (CONVERT_EXPR_P (op1) > - && (TYPE_PRECISION (TREE_TYPE (op1)) > - == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0))))) > - con1 = TREE_OPERAND (op1, 0); > - else > - con1 = op1; > - > - if (TREE_CODE (con0) == POINTER_PLUS_EXPR) > - { > - lit0 = TREE_OPERAND (con0, 1); > - con0 = TREE_OPERAND (con0, 0); > - } > - else > - lit0 = integer_zero_node; > - > - if (TREE_CODE (con1) == POINTER_PLUS_EXPR) > - { > - lit1 = TREE_OPERAND (con1, 1); > - con1 = TREE_OPERAND (con1, 0); > - } > - else > - lit1 = integer_zero_node; > - > - if (operand_equal_p (con0, con1, 0)) > - { > - op0 = lit0; > - op1 = lit1; > - } > - > - > /* First do the subtraction as integers; > then drop through to build the divide operator. > Do not do default conversions on the minus operator > diff --git gcc/fold-const.c gcc/fold-const.c > index 7180662..8d66957 100644 > --- gcc/fold-const.c > +++ gcc/fold-const.c > @@ -10831,6 +10831,19 @@ fold_binary_loc (location_t loc, > if (tmp) > return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01); > } > + /* PTR0 - (PTR1 p+ A) -> (PTR0 - PTR1) - A, assuming PTR0 - PTR1 > + simplifies. */ > + else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR) > + { > + tree arg10 = fold_convert_loc (loc, type, > + TREE_OPERAND (arg1, 0)); > + tree arg11 = fold_convert_loc (loc, type, > + TREE_OPERAND (arg1, 1)); > + tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, arg0, > + fold_convert_loc (loc, type, arg10)); > + if (tmp) > + return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11); > + } > } > /* A - (-B) -> A + B */ > if (TREE_CODE (arg1) == NEGATE_EXPR) > diff --git gcc/testsuite/gcc.dg/fold-reassoc-3.c > gcc/testsuite/gcc.dg/fold-reassoc-3.c > index e69de29..313fb98 100644 > --- gcc/testsuite/gcc.dg/fold-reassoc-3.c > +++ gcc/testsuite/gcc.dg/fold-reassoc-3.c > @@ -0,0 +1,17 @@ > +/* { dg-do compile } */ > +/* { dg-options "-fdump-tree-original" } */ > + > +int i; > +int *p = &i; > +static __PTRDIFF_TYPE__ d = p - (p + 1); > + > +void > +foo (void) > +{ > + int *q = &i; > + static __PTRDIFF_TYPE__ e = q - (q + 1); > +} > + > +/* { dg-final { scan-tree-dump-not " - " "original" } } */ > +/* { dg-final { scan-tree-dump-not " \\\+ " "original" } } */ > +/* { dg-final { cleanup-tree-dump "orginal" } } */ > > Marek > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer