This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix COND_EXPR with sibcall optimization


Hi!

The following testcase is miscompiled on SPARC and I suppose lots of other
arches too with -O2.
The problem is that expand_expr [COND_EXPR] changes operand 0 of COND_EXPR
in place and if do_store_flag is successful, doesn't reset it back.
With sibcall optimization, that COND_EXPR is evaluated twice, once in
the sibcall RTL chain and once in normal RTL chain, and thus in the second
case it is not z > 0 ? b - a : b - a - 1 as it should, but
z <= 0 ? b - a : b - a - 1 instead. This call cannot be a sibling and thus
we get the wrong result.
The comment above it said that it modifies it in place because
invert_truthvalue might modify the tree pointed by its argument.
Comment above invert_truthvalue says the contrary, ie.
this never alters ARG itself and my inspection leads me to believe the
latter is true. If not, the second invert_truthvalue would have to be called
right after do_store_flag, not only in one of the branches.

Ok to commit if bootstrap succeeds?
What about 3.2 branch? It is definitely a regression from pre-sibcall gcc's.

2002-12-04  Jakub Jelinek  <jakub@redhat.com>

	* expr.c (expand_expr) [COND_EXPR]: Never modify exp in place.

	* gcc.c-torture/execute/20021204-1.c: New test.

--- gcc/testsuite/gcc.c-torture/execute/20021204-1.c.jj	2002-12-04 20:35:40.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20021204-1.c	2002-12-04 20:35:04.000000000 +0100
@@ -0,0 +1,25 @@
+/* This test was miscompiled when using sibling call optimization,
+   because X ? Y : Y - 1 optimization changed X into !X in place
+   and haven't reverted it if do_store_flag was successful, so
+   when expanding the expression the second time it was
+   !X ? Y : Y - 1.  */
+
+extern void abort (void);
+extern void exit (int);
+
+void foo (int x)
+{
+  if (x != 1)
+    abort ();
+}
+
+int z;
+
+int main (int argc, char **argv)
+{
+  char *a = "test";
+  char *b = a + 2;
+
+  foo (z > 0 ? b - a : b - a - 1);
+  exit (0);
+}
--- gcc/expr.c.jj	2002-11-28 17:07:33.000000000 +0100
+++ gcc/expr.c	2002-12-04 20:21:30.000000000 +0100
@@ -8618,6 +8618,7 @@ expand_expr (exp, target, tmode, modifie
 	    && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
 	  {
 	    rtx result;
+	    tree cond;
 	    optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
 			    ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
 			       ? addv_optab : add_optab)
@@ -8627,20 +8628,14 @@ expand_expr (exp, target, tmode, modifie
 			    : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
 			    : xor_optab);
 
-	    /* If we had X ? A : A + 1, do this as A + (X == 0).
-
-	       We have to invert the truth value here and then put it
-	       back later if do_store_flag fails.  We cannot simply copy
-	       TREE_OPERAND (exp, 0) to another variable and modify that
-	       because invert_truthvalue can modify the tree pointed to
-	       by its argument.  */
+	    /* If we had X ? A : A + 1, do this as A + (X == 0).  */
 	    if (singleton == TREE_OPERAND (exp, 1))
-	      TREE_OPERAND (exp, 0)
-		= invert_truthvalue (TREE_OPERAND (exp, 0));
+	      cond = invert_truthvalue (TREE_OPERAND (exp, 0));
+	    else
+	      cond = TREE_OPERAND (exp, 0);
 
-	    result = do_store_flag (TREE_OPERAND (exp, 0),
-				    (safe_from_p (temp, singleton, 1)
-				     ? temp : NULL_RTX),
+	    result = do_store_flag (cond, (safe_from_p (temp, singleton, 1)
+					   ? temp : NULL_RTX),
 				    mode, BRANCH_COST <= 1);
 
 	    if (result != 0 && ! integer_onep (TREE_OPERAND (binary_op, 1)))
@@ -8658,9 +8653,6 @@ expand_expr (exp, target, tmode, modifie
 		return expand_binop (mode, boptab, op1, result, temp,
 				     unsignedp, OPTAB_LIB_WIDEN);
 	      }
-	    else if (singleton == TREE_OPERAND (exp, 1))
-	      TREE_OPERAND (exp, 0)
-		= invert_truthvalue (TREE_OPERAND (exp, 0));
 	  }
 
 	do_pending_stack_adjust ();

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]