summaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-17 13:19:46 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-17 13:19:46 +0000
commitb4f314ea97f04620d290f3ae25d831f46692864f (patch)
treee99df6f0f35dce95dacd7a91b0242e81462a0860 /gcc/config/i386/i386.c
parent644412e1c29a2984b1b37656c18fe9f33791eff1 (diff)
parent7de380af566c189319d706d3b4ab04e32ecc5d90 (diff)
downloadgcc-b4f314ea97f04620d290f3ae25d831f46692864f.tar.gz
Merge from trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@209485 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r--gcc/config/i386/i386.c175
1 files changed, 91 insertions, 84 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 46a4d2e528d..3aa2ac4832c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -82,6 +82,7 @@ along with GCC; see the file COPYING3. If not see
#include "context.h"
#include "pass_manager.h"
#include "target-globals.h"
+#include "tree-vectorizer.h"
static rtx legitimize_dllimport_symbol (rtx, bool);
static rtx legitimize_pe_coff_extern_decl (rtx, bool);
@@ -1739,7 +1740,7 @@ struct processor_costs slm_cost = {
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
1, /* vec_stmt_cost. */
- 1, /* vec_to_scalar_cost. */
+ 4, /* vec_to_scalar_cost. */
1, /* scalar_to_vec_cost. */
1, /* vec_align_load_cost. */
2, /* vec_unalign_load_cost. */
@@ -1816,7 +1817,7 @@ struct processor_costs intel_cost = {
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
1, /* vec_stmt_cost. */
- 1, /* vec_to_scalar_cost. */
+ 4, /* vec_to_scalar_cost. */
1, /* scalar_to_vec_cost. */
1, /* vec_align_load_cost. */
2, /* vec_unalign_load_cost. */
@@ -6807,8 +6808,9 @@ classify_argument (enum machine_mode mode, const_tree type,
}
/* Examine the argument and return set number of register required in each
- class. Return 0 iff parameter should be passed in memory. */
-static int
+ class. Return true iff parameter should be passed in memory. */
+
+static bool
examine_argument (enum machine_mode mode, const_tree type, int in_return,
int *int_nregs, int *sse_nregs)
{
@@ -6817,8 +6819,9 @@ examine_argument (enum machine_mode mode, const_tree type, int in_return,
*int_nregs = 0;
*sse_nregs = 0;
+
if (!n)
- return 0;
+ return true;
for (n--; n >= 0; n--)
switch (regclass[n])
{
@@ -6836,15 +6839,15 @@ examine_argument (enum machine_mode mode, const_tree type, int in_return,
break;
case X86_64_X87_CLASS:
case X86_64_X87UP_CLASS:
+ case X86_64_COMPLEX_X87_CLASS:
if (!in_return)
- return 0;
+ return true;
break;
- case X86_64_COMPLEX_X87_CLASS:
- return in_return ? 2 : 0;
case X86_64_MEMORY_CLASS:
gcc_unreachable ();
}
- return 1;
+
+ return false;
}
/* Construct container for the argument used by GCC interface. See
@@ -6874,8 +6877,8 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
n = classify_argument (mode, type, regclass, 0);
if (!n)
return NULL;
- if (!examine_argument (mode, type, in_return, &needed_intregs,
- &needed_sseregs))
+ if (examine_argument (mode, type, in_return, &needed_intregs,
+ &needed_sseregs))
return NULL;
if (needed_intregs > nintregs || needed_sseregs > nsseregs)
return NULL;
@@ -7194,7 +7197,7 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|| VALID_AVX256_REG_MODE (mode)))
return;
- if (examine_argument (mode, type, 0, &int_nregs, &sse_nregs)
+ if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs)
&& sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
{
cum->nregs -= int_nregs;
@@ -7989,95 +7992,87 @@ ix86_libcall_value (enum machine_mode mode)
/* Return true iff type is returned in memory. */
-static bool ATTRIBUTE_UNUSED
-return_in_memory_32 (const_tree type, enum machine_mode mode)
+static bool
+ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
+#ifdef SUBTARGET_RETURN_IN_MEMORY
+ return SUBTARGET_RETURN_IN_MEMORY (type, fntype);
+#else
+ const enum machine_mode mode = type_natural_mode (type, NULL, true);
HOST_WIDE_INT size;
- if (mode == BLKmode)
- return true;
-
- size = int_size_in_bytes (type);
-
- if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
- return false;
-
- if (VECTOR_MODE_P (mode) || mode == TImode)
+ if (TARGET_64BIT)
{
- /* User-created vectors small enough to fit in EAX. */
- if (size < 8)
- return false;
-
- /* MMX/3dNow values are returned in MM0,
- except when it doesn't exits or the ABI prescribes otherwise. */
- if (size == 8)
- return !TARGET_MMX || TARGET_VECT8_RETURNS;
+ if (ix86_function_type_abi (fntype) == MS_ABI)
+ {
+ size = int_size_in_bytes (type);
- /* SSE values are returned in XMM0, except when it doesn't exist. */
- if (size == 16)
- return !TARGET_SSE;
+ /* __m128 is returned in xmm0. */
+ if ((!type || VECTOR_INTEGER_TYPE_P (type)
+ || INTEGRAL_TYPE_P (type)
+ || VECTOR_FLOAT_TYPE_P (type))
+ && (SCALAR_INT_MODE_P (mode) || VECTOR_MODE_P (mode))
+ && !COMPLEX_MODE_P (mode)
+ && (GET_MODE_SIZE (mode) == 16 || size == 16))
+ return false;
- /* AVX values are returned in YMM0, except when it doesn't exist. */
- if (size == 32)
- return !TARGET_AVX;
+ /* Otherwise, the size must be exactly in [1248]. */
+ return size != 1 && size != 2 && size != 4 && size != 8;
+ }
+ else
+ {
+ int needed_intregs, needed_sseregs;
- /* AVX512F values are returned in ZMM0, except when it doesn't exist. */
- if (size == 64)
- return !TARGET_AVX512F;
+ return examine_argument (mode, type, 1,
+ &needed_intregs, &needed_sseregs);
+ }
}
+ else
+ {
+ if (mode == BLKmode)
+ return true;
- if (mode == XFmode)
- return false;
+ size = int_size_in_bytes (type);
- if (size > 12)
- return true;
+ if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
+ return false;
- /* OImode shouldn't be used directly. */
- gcc_assert (mode != OImode);
+ if (VECTOR_MODE_P (mode) || mode == TImode)
+ {
+ /* User-created vectors small enough to fit in EAX. */
+ if (size < 8)
+ return false;
- return false;
-}
+ /* Unless ABI prescibes otherwise,
+ MMX/3dNow values are returned in MM0 if available. */
+
+ if (size == 8)
+ return TARGET_VECT8_RETURNS || !TARGET_MMX;
-static bool ATTRIBUTE_UNUSED
-return_in_memory_64 (const_tree type, enum machine_mode mode)
-{
- int needed_intregs, needed_sseregs;
- return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
-}
+ /* SSE values are returned in XMM0 if available. */
+ if (size == 16)
+ return !TARGET_SSE;
-static bool ATTRIBUTE_UNUSED
-return_in_memory_ms_64 (const_tree type, enum machine_mode mode)
-{
- HOST_WIDE_INT size = int_size_in_bytes (type);
+ /* AVX values are returned in YMM0 if available. */
+ if (size == 32)
+ return !TARGET_AVX;
- /* __m128 is returned in xmm0. */
- if ((!type || VECTOR_INTEGER_TYPE_P (type) || INTEGRAL_TYPE_P (type)
- || VECTOR_FLOAT_TYPE_P (type))
- && (SCALAR_INT_MODE_P (mode) || VECTOR_MODE_P (mode))
- && !COMPLEX_MODE_P (mode) && (GET_MODE_SIZE (mode) == 16 || size == 16))
- return false;
+ /* AVX512F values are returned in ZMM0 if available. */
+ if (size == 64)
+ return !TARGET_AVX512F;
+ }
- /* Otherwise, the size must be exactly in [1248]. */
- return size != 1 && size != 2 && size != 4 && size != 8;
-}
+ if (mode == XFmode)
+ return false;
-static bool
-ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
-#ifdef SUBTARGET_RETURN_IN_MEMORY
- return SUBTARGET_RETURN_IN_MEMORY (type, fntype);
-#else
- const enum machine_mode mode = type_natural_mode (type, NULL, true);
+ if (size > 12)
+ return true;
- if (TARGET_64BIT)
- {
- if (ix86_function_type_abi (fntype) == MS_ABI)
- return return_in_memory_ms_64 (type, mode);
- else
- return return_in_memory_64 (type, mode);
+ /* OImode shouldn't be used directly. */
+ gcc_assert (mode != OImode);
+
+ return false;
}
- else
- return return_in_memory_32 (type, mode);
#endif
}
@@ -44031,7 +44026,7 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
gcc_unreachable ();
case V8HImode:
- if (TARGET_SSSE3)
+ if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
return expand_vec_perm_pshufb2 (d);
else
{
@@ -44054,7 +44049,7 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
break;
case V16QImode:
- if (TARGET_SSSE3)
+ if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
return expand_vec_perm_pshufb2 (d);
else
{
@@ -46334,6 +46329,18 @@ ix86_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
count *= 50; /* FIXME. */
retval = (unsigned) (count * stmt_cost);
+
+ /* We need to multiply all vector stmt cost by 1.7 (estimated cost)
+ for Silvermont as it has out of order integer pipeline and can execute
+ 2 scalar instruction per tick, but has in order SIMD pipeline. */
+ if (TARGET_SILVERMONT || TARGET_INTEL)
+ if (stmt_info && stmt_info->stmt)
+ {
+ tree lhs_op = gimple_get_lhs (stmt_info->stmt);
+ if (lhs_op && TREE_CODE (TREE_TYPE (lhs_op)) == INTEGER_TYPE)
+ retval = (retval * 17) / 10;
+ }
+
cost[where] += retval;
return retval;