diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-04-17 13:19:46 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-04-17 13:19:46 +0000 |
commit | b4f314ea97f04620d290f3ae25d831f46692864f (patch) | |
tree | e99df6f0f35dce95dacd7a91b0242e81462a0860 /gcc/config/i386/i386.c | |
parent | 644412e1c29a2984b1b37656c18fe9f33791eff1 (diff) | |
parent | 7de380af566c189319d706d3b4ab04e32ecc5d90 (diff) | |
download | gcc-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.c | 175 |
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; |