From 9776e6920dec9aa23adbdd7f0c264804c7fe6fdf Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Thu, 21 Jan 2016 18:10:03 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 10 ++++++++++ gcc/expr.c | 10 +++++----- gcc/rtl.h | 1 + gcc/rtlanal.c | 13 +++++++++++++ gcc/simplify-rtx.c | 7 +++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr66178.c | 17 +++++++++++++++++ 7 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr66178.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab7dc3a4efa..124708bb3e5 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 8123cc2d01b..0ce5936d3cf 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 515fdeeef7c..2f5be5f010a 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 0e0d097f727..71dfd33e9e3 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 1e6e46daf7b..39049e577a6 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 35fb4fc7762..4ec1b309202 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 00000000000..ebc626c6f5a --- /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; +}