PR middle-end/18029 and PR middle-end/18030
authorKazu Hirata <kazu@cs.umass.edu>
Wed, 2 Mar 2005 16:04:50 +0000 (16:04 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Wed, 2 Mar 2005 16:04:50 +0000 (16:04 +0000)
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.

From-SVN: r95782

gcc/ChangeLog
gcc/expr.c

index d4aa50a17f0da05c578306ea6e7cefb221389f3f..fccfa7e3606d91151e0ceb811ce1857a4eff3df6 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 ab7cf930d8b95e8dd85a974590fba537e0648d30..c2c9ffe10b06418b6633d4a837adb93acb62fff5 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;
     }