[clang] [Clang][CodeGen] Fix builtin_fpclassify with llvm.is.fpclass (PR #183430)
Yeongu Choe via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 11 03:06:42 PDT 2026
https://github.com/YeonguChoe updated https://github.com/llvm/llvm-project/pull/183430
>From 5797e946f4f9402f0aa8d73933731332956230c8 Mon Sep 17 00:00:00 2001
From: YeonguChoe <yeongu.choe at icloud.com>
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 <yeongu.choe at icloud.com>
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 <yeongu.choe at icloud.com>
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));
More information about the cfe-commits
mailing list