Index: llvm/lib/Analysis/ConstantFolding.cpp =================================================================== --- llvm/lib/Analysis/ConstantFolding.cpp +++ llvm/lib/Analysis/ConstantFolding.cpp @@ -1617,6 +1617,7 @@ // exceptions even for SNANs. case Intrinsic::fabs: case Intrinsic::copysign: + case Intrinsic::is_fpclass: // Non-constrained variants of rounding operations means default FP // environment, they can be folded in any case. case Intrinsic::ceil: @@ -2626,6 +2627,26 @@ break; } } else if (auto *Op2C = dyn_cast(Operands[1])) { + switch (IntrinsicID) { + case Intrinsic::is_fpclass: { + uint32_t Mask = Op2C->getZExtValue(); + bool Result = + ((Mask & fcSNan) && Op1V.isNaN() && Op1V.isSignaling()) || + ((Mask & fcQNan) && Op1V.isNaN() && !Op1V.isSignaling()) || + ((Mask & fcNegInf) && Op1V.isInfinity() && Op1V.isNegative()) || + ((Mask & fcNegNormal) && Op1V.isNormal() && Op1V.isNegative()) || + ((Mask & fcNegSubnormal) && Op1V.isDenormal() && Op1V.isNegative()) || + ((Mask & fcNegZero) && Op1V.isZero() && Op1V.isNegative()) || + ((Mask & fcPosZero) && Op1V.isZero() && !Op1V.isNegative()) || + ((Mask & fcPosSubnormal) && Op1V.isDenormal() && !Op1V.isNegative()) || + ((Mask & fcPosNormal) && Op1V.isNormal() && !Op1V.isNegative()) || + ((Mask & fcPosInf) && Op1V.isInfinity() && !Op1V.isNegative()); + return ConstantInt::get(Ty, Result); + } + default: + break; + } + if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) return nullptr; if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy()) Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -6118,6 +6118,19 @@ match(Op1, m_FNeg(m_Specific(Op0)))) return Op1; break; + case Intrinsic::is_fpclass: { + uint64_t Mask = cast(Op1)->getZExtValue(); + // If all tests are made, it doesn't matter what the value is. + if ((Mask & fcAllFlags) == fcAllFlags) + return ConstantInt::get(ReturnType, true); + if ((Mask & fcAllFlags) == 0) + return ConstantInt::get(ReturnType, false); + if (isa(Op0)) + return PoisonValue::get(ReturnType); + if (Q.isUndefValue(Op0)) + return UndefValue::get(ReturnType); + break; + } case Intrinsic::maxnum: case Intrinsic::minnum: case Intrinsic::maximum: Index: llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp @@ -422,85 +422,20 @@ Value *Src0 = II.getArgOperand(0); Value *Src1 = II.getArgOperand(1); const ConstantInt *CMask = dyn_cast(Src1); - if (!CMask) { - if (isa(Src0)) { - return IC.replaceInstUsesWith(II, UndefValue::get(II.getType())); - } - - if (isa(Src1)) { - return IC.replaceInstUsesWith(II, - ConstantInt::get(II.getType(), false)); - } - break; + if (CMask) { + II.setCalledOperand(Intrinsic::getDeclaration( + II.getModule(), Intrinsic::is_fpclass, Src0->getType())); + return ⅈ } - uint32_t Mask = CMask->getZExtValue(); - - // If all tests are made, it doesn't matter what the value is. - if ((Mask & fcAllFlags) == fcAllFlags) { - return IC.replaceInstUsesWith(II, ConstantInt::get(II.getType(), true)); - } + if (isa(Src0)) + return IC.replaceInstUsesWith(II, UndefValue::get(II.getType())); - if ((Mask & fcAllFlags) == 0) { + if (isa(Src1)) { return IC.replaceInstUsesWith(II, ConstantInt::get(II.getType(), false)); } - if (Mask == fcNan && !II.isStrictFP()) { - // Equivalent of isnan. Replace with standard fcmp. - Value *FCmp = IC.Builder.CreateFCmpUNO(Src0, Src0); - FCmp->takeName(&II); - return IC.replaceInstUsesWith(II, FCmp); - } - - if (Mask == fcZero && !II.isStrictFP()) { - // Equivalent of == 0. - Value *FCmp = - IC.Builder.CreateFCmpOEQ(Src0, ConstantFP::get(Src0->getType(), 0.0)); - - FCmp->takeName(&II); - return IC.replaceInstUsesWith(II, FCmp); - } - - // fp_class (nnan x), qnan|snan|other -> fp_class (nnan x), other - if ((Mask & fcNan) && isKnownNeverNaN(Src0, &IC.getTargetLibraryInfo())) { - return IC.replaceOperand( - II, 1, ConstantInt::get(Src1->getType(), Mask & ~fcNan)); - } - - const ConstantFP *CVal = dyn_cast(Src0); - if (!CVal) { - if (isa(Src0)) { - return IC.replaceInstUsesWith(II, UndefValue::get(II.getType())); - } - - // Clamp mask to used bits - if ((Mask & fcAllFlags) != Mask) { - CallInst *NewCall = IC.Builder.CreateCall( - II.getCalledFunction(), - {Src0, ConstantInt::get(Src1->getType(), Mask & fcAllFlags)}); - - NewCall->takeName(&II); - return IC.replaceInstUsesWith(II, NewCall); - } - - break; - } - - const APFloat &Val = CVal->getValueAPF(); - - bool Result = - ((Mask & fcSNan) && Val.isNaN() && Val.isSignaling()) || - ((Mask & fcQNan) && Val.isNaN() && !Val.isSignaling()) || - ((Mask & fcNegInf) && Val.isInfinity() && Val.isNegative()) || - ((Mask & fcNegNormal) && Val.isNormal() && Val.isNegative()) || - ((Mask & fcNegSubnormal) && Val.isDenormal() && Val.isNegative()) || - ((Mask & fcNegZero) && Val.isZero() && Val.isNegative()) || - ((Mask & fcPosZero) && Val.isZero() && !Val.isNegative()) || - ((Mask & fcPosSubnormal) && Val.isDenormal() && !Val.isNegative()) || - ((Mask & fcPosNormal) && Val.isNormal() && !Val.isNegative()) || - ((Mask & fcPosInf) && Val.isInfinity() && !Val.isNegative()); - - return IC.replaceInstUsesWith(II, ConstantInt::get(II.getType(), Result)); + break; } case Intrinsic::amdgcn_cvt_pkrtz: { Value *Src0 = II.getArgOperand(0); Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -820,6 +820,51 @@ return nullptr; } +Instruction *InstCombinerImpl::foldIntrinsicIsFPClass(IntrinsicInst &II) { + Value *Src0 = II.getArgOperand(0); + Value *Src1 = II.getArgOperand(1); + const ConstantInt *CMask = cast(Src1); + uint32_t Mask = CMask->getZExtValue(); + const bool IsStrict = II.isStrictFP(); + + if (Mask == fcNan && !IsStrict) { + // Equivalent of isnan. Replace with standard fcmp. + Value *FCmp = Builder.CreateFCmpUNO(Src0, Src0); + FCmp->takeName(&II); + return replaceInstUsesWith(II, FCmp); + } + + if (Mask == fcZero && !IsStrict) { + // Equivalent of == 0. + Value *FCmp = + Builder.CreateFCmpOEQ(Src0, ConstantFP::get(Src0->getType(), 0.0)); + + FCmp->takeName(&II); + return replaceInstUsesWith(II, FCmp); + } + + // fp_class (nnan x), qnan|snan|other -> fp_class (nnan x), other + if ((Mask & fcNan) && isKnownNeverNaN(Src0, &getTargetLibraryInfo())) { + return replaceOperand(II, 1, + ConstantInt::get(Src1->getType(), Mask & ~fcNan)); + } + + // TODO: Handle inverted mask cases, e.g. + // fp_class (nnan x), ~(qnan|snan) -> true + + // Clamp mask to used bits + if ((Mask & fcAllFlags) != Mask) { + CallInst *NewCall = Builder.CreateCall( + II.getCalledFunction(), + {Src0, ConstantInt::get(Src1->getType(), Mask & fcAllFlags)}); + + NewCall->takeName(&II); + return replaceInstUsesWith(II, NewCall); + } + + return nullptr; +} + static Optional getKnownSign(Value *Op, Instruction *CxtI, const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT) { @@ -2825,6 +2870,11 @@ } break; } + case Intrinsic::is_fpclass: { + if (Instruction *I = foldIntrinsicIsFPClass(*II)) + return I; + break; + } default: { // Handle target specific intrinsics Optional V = targetInstCombineIntrinsic(*II); Index: llvm/lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -369,6 +369,7 @@ Instruction *foldExtractOfOverflowIntrinsic(ExtractValueInst &EV); Instruction *foldIntrinsicWithOverflowCommon(IntrinsicInst *II); + Instruction *foldIntrinsicIsFPClass(IntrinsicInst &II); Instruction *foldFPSignBitOps(BinaryOperator &I); Instruction *foldFDivConstantDivisor(BinaryOperator &I); Index: llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll =================================================================== --- llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll +++ llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll @@ -66,7 +66,7 @@ define float @test_constant_fold_rcp_f32_43_strictfp() nounwind strictfp { ; CHECK-LABEL: @test_constant_fold_rcp_f32_43_strictfp( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.rcp.f32(float 4.300000e+01) #[[ATTR14:[0-9]+]] +; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.rcp.f32(float 4.300000e+01) #[[ATTR15:[0-9]+]] ; CHECK-NEXT: ret float [[VAL]] ; %val = call float @llvm.amdgcn.rcp.f32(float 4.300000e+01) strictfp nounwind readnone @@ -107,7 +107,7 @@ define half @test_constant_fold_sqrt_f16_0() nounwind { ; CHECK-LABEL: @test_constant_fold_sqrt_f16_0( -; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.sqrt.f16(half 0xH0000) #[[ATTR15:[0-9]+]] +; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.sqrt.f16(half 0xH0000) #[[ATTR16:[0-9]+]] ; CHECK-NEXT: ret half [[VAL]] ; %val = call half @llvm.amdgcn.sqrt.f16(half 0.0) nounwind readnone @@ -116,7 +116,7 @@ define float @test_constant_fold_sqrt_f32_0() nounwind { ; CHECK-LABEL: @test_constant_fold_sqrt_f32_0( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 0.000000e+00) #[[ATTR15]] +; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 0.000000e+00) #[[ATTR16]] ; CHECK-NEXT: ret float [[VAL]] ; %val = call float @llvm.amdgcn.sqrt.f32(float 0.0) nounwind readnone @@ -125,7 +125,7 @@ define double @test_constant_fold_sqrt_f64_0() nounwind { ; CHECK-LABEL: @test_constant_fold_sqrt_f64_0( -; CHECK-NEXT: [[VAL:%.*]] = call double @llvm.amdgcn.sqrt.f64(double 0.000000e+00) #[[ATTR15]] +; CHECK-NEXT: [[VAL:%.*]] = call double @llvm.amdgcn.sqrt.f64(double 0.000000e+00) #[[ATTR16]] ; CHECK-NEXT: ret double [[VAL]] ; %val = call double @llvm.amdgcn.sqrt.f64(double 0.0) nounwind readnone @@ -134,7 +134,7 @@ define half @test_constant_fold_sqrt_f16_neg0() nounwind { ; CHECK-LABEL: @test_constant_fold_sqrt_f16_neg0( -; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.sqrt.f16(half 0xH8000) #[[ATTR15]] +; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.sqrt.f16(half 0xH8000) #[[ATTR16]] ; CHECK-NEXT: ret half [[VAL]] ; %val = call half @llvm.amdgcn.sqrt.f16(half -0.0) nounwind readnone @@ -143,7 +143,7 @@ define float @test_constant_fold_sqrt_f32_neg0() nounwind { ; CHECK-LABEL: @test_constant_fold_sqrt_f32_neg0( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.sqrt.f32(float -0.000000e+00) #[[ATTR15]] +; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.sqrt.f32(float -0.000000e+00) #[[ATTR16]] ; CHECK-NEXT: ret float [[VAL]] ; %val = call float @llvm.amdgcn.sqrt.f32(float -0.0) nounwind readnone @@ -152,7 +152,7 @@ define double @test_constant_fold_sqrt_f64_neg0() nounwind { ; CHECK-LABEL: @test_constant_fold_sqrt_f64_neg0( -; CHECK-NEXT: [[VAL:%.*]] = call double @llvm.amdgcn.sqrt.f64(double -0.000000e+00) #[[ATTR15]] +; CHECK-NEXT: [[VAL:%.*]] = call double @llvm.amdgcn.sqrt.f64(double -0.000000e+00) #[[ATTR16]] ; CHECK-NEXT: ret double [[VAL]] ; %val = call double @llvm.amdgcn.sqrt.f64(double -0.0) nounwind readnone @@ -569,7 +569,7 @@ define i1 @test_class_over_max_mask_f32(float %x) nounwind { ; CHECK-LABEL: @test_class_over_max_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.amdgcn.class.f32(float [[X:%.*]], i32 1) +; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 1) ; CHECK-NEXT: ret i1 [[VAL]] ; %val = call i1 @llvm.amdgcn.class.f32(float %x, i32 1025) @@ -883,7 +883,7 @@ define i1 @test_class_is_nan_other_nnan_src(float %x) { ; CHECK-LABEL: @test_class_is_nan_other_nnan_src( ; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.amdgcn.class.f32(float [[NNAN]], i32 264) +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NNAN]], i32 264) ; CHECK-NEXT: ret i1 [[CLASS]] ; %nnan = fadd nnan float %x, 1.0 Index: llvm/test/Transforms/InstCombine/is_fpclass.ll =================================================================== --- llvm/test/Transforms/InstCombine/is_fpclass.ll +++ llvm/test/Transforms/InstCombine/is_fpclass.ll @@ -13,7 +13,7 @@ define i1 @test_class_over_max_mask_f32(float %x) { ; CHECK-LABEL: @test_class_over_max_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 1025) +; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 1) ; CHECK-NEXT: ret i1 [[VAL]] ; %val = call i1 @llvm.is.fpclass.f32(float %x, i32 1025) @@ -22,8 +22,7 @@ define i1 @test_class_no_mask_f32(float %x) { ; CHECK-LABEL: @test_class_no_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 0) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f32(float %x, i32 0) ret i1 %val @@ -31,8 +30,7 @@ define i1 @test_class_full_mask_f32(float %x) { ; CHECK-LABEL: @test_class_full_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 1023) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f32(float %x, i32 1023) ret i1 %val @@ -40,8 +38,7 @@ define i1 @test_class_undef_no_mask_f32() { ; CHECK-LABEL: @test_class_undef_no_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float undef, i32 0) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f32(float undef, i32 0) ret i1 %val @@ -49,8 +46,7 @@ define i1 @test_class_undef_full_mask_f32() { ; CHECK-LABEL: @test_class_undef_full_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float undef, i32 1023) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f32(float undef, i32 1023) ret i1 %val @@ -58,8 +54,7 @@ define i1 @test_class_poison_no_mask_f32() { ; CHECK-LABEL: @test_class_poison_no_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float poison, i32 0) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f32(float poison, i32 0) ret i1 %val @@ -67,8 +62,7 @@ define i1 @test_class_poison_full_mask_f32() { ; CHECK-LABEL: @test_class_poison_full_mask_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float poison, i32 1023) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f32(float poison, i32 1023) ret i1 %val @@ -76,8 +70,7 @@ define i1 @test_class_undef_val_f32() { ; CHECK-LABEL: @test_class_undef_val_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float undef, i32 4) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 undef ; %val = call i1 @llvm.is.fpclass.f32(float undef, i32 4) ret i1 %val @@ -85,8 +78,7 @@ define i1 @test_class_poison_val_f32() { ; CHECK-LABEL: @test_class_poison_val_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float poison, i32 4) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 poison ; %val = call i1 @llvm.is.fpclass.f32(float poison, i32 4) ret i1 %val @@ -106,7 +98,7 @@ define i1 @test_class_isnan_f32(float %x) { ; CHECK-LABEL: @test_class_isnan_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 3) +; CHECK-NEXT: [[VAL:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[VAL]] ; %val = call i1 @llvm.is.fpclass.f32(float %x, i32 3) @@ -124,7 +116,7 @@ define i1 @test_class_is_p0_n0_f32(float %x) { ; CHECK-LABEL: @test_class_is_p0_n0_f32( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 96) +; CHECK-NEXT: [[VAL:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[VAL]] ; %val = call i1 @llvm.is.fpclass.f32(float %x, i32 96) @@ -142,8 +134,7 @@ define i1 @test_constant_class_snan_test_snan_f64() { ; CHECK-LABEL: @test_constant_class_snan_test_snan_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000001, i32 1) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000001, i32 1) ret i1 %val @@ -151,8 +142,7 @@ define i1 @test_constant_class_qnan_test_qnan_f64() { ; CHECK-LABEL: @test_constant_class_qnan_test_qnan_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 2) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 2) ret i1 %val @@ -160,8 +150,7 @@ define i1 @test_constant_class_qnan_test_snan_f64() { ; CHECK-LABEL: @test_constant_class_qnan_test_snan_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 1) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 1) ret i1 %val @@ -169,8 +158,7 @@ define i1 @test_constant_class_ninf_test_ninf_f64() { ; CHECK-LABEL: @test_constant_class_ninf_test_ninf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0xFFF0000000000000, i32 4) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0xFFF0000000000000, i32 4) ret i1 %val @@ -178,8 +166,7 @@ define i1 @test_constant_class_pinf_test_ninf_f64() { ; CHECK-LABEL: @test_constant_class_pinf_test_ninf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000000, i32 4) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000000, i32 4) ret i1 %val @@ -187,8 +174,7 @@ define i1 @test_constant_class_qnan_test_ninf_f64() { ; CHECK-LABEL: @test_constant_class_qnan_test_ninf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 4) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 4) ret i1 %val @@ -196,8 +182,7 @@ define i1 @test_constant_class_snan_test_ninf_f64() { ; CHECK-LABEL: @test_constant_class_snan_test_ninf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000001, i32 4) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000001, i32 4) ret i1 %val @@ -205,8 +190,7 @@ define i1 @test_constant_class_nnormal_test_nnormal_f64() { ; CHECK-LABEL: @test_constant_class_nnormal_test_nnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double -1.000000e+00, i32 8) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double -1.0, i32 8) ret i1 %val @@ -214,8 +198,7 @@ define i1 @test_constant_class_pnormal_test_nnormal_f64() { ; CHECK-LABEL: @test_constant_class_pnormal_test_nnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 1.000000e+00, i32 8) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 1.0, i32 8) ret i1 %val @@ -223,8 +206,7 @@ define i1 @test_constant_class_nsubnormal_test_nsubnormal_f64() { ; CHECK-LABEL: @test_constant_class_nsubnormal_test_nsubnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x800FFFFFFFFFFFFF, i32 16) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0x800fffffffffffff, i32 16) ret i1 %val @@ -232,8 +214,7 @@ define i1 @test_constant_class_psubnormal_test_nsubnormal_f64() { ; CHECK-LABEL: @test_constant_class_psubnormal_test_nsubnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0xFFFFFFFFFFFFF, i32 16) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x000fffffffffffff, i32 16) ret i1 %val @@ -241,8 +222,7 @@ define i1 @test_constant_class_nzero_test_nzero_f64() { ; CHECK-LABEL: @test_constant_class_nzero_test_nzero_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double -0.000000e+00, i32 32) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double -0.0, i32 32) ret i1 %val @@ -250,8 +230,7 @@ define i1 @test_constant_class_pzero_test_nzero_f64() { ; CHECK-LABEL: @test_constant_class_pzero_test_nzero_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0.000000e+00, i32 32) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0.0, i32 32) ret i1 %val @@ -259,8 +238,7 @@ define i1 @test_constant_class_pzero_test_pzero_f64() { ; CHECK-LABEL: @test_constant_class_pzero_test_pzero_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0.000000e+00, i32 64) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0.0, i32 64) ret i1 %val @@ -268,8 +246,7 @@ define i1 @test_constant_class_nzero_test_pzero_f64() { ; CHECK-LABEL: @test_constant_class_nzero_test_pzero_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double -0.000000e+00, i32 64) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double -0.0, i32 64) ret i1 %val @@ -277,8 +254,7 @@ define i1 @test_constant_class_psubnormal_test_psubnormal_f64() { ; CHECK-LABEL: @test_constant_class_psubnormal_test_psubnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0xFFFFFFFFFFFFF, i32 128) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0x000fffffffffffff, i32 128) ret i1 %val @@ -286,8 +262,7 @@ define i1 @test_constant_class_nsubnormal_test_psubnormal_f64() { ; CHECK-LABEL: @test_constant_class_nsubnormal_test_psubnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x800FFFFFFFFFFFFF, i32 128) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x800fffffffffffff, i32 128) ret i1 %val @@ -295,8 +270,7 @@ define i1 @test_constant_class_pnormal_test_pnormal_f64() { ; CHECK-LABEL: @test_constant_class_pnormal_test_pnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 1.000000e+00, i32 256) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 1.0, i32 256) ret i1 %val @@ -304,8 +278,7 @@ define i1 @test_constant_class_nnormal_test_pnormal_f64() { ; CHECK-LABEL: @test_constant_class_nnormal_test_pnormal_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double -1.000000e+00, i32 256) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double -1.0, i32 256) ret i1 %val @@ -313,8 +286,7 @@ define i1 @test_constant_class_pinf_test_pinf_f64() { ; CHECK-LABEL: @test_constant_class_pinf_test_pinf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000000, i32 512) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 true ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000000, i32 512) ret i1 %val @@ -322,8 +294,7 @@ define i1 @test_constant_class_ninf_test_pinf_f64() { ; CHECK-LABEL: @test_constant_class_ninf_test_pinf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0xFFF0000000000000, i32 512) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0xFFF0000000000000, i32 512) ret i1 %val @@ -331,8 +302,7 @@ define i1 @test_constant_class_qnan_test_pinf_f64() { ; CHECK-LABEL: @test_constant_class_qnan_test_pinf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 512) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF8000000000000, i32 512) ret i1 %val @@ -340,8 +310,7 @@ define i1 @test_constant_class_snan_test_pinf_f64() { ; CHECK-LABEL: @test_constant_class_snan_test_pinf_f64( -; CHECK-NEXT: [[VAL:%.*]] = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000001, i32 512) -; CHECK-NEXT: ret i1 [[VAL]] +; CHECK-NEXT: ret i1 false ; %val = call i1 @llvm.is.fpclass.f64(double 0x7FF0000000000001, i32 512) ret i1 %val @@ -349,9 +318,7 @@ define i1 @test_class_is_snan_nnan_src(float %x) { ; CHECK-LABEL: @test_class_is_snan_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NNAN]], i32 1) -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan float %x, 1.0 %class = call i1 @llvm.is.fpclass.f32(float %nnan, i32 1) @@ -360,9 +327,7 @@ define i1 @test_class_is_qnan_nnan_src(float %x) { ; CHECK-LABEL: @test_class_is_qnan_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NNAN]], i32 2) -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan float %x, 1.0 %class = call i1 @llvm.is.fpclass.f32(float %nnan, i32 2) @@ -371,9 +336,7 @@ define i1 @test_class_is_nan_nnan_src(float %x) { ; CHECK-LABEL: @test_class_is_nan_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NNAN]], i32 3) -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan float %x, 1.0 %class = call i1 @llvm.is.fpclass.f32(float %nnan, i32 3) @@ -383,7 +346,7 @@ define i1 @test_class_is_nan_other_nnan_src(float %x) { ; CHECK-LABEL: @test_class_is_nan_other_nnan_src( ; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NNAN]], i32 267) +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NNAN]], i32 264) ; CHECK-NEXT: ret i1 [[CLASS]] ; %nnan = fadd nnan float %x, 1.0 @@ -397,9 +360,8 @@ define i1 @test_class_not_is_nan(float %x) { ; CHECK-LABEL: @test_class_not_is_nan( -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 3) -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[CLASS]], true -; CHECK-NEXT: ret i1 [[NOT]] +; CHECK-NEXT: [[CLASS:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CLASS]] ; %class = call i1 @llvm.is.fpclass.f32(float %x, i32 3) %not = xor i1 %class, true @@ -408,7 +370,7 @@ define i1 @test_class_not_is_nan_multi_use(float %x, ptr %ptr) { ; CHECK-LABEL: @test_class_not_is_nan_multi_use( -; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 3) +; CHECK-NEXT: [[CLASS:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: store i1 [[CLASS]], ptr [[PTR:%.*]], align 1 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[CLASS]], true ; CHECK-NEXT: ret i1 [[NOT]]