Patchwork 6 backports from the trunk to 4.4 branch

login
register
mail settings
Submitter Jakub Jelinek
Date July 19, 2011, 7:48 p.m.
Message ID <20110719194836.GG2687@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/105511/
State New
Headers show

Comments

Jakub Jelinek - July 19, 2011, 7:48 p.m.
On Tue, Jul 19, 2011 at 03:13:59PM +0200, Jakub Jelinek wrote:
> I've bootstrapped/regtested on 4.5 branch on x86_64-linux and i686-linux following
> patches and committed to the branch.  Will backport those that are needed
> for 4.4 also soon.

And here are the 4.4 backports, again bootstrapped/regtested on x86_64-linux
and i686-linux, committed to 4.4 branch.

	Jakub
2011-07-19  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-05-18  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/49039
	* tree-vrp.c (extract_range_from_binary_expr): For
	MIN_EXPR <~[a, b], ~[c, d]> and MAX_EXPR <~[a, b], ~[c, d]>
	return ~[MAX_EXPR <a, c>, MIN_EXPR <b, d>].

	* gcc.c-torture/execute/pr49039.c: New test.
	* gcc.dg/tree-ssa/pr49039.c: New test.
	* g++.dg/torture/pr49039.C: New test.
2011-07-19  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-05-23  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/48973
	* expr.c (expand_expr_real_1) <case LT_EXPR>: If do_store_flag
	failed and the comparison has a single bit signed type, use
	constm1_rtx instead of const1_rtx for true value.
	(do_store_flag): If TREE_TYPE (exp) is single bit signed type, disable
	single bit test optimization, pass -1 instead of 1 as last
	parameter to emit_store_flag and use constm1_rtx instead of
	const1_rtx as true value.

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

--- gcc/expr.c	(revision 174059)
+++ gcc/expr.c	(revision 174060)
@@ -9113,10 +9113,12 @@ expand_expr_real_1 (tree exp, rtx target
 	  /* If temp is constant, we can just compute the result.  */
 	  if (GET_CODE (temp) == CONST_INT)
 	    {
-	      if (INTVAL (temp) != 0)
-	        emit_move_insn (target, const1_rtx);
-	      else
+	      if (INTVAL (temp) == 0)
 	        emit_move_insn (target, const0_rtx);
+	      else if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
+		emit_move_insn (target, constm1_rtx);
+	      else
+	        emit_move_insn (target, const1_rtx);
 
 	      return target;
 	    }
@@ -9133,7 +9135,9 @@ expand_expr_real_1 (tree exp, rtx target
 	  op1 = gen_label_rtx ();
 	  emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
 				   GET_MODE (temp), unsignedp, op1);
-	  emit_move_insn (temp, const1_rtx);
+	  emit_move_insn (temp,
+			  TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)
+			  ? constm1_rtx : const1_rtx);
 	  emit_label (op1);
 	  return temp;
 	}
@@ -9757,7 +9761,7 @@ do_store_flag (tree exp, rtx target, enu
   rtx op0, op1;
   enum insn_code icode;
   rtx subtarget = target;
-  rtx result, label;
+  rtx result, label, trueval = const1_rtx;
 
   /* If this is a TRUTH_NOT_EXPR, set a flag indicating we must invert the
      result at the end.  We can't simply invert the test since it would
@@ -9887,7 +9891,9 @@ do_store_flag (tree exp, rtx target, enu
 
   if ((code == NE || code == EQ)
       && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
-      && integer_pow2p (TREE_OPERAND (arg0, 1)))
+      && integer_pow2p (TREE_OPERAND (arg0, 1))
+      && (TYPE_PRECISION (TREE_TYPE (exp)) != 1
+	  || TYPE_UNSIGNED (TREE_TYPE (exp))))
     {
       tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
       return expand_expr (fold_single_bit_test (code == NE ? NE_EXPR : EQ_EXPR,
@@ -9939,13 +9945,18 @@ do_store_flag (tree exp, rtx target, enu
   if (target == 0)
     target = gen_reg_rtx (mode);
 
+  if (TYPE_PRECISION (TREE_TYPE (exp)) == 1
+      && !TYPE_UNSIGNED (TREE_TYPE (exp)))
+    trueval = constm1_rtx;
+
   result = emit_store_flag (target, code, op0, op1,
-			    operand_mode, unsignedp, 1);
+			    operand_mode, unsignedp,
+			    trueval == const1_rtx ? 1 : -1);
 
   if (result)
     {
       if (invert)
-	result = expand_binop (mode, xor_optab, result, const1_rtx,
+	result = expand_binop (mode, xor_optab, result, trueval,
 			       result, 0, OPTAB_LIB_WIDEN);
       return result;
     }
@@ -9955,12 +9966,12 @@ do_store_flag (tree exp, rtx target, enu
       || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
     target = gen_reg_rtx (GET_MODE (target));
 
-  emit_move_insn (target, invert ? const0_rtx : const1_rtx);
+  emit_move_insn (target, invert ? const0_rtx : trueval);
   label = gen_label_rtx ();
   do_compare_rtx_and_jump (op0, op1, code, unsignedp, operand_mode, NULL_RTX,
 			   NULL_RTX, label, -1);
 
-  emit_move_insn (target, invert ? const1_rtx : const0_rtx);
+  emit_move_insn (target, invert ? trueval : const0_rtx);
   emit_label (label);
 
   return target;
--- gcc/testsuite/gcc.c-torture/execute/pr48973-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr48973-1.c	(revision 174060)
@@ -0,0 +1,20 @@
+/* PR middle-end/48973 */
+
+extern void abort (void);
+struct S { int f : 1; } s;
+int v = -1;
+
+void
+foo (unsigned int x)
+{
+  if (x != -1U)
+    abort ();
+}
+
+int
+main ()
+{
+  s.f = (v & 1) > 0;
+  foo (s.f);
+  return 0;
+}
--- gcc/testsuite/gcc.c-torture/execute/pr48973-2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr48973-2.c	(revision 174060)
@@ -0,0 +1,14 @@
+/* PR middle-end/48973 */
+
+extern void abort (void);
+struct S { int f : 1; } s;
+int v = -1;
+
+int
+main ()
+{
+  s.f = v < 0;
+  if ((unsigned int) s.f != -1U)
+    abort ();
+  return 0;
+}
2011-07-19  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-05-26  Jakub Jelinek  <jakub@redhat.com>

	PR c++/49165
	* gimplify.c (shortcut_cond_r): Don't special case
	COND_EXPRs if they have void type on one of their arms.

	* g++.dg/eh/cond5.C: New test.

--- gcc/gimplify.c	(revision 174272)
+++ gcc/gimplify.c	(revision 174273)
@@ -2570,13 +2570,18 @@ shortcut_cond_r (tree pred, tree *true_l
 			   false_label_p);
       append_to_statement_list (t, &expr);
     }
-  else if (TREE_CODE (pred) == COND_EXPR)
+  else if (TREE_CODE (pred) == COND_EXPR
+	   && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
+	   && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
     {
       /* As long as we're messing with gotos, turn if (a ? b : c) into
 	 if (a)
 	   if (b) goto yes; else goto no;
 	 else
-	   if (c) goto yes; else goto no;  */
+	   if (c) goto yes; else goto no;
+
+	 Don't do this if one of the arms has void type, which can happen
+	 in C++ when the arm is throw.  */
       expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
 		     shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
 				      false_label_p),
--- gcc/testsuite/g++.dg/eh/cond5.C	(revision 0)
+++ gcc/testsuite/g++.dg/eh/cond5.C	(revision 174273)
@@ -0,0 +1,43 @@
+// PR c++/49165
+// { dg-do run }
+
+extern "C" void abort ();
+
+int
+foo (bool x, int y)
+{
+  if (y < 10 && (x ? true : throw 1))
+    y++;
+  if (y > 20 || (x ? true : throw 2))
+    y++;
+  return y;
+}
+
+int
+main ()
+{
+  if (foo (true, 0) != 2
+      || foo (true, 10) != 11
+      || foo (false, 30) != 31)
+    abort ();
+  try
+    {
+      foo (false, 0);
+      abort ();
+    }
+  catch (int i)
+    {
+      if (i != 1)
+	abort ();
+    }
+  try
+    {
+      foo (false, 10);
+      abort ();
+    }
+  catch (int i)
+    {
+      if (i != 2)
+	abort ();
+    }
+}
2011-07-19  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-05-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/49165
	* c-common.c (c_common_truthvalue_conversion) <case COND_EXPR>: For
	C++ don't call c_common_truthvalue_conversion on void type arms.

	* g++.dg/eh/cond6.C: New test.

--- gcc/c-common.c	(revision 174349)
+++ gcc/c-common.c	(revision 174350)
@@ -3430,13 +3430,18 @@ c_common_truthvalue_conversion (location
 					       TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
-      /* Distribute the conversion into the arms of a COND_EXPR.  */
-      return fold_build3 (COND_EXPR, truthvalue_type_node,
-		TREE_OPERAND (expr, 0),
-		c_common_truthvalue_conversion (location,
-						TREE_OPERAND (expr, 1)),
-		c_common_truthvalue_conversion (location,
-						TREE_OPERAND (expr, 2)));
+      {
+	tree op1 = TREE_OPERAND (expr, 1);
+	tree op2 = TREE_OPERAND (expr, 2);
+        /* In C++ one of the arms might have void type if it is throw.  */
+	if (!VOID_TYPE_P (TREE_TYPE (op1)))
+	  op1 = c_common_truthvalue_conversion (location, op1);
+	if (!VOID_TYPE_P (TREE_TYPE (op2)))
+	  op2 = c_common_truthvalue_conversion (location, op2);
+	/* Distribute the conversion into the arms of a COND_EXPR.  */
+	return fold_build3 (COND_EXPR, truthvalue_type_node,
+			    TREE_OPERAND (expr, 0), op1, op2);
+      }
 
     CASE_CONVERT:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
--- gcc/testsuite/g++.dg/eh/cond6.C	(revision 0)
+++ gcc/testsuite/g++.dg/eh/cond6.C	(revision 174350)
@@ -0,0 +1,43 @@
+// PR c++/49165
+// { dg-do run }
+
+extern "C" void abort ();
+
+int
+foo (bool x, int y)
+{
+  if (y < 10 && (x ? 1 : throw 1))
+    y++;
+  if (y > 20 || (x ? 1 : throw 2))
+    y++;
+  return y;
+}
+
+int
+main ()
+{
+  if (foo (true, 0) != 2
+      || foo (true, 10) != 11
+      || foo (false, 30) != 31)
+    abort ();
+  try
+    {
+      foo (false, 0);
+      abort ();
+    }
+  catch (int i)
+    {
+      if (i != 1)
+	abort ();
+    }
+  try
+    {
+      foo (false, 10);
+      abort ();
+    }
+  catch (int i)
+    {
+      if (i != 2)
+	abort ();
+    }
+}
2011-07-19  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-07-04  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/49619
	* combine.c (combine_simplify_rtx): In PLUS -> IOR simplification
	pass VOIDmode as op0_mode to recursive call.

	* gcc.dg/pr49619.c: New test.

--- gcc/combine.c	(revision 175824)
+++ gcc/combine.c	(revision 175825)
@@ -5298,7 +5298,7 @@ combine_simplify_rtx (rtx x, enum machin
 	{
 	  /* Try to simplify the expression further.  */
 	  rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
-	  temp = combine_simplify_rtx (tor, mode, in_dest);
+	  temp = combine_simplify_rtx (tor, VOIDmode, in_dest);
 
 	  /* If we could, great.  If not, do not go ahead with the IOR
 	     replacement, since PLUS appears in many special purpose
--- gcc/testsuite/gcc.dg/pr49619.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr49619.c	(revision 175825)
@@ -0,0 +1,13 @@
+/* PR rtl-optimization/49619 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-fre" } */
+
+extern int a, b;
+
+void
+foo (int x)
+{
+  a = 2;
+  b = 0;
+  b = (a && ((a = 1, 0 >= b) || (short) (x + (b & x))));
+}
2011-07-19  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-07-07  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/49640
	* gimplify.c (gimplify_compound_lval): For last 2 ARRAY_*REF
	operands and last COMPONENT_REF operand call gimplify_expr on it
	if non-NULL.

	* gcc.dg/gomp/pr49640.c: New test.

--- gcc/gimplify.c	(revision 175966)
+++ gcc/gimplify.c	(revision 175967)
@@ -2010,8 +2010,14 @@ gimplify_compound_lval (tree *expr_p, gi
 		  ret = MIN (ret, tret);
 		}
 	    }
+	  else
+	    {
+	      tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+				    is_gimple_reg, fb_rvalue);
+	      ret = MIN (ret, tret);
+	    }
 
-	  if (!TREE_OPERAND (t, 3))
+	  if (TREE_OPERAND (t, 3) == NULL_TREE)
 	    {
 	      tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
 	      tree elmt_size = unshare_expr (array_ref_element_size (t));
@@ -2031,11 +2037,17 @@ gimplify_compound_lval (tree *expr_p, gi
 		  ret = MIN (ret, tret);
 		}
 	    }
+	  else
+	    {
+	      tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
+				    is_gimple_reg, fb_rvalue);
+	      ret = MIN (ret, tret);
+	    }
 	}
       else if (TREE_CODE (t) == COMPONENT_REF)
 	{
 	  /* Set the field offset into T and gimplify it.  */
-	  if (!TREE_OPERAND (t, 2))
+	  if (TREE_OPERAND (t, 2) == NULL_TREE)
 	    {
 	      tree offset = unshare_expr (component_ref_field_offset (t));
 	      tree field = TREE_OPERAND (t, 1);
@@ -2054,6 +2066,12 @@ gimplify_compound_lval (tree *expr_p, gi
 		  ret = MIN (ret, tret);
 		}
 	    }
+	  else
+	    {
+	      tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+				    is_gimple_reg, fb_rvalue);
+	      ret = MIN (ret, tret);
+	    }
 	}
     }
 
--- gcc/testsuite/gcc.dg/gomp/pr49640.c	(revision 0)
+++ gcc/testsuite/gcc.dg/gomp/pr49640.c	(revision 175967)
@@ -0,0 +1,29 @@
+/* PR middle-end/49640 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -fopenmp" } */
+
+void
+foo (int N, int M, int K, int P, int Q, int R, int i, int j, int k,
+     unsigned char x[P][Q][R], int y[N][M][K])
+{
+  int ii, jj, kk;
+
+#pragma omp parallel for private(ii,jj,kk)
+  for (ii = 0; ii < P; ++ii)
+    for (jj = 0; jj < Q; ++jj)
+      for (kk = 0; kk < R; ++kk)
+	y[i + ii][j + jj][k + kk] = x[ii][jj][kk];
+}
+
+void
+bar (int N, int M, int K, int P, int Q, int R, int i, int j, int k,
+     unsigned char x[P][Q][R], float y[N][M][K], float factor, float zero)
+{
+  int ii, jj, kk;
+
+#pragma omp parallel for private(ii,jj,kk)
+  for (ii = 0; ii < P; ++ii)
+    for (jj = 0; jj < Q; ++jj)
+      for (kk = 0; kk < R; ++kk)
+	y[i + ii][j + jj][k + kk] = factor * x[ii][jj][kk] + zero;
+}

Patch

--- gcc/tree-vrp.c	(revision 173875)
+++ gcc/tree-vrp.c	(revision 173876)
@@ -2259,17 +2259,27 @@  extract_range_from_binary_expr (value_ra
 	 op0 + op1 == 0, so we cannot claim that the sum is in ~[0,0].
 	 Note that we are guaranteed to have vr0.type == vr1.type at
 	 this point.  */
-      if (code == PLUS_EXPR && vr0.type == VR_ANTI_RANGE)
+      if (vr0.type == VR_ANTI_RANGE)
 	{
-	  set_value_range_to_varying (vr);
-	  return;
+	  if (code == PLUS_EXPR)
+	    {
+	      set_value_range_to_varying (vr);
+	      return;
+	    }
+	  /* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs,
+	     the resulting VR_ANTI_RANGE is the same - intersection
+	     of the two ranges.  */
+	  min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min);
+	  max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max);
+	}
+      else
+	{
+	  /* For operations that make the resulting range directly
+	     proportional to the original ranges, apply the operation to
+	     the same end of each range.  */
+	  min = vrp_int_const_binop (code, vr0.min, vr1.min);
+	  max = vrp_int_const_binop (code, vr0.max, vr1.max);
 	}
-
-      /* For operations that make the resulting range directly
-	 proportional to the original ranges, apply the operation to
-	 the same end of each range.  */
-      min = vrp_int_const_binop (code, vr0.min, vr1.min);
-      max = vrp_int_const_binop (code, vr0.max, vr1.max);
     }
   else if (code == MULT_EXPR
 	   || code == TRUNC_DIV_EXPR
--- gcc/testsuite/gcc.c-torture/execute/pr49039.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr49039.c	(revision 173876)
@@ -0,0 +1,26 @@ 
+/* PR tree-optimization/49039 */
+extern void abort (void);
+int cnt;
+
+__attribute__((noinline, noclone)) void
+foo (unsigned int x, unsigned int y)
+{
+  unsigned int minv, maxv;
+  if (x == 1 || y == -2U)
+    return;
+  minv = x < y ? x : y;
+  maxv = x > y ? x : y;
+  if (minv == 1)
+    ++cnt;
+  if (maxv == -2U)
+    ++cnt;
+}
+
+int
+main ()
+{
+  foo (-2U, 1);
+  if (cnt != 2)
+    abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/tree-ssa/pr49039.c	(revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr49039.c	(revision 173876)
@@ -0,0 +1,31 @@ 
+/* PR tree-optimization/49039 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+extern void bar (void);
+
+void
+foo (unsigned int x, unsigned int y)
+{
+  unsigned int minv, maxv;
+  if (x >= 3 && x <= 6)
+    return;
+  if (y >= 5 && y <= 8)
+    return;
+  minv = x < y ? x : y;
+  maxv = x > y ? x : y;
+  if (minv == 5)
+    bar ();
+  if (minv == 6)
+    bar ();
+  if (maxv == 5)
+    bar ();
+  if (maxv == 6)
+    bar ();
+}
+
+/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 5 to 0" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 6 to 0" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 5 to 0" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 6 to 0" "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
--- gcc/testsuite/g++.dg/torture/pr49039.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr49039.C	(revision 173876)
@@ -0,0 +1,76 @@ 
+// PR tree-optimization/49039
+// { dg-do run }
+
+template <class T1, class T2>
+struct pair
+{
+  T1 first;
+  T2 second;
+  pair (const T1 & a, const T2 & b):first (a), second (b) {}
+};
+
+template <class T1, class T2>
+inline pair <T1, T2>
+make_pair (T1 x, T2 y)
+{
+  return pair <T1, T2> (x, y);
+}
+
+typedef __SIZE_TYPE__ size_t;
+struct S
+{
+  const char *Data;
+  size_t Length;
+  static size_t min (size_t a, size_t b) { return a < b ? a : b; }
+  static size_t max (size_t a, size_t b) { return a > b ? a : b; }
+  S () :Data (0), Length (0) { }
+  S (const char *Str) : Data (Str), Length (__builtin_strlen (Str)) {}
+  S (const char *data, size_t length) : Data (data), Length (length) {}
+  bool empty () const { return Length == 0; }
+  size_t size () const { return Length; }
+  S slice (size_t Start, size_t End) const
+  {
+    Start = min (Start, Length);
+    End = min (max (Start, End), Length);
+    return S (Data + Start, End - Start);
+  }
+  pair <S, S> split (char Separator) const
+  {
+    size_t Idx = find (Separator);
+    if (Idx == ~size_t (0))
+      return make_pair (*this, S ());
+    return make_pair (slice (0, Idx), slice (Idx + 1, ~size_t (0)));
+  }
+  size_t find (char C, size_t From = 0) const
+  {
+    for (size_t i = min (From, Length), e = Length; i != e; ++i)
+      if (Data[i] == C)
+	return i;
+    return ~size_t (0);
+  }
+};
+
+void
+Test (const char *arg)
+{
+  S Desc (arg);
+  while (!Desc.empty ())
+    {
+      pair <S, S> Split = Desc.split ('-');
+      S Token = Split.first;
+      Desc = Split.second;
+      if (Token.empty ())
+	continue;
+      Split = Token.split (':');
+      S Specifier = Split.first;
+      if (Specifier.empty ())
+	__builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  Test ("-");
+  return 0;
+}