Skip to content

Commit 490a1da

Browse files
committed
[Mips] Support llvm.readcyclecounter intrinsic
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.
1 parent ba5676c commit 490a1da

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
358358
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
359359
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
360360
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
361+
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
361362

362363
// Lower fmin/fmax/fclass operations for MIPS R6.
363364
if (Subtarget.hasMips32r6()) {
@@ -1311,6 +1312,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
13111312
case ISD::STORE: return lowerSTORE(Op, DAG);
13121313
case ISD::EH_DWARF_CFA: return lowerEH_DWARF_CFA(Op, DAG);
13131314
case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG);
1315+
case ISD::READCYCLECOUNTER:
1316+
return lowerREADCYCLECOUNTER(Op, DAG);
13141317
}
13151318
return SDValue();
13161319
}
@@ -2092,6 +2095,42 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword(
20922095
return exitMBB;
20932096
}
20942097

2098+
SDValue MipsTargetLowering::lowerREADCYCLECOUNTER(SDValue Op,
2099+
SelectionDAG &DAG) const {
2100+
SmallVector<SDValue, 3> Results;
2101+
SDLoc DL(Op);
2102+
unsigned RdhwrOpc, DestReg;
2103+
2104+
if (Subtarget.hasMips64()) {
2105+
RdhwrOpc = Mips::RDHWR64;
2106+
DestReg = Mips::V1_64;
2107+
SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i64, MVT::Glue,
2108+
DAG.getRegister(Mips::HWR2, MVT::i32),
2109+
DAG.getTargetConstant(0, DL, MVT::i32));
2110+
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
2111+
SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
2112+
SDValue ResNode =
2113+
DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i64, Chain.getValue(1));
2114+
Results.push_back(ResNode);
2115+
Results.push_back(ResNode.getValue(1));
2116+
} else {
2117+
RdhwrOpc = Mips::RDHWR;
2118+
DestReg = Mips::V1;
2119+
SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i32, MVT::Glue,
2120+
DAG.getRegister(Mips::HWR2, MVT::i32),
2121+
DAG.getTargetConstant(0, DL, MVT::i32));
2122+
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
2123+
SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
2124+
SDValue ResNode =
2125+
DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i32, Chain.getValue(1));
2126+
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResNode,
2127+
DAG.getConstant(0, DL, MVT::i32)));
2128+
Results.push_back(ResNode.getValue(1));
2129+
}
2130+
2131+
return DAG.getMergeValues(Results, DL);
2132+
}
2133+
20952134
SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
20962135
// The first operand is the chain, the second is the condition, the third is
20972136
// the block to branch to if the condition is true.

llvm/lib/Target/Mips/MipsISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ class TargetRegisterClass;
560560
bool IsSRA) const;
561561
SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
562562
SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
563+
SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
563564

564565
/// isEligibleForTailCallOptimization - Check whether the call is eligible
565566
/// for tail call optimization.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
;RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32r2 < %s | FileCheck %s --check-prefix=MIPSEL
2+
;RUN: llc -mtriple=mips64el-linux-gnuabi64 -mcpu=mips64r6 < %s | FileCheck %s --check-prefix=MIPS64EL
3+
4+
define i64 @test_readcyclecounter() nounwind {
5+
; MIPSEL-LABEL: test_readcyclecounter:
6+
; MIPSEL: # %bb.0: # %entry
7+
; MIPSEL-NEXT: .set push
8+
; MIPSEL-NEXT: .set mips32r2
9+
; MIPSEL-NEXT: rdhwr $3, $hwr_cc
10+
; MIPSEL-NEXT: .set pop
11+
; MIPSEL-NEXT: move $2, $3
12+
; MIPSEL-NEXT: jr $ra
13+
; MIPSEL-NEXT: addiu $3, $zero, 0
14+
;
15+
; MIPS64EL-LABEL: test_readcyclecounter:
16+
; MIPS64EL: # %bb.0: # %entry
17+
; MIPS64EL-NEXT: .set push
18+
; MIPS64EL-NEXT: .set mips32r2
19+
; MIPS64EL-NEXT: rdhwr $3, $hwr_cc
20+
; MIPS64EL-NEXT: .set pop
21+
; MIPS64EL-NEXT: jr $ra
22+
; MIPS64EL-NEXT: move $2, $3
23+
24+
entry:
25+
%tmp0 = call i64 @llvm.readcyclecounter()
26+
ret i64 %tmp0
27+
}
28+

0 commit comments

Comments
 (0)