This makes use of native_encode/interpret_expr to do $subject.
Pretty straight-forward and something value-numbering already
does.  Not sure what a good upper bound for the encode buffer
size should be - I suppose at some point we should teach
encode to skip uninteresting start bytes (and teach it to
interpret CONSTRUCTORs - the single major missing feature).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2012-03-16  Richard Guenther  <rguent...@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.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 185465)
--- gcc/fold-const.c    (working copy)
*************** native_interpret_expr (tree type, const
*** 7530,7535 ****
--- 7530,7537 ----
      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:
*************** native_interpret_expr (tree type, const
*** 7546,7551 ****
--- 7548,7574 ----
      }
  }
  
+ /* 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
*************** fold_ternary_loc (location_t loc, enum t
*** 13945,13950 ****
--- 14004,14043 ----
          && 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);
+             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:

Reply via email to