[llvm] 9cc7ee1 - [Mips] Support llvm.readcyclecounter intrinsic (#114953)

via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 10 16:47:54 PST 2025


Author: yingopq
Date: 2025-02-11T08:47:50+08:00
New Revision: 9cc7ee16e3bb849fb3c0155a843bfe349a2d2175

URL: https://github.com/llvm/llvm-project/commit/9cc7ee16e3bb849fb3c0155a843bfe349a2d2175
DIFF: https://github.com/llvm/llvm-project/commit/9cc7ee16e3bb849fb3c0155a843bfe349a2d2175.diff

LOG: [Mips] Support llvm.readcyclecounter intrinsic (#114953)

The llvm.readcyclecounter intrinsic can be implemented via the `rdhwr
$3, $hwr_cc` instruction.
$hwr_cc: High-resolution cycle counter. This register provides read
access to the coprocessor 0 Count Register.

Fix #106318.

Added: 
    llvm/test/CodeGen/Mips/readcyclecounter.ll

Modified: 
    llvm/lib/Target/Mips/MipsISelLowering.cpp
    llvm/lib/Target/Mips/MipsISelLowering.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index afec52e289e2262..e737c5aeb43c635 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -357,6 +357,10 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
   setOperationAction(ISD::FCOPYSIGN,          MVT::f64,   Custom);
   setOperationAction(ISD::FP_TO_SINT,         MVT::i32,   Custom);
 
+  if (Subtarget.hasMips32r2() ||
+      getTargetMachine().getTargetTriple().isOSLinux())
+    setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
+
   // Lower fmin/fmax/fclass operations for MIPS R6.
   if (Subtarget.hasMips32r6()) {
     setOperationAction(ISD::FMINNUM_IEEE, MVT::f32, Legal);
@@ -1315,6 +1319,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
   case ISD::STORE:              return lowerSTORE(Op, DAG);
   case ISD::EH_DWARF_CFA:       return lowerEH_DWARF_CFA(Op, DAG);
   case ISD::FP_TO_SINT:         return lowerFP_TO_SINT(Op, DAG);
+  case ISD::READCYCLECOUNTER:
+    return lowerREADCYCLECOUNTER(Op, DAG);
   }
   return SDValue();
 }
@@ -2096,6 +2102,44 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword(
   return exitMBB;
 }
 
+SDValue MipsTargetLowering::lowerREADCYCLECOUNTER(SDValue Op,
+                                                  SelectionDAG &DAG) const {
+  SmallVector<SDValue, 3> Results;
+  SDLoc DL(Op);
+  MachineFunction &MF = DAG.getMachineFunction();
+  unsigned RdhwrOpc, DestReg;
+  EVT PtrVT = getPointerTy(DAG.getDataLayout());
+
+  if (PtrVT == MVT::i64) {
+    RdhwrOpc = Mips::RDHWR64;
+    DestReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
+    SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i64, MVT::Glue,
+                                       DAG.getRegister(Mips::HWR2, MVT::i32),
+                                       DAG.getTargetConstant(0, DL, MVT::i32));
+    SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
+                                     SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
+    SDValue ResNode =
+        DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i64, Chain.getValue(1));
+    Results.push_back(ResNode);
+    Results.push_back(ResNode.getValue(1));
+  } else {
+    RdhwrOpc = Mips::RDHWR;
+    DestReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32));
+    SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i32, MVT::Glue,
+                                       DAG.getRegister(Mips::HWR2, MVT::i32),
+                                       DAG.getTargetConstant(0, DL, MVT::i32));
+    SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
+                                     SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
+    SDValue ResNode =
+        DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i32, Chain.getValue(1));
+    Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResNode,
+                                  DAG.getConstant(0, DL, MVT::i32)));
+    Results.push_back(ResNode.getValue(1));
+  }
+
+  return DAG.getMergeValues(Results, DL);
+}
+
 SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
   // The first operand is the chain, the second is the condition, the third is
   // the block to branch to if the condition is true.

diff  --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index ee1ab6a17a91e29..1d5f5e663d531c9 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -591,6 +591,7 @@ class TargetRegisterClass;
                                  bool IsSRA) const;
     SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
+    SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
 
     /// isEligibleForTailCallOptimization - Check whether the call is eligible
     /// for tail call optimization.

diff  --git a/llvm/test/CodeGen/Mips/readcyclecounter.ll b/llvm/test/CodeGen/Mips/readcyclecounter.ll
new file mode 100644
index 000000000000000..c7a27d34806f8fe
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/readcyclecounter.ll
@@ -0,0 +1,43 @@
+;RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32r2 < %s | FileCheck %s --check-prefix=MIPSEL
+;RUN: llc -mtriple=mips64el-linux-gnuabi64 -mcpu=mips64r2 < %s | FileCheck %s --check-prefix=MIPS64EL
+;RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips2 < %s | FileCheck %s --check-prefix=MIPSEL
+;RUN: llc -mtriple=mips64el-linux-gnuabi64 -mcpu=mips3 < %s | FileCheck %s --check-prefix=MIPS64EL
+;RUN: llc -mtriple=mipsel -mcpu=mips32r2 < %s | FileCheck %s --check-prefix=MIPSEL
+;RUN: llc -mtriple=mips64el -mcpu=mips64r2 < %s | FileCheck %s --check-prefix=MIPS64EL
+;RUN: llc -mtriple=mipsel -mcpu=mips2 < %s | FileCheck %s --check-prefix=MIPSEL_NOT_SUPPORTED
+;RUN: llc -mtriple=mips64el -mcpu=mips3 < %s | FileCheck %s --check-prefix=MIPS64EL_NOT_SUPPORTED
+
+define i64 @test_readcyclecounter() nounwind {
+; MIPSEL-LABEL: test_readcyclecounter:
+; MIPSEL:       # %bb.0: # %entry
+; MIPSEL-NEXT:    .set push
+; MIPSEL-NEXT:    .set mips32r2
+; MIPSEL-NEXT:    rdhwr $2, $hwr_cc
+; MIPSEL-NEXT:    .set pop
+; MIPSEL-NEXT:    jr $ra
+; MIPSEL-NEXT:    addiu $3, $zero, 0
+;
+; MIPSEL_NOT_SUPPORTED-LABEL: test_readcyclecounter:
+; MIPSEL_NOT_SUPPORTED:       # %bb.0: # %entry
+; MIPSEL_NOT_SUPPORTED-NEXT:    addiu $2, $zero, 0
+; MIPSEL_NOT_SUPPORTED-NEXT:    jr $ra
+; MIPSEL_NOT_SUPPORTED-NEXT:    addiu $3, $zero, 0
+;
+; MIPS64EL-LABEL: test_readcyclecounter:
+; MIPS64EL:       # %bb.0: # %entry
+; MIPS64EL-NEXT:    .set push
+; MIPS64EL-NEXT:    .set mips32r2
+; MIPS64EL-NEXT:    rdhwr $2, $hwr_cc
+; MIPS64EL-NEXT:    .set pop
+; MIPS64EL-NEXT:    jr $ra
+; MIPS64EL-NEXT:    nop
+;
+; MIPS64EL_NOT_SUPPORTED-LABEL: test_readcyclecounter:
+; MIPS64EL_NOT_SUPPORTED:       # %bb.0: # %entry
+; MIPS64EL_NOT_SUPPORTED-NEXT:    jr $ra
+; MIPS64EL_NOT_SUPPORTED-NEXT:    daddiu $2, $zero, 0
+entry:
+  %tmp0 = call i64 @llvm.readcyclecounter()
+  ret i64 %tmp0
+}
+


        


More information about the llvm-commits mailing list