aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2012-03-16 14:49:48 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2012-03-16 14:49:48 +0000
commit6814f778d841cb75ff96eaeea78ddfbf7952f475 (patch)
tree667889b647704b21f167fc57a211fa1ef2fc27f9 /gcc/fold-const.c
parentada3df5081a4fb89ae83bce787fc9c949cdfc9ce (diff)
downloadgcc-6814f778d841cb75ff96eaeea78ddfbf7952f475.zip
gcc-6814f778d841cb75ff96eaeea78ddfbf7952f475.tar.gz
gcc-6814f778d841cb75ff96eaeea78ddfbf7952f475.tar.bz2
fold-const.c (native_interpret_expr): Also support POINTER_TYPE and REFERENCE_TYPE interpretations.
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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6c4f7f8..33b8dc8 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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: