r344765 - [COFF, ARM64] Add _ReadStatusReg and_WriteStatusReg intrinsics

Mandeep Singh Grang via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 18 16:35:35 PDT 2018


Author: mgrang
Date: Thu Oct 18 16:35:35 2018
New Revision: 344765

URL: http://llvm.org/viewvc/llvm-project?rev=344765&view=rev
Log:
[COFF, ARM64] Add _ReadStatusReg and_WriteStatusReg intrinsics

Reviewers: rnk, compnerd, mstorsjo, efriedma, TomTan, haripul, javed.absar

Reviewed By: efriedma

Subscribers: dmajor, kristof.beyls, chrib, cfe-commits

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

Added:
    cfe/trunk/test/CodeGen/arm64-microsoft-status-reg.cpp
Modified:
    cfe/trunk/include/clang/Basic/BuiltinsAArch64.def
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/Headers/intrin.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/Sema/builtins-microsoft-arm64.c

Modified: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/BuiltinsAArch64.def?rev=344765&r1=344764&r2=344765&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/BuiltinsAArch64.def (original)
+++ cfe/trunk/include/clang/Basic/BuiltinsAArch64.def Thu Oct 18 16:35:35 2018
@@ -106,6 +106,8 @@ TARGET_HEADER_BUILTIN(_InterlockedXor64,
 
 TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_ReadStatusReg,  "ii",  "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_WriteStatusReg, "vii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
 
 #undef BUILTIN
 #undef LANGBUILTIN

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=344765&r1=344764&r2=344765&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Oct 18 16:35:35 2018
@@ -6667,6 +6667,43 @@ Value *CodeGenFunction::EmitAArch64Built
     return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead);
   }
 
+  if (BuiltinID == AArch64::BI_ReadStatusReg ||
+      BuiltinID == AArch64::BI_WriteStatusReg) {
+    LLVMContext &Context = CGM.getLLVMContext();
+
+    unsigned SysReg =
+      E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
+
+    std::string SysRegStr;
+    llvm::raw_string_ostream(SysRegStr) <<
+                       ((1 << 1) | ((SysReg >> 14) & 1))  << ":" <<
+                       ((SysReg >> 11) & 7)               << ":" <<
+                       ((SysReg >> 7)  & 15)              << ":" <<
+                       ((SysReg >> 3)  & 15)              << ":" <<
+                       ( SysReg        & 7);
+
+    llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) };
+    llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
+    llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
+
+    llvm::Type *RegisterType = Int64Ty;
+    llvm::Type *ValueType = Int32Ty;
+    llvm::Type *Types[] = { RegisterType };
+
+    if (BuiltinID == AArch64::BI_ReadStatusReg) {
+      llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
+      llvm::Value *Call = Builder.CreateCall(F, Metadata);
+
+      return Builder.CreateTrunc(Call, ValueType);
+    }
+
+    llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
+    llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
+    ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
+
+    return Builder.CreateCall(F, { Metadata, ArgValue });
+  }
+
   // Find out if any arguments are required to be integer constant
   // expressions.
   unsigned ICEArguments = 0;

Modified: cfe/trunk/lib/Headers/intrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/intrin.h?rev=344765&r1=344764&r2=344765&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/intrin.h (original)
+++ cfe/trunk/lib/Headers/intrin.h Thu Oct 18 16:35:35 2018
@@ -870,6 +870,8 @@ __nop(void) {
 #if defined(__aarch64__)
 unsigned __int64 __getReg(int);
 long _InterlockedAdd(long volatile *Addend, long Value);
+int _ReadStatusReg(int);
+void _WriteStatusReg(int, int);
 #endif
 
 /*----------------------------------------------------------------------------*\

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=344765&r1=344764&r2=344765&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Oct 18 16:35:35 2018
@@ -1749,6 +1749,13 @@ bool Sema::CheckAArch64BuiltinFunctionCa
       BuiltinID == AArch64::BI__builtin_arm_wsrp)
     return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
 
+  // Only check the valid encoding range. Any constant in this range would be
+  // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
+  // an exception for incorrect registers. This matches MSVC behavior.
+  if (BuiltinID == AArch64::BI_ReadStatusReg ||
+      BuiltinID == AArch64::BI_WriteStatusReg)
+    return SemaBuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
+
   if (BuiltinID == AArch64::BI__getReg)
     return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
 

Added: cfe/trunk/test/CodeGen/arm64-microsoft-status-reg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm64-microsoft-status-reg.cpp?rev=344765&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arm64-microsoft-status-reg.cpp (added)
+++ cfe/trunk/test/CodeGen/arm64-microsoft-status-reg.cpp Thu Oct 18 16:35:35 2018
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm -S \
+// RUN: -o - %s | FileCheck %s -check-prefix CHECK-ASM
+
+// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm \
+// RUN: -o - %s | FileCheck %s -check-prefix CHECK-IR
+
+// From winnt.h
+#define ARM64_SYSREG(op0, op1, crn, crm, op2) \
+        ( ((op0 & 1) << 14) | \
+          ((op1 & 7) << 11) | \
+          ((crn & 15) << 7) | \
+          ((crm & 15) << 3) | \
+          ((op2 & 7) << 0) )
+
+#define ARM64_CNTVCT            ARM64_SYSREG(3,3,14, 0,2)  // Generic Timer counter register
+#define ARM64_PMCCNTR_EL0       ARM64_SYSREG(3,3, 9,13,0)  // Cycle Count Register [CP15_PMCCNTR]
+#define ARM64_PMSELR_EL0        ARM64_SYSREG(3,3, 9,12,5)  // Event Counter Selection Register [CP15_PMSELR]
+#define ARM64_PMXEVCNTR_EL0     ARM64_SYSREG(3,3, 9,13,2)  // Event Count Register [CP15_PMXEVCNTR]
+#define ARM64_PMXEVCNTRn_EL0(n) ARM64_SYSREG(3,3,14, 8+((n)/8), (n)%8)    // Direct Event Count Register [n/a]
+#define ARM64_TPIDR_EL0         ARM64_SYSREG(3,3,13, 0,2)  // Thread ID Register, User Read/Write [CP15_TPIDRURW]
+#define ARM64_TPIDRRO_EL0       ARM64_SYSREG(3,3,13, 0,3)  // Thread ID Register, User Read Only [CP15_TPIDRURO]
+#define ARM64_TPIDR_EL1         ARM64_SYSREG(3,0,13, 0,4)  // Thread ID Register, Privileged Only [CP15_TPIDRPRW]
+
+void check_ReadWriteStatusReg(int v) {
+  int ret;
+  ret = _ReadStatusReg(ARM64_CNTVCT);
+// CHECK-ASM: mrs     x8, CNTVCT_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
+
+  ret = _ReadStatusReg(ARM64_PMCCNTR_EL0);
+// CHECK-ASM: mrs     x8, PMCCNTR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+  ret = _ReadStatusReg(ARM64_PMSELR_EL0);
+// CHECK-ASM: mrs     x8, PMSELR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD4:.*]])
+
+  ret = _ReadStatusReg(ARM64_PMXEVCNTR_EL0);
+// CHECK-ASM: mrs     x8, PMXEVCNTR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD5:.*]])
+
+  ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(0));
+// CHECK-ASM: mrs     x8, PMEVCNTR0_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD6:.*]])
+
+  ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(1));
+// CHECK-ASM: mrs     x8, PMEVCNTR1_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD7:.*]])
+
+  ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(30));
+// CHECK-ASM: mrs     x8, PMEVCNTR30_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD8:.*]])
+
+  ret = _ReadStatusReg(ARM64_TPIDR_EL0);
+// CHECK-ASM: mrs     x8, TPIDR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD9:.*]])
+
+  ret = _ReadStatusReg(ARM64_TPIDRRO_EL0);
+// CHECK-ASM: mrs     x8, TPIDRRO_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD10:.*]])
+
+  ret = _ReadStatusReg(ARM64_TPIDR_EL1);
+// CHECK-ASM: mrs     x8, TPIDR_EL1
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD11:.*]])
+
+
+  _WriteStatusReg(ARM64_CNTVCT, v);
+// CHECK-ASM: msr     S3_3_C14_C0_2, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_PMCCNTR_EL0, v);
+// CHECK-ASM: msr     PMCCNTR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_PMSELR_EL0, v);
+// CHECK-ASM: msr     PMSELR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_PMXEVCNTR_EL0, v);
+// CHECK-ASM: msr     PMXEVCNTR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(0), v);
+// CHECK-ASM: msr     PMEVCNTR0_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(1), v);
+// CHECK-ASM: msr     PMEVCNTR1_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD7:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(30), v);
+// CHECK-ASM: msr     PMEVCNTR30_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD8:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_TPIDR_EL0, v);
+// CHECK-ASM: msr     TPIDR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD9:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_TPIDRRO_EL0, v);
+// CHECK-ASM: msr     TPIDRRO_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD10:.*]], i64 {{%.*}})
+
+  _WriteStatusReg(ARM64_TPIDR_EL1, v);
+// CHECK-ASM: msr     TPIDR_EL1, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD11:.*]], i64 {{%.*}})
+}
+
+// CHECK-IR: ![[MD2]] = !{!"3:3:14:0:2"}
+// CHECK-IR: ![[MD3]] = !{!"3:3:9:13:0"}
+// CHECK-IR: ![[MD4]] = !{!"3:3:9:12:5"}
+// CHECK-IR: ![[MD5]] = !{!"3:3:9:13:2"}
+// CHECK-IR: ![[MD6]] = !{!"3:3:14:8:0"}
+// CHECK-IR: ![[MD7]] = !{!"3:3:14:8:1"}
+// CHECK-IR: ![[MD8]] = !{!"3:3:14:11:6"}
+// CHECK-IR: ![[MD9]] = !{!"3:3:13:0:2"}
+// CHECK-IR: ![[MD10]] = !{!"3:3:13:0:3"}
+// CHECK-IR: ![[MD11]] = !{!"3:0:13:0:4"}

Modified: cfe/trunk/test/Sema/builtins-microsoft-arm64.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/builtins-microsoft-arm64.c?rev=344765&r1=344764&r2=344765&view=diff
==============================================================================
--- cfe/trunk/test/Sema/builtins-microsoft-arm64.c (original)
+++ cfe/trunk/test/Sema/builtins-microsoft-arm64.c Thu Oct 18 16:35:35 2018
@@ -7,3 +7,9 @@ void check__getReg() {
   __getReg(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
   __getReg(32); // expected-error-re {{argument value {{.*}} is outside the valid range}}
 }
+
+void check_ReadWriteStatusReg(int v) {
+  int x;
+  _ReadStatusReg(x); // expected-error {{argument to '_ReadStatusReg' must be a constant integer}}
+  _WriteStatusReg(x, v); // expected-error {{argument to '_WriteStatusReg' must be a constant integer}}
+}




More information about the cfe-commits mailing list