Skip to content

Commit acbd813

Browse files
committed
[AArch64] Add support for the __{inc|add}x18{byte|word|dword|qword intrinsics
1 parent b0ca543 commit acbd813

File tree

4 files changed

+260
-33
lines changed

4 files changed

+260
-33
lines changed

clang/include/clang/Basic/BuiltinsAArch64.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,16 @@ TARGET_HEADER_BUILTIN(__readx18word, "UsUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES,
281281
TARGET_HEADER_BUILTIN(__readx18dword, "UNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
282282
TARGET_HEADER_BUILTIN(__readx18qword, "ULLiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
283283

284+
TARGET_HEADER_BUILTIN(__addx18byte, "vUNiUc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
285+
TARGET_HEADER_BUILTIN(__addx18word, "vUNiUs", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
286+
TARGET_HEADER_BUILTIN(__addx18dword, "vUNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
287+
TARGET_HEADER_BUILTIN(__addx18qword, "vUNiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
288+
289+
TARGET_HEADER_BUILTIN(__incx18byte, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
290+
TARGET_HEADER_BUILTIN(__incx18word, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
291+
TARGET_HEADER_BUILTIN(__incx18dword, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
292+
TARGET_HEADER_BUILTIN(__incx18qword, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
293+
284294
TARGET_HEADER_BUILTIN(_CopyDoubleFromInt64, "dSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
285295
TARGET_HEADER_BUILTIN(_CopyFloatFromInt32, "fSi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
286296
TARGET_HEADER_BUILTIN(_CopyInt32FromFloat, "Sif", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,19 @@ static Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) {
244244
return CGF.Builder.CreateBitCast(BitVec, ResultType);
245245
}
246246

247+
/// Helper for the read/write/add/inc X18 builtins: read the X18 register and
248+
/// return it as an i8 pointer.
249+
Value *readX18AsPtr(CodeGenFunction &CGF) {
250+
LLVMContext &Context = CGF.CGM.getLLVMContext();
251+
llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
252+
llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
253+
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
254+
llvm::Function *F =
255+
CGF.CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF.Int64Ty});
256+
llvm::Value *X18 = CGF.Builder.CreateCall(F, Metadata);
257+
return CGF.Builder.CreateIntToPtr(X18, CGF.Int8PtrTy);
258+
}
259+
247260
/// getBuiltinLibFunction - Given a builtin id for a function like
248261
/// "__builtin_fabsf", return a Function* for "fabsf".
249262
llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
@@ -11820,47 +11833,93 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
1182011833
BuiltinID == AArch64::BI__writex18word ||
1182111834
BuiltinID == AArch64::BI__writex18dword ||
1182211835
BuiltinID == AArch64::BI__writex18qword) {
11836+
// Process the args first
11837+
Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11838+
Value *DataArg = EmitScalarExpr(E->getArg(1));
11839+
1182311840
// Read x18 as i8*
11824-
LLVMContext &Context = CGM.getLLVMContext();
11825-
llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
11826-
llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
11827-
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
11828-
llvm::Function *F =
11829-
CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
11830-
llvm::Value *X18 = Builder.CreateCall(F, Metadata);
11831-
X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
11841+
llvm::Value *X18 = readX18AsPtr(*this);
1183211842

1183311843
// Store val at x18 + offset
11834-
Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty);
11844+
Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
1183511845
Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11836-
Value *Val = EmitScalarExpr(E->getArg(1));
11837-
StoreInst *Store = Builder.CreateAlignedStore(Val, Ptr, CharUnits::One());
11846+
StoreInst *Store =
11847+
Builder.CreateAlignedStore(DataArg, Ptr, CharUnits::One());
1183811848
return Store;
1183911849
}
1184011850

1184111851
if (BuiltinID == AArch64::BI__readx18byte ||
1184211852
BuiltinID == AArch64::BI__readx18word ||
1184311853
BuiltinID == AArch64::BI__readx18dword ||
1184411854
BuiltinID == AArch64::BI__readx18qword) {
11845-
llvm::Type *IntTy = ConvertType(E->getType());
11855+
// Process the args first
11856+
Value *OffsetArg = EmitScalarExpr(E->getArg(0));
1184611857

1184711858
// Read x18 as i8*
11848-
LLVMContext &Context = CGM.getLLVMContext();
11849-
llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
11850-
llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
11851-
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
11852-
llvm::Function *F =
11853-
CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
11854-
llvm::Value *X18 = Builder.CreateCall(F, Metadata);
11855-
X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
11859+
llvm::Value *X18 = readX18AsPtr(*this);
1185611860

1185711861
// Load x18 + offset
11858-
Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty);
11862+
Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
1185911863
Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11864+
llvm::Type *IntTy = ConvertType(E->getType());
1186011865
LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
1186111866
return Load;
1186211867
}
1186311868

11869+
if (BuiltinID == AArch64::BI__addx18byte ||
11870+
BuiltinID == AArch64::BI__addx18word ||
11871+
BuiltinID == AArch64::BI__addx18dword ||
11872+
BuiltinID == AArch64::BI__addx18qword ||
11873+
BuiltinID == AArch64::BI__incx18byte ||
11874+
BuiltinID == AArch64::BI__incx18word ||
11875+
BuiltinID == AArch64::BI__incx18dword ||
11876+
BuiltinID == AArch64::BI__incx18qword) {
11877+
llvm::Type *IntTy;
11878+
bool isIncrement;
11879+
switch (BuiltinID) {
11880+
case AArch64::BI__incx18byte:
11881+
IntTy = Int8Ty;
11882+
isIncrement = true;
11883+
break;
11884+
case AArch64::BI__incx18word:
11885+
IntTy = Int16Ty;
11886+
isIncrement = true;
11887+
break;
11888+
case AArch64::BI__incx18dword:
11889+
IntTy = Int32Ty;
11890+
isIncrement = true;
11891+
break;
11892+
case AArch64::BI__incx18qword:
11893+
IntTy = Int64Ty;
11894+
isIncrement = true;
11895+
break;
11896+
default:
11897+
IntTy = ConvertType(E->getArg(1)->getType());
11898+
isIncrement = false;
11899+
break;
11900+
}
11901+
// Process the args first
11902+
Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11903+
Value *ValToAdd =
11904+
isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1));
11905+
11906+
// Read x18 as i8*
11907+
llvm::Value *X18 = readX18AsPtr(*this);
11908+
11909+
// Load x18 + offset
11910+
Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
11911+
Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11912+
LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
11913+
11914+
// Add values
11915+
Value *AddResult = Builder.CreateAdd(Load, ValToAdd);
11916+
11917+
// Store val at x18 + offset
11918+
StoreInst *Store =
11919+
Builder.CreateAlignedStore(AddResult, Ptr, CharUnits::One());
11920+
return Store;
11921+
}
11922+
1186411923
if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
1186511924
BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
1186611925
BuiltinID == AArch64::BI_CopyInt32FromFloat ||

clang/lib/Headers/intrin.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,16 @@ unsigned short __readx18word(unsigned long offset);
396396
unsigned long __readx18dword(unsigned long offset);
397397
unsigned __int64 __readx18qword(unsigned long offset);
398398

399+
void __addx18byte(unsigned long offset, unsigned char data);
400+
void __addx18word(unsigned long offset, unsigned short data);
401+
void __addx18dword(unsigned long offset, unsigned long data);
402+
void __addx18qword(unsigned long offset, unsigned __int64 data);
403+
404+
void __incx18byte(unsigned long offset);
405+
void __incx18word(unsigned long offset);
406+
void __incx18dword(unsigned long offset);
407+
void __incx18qword(unsigned long offset);
408+
399409
double _CopyDoubleFromInt64(__int64);
400410
float _CopyFloatFromInt32(__int32);
401411
__int32 _CopyInt32FromFloat(float);

0 commit comments

Comments
 (0)