diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1994-07-13 14:44:38 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1994-07-13 14:44:38 -0400 |
commit | 6d9f1f5f63493bfe17c9b648084abe348d842834 (patch) | |
tree | ddfad204698bdea2b22a3ac4e4aaa179cad3b3e4 /gcc | |
parent | 4be40f361984880793e17b2658445eba4fcf9898 (diff) | |
download | gcc-6d9f1f5f63493bfe17c9b648084abe348d842834.zip gcc-6d9f1f5f63493bfe17c9b648084abe348d842834.tar.gz gcc-6d9f1f5f63493bfe17c9b648084abe348d842834.tar.bz2 |
(decode_field_reference): Merge operand of a BIT_AND_EXPR with the
mask made from the description of the field.
From-SVN: r7766
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fold-const.c | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index fc61190..0417aab 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2387,9 +2387,10 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp, int *punsignedp, *pvolatilep; tree *pmask; { - tree mask = 0; - tree inner; - tree offset; + tree and_mask = 0; + tree mask, inner, offset; + tree unsigned_type; + int precision; /* All the optimizations using this function assume integer fields. There are problems with FP fields since the type_for_size call @@ -2401,10 +2402,10 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp, if (TREE_CODE (exp) == BIT_AND_EXPR) { - mask = TREE_OPERAND (exp, 1); + and_mask = TREE_OPERAND (exp, 1); exp = TREE_OPERAND (exp, 0); - STRIP_NOPS (exp); STRIP_NOPS (mask); - if (TREE_CODE (mask) != INTEGER_CST) + STRIP_NOPS (exp); STRIP_NOPS (and_mask); + if (TREE_CODE (and_mask) != INTEGER_CST) return 0; } @@ -2417,17 +2418,20 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp, if (inner == exp || *pbitsize < 0 || offset != 0) return 0; - if (mask == 0) - { - tree unsigned_type = type_for_size (*pbitsize, 1); - int precision = TYPE_PRECISION (unsigned_type); - - mask = build_int_2 (~0, ~0); - TREE_TYPE (mask) = unsigned_type; - force_fit_type (mask, 0); - mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0); - mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0); - } + /* Compute the mask to access the bitfield. */ + unsigned_type = type_for_size (*pbitsize, 1); + precision = TYPE_PRECISION (unsigned_type); + + mask = build_int_2 (~0, ~0); + TREE_TYPE (mask) = unsigned_type; + force_fit_type (mask, 0); + mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0); + mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0); + + /* Merge it with the mask we found in the BIT_AND_EXPR, if any. */ + if (and_mask != 0) + mask = fold (build (BIT_AND_EXPR, unsigned_type, + convert (unsigned_type, and_mask), mask)); *pmask = mask; return inner; |