[llvm] [ValueTracking] Compute knownbits from known fp classes (PR #86409)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 22 00:21:41 PDT 2024


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/86409

>From 682ac8cb267035a4ba638a7de6805c1a266dd3e8 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 11 Apr 2024 19:56:13 +0800
Subject: [PATCH 1/5] [ValueTracking] Add pre-commit tests. NFC.

---
 .../test/Transforms/InstCombine/known-bits.ll | 180 ++++++++++++++++++
 1 file changed, 180 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 8b4249b2c25a92..8fa42b6075bec7 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -1374,5 +1374,185 @@ define i8 @nonzero_reduce_xor_vscale_odd(<vscale x 3 x i8> %xx) {
   ret i8 %r
 }
 
+define i1 @test_sign_pos(float %x) {
+; CHECK-LABEL: @test_sign_pos(
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[FABS]] to i32
+; CHECK-NEXT:    [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1
+; CHECK-NEXT:    ret i1 [[SIGN]]
+;
+  %fabs = call float @llvm.fabs.f32(float %x)
+  %y = bitcast float %fabs to i32
+  %sign = icmp sgt i32 %y, -1
+  ret i1 %sign
+}
+
+define i1 @test_sign_neg(float %x) {
+; CHECK-LABEL: @test_sign_neg(
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[FNABS:%.*]] = fneg float [[FABS]]
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[FNABS]] to i32
+; CHECK-NEXT:    [[SIGN:%.*]] = icmp slt i32 [[Y]], 0
+; CHECK-NEXT:    ret i1 [[SIGN]]
+;
+  %fabs = call float @llvm.fabs.f32(float %x)
+  %fnabs = fneg float %fabs
+  %y = bitcast float %fnabs to i32
+  %sign = icmp slt i32 %y, 0
+  ret i1 %sign
+}
+
+define <2 x i1> @test_sign_pos_vec(<2 x float> %x) {
+; CHECK-LABEL: @test_sign_pos_vec(
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = bitcast <2 x float> [[FABS]] to <2 x i32>
+; CHECK-NEXT:    [[SIGN:%.*]] = icmp slt <2 x i32> [[Y]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[SIGN]]
+;
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x)
+  %y = bitcast <2 x float> %fabs to <2 x i32>
+  %sign = icmp slt <2 x i32> %y, zeroinitializer
+  ret <2 x i1> %sign
+}
+
+define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_only(
+; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[AND:%.*]] = bitcast float [[TMP1]] to i32
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2147483647
+  ret i32 %and
+}
+
+define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) {
+; CHECK-LABEL: @test_zero_only(
+; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[AND:%.*]] = bitcast float [[TMP1]] to i32
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2147483647
+  ret i32 %and
+}
+
+define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) {
+; CHECK-LABEL: @test_zero_only_non_ieee(
+; CHECK-NEXT:    [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[X:%.*]])
+; CHECK-NEXT:    [[AND:%.*]] = bitcast x86_fp80 [[TMP1]] to i80
+; CHECK-NEXT:    ret i80 [[AND]]
+;
+  %y = bitcast x86_fp80 %x to i80
+  %and = and i80 %y, 604462909807314587353087
+  ret i80 %and
+}
+
+define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_nan_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2130706432
+  ret i32 %and
+}
+
+define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
+; CHECK-LABEL: @test_sub_zero_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 2130706432
+  ret i32 %and
+}
+
+define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) {
+; CHECK-LABEL: @test_inf_zero_only(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 16777215
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 16777215
+  ret i32 %and
+}
+
+define i1 @test_simplify_icmp(i32 %x) {
+; CHECK-LABEL: @test_simplify_icmp(
+; CHECK-NEXT:    [[CAST1:%.*]] = uitofp i32 [[X:%.*]] to double
+; CHECK-NEXT:    [[CAST2:%.*]] = bitcast double [[CAST1]] to i64
+; CHECK-NEXT:    [[MASK:%.*]] = and i64 [[CAST2]], -140737488355328
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[MASK]], -1970324836974592
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %cast1 = uitofp i32 %x to double
+  %cast2 = bitcast double %cast1 to i64
+  %mask = and i64 %cast2, -140737488355328
+  %cmp = icmp eq i64 %mask, -1970324836974592
+  ret i1 %cmp
+}
+
+define i16 @test_simplify_mask(i32 %ui, float %x) {
+; CHECK-LABEL: @test_simplify_mask(
+; CHECK-NEXT:    [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast float [[CONV]] to i32
+; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[CAST]], 16
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[SHR]] to i16
+; CHECK-NEXT:    [[AND:%.*]] = and i16 [[TRUNC]], -32768
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint i16 [[AND]], 31744
+; CHECK-NEXT:    ret i16 [[OR]]
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i16 0
+;
+  %conv = uitofp i32 %ui to float
+  %cmp = fcmp olt float %x, %conv
+  br i1 %cmp, label %if.else, label %if.end
+
+if.end:
+  %cast = bitcast float %conv to i32
+  %shr = lshr i32 %cast, 16
+  %trunc = trunc i32 %shr to i16
+  %and = and i16 %trunc, -32768
+  %or = or disjoint i16 %and, 31744
+  ret i16 %or
+
+if.else:
+  ret i16 0
+}
+
+; TODO: %cmp always evaluates to false
+
+define i1 @test_simplify_icmp2(double %x) {
+; CHECK-LABEL: @test_simplify_icmp2(
+; CHECK-NEXT:    [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[COND:%.*]] = fcmp oeq double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[CAST]], 3458764513820540928
+; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i1 false
+;
+  %abs = tail call double @llvm.fabs.f64(double %x)
+  %cond = fcmp oeq double %abs, 0x7FF0000000000000
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %cast = bitcast double %x to i64
+  %cmp = icmp eq i64 %cast, 3458764513820540928
+  ret i1 %cmp
+
+if.else:
+  ret i1 false
+}
+
 declare void @use(i1)
 declare void @sink(i8)

>From 6f5ac7466d4cd33436d19d768cc0c770366144c7 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 11 Apr 2024 20:05:09 +0800
Subject: [PATCH 2/5] [ValueTracking] Infer knownbits from fp classes

---
 llvm/include/llvm/Analysis/ValueTracking.h    |  5 ++
 llvm/lib/Analysis/ValueTracking.cpp           | 34 +++++++++++++
 .../AMDGPU/amdgpu-simplify-libcall-pow.ll     | 14 +++---
 .../AMDGPU/amdgpu-simplify-libcall-pown.ll    | 12 ++---
 llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll | 10 ++--
 .../test/Transforms/InstCombine/known-bits.ll | 49 ++++---------------
 6 files changed, 67 insertions(+), 57 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index bab7c8868532db..4181adbda5a65b 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -259,6 +259,11 @@ struct KnownFPClass {
     return (KnownFPClasses & Mask) == fcNone;
   }
 
+  /// Return true if it's known this can only be one of the mask entries.
+  bool isKnownOnly(FPClassTest Mask) const {
+    return (KnownFPClasses & ~Mask) == fcNone;
+  }
+
   bool isUnknown() const {
     return KnownFPClasses == fcAllFlags && !SignBit;
   }
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c038f7eaabbb67..30adb9c32e3bfa 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1111,6 +1111,40 @@ static void computeKnownBitsFromOperator(const Operator *I,
       break;
     }
 
+    Value *V;
+    // Handle bitcast from floating point to integer.
+    if (match(const_cast<Operator *>(I), m_ElementWiseBitCast(m_Value(V))) &&
+        V->getType()->isFPOrFPVectorTy()) {
+      KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q);
+      if (Result.SignBit) {
+        if (*Result.SignBit)
+          Known.makeNegative();
+        else
+          Known.makeNonNegative();
+      }
+
+      Type *FPType = V->getType()->getScalarType();
+      if (FPType->isIEEELikeFPTy()) {
+        int MantissaWidth = FPType->getFPMantissaWidth();
+        if (MantissaWidth != -1) {
+          if (Result.isKnownOnly(fcInf)) {
+            Known.Zero.setLowBits(MantissaWidth);
+            Known.One.setBits(MantissaWidth, BitWidth - 1);
+          } else if (Result.isKnownOnly(fcZero)) {
+            Known.Zero.setLowBits(BitWidth - 1);
+          } else if (Result.isKnownOnly(fcInf | fcNan)) {
+            Known.One.setBits(MantissaWidth, BitWidth - 1);
+          } else if (Result.isKnownOnly(fcSubnormal | fcZero)) {
+            Known.Zero.setBits(MantissaWidth, BitWidth - 1);
+          } else if (Result.isKnownOnly(fcInf | fcZero)) {
+            Known.Zero.setLowBits(MantissaWidth);
+          }
+        }
+      }
+
+      break;
+    }
+
     // Handle cast from vector integer type to scalar or vector integer.
     auto *SrcVecTy = dyn_cast<FixedVectorType>(SrcTy);
     if (!SrcVecTy || !SrcVecTy->getElementType()->isIntegerTy() ||
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll
index c4bd4bc126f735..5db25a59d33fc9 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll
@@ -2216,7 +2216,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp(float %x, i32 %y)
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float
 ; CHECK-NEXT:    ret float [[TMP5]]
 ;
@@ -2304,7 +2304,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp(float %x, i32 %y)
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float
 ; CHECK-NEXT:    ret float [[TMP5]]
 ;
@@ -2353,7 +2353,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp_i256(float %x, i2
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float
 ; CHECK-NEXT:    ret float [[TMP5]]
 ;
@@ -2376,7 +2376,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp_i256(float %x, i2
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float
 ; CHECK-NEXT:    ret float [[TMP5]]
 ;
@@ -2399,7 +2399,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_sitofp(<2 x floa
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32>
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32>
-; CHECK-NEXT:    [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float>
 ; CHECK-NEXT:    ret <2 x float> [[TMP5]]
 ;
@@ -2448,7 +2448,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_uitofp(<2 x floa
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32>
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32>
-; CHECK-NEXT:    [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float>
 ; CHECK-NEXT:    ret <2 x float> [[TMP5]]
 ;
@@ -2560,7 +2560,7 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float
 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]]
 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float
 ; CHECK-NEXT:    ret float [[TMP5]]
 ;
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll
index 8ddaf243db92c4..e298226ee7ccd8 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll
@@ -680,7 +680,7 @@ define float @test_pown_afn_nnan_ninf_f32(float %x, i32 %y) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
 ; CHECK-NEXT:    ret float [[TMP3]]
 ;
@@ -703,7 +703,7 @@ define <2 x float> @test_pown_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y)
 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[X]] to <2 x i32>
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP0]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32>
-; CHECK-NEXT:    [[TMP2:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP1]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float>
 ; CHECK-NEXT:    ret <2 x float> [[TMP3]]
 ;
@@ -772,7 +772,7 @@ define half @test_pown_afn_nnan_ninf_f16(half %x, i32 %y) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast half [[X]] to i16
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i16 [[__YEVEN]], [[TMP0]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast half [[__EXP2]] to i16
-; CHECK-NEXT:    [[TMP2:%.*]] = or i16 [[__POW_SIGN]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or disjoint i16 [[__POW_SIGN]], [[TMP1]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half
 ; CHECK-NEXT:    ret half [[TMP3]]
 ;
@@ -795,7 +795,7 @@ define <2 x half> @test_pown_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x half> [[X]] to <2 x i16>
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and <2 x i16> [[__YEVEN]], [[TMP0]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x half> [[__EXP2]] to <2 x i16>
-; CHECK-NEXT:    [[TMP2:%.*]] = or <2 x i16> [[__POW_SIGN]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or disjoint <2 x i16> [[__POW_SIGN]], [[TMP1]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x i16> [[TMP2]] to <2 x half>
 ; CHECK-NEXT:    ret <2 x half> [[TMP3]]
 ;
@@ -829,7 +829,7 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 {
 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
 ; CHECK-NEXT:    ret float [[TMP3]]
 ;
@@ -1075,7 +1075,7 @@ define float @test_pown_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf
 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast float [[X]] to i32
 ; CHECK-NEXT:    [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32
-; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
 ; CHECK-NEXT:    ret float [[TMP3]]
 ;
diff --git a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll
index 204c8140d3f17d..54ca33401ccf4d 100644
--- a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll
+++ b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll
@@ -360,7 +360,7 @@ declare half @_Z4pownDhi(half, i32)
 ; GCN-NATIVE: %0 = bitcast half %x to i16
 ; GCN-NATIVE: %__pow_sign = and i16 %__yeven, %0
 ; GCN-NATIVE: %1 = bitcast half %__exp2 to i16
-; GCN-NATIVE: %2 = or i16 %__pow_sign, %1
+; GCN-NATIVE: %2 = or disjoint i16 %__pow_sign, %1
 ; GCN-NATIVE: %3 = bitcast i16 %2 to half
 define half @test_pown_f16(half %x, i32 %y) {
 entry:
@@ -378,7 +378,7 @@ declare float @_Z4pownfi(float, i32)
 ; GCN: %[[r0:.*]] = bitcast float %tmp to i32
 ; GCN: %__pow_sign = and i32 %[[r0]], -2147483648
 ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32
-; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]]
+; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]]
 ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4
 define amdgpu_kernel void @test_pow(ptr addrspace(1) nocapture %a) {
 entry:
@@ -414,7 +414,7 @@ entry:
 ; GCN: %[[r0:.*]] = bitcast float %tmp to i32
 ; GCN: %__pow_sign = and i32 %__yeven, %[[r0]]
 ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32
-; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]]
+; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]]
 ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4
 define amdgpu_kernel void @test_pown(ptr addrspace(1) nocapture %a) {
 entry:
@@ -438,7 +438,7 @@ declare <2 x half> @_Z3powDv2_DhS_(<2 x half>, <2 x half>)
 ; GCN: %1 = bitcast half %x to i16
 ; GCN: %__pow_sign = and i16 %1, -32768
 ; GCN: %2 = bitcast half %__exp2 to i16
-; GCN: %3 = or i16 %__pow_sign, %2
+; GCN: %3 = or disjoint i16 %__pow_sign, %2
 ; GCN: %4 = bitcast i16 %3 to half
 define half @test_pow_fast_f16__y_13(half %x) {
   %powr = tail call fast half @_Z3powDhDh(half %x, half 13.0)
@@ -453,7 +453,7 @@ define half @test_pow_fast_f16__y_13(half %x) {
 ; GCN: %1 = bitcast <2 x half> %x to <2 x i16>
 ; GCN: %__pow_sign = and <2 x i16> %1, <i16 -32768, i16 -32768>
 ; GCN: %2 = bitcast <2 x half> %__exp2 to <2 x i16>
-; GCN: %3 = or <2 x i16> %__pow_sign, %2
+; GCN: %3 = or disjoint <2 x i16> %__pow_sign, %2
 ; GCN: %4 = bitcast <2 x i16> %3 to <2 x half>
 define <2 x half> @test_pow_fast_v2f16__y_13(<2 x half> %x) {
   %powr = tail call fast <2 x half> @_Z3powDv2_DhS_(<2 x half> %x, <2 x half> <half 13.0, half 13.0>)
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 8fa42b6075bec7..e624d9c253ea41 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -1376,10 +1376,7 @@ define i8 @nonzero_reduce_xor_vscale_odd(<vscale x 3 x i8> %xx) {
 
 define i1 @test_sign_pos(float %x) {
 ; CHECK-LABEL: @test_sign_pos(
-; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[FABS]] to i32
-; CHECK-NEXT:    [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1
-; CHECK-NEXT:    ret i1 [[SIGN]]
+; CHECK-NEXT:    ret i1 true
 ;
   %fabs = call float @llvm.fabs.f32(float %x)
   %y = bitcast float %fabs to i32
@@ -1389,11 +1386,7 @@ define i1 @test_sign_pos(float %x) {
 
 define i1 @test_sign_neg(float %x) {
 ; CHECK-LABEL: @test_sign_neg(
-; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
-; CHECK-NEXT:    [[FNABS:%.*]] = fneg float [[FABS]]
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[FNABS]] to i32
-; CHECK-NEXT:    [[SIGN:%.*]] = icmp slt i32 [[Y]], 0
-; CHECK-NEXT:    ret i1 [[SIGN]]
+; CHECK-NEXT:    ret i1 true
 ;
   %fabs = call float @llvm.fabs.f32(float %x)
   %fnabs = fneg float %fabs
@@ -1404,10 +1397,7 @@ define i1 @test_sign_neg(float %x) {
 
 define <2 x i1> @test_sign_pos_vec(<2 x float> %x) {
 ; CHECK-LABEL: @test_sign_pos_vec(
-; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = bitcast <2 x float> [[FABS]] to <2 x i32>
-; CHECK-NEXT:    [[SIGN:%.*]] = icmp slt <2 x i32> [[Y]], zeroinitializer
-; CHECK-NEXT:    ret <2 x i1> [[SIGN]]
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
 ;
   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x)
   %y = bitcast <2 x float> %fabs to <2 x i32>
@@ -1417,9 +1407,7 @@ define <2 x i1> @test_sign_pos_vec(<2 x float> %x) {
 
 define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
 ; CHECK-LABEL: @test_inf_only(
-; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
-; CHECK-NEXT:    [[AND:%.*]] = bitcast float [[TMP1]] to i32
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 2130706432
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2147483647
@@ -1428,9 +1416,7 @@ define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
 
 define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) {
 ; CHECK-LABEL: @test_zero_only(
-; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
-; CHECK-NEXT:    [[AND:%.*]] = bitcast float [[TMP1]] to i32
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2147483647
@@ -1450,9 +1436,7 @@ define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) {
 
 define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
 ; CHECK-LABEL: @test_inf_nan_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 2130706432
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2130706432
@@ -1461,9 +1445,7 @@ define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
 
 define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
 ; CHECK-LABEL: @test_sub_zero_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2130706432
@@ -1472,9 +1454,7 @@ define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
 
 define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) {
 ; CHECK-LABEL: @test_inf_zero_only(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 16777215
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 16777215
@@ -1483,11 +1463,7 @@ define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) {
 
 define i1 @test_simplify_icmp(i32 %x) {
 ; CHECK-LABEL: @test_simplify_icmp(
-; CHECK-NEXT:    [[CAST1:%.*]] = uitofp i32 [[X:%.*]] to double
-; CHECK-NEXT:    [[CAST2:%.*]] = bitcast double [[CAST1]] to i64
-; CHECK-NEXT:    [[MASK:%.*]] = and i64 [[CAST2]], -140737488355328
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[MASK]], -1970324836974592
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %cast1 = uitofp i32 %x to double
   %cast2 = bitcast double %cast1 to i64
@@ -1502,12 +1478,7 @@ define i16 @test_simplify_mask(i32 %ui, float %x) {
 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.end:
-; CHECK-NEXT:    [[CAST:%.*]] = bitcast float [[CONV]] to i32
-; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[CAST]], 16
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[SHR]] to i16
-; CHECK-NEXT:    [[AND:%.*]] = and i16 [[TRUNC]], -32768
-; CHECK-NEXT:    [[OR:%.*]] = or disjoint i16 [[AND]], 31744
-; CHECK-NEXT:    ret i16 [[OR]]
+; CHECK-NEXT:    ret i16 31744
 ; CHECK:       if.else:
 ; CHECK-NEXT:    ret i16 0
 ;

>From a7a923343a9b2d9d2cd610d99fe3771271ebfa53 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 12 Apr 2024 16:19:13 +0800
Subject: [PATCH 3/5] [ValueTracking] Add additional tests. NFC.

---
 .../test/Transforms/InstCombine/known-bits.ll | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index e624d9c253ea41..c4bf7bf5a1b713 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -1384,6 +1384,29 @@ define i1 @test_sign_pos(float %x) {
   ret i1 %sign
 }
 
+define i1 @test_sign_pos_half(half %x) {
+; CHECK-LABEL: @test_sign_pos_half(
+; CHECK-NEXT:    ret i1 true
+;
+  %fabs = call half @llvm.fabs.f16(half %x)
+  %y = bitcast half %fabs to i16
+  %sign = icmp sgt i16 %y, -1
+  ret i1 %sign
+}
+
+define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) {
+; CHECK-LABEL: @test_sign_pos_half_non_elementwise(
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32
+; CHECK-NEXT:    [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1
+; CHECK-NEXT:    ret i1 [[SIGN]]
+;
+  %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x)
+  %y = bitcast <2 x half> %fabs to i32
+  %sign = icmp sgt i32 %y, -1
+  ret i1 %sign
+}
+
 define i1 @test_sign_neg(float %x) {
 ; CHECK-LABEL: @test_sign_neg(
 ; CHECK-NEXT:    ret i1 true
@@ -1414,6 +1437,26 @@ define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
   ret i32 %and
 }
 
+define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_only_bfloat(
+; CHECK-NEXT:    ret i16 32512
+;
+  %y = bitcast bfloat %x to i16
+  %and = and i16 %y, 32767
+  ret i16 %and
+}
+
+define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) {
+; CHECK-LABEL: @test_inf_only_ppc_fp128(
+; CHECK-NEXT:    [[Y:%.*]] = bitcast ppc_fp128 [[X:%.*]] to i128
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], 170141183460469231731687303715884105727
+; CHECK-NEXT:    ret i128 [[AND]]
+;
+  %y = bitcast ppc_fp128 %x to i128
+  %and = and i128 %y, 170141183460469231731687303715884105727
+  ret i128 %and
+}
+
 define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) {
 ; CHECK-LABEL: @test_zero_only(
 ; CHECK-NEXT:    ret i32 0

>From c089c591e9e8306ac30b9c14c5e3003d8cc0ea1c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 14 Apr 2024 01:44:45 +0800
Subject: [PATCH 4/5] [ValueTracking] Address review comments.

---
 llvm/include/llvm/IR/PatternMatch.h |  2 +-
 llvm/lib/Analysis/ValueTracking.cpp | 29 ++++++++++++++---------------
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 1b418a98545414..ab24e41e58a3a2 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1838,7 +1838,7 @@ template <typename Op_t> struct ElementWiseBitCast_match {
   ElementWiseBitCast_match(const Op_t &OpMatch) : Op(OpMatch) {}
 
   template <typename OpTy> bool match(OpTy *V) {
-    BitCastInst *I = dyn_cast<BitCastInst>(V);
+    auto *I = dyn_cast<BitCastInst>(V);
     if (!I)
       return false;
     Type *SrcType = I->getSrcTy();
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 30adb9c32e3bfa..ecbba433f41450 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1111,9 +1111,9 @@ static void computeKnownBitsFromOperator(const Operator *I,
       break;
     }
 
-    Value *V;
+    const Value *V;
     // Handle bitcast from floating point to integer.
-    if (match(const_cast<Operator *>(I), m_ElementWiseBitCast(m_Value(V))) &&
+    if (match(I, m_ElementWiseBitCast(m_Value(V))) &&
         V->getType()->isFPOrFPVectorTy()) {
       KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q);
       if (Result.SignBit) {
@@ -1126,19 +1126,18 @@ static void computeKnownBitsFromOperator(const Operator *I,
       Type *FPType = V->getType()->getScalarType();
       if (FPType->isIEEELikeFPTy()) {
         int MantissaWidth = FPType->getFPMantissaWidth();
-        if (MantissaWidth != -1) {
-          if (Result.isKnownOnly(fcInf)) {
-            Known.Zero.setLowBits(MantissaWidth);
-            Known.One.setBits(MantissaWidth, BitWidth - 1);
-          } else if (Result.isKnownOnly(fcZero)) {
-            Known.Zero.setLowBits(BitWidth - 1);
-          } else if (Result.isKnownOnly(fcInf | fcNan)) {
-            Known.One.setBits(MantissaWidth, BitWidth - 1);
-          } else if (Result.isKnownOnly(fcSubnormal | fcZero)) {
-            Known.Zero.setBits(MantissaWidth, BitWidth - 1);
-          } else if (Result.isKnownOnly(fcInf | fcZero)) {
-            Known.Zero.setLowBits(MantissaWidth);
-          }
+        assert(MantissaWidth != -1 && "Invalid mantissa width");
+        if (Result.isKnownOnly(fcInf)) {
+          Known.Zero.setLowBits(MantissaWidth);
+          Known.One.setBits(MantissaWidth, BitWidth - 1);
+        } else if (Result.isKnownOnly(fcZero)) {
+          Known.Zero.setLowBits(BitWidth - 1);
+        } else if (Result.isKnownOnly(fcInf | fcNan)) {
+          Known.One.setBits(MantissaWidth, BitWidth - 1);
+        } else if (Result.isKnownOnly(fcSubnormal | fcZero)) {
+          Known.Zero.setBits(MantissaWidth, BitWidth - 1);
+        } else if (Result.isKnownOnly(fcInf | fcZero)) {
+          Known.Zero.setLowBits(MantissaWidth);
         }
       }
 

>From 937a405347b1c3afc0229a0ef5a6f9749689a26e Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 22 Apr 2024 15:19:10 +0800
Subject: [PATCH 5/5] [InstCombine] Address review comments.

---
 llvm/include/llvm/Analysis/ValueTracking.h    |  5 --
 llvm/lib/Analysis/ValueTracking.cpp           | 55 +++++++++++++------
 .../test/Transforms/InstCombine/known-bits.ll | 38 +++++++++----
 3 files changed, 66 insertions(+), 32 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 4181adbda5a65b..bab7c8868532db 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -259,11 +259,6 @@ struct KnownFPClass {
     return (KnownFPClasses & Mask) == fcNone;
   }
 
-  /// Return true if it's known this can only be one of the mask entries.
-  bool isKnownOnly(FPClassTest Mask) const {
-    return (KnownFPClasses & ~Mask) == fcNone;
-  }
-
   bool isUnknown() const {
     return KnownFPClasses == fcAllFlags && !SignBit;
   }
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ecbba433f41450..3963b44533b862 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1115,31 +1115,52 @@ static void computeKnownBitsFromOperator(const Operator *I,
     // Handle bitcast from floating point to integer.
     if (match(I, m_ElementWiseBitCast(m_Value(V))) &&
         V->getType()->isFPOrFPVectorTy()) {
+      Type *FPType = V->getType()->getScalarType();
       KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q);
+      FPClassTest FPClasses = Result.KnownFPClasses;
+
+      if (Result.isKnownNever(fcNormal | fcSubnormal)) {
+        Known.Zero.setAllBits();
+        Known.One.setAllBits();
+
+        if (FPClasses & fcSNan) {
+          APInt Payload = APInt::getAllOnes(FPType->getScalarSizeInBits());
+          Known = Known.intersectWith(KnownBits::makeConstant(
+              APFloat::getSNaN(FPType->getFltSemantics()).bitcastToAPInt()));
+          Known = Known.intersectWith(KnownBits::makeConstant(
+              APFloat::getSNaN(FPType->getFltSemantics(), &Payload)
+                  .bitcastToAPInt()));
+        }
+
+        if (FPClasses & fcQNan) {
+          APInt Payload = APInt::getAllOnes(FPType->getScalarSizeInBits());
+          Known = Known.intersectWith(KnownBits::makeConstant(
+              APFloat::getQNaN(FPType->getFltSemantics()).bitcastToAPInt()));
+          Known = Known.intersectWith(KnownBits::makeConstant(
+              APFloat::getQNaN(FPType->getFltSemantics(), &Payload)
+                  .bitcastToAPInt()));
+        }
+
+        if (FPClasses & fcInf)
+          Known = Known.intersectWith(KnownBits::makeConstant(
+              APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt()));
+
+        if (FPClasses & fcZero)
+          Known = Known.intersectWith(KnownBits::makeConstant(
+              APInt::getZero(FPType->getScalarSizeInBits())));
+      }
+
       if (Result.SignBit) {
         if (*Result.SignBit)
           Known.makeNegative();
         else
           Known.makeNonNegative();
+      } else {
+        Known.Zero.clearSignBit();
+        Known.One.clearSignBit();
       }
 
-      Type *FPType = V->getType()->getScalarType();
-      if (FPType->isIEEELikeFPTy()) {
-        int MantissaWidth = FPType->getFPMantissaWidth();
-        assert(MantissaWidth != -1 && "Invalid mantissa width");
-        if (Result.isKnownOnly(fcInf)) {
-          Known.Zero.setLowBits(MantissaWidth);
-          Known.One.setBits(MantissaWidth, BitWidth - 1);
-        } else if (Result.isKnownOnly(fcZero)) {
-          Known.Zero.setLowBits(BitWidth - 1);
-        } else if (Result.isKnownOnly(fcInf | fcNan)) {
-          Known.One.setBits(MantissaWidth, BitWidth - 1);
-        } else if (Result.isKnownOnly(fcSubnormal | fcZero)) {
-          Known.Zero.setBits(MantissaWidth, BitWidth - 1);
-        } else if (Result.isKnownOnly(fcInf | fcZero)) {
-          Known.Zero.setLowBits(MantissaWidth);
-        }
-      }
+      assert(!Known.hasConflict() && "Bits known to be one AND zero?");
 
       break;
     }
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index c4bf7bf5a1b713..dd6b6a9ef25fa0 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -1430,7 +1430,7 @@ define <2 x i1> @test_sign_pos_vec(<2 x float> %x) {
 
 define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
 ; CHECK-LABEL: @test_inf_only(
-; CHECK-NEXT:    ret i32 2130706432
+; CHECK-NEXT:    ret i32 2139095040
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2147483647
@@ -1439,7 +1439,7 @@ define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) {
 
 define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) {
 ; CHECK-LABEL: @test_inf_only_bfloat(
-; CHECK-NEXT:    ret i16 32512
+; CHECK-NEXT:    ret i16 32640
 ;
   %y = bitcast bfloat %x to i16
   %and = and i16 %y, 32767
@@ -1448,9 +1448,7 @@ define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) {
 
 define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) {
 ; CHECK-LABEL: @test_inf_only_ppc_fp128(
-; CHECK-NEXT:    [[Y:%.*]] = bitcast ppc_fp128 [[X:%.*]] to i128
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], 170141183460469231731687303715884105727
-; CHECK-NEXT:    ret i128 [[AND]]
+; CHECK-NEXT:    ret i128 9218868437227405312
 ;
   %y = bitcast ppc_fp128 %x to i128
   %and = and i128 %y, 170141183460469231731687303715884105727
@@ -1468,9 +1466,7 @@ define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) {
 
 define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) {
 ; CHECK-LABEL: @test_zero_only_non_ieee(
-; CHECK-NEXT:    [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[X:%.*]])
-; CHECK-NEXT:    [[AND:%.*]] = bitcast x86_fp80 [[TMP1]] to i80
-; CHECK-NEXT:    ret i80 [[AND]]
+; CHECK-NEXT:    ret i80 0
 ;
   %y = bitcast x86_fp80 %x to i80
   %and = and i80 %y, 604462909807314587353087
@@ -1488,7 +1484,9 @@ define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) {
 
 define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
 ; CHECK-LABEL: @test_sub_zero_only(
-; CHECK-NEXT:    ret i32 0
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 2130706432
+; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 2130706432
@@ -1497,7 +1495,9 @@ define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) {
 
 define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) {
 ; CHECK-LABEL: @test_inf_zero_only(
-; CHECK-NEXT:    ret i32 0
+; CHECK-NEXT:    [[Y:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], 8388608
+; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %y = bitcast float %x to i32
   %and = and i32 %y, 16777215
@@ -1568,5 +1568,23 @@ if.else:
   ret i1 false
 }
 
+define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) {
+; CHECK-LABEL: @test_snan_only(
+; CHECK-NEXT:    ret i32 0
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 4194304
+  ret i32 %and
+}
+
+define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) {
+; CHECK-LABEL: @test_qnan_only(
+; CHECK-NEXT:    ret i32 4194304
+;
+  %y = bitcast float %x to i32
+  %and = and i32 %y, 4194304
+  ret i32 %and
+}
+
 declare void @use(i1)
 declare void @sink(i8)



More information about the llvm-commits mailing list