fold-const.c (native_interpret_expr): Also support POINTER_TYPE and REFERENCE_TYPE...
authorRichard Guenther <rguenther@suse.de>
Fri, 16 Mar 2012 14:49:48 +0000 (14:49 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 16 Mar 2012 14:49:48 +0000 (14:49 +0000)
2012-03-16  Richard Guenther  <rguenther@suse.de>

* fold-const.c (native_interpret_expr): Also support POINTER_TYPE
and REFERENCE_TYPE interpretations.
(can_native_interpret_type_p): New function.
(fold_ternary_loc): Use native encode/interpret to fold
BIT_FIELD_REFs of constants.

From-SVN: r185469

gcc/ChangeLog
gcc/fold-const.c

index 1775524..7f14c96 100644 (file)
@@ -1,5 +1,13 @@
 2012-03-16  Richard Guenther  <rguenther@suse.de>
 
+       * fold-const.c (native_interpret_expr): Also support POINTER_TYPE
+       and REFERENCE_TYPE interpretations.
+       (can_native_interpret_type_p): New function.
+       (fold_ternary_loc): Use native encode/interpret to fold
+       BIT_FIELD_REFs of constants.
+
+2012-03-16  Richard Guenther  <rguenther@suse.de>
+
        PR middle-end/52584
        * fold-const.c (fold_ternary_loc): Fold vector typed BIT_FIELD_REFs
        of vector constants and constructors.
index 6c4f7f8..33b8dc8 100644 (file)
@@ -7530,6 +7530,8 @@ native_interpret_expr (tree type, const unsigned char *ptr, int len)
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
       return native_interpret_int (type, ptr, len);
 
     case REAL_TYPE:
@@ -7546,6 +7548,27 @@ native_interpret_expr (tree type, const unsigned char *ptr, int len)
     }
 }
 
+/* Returns true if we can interpret the contents of a native encoding
+   as TYPE.  */
+
+static bool
+can_native_interpret_type_p (tree type)
+{
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case REAL_TYPE:
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+      return true;
+    default:
+      return false;
+    }
+}
 
 /* Fold a VIEW_CONVERT_EXPR of a constant expression EXPR to type
    TYPE at compile-time.  If we're unable to perform the conversion
@@ -13978,6 +14001,40 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          && integer_zerop (op2))
        return fold_convert_loc (loc, type, arg0);
 
+      /* On constants we can use native encode/interpret to constant
+         fold (nearly) all BIT_FIELD_REFs.  */
+      if (CONSTANT_CLASS_P (arg0)
+         && can_native_interpret_type_p (type)
+         && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (arg0)), 1)
+         /* This limitation should not be necessary, we just need to
+            round this up to mode size.  */
+         && tree_low_cst (op1, 1) % BITS_PER_UNIT == 0
+         /* Need bit-shifting of the buffer to relax the following.  */
+         && tree_low_cst (op2, 1) % BITS_PER_UNIT == 0)
+       {
+         unsigned HOST_WIDE_INT bitpos = tree_low_cst (op1, 2);
+         unsigned HOST_WIDE_INT bitsize = tree_low_cst (op1, 1);
+         unsigned HOST_WIDE_INT clen;
+         clen = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (arg0)), 1);
+         /* ???  We cannot tell native_encode_expr to start at
+            some random byte only.  So limit us to a reasonable amount
+            of work.  */
+         if (clen <= 4096)
+           {
+             unsigned char *b = XALLOCAVEC (unsigned char, clen);
+             unsigned HOST_WIDE_INT len = native_encode_expr (arg0, b, clen);
+             if (len > 0
+                 && len * BITS_PER_UNIT >= bitpos + bitsize)
+               {
+                 tree v = native_interpret_expr (type,
+                                                 b + bitpos / BITS_PER_UNIT,
+                                                 bitsize / BITS_PER_UNIT);
+                 if (v)
+                   return v;
+               }
+           }
+       }
+
       return NULL_TREE;
 
     case FMA_EXPR: