https://github.com/choikwa updated https://github.com/llvm/llvm-project/pull/129347
>From 36bdf55ec26cfabd608548aa6fd6b703d2879d08 Mon Sep 17 00:00:00 2001 From: Kevin Choi <kevin.c...@amd.com> Date: Fri, 28 Feb 2025 16:52:03 -0600 Subject: [PATCH] [AMDGPU][clang] provide device implementation for __builtin_logb and __builtin_scalbn Clang generates library calls for __builtin_* functions which can be a problem for GPUs that cannot handle them. This patch generates a device implementations for __builtin_logb and __builtin_scalbn by emitting LLVM IRs. Only emit IRs when FP exceptions are disabled and math-errno is unset. --- clang/lib/CodeGen/CGBuiltin.cpp | 35 +- clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp | 73 ++ clang/test/CodeGen/logb_scalbn.c | 1045 +++++++++++++++++++ 3 files changed, 1150 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGen/logb_scalbn.c diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index fe55dfffc1cbe..941bd93b153ee 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -43,6 +43,33 @@ using namespace clang; using namespace CodeGen; using namespace llvm; +/// Some builtins do not have library implementation on some targets and +/// are instead emitted as LLVM IRs by some target builtin emitters. +/// FIXME: Remove this when library support is added +static bool shouldEmitBuiltinAsIR(unsigned BuiltinID, + const Builtin::Context &BI, + const CodeGenFunction &CGF) { + if (!CGF.CGM.getLangOpts().MathErrno && + CGF.CurFPFeatures.getExceptionMode() == + LangOptions::FPExceptionModeKind::FPE_Ignore && + CGF.getTarget().getTriple().isAMDGCN()) { + switch (BuiltinID) { + default: + return false; + case Builtin::BIlogbf: + case Builtin::BI__builtin_logbf: + case Builtin::BIlogb: + case Builtin::BI__builtin_logb: + case Builtin::BIscalbnf: + case Builtin::BI__builtin_scalbnf: + case Builtin::BIscalbn: + case Builtin::BI__builtin_scalbn: + return true; + } + } + return false; +} + static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF, unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue, @@ -2414,7 +2441,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // disabled. // Math intrinsics are generated only when math-errno is disabled. Any pragmas // or attributes that affect math-errno should prevent or allow math - // intrincs to be generated. Intrinsics are generated: + // intrinsics to be generated. Intrinsics are generated: // 1- In fast math mode, unless math-errno is overriden // via '#pragma float_control(precise, on)', or via an // 'attribute__((optnone))'. @@ -5999,13 +6026,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is an alias for a lib function (e.g. __builtin_sin), emit // the call using the normal call path, but using the unmangled // version of the function name. - if (getContext().BuiltinInfo.isLibFunction(BuiltinID)) + const auto &BI = getContext().BuiltinInfo; + if (!shouldEmitBuiltinAsIR(BuiltinID, BI, *this) && + BI.isLibFunction(BuiltinID)) return emitLibraryCall(*this, FD, E, CGM.getBuiltinLibFunction(FD, BuiltinID)); // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. - if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + if (BI.isPredefinedLibFunction(BuiltinID)) return emitLibraryCall(*this, FD, E, CGM.getRawFunctionPointer(FD)); // Check that a call to a target specific builtin has the correct target diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp index b56b739094ff3..fb5f7ad6ec489 100644 --- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp @@ -23,6 +23,27 @@ using namespace CodeGen; using namespace llvm; namespace { + +// Has second type mangled argument. +static Value * +emitBinaryExpMaybeConstrainedFPBuiltin(CodeGenFunction &CGF, const CallExpr *E, + Intrinsic::ID IntrinsicID, + Intrinsic::ID ConstrainedIntrinsicID) { + llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); + + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E); + if (CGF.Builder.getIsFPConstrained()) { + Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, + {Src0->getType(), Src1->getType()}); + return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1}); + } + + Function *F = + CGF.CGM.getIntrinsic(IntrinsicID, {Src0->getType(), Src1->getType()}); + return CGF.Builder.CreateCall(F, {Src0, Src1}); +} + // If \p E is not null pointer, insert address space cast to match return // type of \p E if necessary. Value *EmitAMDGPUDispatchPtr(CodeGenFunction &CGF, @@ -1142,6 +1163,58 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_s_prefetch_data: return emitBuiltinWithOneOverloadedType<2>( *this, E, Intrinsic::amdgcn_s_prefetch_data); + case Builtin::BIlogbf: + case Builtin::BI__builtin_logbf: { + Value *Src0 = EmitScalarExpr(E->getArg(0)); + Function *FrExpFunc = CGM.getIntrinsic( + Intrinsic::frexp, {Src0->getType(), Builder.getInt32Ty()}); + CallInst *FrExp = Builder.CreateCall(FrExpFunc, Src0); + Value *Exp = Builder.CreateExtractValue(FrExp, 1); + Value *Add = Builder.CreateAdd( + Exp, ConstantInt::getSigned(Exp->getType(), -1), "", false, true); + Value *SIToFP = Builder.CreateSIToFP(Add, Builder.getFloatTy()); + Value *Fabs = + emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::fabs); + Value *FCmpONE = Builder.CreateFCmpONE( + Fabs, ConstantFP::getInfinity(Builder.getFloatTy())); + Value *Sel1 = Builder.CreateSelect(FCmpONE, SIToFP, Fabs); + Value *FCmpOEQ = + Builder.CreateFCmpOEQ(Src0, ConstantFP::getZero(Builder.getFloatTy())); + Value *Sel2 = Builder.CreateSelect( + FCmpOEQ, + ConstantFP::getInfinity(Builder.getFloatTy(), /*Negative=*/true), + Sel1); + return Sel2; + } + case Builtin::BIlogb: + case Builtin::BI__builtin_logb: { + Value *Src0 = EmitScalarExpr(E->getArg(0)); + Function *FrExpFunc = CGM.getIntrinsic( + Intrinsic::frexp, {Src0->getType(), Builder.getInt32Ty()}); + CallInst *FrExp = Builder.CreateCall(FrExpFunc, Src0); + Value *Exp = Builder.CreateExtractValue(FrExp, 1); + Value *Add = Builder.CreateAdd( + Exp, ConstantInt::getSigned(Exp->getType(), -1), "", false, true); + Value *SIToFP = Builder.CreateSIToFP(Add, Builder.getDoubleTy()); + Value *Fabs = + emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::fabs); + Value *FCmpONE = Builder.CreateFCmpONE( + Fabs, ConstantFP::getInfinity(Builder.getDoubleTy())); + Value *Sel1 = Builder.CreateSelect(FCmpONE, SIToFP, Fabs); + Value *FCmpOEQ = + Builder.CreateFCmpOEQ(Src0, ConstantFP::getZero(Builder.getDoubleTy())); + Value *Sel2 = Builder.CreateSelect( + FCmpOEQ, + ConstantFP::getInfinity(Builder.getDoubleTy(), /*Negative=*/true), + Sel1); + return Sel2; + } + case Builtin::BIscalbnf: + case Builtin::BI__builtin_scalbnf: + case Builtin::BIscalbn: + case Builtin::BI__builtin_scalbn: + return emitBinaryExpMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::ldexp, Intrinsic::experimental_constrained_ldexp); default: return nullptr; } diff --git a/clang/test/CodeGen/logb_scalbn.c b/clang/test/CodeGen/logb_scalbn.c new file mode 100644 index 0000000000000..be5e68b5fd4b0 --- /dev/null +++ b/clang/test/CodeGen/logb_scalbn.c @@ -0,0 +1,1045 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -emit-llvm %s | FileCheck %s -check-prefixes=DEFAULT +// RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -ffp-exception-behavior=ignore -emit-llvm %s | FileCheck %s -check-prefixes=IGNORE +// RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -ffp-exception-behavior=strict -emit-llvm %s | FileCheck %s -check-prefixes=STRICT +// RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -ffp-exception-behavior=maytrap -emit-llvm %s | FileCheck %s -check-prefixes=MAYTRAP +// RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -fmath-errno -emit-llvm %s | FileCheck %s -check-prefixes=ERRNO + +// DEFAULT-LABEL: define dso_local void @test_logbf( +// DEFAULT-SAME: ) #[[ATTR0:[0-9]+]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: [[TMP0:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000) +// DEFAULT-NEXT: [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1 +// DEFAULT-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// DEFAULT-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float +// DEFAULT-NEXT: [[TMP4:%.*]] = call float @llvm.fabs.f32(float 0x40301999A0000000) +// DEFAULT-NEXT: [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000 +// DEFAULT-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]] +// DEFAULT-NEXT: [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]] +// DEFAULT-NEXT: store float [[TMP7]], ptr [[D1_ASCAST]], align 4 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_logbf( +// IGNORE-SAME: ) #[[ATTR0:[0-9]+]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: [[TMP0:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000) +// IGNORE-NEXT: [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1 +// IGNORE-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// IGNORE-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float +// IGNORE-NEXT: [[TMP4:%.*]] = call float @llvm.fabs.f32(float 0x40301999A0000000) +// IGNORE-NEXT: [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000 +// IGNORE-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]] +// IGNORE-NEXT: [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]] +// IGNORE-NEXT: store float [[TMP7]], ptr [[D1_ASCAST]], align 4 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_logbf( +// STRICT-SAME: ) #[[ATTR0:[0-9]+]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: [[TMP0:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000) +// STRICT-NEXT: [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1 +// STRICT-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// STRICT-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float +// STRICT-NEXT: [[TMP4:%.*]] = call float @llvm.fabs.f32(float 0x40301999A0000000) +// STRICT-NEXT: [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000 +// STRICT-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]] +// STRICT-NEXT: [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]] +// STRICT-NEXT: store float [[TMP7]], ptr [[D1_ASCAST]], align 4 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_logbf( +// MAYTRAP-SAME: ) #[[ATTR0:[0-9]+]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: [[TMP0:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000) +// MAYTRAP-NEXT: [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1 +// MAYTRAP-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// MAYTRAP-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float +// MAYTRAP-NEXT: [[TMP4:%.*]] = call float @llvm.fabs.f32(float 0x40301999A0000000) +// MAYTRAP-NEXT: [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000 +// MAYTRAP-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]] +// MAYTRAP-NEXT: [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]] +// MAYTRAP-NEXT: store float [[TMP7]], ptr [[D1_ASCAST]], align 4 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_logbf( +// ERRNO-SAME: ) #[[ATTR0:[0-9]+]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: [[CALL:%.*]] = call float @logbf(float noundef 0x40301999A0000000) #[[ATTR2:[0-9]+]] +// ERRNO-NEXT: store float [[CALL]], ptr [[D1_ASCAST]], align 4 +// ERRNO-NEXT: ret void +// +void test_logbf() { + float D1 = __builtin_logbf(16.1f); +} +// DEFAULT-LABEL: define dso_local void @test_logbf_var( +// DEFAULT-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP1:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]]) +// DEFAULT-NEXT: [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1 +// DEFAULT-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// DEFAULT-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float +// DEFAULT-NEXT: [[TMP5:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP6:%.*]] = call float @llvm.fabs.f32(float [[TMP5]]) +// DEFAULT-NEXT: [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000 +// DEFAULT-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]] +// DEFAULT-NEXT: [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00 +// DEFAULT-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]] +// DEFAULT-NEXT: store float [[TMP10]], ptr [[D1_ASCAST]], align 4 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_logbf_var( +// IGNORE-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP1:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]]) +// IGNORE-NEXT: [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1 +// IGNORE-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// IGNORE-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float +// IGNORE-NEXT: [[TMP5:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP6:%.*]] = call float @llvm.fabs.f32(float [[TMP5]]) +// IGNORE-NEXT: [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000 +// IGNORE-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]] +// IGNORE-NEXT: [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00 +// IGNORE-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]] +// IGNORE-NEXT: store float [[TMP10]], ptr [[D1_ASCAST]], align 4 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_logbf_var( +// STRICT-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP1:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]]) +// STRICT-NEXT: [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1 +// STRICT-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// STRICT-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float +// STRICT-NEXT: [[TMP5:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP6:%.*]] = call float @llvm.fabs.f32(float [[TMP5]]) +// STRICT-NEXT: [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000 +// STRICT-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]] +// STRICT-NEXT: [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00 +// STRICT-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]] +// STRICT-NEXT: store float [[TMP10]], ptr [[D1_ASCAST]], align 4 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_logbf_var( +// MAYTRAP-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP1:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]]) +// MAYTRAP-NEXT: [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1 +// MAYTRAP-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// MAYTRAP-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float +// MAYTRAP-NEXT: [[TMP5:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP6:%.*]] = call float @llvm.fabs.f32(float [[TMP5]]) +// MAYTRAP-NEXT: [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000 +// MAYTRAP-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]] +// MAYTRAP-NEXT: [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00 +// MAYTRAP-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]] +// MAYTRAP-NEXT: store float [[TMP10]], ptr [[D1_ASCAST]], align 4 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_logbf_var( +// ERRNO-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[CALL:%.*]] = call float @logbf(float noundef [[TMP0]]) #[[ATTR2]] +// ERRNO-NEXT: store float [[CALL]], ptr [[D1_ASCAST]], align 4 +// ERRNO-NEXT: ret void +// +void test_logbf_var(float a) { + float D1 = __builtin_logbf(a); +} +// CHECK-LABEL: define dso_local void @test_logb( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: [[TMP0:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double 1.510000e+01) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { double, i32 } [[TMP0]], 1 +// CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// CHECK-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to double +// CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fabs.f64(double 1.510000e+01) +// CHECK-NEXT: [[TMP5:%.*]] = fcmp one double [[TMP4]], 0x7FF0000000000000 +// CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP3]], double [[TMP4]] +// CHECK-NEXT: [[TMP7:%.*]] = select i1 false, double 0xFFF0000000000000, double [[TMP6]] +// CHECK-NEXT: store double [[TMP7]], ptr [[D1_ASCAST]], align 8 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_logb( +// DEFAULT-SAME: ) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: [[TMP0:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double 1.510000e+01) +// DEFAULT-NEXT: [[TMP1:%.*]] = extractvalue { double, i32 } [[TMP0]], 1 +// DEFAULT-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// DEFAULT-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to double +// DEFAULT-NEXT: [[TMP4:%.*]] = call double @llvm.fabs.f64(double 1.510000e+01) +// DEFAULT-NEXT: [[TMP5:%.*]] = fcmp one double [[TMP4]], 0x7FF0000000000000 +// DEFAULT-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP3]], double [[TMP4]] +// DEFAULT-NEXT: [[TMP7:%.*]] = select i1 false, double 0xFFF0000000000000, double [[TMP6]] +// DEFAULT-NEXT: store double [[TMP7]], ptr [[D1_ASCAST]], align 8 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_logb( +// IGNORE-SAME: ) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: [[TMP0:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double 1.510000e+01) +// IGNORE-NEXT: [[TMP1:%.*]] = extractvalue { double, i32 } [[TMP0]], 1 +// IGNORE-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// IGNORE-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to double +// IGNORE-NEXT: [[TMP4:%.*]] = call double @llvm.fabs.f64(double 1.510000e+01) +// IGNORE-NEXT: [[TMP5:%.*]] = fcmp one double [[TMP4]], 0x7FF0000000000000 +// IGNORE-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP3]], double [[TMP4]] +// IGNORE-NEXT: [[TMP7:%.*]] = select i1 false, double 0xFFF0000000000000, double [[TMP6]] +// IGNORE-NEXT: store double [[TMP7]], ptr [[D1_ASCAST]], align 8 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_logb( +// STRICT-SAME: ) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: [[TMP0:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double 1.510000e+01) +// STRICT-NEXT: [[TMP1:%.*]] = extractvalue { double, i32 } [[TMP0]], 1 +// STRICT-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// STRICT-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to double +// STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.fabs.f64(double 1.510000e+01) +// STRICT-NEXT: [[TMP5:%.*]] = fcmp one double [[TMP4]], 0x7FF0000000000000 +// STRICT-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP3]], double [[TMP4]] +// STRICT-NEXT: [[TMP7:%.*]] = select i1 false, double 0xFFF0000000000000, double [[TMP6]] +// STRICT-NEXT: store double [[TMP7]], ptr [[D1_ASCAST]], align 8 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_logb( +// MAYTRAP-SAME: ) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: [[TMP0:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double 1.510000e+01) +// MAYTRAP-NEXT: [[TMP1:%.*]] = extractvalue { double, i32 } [[TMP0]], 1 +// MAYTRAP-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1 +// MAYTRAP-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to double +// MAYTRAP-NEXT: [[TMP4:%.*]] = call double @llvm.fabs.f64(double 1.510000e+01) +// MAYTRAP-NEXT: [[TMP5:%.*]] = fcmp one double [[TMP4]], 0x7FF0000000000000 +// MAYTRAP-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP3]], double [[TMP4]] +// MAYTRAP-NEXT: [[TMP7:%.*]] = select i1 false, double 0xFFF0000000000000, double [[TMP6]] +// MAYTRAP-NEXT: store double [[TMP7]], ptr [[D1_ASCAST]], align 8 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_logb( +// ERRNO-SAME: ) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: [[CALL:%.*]] = call double @logb(double noundef 1.510000e+01) #[[ATTR2]] +// ERRNO-NEXT: store double [[CALL]], ptr [[D1_ASCAST]], align 8 +// ERRNO-NEXT: ret void +// +void test_logb() { + double D1 = __builtin_logb(15.1); +} +// CHECK-LABEL: define dso_local void @test_logb_var( +// CHECK-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { double, i32 } [[TMP1]], 1 +// CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// CHECK-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to double +// CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = call double @llvm.fabs.f64(double [[TMP5]]) +// CHECK-NEXT: [[TMP7:%.*]] = fcmp one double [[TMP6]], 0x7FF0000000000000 +// CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP4]], double [[TMP6]] +// CHECK-NEXT: [[TMP9:%.*]] = fcmp oeq double [[TMP0]], 0.000000e+00 +// CHECK-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[TMP8]] +// CHECK-NEXT: store double [[TMP10]], ptr [[D1_ASCAST]], align 8 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_logb_var( +// DEFAULT-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: [[TMP1:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double [[TMP0]]) +// DEFAULT-NEXT: [[TMP2:%.*]] = extractvalue { double, i32 } [[TMP1]], 1 +// DEFAULT-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// DEFAULT-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to double +// DEFAULT-NEXT: [[TMP5:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: [[TMP6:%.*]] = call double @llvm.fabs.f64(double [[TMP5]]) +// DEFAULT-NEXT: [[TMP7:%.*]] = fcmp one double [[TMP6]], 0x7FF0000000000000 +// DEFAULT-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP4]], double [[TMP6]] +// DEFAULT-NEXT: [[TMP9:%.*]] = fcmp oeq double [[TMP0]], 0.000000e+00 +// DEFAULT-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[TMP8]] +// DEFAULT-NEXT: store double [[TMP10]], ptr [[D1_ASCAST]], align 8 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_logb_var( +// IGNORE-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: [[TMP1:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double [[TMP0]]) +// IGNORE-NEXT: [[TMP2:%.*]] = extractvalue { double, i32 } [[TMP1]], 1 +// IGNORE-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// IGNORE-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to double +// IGNORE-NEXT: [[TMP5:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: [[TMP6:%.*]] = call double @llvm.fabs.f64(double [[TMP5]]) +// IGNORE-NEXT: [[TMP7:%.*]] = fcmp one double [[TMP6]], 0x7FF0000000000000 +// IGNORE-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP4]], double [[TMP6]] +// IGNORE-NEXT: [[TMP9:%.*]] = fcmp oeq double [[TMP0]], 0.000000e+00 +// IGNORE-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[TMP8]] +// IGNORE-NEXT: store double [[TMP10]], ptr [[D1_ASCAST]], align 8 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_logb_var( +// STRICT-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: [[TMP1:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double [[TMP0]]) +// STRICT-NEXT: [[TMP2:%.*]] = extractvalue { double, i32 } [[TMP1]], 1 +// STRICT-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// STRICT-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to double +// STRICT-NEXT: [[TMP5:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: [[TMP6:%.*]] = call double @llvm.fabs.f64(double [[TMP5]]) +// STRICT-NEXT: [[TMP7:%.*]] = fcmp one double [[TMP6]], 0x7FF0000000000000 +// STRICT-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP4]], double [[TMP6]] +// STRICT-NEXT: [[TMP9:%.*]] = fcmp oeq double [[TMP0]], 0.000000e+00 +// STRICT-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[TMP8]] +// STRICT-NEXT: store double [[TMP10]], ptr [[D1_ASCAST]], align 8 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_logb_var( +// MAYTRAP-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: [[TMP1:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double [[TMP0]]) +// MAYTRAP-NEXT: [[TMP2:%.*]] = extractvalue { double, i32 } [[TMP1]], 1 +// MAYTRAP-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1 +// MAYTRAP-NEXT: [[TMP4:%.*]] = sitofp i32 [[TMP3]] to double +// MAYTRAP-NEXT: [[TMP5:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: [[TMP6:%.*]] = call double @llvm.fabs.f64(double [[TMP5]]) +// MAYTRAP-NEXT: [[TMP7:%.*]] = fcmp one double [[TMP6]], 0x7FF0000000000000 +// MAYTRAP-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP4]], double [[TMP6]] +// MAYTRAP-NEXT: [[TMP9:%.*]] = fcmp oeq double [[TMP0]], 0.000000e+00 +// MAYTRAP-NEXT: [[TMP10:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[TMP8]] +// MAYTRAP-NEXT: store double [[TMP10]], ptr [[D1_ASCAST]], align 8 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_logb_var( +// ERRNO-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// ERRNO-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// ERRNO-NEXT: [[CALL:%.*]] = call double @logb(double noundef [[TMP0]]) #[[ATTR2]] +// ERRNO-NEXT: store double [[CALL]], ptr [[D1_ASCAST]], align 8 +// ERRNO-NEXT: ret void +// +void test_logb_var(double a) { + double D1 = __builtin_logb(a); +} + +// CHECK-LABEL: define dso_local void @test_scalbnf( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.ldexp.f32.i32(float 0x4030B33340000000, i32 10) +// CHECK-NEXT: store float [[TMP0]], ptr [[D1_ASCAST]], align 4 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbnf( +// DEFAULT-SAME: ) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: [[TMP0:%.*]] = call float @llvm.ldexp.f32.i32(float 0x4030B33340000000, i32 10) +// DEFAULT-NEXT: store float [[TMP0]], ptr [[D1_ASCAST]], align 4 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbnf( +// IGNORE-SAME: ) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: [[TMP0:%.*]] = call float @llvm.ldexp.f32.i32(float 0x4030B33340000000, i32 10) +// IGNORE-NEXT: store float [[TMP0]], ptr [[D1_ASCAST]], align 4 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbnf( +// STRICT-SAME: ) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: [[TMP0:%.*]] = call float @llvm.ldexp.f32.i32(float 0x4030B33340000000, i32 10) +// STRICT-NEXT: store float [[TMP0]], ptr [[D1_ASCAST]], align 4 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbnf( +// MAYTRAP-SAME: ) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: [[TMP0:%.*]] = call float @llvm.ldexp.f32.i32(float 0x4030B33340000000, i32 10) +// MAYTRAP-NEXT: store float [[TMP0]], ptr [[D1_ASCAST]], align 4 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbnf( +// ERRNO-SAME: ) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: [[CALL:%.*]] = call float @scalbnf(float noundef 0x4030B33340000000, i32 noundef 10) #[[ATTR2]] +// ERRNO-NEXT: store float [[CALL]], ptr [[D1_ASCAST]], align 4 +// ERRNO-NEXT: ret void +// +void test_scalbnf() { + float D1 = __builtin_scalbnf(16.7f, 10); +} +// CHECK-LABEL: define dso_local void @test_scalbnf_var1( +// CHECK-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 9) +// CHECK-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbnf_var1( +// DEFAULT-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 9) +// DEFAULT-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbnf_var1( +// IGNORE-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 9) +// IGNORE-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbnf_var1( +// STRICT-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 9) +// STRICT-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbnf_var1( +// MAYTRAP-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 9) +// MAYTRAP-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbnf_var1( +// ERRNO-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[CALL:%.*]] = call float @scalbnf(float noundef [[TMP0]], i32 noundef 9) #[[ATTR2]] +// ERRNO-NEXT: store float [[CALL]], ptr [[D1_ASCAST]], align 4 +// ERRNO-NEXT: ret void +// +void test_scalbnf_var1(float a) { + float D1 = __builtin_scalbnf(a, 9); +} +// CHECK-LABEL: define dso_local void @test_scalbnf_var2( +// CHECK-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float 0x402E666660000000, i32 [[TMP0]]) +// CHECK-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbnf_var2( +// DEFAULT-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float 0x402E666660000000, i32 [[TMP0]]) +// DEFAULT-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbnf_var2( +// IGNORE-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float 0x402E666660000000, i32 [[TMP0]]) +// IGNORE-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbnf_var2( +// STRICT-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float 0x402E666660000000, i32 [[TMP0]]) +// STRICT-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbnf_var2( +// MAYTRAP-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float 0x402E666660000000, i32 [[TMP0]]) +// MAYTRAP-NEXT: store float [[TMP1]], ptr [[D1_ASCAST]], align 4 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbnf_var2( +// ERRNO-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[CALL:%.*]] = call float @scalbnf(float noundef 0x402E666660000000, i32 noundef [[TMP0]]) #[[ATTR2]] +// ERRNO-NEXT: store float [[CALL]], ptr [[D1_ASCAST]], align 4 +// ERRNO-NEXT: ret void +// +void test_scalbnf_var2(int b) { + float D1 = __builtin_scalbnf(15.2f, b); +} +// CHECK-LABEL: define dso_local void @test_scalbnf_var3( +// CHECK-SAME: float noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 [[TMP1]]) +// CHECK-NEXT: store float [[TMP2]], ptr [[D1_ASCAST]], align 4 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbnf_var3( +// DEFAULT-SAME: float noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// DEFAULT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// DEFAULT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP2:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 [[TMP1]]) +// DEFAULT-NEXT: store float [[TMP2]], ptr [[D1_ASCAST]], align 4 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbnf_var3( +// IGNORE-SAME: float noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// IGNORE-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// IGNORE-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP2:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 [[TMP1]]) +// IGNORE-NEXT: store float [[TMP2]], ptr [[D1_ASCAST]], align 4 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbnf_var3( +// STRICT-SAME: float noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// STRICT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// STRICT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP2:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 [[TMP1]]) +// STRICT-NEXT: store float [[TMP2]], ptr [[D1_ASCAST]], align 4 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbnf_var3( +// MAYTRAP-SAME: float noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// MAYTRAP-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// MAYTRAP-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP2:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP0]], i32 [[TMP1]]) +// MAYTRAP-NEXT: store float [[TMP2]], ptr [[D1_ASCAST]], align 4 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbnf_var3( +// ERRNO-SAME: float noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca float, align 4, addrspace(5) +// ERRNO-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// ERRNO-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store float [[A]], ptr [[A_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[CALL:%.*]] = call float @scalbnf(float noundef [[TMP0]], i32 noundef [[TMP1]]) #[[ATTR2]] +// ERRNO-NEXT: store float [[CALL]], ptr [[D1_ASCAST]], align 4 +// ERRNO-NEXT: ret void +// +void test_scalbnf_var3(float a, int b) { + float D1 = __builtin_scalbnf(a, b); +} + +// CHECK-LABEL: define dso_local void @test_scalbn( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.ldexp.f64.i32(double 1.720000e+01, i32 10) +// CHECK-NEXT: store double [[TMP0]], ptr [[D1_ASCAST]], align 8 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbn( +// DEFAULT-SAME: ) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: [[TMP0:%.*]] = call double @llvm.ldexp.f64.i32(double 1.720000e+01, i32 10) +// DEFAULT-NEXT: store double [[TMP0]], ptr [[D1_ASCAST]], align 8 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbn( +// IGNORE-SAME: ) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: [[TMP0:%.*]] = call double @llvm.ldexp.f64.i32(double 1.720000e+01, i32 10) +// IGNORE-NEXT: store double [[TMP0]], ptr [[D1_ASCAST]], align 8 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbn( +// STRICT-SAME: ) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: [[TMP0:%.*]] = call double @llvm.ldexp.f64.i32(double 1.720000e+01, i32 10) +// STRICT-NEXT: store double [[TMP0]], ptr [[D1_ASCAST]], align 8 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbn( +// MAYTRAP-SAME: ) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: [[TMP0:%.*]] = call double @llvm.ldexp.f64.i32(double 1.720000e+01, i32 10) +// MAYTRAP-NEXT: store double [[TMP0]], ptr [[D1_ASCAST]], align 8 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbn( +// ERRNO-SAME: ) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: [[CALL:%.*]] = call double @scalbn(double noundef 1.720000e+01, i32 noundef 10) #[[ATTR2]] +// ERRNO-NEXT: store double [[CALL]], ptr [[D1_ASCAST]], align 8 +// ERRNO-NEXT: ret void +// +void test_scalbn() { + double D1 = __builtin_scalbn(17.2, 10); +} +// CHECK-LABEL: define dso_local void @test_scalbn_var1( +// CHECK-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 9) +// CHECK-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbn_var1( +// DEFAULT-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 9) +// DEFAULT-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbn_var1( +// IGNORE-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 9) +// IGNORE-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbn_var1( +// STRICT-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 9) +// STRICT-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbn_var1( +// MAYTRAP-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 9) +// MAYTRAP-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbn_var1( +// ERRNO-SAME: double noundef [[A:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// ERRNO-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// ERRNO-NEXT: [[CALL:%.*]] = call double @scalbn(double noundef [[TMP0]], i32 noundef 9) #[[ATTR2]] +// ERRNO-NEXT: store double [[CALL]], ptr [[D1_ASCAST]], align 8 +// ERRNO-NEXT: ret void +// +void test_scalbn_var1(double a) { + double D1 = __builtin_scalbn(a, 9); +} +// CHECK-LABEL: define dso_local void @test_scalbn_var2( +// CHECK-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double 1.540000e+01, i32 [[TMP0]]) +// CHECK-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbn_var2( +// DEFAULT-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double 1.540000e+01, i32 [[TMP0]]) +// DEFAULT-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbn_var2( +// IGNORE-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double 1.540000e+01, i32 [[TMP0]]) +// IGNORE-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbn_var2( +// STRICT-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double 1.540000e+01, i32 [[TMP0]]) +// STRICT-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbn_var2( +// MAYTRAP-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP1:%.*]] = call double @llvm.ldexp.f64.i32(double 1.540000e+01, i32 [[TMP0]]) +// MAYTRAP-NEXT: store double [[TMP1]], ptr [[D1_ASCAST]], align 8 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbn_var2( +// ERRNO-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP0:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[CALL:%.*]] = call double @scalbn(double noundef 1.540000e+01, i32 noundef [[TMP0]]) #[[ATTR2]] +// ERRNO-NEXT: store double [[CALL]], ptr [[D1_ASCAST]], align 8 +// ERRNO-NEXT: ret void +// +void test_scalbn_var2(int b) { + double D1 = __builtin_scalbn(15.4, b); +} +// CHECK-LABEL: define dso_local void @test_scalbn_var3( +// CHECK-SAME: double noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// CHECK-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 [[TMP1]]) +// CHECK-NEXT: store double [[TMP2]], ptr [[D1_ASCAST]], align 8 +// CHECK-NEXT: ret void +// DEFAULT-LABEL: define dso_local void @test_scalbn_var3( +// DEFAULT-SAME: double noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// DEFAULT-NEXT: [[ENTRY:.*:]] +// DEFAULT-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DEFAULT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// DEFAULT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// DEFAULT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// DEFAULT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// DEFAULT-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// DEFAULT-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// DEFAULT-NEXT: [[TMP2:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 [[TMP1]]) +// DEFAULT-NEXT: store double [[TMP2]], ptr [[D1_ASCAST]], align 8 +// DEFAULT-NEXT: ret void +// +// IGNORE-LABEL: define dso_local void @test_scalbn_var3( +// IGNORE-SAME: double noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// IGNORE-NEXT: [[ENTRY:.*:]] +// IGNORE-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// IGNORE-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// IGNORE-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// IGNORE-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// IGNORE-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// IGNORE-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// IGNORE-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// IGNORE-NEXT: [[TMP2:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 [[TMP1]]) +// IGNORE-NEXT: store double [[TMP2]], ptr [[D1_ASCAST]], align 8 +// IGNORE-NEXT: ret void +// +// STRICT-LABEL: define dso_local void @test_scalbn_var3( +// STRICT-SAME: double noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// STRICT-NEXT: [[ENTRY:.*:]] +// STRICT-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// STRICT-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// STRICT-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// STRICT-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// STRICT-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// STRICT-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// STRICT-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 [[TMP1]]) +// STRICT-NEXT: store double [[TMP2]], ptr [[D1_ASCAST]], align 8 +// STRICT-NEXT: ret void +// +// MAYTRAP-LABEL: define dso_local void @test_scalbn_var3( +// MAYTRAP-SAME: double noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// MAYTRAP-NEXT: [[ENTRY:.*:]] +// MAYTRAP-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// MAYTRAP-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// MAYTRAP-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// MAYTRAP-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// MAYTRAP-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// MAYTRAP-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// MAYTRAP-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// MAYTRAP-NEXT: [[TMP2:%.*]] = call double @llvm.ldexp.f64.i32(double [[TMP0]], i32 [[TMP1]]) +// MAYTRAP-NEXT: store double [[TMP2]], ptr [[D1_ASCAST]], align 8 +// MAYTRAP-NEXT: ret void +// +// ERRNO-LABEL: define dso_local void @test_scalbn_var3( +// ERRNO-SAME: double noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// ERRNO-NEXT: [[ENTRY:.*:]] +// ERRNO-NEXT: [[A_ADDR:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// ERRNO-NEXT: [[D1:%.*]] = alloca double, align 8, addrspace(5) +// ERRNO-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// ERRNO-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// ERRNO-NEXT: [[D1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D1]] to ptr +// ERRNO-NEXT: store double [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// ERRNO-NEXT: store i32 [[B]], ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[TMP0:%.*]] = load double, ptr [[A_ADDR_ASCAST]], align 8 +// ERRNO-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// ERRNO-NEXT: [[CALL:%.*]] = call double @scalbn(double noundef [[TMP0]], i32 noundef [[TMP1]]) #[[ATTR2]] +// ERRNO-NEXT: store double [[CALL]], ptr [[D1_ASCAST]], align 8 +// ERRNO-NEXT: ret void +// +void test_scalbn_var3(double a, int b) { + double D1 = __builtin_scalbn(a, b); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits