[PATCH] D12313: Introduce __builtin_nontemporal_store and __builtin_nontemporal_load.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 26 15:46:58 PDT 2015
rsmith added inline comments.
================
Comment at: include/clang/Basic/Builtins.def:1249-1255
@@ +1248,9 @@
+BUILTIN(__builtin_nontemporal_store, "v.", "t")
+BUILTIN(__builtin_nontemporal_store_1, "vcc*.", "")
+BUILTIN(__builtin_nontemporal_store_2, "vss*.", "")
+BUILTIN(__builtin_nontemporal_store_4, "vii*.", "")
+BUILTIN(__builtin_nontemporal_store_8, "vLLiLLi*.", "")
+BUILTIN(__builtin_nontemporal_store_16, "vLLLiLLLi*.", "")
+BUILTIN(__builtin_nontemporal_store_f, "vff*.", "")
+BUILTIN(__builtin_nontemporal_store_d, "vdd*.", "")
+
----------------
Do we need these typed versions?
================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:6198-6203
@@ +6197,8 @@
+ "address argument to nontemporal builtin must be a pointer (%0 invalid)">;
+def err_nontemporal_builtin_must_be_pointer_intfltptr : Error<
+ "address argument to nontemporal builtin must be a pointer to integer, float "
+ "or pointer (%0 invalid)">;
+def err_nontemporal_builtin_pointer_size : Error<
+ "address argument to nontemporal builtin must be a pointer to 1,2,4,8 or 16 "
+ "byte type (%0 invalid)">;
+
----------------
Nontemporal loads and stores of, say, vector types seem useful, but I can understand if you want to restrict the complexity of the CodeGen changes here.
================
Comment at: lib/CodeGen/CGBuiltin.cpp:128-129
@@ +127,4 @@
+ // Convert the type of the pointer to a pointer to the stored type.
+ Value *BC = CGF.Builder.CreateBitCast(
+ Address, llvm::PointerType::getUnqual(ValueTy), "cast");
+ StoreInst *SI = CGF.Builder.CreateStore(Val, BC);
----------------
You should pass `Val` through `EmitToMemory` first to widen `bool` from `i1` to `i8`.
================
Comment at: lib/CodeGen/CGBuiltin.cpp:149
@@ +148,3 @@
+ LI->setAlignment(Align);
+ return LI;
+}
----------------
Likewise, you should pass this though `EmitFromMemory`.
================
Comment at: lib/Sema/SemaChecking.cpp:2235-2241
@@ +2234,9 @@
+
+ // Ensure that we have at least one argument to do type inference from.
+ if (TheCall->getNumArgs() < numArgs) {
+ Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return ExprError();
+ }
+
----------------
You should also reject calls with too many arguments here. Maybe just call `checkArgCount(*this, TheCall, numArgs)`?
================
Comment at: lib/Sema/SemaChecking.cpp:2275-2357
@@ +2274,85 @@
+
+#define BUILTIN_ROW(x) \
+ { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
+ Builtin::BI##x##_8, Builtin::BI##x##_16, \
+ Builtin::BI##x##_f, Builtin::BI##x##_d }
+
+ static const unsigned BuiltinIndices[][7] = {
+ BUILTIN_ROW(__builtin_nontemporal_store),
+ BUILTIN_ROW(__builtin_nontemporal_load)
+ };
+#undef BUILTIN_ROW
+
+ // Determine the index of the size.
+ unsigned SizeIndex;
+ if (ValType->isFloatingType()) {
+ switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
+ case 4: SizeIndex = 5; break;
+ case 8: SizeIndex = 6; break;
+ default:
+ Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_pointer_size)
+ << AddressArg->getType() << AddressArg->getSourceRange();
+ return ExprError();
+ }
+ } else {
+ switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
+ case 1: SizeIndex = 0; break;
+ case 2: SizeIndex = 1; break;
+ case 4: SizeIndex = 2; break;
+ case 8: SizeIndex = 3; break;
+ case 16: SizeIndex = 4; break;
+ default:
+ Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_pointer_size)
+ << AddressArg->getType() << AddressArg->getSourceRange();
+ return ExprError();
+ }
+ }
+ // Get the decl for the concrete builtin from this, we can tell what the
+ // concrete integer type we should convert to is.
+ unsigned NewBuiltinID = BuiltinIndices[isStore ? 0 : 1][SizeIndex];
+ const char *NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID);
+
+ // Perform builtin lookup to avoid redeclaring it.
+ DeclarationName DN(&Context.Idents.get(NewBuiltinName));
+ LookupResult Res(*this, DN, DRE->getLocStart(), LookupOrdinaryName);
+ LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true);
+ assert(Res.getFoundDecl());
+ FunctionDecl *NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
+ if (!NewBuiltinDecl)
+ return ExprError();
+
+ // For stores convert the value (the first argument) to the type of the
+ // pointer (the second argument).
+ if (isStore) {
+ ExprResult Arg = TheCall->getArg(0);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, ValType, /*consume*/ false);
+ Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return ExprError();
+
+ TheCall->setArg(0, Arg.get());
+ }
+
+ ASTContext &Context = this->getASTContext();
+
+ // Create a new DeclRefExpr to refer to the new decl.
+ DeclRefExpr *NewDRE = DeclRefExpr::Create(
+ Context, DRE->getQualifierLoc(), SourceLocation(), NewBuiltinDecl,
+ /*enclosing*/ false, DRE->getLocation(), Context.BuiltinFnTy,
+ DRE->getValueKind());
+
+ // Set the callee in the CallExpr.
+ // FIXME: This loses syntactic information.
+ QualType CalleePtrTy = Context.getPointerType(NewBuiltinDecl->getType());
+ ExprResult PromotedCall =
+ ImpCastExprToType(NewDRE, CalleePtrTy, CK_BuiltinFnToFnPtr);
+ TheCall->setCallee(PromotedCall.get());
+
+ // For loads change the result type of the call to match the original value
+ // type. This is arbitrary, but the codegen for these builtins ins design to
+ // handle it gracefully.
+ if (!isStore)
+ TheCall->setType(ValType);
+
+ return TheCallResult;
----------------
Instead of doing all of this, you can just (for stores) check the type of the second parameter or (for loads) set the type of the call expression. (See `CheckARMBuiltinExclusiveCall` for an example.)
http://reviews.llvm.org/D12313
More information about the cfe-commits
mailing list