[llvm] [Mips] Support llvm.readcyclecounter intrinsic (PR #114953)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 27 01:22:11 PST 2024
https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/114953
>From f6b1cb996e2bcb32172dfb53ace8f939280381c2 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Tue, 5 Nov 2024 03:33:45 -0500
Subject: [PATCH] [Mips] Support llvm.readcyclecounter intrinsic
The llvm.readcyclecounter intrinsic can be implemented via the
`rdhwr $2, $hwr_cc` instruction.
$hwr_cc: High-resolution cycle counter. This register provides read
access to the coprocessor 0 Count Register.
Fix #106318.
---
llvm/lib/Target/Mips/MipsISelLowering.cpp | 40 ++++++++++++++++++++++
llvm/lib/Target/Mips/MipsISelLowering.h | 1 +
llvm/test/CodeGen/Mips/readcyclecounter.ll | 26 ++++++++++++++
3 files changed, 67 insertions(+)
create mode 100644 llvm/test/CodeGen/Mips/readcyclecounter.ll
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index f1cc9fd958447a..59b84285debfb7 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -358,6 +358,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
+ setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
// Lower fmin/fmax/fclass operations for MIPS R6.
if (Subtarget.hasMips32r6()) {
@@ -1311,6 +1312,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();
}
@@ -2092,6 +2095,43 @@ 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;
+
+ if (Subtarget.hasMips64()) {
+ 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 2b18b299180926..e96f6500d0f137 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -560,6 +560,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 00000000000000..16fa1540729217
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/readcyclecounter.ll
@@ -0,0 +1,26 @@
+;RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32r2 < %s | FileCheck %s --check-prefix=MIPSEL
+;RUN: llc -mtriple=mips64el-linux-gnuabi64 -mcpu=mips64r6 < %s | FileCheck %s --check-prefix=MIPS64EL
+
+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
+;
+; 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: jrc $ra
+
+entry:
+ %tmp0 = call i64 @llvm.readcyclecounter()
+ ret i64 %tmp0
+}
+
More information about the llvm-commits
mailing list