Skip to content

Commit 99e5f5f

Browse files
committed
[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.
1 parent ba5676c commit 99e5f5f

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 44 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,47 @@ 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+
MachineFunction &MF = DAG.getMachineFunction();
2103+
unsigned RdhwrOpc, DestReg;
2104+
2105+
if (!Subtarget.hasMips32r6() &&
2106+
!getTargetMachine().getTargetTriple().isOSLinux())
2107+
return Op;
2108+
2109+
if (Subtarget.hasMips64()) {
2110+
RdhwrOpc = Mips::RDHWR64;
2111+
DestReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
2112+
SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i64, MVT::Glue,
2113+
DAG.getRegister(Mips::HWR2, MVT::i32),
2114+
DAG.getTargetConstant(0, DL, MVT::i32));
2115+
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
2116+
SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
2117+
SDValue ResNode =
2118+
DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i64, Chain.getValue(1));
2119+
Results.push_back(ResNode);
2120+
Results.push_back(ResNode.getValue(1));
2121+
} else {
2122+
RdhwrOpc = Mips::RDHWR;
2123+
DestReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32));
2124+
SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i32, MVT::Glue,
2125+
DAG.getRegister(Mips::HWR2, MVT::i32),
2126+
DAG.getTargetConstant(0, DL, MVT::i32));
2127+
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
2128+
SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
2129+
SDValue ResNode =
2130+
DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i32, Chain.getValue(1));
2131+
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResNode,
2132+
DAG.getConstant(0, DL, MVT::i32)));
2133+
Results.push_back(ResNode.getValue(1));
2134+
}
2135+
2136+
return DAG.getMergeValues(Results, DL);
2137+
}
2138+
20952139
SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
20962140
// The first operand is the chain, the second is the condition, the third is
20972141
// 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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 $2, $hwr_cc
10+
; MIPSEL-NEXT: .set pop
11+
; MIPSEL-NEXT: jr $ra
12+
; MIPSEL-NEXT: addiu $3, $zero, 0
13+
;
14+
; MIPS64EL-LABEL: test_readcyclecounter:
15+
; MIPS64EL: # %bb.0: # %entry
16+
; MIPS64EL-NEXT: .set push
17+
; MIPS64EL-NEXT: .set mips32r2
18+
; MIPS64EL-NEXT: rdhwr $2, $hwr_cc
19+
; MIPS64EL-NEXT: .set pop
20+
; MIPS64EL-NEXT: jrc $ra
21+
22+
entry:
23+
%tmp0 = call i64 @llvm.readcyclecounter()
24+
ret i64 %tmp0
25+
}
26+

0 commit comments

Comments
 (0)