Hi Segher,

Segher Boessenkool <seg...@kernel.crashing.org> writes:
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.

Are you thinking in a function that returns only the TBL?
I don't think such a builtin would make sense on a 64-bit environment, right?
Do you have a suggestion for its name?

Please add documentation for the new builtin(s).

Sure!

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

I'm replacing.

+/* 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?

zeroop is much better.


+(define_expand "get_timebase"

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

OK.

+  [(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.

OK.

+(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.

Yes.

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

Yes.

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

According to the Power ISA 2.06 they should 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.

Nice catch!

+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?

Yes.

Thank you,

--
Tulio Magno

Reply via email to