Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -399,6 +399,11 @@ setOperationAction(ISD::PREFETCH, MVT::Other, Custom); + // Lower READCYCLECOUNTER using an mrs from PMCCNTR_EL0. + // Technically, this requires the Performance Monitors (optional) extension, + // but all of the A-class CPUs we support have it. + setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Legal); + if (Subtarget->isTargetMachO()) { // For iOS, we don't want to the normal expansion of a libcall to // sincos. We want to issue a libcall to __sincos_stret to avoid memory Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -404,6 +404,9 @@ // TPIDR_EL0. def : Pat<(AArch64threadpointer), (MRS 0xde82)>; +// The cycle counter PMC register is PMCCNTR_EL0. +def : Pat<(readcyclecounter), (MRS 0xdce8)>; + // Generic system instructions def SYSxt : SystemXtI<0, "sys">; def SYSLxt : SystemLXtI<1, "sysl">; Index: test/CodeGen/AArch64/readcyclecounter.ll =================================================================== --- test/CodeGen/AArch64/readcyclecounter.ll +++ test/CodeGen/AArch64/readcyclecounter.ll @@ -0,0 +1,11 @@ +; RUN: llc -mtriple=arm64-unknown-unknown -asm-verbose=false < %s | FileCheck %s + +define i64 @test_readcyclecounter() nounwind { + ; CHECK-LABEL: test_readcyclecounter: + ; CHECK-NEXT: mrs x0, PMCCNTR_EL0 + ; CHECK-NEXT: ret + %tmp0 = call i64 @llvm.readcyclecounter() + ret i64 %tmp0 +} + +declare i64 @llvm.readcyclecounter()