diff mbox

Fixes for PR66178

Message ID 569F98C8.4090907@redhat.com
State New
Headers show

Commit Message

Bernd Schmidt Jan. 20, 2016, 2:25 p.m. UTC
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.

Comments

Jeff Law Jan. 21, 2016, 3:12 a.m. UTC | #1
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
diff mbox

Patch

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;
+}