X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftestsuite%2Flib%2Ftarget-supports.exp;h=7741f91cf3061bfc4ba285fdbc2e2687cff28b6c;hp=50039e08f4cf3ec2198a8d317f5307c674a7d500;hb=2dfa96e7dabc43d6f9ebf87461581e32a3f3cdcb;hpb=ab10d69dec2ac025bf68fb1a18fad9f7444d97de diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 50039e08f4c..7741f91cf30 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -1,5 +1,5 @@ -# Copyright (C) 1999, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 -# Free Software Foundation, Inc. +# Copyright (C) 1999, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -34,7 +34,8 @@ # "// C++" for c++, # "! Fortran" for Fortran code, # "/* ObjC", for ObjC -# and "// ObjC++" for ObjC++ +# "// ObjC++" for ObjC++ +# and "// Go" for Go # If the tool is ObjC/ObjC++ then we overide the extension to .m/.mm to # allow for ObjC/ObjC++ specific flags. proc check_compile {basename type contents args} { @@ -51,6 +52,7 @@ proc check_compile {basename type contents args} { "*// C++*" { set src ${basename}[pid].cc } "*// ObjC++*" { set src ${basename}[pid].mm } "*/* ObjC*" { set src ${basename}[pid].m } + "*// Go*" { set src ${basename}[pid].go } default { switch -- $tool { "objc" { set src ${basename}[pid].m } @@ -217,7 +219,6 @@ proc check_runtime {prop args} { # this proc returns 1 if they're supported, 0 if they're not, or -1 if unsure proc check_weak_available { } { - global target_triplet global target_cpu # All mips targets should support it @@ -228,25 +229,25 @@ proc check_weak_available { } { # All solaris2 targets should support it - if { [regexp ".*-solaris2.*" $target_triplet] } { + if { [istarget *-*-solaris2*] } { return 1 } # DEC OSF/1/Digital UNIX/Tru64 UNIX supports it - if { [regexp "alpha.*osf.*" $target_triplet] } { + if { [istarget alpha*-dec-osf*] } { return 1 } # Windows targets Cygwin and MingW32 support it - if { [regexp ".*mingw32|.*cygwin" $target_triplet] } { + if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } { return 1 } # HP-UX 10.X doesn't support it - if { [istarget "hppa*-*-hpux10*"] } { + if { [istarget hppa*-*-hpux10*] } { return 0 } @@ -274,7 +275,7 @@ proc check_weak_available { } { # cannot be overridden. proc check_weak_override_available { } { - if { [istarget "*-*-mingw*"] } { + if { [istarget *-*-mingw*] } { return 0 } return [check_weak_available] @@ -289,14 +290,6 @@ proc check_weak_override_available { } { # The argument is the kind of visibility, default/protected/hidden/internal. proc check_visibility_available { what_kind } { - global tool - global target_triplet - - # On NetWare, support makes no sense. - if { [istarget *-*-netware*] } { - return 0 - } - if [string match "" $what_kind] { set what_kind "hidden" } return [check_no_compiler_messages visibility_available_$what_kind object " @@ -368,45 +361,16 @@ proc check_alias_available { } { return $alias_available_saved } -############################### -# proc check_ifunc_available { } -############################### - -# Determine if the target toolchain supports the ifunc attribute. - -# Returns 1 if the target supports ifunc. Returns 0 if the target -# does not support ifunc. +# Returns 1 if the target toolchain supports ifunc, 0 otherwise. proc check_ifunc_available { } { - global ifunc_available_saved - global tool - - if [info exists ifunc_available_saved] { - verbose "check_ifunc_available returning saved $ifunc_available_saved" 2 - } else { - set src ifunc[pid].c - set obj ifunc[pid].o - verbose "check_ifunc_available compiling testfile $src" 2 - set f [open $src "w"] - puts $f "#endif" - puts $f "#ifdef __cplusplus\nextern \"C\"\n#endif" - puts $f "void g() {}" - puts $f "void f() __attribute__((ifunc(\"g\")));" - close $f - set lines [${tool}_target_compile $src $obj object ""] - file delete $src - remote_file build delete $obj - - if [string match "" $lines] then { - set ifunc_available_saved 1 - } else { - set ifunc_available_saved 0 - } - - verbose "check_ifunc_available returning $ifunc_available_saved" 2 - } - - return $ifunc_available_saved + return [check_no_compiler_messages ifunc_available object { + #ifdef __cplusplus + extern "C" + #endif + void g() {} + void f() __attribute__((ifunc("g"))); + }] } # Returns true if --gc-sections is supported on the target. @@ -493,11 +457,18 @@ proc check_profiling_available { test_what } { # These conditions depend on the argument so examine them before # looking at the cache variable. + # Tree profiling requires TLS runtime support. + if { $test_what == "-fprofile-generate" } { + if { ![check_effective_target_tls_runtime] } { + return 0 + } + } + # Support for -p on solaris2 relies on mcrt1.o which comes with the # vendor compiler. We cannot reliably predict the directory where the # vendor compiler (and thus mcrt1.o) is installed so we can't # necessarily find mcrt1.o even if we have it. - if { [istarget *-*-solaris2*] && [lindex $test_what 1] == "-p" } { + if { [istarget *-*-solaris2*] && $test_what == "-p" } { return 0 } @@ -506,32 +477,30 @@ proc check_profiling_available { test_what } { # Support for -pg on irix relies on gcrt1.o which doesn't exist yet. # See: http://gcc.gnu.org/ml/gcc/2002-10/msg00169.html if { [istarget mips*-*-irix*] - && ([lindex $test_what 1] == "-p" || [lindex $test_what 1] == "-pg") } { + && ($test_what == "-p" || $test_what == "-pg") } { return 0 } # We don't yet support profiling for MIPS16. if { [istarget mips*-*-*] && ![check_effective_target_nomips16] - && ([lindex $test_what 1] == "-p" - || [lindex $test_what 1] == "-pg") } { + && ($test_what == "-p" || $test_what == "-pg") } { return 0 } # MinGW does not support -p. - if { [istarget *-*-mingw*] && [lindex $test_what 1] == "-p" } { + if { [istarget *-*-mingw*] && $test_what == "-p" } { return 0 } # cygwin does not support -p. - if { [istarget *-*-cygwin*] && [lindex $test_what 1] == "-p" } { + if { [istarget *-*-cygwin*] && $test_what == "-p" } { return 0 } # uClibc does not have gcrt1.o. if { [check_effective_target_uclibc] - && ([lindex $test_what 1] == "-p" - || [lindex $test_what 1] == "-pg") } { + && ($test_what == "-p" || $test_what == "-pg") } { return 0 } @@ -539,28 +508,30 @@ proc check_profiling_available { test_what } { if {![info exists profiling_available_saved]} { # Some targets don't have any implementation of __bb_init_func or are # missing other needed machinery. - if { [istarget mmix-*-*] + if { [istarget am3*-*-linux*] || [istarget arm*-*-eabi*] - || [istarget picochip-*-*] - || [istarget *-*-netware*] || [istarget arm*-*-elf] || [istarget arm*-*-symbianelf*] || [istarget avr-*-*] || [istarget bfin-*-*] - || [istarget powerpc-*-eabi*] - || [istarget powerpc-*-elf] || [istarget cris-*-*] || [istarget crisv32-*-*] || [istarget fido-*-elf] || [istarget h8300-*-*] - || [istarget lm32-*-*] - || [istarget m32c-*-elf] + || [istarget lm32-*-*] + || [istarget m32c-*-elf] || [istarget m68k-*-elf] || [istarget m68k-*-uclinux*] || [istarget mep-*-elf] || [istarget mips*-*-elf*] + || [istarget mmix-*-*] + || [istarget mn10300-*-elf*] || [istarget moxie-*-elf*] + || [istarget picochip-*-*] + || [istarget powerpc-*-eabi*] + || [istarget powerpc-*-elf] || [istarget rx-*-*] + || [istarget tic6x-*-elf] || [istarget xstormy16-*] || [istarget xtensa*-*-elf] || [istarget *-*-rtems*] @@ -615,7 +586,7 @@ proc check_effective_target_pcc_bitfield_type_matters { } { proc add_options_for_tls { flags } { # Tru64 UNIX uses emutls, which relies on a couple of pthread functions # which only live in libpthread, so always pass -pthread for TLS. - if { [istarget *-*-osf*] } { + if { [istarget alpha*-dec-osf*] } { return "$flags -pthread" } # On Solaris 8 and 9, __tls_get_addr/___tls_get_addr only lives in @@ -648,8 +619,7 @@ proc check_effective_target_tls {} { proc check_effective_target_tls_native {} { # VxWorks uses emulated TLS machinery, but with non-standard helper # functions, so we fail to automatically detect it. - global target_triplet - if { [regexp ".*-.*-vxworks.*" $target_triplet] } { + if { [istarget *-*-vxworks*] } { return 0 } @@ -665,8 +635,7 @@ proc check_effective_target_tls_native {} { proc check_effective_target_tls_emulated {} { # VxWorks uses emulated TLS machinery, but with non-standard helper # functions, so we fail to automatically detect it. - global target_triplet - if { [regexp ".*-.*-vxworks.*" $target_triplet] } { + if { [istarget *-*-vxworks*] } { return 1 } @@ -683,15 +652,36 @@ proc check_effective_target_tls_runtime {} { return [check_runtime tls_runtime { __thread int thr = 0; int main (void) { return thr; } - }] + } [add_options_for_tls ""]] +} + +# Return 1 if atomic compare-and-swap is supported on 'int' + +proc check_effective_target_cas_char {} { + return [check_no_compiler_messages cas_char assembly { + #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 + #error unsupported + #endif + } ""] +} + +proc check_effective_target_cas_int {} { + return [check_no_compiler_messages cas_int assembly { + #if __INT_MAX__ == 0x7fff && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + /* ok */ + #elif __INT_MAX__ == 0x7fffffff && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + /* ok */ + #else + #error unsupported + #endif + } ""] } # Return 1 if -ffunction-sections is supported, 0 otherwise. proc check_effective_target_function_sections {} { # Darwin has its own scheme and silently accepts -ffunction-sections. - global target_triplet - if { [regexp ".*-.*-darwin.*" $target_triplet] } { + if { [istarget *-*-darwin*] } { return 0 } @@ -700,6 +690,14 @@ proc check_effective_target_function_sections {} { } "-ffunction-sections"] } +# Return 1 if instruction scheduling is available, 0 otherwise. + +proc check_effective_target_scheduling {} { + return [check_no_compiler_messages scheduling object { + void foo (void) { } + } "-fschedule-insns"] +} + # Return 1 if compilation with -fgraphite is error-free for trivial # code, 0 otherwise. @@ -718,6 +716,21 @@ proc check_effective_target_fopenmp {} { } "-fopenmp"] } +# Return 1 if compilation with -fgnu-tm is error-free for trivial +# code, 0 otherwise. + +proc check_effective_target_fgnu_tm {} { + return [check_no_compiler_messages fgnu_tm object { + void foo (void) { } + } "-fgnu-tm"] +} + +# Return 1 if the target supports mmap, 0 otherwise. + +proc check_effective_target_mmap {} { + return [check_function_available "mmap"] +} + # Return 1 if compilation with -pthread is error-free for trivial # code, 0 otherwise. @@ -781,6 +794,16 @@ proc check_effective_target_fpic { } { return 0 } +# Return 1 if -pie, -fpie and -fPIE are supported, 0 otherwise. + +proc check_effective_target_pie { } { + if { [istarget *-*-darwin\[912\]*] + || [istarget *-*-linux*] } { + return 1; + } + return 0 +} + # Return true if the target supports -mpaired-single (as used on MIPS). proc check_effective_target_mpaired_single { } { @@ -876,6 +899,53 @@ proc check_effective_target_mips_newabi_large_long_double { } { } "-mabi=64"] } +# Return true if the target is a MIPS target that has access +# to the LL and SC instructions. + +proc check_effective_target_mips_llsc { } { + if { ![istarget mips*-*-*] } { + return 0 + } + # Assume that these instructions are always implemented for + # non-elf* targets, via emulation if necessary. + if { ![istarget *-*-elf*] } { + return 1 + } + # Otherwise assume LL/SC support for everything but MIPS I. + return [check_no_compiler_messages mips_llsc assembly { + #if __mips == 1 + #error FOO + #endif + }] +} + +# Return true if the target is a MIPS target that uses in-place relocations. + +proc check_effective_target_mips_rel { } { + if { ![istarget mips*-*-*] } { + return 0 + } + return [check_no_compiler_messages mips_rel object { + #if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \ + || (defined _ABI64 && _MIPS_SIM == _ABI64) + #error FOO + #endif + }] +} + +# Return true if the target is a MIPS target that uses the EABI. + +proc check_effective_target_mips_eabi { } { + if { ![istarget mips*-*-*] } { + return 0 + } + return [check_no_compiler_messages mips_eabi object { + #ifndef __mips_eabi + #error FOO + #endif + }] +} + # Return 1 if the current multilib does not generate PIC by default. proc check_effective_target_nonpic { } { @@ -920,6 +990,17 @@ proc check_iconv_available { test_what } { }] $libiconv] } +# Return 1 if an ASCII locale is supported on this host, 0 otherwise. + +proc check_ascii_locale_available { } { + if { ([ishost alpha*-dec-osf*] || [ishost mips-sgi-irix*]) } { + # Neither Tru64 UNIX nor IRIX support an ASCII locale. + return 0 + } else { + return 1 + } +} + # Return true if named sections are supported on this target. proc check_named_sections_available { } { @@ -943,6 +1024,44 @@ proc check_effective_target_fortran_large_real { } { }] } +# Return 1 if the target supports Fortran real kind real(16), +# 0 otherwise. Contrary to check_effective_target_fortran_large_real +# this checks for Real(16) only; the other returned real(10) if +# both real(10) and real(16) are available. +# +# When the target name changes, replace the cached result. + +proc check_effective_target_fortran_real_16 { } { + return [check_no_compiler_messages fortran_real_16 executable { + ! Fortran + real(kind=16) :: x + x = cos (x) + end + }] +} + + +# Return 1 if the target supports SQRT for the largest floating-point +# type. (Some targets lack the libm support for this FP type.) +# On most targets, this check effectively checks either whether sqrtl is +# available or on __float128 systems whether libquadmath is installed, +# which provides sqrtq. +# +# When the target name changes, replace the cached result. + +proc check_effective_target_fortran_largest_fp_has_sqrt { } { + return [check_no_compiler_messages fortran_largest_fp_has_sqrt executable { + ! Fortran + use iso_fortran_env, only: real_kinds + integer,parameter:: maxFP = real_kinds(ubound(real_kinds,dim=1)) + real(kind=maxFP), volatile :: x + x = 2.0_maxFP + x = sqrt (x) + end + }] +} + + # Return 1 if the target supports Fortran integer kinds larger than # integer(8), 0 otherwise. # @@ -1025,8 +1144,8 @@ proc check_sse_os_support_available { } { check_runtime_nocache sse_os_support_available { int main () { - __asm__ volatile ("movss %xmm2,%xmm1"); - return 0; + asm volatile ("movaps %xmm0,%xmm0"); + return 0; } } "-msse" } else { @@ -1035,6 +1154,29 @@ proc check_sse_os_support_available { } { }] } +# Return 1 if the target OS supports running AVX executables, 0 +# otherwise. Cache the result. + +proc check_avx_os_support_available { } { + return [check_cached_effective_target avx_os_support_available { + # If this is not the right target then we can skip the test. + if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } { + expr 0 + } else { + # Check that OS has AVX and SSE saving enabled. + check_runtime_nocache avx_os_support_available { + int main () + { + unsigned int eax, edx; + + asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0)); + return (eax & 6) != 6; + } + } "" + } + }] +} + # Return 1 if the target supports executing SSE instructions, 0 # otherwise. Cache the result. @@ -1131,7 +1273,8 @@ proc check_effective_target_sse2_runtime { } { proc check_effective_target_avx_runtime { } { if { [check_effective_target_avx] - && [check_avx_hw_available] } { + && [check_avx_hw_available] + && [check_avx_os_support_available] } { return 1 } return 0 @@ -1348,6 +1491,25 @@ proc check_effective_target_broken_cplxf_arg { } { }] } +# Return 1 is this is a TI C6X target supporting C67X instructions +proc check_effective_target_ti_c67x { } { + return [check_no_compiler_messages ti_c67x assembly { + #if !defined(_TMS320C6700) + #error FOO + #endif + }] +} + +# Return 1 is this is a TI C6X target supporting C64X+ instructions +proc check_effective_target_ti_c64xp { } { + return [check_no_compiler_messages ti_c64xp assembly { + #if !defined(_TMS320C6400_PLUS) + #error FOO + #endif + }] +} + + proc check_alpha_max_hw_available { } { return [check_runtime alpha_max_hw_available { int main() { return __builtin_alpha_amask(1<<8) != 0; } @@ -1378,7 +1540,7 @@ proc check_fork_available {} { # Returns true iff "mkfifo" is available on the target system. proc check_mkfifo_available {} { - if {[istarget *-*-cygwin*]} { + if { [istarget *-*-cygwin*] } { # Cygwin has mkfifo, but support is incomplete. return 0 } @@ -1390,10 +1552,10 @@ proc check_mkfifo_available {} { proc check_cxa_atexit_available { } { return [check_cached_effective_target cxa_atexit_available { - if { [istarget "hppa*-*-hpux10*"] } { + if { [istarget hppa*-*-hpux10*] } { # HP-UX 10 doesn't have __cxa_atexit but subsequent test passes. expr 0 - } elseif { [istarget "*-*-vxworks"] } { + } elseif { [istarget *-*-vxworks] } { # vxworks doesn't have __cxa_atexit but subsequent test passes. expr 0 } else { @@ -1463,6 +1625,28 @@ proc check_effective_target_ilp32 { } { }] } +# Return 1 if we're generating ia32 code using default options, 0 +# otherwise. + +proc check_effective_target_ia32 { } { + return [check_no_compiler_messages ia32 object { + int dummy[sizeof (int) == 4 + && sizeof (void *) == 4 + && sizeof (long) == 4 ? 1 : -1] = { __i386__ }; + }] +} + +# Return 1 if we're generating x32 code using default options, 0 +# otherwise. + +proc check_effective_target_x32 { } { + return [check_no_compiler_messages x32 object { + int dummy[sizeof (int) == 4 + && sizeof (void *) == 4 + && sizeof (long) == 4 ? 1 : -1] = { __x86_64__ }; + }] +} + # Return 1 if we're generating 32-bit or larger integers using default # options, 0 otherwise. @@ -1664,10 +1848,12 @@ proc check_effective_target_vect_cmdline_needed { } { if { [istarget alpha*-*-*] || [istarget ia64-*-*] || (([istarget x86_64-*-*] || [istarget i?86-*-*]) - && [check_effective_target_lp64]) + && ([check_effective_target_x32] + || [check_effective_target_lp64])) || ([istarget powerpc*-*-*] && ([check_effective_target_powerpc_spe] || [check_effective_target_powerpc_altivec])) + || ([istarget sparc*-*-*] && [check_effective_target_sparc_vis]) || [istarget spu-*-*] || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { set et_vect_cmdline_needed_saved 0 @@ -1721,7 +1907,9 @@ proc check_effective_target_vect_intfloat_cvt { } { if { [istarget i?86-*-*] || ([istarget powerpc*-*-*] && ![istarget powerpc-*-linux*paired*]) - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] + || ([istarget arm*-*-*] + && [check_effective_target_arm_neon_ok])} { set et_vect_intfloat_cvt_saved 1 } } @@ -1757,7 +1945,9 @@ proc check_effective_target_vect_uintfloat_cvt { } { if { [istarget i?86-*-*] || ([istarget powerpc*-*-*] && ![istarget powerpc-*-linux*paired*]) - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] + || ([istarget arm*-*-*] + && [check_effective_target_arm_neon_ok])} { set et_vect_uintfloat_cvt_saved 1 } } @@ -1780,7 +1970,9 @@ proc check_effective_target_vect_floatint_cvt { } { if { [istarget i?86-*-*] || ([istarget powerpc*-*-*] && ![istarget powerpc-*-linux*paired*]) - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] + || ([istarget arm*-*-*] + && [check_effective_target_arm_neon_ok])} { set et_vect_floatint_cvt_saved 1 } } @@ -1800,7 +1992,9 @@ proc check_effective_target_vect_floatuint_cvt { } { } else { set et_vect_floatuint_cvt_saved 0 if { ([istarget powerpc*-*-*] - && ![istarget powerpc-*-linux*paired*]) } { + && ![istarget powerpc-*-linux*paired*]) + || ([istarget arm*-*-*] + && [check_effective_target_arm_neon_ok])} { set et_vect_floatuint_cvt_saved 1 } } @@ -1818,6 +2012,24 @@ proc check_effective_target_arm32 { } { }] } +# Return 1 is this is an arm target not using Thumb +proc check_effective_target_arm_nothumb { } { + return [check_no_compiler_messages arm_nothumb assembly { + #if (defined(__thumb__) || defined(__thumb2__)) + #error FOO + #endif + }] +} + +# Return 1 if this is a little-endian ARM target +proc check_effective_target_arm_little_endian { } { + return [check_no_compiler_messages arm_little_endian assembly { + #if !defined(__arm__) || !defined(__ARMEL__) + #error FOO + #endif + }] +} + # Return 1 if this is an ARM target that only supports aligned vector accesses proc check_effective_target_arm_vect_no_misalign { } { return [check_no_compiler_messages arm_vect_no_misalign assembly { @@ -1858,6 +2070,30 @@ proc check_effective_target_arm_hard_vfp_ok { } { } } +# Return 1 if this is an ARM target that supports DSP multiply with +# current multilib flags. + +proc check_effective_target_arm_dsp { } { + return [check_no_compiler_messages arm_dsp assembly { + #ifndef __ARM_FEATURE_DSP + #error not DSP + #endif + int i; + }] +} + +# Return 1 if this is an ARM target that supports unaligned word/halfword +# load/store instructions. + +proc check_effective_target_arm_unaligned { } { + return [check_no_compiler_messages arm_unaligned assembly { + #ifndef __ARM_FEATURE_UNALIGNED + #error no unaligned support + #endif + int i; + }] +} + # Add the options needed for NEON. We need either -mfloat-abi=softfp # or -mfloat-abi=hard, but if one is already specified by the # multilib, use it. Similarly, if a -mfpu option already enables @@ -1903,44 +2139,96 @@ proc check_effective_target_arm_neon_ok { } { # or -mfloat-abi=hard, but if one is already specified by the # multilib, use it. -proc add_options_for_arm_neon_fp16 { flags } { - if { ! [check_effective_target_arm_neon_fp16_ok] } { +proc add_options_for_arm_fp16 { flags } { + if { ! [check_effective_target_arm_fp16_ok] } { return "$flags" } - global et_arm_neon_fp16_flags - return "$flags $et_arm_neon_fp16_flags" + global et_arm_fp16_flags + return "$flags $et_arm_fp16_flags" } -# Return 1 if this is an ARM target supporting -mfpu=neon-fp16 -# -mfloat-abi=softfp or equivalent options. Some multilibs may be -# incompatible with these options. Also set et_arm_neon_flags to the -# best options to add. +# Return 1 if this is an ARM target that can support a VFP fp16 variant. +# Skip multilibs that are incompatible with these options and set +# et_arm_fp16_flags to the best options to add. -proc check_effective_target_arm_neon_fp16_ok_nocache { } { - global et_arm_neon_fp16_flags - set et_arm_neon_fp16_flags "" - if { [check_effective_target_arm32] } { - # Always add -mfpu=neon-fp16, since there is no preprocessor - # macro for FP16 support. - foreach flags {"-mfpu=neon-fp16" "-mfpu=neon-fp16 -mfloat-abi=softfp"} { - if { [check_no_compiler_messages_nocache arm_neon_fp16_ok object { - #include "arm_neon.h" - int dummy; - } "$flags"] } { - set et_arm_neon_fp16_flags $flags - return 1 - } - } +proc check_effective_target_arm_fp16_ok_nocache { } { + global et_arm_fp16_flags + set et_arm_fp16_flags "" + if { ! [check_effective_target_arm32] } { + return 0; + } + if [check-flags [list "" { *-*-* } { "-mfpu=*" } { "-mfpu=*fp16*" "-mfpu=*fpv[4-9]*" "-mfpu=*fpv[1-9][0-9]*" } ]] { + # Multilib flags would override -mfpu. + return 0 + } + if [check-flags [list "" { *-*-* } { "-mfloat-abi=soft" } { "" } ]] { + # Must generate floating-point instructions. + return 0 + } + if [check-flags [list "" { *-*-* } { "-mfpu=*" } { "" } ]] { + # The existing -mfpu value is OK; use it, but add softfp. + set et_arm_fp16_flags "-mfloat-abi=softfp" + return 1; + } + # Add -mfpu for a VFP fp16 variant since there is no preprocessor + # macro to check for this support. + set flags "-mfpu=vfpv4 -mfloat-abi=softfp" + if { [check_no_compiler_messages_nocache arm_fp16_ok assembly { + int dummy; + } "$flags"] } { + set et_arm_fp16_flags "$flags" + return 1 } return 0 } -proc check_effective_target_arm_neon_fp16_ok { } { - return [check_cached_effective_target arm_neon_fp16_ok \ - check_effective_target_arm_neon_fp16_ok_nocache] +proc check_effective_target_arm_fp16_ok { } { + return [check_cached_effective_target arm_fp16_ok \ + check_effective_target_arm_fp16_ok_nocache] +} + +# Creates a series of routines that return 1 if the given architecture +# can be selected and a routine to give the flags to select that architecture +# Note: Extra flags may be added to disable options from newer compilers +# (Thumb in particular - but others may be added in the future) +# Usage: /* { dg-require-effective-target arm_arch_v5_ok } */ +# /* { dg-add-options arm_arch_v5 } */ +foreach { armfunc armflag armdef } { v5 "-march=armv5 -marm" __ARM_ARCH_5__ + v6 "-march=armv6" __ARM_ARCH_6__ + v6k "-march=armv6k" __ARM_ARCH_6K__ + v7a "-march=armv7-a" __ARM_ARCH_7A__ } { + eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] { + proc check_effective_target_arm_arch_FUNC_ok { } { + if { [ string match "*-marm*" "FLAG" ] && + ![check_effective_target_arm_arm_ok] } { + return 0 + } + return [check_no_compiler_messages arm_arch_FUNC_ok assembly { + #if !defined (DEF) + #error FOO + #endif + } "FLAG" ] + } + + proc add_options_for_arm_arch_FUNC { flags } { + return "$flags FLAG" + } + }] +} + +# Return 1 if this is an ARM target where -marm causes ARM to be +# used (not Thumb) + +proc check_effective_target_arm_arm_ok { } { + return [check_no_compiler_messages arm_arm_ok assembly { + #if !defined (__arm__) || defined (__thumb__) || defined (__thumb2__) + #error FOO + #endif + } "-marm"] } + # Return 1 is this is an ARM target where -mthumb causes Thumb-1 to be # used. @@ -1963,6 +2251,43 @@ proc check_effective_target_arm_thumb2_ok { } { } "-mthumb"] } +# Return 1 if this is an ARM target where Thumb-1 is used without options +# added by the test. + +proc check_effective_target_arm_thumb1 { } { + return [check_no_compiler_messages arm_thumb1 assembly { + #if !defined(__arm__) || !defined(__thumb__) || defined(__thumb2__) + #error not thumb1 + #endif + int i; + } ""] +} + +# Return 1 if this is an ARM target where Thumb-2 is used without options +# added by the test. + +proc check_effective_target_arm_thumb2 { } { + return [check_no_compiler_messages arm_thumb2 assembly { + #if !defined(__thumb2__) + #error FOO + #endif + int i; + } ""] +} + +# Return 1 if this is an ARM cortex-M profile cpu + +proc check_effective_target_arm_cortex_m { } { + return [check_no_compiler_messages arm_cortex_m assembly { + #if !defined(__ARM_ARCH_7M__) \ + && !defined (__ARM_ARCH_7EM__) \ + && !defined (__ARM_ARCH_6M__) + #error FOO + #endif + int i; + } "-mthumb"] +} + # Return 1 if the target supports executing NEON instructions, 0 # otherwise. Cache the result. @@ -2137,7 +2462,7 @@ proc check_effective_target_powerpc_ppu_ok { } { # Return 1 if this is a PowerPC target that supports SPU. proc check_effective_target_powerpc_spu { } { - if [istarget powerpc*-*-linux*] { + if { [istarget powerpc*-*-linux*] } { return [check_effective_target_powerpc_altivec_ok] } else { return 0 @@ -2233,6 +2558,40 @@ proc check_effective_target_ultrasparc_hw { } { } "-mcpu=ultrasparc"] } +# Return 1 if the test environment supports executing UltraSPARC VIS2 +# instructions. We check this by attempting: "bmask %g0, %g0, %g0" + +proc check_effective_target_ultrasparc_vis2_hw { } { + return [check_runtime ultrasparc_vis2_hw { + int main() { __asm__(".word 0x81b00320"); return 0; } + } "-mcpu=ultrasparc3"] +} + +# Return 1 if the test environment supports executing UltraSPARC VIS3 +# instructions. We check this by attempting: "addxc %g0, %g0, %g0" + +proc check_effective_target_ultrasparc_vis3_hw { } { + return [check_runtime ultrasparc_vis3_hw { + int main() { __asm__(".word 0x81b00220"); return 0; } + } "-mcpu=niagara3"] +} + +# Return 1 if this is a Sparc target with VIS enabled. + +proc check_effective_target_sparc_vis { } { + if { [istarget sparc*-*-*] } { + return [check_no_compiler_messages sparc_vis object { + #ifndef __VIS__ + #error not VIS + #else + int dummy; + #endif + }] + } else { + return 0 + } +} + # Return 1 if the target supports hardware vector shift operation. proc check_effective_target_vect_shift { } { @@ -2258,27 +2617,26 @@ proc check_effective_target_vect_shift { } { return $et_vect_shift_saved } -# Return 1 if the target supports hardware vector shift operation with -# scalar shift argument. +# Return 1 if the target supports hardware vector shift operation for char. -proc check_effective_target_vect_shift_scalar { } { - global et_vect_shift_scalar_saved +proc check_effective_target_vect_shift_char { } { + global et_vect_shift_char_saved - if [info exists et_vect_shift_scalar_saved] { - verbose "check_effective_target_vect_shift_scalar: using cached result" 2 + if [info exists et_vect_shift_char_saved] { + verbose "check_effective_target_vect_shift_char: using cached result" 2 } else { - set et_vect_shift_scalar_saved 0 - if { [istarget x86_64-*-*] - || [istarget i?86-*-*] } { - set et_vect_shift_scalar_saved 1 - } + set et_vect_shift_char_saved 0 + if { ([istarget powerpc*-*-*] + && ![istarget powerpc-*-linux*paired*]) + || [check_effective_target_arm32] } { + set et_vect_shift_char_saved 1 + } } - verbose "check_effective_target_vect_shift_scalar: returning $et_vect_shift_scalar_saved" 2 - return $et_vect_shift_scalar_saved + verbose "check_effective_target_vect_shift_char: returning $et_vect_shift_char_saved" 2 + return $et_vect_shift_char_saved } - # Return 1 if the target supports hardware vectors of long, 0 otherwise. # # This can change for different subtargets so do not cache the result. @@ -2453,10 +2811,13 @@ proc check_effective_target_vect_perm { } { verbose "check_effective_target_vect_perm: using cached result" 2 } else { set et_vect_perm_saved 0 - if { [istarget powerpc*-*-*] + if { [is-effective-target arm_neon_ok] + || [istarget powerpc*-*-*] || [istarget spu-*-*] || [istarget i?86-*-*] - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] + || ([istarget mips*-*-*] + && [check_effective_target_mpaired_single]) } { set et_vect_perm_saved 1 } } @@ -2476,7 +2837,8 @@ proc check_effective_target_vect_perm_byte { } { verbose "check_effective_target_vect_perm_byte: using cached result" 2 } else { set et_vect_perm_byte_saved 0 - if { [istarget powerpc*-*-*] + if { [is-effective-target arm_neon_ok] + || [istarget powerpc*-*-*] || [istarget spu-*-*] } { set et_vect_perm_byte_saved 1 } @@ -2497,7 +2859,8 @@ proc check_effective_target_vect_perm_short { } { verbose "check_effective_target_vect_perm_short: using cached result" 2 } else { set et_vect_perm_short_saved 0 - if { [istarget powerpc*-*-*] + if { [is-effective-target arm_neon_ok] + || [istarget powerpc*-*-*] || [istarget spu-*-*] } { set et_vect_perm_short_saved 1 } @@ -2518,7 +2881,8 @@ proc check_effective_target_vect_widen_sum_hi_to_si_pattern { } { verbose "check_effective_target_vect_widen_sum_hi_to_si_pattern: using cached result" 2 } else { set et_vect_widen_sum_hi_to_si_pattern_saved 0 - if { [istarget powerpc*-*-*] } { + if { [istarget powerpc*-*-*] + || [istarget ia64-*-*] } { set et_vect_widen_sum_hi_to_si_pattern_saved 1 } } @@ -2613,7 +2977,8 @@ proc check_effective_target_vect_widen_mult_qi_to_hi { } { } else { set et_vect_widen_mult_qi_to_hi_saved 0 } - if { [istarget powerpc*-*-*] } { + if { [istarget powerpc*-*-*] + || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { set et_vect_widen_mult_qi_to_hi_saved 1 } } @@ -2644,8 +3009,10 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } { } if { [istarget powerpc*-*-*] || [istarget spu-*-*] + || [istarget ia64-*-*] || [istarget i?86-*-*] - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] + || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { set et_vect_widen_mult_hi_to_si_saved 1 } } @@ -2654,6 +3021,72 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } { } # Return 1 if the target plus current options supports a vector +# widening multiplication of *char* args into *short* result, 0 otherwise. +# +# This won't change for different subtargets so cache the result. + +proc check_effective_target_vect_widen_mult_qi_to_hi_pattern { } { + global et_vect_widen_mult_qi_to_hi_pattern + + if [info exists et_vect_widen_mult_qi_to_hi_pattern_saved] { + verbose "check_effective_target_vect_widen_mult_qi_to_hi_pattern: using cached result" 2 + } else { + set et_vect_widen_mult_qi_to_hi_pattern_saved 0 + if { [istarget powerpc*-*-*] + || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { + set et_vect_widen_mult_qi_to_hi_pattern_saved 1 + } + } + verbose "check_effective_target_vect_widen_mult_qi_to_hi_pattern: returning $et_vect_widen_mult_qi_to_hi_pattern_saved" 2 + return $et_vect_widen_mult_qi_to_hi_pattern_saved +} + +# Return 1 if the target plus current options supports a vector +# widening multiplication of *short* args into *int* result, 0 otherwise. +# +# This won't change for different subtargets so cache the result. + +proc check_effective_target_vect_widen_mult_hi_to_si_pattern { } { + global et_vect_widen_mult_hi_to_si_pattern + + if [info exists et_vect_widen_mult_hi_to_si_pattern_saved] { + verbose "check_effective_target_vect_widen_mult_hi_to_si_pattern: using cached result" 2 + } else { + set et_vect_widen_mult_hi_to_si_pattern_saved 0 + if { [istarget powerpc*-*-*] + || [istarget spu-*-*] + || [istarget ia64-*-*] + || [istarget i?86-*-*] + || [istarget x86_64-*-*] + || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { + set et_vect_widen_mult_hi_to_si_pattern_saved 1 + } + } + verbose "check_effective_target_vect_widen_mult_hi_to_si_pattern: returning $et_vect_widen_mult_hi_to_si_pattern_saved" 2 + return $et_vect_widen_mult_hi_to_si_pattern_saved +} + +# Return 1 if the target plus current options supports a vector +# widening shift, 0 otherwise. +# +# This won't change for different subtargets so cache the result. + +proc check_effective_target_vect_widen_shift { } { + global et_vect_widen_shift_saved + + if [info exists et_vect_shift_saved] { + verbose "check_effective_target_vect_widen_shift: using cached result" 2 + } else { + set et_vect_widen_shift_saved 0 + if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } { + set et_vect_widen_shift_saved 1 + } + } + verbose "check_effective_target_vect_widen_shift: returning $et_vect_widen_shift_saved" 2 + return $et_vect_widen_shift_saved +} + +# Return 1 if the target plus current options supports a vector # dot-product of signed chars, 0 otherwise. # # This won't change for different subtargets so cache the result. @@ -2665,6 +3098,9 @@ proc check_effective_target_vect_sdot_qi { } { verbose "check_effective_target_vect_sdot_qi: using cached result" 2 } else { set et_vect_sdot_qi_saved 0 + if { [istarget ia64-*-*] } { + set et_vect_udot_qi_saved 1 + } } verbose "check_effective_target_vect_sdot_qi: returning $et_vect_sdot_qi_saved" 2 return $et_vect_sdot_qi_saved @@ -2682,7 +3118,8 @@ proc check_effective_target_vect_udot_qi { } { verbose "check_effective_target_vect_udot_qi: using cached result" 2 } else { set et_vect_udot_qi_saved 0 - if { [istarget powerpc*-*-*] } { + if { [istarget powerpc*-*-*] + || [istarget ia64-*-*] } { set et_vect_udot_qi_saved 1 } } @@ -2703,6 +3140,7 @@ proc check_effective_target_vect_sdot_hi { } { } else { set et_vect_sdot_hi_saved 0 if { ([istarget powerpc*-*-*] && ![istarget powerpc-*-linux*paired*]) + || [istarget ia64-*-*] || [istarget i?86-*-*] || [istarget x86_64-*-*] } { set et_vect_sdot_hi_saved 1 @@ -2750,7 +3188,8 @@ proc check_effective_target_vect_pack_trunc { } { || [istarget i?86-*-*] || [istarget x86_64-*-*] || [istarget spu-*-*] - || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { + || ([istarget arm*-*-*] && [check_effective_target_arm_neon] + && [check_effective_target_arm_little_endian]) } { set et_vect_pack_trunc_saved 1 } } @@ -2774,7 +3213,9 @@ proc check_effective_target_vect_unpack { } { || [istarget i?86-*-*] || [istarget x86_64-*-*] || [istarget spu-*-*] - || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { + || [istarget ia64-*-*] + || ([istarget arm*-*-*] && [check_effective_target_arm_neon] + && [check_effective_target_arm_little_endian]) } { set et_vect_unpack_saved 1 } } @@ -2857,9 +3298,14 @@ proc check_effective_target_vect_aligned_arrays { } { verbose "check_effective_target_vect_aligned_arrays: using cached result" 2 } else { set et_vect_aligned_arrays_saved 0 - if { (([istarget x86_64-*-*] - || [istarget i?86-*-*]) && [is-effective-target lp64]) - || [istarget spu-*-*] } { + if { ([istarget x86_64-*-*] || [istarget i?86-*-*]) } { + if { ([is-effective-target lp64] + && ( ![check_avx_available] + || [check_prefer_avx128])) } { + set et_vect_aligned_arrays_saved 1 + } + } + if [istarget spu-*-*] { set et_vect_aligned_arrays_saved 1 } } @@ -2960,7 +3406,8 @@ proc check_effective_target_vect_element_align { } { verbose "check_effective_target_vect_element_align: using cached result" 2 } else { set et_vect_element_align 0 - if { [istarget arm*-*-*] + if { ([istarget arm*-*-*] + && ![check_effective_target_arm_vect_no_misalign]) || [check_effective_target_vect_hw_misalign] } { set et_vect_element_align 1 } @@ -2983,7 +3430,8 @@ proc check_effective_target_vect_condition { } { || [istarget ia64-*-*] || [istarget i?86-*-*] || [istarget spu-*-*] - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] + || ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } { set et_vect_cond_saved 1 } } @@ -2992,6 +3440,27 @@ proc check_effective_target_vect_condition { } { return $et_vect_cond_saved } +# Return 1 if the target supports vector conditional operations where +# the comparison has different type from the lhs, 0 otherwise. + +proc check_effective_target_vect_cond_mixed { } { + global et_vect_cond_mixed_saved + + if [info exists et_vect_cond_mixed_saved] { + verbose "check_effective_target_vect_cond_mixed: using cached result" 2 + } else { + set et_vect_cond_mixed_saved 0 + if { [istarget i?86-*-*] + || [istarget x86_64-*-*] + || [istarget powerpc*-*-*] } { + set et_vect_cond_mixed_saved 1 + } + } + + verbose "check_effective_target_vect_cond_mixed: returning $et_vect_cond_mixed_saved" 2 + return $et_vect_cond_mixed_saved +} + # Return 1 if the target supports vector char multiplication, 0 otherwise. proc check_effective_target_vect_char_mult { } { @@ -3050,6 +3519,7 @@ proc check_effective_target_vect_int_mult { } { || [istarget spu-*-*] || [istarget i?86-*-*] || [istarget x86_64-*-*] + || [istarget ia64-*-*] || [check_effective_target_arm32] } { set et_vect_int_mult_saved 1 } @@ -3069,10 +3539,14 @@ proc check_effective_target_vect_extract_even_odd { } { } else { set et_vect_extract_even_odd_saved 0 if { [istarget powerpc*-*-*] + || [is-effective-target arm_neon_ok] || [istarget i?86-*-*] || [istarget x86_64-*-*] - || [istarget spu-*-*] } { - set et_vect_extract_even_odd_saved 1 + || [istarget ia64-*-*] + || [istarget spu-*-*] + || ([istarget mips*-*-*] + && [check_effective_target_mpaired_single]) } { + set et_vect_extract_even_odd_saved 1 } } @@ -3080,28 +3554,6 @@ proc check_effective_target_vect_extract_even_odd { } { return $et_vect_extract_even_odd_saved } -# Return 1 if the target supports vector even/odd elements extraction of -# vectors with SImode elements or larger, 0 otherwise. - -proc check_effective_target_vect_extract_even_odd_wide { } { - global et_vect_extract_even_odd_wide_saved - - if [info exists et_vect_extract_even_odd_wide_saved] { - verbose "check_effective_target_vect_extract_even_odd_wide: using cached result" 2 - } else { - set et_vect_extract_even_odd_wide_saved 0 - if { [istarget powerpc*-*-*] - || [istarget i?86-*-*] - || [istarget x86_64-*-*] - || [istarget spu-*-*] } { - set et_vect_extract_even_odd_wide_saved 1 - } - } - - verbose "check_effective_target_vect_extract_even_wide_odd: returning $et_vect_extract_even_odd_wide_saved" 2 - return $et_vect_extract_even_odd_wide_saved -} - # Return 1 if the target supports vector interleaving, 0 otherwise. proc check_effective_target_vect_interleave { } { @@ -3112,9 +3564,13 @@ proc check_effective_target_vect_interleave { } { } else { set et_vect_interleave_saved 0 if { [istarget powerpc*-*-*] + || [is-effective-target arm_neon_ok] || [istarget i?86-*-*] || [istarget x86_64-*-*] - || [istarget spu-*-*] } { + || [istarget ia64-*-*] + || [istarget spu-*-*] + || ([istarget mips*-*-*] + && [check_effective_target_mpaired_single]) } { set et_vect_interleave_saved 1 } } @@ -3123,41 +3579,119 @@ proc check_effective_target_vect_interleave { } { return $et_vect_interleave_saved } -# Return 1 if the target supports vector interleaving and extract even/odd, 0 otherwise. -proc check_effective_target_vect_strided { } { - global et_vect_strided_saved +foreach N {2 3 4 8} { + eval [string map [list N $N] { + # Return 1 if the target supports 2-vector interleaving + proc check_effective_target_vect_stridedN { } { + global et_vect_stridedN_saved + + if [info exists et_vect_stridedN_saved] { + verbose "check_effective_target_vect_stridedN: using cached result" 2 + } else { + set et_vect_stridedN_saved 0 + if { (N & -N) == N + && [check_effective_target_vect_interleave] + && [check_effective_target_vect_extract_even_odd] } { + set et_vect_stridedN_saved 1 + } + if { [istarget arm*-*-*] && N >= 2 && N <= 4 } { + set et_vect_stridedN_saved 1 + } + } + + verbose "check_effective_target_vect_stridedN: returning $et_vect_stridedN_saved" 2 + return $et_vect_stridedN_saved + } + }] +} + +# Return 1 if the target supports multiple vector sizes + +proc check_effective_target_vect_multiple_sizes { } { + global et_vect_multiple_sizes_saved + + set et_vect_multiple_sizes_saved 0 + if { ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } { + set et_vect_multiple_sizes_saved 1 + } + if { ([istarget x86_64-*-*] || [istarget i?86-*-*]) } { + if { ([check_avx_available] && ![check_prefer_avx128]) } { + set et_vect_multiple_sizes_saved 1 + } + } - if [info exists et_vect_strided_saved] { - verbose "check_effective_target_vect_strided: using cached result" 2 + verbose "check_effective_target_vect_multiple_sizes: returning $et_vect_multiple_sizes_saved" 2 + return $et_vect_multiple_sizes_saved +} + +# Return 1 if the target supports vectors of 64 bits. + +proc check_effective_target_vect64 { } { + global et_vect64_saved + + if [info exists et_vect64_saved] { + verbose "check_effective_target_vect64: using cached result" 2 } else { - set et_vect_strided_saved 0 - if { [check_effective_target_vect_interleave] - && [check_effective_target_vect_extract_even_odd] } { - set et_vect_strided_saved 1 + set et_vect64_saved 0 + if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } { + set et_vect64_saved 1 } } - verbose "check_effective_target_vect_strided: returning $et_vect_strided_saved" 2 - return $et_vect_strided_saved + verbose "check_effective_target_vect64: returning $et_vect64_saved" 2 + return $et_vect64_saved } -# Return 1 if the target supports vector interleaving and extract even/odd -# for wide element types, 0 otherwise. -proc check_effective_target_vect_strided_wide { } { - global et_vect_strided_wide_saved +# Return 1 if the target supports vector copysignf calls. - if [info exists et_vect_strided_wide_saved] { - verbose "check_effective_target_vect_strided_wide: using cached result" 2 +proc check_effective_target_vect_call_copysignf { } { + global et_vect_call_copysignf_saved + + if [info exists et_vect_call_copysignf_saved] { + verbose "check_effective_target_vect_call_copysignf: using cached result" 2 } else { - set et_vect_strided_wide_saved 0 - if { [check_effective_target_vect_interleave] - && [check_effective_target_vect_extract_even_odd_wide] } { - set et_vect_strided_wide_saved 1 - } + set et_vect_call_copysignf_saved 0 + if { [istarget i?86-*-*] + || [istarget x86_64-*-*] + || [istarget powerpc*-*-*] } { + set et_vect_call_copysignf_saved 1 + } + } + + verbose "check_effective_target_vect_call_copysignf: returning $et_vect_call_copysignf_saved" 2 + return $et_vect_call_copysignf_saved +} + +# Return 1 if the target supports vector sqrtf calls. + +proc check_effective_target_vect_call_sqrtf { } { + global et_vect_call_sqrtf_saved + + if [info exists et_vect_call_sqrtf_saved] { + verbose "check_effective_target_vect_call_sqrtf: using cached result" 2 + } else { + set et_vect_call_sqrtf_saved 0 + if { [istarget i?86-*-*] + || [istarget x86_64-*-*] + || ([istarget powerpc*-*-*] && [check_vsx_hw_available]) } { + set et_vect_call_sqrtf_saved 1 + } + } + + verbose "check_effective_target_vect_call_sqrtf: returning $et_vect_call_sqrtf_saved" 2 + return $et_vect_call_sqrtf_saved +} + +# Return 1 if the target supports vector lrint calls. + +proc check_effective_target_vect_call_lrint { } { + set et_vect_call_lrint 0 + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) && [check_effective_target_ilp32] } { + set et_vect_call_lrint 1 } - verbose "check_effective_target_vect_strided_wide: returning $et_vect_strided_wide_saved" 2 - return $et_vect_strided_wide_saved + verbose "check_effective_target_vect_call_lrint: returning $et_vect_call_lrint" 2 + return $et_vect_call_lrint } # Return 1 if the target supports section-anchors @@ -3179,6 +3713,98 @@ proc check_effective_target_section_anchors { } { return $et_section_anchors_saved } +# Return 1 if the target supports atomic operations on "int_128" values. + +proc check_effective_target_sync_int_128 { } { + if { ([istarget x86_64-*-*] || [istarget i?86-*-*]) + && ![is-effective-target ia32] } { + return 1 + } else { + return 0 + } +} + +# Return 1 if the target supports atomic operations on "int_128" values +# and can execute them. + +proc check_effective_target_sync_int_128_runtime { } { + if { ([istarget x86_64-*-*] || [istarget i?86-*-*]) + && ![is-effective-target ia32] } { + return [check_cached_effective_target sync_int_128_available { + check_runtime_nocache sync_int_128_available { + #include "cpuid.h" + int main () + { + unsigned int eax, ebx, ecx, edx; + if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return !(ecx & bit_CMPXCHG16B); + return 1; + } + } "" + }] + } else { + return 0 + } +} + +# Return 1 if the target supports atomic operations on "long long". +# +# Note: 32bit x86 targets require -march=pentium in dg-options. + +proc check_effective_target_sync_long_long { } { + if { [istarget x86_64-*-*] + || [istarget i?86-*-*]) + || [istarget arm*-*-*] + || [istarget alpha*-*-*] } { + return 1 + } else { + return 0 + } +} + +# Return 1 if the target supports atomic operations on "long long" +# and can execute them. +# +# Note: 32bit x86 targets require -march=pentium in dg-options. + +proc check_effective_target_sync_long_long_runtime { } { + if { [istarget x86_64-*-*] + || [istarget i?86-*-*] } { + return [check_cached_effective_target sync_long_long_available { + check_runtime_nocache sync_long_long_available { + #include "cpuid.h" + int main () + { + unsigned int eax, ebx, ecx, edx; + if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return !(edx & bit_CMPXCHG8B); + return 1; + } + } "" + }] + } elseif { [istarget arm*-*-linux-gnueabi] } { + return [check_runtime sync_longlong_runtime { + #include + int main () + { + long long l1; + + if (sizeof (long long) != 8) + exit (1); + + /* Just check for native; checking for kernel fallback is tricky. */ + asm volatile ("ldrexd r0,r1, [%0]" : : "r" (&l1) : "r0", "r1"); + + exit (0); + } + } "" ] + } elseif { [istarget alpha*-*-*] } { + return 1 + } else { + return 0 + } +} + # Return 1 if the target supports atomic operations on "int" and "long". proc check_effective_target_sync_int_long { } { @@ -3201,7 +3827,7 @@ proc check_effective_target_sync_int_long { } { || [istarget powerpc*-*-*] || [istarget sparc64-*-*] || [istarget sparcv9-*-*] - || [istarget mips*-*-*] } { + || [check_effective_target_mips_llsc] } { set et_sync_int_long_saved 1 } } @@ -3231,7 +3857,7 @@ proc check_effective_target_sync_char_short { } { || [istarget powerpc*-*-*] || [istarget sparc64-*-*] || [istarget sparcv9-*-*] - || [istarget mips*-*-*] } { + || [check_effective_target_mips_llsc] } { set et_sync_char_short_saved 1 } } @@ -3471,16 +4097,25 @@ proc check_effective_target_fd_truncate { } { int fd; const char t[] = "test writing more than ten characters"; char s[11]; - fd = fileno (f); + int status = 0; + fd = fileno (f); write (fd, t, sizeof (t) - 1); lseek (fd, 0, 0); if (ftruncate (fd, 10) != 0) - exit (1); + status = 1; close (fd); + fclose (f); + if (status) + { + unlink ("tst.tmp"); + exit (status); + } f = fopen ("tst.tmp", "rb"); if (fread (s, 1, sizeof (s), f) != 10 || strncmp (s, t, 10) != 0) - exit (1); - exit (0); + status = 1; + fclose (f); + unlink ("tst.tmp"); + exit (status); } } @@ -3498,6 +4133,9 @@ proc add_options_for_c99_runtime { flags } { if { [istarget *-*-solaris2*] } { return "$flags -std=c99" } + if { [istarget mips-sgi-irix6.5*] } { + return "$flags -std=c99" + } if { [istarget powerpc-*-darwin*] } { return "$flags -mmacosx-version-min=10.3" } @@ -3508,10 +4146,13 @@ proc add_options_for_c99_runtime { flags } { # full IEEE compliance mode. proc add_options_for_ieee { flags } { - if { [istarget "alpha*-*-*"] - || [istarget "sh*-*-*"] } { + if { [istarget alpha*-*-*] + || [istarget sh*-*-*] } { return "$flags -mieee" } + if { [istarget rx-*-*] } { + return "$flags -mnofpu" + } return $flags } @@ -3537,11 +4178,11 @@ proc add_options_for_bind_pic_locally { flags } { return $flags } -# Add to FLAGS the flags needed to enable 128-bit vectors. +# Add to FLAGS the flags needed to enable 64-bit vectors. -proc add_options_for_quad_vectors { flags } { +proc add_options_for_double_vectors { flags } { if [is-effective-target arm_neon_ok] { - return "$flags -mvectorize-with-neon-quad" + return "$flags -mvectorize-with-neon-double" } return $flags @@ -3588,6 +4229,39 @@ proc check_effective_target_automatic_stack_alignment { } { return 0; } +# Return true if we are compiling for AVX target. + +proc check_avx_available { } { + if { [check_no_compiler_messages avx_available assembly { + #ifndef __AVX__ + #error unsupported + #endif + } ""] } { + return 1; + } + return 0; +} + +# Return true if 32- and 16-bytes vectors are available. + +proc check_effective_target_vect_sizes_32B_16B { } { + return [check_avx_available]; +} + +# Return true if 128-bits vectors are preferred even if 256-bits vectors +# are available. + +proc check_prefer_avx128 { } { + if ![check_avx_available] { + return 0; + } + return [check_no_messages_and_pattern avx_explicit "xmm" assembly { + float a[1024],b[1024],c[1024]; + void foo (void) { int i; for (i = 0; i < 1024; i++) a[i]=b[i]+c[i];} + } "-O2 -ftree-vectorize"] +} + + # Return 1 if avx instructions can be compiled. proc check_effective_target_avx { } { @@ -3717,6 +4391,26 @@ proc check_effective_target_gas { } { return $use_gas_saved } +# Return 1 if GNU ld is used. + +proc check_effective_target_gld { } { + global use_gld_saved + global tool + + if {![info exists use_gld_saved]} { + # Check if the ld used by gcc is GNU ld. + set gcc_ld [lindex [${tool}_target_compile "-print-prog-name=ld" "" "none" ""] 0] + set status [remote_exec host "$gcc_ld" "--version"] + set ld_output [lindex $status 1] + if { [ string first "GNU" $ld_output ] >= 0 } { + set use_gld_saved 1 + } else { + set use_gld_saved 0 + } + } + return $use_gld_saved +} + # Return 1 if the compiler has been configure with link-time optimization # (LTO) support. @@ -3754,6 +4448,24 @@ proc check_effective_target_c++ { } { return 0 } +# Check which language standard is active by checking for the presence of +# one of the C++11 -std flags. This assumes that the default for the +# compiler is C++98, and that there will never be multiple -std= arguments +# on the command line. +proc check_effective_target_c++11 { } { + if ![check_effective_target_c++] { + return 0 + } + return [check-flags { { } { } { -std=c++0x -std=gnu++0x -std=c++11 -std=gnu++11 } }] +} + +proc check_effective_target_c++98 { } { + if ![check_effective_target_c++] { + return 0 + } + return [check-flags { { } { } { } { -std=c++0x -std=gnu++0x -std=c++11 -std=gnu++11 } }] +} + # Return 1 if expensive testcases should be run. proc check_effective_target_run_expensive_tests { } { @@ -3768,3 +4480,114 @@ proc check_effective_target_run_expensive_tests { } { proc check_effective_target_mempcpy {} { return [check_function_available "mempcpy"] } + +# Check whether the vectorizer tests are supported by the target and +# append additional target-dependent compile flags to DEFAULT_VECTCFLAGS. +# Set dg-do-what-default to either compile or run, depending on target +# capabilities. Return 1 if vectorizer tests are supported by +# target, 0 otherwise. + +proc check_vect_support_and_set_flags { } { + global DEFAULT_VECTCFLAGS + global dg-do-what-default + + if [istarget powerpc-*paired*] { + lappend DEFAULT_VECTCFLAGS "-mpaired" + if [check_750cl_hw_available] { + set dg-do-what-default run + } else { + set dg-do-what-default compile + } + } elseif [istarget powerpc*-*-*] { + # Skip targets not supporting -maltivec. + if ![is-effective-target powerpc_altivec_ok] { + return 0 + } + + lappend DEFAULT_VECTCFLAGS "-maltivec" + if [check_vsx_hw_available] { + lappend DEFAULT_VECTCFLAGS "-mvsx" "-mno-allow-movmisalign" + } + + if [check_vmx_hw_available] { + set dg-do-what-default run + } else { + if [is-effective-target ilp32] { + # Specify a cpu that supports VMX for compile-only tests. + lappend DEFAULT_VECTCFLAGS "-mcpu=970" + } + set dg-do-what-default compile + } + } elseif { [istarget spu-*-*] } { + set dg-do-what-default run + } elseif { [istarget i?86-*-*] || [istarget x86_64-*-*] } { + lappend DEFAULT_VECTCFLAGS "-msse2" + if { [check_effective_target_sse2_runtime] } { + set dg-do-what-default run + } else { + set dg-do-what-default compile + } + } elseif { [istarget mips*-*-*] + && ([check_effective_target_mpaired_single] + || [check_effective_target_mips_loongson]) + && [check_effective_target_nomips16] } { + if { [check_effective_target_mpaired_single] } { + lappend DEFAULT_VECTCFLAGS "-mpaired-single" + } + set dg-do-what-default run + } elseif [istarget sparc*-*-*] { + lappend DEFAULT_VECTCFLAGS "-mcpu=ultrasparc" "-mvis" + if [check_effective_target_ultrasparc_hw] { + set dg-do-what-default run + } else { + set dg-do-what-default compile + } + } elseif [istarget alpha*-*-*] { + # Alpha's vectorization capabilities are extremely limited. + # It's more effort than its worth disabling all of the tests + # that it cannot pass. But if you actually want to see what + # does work, command out the return. + return 0 + + lappend DEFAULT_VECTCFLAGS "-mmax" + if [check_alpha_max_hw_available] { + set dg-do-what-default run + } else { + set dg-do-what-default compile + } + } elseif [istarget ia64-*-*] { + set dg-do-what-default run + } elseif [is-effective-target arm_neon_ok] { + eval lappend DEFAULT_VECTCFLAGS [add_options_for_arm_neon ""] + # NEON does not support denormals, so is not used for vectorization by + # default to avoid loss of precision. We must pass -ffast-math to test + # vectorization of float operations. + lappend DEFAULT_VECTCFLAGS "-ffast-math" + if [is-effective-target arm_neon_hw] { + set dg-do-what-default run + } else { + set dg-do-what-default compile + } + } else { + return 0 + } + + return 1 +} + +proc check_effective_target_non_strict_align {} { + return [check_no_compiler_messages non_strict_align assembly { + char *y; + typedef char __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) c; + c *z; + void foo(void) { z = (c *) y; } + } "-Wcast-align"] +} + +# Return 1 if the target has . + +proc check_effective_target_ucontext_h { } { + return [check_no_compiler_messages ucontext_h assembly { + #include + }] +}