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]

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


Hi Tulio,

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.

For things that do mftb with high frequency, maybe you should also add a builtin that does just an mftb, i.e. returns a 32-bit result on 32-bit implementations.

Please add documentation for the new builtin(s).

--- 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)

RS6000_BTM_POWERPC does not exist anymore. RS6000_BTM_ALWAYS?


+/* Expand an expression EXP that calls a builtin without arguments. */
+static rtx
+rs6000_expand_noop_builtin (enum insn_code icode, rtx target)

"noop" gives the wrong idea, "zeroop" perhaps?


+(define_expand "get_timebase"

You should probably prefix this with powerpc_ or rs6000_ as well. The existing code is not very consistent in this.

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

TARGET_POWERPC is always true.


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

This only works for WORDS_BIG_ENDIAN.


You should say you clobber CR0 here I think; actually, allow any CRn
instead.

Does mftb work on all supported assemblers?  The machine instruction
is phased out, but some assemblers translate it to mfspr.

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

POWER3 needs mftb.


--- /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;
+}

On some systems the timebase runs at a rather low frequency, say 20MHz. This test will spuriously fail there. Waste a million CPU cycles before reading TB the second time?


Segher



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