diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2022-12-07 22:49:27 -0500 |
---|---|---|
committer | Matt Arsenault <arsenm2@gmail.com> | 2023-02-24 21:55:08 -0400 |
commit | 8709bcacfb3a06847b47bb6b47e8556db43f3a43 (patch) | |
tree | 4b861499828d3ce9b4225b473ed376c9254624b0 /clang/lib/Sema/SemaChecking.cpp | |
parent | 5cf549e6b1a572f5be5a575ffb878bb927ba81b3 (diff) | |
download | llvm-8709bcacfb3a06847b47bb6b47e8556db43f3a43.zip llvm-8709bcacfb3a06847b47bb6b47e8556db43f3a43.tar.gz llvm-8709bcacfb3a06847b47bb6b47e8556db43f3a43.tar.bz2 |
clang: Add __builtin_elementwise_fma
I didn't understand why the other builtins have promotion logic,
or how it would apply for a ternary operation. Implicit conversions
are evil to begin with, and even more so when the purpose is to get
an exact IR intrinsic. This checks all the arguments have the same type.
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index eded606..485351f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2626,20 +2626,16 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); QualType ArgTy = TheCall->getArg(0)->getType(); - QualType EltTy = ArgTy; - - if (auto *VecTy = EltTy->getAs<VectorType>()) - EltTy = VecTy->getElementType(); - if (!EltTy->isFloatingType()) { - Diag(TheCall->getArg(0)->getBeginLoc(), - diag::err_builtin_invalid_arg_type) - << 1 << /* float ty*/ 5 << ArgTy; - + if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(), + ArgTy, 1)) + return ExprError(); + break; + } + case Builtin::BI__builtin_elementwise_fma: { + if (SemaBuiltinElementwiseTernaryMath(TheCall)) return ExprError(); - } break; } - // These builtins restrict the element type to integer // types only. case Builtin::BI__builtin_elementwise_add_sat: @@ -17877,6 +17873,40 @@ bool Sema::SemaBuiltinElementwiseMath(CallExpr *TheCall) { return false; } +bool Sema::SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall) { + if (checkArgCount(*this, TheCall, 3)) + return true; + + Expr *Args[3]; + for (int I = 0; I < 3; ++I) { + ExprResult Converted = UsualUnaryConversions(TheCall->getArg(I)); + if (Converted.isInvalid()) + return true; + Args[I] = Converted.get(); + } + + int ArgOrdinal = 1; + for (Expr *Arg : Args) { + if (checkFPMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(), + ArgOrdinal++)) + return true; + } + + for (int I = 1; I < 3; ++I) { + if (Args[0]->getType().getCanonicalType() != + Args[I]->getType().getCanonicalType()) { + return Diag(Args[0]->getBeginLoc(), + diag::err_typecheck_call_different_arg_types) + << Args[0]->getType() << Args[I]->getType(); + } + + TheCall->setArg(I, Args[I]); + } + + TheCall->setType(Args[0]->getType()); + return false; +} + bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall) { if (checkArgCount(*this, TheCall, 1)) return true; |