aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-06-30 12:09:55 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2004-06-30 12:09:55 +0200
commitdf62f18ae1401944493ecccd47f7b0714d0ab8f8 (patch)
treede710deee48e0626b77470a406d37539f06fe50a /gcc/expr.c
parente6a0022b28265f3676f7273a05afb4f6d1d7fd14 (diff)
downloadgcc-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.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index a92eab6..d67e6ee 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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. */