OSDN Git Service

PR middle-end/44828
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index a2a8054..00ebfdc 100644 (file)
@@ -201,41 +201,6 @@ static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
    < (unsigned int) MOVE_RATIO (optimize_insn_for_speed_p ()))
 #endif
 
-/* This array records the insn_code of insns to perform block moves.  */
-enum insn_code movmem_optab[NUM_MACHINE_MODES];
-
-/* This array records the insn_code of insns to perform block sets.  */
-enum insn_code setmem_optab[NUM_MACHINE_MODES];
-
-/* These arrays record the insn_code of three different kinds of insns
-   to perform block compares.  */
-enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
-enum insn_code cmpstrn_optab[NUM_MACHINE_MODES];
-enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
-
-/* Synchronization primitives.  */
-enum insn_code sync_add_optab[NUM_MACHINE_MODES];
-enum insn_code sync_sub_optab[NUM_MACHINE_MODES];
-enum insn_code sync_ior_optab[NUM_MACHINE_MODES];
-enum insn_code sync_and_optab[NUM_MACHINE_MODES];
-enum insn_code sync_xor_optab[NUM_MACHINE_MODES];
-enum insn_code sync_nand_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_add_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_sub_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_ior_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_and_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_xor_optab[NUM_MACHINE_MODES];
-enum insn_code sync_old_nand_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_add_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_sub_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_ior_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_and_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_xor_optab[NUM_MACHINE_MODES];
-enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES];
-enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES];
-enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES];
-enum insn_code sync_lock_release[NUM_MACHINE_MODES];
-
 /* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow.  */
 
 #ifndef SLOW_UNALIGNED_ACCESS
@@ -434,7 +399,7 @@ convert_move (rtx to, rtx from, int unsignedp)
 
       /* Try converting directly if the insn is supported.  */
 
-      code = convert_optab_handler (tab, to_mode, from_mode)->insn_code;
+      code = convert_optab_handler (tab, to_mode, from_mode);
       if (code != CODE_FOR_nothing)
        {
          emit_unop_insn (code, to, from,
@@ -468,12 +433,12 @@ convert_move (rtx to, rtx from, int unsignedp)
       enum machine_mode full_mode
        = smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
 
-      gcc_assert (convert_optab_handler (trunc_optab, to_mode, full_mode)->insn_code
+      gcc_assert (convert_optab_handler (trunc_optab, to_mode, full_mode)
                  != CODE_FOR_nothing);
 
       if (full_mode != from_mode)
        from = convert_to_mode (full_mode, from, unsignedp);
-      emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, full_mode)->insn_code,
+      emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, full_mode),
                      to, from, UNKNOWN);
       return;
     }
@@ -483,18 +448,19 @@ convert_move (rtx to, rtx from, int unsignedp)
       enum machine_mode full_mode
        = smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
 
-      gcc_assert (convert_optab_handler (sext_optab, full_mode, from_mode)->insn_code
+      gcc_assert (convert_optab_handler (sext_optab, full_mode, from_mode)
                  != CODE_FOR_nothing);
 
       if (to_mode == full_mode)
        {
-         emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode)->insn_code,
+         emit_unop_insn (convert_optab_handler (sext_optab, full_mode,
+                                                from_mode),
                          to, from, UNKNOWN);
          return;
        }
 
       new_from = gen_reg_rtx (full_mode);
-      emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode)->insn_code,
+      emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode),
                      new_from, from, UNKNOWN);
 
       /* else proceed to integer conversions below.  */
@@ -695,9 +661,10 @@ convert_move (rtx to, rtx from, int unsignedp)
     }
 
   /* Support special truncate insns for certain modes.  */
-  if (convert_optab_handler (trunc_optab, to_mode, from_mode)->insn_code != CODE_FOR_nothing)
+  if (convert_optab_handler (trunc_optab, to_mode,
+                            from_mode) != CODE_FOR_nothing)
     {
-      emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, from_mode)->insn_code,
+      emit_unop_insn (convert_optab_handler (trunc_optab, to_mode, from_mode),
                      to, from, UNKNOWN);
       return;
     }
@@ -990,7 +957,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
       if (mode == VOIDmode)
        break;
 
-      icode = optab_handler (mov_optab, mode)->insn_code;
+      icode = optab_handler (mov_optab, mode);
       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
        move_by_pieces_1 (GEN_FCN (icode), mode, &data);
 
@@ -1071,7 +1038,7 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
       if (mode == VOIDmode)
        break;
 
-      icode = optab_handler (mov_optab, mode)->insn_code;
+      icode = optab_handler (mov_optab, mode);
       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
        n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
 
@@ -1313,7 +1280,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
-      enum insn_code code = movmem_optab[(int) mode];
+      enum insn_code code = direct_optab_handler (movmem_optab, mode);
       insn_operand_predicate_fn pred;
 
       if (code != CODE_FOR_nothing
@@ -2352,7 +2319,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
          if (mode == VOIDmode)
            break;
 
-         icode = optab_handler (mov_optab, mode)->insn_code;
+         icode = optab_handler (mov_optab, mode);
          if (icode != CODE_FOR_nothing
              && align >= GET_MODE_ALIGNMENT (mode))
            {
@@ -2565,7 +2532,7 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
       if (mode == VOIDmode)
        break;
 
-      icode = optab_handler (mov_optab, mode)->insn_code;
+      icode = optab_handler (mov_optab, mode);
       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
        store_by_pieces_2 (GEN_FCN (icode), mode, data);
 
@@ -2789,7 +2756,7 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
-      enum insn_code code = setmem_optab[(int) mode];
+      enum insn_code code = direct_optab_handler (setmem_optab, mode);
       insn_operand_predicate_fn pred;
 
       if (code != CODE_FOR_nothing
@@ -3034,7 +3001,7 @@ emit_move_via_integer (enum machine_mode mode, rtx x, rtx y, bool force)
     return NULL_RTX;
 
   /* The target must support moves in this mode.  */
-  code = optab_handler (mov_optab, imode)->insn_code;
+  code = optab_handler (mov_optab, imode);
   if (code == CODE_FOR_nothing)
     return NULL_RTX;
 
@@ -3184,7 +3151,7 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
 
   /* Move floating point as parts.  */
   if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-      && optab_handler (mov_optab, GET_MODE_INNER (mode))->insn_code != CODE_FOR_nothing)
+      && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing)
     try_int = false;
   /* Not possible if the values are inherently not adjacent.  */
   else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
@@ -3235,7 +3202,7 @@ emit_move_ccmode (enum machine_mode mode, rtx x, rtx y)
   /* Assume all MODE_CC modes are equivalent; if we have movcc, use it.  */
   if (mode != CCmode)
     {
-      enum insn_code code = optab_handler (mov_optab, CCmode)->insn_code;
+      enum insn_code code = optab_handler (mov_optab, CCmode);
       if (code != CODE_FOR_nothing)
        {
          x = emit_move_change_mode (CCmode, mode, x, true);
@@ -3375,7 +3342,7 @@ emit_move_insn_1 (rtx x, rtx y)
 
   gcc_assert ((unsigned int) mode < (unsigned int) MAX_MACHINE_MODE);
 
-  code = optab_handler (mov_optab, mode)->insn_code;
+  code = optab_handler (mov_optab, mode);
   if (code != CODE_FOR_nothing)
     return emit_insn (GEN_FCN (code) (x, y));
 
@@ -3627,7 +3594,7 @@ emit_single_push_insn (enum machine_mode mode, rtx x, tree type)
   stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
   /* If there is push pattern, use it.  Otherwise try old way of throwing
      MEM representing push operation to move expander.  */
-  icode = optab_handler (push_optab, mode)->insn_code;
+  icode = optab_handler (push_optab, mode);
   if (icode != CODE_FOR_nothing)
     {
       if (((pred = insn_data[(int) icode].operand[0].predicate)
@@ -4363,7 +4330,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
        set_mem_attributes (mem, to, 0);
        set_mem_addr_space (mem, as);
 
-       icode = movmisalign_optab->handlers[mode].insn_code;
+       icode = optab_handler (movmisalign_optab, mode);
        gcc_assert (icode != CODE_FOR_nothing);
 
        op_mode1 = insn_data[icode].operand[1].mode;
@@ -4496,7 +4463,7 @@ bool
 emit_storent_insn (rtx to, rtx from)
 {
   enum machine_mode mode = GET_MODE (to), imode;
-  enum insn_code code = optab_handler (storent_optab, mode)->insn_code;
+  enum insn_code code = optab_handler (storent_optab, mode);
   rtx pattern;
 
   if (code == CODE_FOR_nothing)
@@ -5703,7 +5670,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
          {
            enum machine_mode mode = GET_MODE (target);
 
-           icode = (int) optab_handler (vec_init_optab, mode)->insn_code;
+           icode = (int) optab_handler (vec_init_optab, mode);
            if (icode != CODE_FOR_nothing)
              {
                unsigned int i;
@@ -6703,7 +6670,6 @@ safe_from_p (const_rtx x, tree exp, int top_p)
          break;
 
        case MISALIGNED_INDIRECT_REF:
-       case ALIGN_INDIRECT_REF:
        case INDIRECT_REF:
          if (MEM_P (x)
              && alias_sets_conflict_p (MEM_ALIAS_SET (x),
@@ -7704,7 +7670,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
          this_optab = usmul_widen_optab;
          if (mode == GET_MODE_2XWIDER_MODE (innermode))
            {
-             if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
+             if (optab_handler (this_optab, mode) != CODE_FOR_nothing)
                {
                  if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
                    expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
@@ -7730,7 +7696,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
          if (mode == GET_MODE_2XWIDER_MODE (innermode))
            {
-             if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
+             if (optab_handler (this_optab, mode) != CODE_FOR_nothing)
                {
                  expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
                                   EXPAND_NORMAL);
@@ -7738,7 +7704,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                                               unsignedp, this_optab);
                  return REDUCE_BIT_FIELD (temp);
                }
-             if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
+             if (optab_handler (other_optab, mode) != CODE_FOR_nothing
                  && innermode == word_mode)
                {
                  rtx htem, hipart;
@@ -8679,12 +8645,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return expand_constructor (exp, target, modifier, false);
 
     case MISALIGNED_INDIRECT_REF:
-    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       {
        tree exp1 = treeop0;
        addr_space_t as = ADDR_SPACE_GENERIC;
-       enum machine_mode address_mode = Pmode;
 
        if (modifier != EXPAND_WRITE)
          {
@@ -8696,21 +8660,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          }
 
        if (POINTER_TYPE_P (TREE_TYPE (exp1)))
-         {
-           as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
-           address_mode = targetm.addr_space.address_mode (as);
-         }
+         as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
 
        op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address_addr_space (mode, op0, as);
 
-       if (code == ALIGN_INDIRECT_REF)
-         {
-           int align = TYPE_ALIGN_UNIT (type);
-           op0 = gen_rtx_AND (address_mode, op0, GEN_INT (-align));
-           op0 = memory_address_addr_space (mode, op0, as);
-         }
-
        temp = gen_rtx_MEM (mode, op0);
 
        set_mem_attributes (temp, exp, 0);
@@ -8727,7 +8681,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                        || modifier == EXPAND_STACK_PARM);
 
            /* The vectorizer should have already checked the mode.  */
-           icode = optab_handler (movmisalign_optab, mode)->insn_code;
+           icode = optab_handler (movmisalign_optab, mode);
            gcc_assert (icode != CODE_FOR_nothing);
 
            /* We've already validated the memory, and we're creating a
@@ -8775,6 +8729,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))));
        enum machine_mode address_mode;
        tree base = TREE_OPERAND (exp, 0);
+       gimple def_stmt;
        /* Handle expansion of non-aliased memory with non-BLKmode.  That
           might end up in a register.  */
        if (TREE_CODE (base) == ADDR_EXPR)
@@ -8817,14 +8772,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              }
          }
        address_mode = targetm.addr_space.address_mode (as);
-       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, address_mode,
-                          EXPAND_NORMAL);
+       base = TREE_OPERAND (exp, 0);
+       if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR)))
+         base = build2 (BIT_AND_EXPR, TREE_TYPE (base),
+                        gimple_assign_rhs1 (def_stmt),
+                        gimple_assign_rhs2 (def_stmt));
        if (!integer_zerop (TREE_OPERAND (exp, 1)))
-         {
-           rtx off;
-           off = immed_double_int_const (mem_ref_offset (exp), address_mode);
-           op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
-         }
+         base = build2 (POINTER_PLUS_EXPR, TREE_TYPE (base),
+                        base, double_int_to_tree (sizetype,
+                                                  mem_ref_offset (exp)));
+       op0 = expand_expr (base, NULL_RTX, address_mode, EXPAND_SUM);
        op0 = memory_address_addr_space (mode, op0, as);
        temp = gen_rtx_MEM (mode, op0);
        set_mem_attributes (temp, exp, 0);
@@ -10295,39 +10252,6 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
   return 1;
 }
 
-/* Nonzero if the mode is a valid vector mode for this architecture.
-   This returns nonzero even if there is no hardware support for the
-   vector mode, but we can emulate with narrower modes.  */
-
-int
-vector_mode_valid_p (enum machine_mode mode)
-{
-  enum mode_class mclass = GET_MODE_CLASS (mode);
-  enum machine_mode innermode;
-
-  /* Doh!  What's going on?  */
-  if (mclass != MODE_VECTOR_INT
-      && mclass != MODE_VECTOR_FLOAT
-      && mclass != MODE_VECTOR_FRACT
-      && mclass != MODE_VECTOR_UFRACT
-      && mclass != MODE_VECTOR_ACCUM
-      && mclass != MODE_VECTOR_UACCUM)
-    return 0;
-
-  /* Hardware support.  Woo hoo!  */
-  if (targetm.vector_mode_supported_p (mode))
-    return 1;
-
-  innermode = GET_MODE_INNER (mode);
-
-  /* We should probably return 1 if requesting V4DI and we have no DI,
-     but we have V2DI, but this is probably very unlikely.  */
-
-  /* If we have support for the inner mode, we can safely emulate it.
-     We may not have V2DI, but me can emulate with a pair of DIs.  */
-  return targetm.scalar_mode_supported_p (innermode);
-}
-
 /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
 static rtx
 const_vector_from_tree (tree exp)