Skip to content

Commit af1e2a3

Browse files
authored
[Mips] Support llvm.readcyclecounter intrinsic (#127553)
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 4dee305 commit af1e2a3

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
357357
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
358358
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
359359

360+
if (Subtarget.hasMips32r2() ||
361+
getTargetMachine().getTargetTriple().isOSLinux())
362+
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
363+
360364
// Lower fmin/fmax/fclass operations for MIPS R6.
361365
if (Subtarget.hasMips32r6()) {
362366
setOperationAction(ISD::FMINNUM_IEEE, MVT::f32, Legal);
@@ -1315,6 +1319,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
13151319
case ISD::STORE: return lowerSTORE(Op, DAG);
13161320
case ISD::EH_DWARF_CFA: return lowerEH_DWARF_CFA(Op, DAG);
13171321
case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG);
1322+
case ISD::READCYCLECOUNTER:
1323+
return lowerREADCYCLECOUNTER(Op, DAG);
13181324
}
13191325
return SDValue();
13201326
}
@@ -2096,6 +2102,44 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword(
20962102
return exitMBB;
20972103
}
20982104

2105+
SDValue MipsTargetLowering::lowerREADCYCLECOUNTER(SDValue Op,
2106+
SelectionDAG &DAG) const {
2107+
SmallVector<SDValue, 3> Results;
2108+
SDLoc DL(Op);
2109+
MachineFunction &MF = DAG.getMachineFunction();
2110+
unsigned RdhwrOpc, DestReg;
2111+
EVT PtrVT = getPointerTy(DAG.getDataLayout());
2112+
2113+
if (PtrVT == MVT::i64) {
2114+
RdhwrOpc = Mips::RDHWR64;
2115+
DestReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
2116+
SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i64, MVT::Glue,
2117+
DAG.getRegister(Mips::HWR2, MVT::i32),
2118+
DAG.getTargetConstant(0, DL, MVT::i32));
2119+
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
2120+
SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
2121+
SDValue ResNode =
2122+
DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i64, Chain.getValue(1));
2123+
Results.push_back(ResNode);
2124+
Results.push_back(ResNode.getValue(1));
2125+
} else {
2126+
RdhwrOpc = Mips::RDHWR;
2127+
DestReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32));
2128+
SDNode *Rdhwr = DAG.getMachineNode(RdhwrOpc, DL, MVT::i32, MVT::Glue,
2129+
DAG.getRegister(Mips::HWR2, MVT::i32),
2130+
DAG.getTargetConstant(0, DL, MVT::i32));
2131+
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), DL, DestReg,
2132+
SDValue(Rdhwr, 0), SDValue(Rdhwr, 1));
2133+
SDValue ResNode =
2134+
DAG.getCopyFromReg(Chain, DL, DestReg, MVT::i32, Chain.getValue(1));
2135+
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResNode,
2136+
DAG.getConstant(0, DL, MVT::i32)));
2137+
Results.push_back(ResNode.getValue(1));
2138+
}
2139+
2140+
return DAG.getMergeValues(Results, DL);
2141+
}
2142+
20992143
SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
21002144
// The first operand is the chain, the second is the condition, the third is
21012145
// 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
@@ -591,6 +591,7 @@ class TargetRegisterClass;
591591
bool IsSRA) const;
592592
SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
593593
SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
594+
SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
594595

595596
/// isEligibleForTailCallOptimization - Check whether the call is eligible
596597
/// for tail call optimization.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
;RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32r2 < %s | FileCheck %s --check-prefix=MIPSEL
2+
;RUN: llc -mtriple=mips64el-linux-gnuabi64 -mcpu=mips64r2 < %s | FileCheck %s --check-prefix=MIPS64EL
3+
;RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips2 < %s | FileCheck %s --check-prefix=MIPSEL
4+
;RUN: llc -mtriple=mips64el-linux-gnuabi64 -mcpu=mips3 < %s | FileCheck %s --check-prefix=MIPS64EL
5+
;RUN: llc -mtriple=mipsel -mcpu=mips32r2 < %s | FileCheck %s --check-prefix=MIPSEL
6+
;RUN: llc -mtriple=mips64el -mcpu=mips64r2 < %s | FileCheck %s --check-prefix=MIPS64EL
7+
;RUN: llc -mtriple=mipsel -mcpu=mips2 < %s | FileCheck %s --check-prefix=MIPSEL_NOT_SUPPORTED
8+
;RUN: llc -mtriple=mips64el -mcpu=mips3 < %s | FileCheck %s --check-prefix=MIPS64EL_NOT_SUPPORTED
9+
10+
declare i64 @llvm.readcyclecounter() nounwind readnone
11+
12+
define i64 @test_readcyclecounter() nounwind {
13+
; MIPSEL-LABEL: test_readcyclecounter:
14+
; MIPSEL: # %bb.0: # %entry
15+
; MIPSEL-NEXT: .set push
16+
; MIPSEL-NEXT: .set mips32r2
17+
; MIPSEL-NEXT: rdhwr $2, $hwr_cc
18+
; MIPSEL-NEXT: .set pop
19+
; MIPSEL-NEXT: jr $ra
20+
; MIPSEL-NEXT: addiu $3, $zero, 0
21+
;
22+
; MIPSEL_NOT_SUPPORTED-LABEL: test_readcyclecounter:
23+
; MIPSEL_NOT_SUPPORTED: # %bb.0: # %entry
24+
; MIPSEL_NOT_SUPPORTED-NEXT: addiu $2, $zero, 0
25+
; MIPSEL_NOT_SUPPORTED-NEXT: jr $ra
26+
; MIPSEL_NOT_SUPPORTED-NEXT: addiu $3, $zero, 0
27+
;
28+
; MIPS64EL-LABEL: test_readcyclecounter:
29+
; MIPS64EL: # %bb.0: # %entry
30+
; MIPS64EL-NEXT: .set push
31+
; MIPS64EL-NEXT: .set mips32r2
32+
; MIPS64EL-NEXT: rdhwr $2, $hwr_cc
33+
; MIPS64EL-NEXT: .set pop
34+
; MIPS64EL-NEXT: jr $ra
35+
; MIPS64EL-NEXT: nop
36+
;
37+
; MIPS64EL_NOT_SUPPORTED-LABEL: test_readcyclecounter:
38+
; MIPS64EL_NOT_SUPPORTED: # %bb.0: # %entry
39+
; MIPS64EL_NOT_SUPPORTED-NEXT: jr $ra
40+
; MIPS64EL_NOT_SUPPORTED-NEXT: daddiu $2, $zero, 0
41+
entry:
42+
%tmp0 = tail call i64 @llvm.readcyclecounter()
43+
ret i64 %tmp0
44+
}
45+

0 commit comments

Comments
 (0)