[llvm] r182603 - ARM: implement @llvm.readcyclecounter intrinsic

JF Bastien jfb at google.com
Fri May 24 13:49:25 PDT 2013


PMUSERENR.EN seems to default to zero on Linux, no? At least my local
Ubuntu A15 board test says so, and as expected I get SIGILL in user mode.

Wouldn't it also useful to have an intrinsic to check for the value? "mrc
p15, 0, %0, c9, c14, 0"'s bottom bit should do it. Or figure out which OS
also supports PMUSERENR.EN=1 by default, with an override flag?


On Thu, May 23, 2013 at 12:11 PM, Tim Northover <t.p.northover at gmail.com>wrote:

> Author: tnorthover
> Date: Thu May 23 14:11:20 2013
> New Revision: 182603
>
> URL: http://llvm.org/viewvc/llvm-project?rev=182603&view=rev
> Log:
> ARM: implement @llvm.readcyclecounter intrinsic
>
> This implements the @llvm.readcyclecounter intrinsic as the specific
> MRC instruction specified in the ARM manuals for CPUs with the Power
> Management extensions.
>
> Older CPUs had slightly different methods which may also have to be
> implemented eventually, but this should cover all v7 cases.
>
> rdar://problem/13939186
>
> Added:
>     llvm/trunk/test/CodeGen/ARM/readcyclecounter.ll
> Modified:
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=182603&r1=182602&r2=182603&view=diff
>
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Thu May 23 14:11:20 2013
> @@ -6663,6 +6663,9 @@ memory. Implementations are allowed to e
>  specific value or a system wide value. On backends without support, this
>  is lowered to a constant 0.
>
> +Note that runtime support may be conditional on the privilege-level code
> is
> +running at and the host platform.
> +
>  Standard C Library Intrinsics
>  -----------------------------
>
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=182603&r1=182602&r2=182603&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Thu May 23 14:11:20 2013
> @@ -681,6 +681,8 @@ ARMTargetLowering::ARMTargetLowering(Tar
>    setOperationAction(ISD::CTTZ_ZERO_UNDEF  , MVT::i32  , Expand);
>    setOperationAction(ISD::CTLZ_ZERO_UNDEF  , MVT::i32  , Expand);
>
> +  setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
> +
>    // Only ARMv6 has BSWAP.
>    if (!Subtarget->hasV6Ops())
>      setOperationAction(ISD::BSWAP, MVT::i32, Expand);
> @@ -5702,7 +5704,6 @@ static SDValue LowerAtomicLoadStore(SDVa
>    return SDValue();
>  }
>
> -
>  static void
>  ReplaceATOMIC_OP_64(SDNode *Node, SmallVectorImpl<SDValue>& Results,
>                      SelectionDAG &DAG, unsigned NewOp) {
> @@ -5736,6 +5737,44 @@ ReplaceATOMIC_OP_64(SDNode *Node, SmallV
>    Results.push_back(Result.getValue(2));
>  }
>
> +static void ReplaceREADCYCLECOUNTER(SDNode *N,
> +                                    SmallVectorImpl<SDValue> &Results,
> +                                    SelectionDAG &DAG,
> +                                    const ARMSubtarget *Subtarget) {
> +  DebugLoc DL = N->getDebugLoc();
> +  SDValue Cycles32, OutChain;
> +
> +  if (Subtarget->hasPerfMon()) {
> +    // Under Power Management extensions, the cycle-count is:
> +    //    mrc p15, #0, <Rt>, c9, c13, #0
> +    SDValue Ops[] = { N->getOperand(0), // Chain
> +                      DAG.getConstant(Intrinsic::arm_mrc, MVT::i32),
> +                      DAG.getConstant(15, MVT::i32),
> +                      DAG.getConstant(0, MVT::i32),
> +                      DAG.getConstant(9, MVT::i32),
> +                      DAG.getConstant(13, MVT::i32),
> +                      DAG.getConstant(0, MVT::i32)
> +    };
> +
> +    Cycles32 = DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL,
> +                           DAG.getVTList(MVT::i32, MVT::Other), &Ops[0],
> +                           array_lengthof(Ops));
> +    OutChain = Cycles32.getValue(1);
> +  } else {
> +    // Intrinsic is defined to return 0 on unsupported platforms.
> Technically
> +    // there are older ARM CPUs that have implementation-specific ways of
> +    // obtaining this information (FIXME!).
> +    Cycles32 = DAG.getConstant(0, MVT::i32);
> +    OutChain = DAG.getEntryNode();
> +  }
> +
> +
> +  SDValue Cycles64 = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64,
> +                                 Cycles32, DAG.getConstant(0, MVT::i32));
> +  Results.push_back(Cycles64);
> +  Results.push_back(OutChain);
> +}
> +
>  SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
> const {
>    switch (Op.getOpcode()) {
>    default: llvm_unreachable("Don't know how to custom lower this!");
> @@ -5813,6 +5852,9 @@ void ARMTargetLowering::ReplaceNodeResul
>    case ISD::SRA:
>      Res = Expand64BitShift(N, DAG, Subtarget);
>      break;
> +  case ISD::READCYCLECOUNTER:
> +    ReplaceREADCYCLECOUNTER(N, Results, DAG, Subtarget);
> +    return;
>    case ISD::ATOMIC_LOAD_ADD:
>      ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMADD64_DAG);
>      return;
>
> Added: llvm/trunk/test/CodeGen/ARM/readcyclecounter.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/readcyclecounter.ll?rev=182603&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/readcyclecounter.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/readcyclecounter.ll Thu May 23 14:11:20
> 2013
> @@ -0,0 +1,24 @@
> +; RUN: llc -mtriple=armv7-none-linux-gnueabi < %s | FileCheck %s
> +; RUN: llc -mtriple=thumbv7-none-linux-gnueabi < %s | FileCheck %s
> +; RUN: llc -mtriple=armv7-none-linux-gnueabi -mattr=-perfmon < %s |
> FileCheck %s --check-prefix=CHECK-NO-PERFMON
> +; RUN: llc -mtriple=armv6-none-linux-gnueabi < %s | FileCheck %s
> --check-prefix=CHECK-NO-PERFMON
> +
> +; The performance monitor we're looking for is an ARMv7 extension. It
> should be
> +; possible to disable it, but realistically present on at least every v7-A
> +; processor (but not on v6, at least by default).
> +
> +declare i64 @llvm.readcyclecounter()
> +
> +define i64 @get_count() {
> +  %val = call i64 @llvm.readcyclecounter()
> +  ret i64 %val
> +
> +  ; As usual, exact registers only sort of matter but the cycle-count had
> better
> +  ; end up in r0 in the end.
> +
> +; CHECK: mrc p15, #0, r0, c9, c13, #0
> +; CHECK: {{movs?}} r1, #0
> +
> +; CHECK-NO-PERFMON: {{movs?}} r0, #0
> +; CHECK-NO-PERFMON: {{movs?}} r1, #0
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130524/137e3a65/attachment.html>


More information about the llvm-commits mailing list