Hi!

The tree-cfg.c verification requires that BIT_FIELD_REF bitpos fits into
uhwi, but fold-const.c happily creates BIT_FIELD_REFs with negative bitpos
(on invalid source).

The following patch just punts optimization instead of creating
BIT_FIELD_REF with negative bitpos and also adds some formatting fixes.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-10-16  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/82549
        * fold-const.c (optimize_bit_field_compare, fold_truth_andor_1):
        Formatting fixes.  Instead of calling make_bit_field_ref with negative
        bitpos return 0.

        * gcc.c-torture/compile/pr82549.c: New test.

--- gcc/fold-const.c.jj 2017-10-13 09:17:44.000000000 +0200
+++ gcc/fold-const.c    2017-10-14 13:46:35.939329846 +0200
@@ -4013,21 +4013,20 @@ optimize_bit_field_compare (location_t l
                      size_int (nbitsize - lbitsize - lbitpos));
 
   if (! const_p)
-    /* If not comparing with constant, just rework the comparison
-       and return.  */
-    return fold_build2_loc (loc, code, compare_type,
-                       fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
-                                    make_bit_field_ref (loc, linner, lhs,
-                                                        unsigned_type,
-                                                        nbitsize, nbitpos,
-                                                        1, lreversep),
-                                    mask),
-                       fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
-                                    make_bit_field_ref (loc, rinner, rhs,
-                                                        unsigned_type,
-                                                        nbitsize, nbitpos,
-                                                        1, rreversep),
-                                    mask));
+    {
+      if (nbitpos < 0)
+       return 0;
+
+      /* If not comparing with constant, just rework the comparison
+        and return.  */
+      tree t1 = make_bit_field_ref (loc, linner, lhs, unsigned_type,
+                                   nbitsize, nbitpos, 1, lreversep);
+      t1 = fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type, t1, mask);
+      tree t2 = make_bit_field_ref (loc, rinner, rhs, unsigned_type,
+                                   nbitsize, nbitpos, 1, rreversep);
+      t2 = fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type, t2, mask);
+      return fold_build2_loc (loc, code, compare_type, t1, t2);
+    }
 
   /* Otherwise, we are handling the constant case.  See if the constant is too
      big for the field.  Warn and return a tree for 0 (false) if so.  We do
@@ -4058,6 +4057,9 @@ optimize_bit_field_compare (location_t l
        }
     }
 
+  if (nbitpos < 0)
+    return 0;
+
   /* Single-bit compares should always be against zero.  */
   if (lbitsize == 1 && ! integer_zerop (rhs))
     {
@@ -5874,7 +5876,10 @@ fold_truth_andor_1 (location_t loc, enum
         results.  */
       ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
       lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask);
-      if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
+      if (lnbitsize == rnbitsize
+         && xll_bitpos == xlr_bitpos
+         && lnbitpos >= 0
+         && rnbitpos >= 0)
        {
          lhs = make_bit_field_ref (loc, ll_inner, ll_arg,
                                    lntype, lnbitsize, lnbitpos,
@@ -5898,10 +5903,14 @@ fold_truth_andor_1 (location_t loc, enum
         Note that we still must mask the lhs/rhs expressions.  Furthermore,
         the mask must be shifted to account for the shift done by
         make_bit_field_ref.  */
-      if ((ll_bitsize + ll_bitpos == rl_bitpos
-          && lr_bitsize + lr_bitpos == rr_bitpos)
-         || (ll_bitpos == rl_bitpos + rl_bitsize
-             && lr_bitpos == rr_bitpos + rr_bitsize))
+      if (((ll_bitsize + ll_bitpos == rl_bitpos
+           && lr_bitsize + lr_bitpos == rr_bitpos)
+          || (ll_bitpos == rl_bitpos + rl_bitsize
+              && lr_bitpos == rr_bitpos + rr_bitsize))
+         && ll_bitpos >= 0
+         && rl_bitpos >= 0
+         && lr_bitpos >= 0
+         && rr_bitpos >= 0)
        {
          tree type;
 
@@ -5970,6 +5979,9 @@ fold_truth_andor_1 (location_t loc, enum
        }
     }
 
+  if (lnbitpos < 0)
+    return 0;
+
   /* Construct the expression we will return.  First get the component
      reference we will make.  Unless the mask is all ones the width of
      that field, perform the mask operation.  Then compare with the
--- gcc/testsuite/gcc.c-torture/compile/pr82549.c.jj    2017-10-14 
13:49:27.831214544 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr82549.c       2017-10-14 
13:49:23.561267090 +0200
@@ -0,0 +1,9 @@
+/* PR tree-optimization/82549 */
+
+int a, b[1];
+
+int
+main ()
+{
+  return !a || b[-2] || b[-2];
+}

        Jakub

Reply via email to