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  <ja...@redhat.com>

        Backport from mainline
        2011-05-18  Jakub Jelinek  <ja...@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.

--- 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;
+}
2011-07-19  Jakub Jelinek  <ja...@redhat.com>

        Backport from mainline
        2011-05-23  Jakub Jelinek  <ja...@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  <ja...@redhat.com>

        Backport from mainline
        2011-05-26  Jakub Jelinek  <ja...@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  <ja...@redhat.com>

        Backport from mainline
        2011-05-27  Jakub Jelinek  <ja...@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  <ja...@redhat.com>

        Backport from mainline
        2011-07-04  Jakub Jelinek  <ja...@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  <ja...@redhat.com>

        Backport from mainline
        2011-07-07  Jakub Jelinek  <ja...@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;
+}

Reply via email to