-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[aarch64] Add support for the __{inc|add}x18{byte|word|dword|qword intrinsics #117752
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-backend-x86 Author: Daniel Paoliello (dpaoliello) ChangesAdds support for the following MSVC intrinsics:
These are documented at: <https://learn.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=msvc-170> Full diff: https://github.com/llvm/llvm-project/pull/117752.diff 4 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 473b1d4698f04a..aeb9cdee38f40f 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -281,6 +281,16 @@ TARGET_HEADER_BUILTIN(__readx18word, "UsUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES,
TARGET_HEADER_BUILTIN(__readx18dword, "UNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readx18qword, "ULLiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__addx18byte, "vUNiUc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__addx18word, "vUNiUs", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__addx18dword, "vUNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__addx18qword, "vUNiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(__incx18byte, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__incx18word, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__incx18dword, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__incx18qword, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
+
TARGET_HEADER_BUILTIN(_CopyDoubleFromInt64, "dSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_CopyFloatFromInt32, "fSi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_CopyInt32FromFloat, "Sif", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 91b70b4fdf3d20..d6f5e71d989bbc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -244,6 +244,19 @@ static Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) {
return CGF.Builder.CreateBitCast(BitVec, ResultType);
}
+/// Helper for the read/write/add/inc X18 builtins: read the X18 register and
+/// return it as an i8 pointer.
+Value *readX18AsPtr(CodeGenFunction &CGF) {
+ LLVMContext &Context = CGF.CGM.getLLVMContext();
+ llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
+ llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
+ llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
+ llvm::Function *F =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF.Int64Ty});
+ llvm::Value *X18 = CGF.Builder.CreateCall(F, Metadata);
+ return CGF.Builder.CreateIntToPtr(X18, CGF.Int8PtrTy);
+}
+
/// getBuiltinLibFunction - Given a builtin id for a function like
/// "__builtin_fabsf", return a Function* for "fabsf".
llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
@@ -11821,14 +11834,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
BuiltinID == AArch64::BI__writex18dword ||
BuiltinID == AArch64::BI__writex18qword) {
// Read x18 as i8*
- LLVMContext &Context = CGM.getLLVMContext();
- llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
- llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
- llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
- llvm::Function *F =
- CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
- llvm::Value *X18 = Builder.CreateCall(F, Metadata);
- X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
+ llvm::Value *X18 = readX18AsPtr(*this);
// Store val at x18 + offset
Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty);
@@ -11842,23 +11848,67 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
BuiltinID == AArch64::BI__readx18word ||
BuiltinID == AArch64::BI__readx18dword ||
BuiltinID == AArch64::BI__readx18qword) {
+ // Read x18 as i8*
+ llvm::Value *X18 = readX18AsPtr(*this);
+
+ // Load x18 + offset
+ Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty);
+ Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
llvm::Type *IntTy = ConvertType(E->getType());
+ LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
+ return Load;
+ }
+
+ if (BuiltinID == AArch64::BI__addx18byte ||
+ BuiltinID == AArch64::BI__addx18word ||
+ BuiltinID == AArch64::BI__addx18dword ||
+ BuiltinID == AArch64::BI__addx18qword ||
+ BuiltinID == AArch64::BI__incx18byte ||
+ BuiltinID == AArch64::BI__incx18word ||
+ BuiltinID == AArch64::BI__incx18dword ||
+ BuiltinID == AArch64::BI__incx18qword) {
+ llvm::Type *IntTy;
+ bool isIncrement;
+ switch (BuiltinID) {
+ case AArch64::BI__incx18byte:
+ IntTy = Int8Ty;
+ isIncrement = true;
+ break;
+ case AArch64::BI__incx18word:
+ IntTy = Int16Ty;
+ isIncrement = true;
+ break;
+ case AArch64::BI__incx18dword:
+ IntTy = Int32Ty;
+ isIncrement = true;
+ break;
+ case AArch64::BI__incx18qword:
+ IntTy = Int64Ty;
+ isIncrement = true;
+ break;
+ default:
+ IntTy = ConvertType(E->getArg(1)->getType());
+ isIncrement = false;
+ break;
+ }
// Read x18 as i8*
- LLVMContext &Context = CGM.getLLVMContext();
- llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
- llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
- llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
- llvm::Function *F =
- CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
- llvm::Value *X18 = Builder.CreateCall(F, Metadata);
- X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
+ llvm::Value *X18 = readX18AsPtr(*this);
// Load x18 + offset
Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty);
Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
- return Load;
+
+ // Add values
+ Value *ValToAdd =
+ isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1));
+ Value *AddResult = Builder.CreateAdd(Load, ValToAdd);
+
+ // Store val at x18 + offset
+ StoreInst *Store =
+ Builder.CreateAlignedStore(AddResult, Ptr, CharUnits::One());
+ return Store;
}
if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 6308c865ca9136..9e89ae31187d14 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -396,6 +396,16 @@ unsigned short __readx18word(unsigned long offset);
unsigned long __readx18dword(unsigned long offset);
unsigned __int64 __readx18qword(unsigned long offset);
+void __addx18byte(unsigned long offset, unsigned char data);
+void __addx18word(unsigned long offset, unsigned short data);
+void __addx18dword(unsigned long offset, unsigned long data);
+void __addx18qword(unsigned long offset, unsigned __int64 data);
+
+void __incx18byte(unsigned long offset);
+void __incx18word(unsigned long offset);
+void __incx18dword(unsigned long offset);
+void __incx18qword(unsigned long offset);
+
double _CopyDoubleFromInt64(__int64);
float _CopyFloatFromInt32(__int32);
__int32 _CopyInt32FromFloat(float);
diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
index 7953618d2f9d13..fd104642664611 100644
--- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -288,6 +288,154 @@ unsigned __int64 check__readx18qword(unsigned LONG offset) {
// CHECK-MSCOMPAT: %[[RETVAL:.*]] = load i64, ptr %[[PTR]], align 1
// CHECK-MSCOMPAT: ret i64 %[[RETVAL]]
+#ifdef __LP64__
+void check__addx18byte(unsigned char data, unsigned LONG offset) {
+#else
+void check__addx18byte(unsigned LONG offset, unsigned char data) {
+#endif
+ __addx18byte(offset, data);
+}
+
+// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i8, align 1
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i8 %data, ptr %[[DATA_ADDR]], align 1
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i8, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i8 %[[ORIG_VAL]], %[[DATA]]
+// CHECK-MSCOMPAT: store i8 %[[SUM]], ptr %[[PTR]], align 1
+
+#ifdef __LP64__
+void check__addx18word(unsigned short data, unsigned LONG offset) {
+#else
+void check__addx18word(unsigned LONG offset, unsigned short data) {
+#endif
+ __addx18word(offset, data);
+}
+
+// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i16, align 2
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i16 %data, ptr %[[DATA_ADDR]], align 2
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i16, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i16 %[[ORIG_VAL]], %[[DATA]]
+// CHECK-MSCOMPAT: store i16 %[[SUM]], ptr %[[PTR]], align 1
+
+#ifdef __LP64__
+void check__addx18dword(unsigned LONG data, unsigned LONG offset) {
+#else
+void check__addx18dword(unsigned LONG offset, unsigned LONG data) {
+#endif
+ __addx18dword(offset, data);
+}
+
+// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i32 %data, ptr %[[DATA_ADDR]], align 4
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i32, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[DATA:.*]] = load i32, ptr %[[DATA_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i32 %[[ORIG_VAL]], %[[DATA]]
+// CHECK-MSCOMPAT: store i32 %[[SUM]], ptr %[[PTR]], align 1
+
+#ifdef __LP64__
+void check__addx18qword(unsigned __int64 data, unsigned LONG offset) {
+#else
+void check__addx18qword(unsigned LONG offset, unsigned __int64 data) {
+#endif
+ __addx18qword(offset, data);
+}
+
+// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i64, align 8
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i64 %data, ptr %[[DATA_ADDR]], align 8
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i64, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i64 %[[ORIG_VAL]], %[[DATA]]
+// CHECK-MSCOMPAT: store i64 %[[SUM]], ptr %[[PTR]], align 1
+
+void check__incx18byte(unsigned LONG offset) {
+ __incx18byte(offset);
+}
+
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i8, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i8 %[[ORIG_VAL]], 1
+// CHECK-MSCOMPAT: store i8 %[[SUM]], ptr %[[PTR]], align 1
+
+void check__incx18word(unsigned LONG offset) {
+ __incx18word(offset);
+}
+
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i16, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i16 %[[ORIG_VAL]], 1
+// CHECK-MSCOMPAT: store i16 %[[SUM]], ptr %[[PTR]], align 1
+
+void check__incx18dword(unsigned LONG offset) {
+ __incx18dword(offset);
+}
+
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i32, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i32 %[[ORIG_VAL]], 1
+// CHECK-MSCOMPAT: store i32 %[[SUM]], ptr %[[PTR]], align 1
+
+void check__incx18qword(unsigned LONG offset) {
+ __incx18qword(offset);
+}
+
+// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4
+// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]])
+// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr
+// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4
+// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64
+// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]]
+// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i64, ptr %[[PTR]], align 1
+// CHECK-MSCOMPAT: %[[SUM:.*]] = add i64 %[[ORIG_VAL]], 1
+// CHECK-MSCOMPAT: store i64 %[[SUM]], ptr %[[PTR]], align 1
+
double check__CopyDoubleFromInt64(__int64 arg1) {
return _CopyDoubleFromInt64(arg1);
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just spotted an issue: I don't think you're emitting the operations in the correct order. You need to emit both arguments before you read the register or load the value.
If you have some non-trivial operation like a call in one of the arguments, you don't want that call to happen in the middle of the operation. MSVC appears to emit the arguments before touching x18.
Done, and fixed the read/write x18 intrinsics as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Adds support for the following MSVC intrinsics:
__addx18byte
__addx18word
__addx18dword
__addx18qword
__incx18byte
__incx18word
__incx18dword
__incx18qword
These are documented at: https://learn.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=msvc-170