From b6a635d5b726c0bf441c8f09cda7bd5acf411fda Mon Sep 17 00:00:00 2001 From: Sirui Mu Date: Fri, 12 Jul 2024 05:53:40 +0800 Subject: [PATCH] [CIR][Fix] FP builtins should lower directly to LLVM builtins (#670) LLVM lowering for the following operations is introduced in #616 and #651: `cos`, `exp`, `exp2`, `log`, `log10`, `log2`, `sin`, `sqrt`, `fmod`, and `pow`. However, they are not lowered to their corresponding LLVM intrinsics; instead they are transformed to libc calls during lowering prepare. This does not match the upstream behavior. This PR tries to correct this mistake. It makes all CIR FP intrinsic ops lower to their corresponding LLVM intrinsics (`fmod` is a special case and it is lowered to the `frem` LLVM instruction). --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 20 +++ .../Dialect/Transforms/LoweringPrepare.cpp | 71 ----------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 46 ++++++- .../test/CIR/CodeGen/builtin-floating-point.c | 120 +++++++++--------- .../test/CIR/Lowering/builtin-binary-fp2fp.c | 64 +++++++++- 5 files changed, 184 insertions(+), 137 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 5b76c9b84e57..3919050ae4fc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -448,6 +448,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_cosf16: case Builtin::BI__builtin_cosl: case Builtin::BI__builtin_cosf128: + assert(getContext().getLangOpts().FastMath && + "cir.cos is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BIexp: @@ -458,6 +460,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_expf16: case Builtin::BI__builtin_expl: case Builtin::BI__builtin_expf128: + assert(getContext().getLangOpts().FastMath && + "cir.exp is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BIexp2: @@ -468,6 +472,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_exp2f16: case Builtin::BI__builtin_exp2l: case Builtin::BI__builtin_exp2f128: + assert(getContext().getLangOpts().FastMath && + "cir.exp2 is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BIfabs: @@ -534,6 +540,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_fmod: case Builtin::BI__builtin_fmodf: case Builtin::BI__builtin_fmodl: + assert(getContext().getLangOpts().FastMath && + "cir.fmod is only expected under -ffast-math"); return buildBinaryFPBuiltin(*this, *E); case Builtin::BI__builtin_fmodf16: @@ -548,6 +556,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_logf16: case Builtin::BI__builtin_logl: case Builtin::BI__builtin_logf128: + assert(getContext().getLangOpts().FastMath && + "cir.log is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BIlog10: @@ -558,6 +568,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_log10f16: case Builtin::BI__builtin_log10l: case Builtin::BI__builtin_log10f128: + assert(getContext().getLangOpts().FastMath && + "cir.log10 is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BIlog2: @@ -568,6 +580,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_log2f16: case Builtin::BI__builtin_log2l: case Builtin::BI__builtin_log2f128: + assert(getContext().getLangOpts().FastMath && + "cir.log2 is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BInearbyint: @@ -585,6 +599,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_pow: case Builtin::BI__builtin_powf: case Builtin::BI__builtin_powl: + assert(getContext().getLangOpts().FastMath && + "cir.pow is only expected under -ffast-math"); return RValue::get( buildBinaryMaybeConstrainedFPBuiltin(*this, *E)); @@ -620,6 +636,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_sinf16: case Builtin::BI__builtin_sinl: case Builtin::BI__builtin_sinf128: + assert(getContext().getLangOpts().FastMath && + "cir.sin is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BIsqrt: @@ -630,6 +648,8 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_sqrtf16: case Builtin::BI__builtin_sqrtl: case Builtin::BI__builtin_sqrtf128: + assert(getContext().getLangOpts().FastMath && + "cir.sqrt is only expected under -ffast-math"); return buildUnaryFPBuiltin(*this, *E); case Builtin::BItrunc: diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 49f05d4187f3..1172c7332ce2 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -24,7 +24,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" @@ -71,7 +70,6 @@ struct LoweringPreparePass : public LoweringPrepareBase { void runOnOperation() override; void runOnOp(Operation *op); - void runOnMathOp(Operation *op); void lowerThreeWayCmpOp(CmpThreeWayOp op); void lowerVAArgOp(VAArgOp op); void lowerGlobalOp(GlobalOp op); @@ -650,69 +648,6 @@ void LoweringPreparePass::runOnOp(Operation *op) { } } -void LoweringPreparePass::runOnMathOp(Operation *op) { - struct MathOpFunctionNames { - llvm::StringRef floatVer; - llvm::StringRef doubleVer; - llvm::StringRef longDoubleVer; - }; - - mlir::Type ty = op->getResult(0).getType(); - - MathOpFunctionNames rtFuncNames = - llvm::TypeSwitch(op) - .Case([](auto) { - return MathOpFunctionNames{"fmodf", "fmod", "fmodl"}; - }) - .Case( - [](auto) { return MathOpFunctionNames{"powf", "pow", "powl"}; }) - .Case( - [](auto) { return MathOpFunctionNames{"cosf", "cos", "cosl"}; }) - .Case( - [](auto) { return MathOpFunctionNames{"expf", "exp", "expl"}; }) - .Case([](auto) { - return MathOpFunctionNames{"exp2f", "exp2", "exp2l"}; - }) - .Case( - [](auto) { return MathOpFunctionNames{"logf", "log", "logl"}; }) - .Case([](auto) { - return MathOpFunctionNames{"log10f", "log10", "log10l"}; - }) - .Case([](auto) { - return MathOpFunctionNames{"log2f", "log2", "log2l"}; - }) - .Case( - [](auto) { return MathOpFunctionNames{"sinf", "sin", "sinl"}; }) - .Case([](auto) { - return MathOpFunctionNames{"sqrtf", "sqrt", "sqrtl"}; - }); - llvm::StringRef rtFuncName = llvm::TypeSwitch(ty) - .Case([&](auto) { - return rtFuncNames.floatVer; - }) - .Case([&](auto) { - return rtFuncNames.doubleVer; - }) - .Case([&](auto) { - return rtFuncNames.longDoubleVer; - }); - - CIRBaseBuilderTy builder(*theModule.getContext()); - builder.setInsertionPointToStart(theModule.getBody()); - - llvm::SmallVector operandTypes(op->getNumOperands(), ty); - auto rtFuncTy = - mlir::cir::FuncType::get(operandTypes, op->getResult(0).getType()); - FuncOp rtFunc = - buildRuntimeFunction(builder, rtFuncName, op->getLoc(), rtFuncTy); - - builder.setInsertionPointAfter(op); - auto call = builder.createCallOp(op->getLoc(), rtFunc, op->getOperands()); - - op->replaceAllUsesWith(call); - op->erase(); -} - void LoweringPreparePass::runOnOperation() { assert(astCtx && "Missing ASTContext, please construct with the right ctor"); auto *op = getOperation(); @@ -721,22 +656,16 @@ void LoweringPreparePass::runOnOperation() { } SmallVector opsToTransform; - SmallVector mathOpsToTransform; op->walk([&](Operation *op) { if (isa( op)) opsToTransform.push_back(op); - else if (isa(op)) - mathOpsToTransform.push_back(op); }); for (auto *o : opsToTransform) runOnOp(o); - for (auto *o : mathOpsToTransform) - runOnMathOp(o); buildCXXGlobalInitFunc(); buildGlobalCtorDtorList(); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index bf63b3a66d19..fca881dba61b 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3395,10 +3395,22 @@ class CIRUnaryFPBuiltinOpLowering : public mlir::OpConversionPattern { using CIRCeilOpLowering = CIRUnaryFPBuiltinOpLowering; +using CIRCosOpLowering = + CIRUnaryFPBuiltinOpLowering; +using CIRExpOpLowering = + CIRUnaryFPBuiltinOpLowering; +using CIRExp2OpLowering = + CIRUnaryFPBuiltinOpLowering; using CIRFloorOpLowering = CIRUnaryFPBuiltinOpLowering; using CIRFabsOpLowering = CIRUnaryFPBuiltinOpLowering; +using CIRLogOpLowering = + CIRUnaryFPBuiltinOpLowering; +using CIRLog10OpLowering = + CIRUnaryFPBuiltinOpLowering; +using CIRLog2OpLowering = + CIRUnaryFPBuiltinOpLowering; using CIRNearbyintOpLowering = CIRUnaryFPBuiltinOpLowering; @@ -3406,6 +3418,10 @@ using CIRRintOpLowering = CIRUnaryFPBuiltinOpLowering; using CIRRoundOpLowering = CIRUnaryFPBuiltinOpLowering; +using CIRSinOpLowering = + CIRUnaryFPBuiltinOpLowering; +using CIRSqrtOpLowering = + CIRUnaryFPBuiltinOpLowering; using CIRTruncOpLowering = CIRUnaryFPBuiltinOpLowering; @@ -3442,6 +3458,24 @@ using CIRFMaxOpLowering = CIRBinaryFPToFPBuiltinOpLowering; using CIRFMinOpLowering = CIRBinaryFPToFPBuiltinOpLowering; +using CIRPowOpLowering = + CIRBinaryFPToFPBuiltinOpLowering; + +// cir.fmod is special. Instead of lowering it to an intrinsic call, lower it to +// the frem LLVM instruction. +class CIRFModOpLowering : public mlir::OpConversionPattern { +public: + using mlir::OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::FModOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto resTy = this->getTypeConverter()->convertType(op.getType()); + rewriter.replaceOpWithNewOp(op, resTy, adaptor.getLhs(), + adaptor.getRhs()); + return mlir::success(); + } +}; class CIRClearCacheOpLowering : public mlir::OpConversionPattern { @@ -3489,11 +3523,13 @@ void populateCIRToLLVMConversionPatterns(mlir::RewritePatternSet &patterns, CIRGetBitfieldLowering, CIRPrefetchLowering, CIRObjSizeOpLowering, CIRIsConstantOpLowering, CIRCmpThreeWayOpLowering, CIRLroundOpLowering, CIRLLroundOpLowering, CIRLrintOpLowering, CIRLLrintOpLowering, - CIRCeilOpLowering, CIRFloorOpLowering, CIRFAbsOpLowering, - CIRNearbyintOpLowering, CIRRintOpLowering, CIRRoundOpLowering, - CIRTruncOpLowering, CIRCopysignOpLowering, CIRFMaxOpLowering, - CIRFMinOpLowering, CIRClearCacheOpLowering>(converter, - patterns.getContext()); + CIRCeilOpLowering, CIRCosOpLowering, CIRExpOpLowering, CIRExp2OpLowering, + CIRFloorOpLowering, CIRFAbsOpLowering, CIRLogOpLowering, + CIRLog10OpLowering, CIRLog2OpLowering, CIRNearbyintOpLowering, + CIRRintOpLowering, CIRRoundOpLowering, CIRSinOpLowering, + CIRSqrtOpLowering, CIRTruncOpLowering, CIRCopysignOpLowering, + CIRFModOpLowering, CIRFMaxOpLowering, CIRFMinOpLowering, CIRPowOpLowering, + CIRClearCacheOpLowering>(converter, patterns.getContext()); } namespace { diff --git a/clang/test/CIR/CodeGen/builtin-floating-point.c b/clang/test/CIR/CodeGen/builtin-floating-point.c index 51e7a1a6a6ef..84bd60c06ac2 100644 --- a/clang/test/CIR/CodeGen/builtin-floating-point.c +++ b/clang/test/CIR/CodeGen/builtin-floating-point.c @@ -351,7 +351,7 @@ float my_cosf(float f) { // CHECK: {{.+}} = cir.cos {{.+}} : !cir.float // LLVM: define float @my_cosf(float %0) - // LLVM: %{{.+}} = call float @cosf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.cos.f32(float %{{.+}}) // LLVM: } } @@ -361,7 +361,7 @@ double my_cos(double f) { // CHECK: {{.+}} = cir.cos {{.+}} : !cir.double // LLVM: define double @my_cos(double %0) - // LLVM: %{{.+}} = call double @cos(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.cos.f64(double %{{.+}}) // LLVM: } } @@ -372,7 +372,7 @@ long double my_cosl(long double f) { // AARCH64: {{.+}} = cir.cos {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_cosl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @cosl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.cos.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -386,7 +386,7 @@ float call_cosf(float f) { // CHECK: {{.+}} = cir.cos {{.+}} : !cir.float // LLVM: define float @call_cosf(float %0) - // LLVM: %{{.+}} = call float @cosf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.cos.f32(float %{{.+}}) // LLVM: } } @@ -396,7 +396,7 @@ double call_cos(double f) { // CHECK: {{.+}} = cir.cos {{.+}} : !cir.double // LLVM: define double @call_cos(double %0) - // LLVM: %{{.+}} = call double @cos(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.cos.f64(double %{{.+}}) // LLVM: } } @@ -407,7 +407,7 @@ long double call_cosl(long double f) { // AARCH64: {{.+}} = cir.cos {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_cosl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @cosl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.cos.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -419,7 +419,7 @@ float my_expf(float f) { // CHECK: {{.+}} = cir.exp {{.+}} : !cir.float // LLVM: define float @my_expf(float %0) - // LLVM: %{{.+}} = call float @expf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.exp.f32(float %{{.+}}) // LLVM: } } @@ -429,7 +429,7 @@ double my_exp(double f) { // CHECK: {{.+}} = cir.exp {{.+}} : !cir.double // LLVM: define double @my_exp(double %0) - // LLVM: %{{.+}} = call double @exp(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.exp.f64(double %{{.+}}) // LLVM: } } @@ -440,7 +440,7 @@ long double my_expl(long double f) { // AARCH64: {{.+}} = cir.exp {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_expl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @expl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.exp.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -454,7 +454,7 @@ float call_expf(float f) { // CHECK: {{.+}} = cir.exp {{.+}} : !cir.float // LLVM: define float @call_expf(float %0) - // LLVM: %{{.+}} = call float @expf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.exp.f32(float %{{.+}}) // LLVM: } } @@ -464,7 +464,7 @@ double call_exp(double f) { // CHECK: {{.+}} = cir.exp {{.+}} : !cir.double // LLVM: define double @call_exp(double %0) - // LLVM: %{{.+}} = call double @exp(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.exp.f64(double %{{.+}}) // LLVM: } } @@ -475,7 +475,7 @@ long double call_expl(long double f) { // AARCH64: {{.+}} = cir.exp {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_expl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @expl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.exp.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -487,7 +487,7 @@ float my_exp2f(float f) { // CHECK: {{.+}} = cir.exp2 {{.+}} : !cir.float // LLVM: define float @my_exp2f(float %0) - // LLVM: %{{.+}} = call float @exp2f(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.exp2.f32(float %{{.+}}) // LLVM: } } @@ -497,7 +497,7 @@ double my_exp2(double f) { // CHECK: {{.+}} = cir.exp2 {{.+}} : !cir.double // LLVM: define double @my_exp2(double %0) - // LLVM: %{{.+}} = call double @exp2(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.exp2.f64(double %{{.+}}) // LLVM: } } @@ -508,7 +508,7 @@ long double my_exp2l(long double f) { // AARCH64: {{.+}} = cir.exp2 {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_exp2l(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @exp2l(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.exp2.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -522,7 +522,7 @@ float call_exp2f(float f) { // CHECK: {{.+}} = cir.exp2 {{.+}} : !cir.float // LLVM: define float @call_exp2f(float %0) - // LLVM: %{{.+}} = call float @exp2f(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.exp2.f32(float %{{.+}}) // LLVM: } } @@ -532,7 +532,7 @@ double call_exp2(double f) { // CHECK: {{.+}} = cir.exp2 {{.+}} : !cir.double // LLVM: define double @call_exp2(double %0) - // LLVM: %{{.+}} = call double @exp2(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.exp2.f64(double %{{.+}}) // LLVM: } } @@ -543,7 +543,7 @@ long double call_exp2l(long double f) { // AARCH64: {{.+}} = cir.exp2 {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_exp2l(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @exp2l(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.exp2.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -623,7 +623,7 @@ float my_logf(float f) { // CHECK: {{.+}} = cir.log {{.+}} : !cir.float // LLVM: define float @my_logf(float %0) - // LLVM: %{{.+}} = call float @logf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.log.f32(float %{{.+}}) // LLVM: } } @@ -633,7 +633,7 @@ double my_log(double f) { // CHECK: {{.+}} = cir.log {{.+}} : !cir.double // LLVM: define double @my_log(double %0) - // LLVM: %{{.+}} = call double @log(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.log.f64(double %{{.+}}) // LLVM: } } @@ -644,7 +644,7 @@ long double my_logl(long double f) { // AARCH64: {{.+}} = cir.log {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_logl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @logl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.log.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -658,7 +658,7 @@ float call_logf(float f) { // CHECK: {{.+}} = cir.log {{.+}} : !cir.float // LLVM: define float @call_logf(float %0) - // LLVM: %{{.+}} = call float @logf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.log.f32(float %{{.+}}) // LLVM: } } @@ -668,7 +668,7 @@ double call_log(double f) { // CHECK: {{.+}} = cir.log {{.+}} : !cir.double // LLVM: define double @call_log(double %0) - // LLVM: %{{.+}} = call double @log(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.log.f64(double %{{.+}}) // LLVM: } } @@ -679,7 +679,7 @@ long double call_logl(long double f) { // AARCH64: {{.+}} = cir.log {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_logl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @logl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.log.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -691,7 +691,7 @@ float my_log10f(float f) { // CHECK: {{.+}} = cir.log10 {{.+}} : !cir.float // LLVM: define float @my_log10f(float %0) - // LLVM: %{{.+}} = call float @log10f(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.log10.f32(float %{{.+}}) // LLVM: } } @@ -701,7 +701,7 @@ double my_log10(double f) { // CHECK: {{.+}} = cir.log10 {{.+}} : !cir.double // LLVM: define double @my_log10(double %0) - // LLVM: %{{.+}} = call double @log10(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.log10.f64(double %{{.+}}) // LLVM: } } @@ -712,7 +712,7 @@ long double my_log10l(long double f) { // AARCH64: {{.+}} = cir.log10 {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_log10l(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @log10l(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.log10.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -726,7 +726,7 @@ float call_log10f(float f) { // CHECK: {{.+}} = cir.log10 {{.+}} : !cir.float // LLVM: define float @call_log10f(float %0) - // LLVM: %{{.+}} = call float @log10f(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.log10.f32(float %{{.+}}) // LLVM: } } @@ -736,7 +736,7 @@ double call_log10(double f) { // CHECK: {{.+}} = cir.log10 {{.+}} : !cir.double // LLVM: define double @call_log10(double %0) - // LLVM: %{{.+}} = call double @log10(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.log10.f64(double %{{.+}}) // LLVM: } } @@ -747,7 +747,7 @@ long double call_log10l(long double f) { // AARCH64: {{.+}} = cir.log10 {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_log10l(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @log10l(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.log10.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -759,7 +759,7 @@ float my_log2f(float f) { // CHECK: {{.+}} = cir.log2 {{.+}} : !cir.float // LLVM: define float @my_log2f(float %0) - // LLVM: %{{.+}} = call float @log2f(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.log2.f32(float %{{.+}}) // LLVM: } } @@ -769,7 +769,7 @@ double my_log2(double f) { // CHECK: {{.+}} = cir.log2 {{.+}} : !cir.double // LLVM: define double @my_log2(double %0) - // LLVM: %{{.+}} = call double @log2(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.log2.f64(double %{{.+}}) // LLVM: } } @@ -780,7 +780,7 @@ long double my_log2l(long double f) { // AARCH64: {{.+}} = cir.log2 {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_log2l(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @log2l(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.log2.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -794,7 +794,7 @@ float call_log2f(float f) { // CHECK: {{.+}} = cir.log2 {{.+}} : !cir.float // LLVM: define float @call_log2f(float %0) - // LLVM: %{{.+}} = call float @log2f(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.log2.f32(float %{{.+}}) // LLVM: } } @@ -804,7 +804,7 @@ double call_log2(double f) { // CHECK: {{.+}} = cir.log2 {{.+}} : !cir.double // LLVM: define double @call_log2(double %0) - // LLVM: %{{.+}} = call double @log2(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.log2.f64(double %{{.+}}) // LLVM: } } @@ -815,7 +815,7 @@ long double call_log2l(long double f) { // AARCH64: {{.+}} = cir.log2 {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_log2l(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @log2l(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.log2.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -1031,7 +1031,7 @@ float my_sinf(float f) { // CHECK: {{.+}} = cir.sin {{.+}} : !cir.float // LLVM: define float @my_sinf(float %0) - // LLVM: %{{.+}} = call float @sinf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.sin.f32(float %{{.+}}) // LLVM: } } @@ -1041,7 +1041,7 @@ double my_sin(double f) { // CHECK: {{.+}} = cir.sin {{.+}} : !cir.double // LLVM: define double @my_sin(double %0) - // LLVM: %{{.+}} = call double @sin(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.sin.f64(double %{{.+}}) // LLVM: } } @@ -1052,7 +1052,7 @@ long double my_sinl(long double f) { // AARCH64: {{.+}} = cir.sin {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_sinl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @sinl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.sin.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -1066,7 +1066,7 @@ float call_sinf(float f) { // CHECK: {{.+}} = cir.sin {{.+}} : !cir.float // LLVM: define float @call_sinf(float %0) - // LLVM: %{{.+}} = call float @sinf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.sin.f32(float %{{.+}}) // LLVM: } } @@ -1076,7 +1076,7 @@ double call_sin(double f) { // CHECK: {{.+}} = cir.sin {{.+}} : !cir.double // LLVM: define double @call_sin(double %0) - // LLVM: %{{.+}} = call double @sin(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.sin.f64(double %{{.+}}) // LLVM: } } @@ -1087,7 +1087,7 @@ long double call_sinl(long double f) { // AARCH64: {{.+}} = cir.sin {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_sinl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @sinl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.sin.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -1099,7 +1099,7 @@ float my_sqrtf(float f) { // CHECK: {{.+}} = cir.sqrt {{.+}} : !cir.float // LLVM: define float @my_sqrtf(float %0) - // LLVM: %{{.+}} = call float @sqrtf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.sqrt.f32(float %{{.+}}) // LLVM: } } @@ -1109,7 +1109,7 @@ double my_sqrt(double f) { // CHECK: {{.+}} = cir.sqrt {{.+}} : !cir.double // LLVM: define double @my_sqrt(double %0) - // LLVM: %{{.+}} = call double @sqrt(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.sqrt.f64(double %{{.+}}) // LLVM: } } @@ -1120,7 +1120,7 @@ long double my_sqrtl(long double f) { // AARCH64: {{.+}} = cir.sqrt {{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_sqrtl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @sqrtl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.sqrt.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -1134,7 +1134,7 @@ float call_sqrtf(float f) { // CHECK: {{.+}} = cir.sqrt {{.+}} : !cir.float // LLVM: define float @call_sqrtf(float %0) - // LLVM: %{{.+}} = call float @sqrtf(float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.sqrt.f32(float %{{.+}}) // LLVM: } } @@ -1144,7 +1144,7 @@ double call_sqrt(double f) { // CHECK: {{.+}} = cir.sqrt {{.+}} : !cir.double // LLVM: define double @call_sqrt(double %0) - // LLVM: %{{.+}} = call double @sqrt(double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.sqrt.f64(double %{{.+}}) // LLVM: } } @@ -1155,7 +1155,7 @@ long double call_sqrtl(long double f) { // AARCH64: {{.+}} = cir.sqrt {{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_sqrtl(x86_fp80 %0) - // LLVM: %{{.+}} = call x86_fp80 @sqrtl(x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.sqrt.f80(x86_fp80 %{{.+}}) // LLVM: } } @@ -1439,7 +1439,7 @@ float my_fmodf(float x, float y) { // CHECK: %{{.+}} = cir.fmod %{{.+}}, %{{.+}} : !cir.float // LLVM: define float @my_fmodf - // LLVM: %{{.+}} = call float @fmodf(float %{{.+}}, float %{{.+}}) + // LLVM: %{{.+}} = frem float %{{.+}}, %{{.+}} // LLVM: } } @@ -1449,7 +1449,7 @@ double my_fmod(double x, double y) { // CHECK: %{{.+}} = cir.fmod %{{.+}}, %{{.+}} : !cir.double // LLVM: define double @my_fmod - // LLVM: %{{.+}} = call double @fmod(double %{{.+}}, double %{{.+}}) + // LLVM: %{{.+}} = frem double %{{.+}}, %{{.+}} // LLVM: } } @@ -1460,7 +1460,7 @@ long double my_fmodl(long double x, long double y) { // AARCH64: %{{.+}} = cir.fmod %{{.+}}, %{{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_fmodl - // LLVM: %{{.+}} = call x86_fp80 @fmodl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = frem x86_fp80 %{{.+}}, %{{.+}} // LLVM: } } @@ -1474,7 +1474,7 @@ float call_fmodf(float x, float y) { // CHECK: %{{.+}} = cir.fmod %{{.+}}, %{{.+}} : !cir.float // LLVM: define float @call_fmodf - // LLVM: %{{.+}} = call float @fmodf(float %{{.+}}, float %{{.+}}) + // LLVM: %{{.+}} = frem float %{{.+}}, %{{.+}} // LLVM: } } @@ -1484,7 +1484,7 @@ double call_fmod(double x, double y) { // CHECK: %{{.+}} = cir.fmod %{{.+}}, %{{.+}} : !cir.double // LLVM: define double @call_fmod - // LLVM: %{{.+}} = call double @fmod(double %{{.+}}, double %{{.+}}) + // LLVM: %{{.+}} = frem double %{{.+}}, %{{.+}} // LLVM: } } @@ -1495,7 +1495,7 @@ long double call_fmodl(long double x, long double y) { // AARCH64: %{{.+}} = cir.fmod %{{.+}}, %{{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_fmodl - // LLVM: %{{.+}} = call x86_fp80 @fmodl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = frem x86_fp80 %{{.+}}, %{{.+}} // LLVM: } } @@ -1507,7 +1507,7 @@ float my_powf(float x, float y) { // CHECK: %{{.+}} = cir.pow %{{.+}}, %{{.+}} : !cir.float // LLVM: define float @my_powf - // LLVM: %{{.+}} = call float @powf(float %{{.+}}, float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.pow.f32(float %{{.+}}, float %{{.+}}) // LLVM: } } @@ -1517,7 +1517,7 @@ double my_pow(double x, double y) { // CHECK: %{{.+}} = cir.pow %{{.+}}, %{{.+}} : !cir.double // LLVM: define double @my_pow - // LLVM: %{{.+}} = call double @pow(double %{{.+}}, double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.pow.f64(double %{{.+}}, double %{{.+}}) // LLVM: } } @@ -1528,7 +1528,7 @@ long double my_powl(long double x, long double y) { // AARCH64: %{{.+}} = cir.pow %{{.+}}, %{{.+}} : !cir.long_double // LLVM: define x86_fp80 @my_powl - // LLVM: %{{.+}} = call x86_fp80 @powl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.pow.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } } @@ -1542,7 +1542,7 @@ float call_powf(float x, float y) { // CHECK: %{{.+}} = cir.pow %{{.+}}, %{{.+}} : !cir.float // LLVM: define float @call_powf - // LLVM: %{{.+}} = call float @powf(float %{{.+}}, float %{{.+}}) + // LLVM: %{{.+}} = call float @llvm.pow.f32(float %{{.+}}, float %{{.+}}) // LLVM: } } @@ -1552,7 +1552,7 @@ double call_pow(double x, double y) { // CHECK: %{{.+}} = cir.pow %{{.+}}, %{{.+}} : !cir.double // LLVM: define double @call_pow - // LLVM: %{{.+}} = call double @pow(double %{{.+}}, double %{{.+}}) + // LLVM: %{{.+}} = call double @llvm.pow.f64(double %{{.+}}, double %{{.+}}) // LLVM: } } @@ -1563,6 +1563,6 @@ long double call_powl(long double x, long double y) { // AARCH64: %{{.+}} = cir.pow %{{.+}}, %{{.+}} : !cir.long_double // LLVM: define x86_fp80 @call_powl - // LLVM: %{{.+}} = call x86_fp80 @powl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // LLVM: %{{.+}} = call x86_fp80 @llvm.pow.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } } diff --git a/clang/test/CIR/Lowering/builtin-binary-fp2fp.c b/clang/test/CIR/Lowering/builtin-binary-fp2fp.c index acde798fdf11..0910776847dc 100644 --- a/clang/test/CIR/Lowering/builtin-binary-fp2fp.c +++ b/clang/test/CIR/Lowering/builtin-binary-fp2fp.c @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fmath-errno -fclangir -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -ffast-math -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM-FASTMATH // copysign @@ -11,6 +13,10 @@ float my_copysignf(float x, float y) { // LLVM: %{{.+}} = call float @llvm.copysign.f32(float %{{.+}}, float %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define float @my_copysignf +// LLVM-FASTMATH: %{{.+}} = call float @llvm.copysign.f32(float %{{.+}}, float %{{.+}}) +// LLVM-FASTMATH: } + double my_copysign(double x, double y) { return __builtin_copysign(x, y); } @@ -19,6 +25,10 @@ double my_copysign(double x, double y) { // LLVM: %{{.+}} = call double @llvm.copysign.f64(double %{{.+}}, double %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define double @my_copysign +// LLVM-FASTMATH: %{{.+}} = call double @llvm.copysign.f64(double %{{.+}}, double %{{.+}}) +// LLVM-FASTMATH: } + long double my_copysignl(long double x, long double y) { return __builtin_copysignl(x, y); } @@ -27,6 +37,10 @@ long double my_copysignl(long double x, long double y) { // LLVM: %{{.+}} = call x86_fp80 @llvm.copysign.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define x86_fp80 @my_copysignl +// LLVM-FASTMATH: %{{.+}} = call x86_fp80 @llvm.copysign.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) +// LLVM-FASTMATH: } + // fmax float my_fmaxf(float x, float y) { @@ -37,6 +51,10 @@ float my_fmaxf(float x, float y) { // LLVM: %{{.+}} = call float @llvm.maxnum.f32(float %{{.+}}, float %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define float @my_fmaxf +// LLVM-FASTMATH: %{{.+}} = call float @llvm.maxnum.f32(float %{{.+}}, float %{{.+}}) +// LLVM-FASTMATH: } + double my_fmax(double x, double y) { return __builtin_fmax(x, y); } @@ -45,6 +63,10 @@ double my_fmax(double x, double y) { // LLVM: %{{.+}} = call double @llvm.maxnum.f64(double %{{.+}}, double %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define double @my_fmax +// LLVM-FASTMATH: %{{.+}} = call double @llvm.maxnum.f64(double %{{.+}}, double %{{.+}}) +// LLVM-FASTMATH: } + long double my_fmaxl(long double x, long double y) { return __builtin_fmaxl(x, y); } @@ -53,6 +75,10 @@ long double my_fmaxl(long double x, long double y) { // LLVM: %{{.+}} = call x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define x86_fp80 @my_fmaxl +// LLVM-FASTMATH: %{{.+}} = call x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) +// LLVM-FASTMATH: } + // fmin float my_fminf(float x, float y) { @@ -63,6 +89,10 @@ float my_fminf(float x, float y) { // LLVM: %{{.+}} = call float @llvm.minnum.f32(float %{{.+}}, float %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define float @my_fminf +// LLVM-FASTMATH: %{{.+}} = call float @llvm.minnum.f32(float %{{.+}}, float %{{.+}}) +// LLVM-FASTMATH: } + double my_fmin(double x, double y) { return __builtin_fmin(x, y); } @@ -71,6 +101,10 @@ double my_fmin(double x, double y) { // LLVM: %{{.+}} = call double @llvm.minnum.f64(double %{{.+}}, double %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define double @my_fmin +// LLVM-FASTMATH: %{{.+}} = call double @llvm.minnum.f64(double %{{.+}}, double %{{.+}}) +// LLVM-FASTMATH: } + long double my_fminl(long double x, long double y) { return __builtin_fminl(x, y); } @@ -79,6 +113,10 @@ long double my_fminl(long double x, long double y) { // LLVM: %{{.+}} = call x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define x86_fp80 @my_fminl +// LLVM-FASTMATH: %{{.+}} = call x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) +// LLVM-FASTMATH: } + // fmod float my_fmodf(float x, float y) { @@ -89,6 +127,10 @@ float my_fmodf(float x, float y) { // LLVM: %{{.+}} = call float @fmodf(float %{{.+}}, float %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define float @my_fmodf +// LLVM-FASTMATH: %{{.+}} = frem float %{{.+}}, %{{.+}} +// LLVM-FASTMATH: } + double my_fmod(double x, double y) { return __builtin_fmod(x, y); } @@ -97,6 +139,10 @@ double my_fmod(double x, double y) { // LLVM: %{{.+}} = call double @fmod(double %{{.+}}, double %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define double @my_fmod +// LLVM-FASTMATH: %{{.+}} = frem double %{{.+}}, %{{.+}} +// LLVM-FASTMATH: } + long double my_fmodl(long double x, long double y) { return __builtin_fmodl(x, y); } @@ -105,6 +151,10 @@ long double my_fmodl(long double x, long double y) { // LLVM: %{{.+}} = call x86_fp80 @fmodl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define x86_fp80 @my_fmodl +// LLVM-FASTMATH: %{{.+}} = frem x86_fp80 %{{.+}}, %{{.+}} +// LLVM-FASTMATH: } + // pow float my_powf(float x, float y) { @@ -115,6 +165,10 @@ float my_powf(float x, float y) { // LLVM: %{{.+}} = call float @powf(float %{{.+}}, float %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define float @my_powf +// LLVM-FASTMATH: %{{.+}} = call float @llvm.pow.f32(float %{{.+}}, float %{{.+}}) +// LLVM-FASTMATH: } + double my_pow(double x, double y) { return __builtin_pow(x, y); } @@ -123,6 +177,10 @@ double my_pow(double x, double y) { // LLVM: %{{.+}} = call double @pow(double %{{.+}}, double %{{.+}}) // LLVM: } +// LLVM-FASTMATH: define double @my_pow +// LLVM-FASTMATH: %{{.+}} = call double @llvm.pow.f64(double %{{.+}}, double %{{.+}}) +// LLVM-FASTMATH: } + long double my_powl(long double x, long double y) { return __builtin_powl(x, y); } @@ -130,3 +188,7 @@ long double my_powl(long double x, long double y) { // LLVM: define x86_fp80 @my_powl // LLVM: %{{.+}} = call x86_fp80 @powl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // LLVM: } + +// LLVM-FASTMATH: define x86_fp80 @my_powl +// LLVM-FASTMATH: %{{.+}} = call x86_fp80 @llvm.pow.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) +// LLVM-FASTMATH: }