Message ID | 569F98C8.4090907@redhat.com |
---|---|
State | New |
Headers | show |
On 01/20/2016 07:25 AM, Bernd Schmidt wrote: > PR66178 has some testcases where we construct expressions involving > additions and subtractions of label addresses, and we crash when trying > to expand these. There are two different issues here, shown by various > testcases in the PR: > > * expand_expr_real_2 can drop EXPAND_INITIALIZER and then go into > a path where it wants to gen_reg_rtx. > * simplify-rtx can turn subtractions into NOT operations in some > cases. That seems inadvisable for symbolic expressions. > > The following was bootstrapped and tested on x86_64-linux. Ok for all > branches? > > PR middle-end/66178 > * expr.c (expand_expr_real_2) [PLUS_EXPR, MINUS_EXPR]: Don't > drop EXPAND_INITIALIZER. > * rtl.h (contains_symbolic_reference_p): Declare. > * rtlanal.c (contains_symbolic_reference_p): New function. > * simplify-rtx.c (simplify_binary_operation_1): Don't turn > a subtraction into a NOT if symbolic constants are involved. > > testsuite/ > PR middle-end/66178 > gcc.dg/torture/pr66178.c: New test. > > pr66178.diff > > > > Index: gcc/rtlanal.c > =================================================================== > --- gcc/rtlanal.c (revision 232555) > +++ gcc/rtlanal.c (working copy) > @@ -6243,6 +6243,19 @@ contains_symbol_ref_p (const_rtx x) > return false; > } > > +/* Return true if RTL X contains a SYMBOL_REF or LABEL_REF. */ > + > +bool > +contains_symbolic_reference_p (const_rtx x) > +{ > + subrtx_iterator::array_type array; > + FOR_EACH_SUBRTX (iter, array, x, ALL) > + if (SYMBOL_REF_P (*iter) || GET_CODE (*iter) == LABEL_REF) > + return true; > + > + return false; > +} > + I thought we already had a routine to do this. I thought we needed it in varasm.c, but couldn't find it. Then I found contains_symbol_ref_p, but obviously that's not good enough because you need LABEL_REFs too. > /* Return true if X contains a thread-local symbol. */ > > bool > Index: gcc/simplify-rtx.c > =================================================================== > --- gcc/simplify-rtx.c (revision 232555) > +++ gcc/simplify-rtx.c (working copy) > @@ -2277,8 +2277,11 @@ simplify_binary_operation_1 (enum rtx_co > if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) > return simplify_gen_unary (NEG, mode, op1, mode); > > - /* (-1 - a) is ~a. */ > - if (trueop0 == constm1_rtx) > + /* (-1 - a) is ~a, unless the expression avoids symbolic constants, > + in which case not retaining additions and subtractions could > + cause invalid assembly to be produced. */ "avoids?" Somehow this isn't parsing well. "unless the expression has symbolic constants" or something similar is what I think you want. OK with the comment fixed. jeff
Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 232555) +++ gcc/expr.c (working copy) @@ -8381,11 +8381,11 @@ expand_expr_real_2 (sepops ops, rtx targ if it's all in the wrong mode to form part of an address. And force_operand won't know whether to sign-extend or zero-extend. */ - if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) - || mode != ptr_mode) + if (modifier != EXPAND_INITIALIZER + && (modifier != EXPAND_SUM || mode != ptr_mode)) { expand_operands (treeop0, treeop1, - subtarget, &op0, &op1, EXPAND_NORMAL); + subtarget, &op0, &op1, modifier); if (op0 == const0_rtx) return op1; if (op1 == const0_rtx) @@ -8424,8 +8424,8 @@ expand_expr_real_2 (sepops ops, rtx targ if it's all in the wrong mode to form part of an address. And force_operand won't know whether to sign-extend or zero-extend. */ - if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) - || mode != ptr_mode) + if (modifier != EXPAND_INITIALIZER + && (modifier != EXPAND_SUM || mode != ptr_mode)) goto binop; expand_operands (treeop0, treeop1, Index: gcc/rtl.h =================================================================== --- gcc/rtl.h (revision 232555) +++ gcc/rtl.h (working copy) @@ -2931,6 +2931,7 @@ extern void set_insn_deleted (rtx); extern rtx single_set_2 (const rtx_insn *, const_rtx); extern bool contains_symbol_ref_p (const_rtx); +extern bool contains_symbolic_reference_p (const_rtx); /* Handle the cheap and common cases inline for performance. */ Index: gcc/rtlanal.c =================================================================== --- gcc/rtlanal.c (revision 232555) +++ gcc/rtlanal.c (working copy) @@ -6243,6 +6243,19 @@ contains_symbol_ref_p (const_rtx x) return false; } +/* Return true if RTL X contains a SYMBOL_REF or LABEL_REF. */ + +bool +contains_symbolic_reference_p (const_rtx x) +{ + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, x, ALL) + if (SYMBOL_REF_P (*iter) || GET_CODE (*iter) == LABEL_REF) + return true; + + return false; +} + /* Return true if X contains a thread-local symbol. */ bool Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c (revision 232555) +++ gcc/simplify-rtx.c (working copy) @@ -2277,8 +2277,11 @@ simplify_binary_operation_1 (enum rtx_co if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) return simplify_gen_unary (NEG, mode, op1, mode); - /* (-1 - a) is ~a. */ - if (trueop0 == constm1_rtx) + /* (-1 - a) is ~a, unless the expression avoids symbolic constants, + in which case not retaining additions and subtractions could + cause invalid assembly to be produced. */ + if (trueop0 == constm1_rtx + && !contains_symbolic_reference_p (op1)) return simplify_gen_unary (NOT, mode, op1, mode); /* Subtracting 0 has no effect unless the mode has signed zeros Index: gcc/testsuite/gcc.dg/torture/pr66178.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr66178.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr66178.c (working copy) @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +int test(void) +{ + static int a = ((char *)&&l1-(char *)&&l2)-1; +l1: +l2: + return a; +} + +int test2(void) +{ + static int a = ((char *)&&l2-(char *)&&l3)+((char *)&&l1-(char *)&&l2); +l1: +l2: +l3: + return a; +}