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 true 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) == fcNone) 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)