Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -3305,22 +3305,18 @@ } case Builtin::BI__builtin_isnormal: { - // isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >= float_min + // isnormal(x) --> fabs(x) < infinity && !(fabs(x) < float_min) CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E); // FIXME: for strictfp/IEEE-754 we need to not trap on SNaN here. Value *V = EmitScalarExpr(E->getArg(0)); - Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq"); - Value *Abs = EmitFAbs(*this, V); - Value *IsLessThanInf = - Builder.CreateFCmpULT(Abs, ConstantFP::getInfinity(V->getType()),"isinf"); - APFloat Smallest = APFloat::getSmallestNormalized( - getContext().getFloatTypeSemantics(E->getArg(0)->getType())); - Value *IsNormal = - Builder.CreateFCmpUGE(Abs, ConstantFP::get(V->getContext(), Smallest), - "isnormal"); - V = Builder.CreateAnd(Eq, IsLessThanInf, "and"); - V = Builder.CreateAnd(V, IsNormal, "and"); + Value *IsFinite = Builder.CreateFCmpOLT( + Abs, ConstantFP::getInfinity(V->getType()), "isfinite"); + APFloat SmallestNormal = APFloat::getSmallestNormalized( + getContext().getFloatTypeSemantics(E->getArg(0)->getType())); + Value *IsNormal = Builder.CreateFCmpUGE( + Abs, ConstantFP::get(V->getContext(), SmallestNormal), "isnormal"); + V = Builder.CreateAnd(IsFinite, IsNormal, "and"); return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); } Index: clang/test/CodeGen/builtins.c =================================================================== --- clang/test/CodeGen/builtins.c +++ clang/test/CodeGen/builtins.c @@ -261,20 +261,16 @@ // CHECK: fcmp one double {{.*}}, 0x7FF0000000000000 res = __builtin_isnormal(*H); - // CHECK: fcmp oeq half - // CHECK: call half @llvm.fabs.f16(half - // CHECK: fcmp ult half {{.*}}, 0xH7C00 - // CHECK: fcmp uge half {{.*}}, 0xH0400 - // CHECK: and i1 - // CHECK: and i1 + // CHECK: %[[FABS:.*]] = call half @llvm.fabs.f16(half %[[VAL:.*]]) + // CHECK: %[[ISFINITE:.*]] = fcmp olt half %[[FABS]], 0xH7C00 + // CHECK: %[[ISNORMAL:.*]] = fcmp uge half %[[FABS]], 0xH0400 + // CHECK: and i1 %[[ISFINITE]], %[[ISNORMAL]] res = __builtin_isnormal(F); - // CHECK: fcmp oeq float - // CHECK: call float @llvm.fabs.f32(float - // CHECK: fcmp ult float {{.*}}, 0x7FF0000000000000 - // CHECK: fcmp uge float {{.*}}, 0x3810000000000000 - // CHECK: and i1 - // CHECK: and i1 + // CHECK: %[[FABS:.*]] = call float @llvm.fabs.f32(float %[[VAL:.*]]) + // CHECK: %[[ISFINITE:.*]] = fcmp olt float %[[FABS]], 0x7FF0000000000000 + // CHECK: %[[ISNORMAL:.*]] = fcmp uge float %[[FABS]], 0x3810000000000000 + // CHECK: and i1 %[[ISFINITE]], %[[ISNORMAL]] res = __builtin_flt_rounds(); // CHECK: call i32 @llvm.get.rounding(