OSDN Git Service

PR middle-end/18029 and PR middle-end/18030
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Mar 2005 16:04:50 +0000 (16:04 +0000)
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Mar 2005 16:04:50 +0000 (16:04 +0000)
* expr.c (optimize_bitfield_assignment_op): Add a special case
to handle BIT_IOR_EXPR and BIT_XOR_EXPR.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95782 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c

index d4aa50a..fccfa7e 100644 (file)
@@ -6,6 +6,10 @@
        config/rs6000/rs6000-protos.h, doc/contrib.texi,
        doc/include/gcc-common.texi: Update copyright.
 
+       PR middle-end/18029 and PR middle-end/18030
+       * expr.c (optimize_bitfield_assignment_op): Add a special case
+       to handle BIT_IOR_EXPR and BIT_XOR_EXPR.
+
 2005-03-02  Richard Guenther  <rguenth@gcc.gnu.org>
 
        * cgraph.h (struct cgraph_edge): Add prev_caller and
index ab7cf93..c2c9ffe 100644 (file)
@@ -3755,6 +3755,41 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
        emit_move_insn (str_rtx, result);
       return true;
 
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+      if (TREE_CODE (op1) != INTEGER_CST)
+       break;
+      value = expand_expr (op1, NULL_RTX, GET_MODE (str_rtx), 0);
+      value = convert_modes (GET_MODE (str_rtx),
+                            TYPE_MODE (TREE_TYPE (op1)), value,
+                            TYPE_UNSIGNED (TREE_TYPE (op1)));
+
+      /* We may be accessing data outside the field, which means
+        we can alias adjacent data.  */
+      if (MEM_P (str_rtx))
+       {
+         str_rtx = shallow_copy_rtx (str_rtx);
+         set_mem_alias_set (str_rtx, 0);
+         set_mem_expr (str_rtx, 0);
+       }
+
+      binop = TREE_CODE (src) == BIT_IOR_EXPR ? ior_optab : xor_optab;
+      if (bitpos + bitsize != GET_MODE_BITSIZE (GET_MODE (str_rtx)))
+       {
+         rtx mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << bitsize)
+                             - 1);
+         value = expand_and (GET_MODE (str_rtx), value, mask,
+                             NULL_RTX);
+       }
+      value = expand_shift (LSHIFT_EXPR, GET_MODE (str_rtx), value,
+                           build_int_cst (NULL_TREE, bitpos),
+                           NULL_RTX, 1);
+      result = expand_binop (GET_MODE (str_rtx), binop, str_rtx,
+                            value, str_rtx, 1, OPTAB_WIDEN);
+      if (result != str_rtx)
+       emit_move_insn (str_rtx, result);
+      return true;
+
     default:
       break;
     }