This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] rs6000: Add a builtin to read the time base register on PowerPC


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";
+})
+
 
 
 (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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]