This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] rs6000: Add a builtin to read the time base register on PowerPC
- From: Andrew Pinski <pinskia at gmail dot com>
- To: Tulio Magno Quites Machado Filho <tuliom at linux dot vnet dot ibm dot com>
- Cc: gcc-patches at gcc dot gnu dot org, dje dot gcc at gmail dot com, meissner at gcc dot gnu dot org
- Date: Wed, 29 Aug 2012 10:46:06 -0700
- Subject: Re: [PATCH] rs6000: Add a builtin to read the time base register on PowerPC
- References: <1346248585-10972-1-git-send-email-tuliom@linux.vnet.ibm.com>
On Wed, Aug 29, 2012 at 6:56 AM, Tulio Magno Quites Machado Filho
<tuliom@linux.vnet.ibm.com> wrote:
> Add __builtin_ppc_get_timebase to read the time base register on PowerPC.
> This is required for applications that measure time at high frequencies
> with high precision that can't afford a syscall.
>
> [gcc]
> 2012-08-29 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
>
> * config/rs6000/rs6000-builtin.def: Add __builtin_ppc_get_timebase.
> * config/rs6000/rs6000.c (rs6000_expand_noop_builtin): New
> function to expand an expression that calls a builtin without
> arguments.
> (rs6000_expand_builtin): Add __builtin_ppc_get_timebase.
> (rs6000_init_builtins): Likewise.
> * config/rs6000/rs6000.md: Likewise.
>
> [gcc/testsuite]
> 2012-08-29 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
>
> * gcc.target/powerpc/ppc-get-timebase.c: New file.
> ---
> gcc/config/rs6000/rs6000-builtin.def | 3 ++
> gcc/config/rs6000/rs6000.c | 31 +++++++++++++++++
> gcc/config/rs6000/rs6000.md | 36 ++++++++++++++++++++
> .../gcc.target/powerpc/ppc-get-timebase.c | 22 ++++++++++++
> 4 files changed, 92 insertions(+), 0 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/powerpc/ppc-get-timebase.c
>
> diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
> index c8f8f86..75ad184 100644
> --- a/gcc/config/rs6000/rs6000-builtin.def
> +++ b/gcc/config/rs6000/rs6000-builtin.def
> @@ -1429,6 +1429,9 @@ BU_SPECIAL_X (RS6000_BUILTIN_RSQRT, "__builtin_rsqrt", RS6000_BTM_FRSQRTE,
> BU_SPECIAL_X (RS6000_BUILTIN_RSQRTF, "__builtin_rsqrtf", RS6000_BTM_FRSQRTES,
> RS6000_BTC_FP)
>
> +BU_SPECIAL_X (RS6000_BUILTIN_GET_TB, "__builtin_ppc_get_timebase",
> + RS6000_BTM_POWERPC, RS6000_BTC_MISC)
> +
> /* Darwin CfString builtin. */
> BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
> RS6000_BTC_MISC)
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index 6c58307..24e274d 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -9747,6 +9747,30 @@ rs6000_overloaded_builtin_p (enum rs6000_builtins fncode)
> return (rs6000_builtin_info[(int)fncode].attr & RS6000_BTC_OVERLOADED) != 0;
> }
>
> +/* Expand an expression EXP that calls a builtin without arguments. */
> +static rtx
> +rs6000_expand_noop_builtin (enum insn_code icode, rtx target)
> +{
> + rtx pat;
> + enum machine_mode tmode = insn_data[icode].operand[0].mode;
> +
> + if (icode == CODE_FOR_nothing)
> + /* Builtin not supported on this processor. */
> + return 0;
> +
> + if (target == 0
> + || GET_MODE (target) != tmode
> + || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
> + target = gen_reg_rtx (tmode);
> +
> + pat = GEN_FCN (icode) (target);
> + if (! pat)
> + return 0;
> + emit_insn (pat);
> +
> + return target;
> +}
> +
>
> static rtx
> rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target)
> @@ -11336,6 +11360,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
> ? CODE_FOR_bpermd_di
> : CODE_FOR_bpermd_si), exp, target);
>
> + case RS6000_BUILTIN_GET_TB:
> + return rs6000_expand_noop_builtin (CODE_FOR_get_timebase, target);
> +
> case ALTIVEC_BUILTIN_MASK_FOR_LOAD:
> case ALTIVEC_BUILTIN_MASK_FOR_STORE:
> {
> @@ -11620,6 +11647,10 @@ rs6000_init_builtins (void)
> POWER7_BUILTIN_BPERMD, "__builtin_bpermd");
> def_builtin ("__builtin_bpermd", ftype, POWER7_BUILTIN_BPERMD);
>
> + ftype = build_function_type_list (unsigned_intDI_type_node,
> + NULL_TREE);
> + def_builtin ("__builtin_ppc_get_timebase", ftype, RS6000_BUILTIN_GET_TB);
> +
> #if TARGET_XCOFF
> /* AIX libm provides clog as __clog. */
> if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
> diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
> index d5ffd81..09bdd80 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -136,6 +136,7 @@
> UNSPECV_PROBE_STACK_RANGE ; probe range of stack addresses
> UNSPECV_EH_RR ; eh_reg_restore
> UNSPECV_ISYNC ; isync instruction
> + UNSPECV_GETTB ; get timebase built-in
> ])
>
>
> @@ -14101,6 +14102,41 @@
> ""
> "")
>
> +(define_expand "get_timebase"
> + [(use (match_operand:DI 0 "gpc_reg_operand" ""))]
> + ""
> + "
> +{
> + if (TARGET_POWERPC64)
> + emit_insn (gen_get_timebase_ppc64 (operands[0]));
> + else if (TARGET_POWERPC)
> + emit_insn (gen_get_timebase_ppc32 (operands[0]));
> + else
> + FAIL;
> + DONE;
> +}")
> +
> +(define_insn "get_timebase_ppc32"
> + [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
> + (unspec_volatile:DI [(const_int 0)] UNSPECV_GETTB))
> + (clobber (match_scratch:SI 1 "=r"))]
> + "TARGET_POWERPC && !TARGET_POWERPC64"
> +{
> + return "mftbu %0\;"
> + "mftb %L0\;"
> + "mftbu %1\;"
> + "cmpw %0,%1\;"
> + "bne- $-16";
> +})
> +
> +(define_insn "get_timebase_ppc64"
> + [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
> + (unspec_volatile:DI [(const_int 0)] UNSPECV_GETTB))]
> + "TARGET_POWERPC64"
> +{
> + return "mfspr %0, 268";
> +})
The Cell needs to do the 32bit way all the time to work aound the chip
errata/limitation.
Thanks,
Andrew Pinski
> +
>
>
> (include "sync.md")
> diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-get-timebase.c b/gcc/testsuite/gcc.target/powerpc/ppc-get-timebase.c
> new file mode 100644
> index 0000000..2f40974
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/ppc-get-timebase.c
> @@ -0,0 +1,22 @@
> +/* { dg-do run { target { powerpc*-*-* } } } */
> +
> +/* Test if __builtin_ppc_get_timebase() is compatible with the current
> + processor and if it's changing between reads. A read failure might indicate
> + a Power ISA or binutils change. */
> +
> +#include <inttypes.h>
> +
> +int
> +main(void)
> +{
> + uint64_t t1, t2, t3;
> +
> + t1 = __builtin_ppc_get_timebase ();
> + t2 = __builtin_ppc_get_timebase ();
> + t3 = __builtin_ppc_get_timebase ();
> +
> + if (t1 != t2 && t1 != t3 && t2 != t3)
> + return 0;
> +
> + return 1;
> +}
> --
> 1.7.7.6
>