OSDN Git Service

./:
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 3033ec8..2a4629a 100644 (file)
@@ -53,6 +53,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "tree-flow.h"
 #include "target.h"
 #include "timevar.h"
+#include "df.h"
 
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
@@ -142,7 +143,7 @@ static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
                                     tree, tree, int, int);
 static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
 static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode,
-                       tree, tree, int);
+                       tree, tree, int, bool);
 
 static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (tree, tree);
 
@@ -283,7 +284,7 @@ init_expr_once (void)
            if (! HARD_REGNO_MODE_OK (regno, mode))
              continue;
 
-           REGNO (reg) = regno;
+           SET_REGNO (reg, regno);
 
            SET_SRC (pat) = mem;
            SET_DEST (pat) = reg;
@@ -4074,10 +4075,11 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
 }
 
 
-/* Expand an assignment that stores the value of FROM into TO.  */
+/* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
+   is true, try generating a nontemporal store.  */
 
 void
-expand_assignment (tree to, tree from)
+expand_assignment (tree to, tree from, bool nontemporal)
 {
   rtx to_rtx = 0;
   rtx result;
@@ -4164,12 +4166,13 @@ expand_assignment (tree to, tree from)
          if (TREE_CODE (TREE_TYPE (from)) == COMPLEX_TYPE)
            {
              gcc_assert (bitpos == 0);
-             result = store_expr (from, to_rtx, false);
+             result = store_expr (from, to_rtx, false, nontemporal);
            }
          else
            {
              gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1));
-             result = store_expr (from, XEXP (to_rtx, bitpos != 0), false);
+             result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
+                                  nontemporal);
            }
        }
       else
@@ -4195,7 +4198,8 @@ expand_assignment (tree to, tree from)
            result = NULL;
          else
            result = store_field (to_rtx, bitsize, bitpos, mode1, from,
-                                 TREE_TYPE (tem), get_alias_set (to));
+                                 TREE_TYPE (tem), get_alias_set (to),
+                                 nontemporal);
        }
 
       if (result)
@@ -4302,13 +4306,46 @@ expand_assignment (tree to, tree from)
   /* Compute FROM and store the value in the rtx we got.  */
 
   push_temp_slots ();
-  result = store_expr (from, to_rtx, 0);
+  result = store_expr (from, to_rtx, 0, nontemporal);
   preserve_temp_slots (result);
   free_temp_slots ();
   pop_temp_slots ();
   return;
 }
 
+/* Emits nontemporal store insn that moves FROM to TO.  Returns true if this
+   succeeded, false otherwise.  */
+
+static bool
+emit_storent_insn (rtx to, rtx from)
+{
+  enum machine_mode mode = GET_MODE (to), imode;
+  enum insn_code code = storent_optab->handlers[mode].insn_code;
+  rtx pattern;
+
+  if (code == CODE_FOR_nothing)
+    return false;
+
+  imode = insn_data[code].operand[0].mode;
+  if (!insn_data[code].operand[0].predicate (to, imode))
+    return false;
+
+  imode = insn_data[code].operand[1].mode;
+  if (!insn_data[code].operand[1].predicate (from, imode))
+    {
+      from = copy_to_mode_reg (imode, from);
+      if (!insn_data[code].operand[1].predicate (from, imode))
+       return false;
+    }
+
+  pattern = GEN_FCN (code) (to, from);
+  if (pattern == NULL_RTX)
+    return false;
+
+  emit_insn (pattern);
+  return true;
+}
+
 /* Generate code for computing expression EXP,
    and storing the value into TARGET.
 
@@ -4320,10 +4357,12 @@ expand_assignment (tree to, tree from)
    be more thorough?
 
    If CALL_PARAM_P is nonzero, this is a store into a call param on the
-   stack, and block moves may need to be treated specially.  */
+   stack, and block moves may need to be treated specially.
+   If NONTEMPORAL is true, try using a nontemporal store instruction.  */
 
 rtx
-store_expr (tree exp, rtx target, int call_param_p)
+store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
 {
   rtx temp;
   rtx alt_rtl = NULL_RTX;
@@ -4344,7 +4383,8 @@ store_expr (tree exp, rtx target, int call_param_p)
         part.  */
       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
                   call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL);
-      return store_expr (TREE_OPERAND (exp, 1), target, call_param_p);
+      return store_expr (TREE_OPERAND (exp, 1), target, call_param_p,
+                        nontemporal);
     }
   else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
     {
@@ -4358,11 +4398,13 @@ store_expr (tree exp, rtx target, int call_param_p)
       do_pending_stack_adjust ();
       NO_DEFER_POP;
       jumpifnot (TREE_OPERAND (exp, 0), lab1);
-      store_expr (TREE_OPERAND (exp, 1), target, call_param_p);
+      store_expr (TREE_OPERAND (exp, 1), target, call_param_p,
+                 nontemporal);
       emit_jump_insn (gen_jump (lab2));
       emit_barrier ();
       emit_label (lab1);
-      store_expr (TREE_OPERAND (exp, 2), target, call_param_p);
+      store_expr (TREE_OPERAND (exp, 2), target, call_param_p,
+                 nontemporal);
       emit_label (lab2);
       OK_DEFER_POP;
 
@@ -4394,7 +4436,7 @@ store_expr (tree exp, rtx target, int call_param_p)
              /* Some types, e.g. Fortran's logical*4, won't have a signed
                 version, so use the mode instead.  */
              tree ntype
-               = (get_signed_or_unsigned_type
+               = (signed_or_unsigned_type_for
                   (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)));
              if (ntype == NULL)
                ntype = lang_hooks.types.type_for_mode
@@ -4433,7 +4475,12 @@ store_expr (tree exp, rtx target, int call_param_p)
     }
   else
     {
-      temp = expand_expr_real (exp, target, GET_MODE (target),
+      rtx tmp_target;
+
+      /* If we want to use a nontemporal store, force the value to
+        register first.  */
+      tmp_target = nontemporal ? NULL_RTX : target;
+      temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
                               (call_param_p
                                ? EXPAND_STACK_PARM : EXPAND_NORMAL),
                               &alt_rtl);
@@ -4591,6 +4638,11 @@ store_expr (tree exp, rtx target, int call_param_p)
        emit_block_move (target, temp, expr_size (exp),
                         (call_param_p
                          ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
+      else if (nontemporal
+              && emit_storent_insn (target, temp))
+       /* If we managed to emit a nontemporal store, there is nothing else to
+          do.  */
+       ;
       else
        {
          temp = force_operand (temp, target);
@@ -4941,7 +4993,7 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
       store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
     }
   else
-    store_field (target, bitsize, bitpos, mode, exp, type, alias_set);
+    store_field (target, bitsize, bitpos, mode, exp, type, alias_set, false);
 }
 
 /* Store the value of constructor EXP into the rtx TARGET.
@@ -5291,7 +5343,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                      = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
                                                   &unsignedp, 0));
                    SET_DECL_RTL (index, index_r);
-                   store_expr (lo_index, index_r, 0);
+                   store_expr (lo_index, index_r, 0, false);
 
                    /* Build the head of the loop.  */
                    do_pending_stack_adjust ();
@@ -5318,7 +5370,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                      store_constructor (value, xtarget, cleared,
                                         bitsize / BITS_PER_UNIT);
                    else
-                     store_expr (value, xtarget, 0);
+                     store_expr (value, xtarget, 0, false);
 
                    /* Generate a conditional jump to exit the loop.  */
                    exit_cond = build2 (LT_EXPR, integer_type_node,
@@ -5329,7 +5381,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                       the loop.  */
                    expand_assignment (index,
                                       build2 (PLUS_EXPR, TREE_TYPE (index),
-                                              index, integer_one_node));
+                                              index, integer_one_node),
+                                      false);
 
                    emit_jump (loop_start);
 
@@ -5360,7 +5413,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                                          expand_normal (position),
                                          highest_pow2_factor (position));
                xtarget = adjust_address (xtarget, mode, 0);
-               store_expr (value, xtarget, 0);
+               store_expr (value, xtarget, 0, false);
              }
            else
              {
@@ -5522,11 +5575,14 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 
    ALIAS_SET is the alias set for the destination.  This value will
    (in general) be different from that for TARGET, since TARGET is a
-   reference to the containing structure.  */
+   reference to the containing structure.
+   
+   If NONTEMPORAL is true, try generating a nontemporal store.  */
 
 static rtx
 store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
-            enum machine_mode mode, tree exp, tree type, int alias_set)
+            enum machine_mode mode, tree exp, tree type, int alias_set,
+            bool nontemporal)
 {
   HOST_WIDE_INT width_mask = 0;
 
@@ -5561,7 +5617,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
       if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
        emit_move_insn (object, target);
 
-      store_field (blk_object, bitsize, bitpos, mode, exp, type, alias_set);
+      store_field (blk_object, bitsize, bitpos, mode, exp, type, alias_set,
+                  nontemporal);
 
       emit_move_insn (target, object);
 
@@ -5574,7 +5631,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
       /* We're storing into a struct containing a single __complex.  */
 
       gcc_assert (!bitpos);
-      return store_expr (exp, target, 0);
+      return store_expr (exp, target, 0, nontemporal);
     }
 
   /* If the structure is in a register or if the component
@@ -5675,7 +5732,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
       if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
        set_mem_alias_set (to_rtx, alias_set);
 
-      return store_expr (exp, to_rtx, 0);
+      return store_expr (exp, to_rtx, 0, nontemporal);
     }
 }
 \f
@@ -6001,12 +6058,13 @@ force_operand (rtx value, rtx target)
       && !REG_P (SUBREG_REG (value))
       && !MEM_P (SUBREG_REG (value)))
     {
-      value = simplify_gen_subreg (GET_MODE (value),
-                                  force_reg (GET_MODE (SUBREG_REG (value)),
-                                             force_operand (SUBREG_REG (value),
-                                                            NULL_RTX)),
-                                  GET_MODE (SUBREG_REG (value)),
-                                  SUBREG_BYTE (value));
+      value
+       = simplify_gen_subreg (GET_MODE (value),
+                              force_reg (GET_MODE (SUBREG_REG (value)),
+                                         force_operand (SUBREG_REG (value),
+                                                        NULL_RTX)),
+                              GET_MODE (SUBREG_REG (value)),
+                              SUBREG_BYTE (value));
       code = GET_CODE (value);
     }
 
@@ -6070,23 +6128,18 @@ force_operand (rtx value, rtx target)
                                  FLOAT_MODE_P (GET_MODE (value))
                                  ? RDIV_EXPR : TRUNC_DIV_EXPR,
                                  GET_MODE (value), op1, op2, target, 0);
-         break;
        case MOD:
          return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
                                target, 0);
-         break;
        case UDIV:
          return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
                                target, 1);
-         break;
        case UMOD:
          return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
                                target, 1);
-         break;
        case ASHIFTRT:
          return expand_simple_binop (GET_MODE (value), code, op1, op2,
                                      target, 0, OPTAB_LIB_WIDEN);
-         break;
        default:
          return expand_simple_binop (GET_MODE (value), code, op1, op2,
                                      target, 1, OPTAB_LIB_WIDEN);
@@ -7835,7 +7888,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            /* Store data into beginning of memory target.  */
            store_expr (TREE_OPERAND (exp, 0),
                        adjust_address (target, TYPE_MODE (valtype), 0),
-                       modifier == EXPAND_STACK_PARM);
+                       modifier == EXPAND_STACK_PARM,
+                       false);
 
          else
            {
@@ -7848,7 +7902,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                                 * BITS_PER_UNIT),
                                (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
                           0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
-                          type, 0);
+                          type, 0, false);
            }
 
          /* Return the entire union.  */
@@ -8764,13 +8818,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        op1 = gen_label_rtx ();
        jumpifnot (TREE_OPERAND (exp, 0), op0);
        store_expr (TREE_OPERAND (exp, 1), temp,
-                 modifier == EXPAND_STACK_PARM);
+                 modifier == EXPAND_STACK_PARM,
+                 false);
 
        emit_jump_insn (gen_jump (op1));
        emit_barrier ();
        emit_label (op0);
        store_expr (TREE_OPERAND (exp, 2), temp,
-                 modifier == EXPAND_STACK_PARM);
+                 modifier == EXPAND_STACK_PARM,
+                 false);
 
        emit_label (op1);
        OK_DEFER_POP;
@@ -8785,7 +8841,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        tree lhs = TREE_OPERAND (exp, 0);
        tree rhs = TREE_OPERAND (exp, 1);
        gcc_assert (ignore);
-       expand_assignment (lhs, rhs);
+       expand_assignment (lhs, rhs, false);
        return const0_rtx;
       }
 
@@ -8817,13 +8873,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            do_jump (TREE_OPERAND (rhs, 1),
                     value ? label : 0,
                     value ? 0 : label);
-           expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value));
+           expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
+                              MOVE_NONTEMPORAL (exp));
            do_pending_stack_adjust ();
            emit_label (label);
            return const0_rtx;
          }
 
-       expand_assignment (lhs, rhs);
+       expand_assignment (lhs, rhs, MOVE_NONTEMPORAL (exp));
        return const0_rtx;
       }
 
@@ -8890,6 +8947,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Lowered by gimplify.c.  */
       gcc_unreachable ();
 
+    case CHANGE_DYNAMIC_TYPE_EXPR:
+      /* This is ignored at the RTL level.  The tree level set
+        DECL_POINTER_ALIAS_SET of any variable to be 0, which is
+        overkill for the RTL layer but is all that we can
+        represent.  */
+      return const0_rtx;
+
     case EXC_PTR_EXPR:
       return get_exception_pointer (cfun);