Skip to content

Commit 4b90741

Browse files
committed
[SystemZ] Add support for llvm.readcyclecounter
The llvm.readcyclecounter intrinsic can be implemented via the STORE CLOCK FAST (STCKF) instruction.
1 parent 50e6218 commit 4b90741

File tree

5 files changed

+74
-1
lines changed

5 files changed

+74
-1
lines changed

llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
372372
// Handle prefetches with PFD or PFDRL.
373373
setOperationAction(ISD::PREFETCH, MVT::Other, Custom);
374374

375+
// Handle readcyclecounter with STCKF.
376+
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
377+
375378
for (MVT VT : MVT::fixedlen_vector_valuetypes()) {
376379
// Assume by default that all vector operations need to be expanded.
377380
for (unsigned Opcode = 0; Opcode < ISD::BUILTIN_OP_END; ++Opcode)
@@ -6077,6 +6080,27 @@ SDValue SystemZTargetLowering::lowerIS_FPCLASS(SDValue Op,
60776080
return getCCResult(DAG, Intr);
60786081
}
60796082

6083+
SDValue SystemZTargetLowering::lowerREADCYCLECOUNTER(SDValue Op,
6084+
SelectionDAG &DAG) const {
6085+
SDLoc DL(Op);
6086+
SDValue Chain = Op.getOperand(0);
6087+
6088+
// STCKF only supports a memory operand, so we have to use a temporary.
6089+
SDValue StackPtr = DAG.CreateStackTemporary(MVT::i64);
6090+
int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6091+
MachinePointerInfo MPI =
6092+
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI);
6093+
6094+
// Use STCFK to store the TOD clock into the temporary.
6095+
SDValue StoreOps[] = {Chain, StackPtr};
6096+
Chain = DAG.getMemIntrinsicNode(
6097+
SystemZISD::STCKF, DL, DAG.getVTList(MVT::Other), StoreOps, MVT::i64,
6098+
MPI, MaybeAlign(), MachineMemOperand::MOStore);
6099+
6100+
// And read it back from there.
6101+
return DAG.getLoad(MVT::i64, DL, Chain, StackPtr, MPI);
6102+
}
6103+
60806104
SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
60816105
SelectionDAG &DAG) const {
60826106
switch (Op.getOpcode()) {
@@ -6199,6 +6223,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
61996223
return lowerIS_FPCLASS(Op, DAG);
62006224
case ISD::GET_ROUNDING:
62016225
return lowerGET_ROUNDING(Op, DAG);
6226+
case ISD::READCYCLECOUNTER:
6227+
return lowerREADCYCLECOUNTER(Op, DAG);
62026228
default:
62036229
llvm_unreachable("Unexpected node to lower");
62046230
}
@@ -6425,6 +6451,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
64256451
OPCODE(STRV);
64266452
OPCODE(VLER);
64276453
OPCODE(VSTER);
6454+
OPCODE(STCKF);
64286455
OPCODE(PREFETCH);
64296456
OPCODE(ADA_ENTRY);
64306457
}
@@ -6985,6 +7012,17 @@ SDValue SystemZTargetLowering::combineSTORE(
69857012
}
69867013
}
69877014

7015+
// Combine STORE (READCYCLECOUNTER) into STCKF.
7016+
if (!SN->isTruncatingStore() &&
7017+
Op1.getOpcode() == ISD::READCYCLECOUNTER &&
7018+
Op1.hasOneUse() &&
7019+
N->getOperand(0).reachesChainWithoutSideEffects(SDValue(Op1.getNode(), 1))) {
7020+
SDValue Ops[] = { Op1.getOperand(0), N->getOperand(2) };
7021+
return DAG.getMemIntrinsicNode(SystemZISD::STCKF, SDLoc(N),
7022+
DAG.getVTList(MVT::Other),
7023+
Ops, MemVT, SN->getMemOperand());
7024+
}
7025+
69887026
// Transform a store of an i128 moved from GPRs into two separate stores.
69897027
if (MemVT == MVT::i128 && SN->isSimple() && ISD::isNormalStore(SN)) {
69907028
SDValue LoPart, HiPart;

llvm/lib/Target/SystemZ/SystemZISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ enum NodeType : unsigned {
378378
// Element swapping load/store. Same operands as regular load/store.
379379
VLER, VSTER,
380380

381+
// Use STORE CLOCK FAST to store current TOD clock value.
382+
STCKF,
383+
381384
// Prefetch from the second operand using the 4-bit control code in
382385
// the first operand. The code is 1 for a load prefetch and 2 for
383386
// a store prefetch.
@@ -717,6 +720,7 @@ class SystemZTargetLowering : public TargetLowering {
717720
SDValue lowerShift(SDValue Op, SelectionDAG &DAG, unsigned ByScalar) const;
718721
SDValue lowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const;
719722
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
723+
SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
720724

721725
bool canTreatAsByteVector(EVT VT) const;
722726
SDValue combineExtract(const SDLoc &DL, EVT ElemVT, EVT VecVT, SDValue OrigOp,

llvm/lib/Target/SystemZ/SystemZInstrSystem.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ let hasSideEffects = 1 in
339339
// Store clock (fast / extended).
340340
let hasSideEffects = 1, Defs = [CC] in {
341341
def STCK : StoreInherentS<"stck", 0xB205, null_frag, 8>;
342-
def STCKF : StoreInherentS<"stckf", 0xB27C, null_frag, 8>;
342+
def STCKF : StoreInherentS<"stckf", 0xB27C, z_stckf, 8>;
343343
def STCKE : StoreInherentS<"stcke", 0xB278, null_frag, 16>;
344344
}
345345

llvm/lib/Target/SystemZ/SystemZOperators.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ def SDT_ZIPM : SDTypeProfile<1, 1,
132132
def SDT_ZPrefetch : SDTypeProfile<0, 2,
133133
[SDTCisVT<0, i32>,
134134
SDTCisPtrTy<1>]>;
135+
def SDT_ZStoreInherent : SDTypeProfile<0, 1,
136+
[SDTCisPtrTy<0>]>;
135137
def SDT_ZTBegin : SDTypeProfile<1, 2,
136138
[SDTCisVT<0, i32>,
137139
SDTCisPtrTy<1>,
@@ -307,6 +309,8 @@ def z_loadeswap : SDNode<"SystemZISD::VLER", SDTLoad,
307309
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
308310
def z_storeeswap : SDNode<"SystemZISD::VSTER", SDTStore,
309311
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
312+
def z_stckf : SDNode<"SystemZISD::STCKF", SDT_ZStoreInherent,
313+
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
310314

311315
def z_tdc : SDNode<"SystemZISD::TDC", SDT_ZTest>;
312316

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=s390x-ibm-linux | FileCheck %s
3+
4+
; Verify that we correctly lower ISD::READCYCLECOUNTER.
5+
6+
define i64 @test_builtin_readcyclecounter1() {
7+
; CHECK-LABEL: test_builtin_readcyclecounter1:
8+
; CHECK: # %bb.0:
9+
; CHECK-NEXT: aghi %r15, -168
10+
; CHECK-NEXT: .cfi_def_cfa_offset 328
11+
; CHECK-NEXT: stckf 160(%r15)
12+
; CHECK-NEXT: lg %r2, 160(%r15)
13+
; CHECK-NEXT: aghi %r15, 168
14+
; CHECK-NEXT: br %r14
15+
%1 = tail call i64 @llvm.readcyclecounter()
16+
ret i64 %1
17+
}
18+
19+
define void @test_builtin_readcyclecounter2(ptr %ptr) {
20+
; CHECK-LABEL: test_builtin_readcyclecounter2:
21+
; CHECK: # %bb.0:
22+
; CHECK-NEXT: stckf 0(%r2)
23+
; CHECK-NEXT: br %r14
24+
%1 = tail call i64 @llvm.readcyclecounter()
25+
store i64 %1, ptr %ptr
26+
ret void
27+
}

0 commit comments

Comments
 (0)