diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -52,6 +52,7 @@ llvm::DenseMap CustomNames; static StringLiteral const StandardNames[NumLibFuncs]; bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param; + unsigned SizeOfInt; enum AvailabilityState { StandardName = 3, // (memset to all ones) @@ -189,6 +190,16 @@ /// This queries the 'wchar_size' metadata. unsigned getWCharSize(const Module &M) const; + /// Get size of a C-level int or unsigned int, in bits. + unsigned getIntSize() const { + return SizeOfInt; + } + + /// Initialize the C-level size of an integer. + void setIntSize(unsigned Bits) { + SizeOfInt = Bits; + } + /// Returns the largest vectorization factor used in the list of /// vector functions. void getWidestVF(StringRef ScalarF, ElementCount &FixedVF, @@ -390,6 +401,11 @@ return Impl->getWCharSize(M); } + /// \copydoc TargetLibraryInfoImpl::getIntSize() + unsigned getIntSize() const { + return Impl->getIntSize(); + } + /// Handle invalidation from the pass manager. /// /// If we try to invalidate this info, just return false. It cannot become diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -151,6 +151,11 @@ TLI.setShouldExtI32Return(ShouldExtI32Return); TLI.setShouldSignExtI32Param(ShouldSignExtI32Param); + // Let's assume by default that the size of int is 32 bits, unless the target + // is a 16-bit architecture because then it most likely is 16 bits. If that + // isn't true for a target those defaults should be overridden below. + TLI.setIntSize(T.isArch16Bit() ? 16 : 32); + if (T.isAMDGPU()) TLI.disableAllFunctions(); @@ -639,7 +644,8 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI) : CustomNames(TLI.CustomNames), ShouldExtI32Param(TLI.ShouldExtI32Param), ShouldExtI32Return(TLI.ShouldExtI32Return), - ShouldSignExtI32Param(TLI.ShouldSignExtI32Param) { + ShouldSignExtI32Param(TLI.ShouldSignExtI32Param), + SizeOfInt(TLI.SizeOfInt) { memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); VectorDescs = TLI.VectorDescs; ScalarDescs = TLI.ScalarDescs; @@ -649,7 +655,8 @@ : CustomNames(std::move(TLI.CustomNames)), ShouldExtI32Param(TLI.ShouldExtI32Param), ShouldExtI32Return(TLI.ShouldExtI32Return), - ShouldSignExtI32Param(TLI.ShouldSignExtI32Param) { + ShouldSignExtI32Param(TLI.ShouldSignExtI32Param), + SizeOfInt(TLI.SizeOfInt) { std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); VectorDescs = TLI.VectorDescs; @@ -661,6 +668,7 @@ ShouldExtI32Param = TLI.ShouldExtI32Param; ShouldExtI32Return = TLI.ShouldExtI32Return; ShouldSignExtI32Param = TLI.ShouldSignExtI32Param; + SizeOfInt = TLI.SizeOfInt; memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); return *this; } @@ -670,6 +678,7 @@ ShouldExtI32Param = TLI.ShouldExtI32Param; ShouldExtI32Return = TLI.ShouldExtI32Return; ShouldSignExtI32Param = TLI.ShouldSignExtI32Param; + SizeOfInt = TLI.SizeOfInt; std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); return *this; @@ -1498,7 +1507,7 @@ case LibFunc_ldexpl: return (NumParams == 2 && FTy.getReturnType()->isFloatingPointTy() && FTy.getReturnType() == FTy.getParamType(0) && - FTy.getParamType(1)->isIntegerTy(32)); + FTy.getParamType(1)->isIntegerTy(getIntSize())); case LibFunc_ffs: case LibFunc_ffsl: diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1424,17 +1424,18 @@ return InnerChain[Exp]; } -// Return a properly extended 32-bit integer if the operation is an itofp. -static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B) { +// Return a properly extended integer (DstWidth bits wide) if the operation is +// an itofp. +static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth) { if (isa(I2F) || isa(I2F)) { Value *Op = cast(I2F)->getOperand(0); - // Make sure that the exponent fits inside an int32_t, + // Make sure that the exponent fits inside an "int" of size DstWidth, // thus avoiding any range issues that FP has not. unsigned BitWidth = Op->getType()->getPrimitiveSizeInBits(); - if (BitWidth < 32 || - (BitWidth == 32 && isa(I2F))) - return isa(I2F) ? B.CreateSExt(Op, B.getInt32Ty()) - : B.CreateZExt(Op, B.getInt32Ty()); + if (BitWidth < DstWidth || + (BitWidth == DstWidth && isa(I2F))) + return isa(I2F) ? B.CreateSExt(Op, B.getIntNTy(DstWidth)) + : B.CreateZExt(Op, B.getIntNTy(DstWidth)); } return nullptr; @@ -1524,7 +1525,7 @@ if (match(Base, m_SpecificFP(2.0)) && (isa(Expo) || isa(Expo)) && hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { - if (Value *ExpoI = getIntToFPVal(Expo, B)) + if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize())) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, B, Attrs); @@ -1776,7 +1777,12 @@ // powf(x, itofp(y)) -> powi(x, y) if (AllowApprox && (isa(Expo) || isa(Expo))) { - if (Value *ExpoI = getIntToFPVal(Expo, B)) + // FIXME: Currently we always use 32 bits for the exponent in llvm.powi. In + // the future we want to use the target dependent "size of int", or + // otherwise we could end up using the wrong type for the exponent when + // mapping llvm.powi back to an rtlib call. See + // https://reviews.llvm.org/D99439 for such a fix. + if (Value *ExpoI = getIntToFPVal(Expo, B, 32)) return createPowWithIntegerExponent(Base, ExpoI, M, B); } @@ -1803,11 +1809,11 @@ Type *Ty = CI->getType(); Value *Op = CI->getArgOperand(0); - // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= 32 - // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32 + // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= IntSize + // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < IntSize if ((isa(Op) || isa(Op)) && hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { - if (Value *Exp = getIntToFPVal(Op, B)) + if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize())) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, B, Attrs); diff --git a/llvm/test/Transforms/InstCombine/exp2-1.ll b/llvm/test/Transforms/InstCombine/exp2-1.ll --- a/llvm/test/Transforms/InstCombine/exp2-1.ll +++ b/llvm/test/Transforms/InstCombine/exp2-1.ll @@ -1,8 +1,10 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the exp2 library call simplifier works correctly. ; -; RUN: opt < %s -instcombine -S | FileCheck %s -check-prefix=CHECK -check-prefix=INTRINSIC -check-prefix=LDEXP -check-prefix=LDEXPF -; RUN: opt < %s -instcombine -S -mtriple=i386-pc-win32 | FileCheck %s -check-prefix=INTRINSIC -check-prefix=LDEXP -check-prefix=NOLDEXPF -; RUN: opt < %s -instcombine -S -mtriple=amdgcn-unknown-unknown | FileCheck %s -check-prefix=INTRINSIC -check-prefix=NOLDEXP -check-prefix=NOLDEXPF +; RUN: opt < %s -instcombine -S -mtriple=unknown | FileCheck %s -check-prefixes=LDEXP32 +; RUN: opt < %s -instcombine -S -mtriple=msp430 | FileCheck %s -check-prefixes=LDEXP16 +; RUN: opt < %s -instcombine -S -mtriple=i386-pc-win32 | FileCheck %s -check-prefixes=NOLDEXPF +; RUN: opt < %s -instcombine -S -mtriple=amdgcn-unknown-unknown | FileCheck %s -check-prefixes=NOLDEXP target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" @@ -12,68 +14,208 @@ ; Check exp2(sitofp(x)) -> ldexp(1.0, sext(x)). define double @test_simplify1(i32 %x) { -; CHECK-LABEL: @test_simplify1( +; LDEXP32-LABEL: @test_simplify1( +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_simplify1( +; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to double +; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; LDEXP16-NEXT: ret double [[RET]] +; +; NOLDEXPF-LABEL: @test_simplify1( +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_simplify1( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = sitofp i32 %x to double %ret = call double @exp2(double %conv) -; CHECK: call double @ldexp ret double %ret } define double @test_simplify2(i16 signext %x) { -; CHECK-LABEL: @test_simplify2( +; LDEXP32-LABEL: @test_simplify2( +; LDEXP32-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_simplify2( +; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[X:%.*]]) +; LDEXP16-NEXT: ret double [[LDEXP]] +; +; NOLDEXPF-LABEL: @test_simplify2( +; NOLDEXPF-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_simplify2( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i16 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = sitofp i16 %x to double %ret = call double @exp2(double %conv) -; CHECK: call double @ldexp ret double %ret } define double @test_simplify3(i8 signext %x) { -; CHECK-LABEL: @test_simplify3( +; LDEXP32-LABEL: @test_simplify3( +; LDEXP32-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_simplify3( +; LDEXP16-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16 +; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret double [[LDEXP]] +; +; NOLDEXPF-LABEL: @test_simplify3( +; NOLDEXPF-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_simplify3( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i8 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = sitofp i8 %x to double %ret = call double @exp2(double %conv) -; CHECK: call double @ldexp ret double %ret } define float @test_simplify4(i32 %x) { -; CHECK-LABEL: @test_simplify4( +; LDEXP32-LABEL: @test_simplify4( +; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) +; LDEXP32-NEXT: ret float [[LDEXPF]] +; +; LDEXP16-LABEL: @test_simplify4( +; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; LDEXP16-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) +; LDEXP16-NEXT: ret float [[RET]] +; +; NOLDEXPF-LABEL: @test_simplify4( +; NOLDEXPF-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; NOLDEXPF-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) +; NOLDEXPF-NEXT: ret float [[RET]] +; +; NOLDEXP-LABEL: @test_simplify4( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; NOLDEXP-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) +; NOLDEXP-NEXT: ret float [[RET]] +; %conv = sitofp i32 %x to float %ret = call float @exp2f(float %conv) -; CHECK: call float @ldexpf ret float %ret } ; Check exp2(uitofp(x)) -> ldexp(1.0, zext(x)). define double @test_no_simplify1(i32 %x) { -; CHECK-LABEL: @test_no_simplify1( +; LDEXP32-LABEL: @test_no_simplify1( +; LDEXP32-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double +; LDEXP32-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; LDEXP32-NEXT: ret double [[RET]] +; +; LDEXP16-LABEL: @test_no_simplify1( +; LDEXP16-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double +; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; LDEXP16-NEXT: ret double [[RET]] +; +; NOLDEXPF-LABEL: @test_no_simplify1( +; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double +; NOLDEXPF-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXPF-NEXT: ret double [[RET]] +; +; NOLDEXP-LABEL: @test_no_simplify1( +; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = uitofp i32 %x to double %ret = call double @exp2(double %conv) -; CHECK: call double @exp2 ret double %ret } define double @test_simplify6(i16 zeroext %x) { -; CHECK-LABEL: @test_simplify6( +; LDEXP32-LABEL: @test_simplify6( +; LDEXP32-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_simplify6( +; LDEXP16-NEXT: [[CONV:%.*]] = uitofp i16 [[X:%.*]] to double +; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; LDEXP16-NEXT: ret double [[RET]] +; +; NOLDEXPF-LABEL: @test_simplify6( +; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_simplify6( +; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i16 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = uitofp i16 %x to double %ret = call double @exp2(double %conv) -; CHECK: call double @ldexp ret double %ret } define double @test_simplify7(i8 zeroext %x) { -; CHECK-LABEL: @test_simplify7( +; LDEXP32-LABEL: @test_simplify7( +; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_simplify7( +; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16 +; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret double [[LDEXP]] +; +; NOLDEXPF-LABEL: @test_simplify7( +; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_simplify7( +; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = uitofp i8 %x to double %ret = call double @exp2(double %conv) -; CHECK: call double @ldexp ret double %ret } define float @test_simplify8(i8 zeroext %x) { -; CHECK-LABEL: @test_simplify8( +; LDEXP32-LABEL: @test_simplify8( +; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret float [[LDEXPF]] +; +; LDEXP16-LABEL: @test_simplify8( +; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16 +; LDEXP16-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret float [[LDEXPF]] +; +; NOLDEXPF-LABEL: @test_simplify8( +; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float +; NOLDEXPF-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) +; NOLDEXPF-NEXT: ret float [[RET]] +; +; NOLDEXP-LABEL: @test_simplify8( +; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float +; NOLDEXP-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) +; NOLDEXP-NEXT: ret float [[RET]] +; %conv = uitofp i8 %x to float %ret = call float @exp2f(float %conv) -; CHECK: call float @ldexpf ret float %ret } @@ -81,19 +223,53 @@ declare float @llvm.exp2.f32(float) define double @test_simplify9(i8 zeroext %x) { -; INTRINSIC-LABEL: @test_simplify9( +; LDEXP32-LABEL: @test_simplify9( +; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_simplify9( +; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16 +; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret double [[LDEXP]] +; +; NOLDEXPF-LABEL: @test_simplify9( +; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_simplify9( +; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @llvm.exp2.f64(double [[CONV]]) +; NOLDEXP-NEXT: ret double [[RET]] +; %conv = uitofp i8 %x to double %ret = call double @llvm.exp2.f64(double %conv) -; LDEXP: call double @ldexp -; NOLDEXP-NOT: call double @ldexp ret double %ret } define float @test_simplify10(i8 zeroext %x) { -; INTRINSIC-LABEL: @test_simplify10( +; LDEXP32-LABEL: @test_simplify10( +; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 +; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret float [[LDEXPF]] +; +; LDEXP16-LABEL: @test_simplify10( +; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16 +; LDEXP16-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret float [[LDEXPF]] +; +; NOLDEXPF-LABEL: @test_simplify10( +; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float +; NOLDEXPF-NEXT: [[RET:%.*]] = call float @llvm.exp2.f32(float [[CONV]]) +; NOLDEXPF-NEXT: ret float [[RET]] +; +; NOLDEXP-LABEL: @test_simplify10( +; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float +; NOLDEXP-NEXT: [[RET:%.*]] = call float @llvm.exp2.f32(float [[CONV]]) +; NOLDEXP-NEXT: ret float [[RET]] +; %conv = uitofp i8 %x to float %ret = call float @llvm.exp2.f32(float %conv) -; LDEXPF: call float @ldexpf -; NOLDEXPF-NOT: call float @ldexpf ret float %ret } diff --git a/llvm/test/Transforms/InstCombine/pow_fp_int.ll b/llvm/test/Transforms/InstCombine/pow_fp_int.ll --- a/llvm/test/Transforms/InstCombine/pow_fp_int.ll +++ b/llvm/test/Transforms/InstCombine/pow_fp_int.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -instcombine -S < %s | FileCheck %s +; RUN: opt -mtriple unknown -instcombine -S < %s | FileCheck %s ; PR42190 diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll --- a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll @@ -1,4 +1,5 @@ -; RUN: opt -S < %s -instcombine -instcombine-infinite-loop-threshold=2 | FileCheck %s +; RUN: opt -S < %s -mtriple=unknown -instcombine -instcombine-infinite-loop-threshold=2 | FileCheck -check-prefixes=CHECK,CHECK32 %s +; RUN: opt -S < %s -mtriple=msp430 -instcombine -instcombine-infinite-loop-threshold=2 | FileCheck -check-prefixes=CHECK,CHECK16 %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32" @G = constant [3 x i8] c"%s\00" ; <[3 x i8]*> [#uses=1] @@ -188,14 +189,33 @@ ret double %y } define double @fake_ldexp(i32 %x) { -; CHECK-LABEL: @fake_ldexp( -; CHECK-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 %x) -; CHECK-NEXT: ret double [[Z]] +; CHECK32-LABEL: @fake_ldexp( +; CHECK32-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 %x) +; CHECK32-NEXT: ret double [[Z]] + +; CHECK16-LABEL: @fake_ldexp( +; CHECK16-NEXT: [[Y:%.*]] = sitofp i32 %x to double +; CHECK16-NEXT: [[Z:%.*]] = call inreg double @exp2(double [[Y]]) +; CHECK16-NEXT: ret double [[Z]] %y = sitofp i32 %x to double %z = call inreg double @exp2(double %y) ret double %z } +define double @fake_ldexp_16(i16 %x) { +; CHECK32-LABEL: @fake_ldexp_16( +; CHECK32-NEXT: [[Y:%.*]] = sext i16 %x to i32 +; CHECK32-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 [[Y]]) +; CHECK32-NEXT: ret double [[Z]] + +; CHECK16-LABEL: @fake_ldexp_16( +; CHECK16-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i16 %x) +; CHECK16-NEXT: ret double [[Z]] + + %y = sitofp i16 %x to double + %z = call inreg double @exp2(double %y) + ret double %z +} attributes #0 = { nobuiltin }