https://github.com/arsenm created 
https://github.com/llvm/llvm-project/pull/171977

Reapply "InstCombine: Fold ldexp with constant exponent to fmul" (#171895)

This reverts commit 757c5b3bc70c6f0b55afa310f3fab07a4985e8b8.

Reapply with the transform skipped if the scaling overflows or underflows.

Skip if overflow or underflow

>From 81e746edba5fae4bda3152ca8ce61771cc137b69 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Thu, 11 Dec 2025 22:17:15 +0100
Subject: [PATCH 1/2] Reapply "InstCombine: Fold ldexp with constant exponent
 to fmul" (#171895)

This reverts commit 757c5b3bc70c6f0b55afa310f3fab07a4985e8b8.

Reapply with the transform skipped if the scaling overflows or underflows.
---
 .../InstCombine/InstCombineCalls.cpp          | 13 +++++
 .../InstCombine/fold-select-fmul-if-zero.ll   | 10 +---
 llvm/test/Transforms/InstCombine/ldexp.ll     | 52 +++++++++----------
 3 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 85602a5a7575a..b498bafb3caaa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3089,6 +3089,19 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst 
&CI) {
     // exponent. Also could broaden sign check to cover == 0 case.
     Value *Src = II->getArgOperand(0);
     Value *Exp = II->getArgOperand(1);
+
+    uint64_t ConstExp;
+    if (match(Exp, m_ConstantInt(ConstExp))) {
+      // ldexp(x, K) -> fmul x, 2^K
+      const fltSemantics &FPTy =
+          Src->getType()->getScalarType()->getFltSemantics();
+      Constant *FPConst =
+          ConstantFP::get(Src->getType(), scalbn(APFloat::getOne(FPTy),
+                                                 static_cast<int>(ConstExp),
+                                                 
APFloat::rmNearestTiesToEven));
+      return BinaryOperator::CreateFMulFMF(Src, FPConst, II);
+    }
+
     Value *InnerSrc;
     Value *InnerExp;
     if (match(Src, m_OneUse(m_Intrinsic<Intrinsic::ldexp>(
diff --git a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll 
b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll
index 1ba7005f99e3d..4495b0f26042b 100644
--- a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll
+++ b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll
@@ -49,10 +49,7 @@ define float @fmul_by_32_if_0_oeq_zero_f32(float %x) {
 
 define float @ldexp_by_5_if_0_oeq_zero_f32(float %x) {
 ; CHECK-LABEL: @ldexp_by_5_if_0_oeq_zero_f32(
-; CHECK-NEXT:    [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SCALED_X:%.*]] = call float @llvm.ldexp.f32.i32(float 
[[X]], i32 5)
-; CHECK-NEXT:    [[SCALED_IF_DENORMAL:%.*]] = select i1 [[X_IS_ZERO]], float 
[[SCALED_X]], float [[X]]
-; CHECK-NEXT:    ret float [[SCALED_IF_DENORMAL]]
+; CHECK-NEXT:    ret float [[X:%.*]]
 ;
   %x.is.zero = fcmp oeq float %x, 0.0
   %scaled.x = call float @llvm.ldexp.f32.i32(float %x, i32 5)
@@ -62,10 +59,7 @@ define float @ldexp_by_5_if_0_oeq_zero_f32(float %x) {
 
 define <2 x float> @ldexp_by_5_if_0_oeq_zero_v2f32(<2 x float> %x) {
 ; CHECK-LABEL: @ldexp_by_5_if_0_oeq_zero_v2f32(
-; CHECK-NEXT:    [[X_IS_ZERO:%.*]] = fcmp oeq <2 x float> [[X:%.*]], 
zeroinitializer
-; CHECK-NEXT:    [[SCALED_X:%.*]] = call <2 x float> 
@llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> splat (i32 5))
-; CHECK-NEXT:    [[SCALED_IF_DENORMAL:%.*]] = select <2 x i1> [[X_IS_ZERO]], 
<2 x float> [[SCALED_X]], <2 x float> [[X]]
-; CHECK-NEXT:    ret <2 x float> [[SCALED_IF_DENORMAL]]
+; CHECK-NEXT:    ret <2 x float> [[SCALED_IF_DENORMAL:%.*]]
 ;
   %x.is.zero = fcmp oeq <2 x float> %x, zeroinitializer
   %scaled.x = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x 
i32> <i32 5, i32 5>)
diff --git a/llvm/test/Transforms/InstCombine/ldexp.ll 
b/llvm/test/Transforms/InstCombine/ldexp.ll
index 72997eef4fd6d..d9e4ca4753463 100644
--- a/llvm/test/Transforms/InstCombine/ldexp.ll
+++ b/llvm/test/Transforms/InstCombine/ldexp.ll
@@ -444,7 +444,7 @@ define float @ldexp_ldexp_different_exp_type(float %x, i32 
%a, i64 %b) {
 define float @ldexp_ldexp_constants(float %x) {
 ; CHECK-LABEL: define float @ldexp_ldexp_constants
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float 
[[X]], i32 32)
+; CHECK-NEXT:    [[LDEXP1:%.*]] = fmul reassoc float [[X]], 0x41F0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP1]]
 ;
   %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -455,7 +455,7 @@ define float @ldexp_ldexp_constants(float %x) {
 define float @ldexp_ldexp_constants_nsz(float %x) {
 ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP1:%.*]] = call reassoc nsz float 
@llvm.ldexp.f32.i32(float [[X]], i32 32)
+; CHECK-NEXT:    [[LDEXP1:%.*]] = fmul reassoc nsz float [[X]], 
0x41F0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP1]]
 ;
   %ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -466,7 +466,7 @@ define float @ldexp_ldexp_constants_nsz(float %x) {
 define float @ldexp_ldexp_constants_nsz0(float %x) {
 ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz0
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP1:%.*]] = call reassoc nsz float 
@llvm.ldexp.f32.i32(float [[X]], i32 32)
+; CHECK-NEXT:    [[LDEXP1:%.*]] = fmul reassoc float [[X]], 0x41F0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP1]]
 ;
   %ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -477,7 +477,7 @@ define float @ldexp_ldexp_constants_nsz0(float %x) {
 define float @ldexp_ldexp_constants_nsz1(float %x) {
 ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz1
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP1:%.*]] = call reassoc nsz float 
@llvm.ldexp.f32.i32(float [[X]], i32 32)
+; CHECK-NEXT:    [[LDEXP1:%.*]] = fmul reassoc nsz float [[X]], 
0x41F0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP1]]
 ;
   %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -641,7 +641,7 @@ define float @ldexp_ldexp_0(float %x, i32 %y) {
 define float @ldexp_neg150(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg150
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -150)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0.000000e+00
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -150)
@@ -651,7 +651,7 @@ define float @ldexp_neg150(float %x) {
 define float @ldexp_neg149(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg149
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -149)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x36A0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -149)
@@ -661,7 +661,7 @@ define float @ldexp_neg149(float %x) {
 define float @ldexp_neg148(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg148
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -148)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x36B0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -148)
@@ -671,7 +671,7 @@ define float @ldexp_neg148(float %x) {
 define float @ldexp_neg127(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg127
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -127)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x3800000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -127)
@@ -681,7 +681,7 @@ define float @ldexp_neg127(float %x) {
 define float @ldexp_neg126(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg126
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -126)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x3810000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -126)
@@ -691,7 +691,7 @@ define float @ldexp_neg126(float %x) {
 define float @ldexp_neg125(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg125
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -125)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x3820000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -125)
@@ -701,7 +701,7 @@ define float @ldexp_neg125(float %x) {
 define float @ldexp_neg16(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg16
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -16)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x3EF0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -16)
@@ -711,7 +711,7 @@ define float @ldexp_neg16(float %x) {
 define float @ldexp_neg8(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg8
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -8)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 3.906250e-03
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -8)
@@ -721,7 +721,7 @@ define float @ldexp_neg8(float %x) {
 define float @ldexp_neg4(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg4
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -4)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 6.250000e-02
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -4)
@@ -731,7 +731,7 @@ define float @ldexp_neg4(float %x) {
 define float @ldexp_neg2(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg2
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -2)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 2.500000e-01
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -2)
@@ -741,7 +741,7 @@ define float @ldexp_neg2(float %x) {
 define float @ldexp_neg1(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg1
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -1)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 5.000000e-01
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -1)
@@ -760,7 +760,7 @@ define float @ldexp_0(float %x) {
 define float @ldexp_1(float %x) {
 ; CHECK-LABEL: define float @ldexp_1
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 1)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 2.000000e+00
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 1)
@@ -770,7 +770,7 @@ define float @ldexp_1(float %x) {
 define float @ldexp_2(float %x) {
 ; CHECK-LABEL: define float @ldexp_2
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 2)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 4.000000e+00
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 2)
@@ -780,7 +780,7 @@ define float @ldexp_2(float %x) {
 define float @ldexp_3(float %x) {
 ; CHECK-LABEL: define float @ldexp_3
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 3)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 8.000000e+00
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 3)
@@ -790,7 +790,7 @@ define float @ldexp_3(float %x) {
 define float @ldexp_10(float %x) {
 ; CHECK-LABEL: define float @ldexp_10
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 10)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 1.024000e+03
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 10)
@@ -800,7 +800,7 @@ define float @ldexp_10(float %x) {
 define float @ldexp_125(float %x) {
 ; CHECK-LABEL: define float @ldexp_125
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 125)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x47C0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 125)
@@ -810,7 +810,7 @@ define float @ldexp_125(float %x) {
 define float @ldexp_126(float %x) {
 ; CHECK-LABEL: define float @ldexp_126
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 126)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x47D0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 126)
@@ -820,7 +820,7 @@ define float @ldexp_126(float %x) {
 define float @ldexp_127(float %x) {
 ; CHECK-LABEL: define float @ldexp_127
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 127)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0x47E0000000000000
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 127)
@@ -910,7 +910,7 @@ define float @ldexp_neg260(float %x) {
 define <2 x float> @ldexp_3_vector(<2 x float> %x) {
 ; CHECK-LABEL: define <2 x float> @ldexp_3_vector
 ; CHECK-SAME: (<2 x float> [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x 
float> [[X]], <2 x i32> splat (i32 3))
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul <2 x float> [[X]], splat (float 
8.000000e+00)
 ; CHECK-NEXT:    ret <2 x float> [[LDEXP]]
 ;
   %ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> 
<i32 3, i32 3>)
@@ -940,7 +940,7 @@ define <2 x float> @ldexp_3_4_vector(<2 x float> %x) {
 define float @ldexp_2_flags(float %x) {
 ; CHECK-LABEL: define float @ldexp_2_flags
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call nsz contract float 
@llvm.ldexp.f32.i32(float [[X]], i32 2)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul nsz contract float [[X]], 4.000000e+00
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call contract nsz float @llvm.ldexp.f32.i32(float %x, i32 2)
@@ -950,7 +950,7 @@ define float @ldexp_2_flags(float %x) {
 define float @ldexp_metadata(float %x) {
 ; CHECK-LABEL: define float @ldexp_metadata
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 2), !foo [[META2:![0-9]+]]
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 4.000000e+00
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 2), !foo !2
@@ -960,7 +960,7 @@ define float @ldexp_metadata(float %x) {
 define float @ldexp_8_contractable(float %x, float %y) {
 ; CHECK-LABEL: define float @ldexp_8_contractable
 ; CHECK-SAME: (float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = call contract float @llvm.ldexp.f32.i32(float 
[[X]], i32 2)
+; CHECK-NEXT:    [[LDEXP:%.*]] = fmul contract float [[X]], 4.000000e+00
 ; CHECK-NEXT:    [[FADD:%.*]] = fadd contract float [[LDEXP]], [[Y]]
 ; CHECK-NEXT:    ret float [[FADD]]
 ;

>From cf1c1bf730b747f25f31bb0f9f28aa8c6c0029fd Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Thu, 11 Dec 2025 22:17:52 +0100
Subject: [PATCH 2/2] Skip if overflow or underflow

---
 .../lib/Transforms/InstCombine/InstCombineCalls.cpp | 13 ++++++++-----
 llvm/test/Transforms/InstCombine/ldexp.ll           |  2 +-
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index b498bafb3caaa..04796807ea557 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3095,11 +3095,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst 
&CI) {
       // ldexp(x, K) -> fmul x, 2^K
       const fltSemantics &FPTy =
           Src->getType()->getScalarType()->getFltSemantics();
-      Constant *FPConst =
-          ConstantFP::get(Src->getType(), scalbn(APFloat::getOne(FPTy),
-                                                 static_cast<int>(ConstExp),
-                                                 
APFloat::rmNearestTiesToEven));
-      return BinaryOperator::CreateFMulFMF(Src, FPConst, II);
+
+      APFloat Scaled = scalbn(APFloat::getOne(FPTy), 
static_cast<int>(ConstExp),
+                              APFloat::rmNearestTiesToEven);
+      if (!Scaled.isZero() && !Scaled.isInfinity()) {
+        // Skip overflow and underflow cases.
+        Constant *FPConst = ConstantFP::get(Src->getType(), Scaled);
+        return BinaryOperator::CreateFMulFMF(Src, FPConst, II);
+      }
     }
 
     Value *InnerSrc;
diff --git a/llvm/test/Transforms/InstCombine/ldexp.ll 
b/llvm/test/Transforms/InstCombine/ldexp.ll
index d9e4ca4753463..9586fffe9956c 100644
--- a/llvm/test/Transforms/InstCombine/ldexp.ll
+++ b/llvm/test/Transforms/InstCombine/ldexp.ll
@@ -641,7 +641,7 @@ define float @ldexp_ldexp_0(float %x, i32 %y) {
 define float @ldexp_neg150(float %x) {
 ; CHECK-LABEL: define float @ldexp_neg150
 ; CHECK-SAME: (float [[X:%.*]]) {
-; CHECK-NEXT:    [[LDEXP:%.*]] = fmul float [[X]], 0.000000e+00
+; CHECK-NEXT:    [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], 
i32 -150)
 ; CHECK-NEXT:    ret float [[LDEXP]]
 ;
   %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -150)

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to