From 84df12375cdec370fd09a99e3de2e788351ff403 Mon Sep 17 00:00:00 2001 From: Michael Zolotukhin Date: Tue, 8 Sep 2015 23:52:33 +0000 Subject: Introduce __builtin_nontemporal_store and __builtin_nontemporal_load. Summary: Currently clang provides no general way to generate nontemporal loads/stores. There are some architecture specific builtins for doing so (e.g. in x86), but there is no way to generate non-temporal store on, e.g. AArch64. This patch adds generic builtins which are expanded to a simple store with '!nontemporal' attribute in IR. Differential Revision: http://reviews.llvm.org/D12313 llvm-svn: 247104 --- clang/lib/Sema/SemaChecking.cpp | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'clang/lib/Sema/SemaChecking.cpp') diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 92c94560d57..c6a00b1dad1 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -441,6 +441,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__sync_swap_8: case Builtin::BI__sync_swap_16: return SemaBuiltinAtomicOverloaded(TheCallResult); + case Builtin::BI__builtin_nontemporal_load: + case Builtin::BI__builtin_nontemporal_store: + return SemaBuiltinNontemporalOverloaded(TheCallResult); #define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case Builtin::BI##ID: \ @@ -2210,6 +2213,78 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { return TheCallResult; } +/// SemaBuiltinNontemporalOverloaded - We have a call to +/// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an +/// overloaded function based on the pointer type of its last argument. +/// +/// This function goes through and does final semantic checking for these +/// builtins. +ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) { + CallExpr *TheCall = (CallExpr *)TheCallResult.get(); + DeclRefExpr *DRE = + cast(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast(DRE->getDecl()); + unsigned BuiltinID = FDecl->getBuiltinID(); + assert((BuiltinID == Builtin::BI__builtin_nontemporal_store || + BuiltinID == Builtin::BI__builtin_nontemporal_load) && + "Unexpected nontemporal load/store builtin!"); + bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store; + unsigned numArgs = isStore ? 2 : 1; + + // Ensure that we have the proper number of arguments. + if (checkArgCount(*this, TheCall, numArgs)) + return ExprError(); + + // Inspect the last argument of the nontemporal builtin. This should always + // be a pointer type, from which we imply the type of the memory access. + // Because it is a pointer type, we don't have to worry about any implicit + // casts here. + Expr *PointerArg = TheCall->getArg(numArgs - 1); + ExprResult PointerArgResult = + DefaultFunctionArrayLvalueConversion(PointerArg); + + if (PointerArgResult.isInvalid()) + return ExprError(); + PointerArg = PointerArgResult.get(); + TheCall->setArg(numArgs - 1, PointerArg); + + const PointerType *pointerType = PointerArg->getType()->getAs(); + if (!pointerType) { + Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer) + << PointerArg->getType() << PointerArg->getSourceRange(); + return ExprError(); + } + + QualType ValType = pointerType->getPointeeType(); + + // Strip any qualifiers off ValType. + ValType = ValType.getUnqualifiedType(); + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType() && !ValType->isFloatingType() && + !ValType->isVectorType()) { + Diag(DRE->getLocStart(), + diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) + << PointerArg->getType() << PointerArg->getSourceRange(); + return ExprError(); + } + + if (!isStore) { + TheCall->setType(ValType); + return TheCallResult; + } + + ExprResult ValArg = TheCall->getArg(0); + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, ValType, /*consume*/ false); + ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg); + if (ValArg.isInvalid()) + return ExprError(); + + TheCall->setArg(0, ValArg.get()); + TheCall->setType(Context.VoidTy); + return TheCallResult; +} + /// CheckObjCString - Checks that the argument to the builtin /// CFString constructor is correct /// Note: It might also make sense to do the UTF-16 conversion here (would -- cgit v1.2.3