diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index 473b1d4698f04..aeb9cdee38f40 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 91b70b4fdf3d2..e73c79baf794d 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, @@ -11820,21 +11833,18 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, BuiltinID == AArch64::BI__writex18word || BuiltinID == AArch64::BI__writex18dword || BuiltinID == AArch64::BI__writex18qword) { + // Process the args first + Value *OffsetArg = EmitScalarExpr(E->getArg(0)); + Value *DataArg = EmitScalarExpr(E->getArg(1)); + // 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); + Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty); Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset); - Value *Val = EmitScalarExpr(E->getArg(1)); - StoreInst *Store = Builder.CreateAlignedStore(Val, Ptr, CharUnits::One()); + StoreInst *Store = + Builder.CreateAlignedStore(DataArg, Ptr, CharUnits::One()); return Store; } @@ -11842,25 +11852,74 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, BuiltinID == AArch64::BI__readx18word || BuiltinID == AArch64::BI__readx18dword || BuiltinID == AArch64::BI__readx18qword) { - llvm::Type *IntTy = ConvertType(E->getType()); + // Process the args first + Value *OffsetArg = EmitScalarExpr(E->getArg(0)); // 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 *Offset = Builder.CreateZExt(OffsetArg, 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; + } + // Process the args first + Value *OffsetArg = EmitScalarExpr(E->getArg(0)); + Value *ValToAdd = + isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1)); + + // Read x18 as i8* + llvm::Value *X18 = readX18AsPtr(*this); + + // Load x18 + offset + Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty); + Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset); + LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One()); + + // Add values + 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 || BuiltinID == AArch64::BI_CopyFloatFromInt32 || BuiltinID == AArch64::BI_CopyInt32FromFloat || diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 6308c865ca913..9e89ae31187d1 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 7953618d2f9d1..74c6f2f79e632 100644 --- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -164,12 +164,12 @@ void check__writex18byte(unsigned LONG offset, unsigned char data) { // 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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1 // 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: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1 // CHECK-MSCOMPAT: store i8 %[[DATA]], ptr %[[PTR]], align 1 #ifdef __LP64__ @@ -184,12 +184,12 @@ void check__writex18word(unsigned LONG offset, unsigned short data) { // 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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2 // 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: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2 // CHECK-MSCOMPAT: store i16 %[[DATA]], ptr %[[PTR]], align 1 #ifdef __LP64__ @@ -204,12 +204,12 @@ void check__writex18dword(unsigned LONG offset, unsigned LONG data) { // 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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i32, ptr %[[DATA_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: %[[DATA:.*]] = load i32, ptr %[[DATA_ADDR]], align 4 // CHECK-MSCOMPAT: store i32 %[[DATA]], ptr %[[PTR]], align 1 #ifdef __LP64__ @@ -224,12 +224,12 @@ void check__writex18qword(unsigned LONG offset, unsigned __int64 data) { // 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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8 // 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: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8 // CHECK-MSCOMPAT: store i64 %[[DATA]], ptr %[[PTR]], align 1 unsigned char check__readx18byte(unsigned LONG offset) { @@ -238,9 +238,9 @@ unsigned char check__readx18byte(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, 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: %[[RETVAL:.*]] = load i8, ptr %[[PTR]], align 1 @@ -252,9 +252,9 @@ unsigned short check__readx18word(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, 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: %[[RETVAL:.*]] = load i16, ptr %[[PTR]], align 1 @@ -266,9 +266,9 @@ unsigned LONG check__readx18dword(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, 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: %[[RETVAL:.*]] = load i32, ptr %[[PTR]], align 1 @@ -280,14 +280,162 @@ unsigned __int64 check__readx18qword(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, 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: %[[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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// 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]], %[[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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// 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]], %[[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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i32, ptr %[[DATA_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: %[[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]], %[[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: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// 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]], %[[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: %[[OFFSET:.*]] = load i32, 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: %[[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: %[[OFFSET:.*]] = load i32, 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: %[[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: %[[OFFSET:.*]] = load i32, 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: %[[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: %[[OFFSET:.*]] = load i32, 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: %[[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); }