Skip to content

[aarch64] Add support for the __{inc|add}x18{byte|word|dword|qword intrinsics #117752

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

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/BuiltinsAArch64.def
Original file line number Diff line number Diff line change
Expand Up @@ -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, "")
Expand Down
101 changes: 80 additions & 21 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -11820,47 +11833,93 @@ 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;
}

if (BuiltinID == AArch64::BI__readx18byte ||
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 ||
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Headers/intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading
Loading