def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true",
"Enable ARMv8 CRC-32 checksum instructions">;
+def FeaturePerfMon : SubtargetFeature<"perfmon", "HasPerfMon", "true",
+ "Enable ARMv8 PMUv3 Performance Monitors extension">;
+
/// Cyclone has register move instructions which are "free".
def FeatureZCRegMove : SubtargetFeature<"zcm", "HasZeroCycleRegMove", "true",
"Has zero-cycle register moves">;
[FeatureFPARMv8,
FeatureNEON,
FeatureCrypto,
- FeatureCRC]>;
+ FeatureCRC,
+ FeaturePerfMon]>;
def ProcA57 : SubtargetFeature<"a57", "ARMProcFamily", "CortexA57",
"Cortex-A57 ARM processors",
[FeatureFPARMv8,
FeatureNEON,
FeatureCrypto,
- FeatureCRC]>;
+ FeatureCRC,
+ FeaturePerfMon]>;
def ProcCyclone : SubtargetFeature<"cyclone", "ARMProcFamily", "Cyclone",
"Cyclone",
FeatureNEON,
FeatureCrypto,
FeatureCRC,
+ FeaturePerfMon,
FeatureZCRegMove, FeatureZCZeroing]>;
def : ProcessorModel<"generic", NoSchedModel, [FeatureFPARMv8,
FeatureNEON,
- FeatureCRC]>;
+ FeatureCRC,
+ FeaturePerfMon]>;
def : ProcessorModel<"cortex-a53", CortexA53Model, [ProcA53]>;
def : ProcessorModel<"cortex-a57", CortexA57Model, [ProcA57]>;
setOperationAction(ISD::PREFETCH, MVT::Other, Custom);
+ // Lower READCYCLECOUNTER using an mrs from PMCCNTR_EL0.
+ // This requires the Performance Monitors extension.
+ if (Subtarget->hasPerfMon())
+ 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
AssemblerPredicate<"FeatureCrypto", "crypto">;
def HasCRC : Predicate<"Subtarget->hasCRC()">,
AssemblerPredicate<"FeatureCRC", "crc">;
+def HasPerfMon : Predicate<"Subtarget->hasPerfMon()">;
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
def IsCyclone : Predicate<"Subtarget->isCyclone()">;
// TPIDR_EL0.
def : Pat<(AArch64threadpointer), (MRS 0xde82)>;
+// The cycle counter PMC register is PMCCNTR_EL0.
+let Predicates = [HasPerfMon] in
+def : Pat<(readcyclecounter), (MRS 0xdce8)>;
+
// Generic system instructions
def SYSxt : SystemXtI<0, "sys">;
def SYSLxt : SystemLXtI<1, "sysl">;
const TargetMachine &TM, bool LittleEndian)
: AArch64GenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others),
HasV8_1aOps(false), HasFPARMv8(false), HasNEON(false), HasCrypto(false),
- HasCRC(false), HasZeroCycleRegMove(false), HasZeroCycleZeroing(false),
- StrictAlign(false), ReserveX18(false), IsLittle(LittleEndian),
- CPUString(CPU), TargetTriple(TT), FrameLowering(),
+ HasCRC(false), HasPerfMon(false), HasZeroCycleRegMove(false),
+ HasZeroCycleZeroing(false), StrictAlign(false), ReserveX18(false),
+ IsLittle(LittleEndian), CPUString(CPU), TargetTriple(TT), FrameLowering(),
InstrInfo(initializeSubtargetDependencies(FS)), TSInfo(),
TLInfo(TM, *this) {}
bool HasNEON;
bool HasCrypto;
bool HasCRC;
+ bool HasPerfMon;
// HasZeroCycleRegMove - Has zero-cycle register mov instructions.
bool HasZeroCycleRegMove;
bool hasNEON() const { return HasNEON; }
bool hasCrypto() const { return HasCrypto; }
bool hasCRC() const { return HasCRC; }
+ bool hasPerfMon() const { return HasPerfMon; }
bool isLittleEndian() const { return IsLittle; }
--- /dev/null
+; RUN: llc -mtriple=aarch64-unknown-unknown -asm-verbose=false < %s |\
+; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
+; RUN: llc -mtriple=aarch64-unknown-unknown -mattr=-perfmon -asm-verbose=false < %s |\
+; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOPERFMON
+
+define i64 @test_readcyclecounter() nounwind {
+ ; CHECK-LABEL: test_readcyclecounter:
+ ; PERFMON-NEXT: mrs x0, PMCCNTR_EL0
+ ; NOPERFMON-NEXT: mov x0, xzr
+ ; CHECK-NEXT: ret
+ %tmp0 = call i64 @llvm.readcyclecounter()
+ ret i64 %tmp0
+}
+
+declare i64 @llvm.readcyclecounter()