On Wed, Aug 29, 2012 at 6:56 AM, Tulio Magno Quites Machado Filho
<tul...@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 <tul...@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 <tul...@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
>

Reply via email to