https://github.com/YeonguChoe updated https://github.com/llvm/llvm-project/pull/183430
>From 5797e946f4f9402f0aa8d73933731332956230c8 Mon Sep 17 00:00:00 2001 From: YeonguChoe <[email protected]> Date: Wed, 25 Feb 2026 20:29:01 -0500 Subject: [PATCH 1/3] [Clang][CodeGen] Fix builtin_fpclassify with llvm.is.fpclass - Made fpclassify function to classify floating point number using LLVM IR operation - Reference: https://llvm.org/docs/LangRef.html#floating-point-test-intrinsics --- clang/lib/CodeGen/CGBuiltin.cpp | 78 ++++++++++++-------------- clang/test/CodeGen/strictfp_builtins.c | 27 +++++---- 2 files changed, 50 insertions(+), 55 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 6fb43d5cb0fbf..827c21b8aca7d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4414,60 +4414,56 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_fpclassify: { CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E); - // FIXME: for strictfp/IEEE-754 we need to not trap on SNaN here. Value *V = EmitScalarExpr(E->getArg(5)); - llvm::Type *Ty = ConvertType(E->getArg(5)->getType()); - - // Create Result - BasicBlock *Begin = Builder.GetInsertBlock(); - BasicBlock *End = createBasicBlock("fpclassify_end", this->CurFn); - Builder.SetInsertPoint(End); - PHINode *Result = - Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 4, - "fpclassify_result"); - // if (V==0) return FP_ZERO - Builder.SetInsertPoint(Begin); - Value *IsZero = Builder.CreateFCmpOEQ(V, Constant::getNullValue(Ty), - "iszero"); + Value *NanLiteral = EmitScalarExpr(E->getArg(0)); + Value *InfLiteral = EmitScalarExpr(E->getArg(1)); + Value *NormalLiteral = EmitScalarExpr(E->getArg(2)); + Value *SubnormalLiteral = EmitScalarExpr(E->getArg(3)); Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); - BasicBlock *NotZero = createBasicBlock("fpclassify_not_zero", this->CurFn); - Builder.CreateCondBr(IsZero, End, NotZero); - Result->addIncoming(ZeroLiteral, Begin); - // if (V != V) return FP_NAN - Builder.SetInsertPoint(NotZero); - Value *IsNan = Builder.CreateFCmpUNO(V, V, "cmp"); - Value *NanLiteral = EmitScalarExpr(E->getArg(0)); - BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", this->CurFn); + Value *IsNan = Builder.createIsFPClass(V, 0b0000000011); + Value *IsInf = Builder.createIsFPClass(V, 0b1000000100); + Value *IsNormal = Builder.createIsFPClass(V, 0b0100001000); + Value *IsSubnormal = Builder.createIsFPClass(V, 0b0010010000); + + BasicBlock *Entry = Builder.GetInsertBlock(); + + BasicBlock *End = createBasicBlock("fpclassify_end", CurFn); + Builder.SetInsertPoint(End); + PHINode *Result = Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 5, + "fpclassify_result"); + + // Check if V is NaN + Builder.SetInsertPoint(Entry); + BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", CurFn); Builder.CreateCondBr(IsNan, End, NotNan); - Result->addIncoming(NanLiteral, NotZero); + Result->addIncoming(NanLiteral, Entry); - // if (fabs(V) == infinity) return FP_INFINITY + // Check if V is infinity Builder.SetInsertPoint(NotNan); - Value *VAbs = EmitFAbs(*this, V); - Value *IsInf = - Builder.CreateFCmpOEQ(VAbs, ConstantFP::getInfinity(V->getType()), - "isinf"); - Value *InfLiteral = EmitScalarExpr(E->getArg(1)); - BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", this->CurFn); + BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", CurFn); Builder.CreateCondBr(IsInf, End, NotInf); Result->addIncoming(InfLiteral, NotNan); - // if (fabs(V) >= MIN_NORMAL) return FP_NORMAL else FP_SUBNORMAL + // Check if V is normal Builder.SetInsertPoint(NotInf); - APFloat Smallest = APFloat::getSmallestNormalized( - getContext().getFloatTypeSemantics(E->getArg(5)->getType())); - Value *IsNormal = - Builder.CreateFCmpUGE(VAbs, ConstantFP::get(V->getContext(), Smallest), - "isnormal"); - Value *NormalResult = - Builder.CreateSelect(IsNormal, EmitScalarExpr(E->getArg(2)), - EmitScalarExpr(E->getArg(3))); + BasicBlock *NotNormal = createBasicBlock("fpclassify_not_normal", CurFn); + Builder.CreateCondBr(IsNormal, End, NotNormal); + Result->addIncoming(NormalLiteral, NotInf); + + // Check if V is subnormal + Builder.SetInsertPoint(NotNormal); + BasicBlock *NotSubnormal = + createBasicBlock("fpclassify_not_subnormal", CurFn); + Builder.CreateCondBr(IsSubnormal, End, NotSubnormal); + Result->addIncoming(SubnormalLiteral, NotNormal); + + // If V is not one of the above, it is zero + Builder.SetInsertPoint(NotSubnormal); Builder.CreateBr(End); - Result->addIncoming(NormalResult, NotInf); + Result->addIncoming(ZeroLiteral, NotSubnormal); - // return Result Builder.SetInsertPoint(End); return RValue::get(Result); } diff --git a/clang/test/CodeGen/strictfp_builtins.c b/clang/test/CodeGen/strictfp_builtins.c index 58815c7de4fa9..d965767be095b 100644 --- a/clang/test/CodeGen/strictfp_builtins.c +++ b/clang/test/CodeGen/strictfp_builtins.c @@ -3,7 +3,6 @@ // Test that the constrained intrinsics are picking up the exception // metadata from the AST instead of the global default from the command line. -// FIXME: these functions shouldn't trap on SNaN. #pragma float_control(except, on) @@ -31,22 +30,22 @@ void p(char *str, int x) { // CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 // CHECK-NEXT: store double [[D:%.*]], ptr [[D_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 -// CHECK-NEXT: [[ISZERO:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP0]], double 0.000000e+00, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR4]] -// CHECK-NEXT: br i1 [[ISZERO]], label [[FPCLASSIFY_END:%.*]], label [[FPCLASSIFY_NOT_ZERO:%.*]] +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 3) #[[ATTR4]] +// CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 516) #[[ATTR4]] +// CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 264) #[[ATTR4]] +// CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 144) #[[ATTR4]] +// CHECK-NEXT: br i1 [[TMP1]], label [[FPCLASSIFY_END:%.*]], label [[FPCLASSIFY_NOT_NAN:%.*]] // CHECK: fpclassify_end: -// CHECK-NEXT: [[FPCLASSIFY_RESULT:%.*]] = phi i32 [ 4, [[ENTRY:%.*]] ], [ 0, [[FPCLASSIFY_NOT_ZERO]] ], [ 1, [[FPCLASSIFY_NOT_NAN:%.*]] ], [ [[TMP2:%.*]], [[FPCLASSIFY_NOT_INF:%.*]] ] +// CHECK-NEXT: [[FPCLASSIFY_RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[FPCLASSIFY_NOT_NAN]] ], [ 2, [[FPCLASSIFY_NOT_INF:%.*]] ], [ 3, [[FPCLASSIFY_NOT_NORMAL:%.*]] ], [ 4, [[FPCLASSIFY_NOT_SUBNORMAL:%.*]] ] // CHECK-NEXT: call void @p(ptr noundef @.str.1, i32 noundef [[FPCLASSIFY_RESULT]]) #[[ATTR4]] // CHECK-NEXT: ret void -// CHECK: fpclassify_not_zero: -// CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP0]], double [[TMP0]], metadata !"uno", metadata !"fpexcept.strict") #[[ATTR4]] -// CHECK-NEXT: br i1 [[CMP]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NAN]] // CHECK: fpclassify_not_nan: -// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[TMP0]]) #[[ATTR5:[0-9]+]] -// CHECK-NEXT: [[ISINF:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP1]], double 0x7FF0000000000000, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR4]] -// CHECK-NEXT: br i1 [[ISINF]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF]] +// CHECK-NEXT: br i1 [[TMP2]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF:%.*]] // CHECK: fpclassify_not_inf: -// CHECK-NEXT: [[ISNORMAL:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP1]], double 0x10000000000000, metadata !"uge", metadata !"fpexcept.strict") #[[ATTR4]] -// CHECK-NEXT: [[TMP2]] = select i1 [[ISNORMAL]], i32 2, i32 3 +// CHECK-NEXT: br i1 [[TMP3]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NORMAL:%.*]] +// CHECK: fpclassify_not_normal: +// CHECK-NEXT: br i1 [[TMP4]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_SUBNORMAL:%.*]] +// CHECK: fpclassify_not_subnormal: // CHECK-NEXT: br label [[FPCLASSIFY_END]] // void test_fpclassify(double d) { @@ -156,7 +155,7 @@ void test_double_isfinite(double d) { // CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 // CHECK-NEXT: store double [[D:%.*]], ptr [[D_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[TMP0]]) #[[ATTR5]] +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[TMP0]]) #5 // CHECK-NEXT: [[ISINF:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP1]], double 0x7FF0000000000000, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR4]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast double [[TMP0]] to i64 // CHECK-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 0 @@ -233,4 +232,4 @@ void test_isnormal(double d) { P(isnormal, (d)); return; -} +} \ No newline at end of file >From 052f66c16283d561136d6e19639482aa341b89aa Mon Sep 17 00:00:00 2001 From: YeonguChoe <[email protected]> Date: Wed, 25 Feb 2026 23:53:02 -0500 Subject: [PATCH 2/3] Fix nvptx_device_math_macro test for llvm.is.fpclass test --- clang/lib/CodeGen/CGBuiltin.cpp | 19 +++++++++---------- clang/test/CodeGen/strictfp_builtins.c | 8 ++++---- .../test/Headers/nvptx_device_math_macro.cpp | 9 +++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 827c21b8aca7d..fdb4c77ab3c39 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4416,16 +4416,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E); Value *V = EmitScalarExpr(E->getArg(5)); - Value *NanLiteral = EmitScalarExpr(E->getArg(0)); - Value *InfLiteral = EmitScalarExpr(E->getArg(1)); - Value *NormalLiteral = EmitScalarExpr(E->getArg(2)); - Value *SubnormalLiteral = EmitScalarExpr(E->getArg(3)); - Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); - - Value *IsNan = Builder.createIsFPClass(V, 0b0000000011); - Value *IsInf = Builder.createIsFPClass(V, 0b1000000100); - Value *IsNormal = Builder.createIsFPClass(V, 0b0100001000); - Value *IsSubnormal = Builder.createIsFPClass(V, 0b0010010000); + Value *IsNan = Builder.createIsFPClass(V, FPClassTest::fcNan); + Value *IsInf = Builder.createIsFPClass(V, FPClassTest::fcInf); + Value *IsNormal = Builder.createIsFPClass(V, FPClassTest::fcNormal); + Value *IsSubnormal = Builder.createIsFPClass(V, FPClassTest::fcSubnormal); BasicBlock *Entry = Builder.GetInsertBlock(); @@ -4438,18 +4432,21 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.SetInsertPoint(Entry); BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", CurFn); Builder.CreateCondBr(IsNan, End, NotNan); + Value *NanLiteral = EmitScalarExpr(E->getArg(0)); Result->addIncoming(NanLiteral, Entry); // Check if V is infinity Builder.SetInsertPoint(NotNan); BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", CurFn); Builder.CreateCondBr(IsInf, End, NotInf); + Value *InfLiteral = EmitScalarExpr(E->getArg(1)); Result->addIncoming(InfLiteral, NotNan); // Check if V is normal Builder.SetInsertPoint(NotInf); BasicBlock *NotNormal = createBasicBlock("fpclassify_not_normal", CurFn); Builder.CreateCondBr(IsNormal, End, NotNormal); + Value *NormalLiteral = EmitScalarExpr(E->getArg(2)); Result->addIncoming(NormalLiteral, NotInf); // Check if V is subnormal @@ -4457,11 +4454,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, BasicBlock *NotSubnormal = createBasicBlock("fpclassify_not_subnormal", CurFn); Builder.CreateCondBr(IsSubnormal, End, NotSubnormal); + Value *SubnormalLiteral = EmitScalarExpr(E->getArg(3)); Result->addIncoming(SubnormalLiteral, NotNormal); // If V is not one of the above, it is zero Builder.SetInsertPoint(NotSubnormal); Builder.CreateBr(End); + Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); Result->addIncoming(ZeroLiteral, NotSubnormal); Builder.SetInsertPoint(End); diff --git a/clang/test/CodeGen/strictfp_builtins.c b/clang/test/CodeGen/strictfp_builtins.c index d965767be095b..4f826d62344fe 100644 --- a/clang/test/CodeGen/strictfp_builtins.c +++ b/clang/test/CodeGen/strictfp_builtins.c @@ -40,11 +40,11 @@ void p(char *str, int x) { // CHECK-NEXT: call void @p(ptr noundef @.str.1, i32 noundef [[FPCLASSIFY_RESULT]]) #[[ATTR4]] // CHECK-NEXT: ret void // CHECK: fpclassify_not_nan: -// CHECK-NEXT: br i1 [[TMP2]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF:%.*]] +// CHECK-NEXT: br i1 [[TMP2]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF]] // CHECK: fpclassify_not_inf: -// CHECK-NEXT: br i1 [[TMP3]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NORMAL:%.*]] +// CHECK-NEXT: br i1 [[TMP3]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NORMAL]] // CHECK: fpclassify_not_normal: -// CHECK-NEXT: br i1 [[TMP4]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_SUBNORMAL:%.*]] +// CHECK-NEXT: br i1 [[TMP4]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_SUBNORMAL]] // CHECK: fpclassify_not_subnormal: // CHECK-NEXT: br label [[FPCLASSIFY_END]] // @@ -155,7 +155,7 @@ void test_double_isfinite(double d) { // CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 // CHECK-NEXT: store double [[D:%.*]], ptr [[D_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[TMP0]]) #5 +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[TMP0]]) #[[ATTR5:[0-9]+]] // CHECK-NEXT: [[ISINF:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double [[TMP1]], double 0x7FF0000000000000, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR4]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast double [[TMP0]] to i64 // CHECK-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 0 diff --git a/clang/test/Headers/nvptx_device_math_macro.cpp b/clang/test/Headers/nvptx_device_math_macro.cpp index 3faf527daf113..11380ba3f7bd3 100644 --- a/clang/test/Headers/nvptx_device_math_macro.cpp +++ b/clang/test/Headers/nvptx_device_math_macro.cpp @@ -8,10 +8,11 @@ #pragma omp declare target int use_macro() { double a(0); -// CHECK-NOT: call {{.*}} -// CHECK: call double @llvm.fabs.f64(double -// CHECK-NOT: call {{.*}} -// CHECK: ret i32 %conv +// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) +// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 516) +// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 264) +// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 144) +// CHECK: ret i32 return (std::fpclassify(a) != FP_ZERO); } #pragma omp end declare target >From 9cb1ad52a7f877ac436112e3a5a710f3f351ca81 Mon Sep 17 00:00:00 2001 From: YeonguChoe <[email protected]> Date: Wed, 11 Mar 2026 06:06:19 -0400 Subject: [PATCH 3/3] fixed Builtin::BI__builtin_fpclassify to correct algorithm --- clang/lib/CodeGen/CGBuiltin.cpp | 58 +++++++++++++------------- clang/test/CodeGen/builtins.c | 28 ++++++++++++- clang/test/CodeGen/strictfp_builtins.c | 22 +++++----- 3 files changed, 67 insertions(+), 41 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index fdb4c77ab3c39..a9f68afa88238 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4414,55 +4414,57 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_fpclassify: { CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E); - Value *V = EmitScalarExpr(E->getArg(5)); - Value *IsNan = Builder.createIsFPClass(V, FPClassTest::fcNan); - Value *IsInf = Builder.createIsFPClass(V, FPClassTest::fcInf); - Value *IsNormal = Builder.createIsFPClass(V, FPClassTest::fcNormal); - Value *IsSubnormal = Builder.createIsFPClass(V, FPClassTest::fcSubnormal); + Value *NanLiteral = EmitScalarExpr(E->getArg(0)); + Value *InfiniteLiteral = EmitScalarExpr(E->getArg(1)); + Value *NormalLiteral = EmitScalarExpr(E->getArg(2)); + Value *SubnormalLiteral = EmitScalarExpr(E->getArg(3)); + Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); + Value *V = EmitScalarExpr(E->getArg(5)); BasicBlock *Entry = Builder.GetInsertBlock(); - + BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", CurFn); + BasicBlock *NotInfinite = createBasicBlock("fpclassify_not_inf", CurFn); + BasicBlock *NotNormal = createBasicBlock("fpclassify_not_normal", CurFn); + BasicBlock *NotSubnormal = + createBasicBlock("fpclassify_not_subnormal", CurFn); BasicBlock *End = createBasicBlock("fpclassify_end", CurFn); + + // End block Builder.SetInsertPoint(End); PHINode *Result = Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 5, "fpclassify_result"); - // Check if V is NaN + // Entry block Builder.SetInsertPoint(Entry); - BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", CurFn); - Builder.CreateCondBr(IsNan, End, NotNan); - Value *NanLiteral = EmitScalarExpr(E->getArg(0)); + Value *IsNan = Builder.createIsFPClass(V, FPClassTest::fcNan); Result->addIncoming(NanLiteral, Entry); + Builder.CreateCondBr(IsNan, End, NotNan); - // Check if V is infinity + // NotNan block Builder.SetInsertPoint(NotNan); - BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", CurFn); - Builder.CreateCondBr(IsInf, End, NotInf); - Value *InfLiteral = EmitScalarExpr(E->getArg(1)); - Result->addIncoming(InfLiteral, NotNan); + Value *IsInf = Builder.createIsFPClass(V, FPClassTest::fcInf); + Result->addIncoming(InfiniteLiteral, NotNan); + Builder.CreateCondBr(IsInf, End, NotInfinite); - // Check if V is normal - Builder.SetInsertPoint(NotInf); - BasicBlock *NotNormal = createBasicBlock("fpclassify_not_normal", CurFn); + // NotInfinite block + Builder.SetInsertPoint(NotInfinite); + Value *IsNormal = Builder.createIsFPClass(V, FPClassTest::fcNormal); + Result->addIncoming(NormalLiteral, NotInfinite); Builder.CreateCondBr(IsNormal, End, NotNormal); - Value *NormalLiteral = EmitScalarExpr(E->getArg(2)); - Result->addIncoming(NormalLiteral, NotInf); - // Check if V is subnormal + // NotNormal block Builder.SetInsertPoint(NotNormal); - BasicBlock *NotSubnormal = - createBasicBlock("fpclassify_not_subnormal", CurFn); - Builder.CreateCondBr(IsSubnormal, End, NotSubnormal); - Value *SubnormalLiteral = EmitScalarExpr(E->getArg(3)); + Value *IsSubnormal = Builder.createIsFPClass(V, FPClassTest::fcSubnormal); Result->addIncoming(SubnormalLiteral, NotNormal); + Builder.CreateCondBr(IsSubnormal, End, NotSubnormal); - // If V is not one of the above, it is zero + // NotSubnormal block Builder.SetInsertPoint(NotSubnormal); - Builder.CreateBr(End); - Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); Result->addIncoming(ZeroLiteral, NotSubnormal); + Builder.CreateBr(End); + // End block Builder.SetInsertPoint(End); return RValue::get(Result); } diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c index 4decb30b18e5f..9f046f3f58e73 100644 --- a/clang/test/CodeGen/builtins.c +++ b/clang/test/CodeGen/builtins.c @@ -265,6 +265,30 @@ void test_conditional_bcopy(void) { // CHECK-LABEL: define{{.*}} void @test_float_builtins void test_float_builtins(__fp16 *H, float F, double D, long double LD) { volatile int res; + + res = __builtin_fpclassify(0, 1, 2, 3, 4, F); + // CHECK: %[[FPVAL:.*]] = load float, ptr %F.addr + // CHECK: %[[ISNAN:.*]] = call i1 @llvm.is.fpclass.f32(float %[[FPVAL]], i32 3) + // CHECK: br i1 %[[ISNAN]], label %fpclassify_end, label %fpclassify_not_nan + // + // CHECK: fpclassify_not_nan: + // CHECK: %[[ISINF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[FPVAL]], i32 516) + // CHECK: br i1 %[[ISINF]], label %fpclassify_end, label %fpclassify_not_inf + // + // CHECK: fpclassify_not_inf: + // CHECK: %[[ISNORMAL:.*]] = call i1 @llvm.is.fpclass.f32(float %[[FPVAL]], i32 264) + // CHECK: br i1 %[[ISNORMAL]], label %fpclassify_end, label %fpclassify_not_normal + // + // CHECK: fpclassify_not_normal: + // CHECK: %[[ISSUBNORMAL:.*]] = call i1 @llvm.is.fpclass.f32(float %[[FPVAL]], i32 144) + // CHECK: br i1 %[[ISSUBNORMAL]], label %fpclassify_end, label %fpclassify_not_subnormal + // + // CHECK: fpclassify_not_subnormal: + // CHECK: br label %fpclassify_end + // + // CHECK: fpclassify_end: + // CHECK: %fpclassify_result = phi i32 [ 0, %{{.*}} ], [ 1, %fpclassify_not_nan ], [ 2, %fpclassify_not_inf ], [ 3, %fpclassify_not_normal ], [ 4, %fpclassify_not_subnormal ] + res = __builtin_isinf(*H); // CHECK: [[TMP:%.*]] = call i1 @llvm.is.fpclass.f16(half {{.*}}, i32 516) // CHECK: zext i1 [[TMP]] to i32 @@ -373,7 +397,7 @@ void test_float_builtin_ops(float F, double D, long double LD, int I) { resld = __builtin_fabsl(LD); // CHECK: call float @llvm.fabs.f32(float // CHECK: call double @llvm.fabs.f64(double - // CHECK: call [[LDTYPE]] @llvm.fabs.[[LDLLVMTY]]([[LDTYPE]] + // CHECK: call [[LDTYPE]] @llvm.fabs.[[LDLLVMTY:[a-z0-9]+]]([[LDTYPE]] resf = __builtin_canonicalizef(F); resd = __builtin_canonicalize(D); @@ -955,7 +979,7 @@ void test_builtin_bswapg(unsigned char uc, unsigned short us, unsigned int ui, ui = __builtin_bswapg(ui); // CHECK: call i32 @llvm.bswap.i32 ul = __builtin_bswapg(ul); - // CHECK: call [[LONGINTTY]] @llvm.bswap.[[LONGINTTY]] + // CHECK: call [[LONGINTTY:[a-z0-9]+]] @llvm.bswap.[[LONGINTTY]] ull = __builtin_bswapg(ull); // CHECK: call i64 @llvm.bswap.i64 #ifdef __SIZEOF_INT128__ diff --git a/clang/test/CodeGen/strictfp_builtins.c b/clang/test/CodeGen/strictfp_builtins.c index 4f826d62344fe..59a57f8e1d9c7 100644 --- a/clang/test/CodeGen/strictfp_builtins.c +++ b/clang/test/CodeGen/strictfp_builtins.c @@ -30,23 +30,23 @@ void p(char *str, int x) { // CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 // CHECK-NEXT: store double [[D:%.*]], ptr [[D_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 3) #[[ATTR4]] -// CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 516) #[[ATTR4]] -// CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 264) #[[ATTR4]] -// CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 144) #[[ATTR4]] +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 3) #[[ATTR:[0-9]+]] // CHECK-NEXT: br i1 [[TMP1]], label [[FPCLASSIFY_END:%.*]], label [[FPCLASSIFY_NOT_NAN:%.*]] -// CHECK: fpclassify_end: -// CHECK-NEXT: [[FPCLASSIFY_RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[FPCLASSIFY_NOT_NAN]] ], [ 2, [[FPCLASSIFY_NOT_INF:%.*]] ], [ 3, [[FPCLASSIFY_NOT_NORMAL:%.*]] ], [ 4, [[FPCLASSIFY_NOT_SUBNORMAL:%.*]] ] -// CHECK-NEXT: call void @p(ptr noundef @.str.1, i32 noundef [[FPCLASSIFY_RESULT]]) #[[ATTR4]] -// CHECK-NEXT: ret void // CHECK: fpclassify_not_nan: -// CHECK-NEXT: br i1 [[TMP2]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF]] +// CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 516) #[[ATTR]] +// CHECK-NEXT: br i1 [[TMP2]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF:%.*]] // CHECK: fpclassify_not_inf: -// CHECK-NEXT: br i1 [[TMP3]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NORMAL]] +// CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 264) #[[ATTR]] +// CHECK-NEXT: br i1 [[TMP3]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NORMAL:%.*]] // CHECK: fpclassify_not_normal: -// CHECK-NEXT: br i1 [[TMP4]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_SUBNORMAL]] +// CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.is.fpclass.f64(double [[TMP0]], i32 144) #[[ATTR]] +// CHECK-NEXT: br i1 [[TMP4]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_SUBNORMAL:%.*]] // CHECK: fpclassify_not_subnormal: // CHECK-NEXT: br label [[FPCLASSIFY_END]] +// CHECK: fpclassify_end: +// CHECK-NEXT: [[FPCLASSIFY_RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[FPCLASSIFY_NOT_NAN]] ], [ 2, [[FPCLASSIFY_NOT_INF]] ], [ 3, [[FPCLASSIFY_NOT_NORMAL]] ], [ 4, [[FPCLASSIFY_NOT_SUBNORMAL]] ] +// CHECK-NEXT: call void @p(ptr noundef @.str.1, i32 noundef [[FPCLASSIFY_RESULT]]) #[[ATTR]] +// CHECK-NEXT: ret void // void test_fpclassify(double d) { P(fpclassify, (0, 1, 2, 3, 4, d)); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
