Index: lib/Target/Sparc/LeonFeatures.td =================================================================== --- lib/Target/Sparc/LeonFeatures.td +++ lib/Target/Sparc/LeonFeatures.td @@ -58,3 +58,7 @@ "true", "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store" >; + +def LeonCycleCounter + : SubtargetFeature<"leoncyclecounter", "HasLeonCycleCounter", "true", + "Use the Leon cycle counter register">; Index: lib/Target/Sparc/Sparc.td =================================================================== --- lib/Target/Sparc/Sparc.td +++ lib/Target/Sparc/Sparc.td @@ -159,7 +159,7 @@ // LEON 4 FT (GR740) // TO DO: Place-holder: Processor specific features will be added *very* soon here. def : Processor<"gr740", LEON4Itineraries, - [FeatureLeon, UMACSMACSupport, LeonCASA]>; + [FeatureLeon, UMACSMACSupport, LeonCASA, LeonCycleCounter]>; //===----------------------------------------------------------------------===// // Declare the target which we are implementing Index: lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- lib/Target/Sparc/SparcISelLowering.cpp +++ lib/Target/Sparc/SparcISelLowering.cpp @@ -1841,6 +1841,9 @@ setOperationAction(ISD::FMUL, MVT::f32, Promote); } + if (Subtarget->hasLeonCycleCounter()) + setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom); + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); setMinFunctionAlignment(2); @@ -3587,7 +3590,16 @@ getLibcallName(libCall), 1)); return; - + case ISD::READCYCLECOUNTER: { + assert(Subtarget->hasLeonCycleCounter()); + SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32); + SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32); + SDValue Ops[] = { Lo, Hi }; + SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops); + Results.push_back(Pair); + Results.push_back(N->getOperand(0)); + return; + } case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: // Custom lower only if it involves f128 or i64. Index: lib/Target/Sparc/SparcRegisterInfo.cpp =================================================================== --- lib/Target/Sparc/SparcRegisterInfo.cpp +++ lib/Target/Sparc/SparcRegisterInfo.cpp @@ -95,6 +95,9 @@ } } + if (Subtarget.hasLeonCycleCounter()) + Reserved.set(SP::ASR23); + return Reserved; } Index: lib/Target/Sparc/SparcSubtarget.h =================================================================== --- lib/Target/Sparc/SparcSubtarget.h +++ lib/Target/Sparc/SparcSubtarget.h @@ -50,6 +50,7 @@ bool InsertNOPLoad; bool FixAllFDIVSQRT; bool DetectRoundChange; + bool HasLeonCycleCounter; SparcInstrInfo InstrInfo; SparcTargetLowering TLInfo; @@ -95,6 +96,7 @@ bool insertNOPLoad() const { return InsertNOPLoad; } bool fixAllFDIVSQRT() const { return FixAllFDIVSQRT; } bool detectRoundChange() const { return DetectRoundChange; } + bool hasLeonCycleCounter() const { return HasLeonCycleCounter; } /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. Index: lib/Target/Sparc/SparcSubtarget.cpp =================================================================== --- lib/Target/Sparc/SparcSubtarget.cpp +++ lib/Target/Sparc/SparcSubtarget.cpp @@ -47,6 +47,7 @@ InsertNOPLoad = false; FixAllFDIVSQRT = false; DetectRoundChange = false; + HasLeonCycleCounter = false; // Determine default and user specified characteristics std::string CPUName = CPU; Index: test/CodeGen/SPARC/readcycle.ll =================================================================== --- /dev/null +++ test/CodeGen/SPARC/readcycle.ll @@ -0,0 +1,11 @@ +; RUN: llc < %s -march=sparc -mcpu=gr740 -verify-machineinstrs | FileCheck %s +; CHECK: rd %asr23, %o1 +; CHECK: mov %g0, %o0 + +define i64 @test() { +entry: + %0 = call i64 @llvm.readcyclecounter() + ret i64 %0 +} + +declare i64 @llvm.readcyclecounter()