diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -257,7 +257,7 @@ BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc") BUILTIN(__builtin_fmaxf128, "LLdLLdLLd", "Fnc") BUILTIN(__builtin_fmin, "ddd", "Fnc") -BUILTIN(__builtin_fminf, "fff", "Fnc") +BUILTIN(__builtin_fminf, "v.", "t") BUILTIN(__builtin_fminf16, "hhh", "Fnc") BUILTIN(__builtin_fminl, "LdLdLd", "Fnc") BUILTIN(__builtin_fminf128, "LLdLLdLLd", "Fnc") diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12643,6 +12643,10 @@ bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc); + ExprResult SemaBuiltinOverloadedMathBuiltin(CallExpr *TheCall, + ExprResult CallResult, + QualType ElementType); + // Matrix builtin handling. ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall, ExprResult CallResult); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1976,6 +1976,10 @@ break; } + case Builtin::BI__builtin_fminf: + return SemaBuiltinOverloadedMathBuiltin(TheCall, TheCallResult, + Context.FloatTy); + case Builtin::BI__builtin_matrix_transpose: return SemaBuiltinMatrixTranspose(TheCall, TheCallResult); @@ -16525,6 +16529,52 @@ _2, _3, _4)); } +ExprResult Sema::SemaBuiltinOverloadedMathBuiltin(CallExpr *TheCall, + ExprResult CallResult, + QualType ElementType) { + if (checkArgCount(*this, TheCall, 2)) + return ExprError(); + + // Apply default Lvalue conversions and convert the expression to size_t. + auto ApplyArgumentConversions = [this](Expr *E, QualType T) { + ExprResult Res(E); + AssignConvertType LHSConvTy = CheckSingleAssignmentConstraints(T, Res); + if (DiagnoseAssignmentResult(LHSConvTy, E->getBeginLoc(), T, E->getType(), + E, AA_Passing)) + return ExprError(); + + ExprResult Conv = DefaultLvalueConversion(E); + assert( + !Conv.isInvalid() && + "conversion should be possible according to DiagnoseAssignmentResult"); + + return tryConvertExprToType(Conv.get(), T); + }; + + if (auto *VecType = ElementType->getAs()) + ElementType = VecType->getElementType(); + + QualType ArgTy = ElementType; + if (auto *VecType = TheCall->getArg(0)->getType()->getAs()) { + ArgTy = Context.getExtVectorType(ElementType, VecType->getNumElements()); + } + + ExprResult A = ApplyArgumentConversions(TheCall->getArg(0), ArgTy); + if (A.isInvalid()) + return A; + + ExprResult B = ApplyArgumentConversions(TheCall->getArg(1), ArgTy); + if (B.isInvalid()) + return B; + + TheCall->setType(ArgTy); + auto *D = TheCall->getCalleeDecl(); + D->addAttr(ConstAttr::CreateImplicit(Context, D->getLocation())); + TheCall->setArg(0, A.get()); + TheCall->setArg(1, B.get()); + return CallResult; +} + ExprResult Sema::SemaBuiltinMatrixTranspose(CallExpr *TheCall, ExprResult CallResult) { if (checkArgCount(*this, TheCall, 1)) diff --git a/clang/test/CodeGen/overloaded-math-builtins.c b/clang/test/CodeGen/overloaded-math-builtins.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/overloaded-math-builtins.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple=x86_64-apple-darwin -S -o - -emit-llvm %s | FileCheck %s + +typedef float float4 __attribute__((ext_vector_type(4))); + +void foo(float f, double d, float4 v) { + // CHECK: call float @llvm.minnum.f32(float {{.*}}, float {{.*}}) + f = __builtin_fminf(f, f); + + // CHECK: [[CONV1:%.*]] = fptrunc double {{.*}} to float + // CHECK: [[CONV2:%.*]] = fptrunc double {{.*}} to float + // CHECK: call float @llvm.minnum.f32(float [[CONV1]], float [[CONV2]]) + f = __builtin_fminf(d, d); + + // CHECK: call <4 x float> @llvm.minnum.v4f32(<4 x float> {{.*}}, <4 x float> {{.*}}) + v = __builtin_fminf(v, v); +}; diff --git a/clang/test/Sema/overloaded-math-builtins.c b/clang/test/Sema/overloaded-math-builtins.c --- a/clang/test/Sema/overloaded-math-builtins.c +++ b/clang/test/Sema/overloaded-math-builtins.c @@ -8,7 +8,7 @@ float r2 = __builtin_fminf(ptr, f); // expected-error@-1 {{passing 'int *' to parameter of incompatible type 'float'}} float r3 = __builtin_fminf(v, f); - // expected-error@-1 {{passing 'float4' (vector of 4 'float' values) to parameter of incompatible type 'float'}} + // expected-error@-1 {{initializing 'float' with an expression of incompatible type 'float __attribute__((ext_vector_type(4)))' (vector of 4 'float' values)}} float r4 = __builtin_fminf(f, v); // expected-error@-1 {{passing 'float4' (vector of 4 'float' values) to parameter of incompatible type 'float'}}