Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -928,30 +928,23 @@
     return replaceInstUsesWith(II, FCmp);
   }
 
-  // fp_class (nnan x), qnan|snan|other -> fp_class (nnan x), other
-  if ((Mask & fcNan) && isKnownNeverNaN(Src0, DL, &getTargetLibraryInfo())) {
-    II.setArgOperand(1, ConstantInt::get(Src1->getType(), Mask & ~fcNan));
-    return ⅈ
-  }
-
-  // fp_class (nnan x), ~(qnan|snan) -> true
-  if (Mask == (~fcNan & fcAllFlags) &&
-      isKnownNeverNaN(Src0, DL, &getTargetLibraryInfo())) {
-    return replaceInstUsesWith(II, ConstantInt::get(II.getType(), true));
-  }
+  KnownFPClass Known = computeKnownFPClass(
+      Src0, DL, Mask, 0, &getTargetLibraryInfo(), &AC, &II, &DT, &ORE);
 
+  // Clear test bits we know must be false from the source value.
+  // fp_class (nnan x), qnan|snan|other -> fp_class (nnan x), other
   // fp_class (ninf x), ninf|pinf|other -> fp_class (ninf x), other
-  if ((Mask & fcInf) &&
-      isKnownNeverInfinity(Src0, DL, &getTargetLibraryInfo())) {
-    II.setArgOperand(1, ConstantInt::get(Src1->getType(), Mask & ~fcInf));
+  if ((Mask & Known.KnownFPClasses) != Mask) {
+    II.setArgOperand(
+        1, ConstantInt::get(Src1->getType(), Mask & Known.KnownFPClasses));
     return ⅈ
   }
 
+  // If none of the tests which can return false are possible, fold to true.
+  // fp_class (nnan x), ~(qnan|snan) -> true
   // fp_class (ninf x), ~(ninf|pinf) -> true
-  if (Mask == (~fcInf & fcAllFlags) &&
-      isKnownNeverInfinity(Src0, DL, &getTargetLibraryInfo())) {
+  if (Mask == Known.KnownFPClasses)
     return replaceInstUsesWith(II, ConstantInt::get(II.getType(), true));
-  }
 
   return nullptr;
 }
Index: llvm/test/Transforms/InstCombine/is_fpclass.ll
===================================================================
--- llvm/test/Transforms/InstCombine/is_fpclass.ll
+++ llvm/test/Transforms/InstCombine/is_fpclass.ll
@@ -2465,8 +2465,7 @@
 
 define i1 @test_class_is_pzero_nozero_src(float nofpclass(zero) %arg) {
 ; CHECK-LABEL: @test_class_is_pzero_nozero_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 64)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 64)
   ret i1 %class
@@ -2474,8 +2473,7 @@
 
 define i1 @test_class_is_pzero_nopzero_src(float nofpclass(pzero) %arg) {
 ; CHECK-LABEL: @test_class_is_pzero_nopzero_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 64)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 64)
   ret i1 %class
@@ -2492,8 +2490,7 @@
 
 define i1 @test_class_is_nzero_nozero_src(float nofpclass(zero) %arg) {
 ; CHECK-LABEL: @test_class_is_nzero_nozero_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 32)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 32)
   ret i1 %class
@@ -2510,8 +2507,7 @@
 
 define i1 @test_class_is_nzero_nonzero_src(float nofpclass(nzero) %arg) {
 ; CHECK-LABEL: @test_class_is_nzero_nonzero_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 32)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 32)
   ret i1 %class
@@ -2519,7 +2515,7 @@
 
 define i1 @test_class_is_normal_or_zero_nozero_src(float nofpclass(zero) %arg) {
 ; CHECK-LABEL: @test_class_is_normal_or_zero_nozero_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 360)
+; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 264)
 ; CHECK-NEXT:    ret i1 [[CLASS]]
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 360)
@@ -2616,8 +2612,7 @@
 
 define i1 @test_class_is_subnormal_nosub_src(float nofpclass(sub) %arg) {
 ; CHECK-LABEL: @test_class_is_subnormal_nosub_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 144)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 144)
   ret i1 %class
@@ -2625,7 +2620,7 @@
 
 define i1 @test_class_is_subnormal_nonsub_src(float nofpclass(nsub) %arg) {
 ; CHECK-LABEL: @test_class_is_subnormal_nonsub_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 144)
+; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 128)
 ; CHECK-NEXT:    ret i1 [[CLASS]]
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 144)
@@ -2634,8 +2629,7 @@
 
 define i1 @test_class_is_not_subnormal_nosub_src(float nofpclass(sub) %arg) {
 ; CHECK-LABEL: @test_class_is_not_subnormal_nosub_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 879)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 879)
   ret i1 %class
@@ -2643,8 +2637,7 @@
 
 define i1 @test_class_is_not_negsubnormal_nosub_src(float nofpclass(sub) %arg) {
 ; CHECK-LABEL: @test_class_is_not_negsubnormal_nosub_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 1007)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 1007)
   ret i1 %class
@@ -2652,8 +2645,7 @@
 
 define i1 @test_class_is_not_negsubnormal_nonegsub_src(float nofpclass(nsub) %arg) {
 ; CHECK-LABEL: @test_class_is_not_negsubnormal_nonegsub_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 1007)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 1007)
   ret i1 %class
@@ -2661,8 +2653,7 @@
 
 define i1 @test_class_is_nnormal_nonorm_src(float nofpclass(norm) %arg) {
 ; CHECK-LABEL: @test_class_is_nnormal_nonorm_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 264)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 264)
   ret i1 %class
@@ -2670,8 +2661,7 @@
 
 define i1 @test_class_is_not_nnormal_nonorm_src(float nofpclass(norm) %arg) {
 ; CHECK-LABEL: @test_class_is_not_nnormal_nonorm_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 759)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 759)
   ret i1 %class
@@ -2679,8 +2669,7 @@
 
 define i1 @test_class_is_not_nnormal_onlynorm_src(float nofpclass(nan inf zero sub) %arg) {
 ; CHECK-LABEL: @test_class_is_not_nnormal_onlynorm_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 240)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 759)
   ret i1 %class
@@ -2688,8 +2677,7 @@
 
 define i1 @test_class_is_nnormal_onlynorm_src(float nofpclass(nan inf zero sub) %arg) {
 ; CHECK-LABEL: @test_class_is_nnormal_onlynorm_src(
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 264)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %class = call i1 @llvm.is.fpclass.f32(float %arg, i32 264)
   ret i1 %class
@@ -2700,8 +2688,7 @@
 ; CHECK-LABEL: @test_class_is_normal_assume_normal(
 ; CHECK-NEXT:    [[ASSUMED_IS_NORMAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 264)
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUMED_IS_NORMAL]])
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 264)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 true
 ;
   %assumed.is.normal = call i1 @llvm.is.fpclass.f32(float %x, i32 264)
   call void @llvm.assume(i1 %assumed.is.normal)
@@ -2713,8 +2700,7 @@
 ; CHECK-LABEL: @test_class_is_normal_assume_not_normal(
 ; CHECK-NEXT:    [[ASSUMED_IS_NORMAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 264)
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUMED_IS_NORMAL]])
-; CHECK-NEXT:    [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 759)
-; CHECK-NEXT:    ret i1 [[CLASS]]
+; CHECK-NEXT:    ret i1 false
 ;
   %assumed.is.normal = call i1 @llvm.is.fpclass.f32(float %x, i32 264)
   call void @llvm.assume(i1 %assumed.is.normal)