diff options
author | Jakub Jelinek <jakub@redhat.com> | 2004-06-30 12:09:55 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2004-06-30 12:09:55 +0200 |
commit | df62f18ae1401944493ecccd47f7b0714d0ab8f8 (patch) | |
tree | de710deee48e0626b77470a406d37539f06fe50a /gcc/expr.c | |
parent | e6a0022b28265f3676f7273a05afb4f6d1d7fd14 (diff) | |
download | gcc-df62f18ae1401944493ecccd47f7b0714d0ab8f8.zip gcc-df62f18ae1401944493ecccd47f7b0714d0ab8f8.tar.gz gcc-df62f18ae1401944493ecccd47f7b0714d0ab8f8.tar.bz2 |
re PR tree-optimization/15310 ([tree-ssa] Optimize an addition in a bit field)
* simplify-rtx.c (simplify_binary_operation): Simplify
((A & N) + B) & M -> (A + B) & M if M is pow2 minus 1 constant and
N has at least all bits in M set as well.
PR tree-optimization/15310
* expr.c (expand_assignment): Optimize += or -= on a bit field in
most significant bits.
* gcc.c-torture/execute/20040629-1.c: New test.
From-SVN: r83900
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 51 |
1 files changed, 51 insertions, 0 deletions
@@ -3858,6 +3858,57 @@ expand_assignment (tree to, tree from, int want_value) MEM_KEEP_ALIAS_SET_P (to_rtx) = 1; } + if (mode1 == VOIDmode && !want_value + && bitpos + bitsize <= BITS_PER_WORD + && bitsize < BITS_PER_WORD + && GET_MODE_BITSIZE (GET_MODE (to_rtx)) <= BITS_PER_WORD + && !TREE_SIDE_EFFECTS (to) + && TREE_CODE (TREE_TYPE (from)) == INTEGER_TYPE + && TREE_CODE_CLASS (TREE_CODE (from)) == '2' + && operand_equal_p (to, TREE_OPERAND (from, 0), 0)) + { + rtx value; + HOST_WIDE_INT count = bitpos; + + if (BYTES_BIG_ENDIAN) + count = GET_MODE_BITSIZE (GET_MODE (to_rtx)) - bitpos - bitsize; + + /* Special case some bitfield op= exp. */ + switch (TREE_CODE (from)) + { + case PLUS_EXPR: + case MINUS_EXPR: + if (count <= 0) + break; + + /* For now, just optimize the case of the topmost bitfield + where we don't need to do any masking. + We might win by one instruction for the other bitfields + too if insv/extv instructions aren't used, so that + can be added later. */ + if (count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx))) + break; + value = expand_expr (TREE_OPERAND (from, 1), NULL_RTX, + VOIDmode, 0); + value = protect_from_queue (value, 0); + to_rtx = protect_from_queue (to_rtx, 1); + value = expand_shift (LSHIFT_EXPR, GET_MODE (to_rtx), + value, build_int_2 (count, 0), + NULL_RTX, 1); + result = expand_binop (GET_MODE (to_rtx), + TREE_CODE (from) == PLUS_EXPR + ? add_optab : sub_optab, to_rtx, + value, to_rtx, 1, OPTAB_WIDEN); + if (result != to_rtx) + emit_move_insn (to_rtx, result); + free_temp_slots (); + pop_temp_slots (); + return NULL_RTX; + default: + break; + } + } + result = store_field (to_rtx, bitsize, bitpos, mode1, from, (want_value /* Spurious cast for HPUX compiler. */ |