[AArch64] Lower READCYCLECOUNTER using MRS PMCCTNR_EL0.
authorAhmed Bougacha <ahmed.bougacha@gmail.com>
Tue, 1 Sep 2015 16:23:45 +0000 (16:23 +0000)
committerAhmed Bougacha <ahmed.bougacha@gmail.com>
Tue, 1 Sep 2015 16:23:45 +0000 (16:23 +0000)
This matches the ARM behavior. In both cases, the register is part
of the optional Performance Monitors extension, so, add the feature,
and enable it for the A-class processors we support.

Differential Revision: http://reviews.llvm.org/D12425

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246555 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64.td
lib/Target/AArch64/AArch64ISelLowering.cpp
lib/Target/AArch64/AArch64InstrInfo.td
lib/Target/AArch64/AArch64Subtarget.cpp
lib/Target/AArch64/AArch64Subtarget.h
test/CodeGen/AArch64/readcyclecounter.ll [new file with mode: 0644]

index d19b319ff7e86b091b0ae5903f3fefbbad3bd1c2..ad6a79ed718eee750c3e0af677b10c7ce645c757 100644 (file)
@@ -32,6 +32,9 @@ def FeatureCrypto : SubtargetFeature<"crypto", "HasCrypto", "true",
 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">;
@@ -84,14 +87,16 @@ def ProcA53     : SubtargetFeature<"a53", "ARMProcFamily", "CortexA53",
                                    [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",
@@ -99,11 +104,13 @@ def ProcCyclone : SubtargetFeature<"cyclone", "ARMProcFamily", "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]>;
index 4198071e3d634e266c403cc31de9e7999e7a1a62..20ed0016a792fdb6c54cacb01b6d3342db1f5ceb 100644 (file)
@@ -399,6 +399,11 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
 
   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
index 17c0afc1ae4c0dc17806559c428a22226df5c2e2..d3c244977ec5944783976a6edfaf6adaaa6c6c91 100644 (file)
@@ -24,6 +24,7 @@ def HasCrypto        : Predicate<"Subtarget->hasCrypto()">,
                                  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()">;
@@ -404,6 +405,10 @@ def MSRpstate: MSRpstateI;
 // 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">;
index 6aa3ed5cec2a91865bd8e1e42c2263851d05049d..6dfa0af4f88240d447422af7949d3a1a36dafe28 100644 (file)
@@ -47,9 +47,9 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
                                    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) {}
 
index 6b5ca20f03399e46a514052bbbba738b41cbdb2e..623202182078387661a1bd58a2609df0b523d867 100644 (file)
@@ -44,6 +44,7 @@ protected:
   bool HasNEON;
   bool HasCrypto;
   bool HasCRC;
+  bool HasPerfMon;
 
   // HasZeroCycleRegMove - Has zero-cycle register mov instructions.
   bool HasZeroCycleRegMove;
@@ -114,6 +115,7 @@ public:
   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; }
 
diff --git a/test/CodeGen/AArch64/readcyclecounter.ll b/test/CodeGen/AArch64/readcyclecounter.ll
new file mode 100644 (file)
index 0000000..037f118
--- /dev/null
@@ -0,0 +1,15 @@
+; 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()