From patchwork Mon Nov 1 23:15:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 69854 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 857A31007D3 for ; Tue, 2 Nov 2010 10:15:46 +1100 (EST) Received: (qmail 31843 invoked by alias); 1 Nov 2010 23:15:44 -0000 Received: (qmail 31826 invoked by uid 22791); 1 Nov 2010 23:15:36 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL, BAYES_00, NO_DNS_FOR_FROM, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from e9.ny.us.ibm.com (HELO e9.ny.us.ibm.com) (32.97.182.139) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 01 Nov 2010 23:15:27 +0000 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by e9.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id oA1MsQ3u020747 for ; Mon, 1 Nov 2010 18:54:26 -0400 Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id oA1NFPQk340618 for ; Mon, 1 Nov 2010 19:15:25 -0400 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id oA1NFOqO015512 for ; Mon, 1 Nov 2010 19:15:25 -0400 Received: from hungry-tiger.westford.ibm.com (dyn9033037049.westford.ibm.com [9.33.37.49]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id oA1NFOd8015491; Mon, 1 Nov 2010 19:15:24 -0400 Received: by hungry-tiger.westford.ibm.com (Postfix, from userid 500) id 2E0D6F84CC; Mon, 1 Nov 2010 19:15:22 -0400 (EDT) Date: Mon, 1 Nov 2010 19:15:22 -0400 From: Michael Meissner To: Michael Meissner , "Joseph S. Myers" , gcc-patches@gcc.gnu.org, dje.gcc@gmail.com Subject: Re: [PATCH] Add attribute((target("..."))) and pragma target to PowerPC Message-ID: <20101101231522.GA22461@hungry-tiger.westford.ibm.com> Mail-Followup-To: Michael Meissner , "Joseph S. Myers" , gcc-patches@gcc.gnu.org, dje.gcc@gmail.com References: <20101031182504.GA14215@hungry-tiger.westford.ibm.com> <20101101174906.GA8243@hungry-tiger.westford.ibm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20101101174906.GA8243@hungry-tiger.westford.ibm.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On Mon, Nov 01, 2010 at 01:49:06PM -0400, Michael Meissner wrote: > The simplest way to fix this is to require the user on 32-bit to use an > explicit -maltivec-abi switch if they want to switch to a power7 cpu or enable > altivec (similarly for the rs6000_spe_abi, rs6000_float_gprs, and > rs6000_darwin64_abi variables). Whoops, that should be -mabi=altivec. The following patch applied on top of my previous patch, will give an error if any option changes the various abi's. It also changes the debug information somewhat. Does this answer your objection? [gcc] 2010-11-01 Michael Meissner * config/rs6000/rs6000.c (rs6000_debug_reg_global): Add more debugging information for -mdebug=reg (cpu, tuning, the status of various abis, tls size, and long double size). (rs6000_init_hard_regno_mode_ok): Only print debug information for -mdebug=reg for the global initialization, not for target attributes, unless -mdebug=target is used. (rs6000_option_override_internal): Update rs6000_cpu_index and rs6000_tune_index when default choices are made. If a target attribute changes the cpu, but does not change the tuning, use the cpu specified instead of the default specified on the command line. Silently disable power7 generating vsx/altivec by default if 32-bit and -maltivec-abi was not used. Given an error if a target attribute changes an option that would involve changing the abi, such as Altivec, SPE, darwin64, etc. (rs6000_conditional_register_usage): Just print trace if -mdebug=target, not -mdebug=reg. (rs6000_valid_attribute_p): Reset default cpu/tune before parsing target attributes/pragmas. (rs6000_pragma_target_parse): Ditto. * doc/extend.texi (Function Attributes): Describe restriction on not using Altivec/VSX if altivec abi was not enabled. Describe using the cpu= attribute/pragma default for tuning if tune= attribute/pragma was not specified. [gcc/testsuite] 2010-11-01 Michael Meissner * gcc.target/powerpc/ppc-target-1.c: Add -mabi=altivec to compile switches. * gcc.target/powerpc/ppc-target-2.c: Ditto. * gcc.target/powerpc/ppc-target-3.c: New test, test that target attribute cpu=power7 does not enable VSX, Altivec on 32-bit without -mabi=altivec. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 166106) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -2014,16 +2014,25 @@ rs6000_debug_reg_print (int first_regno, } } +#define DEBUG_FMT_D "%-32s= %d\n" +#define DEBUG_FMT_S "%-32s= %s\n" + /* Print various interesting information with -mdebug=reg. */ static void rs6000_debug_reg_global (void) { + static const char *const tf[2] = { "false", "true" }; const char *nl = (const char *)0; int m; char costly_num[20]; char nop_num[20]; const char *costly_str; const char *nop_str; + const char *trace_str; + const char *cmodel_str; /* Map enum rs6000_vector to string. */ static const char *rs6000_debug_vector_unit[] = { @@ -2103,6 +2110,14 @@ rs6000_debug_reg_global (void) fputs ("\n", stderr); } + if (rs6000_cpu_index >= 0) + fprintf (stderr, DEBUG_FMT_S, "cpu", + processor_target_table[rs6000_cpu_index].name); + + if (rs6000_tune_index >= 0) + fprintf (stderr, DEBUG_FMT_S, "tune", + processor_target_table[rs6000_tune_index].name); + switch (rs6000_sched_costly_dep) { case max_dep_latency: @@ -2131,6 +2146,8 @@ rs6000_debug_reg_global (void) break; } + fprintf (stderr, DEBUG_FMT_S, "sched_costly_dep", costly_str); + switch (rs6000_sched_insert_nops) { case sched_finish_regroup_exact: @@ -2151,21 +2168,83 @@ rs6000_debug_reg_global (void) break; } - fprintf (stderr, - "always_hint = %s\n" - "align_branch_targets = %s\n" - "sched_restricted_insns_priority = %d\n" - "sched_costly_dep = %s\n" - "sched_insert_nops = %s\n\n", - rs6000_always_hint ? "true" : "false", - rs6000_align_branch_targets ? "true" : "false", - (int)rs6000_sched_restricted_insns_priority, - costly_str, nop_str); + fprintf (stderr, DEBUG_FMT_S, "sched_insert_nops", nop_str); + + switch (rs6000_sdata) + { + default: + case SDATA_NONE: + break; + + case SDATA_DATA: + fprintf (stderr, DEBUG_FMT_S, "sdata", "data"); + break; + + case SDATA_SYSV: + fprintf (stderr, DEBUG_FMT_S, "sdata", "sysv"); + break; + + case SDATA_EABI: + fprintf (stderr, DEBUG_FMT_S, "sdata", "eabi"); + break; + + } + + switch (rs6000_traceback) + { + case traceback_default: trace_str = "default"; break; + case traceback_none: trace_str = "none"; break; + case traceback_part: trace_str = "part"; break; + case traceback_full: trace_str = "full"; break; + default: trace_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "traceback", trace_str); + + switch (rs6000_current_cmodel) + { + case CMODEL_SMALL: cmodel_str = "small"; break; + case CMODEL_MEDIUM: cmodel_str = "medium"; break; + case CMODEL_LARGE: cmodel_str = "large"; break; + default: cmodel_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "cmodel", cmodel_str); + + switch (rs6000_current_abi) + { + case ABI_NONE: abi_str = "none"; break; + case ABI_AIX: abi_str = "aix"; break; + case ABI_V4: abi_str = "V4"; break; + case ABI_DARWIN: abi_str = "darwin"; break; + default: abi_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "abi", abi_str); + + if (rs6000_altivec_abi) + fprintf (stderr, DEBUG_FMT_S, "altivec_abi", "true"); + + if (rs6000_spe_abi) + fprintf (stderr, DEBUG_FMT_S, "spe_abi", "true"); + + if (rs6000_darwin64_abi) + fprintf (stderr, DEBUG_FMT_S, "darwin64_abi", "true"); + + if (rs6000_float_gprs) + fprintf (stderr, DEBUG_FMT_S, "float_gprs", "true"); + + fprintf (stderr, DEBUG_FMT_S, "always_hint", tf[!!rs6000_always_hint]); + fprintf (stderr, DEBUG_FMT_S, "align_branch", + tf[!!rs6000_align_branch_targets]); + fprintf (stderr, DEBUG_FMT_D, "tls_size", rs6000_tls_size); + fprintf (stderr, DEBUG_FMT_D, "long_double_size", + rs6000_long_double_type_size); + fprintf (stderr, DEBUG_FMT_D, "sched_restricted_insns_priority", + (int)rs6000_sched_restricted_insns_priority); } /* Initialize the various global tables that are based on register size. */ static void -rs6000_init_hard_regno_mode_ok (void) +rs6000_init_hard_regno_mode_ok (bool global_init_p) { int r, m, c; int align64; @@ -2461,40 +2540,43 @@ rs6000_init_hard_regno_mode_ok (void) } } - if (TARGET_DEBUG_REG) - rs6000_debug_reg_global (); + if (global_init_p || TARGET_DEBUG_TARGET) + { + if (TARGET_DEBUG_REG) + rs6000_debug_reg_global (); - if (TARGET_DEBUG_COST || TARGET_DEBUG_REG) - fprintf (stderr, - "SImode variable mult cost = %d\n" - "SImode constant mult cost = %d\n" - "SImode short constant mult cost = %d\n" - "DImode multipliciation cost = %d\n" - "SImode division cost = %d\n" - "DImode division cost = %d\n" - "Simple fp operation cost = %d\n" - "DFmode multiplication cost = %d\n" - "SFmode division cost = %d\n" - "DFmode division cost = %d\n" - "cache line size = %d\n" - "l1 cache size = %d\n" - "l2 cache size = %d\n" - "simultaneous prefetches = %d\n" - "\n", - rs6000_cost->mulsi, - rs6000_cost->mulsi_const, - rs6000_cost->mulsi_const9, - rs6000_cost->muldi, - rs6000_cost->divsi, - rs6000_cost->divdi, - rs6000_cost->fp, - rs6000_cost->dmul, - rs6000_cost->sdiv, - rs6000_cost->ddiv, - rs6000_cost->cache_line_size, - rs6000_cost->l1_cache_size, - rs6000_cost->l2_cache_size, - rs6000_cost->simultaneous_prefetches); + if (TARGET_DEBUG_COST || TARGET_DEBUG_REG) + fprintf (stderr, + "SImode variable mult cost = %d\n" + "SImode constant mult cost = %d\n" + "SImode short constant mult cost = %d\n" + "DImode multipliciation cost = %d\n" + "SImode division cost = %d\n" + "DImode division cost = %d\n" + "Simple fp operation cost = %d\n" + "DFmode multiplication cost = %d\n" + "SFmode division cost = %d\n" + "DFmode division cost = %d\n" + "cache line size = %d\n" + "l1 cache size = %d\n" + "l2 cache size = %d\n" + "simultaneous prefetches = %d\n" + "\n", + rs6000_cost->mulsi, + rs6000_cost->mulsi_const, + rs6000_cost->mulsi_const9, + rs6000_cost->muldi, + rs6000_cost->divsi, + rs6000_cost->divdi, + rs6000_cost->fp, + rs6000_cost->dmul, + rs6000_cost->sdiv, + rs6000_cost->ddiv, + rs6000_cost->cache_line_size, + rs6000_cost->l1_cache_size, + rs6000_cost->l2_cache_size, + rs6000_cost->simultaneous_prefetches); + } } #if TARGET_MACHO @@ -2570,9 +2652,11 @@ rs6000_option_override_internal (bool gl bool ret = true; const char *default_cpu = OPTION_TARGET_CPU_DEFAULT; int set_masks; - int defcpu_index; int cpu_index; int tune_index; + struct cl_target_option *main_target_opt + = ((global_init_p || target_option_default_node == NULL) + ? NULL : TREE_TARGET_OPTION (target_option_default_node)); /* Numerous experiment shows that IRA based loop pressure calculation works better for RTL loop invariant motion on targets @@ -2615,9 +2699,21 @@ rs6000_option_override_internal (bool gl default_cpu = "powerpc"; } - defcpu_index = rs6000_cpu_name_lookup (default_cpu); - cpu_index = (rs6000_cpu_index > 0) ? rs6000_cpu_index : defcpu_index; - tune_index = (rs6000_tune_index > 0) ? rs6000_tune_index : cpu_index; + /* Process the -mcpu= and -mtune= argument. If the user changed + the cpu in a target attribute or pragma, but did not specify a tuning + option, use the cpu for the tuning option rather than the option specified + with -mtune on the command line. */ + if (rs6000_cpu_index > 0) + cpu_index = rs6000_cpu_index; + else if (main_target_opt != NULL && main_target_opt->x_rs6000_cpu_index > 0) + rs6000_cpu_index = cpu_index = main_target_opt->x_rs6000_cpu_index; + else + rs6000_cpu_index = cpu_index = rs6000_cpu_name_lookup (default_cpu); + + if (rs6000_tune_index > 0) + tune_index = rs6000_tune_index; + else + rs6000_tune_index = tune_index = cpu_index; if (cpu_index >= 0) { @@ -2790,16 +2886,37 @@ rs6000_option_override_internal (bool gl } if (!rs6000_explicit_options.long_double) - rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE; + { + if (main_target_opt != NULL + && (main_target_opt->x_rs6000_long_double_type_size + != RS6000_DEFAULT_LONG_DOUBLE_SIZE)) + error ("You cannot change long double size within a target attribute " + "or pragma"); + else + rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE; + } #ifndef POWERPC_LINUX if (!rs6000_explicit_options.ieee) rs6000_ieeequad = 1; #endif + /* Disable VSX and Altivec silently if the user switched cpus to power7 in a + target attribute or pragma which automatically enables both options, + unless the altivec ABI was set. This is set by default for 64-bit, but + not for 32-bit. */ + if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi) + target_flags &= ~((MASK_VSX | MASK_ALTIVEC) & ~target_flags_explicit); + /* Enable Altivec ABI for AIX -maltivec. */ if (TARGET_XCOFF && (TARGET_ALTIVEC || TARGET_VSX)) - rs6000_altivec_abi = 1; + { + if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi) + error ("You cannot switch to the altivec abi within a target " + "attribute or pragma"); + else + rs6000_altivec_abi = 1; + } /* The AltiVec ABI is the default for PowerPC-64 GNU/Linux. For PowerPC-32 GNU/Linux, -maltivec implies the AltiVec ABI. It can @@ -2808,7 +2925,14 @@ rs6000_option_override_internal (bool gl { if (!rs6000_explicit_options.altivec_abi && (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX)) - rs6000_altivec_abi = 1; + { + if (main_target_opt != NULL && + !main_target_opt->x_rs6000_altivec_abi) + error ("You cannot switch to the altivec abi within a target " + "attribute or pragma"); + else + rs6000_altivec_abi = 1; + } /* Enable VRSAVE for AltiVec ABI, unless explicitly overridden. */ if (!rs6000_explicit_options.vrsave) @@ -2821,9 +2945,15 @@ rs6000_option_override_internal (bool gl && DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT) { - rs6000_darwin64_abi = 1; - /* Default to natural alignment, for better performance. */ - rs6000_alignment_flags = MASK_ALIGN_NATURAL; + if (main_target_opt != NULL && !main_target_opt->x_rs6000_darwin64_abi) + error ("You cannot switch to the darwin64 abi within a target " + "attribute or pragma"); + else + { + rs6000_darwin64_abi = 1; + /* Default to natural alignment, for better performance. */ + rs6000_alignment_flags = MASK_ALIGN_NATURAL; + } } /* Place FP constants in the constant pool instead of TOC @@ -2854,12 +2984,21 @@ rs6000_option_override_internal (bool gl /* For the powerpc-eabispe configuration, we set all these by default, so let's unset them if we manually set another CPU that is not the E500. */ - if (!rs6000_explicit_options.spe_abi) - rs6000_spe_abi = 0; - if (!rs6000_explicit_options.spe) - rs6000_spe = 0; - if (!rs6000_explicit_options.float_gprs) - rs6000_float_gprs = 0; + if (main_target_opt != NULL + && ((main_target_opt->x_rs6000_spe_abi != rs6000_spe_abi) + || (main_target_opt->x_rs6000_spe != rs6000_spe) + || (main_target_opt->x_rs6000_float_gprs != rs6000_float_gprs))) + error ("You cannot switch to the SPE abi within a target " + "attribute or pragma"); + else + { + if (!rs6000_explicit_options.spe_abi) + rs6000_spe_abi = 0; + if (!rs6000_explicit_options.spe) + rs6000_spe = 0; + if (!rs6000_explicit_options.float_gprs) + rs6000_float_gprs = 0; + } if (!(target_flags_explicit & MASK_ISEL)) target_flags &= ~MASK_ISEL; } @@ -3164,6 +3303,16 @@ rs6000_option_override_internal (bool gl rs6000_single_float = rs6000_double_float = 1; } + if (main_target_opt) + { + if (main_target_opt->x_rs6000_single_float != rs6000_single_float) + error ("You are not allowed to change the single precision floating " + "point unit within a target attribute or pragma"); + if (main_target_opt->x_rs6000_double_float != rs6000_double_float) + error ("You are not allowed to change the double precision floating " + "point unit within a target attribute or pragma"); + } + /* If not explicitly specified via option, decide whether to generate indexed load/store instructions. */ if (TARGET_AVOID_XFORM == -1) @@ -3218,7 +3367,7 @@ rs6000_option_override_internal (bool gl } } - rs6000_init_hard_regno_mode_ok (); + rs6000_init_hard_regno_mode_ok (global_init_p); /* Save the initial options in case the user does function specific options */ if (global_init_p) @@ -6818,7 +6967,7 @@ rs6000_conditional_register_usage (void) { int i; - if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) + if (TARGET_DEBUG_TARGET) fprintf (stderr, "rs6000_conditional_register_usage called\n"); /* Set MQ register fixed (already call_used) if not POWER @@ -27456,6 +27605,7 @@ rs6000_valid_attribute_p (tree fndecl, /* The target attributes may also change some optimization flags, so update the optimization options if necessary. */ cl_target_option_save (&cur_target, &global_options); + rs6000_cpu_index = rs6000_tune_index = -1; ret = rs6000_inner_target_options (args, true); /* Set up any additional state. */ @@ -27529,6 +27679,7 @@ rs6000_pragma_target_parse (tree args, t } else { + rs6000_cpu_index = rs6000_tune_index = -1; ret = rs6000_inner_target_options (args, false); cur_tree = build_target_option_node (); Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 166106) +++ gcc/doc/extend.texi (working copy) @@ -3410,7 +3410,9 @@ On the PowerPC, the following options ar @item altivec @itemx no-altivec @cindex @code{target("altivec")} attribute -Generate code that uses (does not use) AltiVec instructions. +Generate code that uses (does not use) AltiVec instructions. In +32-bit code, you cannot enable Altivec instructions unless +@option{-mabi=altivec} was used on the command line. @item cmpb @itemx no-cmpb @@ -3527,7 +3529,9 @@ do small block moves. @cindex @code{target("vsx")} attribute Generate code that uses (does not use) vector/scalar (VSX) instructions, and also enable the use of built-in functions that allow -more direct access to the VSX instruction set. +more direct access to the VSX instruction set. In 32-bit code, you +cannot enable VSX or Altivec instructions unless +@option{-mabi=altivec} was used on the command line. @item friz @itemx no-friz @@ -3564,11 +3568,18 @@ away so that a longer more expensive cal @item cpu=@var{CPU} @cindex @code{target("cpu=@var{CPU}")} attribute -Specify the architecture to generate code for in compiling the function. +Specify the architecture to generate code for in compiling the +function. If you select @code{"target("cpu=power7)"} attribute when +generating 32-bit code, VSX and Altivec instructions are not generated +unless you use the @option{-mabi=altivec} option on the command line. @item tune=@var{TUNE} @cindex @code{target("tune=@var{TUNE}")} attribute -Specify the architecture to tune for in compiling the function. +Specify the architecture to tune for in compiling the function. If +you do not specify the @code{target("tune=@var{TUNE}")} attribute and +you do specifiy the @code{target("cpu=@var{CPU}")} attribute, +compilation will tune for the @var{CPU} architecture, and not the +default tuning specified on the command line. @end table @end table @end table Index: gcc/testsuite/gcc.target/powerpc/ppc-target-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-target-2.c (revision 166141) +++ gcc/testsuite/gcc.target/powerpc/ppc-target-2.c (working copy) @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_vsx_ok } */ -/* { dg-options "-O2 -ffast-math -mcpu=power5" } */ +/* { dg-options "-O2 -ffast-math -mcpu=power5 -mabi=altivec" } */ /* { dg-final { scan-assembler-times "fabs" 3 } } */ /* { dg-final { scan-assembler-times "fnabs" 3 } } */ /* { dg-final { scan-assembler-times "fsel" 3 } } */ Index: gcc/testsuite/gcc.target/powerpc/ppc-target-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-target-1.c (revision 166141) +++ gcc/testsuite/gcc.target/powerpc/ppc-target-1.c (working copy) @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_vsx_ok } */ -/* { dg-options "-O2 -ffast-math -mcpu=power5" } */ +/* { dg-options "-O2 -ffast-math -mcpu=power5 -mabi=altivec" } */ /* { dg-final { scan-assembler-times "fabs" 3 } } */ /* { dg-final { scan-assembler-times "fnabs" 3 } } */ /* { dg-final { scan-assembler-times "fsel" 3 } } */ Index: gcc/testsuite/gcc.target/powerpc/ppc-target-3.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-target-3.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-target-3.c (revision 0) @@ -0,0 +1,62 @@ +/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O2 -ffast-math -mcpu=power5 -mabi=no-altivec" } */ +/* { dg-final { scan-assembler-times "fabs" 3 } } */ +/* { dg-final { scan-assembler-times "fnabs" 3 } } */ +/* { dg-final { scan-assembler-times "fsel" 3 } } */ +/* { dg-final { scan-assembler-times "fcpsgn" 4 } } */ +/* { dg-final { scan-assembler-not "xscpsgndp" } } */ + +/* Like ppc-target-1.c, but do not enable the altivec abi on 32-bit, so the + power7 code should generate fcpsgn and not xscpsgndp. */ + +double normal1 (double, double); +double power5 (double, double) __attribute__((__target__("cpu=power5"))); +double power6 (double, double) __attribute__((__target__("cpu=power6"))); +double power6x (double, double) __attribute__((__target__("cpu=power6x"))); +double power7 (double, double) __attribute__((__target__("cpu=power7"))); +double power7n (double, double) __attribute__((__target__("cpu=power7,no-vsx"))); +double normal2 (double, double); + +/* fabs/fnabs/fsel */ +double normal1 (double a, double b) +{ + return __builtin_copysign (a, b); +} + +/* fabs/fnabs/fsel */ +double power5 (double a, double b) +{ + return __builtin_copysign (a, b); +} + +/* fcpsgn */ +double power6 (double a, double b) +{ + return __builtin_copysign (a, b); +} + +/* fcpsgn */ +double power6x (double a, double b) +{ + return __builtin_copysign (a, b); +} + +/* xscpsgndp */ +double power7 (double a, double b) +{ + return __builtin_copysign (a, b); +} + +/* fcpsgn */ +double power7n (double a, double b) +{ + return __builtin_copysign (a, b); +} + +/* fabs/fnabs/fsel */ +double normal2 (double a, double b) +{ + return __builtin_copysign (a, b); +}