mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
[SimplifyLibCalls] Take size of int into consideration when emitting ldexp/ldexpf
When rewriting powf(2.0, itofp(x)) -> ldexpf(1.0, x) exp2(sitofp(x)) -> ldexp(1.0, sext(x)) exp2(uitofp(x)) -> ldexp(1.0, zext(x)) the wrong type was used for the second argument in the ldexp/ldexpf libc call, for target architectures with 16 bit "int" type. The transform incorrectly used a bitcasted function pointer with a 32-bit argument when emitting the ldexp/ldexpf call for such targets. The fault is solved by using the correct function prototype in the call, by asking TargetLibraryInfo about the size of "int". TargetLibraryInfo by default derives the size of the int type by assuming that it is 16 bits for 16-bit architectures, and 32 bits otherwise. If this isn't true for a target it should be possible to override that default in the TargetLibraryInfo initializer. Differential Revision: https://reviews.llvm.org/D99438
This commit is contained in:
parent
8a32a3f1a2
commit
1f980badb2
@ -52,6 +52,7 @@ class TargetLibraryInfoImpl {
|
||||
llvm::DenseMap<unsigned, std::string> CustomNames;
|
||||
static StringLiteral const StandardNames[NumLibFuncs];
|
||||
bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param;
|
||||
unsigned SizeOfInt;
|
||||
|
||||
enum AvailabilityState {
|
||||
StandardName = 3, // (memset to all ones)
|
||||
@ -189,6 +190,16 @@ public:
|
||||
/// 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 @@ public:
|
||||
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
|
||||
|
@ -151,6 +151,11 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
|
||||
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 Triple &T) {
|
||||
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 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI)
|
||||
: 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 @@ TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoI
|
||||
ShouldExtI32Param = TLI.ShouldExtI32Param;
|
||||
ShouldExtI32Return = TLI.ShouldExtI32Return;
|
||||
ShouldSignExtI32Param = TLI.ShouldSignExtI32Param;
|
||||
SizeOfInt = TLI.SizeOfInt;
|
||||
memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray));
|
||||
return *this;
|
||||
}
|
||||
@ -670,6 +678,7 @@ TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(TargetLibraryInfoImpl &&
|
||||
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 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
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:
|
||||
|
@ -1424,17 +1424,18 @@ static Value *getPow(Value *InnerChain[33], unsigned Exp, IRBuilderBase &B) {
|
||||
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<SIToFPInst>(I2F) || isa<UIToFPInst>(I2F)) {
|
||||
Value *Op = cast<Instruction>(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<SIToFPInst>(I2F)))
|
||||
return isa<SIToFPInst>(I2F) ? B.CreateSExt(Op, B.getInt32Ty())
|
||||
: B.CreateZExt(Op, B.getInt32Ty());
|
||||
if (BitWidth < DstWidth ||
|
||||
(BitWidth == DstWidth && isa<SIToFPInst>(I2F)))
|
||||
return isa<SIToFPInst>(I2F) ? B.CreateSExt(Op, B.getIntNTy(DstWidth))
|
||||
: B.CreateZExt(Op, B.getIntNTy(DstWidth));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -1524,7 +1525,7 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) {
|
||||
if (match(Base, m_SpecificFP(2.0)) &&
|
||||
(isa<SIToFPInst>(Expo) || isa<UIToFPInst>(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 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) {
|
||||
|
||||
// powf(x, itofp(y)) -> powi(x, y)
|
||||
if (AllowApprox && (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(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 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) {
|
||||
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<SIToFPInst>(Op) || isa<UIToFPInst>(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);
|
||||
|
@ -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 @@ declare float @exp2f(float)
|
||||
; 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 double @llvm.exp2.f64(double)
|
||||
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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 @@ define double @fake_exp2(double %x) {
|
||||
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 }
|
||||
|
Loading…
Reference in New Issue
Block a user