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 >