summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGBuiltin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp71
1 files changed, 51 insertions, 20 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index d9cc37d123fb..172a521e63c1 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -997,9 +997,8 @@ static const FieldDecl *FindFlexibleArrayMemberField(CodeGenFunction &CGF,
/*IgnoreTemplateOrMacroSubstitution=*/true))
return FD;
- if (auto RT = FD->getType()->getAs<RecordType>())
- if (const FieldDecl *FD =
- FindFlexibleArrayMemberField(CGF, Ctx, RT->getAsRecordDecl()))
+ if (const auto *RD = FD->getType()->getAsRecordDecl())
+ if (const FieldDecl *FD = FindFlexibleArrayMemberField(CGF, Ctx, RD))
return FD;
}
@@ -1025,8 +1024,8 @@ static bool GetFieldOffset(ASTContext &Ctx, const RecordDecl *RD,
return true;
}
- if (auto RT = Field->getType()->getAs<RecordType>()) {
- if (GetFieldOffset(Ctx, RT->getAsRecordDecl(), FD, Offset)) {
+ if (const auto *RD = Field->getType()->getAsRecordDecl()) {
+ if (GetFieldOffset(Ctx, RD, FD, Offset)) {
Offset += Layout.getFieldOffset(FieldNo);
return true;
}
@@ -1693,6 +1692,23 @@ getBitTestAtomicOrdering(BitTest::InterlockingKind I) {
llvm_unreachable("invalid interlocking");
}
+static llvm::Value *EmitBitCountExpr(CodeGenFunction &CGF, const Expr *E) {
+ llvm::Value *ArgValue = CGF.EmitScalarExpr(E);
+ llvm::Type *ArgType = ArgValue->getType();
+
+ // Boolean vectors can be casted directly to its bitfield representation. We
+ // intentionally do not round up to the next power of two size and let LLVM
+ // handle the trailing bits.
+ if (auto *VT = dyn_cast<llvm::FixedVectorType>(ArgType);
+ VT && VT->getElementType()->isIntegerTy(1)) {
+ llvm::Type *StorageType =
+ llvm::Type::getIntNTy(CGF.getLLVMContext(), VT->getNumElements());
+ ArgValue = CGF.Builder.CreateBitCast(ArgValue, StorageType);
+ }
+
+ return ArgValue;
+}
+
/// Emit a _bittest* intrinsic. These intrinsics take a pointer to an array of
/// bits and a bit position and read and optionally modify the bit at that
/// position. The position index can be arbitrarily large, i.e. it can be larger
@@ -2020,7 +2036,7 @@ Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E,
assert((Kind == BCK_CLZPassedZero || Kind == BCK_CTZPassedZero) &&
"Unsupported builtin check kind");
- Value *ArgValue = EmitScalarExpr(E);
+ Value *ArgValue = EmitBitCountExpr(*this, E);
if (!SanOpts.has(SanitizerKind::Builtin))
return ArgValue;
@@ -3334,7 +3350,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
E->getNumArgs() > 1;
Value *ArgValue =
- HasFallback ? EmitScalarExpr(E->getArg(0))
+ HasFallback ? EmitBitCountExpr(*this, E->getArg(0))
: EmitCheckedArgForBuiltin(E->getArg(0), BCK_CTZPassedZero);
llvm::Type *ArgType = ArgValue->getType();
@@ -3371,7 +3387,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
E->getNumArgs() > 1;
Value *ArgValue =
- HasFallback ? EmitScalarExpr(E->getArg(0))
+ HasFallback ? EmitBitCountExpr(*this, E->getArg(0))
: EmitCheckedArgForBuiltin(E->getArg(0), BCK_CLZPassedZero);
llvm::Type *ArgType = ArgValue->getType();
@@ -3456,7 +3472,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_popcountl:
case Builtin::BI__builtin_popcountll:
case Builtin::BI__builtin_popcountg: {
- Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ Value *ArgValue = EmitBitCountExpr(*this, E->getArg(0));
llvm::Type *ArgType = ArgValue->getType();
Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
@@ -4255,7 +4271,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Result);
}
- case Builtin::BI__builtin_masked_load: {
+ case Builtin::BI__builtin_masked_load:
+ case Builtin::BI__builtin_masked_expand_load: {
llvm::Value *Mask = EmitScalarExpr(E->getArg(0));
llvm::Value *Ptr = EmitScalarExpr(E->getArg(1));
@@ -4265,15 +4282,24 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::ConstantInt::get(Int32Ty, Align.getQuantity());
llvm::Value *PassThru = llvm::PoisonValue::get(RetTy);
+ if (E->getNumArgs() > 2)
+ PassThru = EmitScalarExpr(E->getArg(2));
- Function *F =
- CGM.getIntrinsic(Intrinsic::masked_load, {RetTy, UnqualPtrTy});
-
- llvm::Value *Result =
- Builder.CreateCall(F, {Ptr, AlignVal, Mask, PassThru}, "masked_load");
+ llvm::Value *Result;
+ if (BuiltinID == Builtin::BI__builtin_masked_load) {
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::masked_load, {RetTy, UnqualPtrTy});
+ Result =
+ Builder.CreateCall(F, {Ptr, AlignVal, Mask, PassThru}, "masked_load");
+ } else {
+ Function *F = CGM.getIntrinsic(Intrinsic::masked_expandload, {RetTy});
+ Result =
+ Builder.CreateCall(F, {Ptr, Mask, PassThru}, "masked_expand_load");
+ }
return RValue::get(Result);
};
- case Builtin::BI__builtin_masked_store: {
+ case Builtin::BI__builtin_masked_store:
+ case Builtin::BI__builtin_masked_compress_store: {
llvm::Value *Mask = EmitScalarExpr(E->getArg(0));
llvm::Value *Val = EmitScalarExpr(E->getArg(1));
llvm::Value *Ptr = EmitScalarExpr(E->getArg(2));
@@ -4286,10 +4312,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *AlignVal =
llvm::ConstantInt::get(Int32Ty, Align.getQuantity());
- llvm::Function *F =
- CGM.getIntrinsic(llvm::Intrinsic::masked_store, {ValLLTy, PtrTy});
-
- Builder.CreateCall(F, {Val, Ptr, AlignVal, Mask});
+ if (BuiltinID == Builtin::BI__builtin_masked_store) {
+ llvm::Function *F =
+ CGM.getIntrinsic(llvm::Intrinsic::masked_store, {ValLLTy, PtrTy});
+ Builder.CreateCall(F, {Val, Ptr, AlignVal, Mask});
+ } else {
+ llvm::Function *F =
+ CGM.getIntrinsic(llvm::Intrinsic::masked_compressstore, {ValLLTy});
+ Builder.CreateCall(F, {Val, Ptr, Mask});
+ }
return RValue::get(nullptr);
}