OSDN Git Service

* config/i386/i386.c (bdesc_args) [IX86_BUILTIN_CVTTPD2DQ256]: Use
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index b020978..84cfe5c 100644 (file)
@@ -4544,6 +4544,27 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
     }
 }
 
+/* Return the alignment of the object EXP, also considering its type
+   when we do not know of explicit misalignment.
+   ???  Note that, in the general case, the type of an expression is not kept
+   consistent with misalignment information by the front-end, for
+   example when taking the address of a member of a packed structure.
+   However, in most of the cases, expressions have the alignment of
+   their type, so we optimistically fall back to the alignment of the
+   type when we cannot compute a misalignment.  */
+
+static unsigned int
+get_object_or_type_alignment (tree exp)
+{
+  unsigned HOST_WIDE_INT misalign;
+  unsigned int align = get_object_alignment_1 (exp, &misalign);
+  if (misalign != 0)
+    align = (misalign & -misalign);
+  else
+    align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
+  return align;
+}
+
 /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
    is true, try generating a nontemporal store.  */
 
@@ -4553,7 +4574,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
   rtx to_rtx = 0;
   rtx result;
   enum machine_mode mode;
-  int align;
+  unsigned int align;
   enum insn_code icode;
 
   /* Don't crash if the lhs of the assignment was erroneous.  */
@@ -4571,8 +4592,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
   if ((TREE_CODE (to) == MEM_REF
        || TREE_CODE (to) == TARGET_MEM_REF)
       && mode != BLKmode
-      && ((align = MAX (TYPE_ALIGN (TREE_TYPE (to)), get_object_alignment (to)))
-         < (signed) GET_MODE_ALIGNMENT (mode))
+      && ((align = get_object_or_type_alignment (to))
+         < GET_MODE_ALIGNMENT (mode))
       && ((icode = optab_handler (movmisalign_optab, mode))
          != CODE_FOR_nothing))
     {
@@ -8646,27 +8667,9 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
     case VEC_EXTRACT_EVEN_EXPR:
     case VEC_EXTRACT_ODD_EXPR:
-      {
-        expand_operands (treeop0,  treeop1,
-                         NULL_RTX, &op0, &op1, EXPAND_NORMAL);
-        this_optab = optab_for_tree_code (code, type, optab_default);
-        temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
-                             OPTAB_WIDEN);
-        gcc_assert (temp);
-        return temp;
-      }
-
     case VEC_INTERLEAVE_HIGH_EXPR:
     case VEC_INTERLEAVE_LOW_EXPR:
-      {
-        expand_operands (treeop0,  treeop1,
-                         NULL_RTX, &op0, &op1, EXPAND_NORMAL);
-        this_optab = optab_for_tree_code (code, type, optab_default);
-        temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
-                             OPTAB_WIDEN);
-        gcc_assert (temp);
-        return temp;
-      }
+      goto binop;
 
     case VEC_LSHIFT_EXPR:
     case VEC_RSHIFT_EXPR:
@@ -8711,6 +8714,19 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
        return target;
       }
 
+    case VEC_WIDEN_LSHIFT_HI_EXPR:
+    case VEC_WIDEN_LSHIFT_LO_EXPR:
+      {
+        tree oprnd0 = treeop0;
+        tree oprnd1 = treeop1;
+
+        expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+        target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
+                                            target, unsignedp);
+        gcc_assert (target);
+        return target;
+      }
+
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
     case VEC_PACK_FIX_TRUNC_EXPR:
@@ -8718,9 +8734,11 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
       goto binop;
 
     case VEC_PERM_EXPR:
-      target = expand_vec_perm_expr (type, treeop0, treeop1, treeop2, target);
-      gcc_assert (target);
-      return target;
+      expand_operands (treeop0, treeop1, target, &op0, &op1, EXPAND_NORMAL);
+      op2 = expand_normal (treeop2);
+      temp = expand_vec_perm (mode, op0, op1, op2, target);
+      gcc_assert (temp);
+      return temp;
 
     case DOT_PROD_EXPR:
       {
@@ -9241,7 +9259,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
        struct mem_address addr;
        enum insn_code icode;
-       int align;
+       unsigned int align;
 
        get_address_description (exp, &addr);
        op0 = addr_for_mem_ref (&addr, as, true);
@@ -9249,9 +9267,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        temp = gen_rtx_MEM (mode, op0);
        set_mem_attributes (temp, exp, 0);
        set_mem_addr_space (temp, as);
-       align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+       align = get_object_or_type_alignment (exp);
        if (mode != BLKmode
-           && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+           && align < GET_MODE_ALIGNMENT (mode)
            /* If the target does not have special handling for unaligned
               loads of mode then it can use regular moves for them.  */
            && ((icode = optab_handler (movmisalign_optab, mode))
@@ -9278,7 +9296,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        tree base = TREE_OPERAND (exp, 0);
        gimple def_stmt;
        enum insn_code icode;
-       int align;
+       unsigned align;
        /* Handle expansion of non-aliased memory with non-BLKmode.  That
           might end up in a register.  */
        if (TREE_CODE (base) == ADDR_EXPR)
@@ -9329,7 +9347,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                           gimple_assign_rhs1 (def_stmt), mask);
            TREE_OPERAND (exp, 0) = base;
          }
-       align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+       align = get_object_or_type_alignment (exp);
        op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address_addr_space (address_mode, op0, as);
        if (!integer_zerop (TREE_OPERAND (exp, 1)))
@@ -9345,7 +9363,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        if (TREE_THIS_VOLATILE (exp))
          MEM_VOLATILE_P (temp) = 1;
        if (mode != BLKmode
-           && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+           && align < GET_MODE_ALIGNMENT (mode)
            /* If the target does not have special handling for unaligned
               loads of mode then it can use regular moves for them.  */
            && ((icode = optab_handler (movmisalign_optab, mode))