[AArch64] Lower READCYCLECOUNTER using MRS CNTVCT_EL0
authorSalvatore Dipietro <dipiets@amazon.com>
Fri, 9 Dec 2022 10:36:16 +0000 (10:36 +0000)
committerDavid Green <david.green@arm.com>
Fri, 9 Dec 2022 10:36:16 +0000 (10:36 +0000)
As suggested in D12425 it would be better for the readcyclecounter
function on ARM architecture to use the CNTVCT_EL0 register
(Counter-timer Virtual Count register) instead of the PMCCNTR_EL0
(Performance Monitors Cycle Count Register) because the PMCCNTR_EL0 is a
PMU register which, depending on the configuration, it might always
return zeroes and it doesn't guaranteed to always be increased.

Differential Revision: https://reviews.llvm.org/D136999

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/test/CodeGen/AArch64/mattr-all.ll
llvm/test/CodeGen/AArch64/readcyclecounter.ll

index 43d7b26..f79b0f1 100644 (file)
@@ -833,10 +833,8 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::LOAD, MVT::v4f64, Custom);
   setOperationAction(ISD::LOAD, MVT::v4i64, Custom);
 
-  // Lower READCYCLECOUNTER using an mrs from PMCCNTR_EL0.
-  // This requires the Performance Monitors extension.
-  if (Subtarget->hasPerfMon())
-    setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Legal);
+  // Lower READCYCLECOUNTER using an mrs from CNTVCT_EL0.
+  setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Legal);
 
   if (getLibcallName(RTLIB::SINCOS_STRET_F32) != nullptr &&
       getLibcallName(RTLIB::SINCOS_STRET_F64) != nullptr) {
index f3fbb94..6bfeae0 100644 (file)
@@ -125,7 +125,6 @@ def HasRAS           : Predicate<"Subtarget->hasRAS()">,
                                  AssemblerPredicateWithAll<(all_of FeatureRAS), "ras">;
 def HasRDM           : Predicate<"Subtarget->hasRDM()">,
                                  AssemblerPredicateWithAll<(all_of FeatureRDM), "rdm">;
-def HasPerfMon       : Predicate<"Subtarget->hasPerfMon()">;
 def HasFullFP16      : Predicate<"Subtarget->hasFullFP16()">,
                                  AssemblerPredicateWithAll<(all_of FeatureFullFP16), "fullfp16">;
 def HasFP16FML       : Predicate<"Subtarget->hasFP16FML()">,
@@ -1526,9 +1525,8 @@ def HWASAN_CHECK_MEMACCESS_SHORTGRANULES : Pseudo<
   Sched<[]>;
 }
 
-// The cycle counter PMC register is PMCCNTR_EL0.
-let Predicates = [HasPerfMon] in
-def : Pat<(readcyclecounter), (MRS 0xdce8)>;
+// The virtual cycle counter register is CNTVCT_EL0.
+def : Pat<(readcyclecounter), (MRS 0xdf02)>;
 
 // FPCR register
 let Uses = [FPCR] in
index c99880b..78a9051 100644 (file)
@@ -11,14 +11,3 @@ define half @bf16() nounwind {
 ; CHECK-NEXT:    ret
   ret half 0xH0000
 }
-
-define i64 @perfmon() nounwind {
-; CHECK-LABEL: perfmon:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov x0, xzr
-; CHECK-NEXT:    ret
-  %tmp0 = call i64 @llvm.readcyclecounter()
-  ret i64 %tmp0
-}
-
-declare i64 @llvm.readcyclecounter()
index 424a446..0cb8c39 100644 (file)
@@ -1,45 +1,11 @@
-; RUN: llc -mtriple=aarch64-unknown-unknown -mattr=+perfmon -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
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a53 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a55 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a510 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a65 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a76 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a77 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a78 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a78c -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-a710 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-r82 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-x1 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=cortex-x2 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=neoverse-e1 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=neoverse-n1 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=neoverse-n2 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
-; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=neoverse-v1 -asm-verbose=false < %s |\
-; RUN:   FileCheck %s --check-prefix=CHECK --check-prefix=PERFMON
+; RUN: llc -mtriple=aarch64 < %s | FileCheck %s
+
 
 define i64 @test_readcyclecounter() nounwind {
   ; CHECK-LABEL:   test_readcyclecounter:
-  ; PERFMON-NEXT:   mrs x0, PMCCNTR_EL0
-  ; NOPERFMON-NEXT: mov x0, xzr
-  ; CHECK-NEXT:     ret
+  ; CHECK:         // %bb.0:
+  ; CHECK-NEXT:    mrs x0, CNTVCT_EL0
+  ; CHECK-NEXT:    ret
   %tmp0 = call i64 @llvm.readcyclecounter()
   ret i64 %tmp0
 }