From: Bernd Schmidt Date: Thu, 21 Jan 2016 18:10:03 +0000 (+0000) Subject: Fix PR66178, ICE due to misexpansion of constant expressions involving labels. X-Git-Tag: basepoints/gcc-7~1418 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9776e6920dec9aa23adbdd7f0c264804c7fe6fdf;p=thirdparty%2Fgcc.git Fix PR66178, ICE due to misexpansion of constant expressions involving labels. 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. From-SVN: r232689 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab7dc3a4efa5..124708bb3e56 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2016-01-21 Bernd Schmidt + + 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. + 2016-01-21 Anton Blanchard Bill Schmidt diff --git a/gcc/expr.c b/gcc/expr.c index 8123cc2d01bc..0ce5936d3cf1 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8381,11 +8381,11 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, 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 target, machine_mode tmode, 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, diff --git a/gcc/rtl.h b/gcc/rtl.h index 515fdeeef7c3..2f5be5f010a6 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -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. */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 0e0d097f7274..71dfd33e9e39 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -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 diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 1e6e46daf7b4..39049e577a65 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2277,8 +2277,11 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 35fb4fc7762d..4ec1b309202f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-01-21 Bernd Schmidt + + PR middle-end/66178 + * gcc.dg/torture/pr66178.c: New test. + 2016-01-21 Anton Blanchard Bill Schmidt diff --git a/gcc/testsuite/gcc.dg/torture/pr66178.c b/gcc/testsuite/gcc.dg/torture/pr66178.c new file mode 100644 index 000000000000..ebc626c6f5a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr66178.c @@ -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; +}