[clang] [CIR][CodeGen] Implement BI__builtin_fpclassify function (PR #183893)
Yeongu Choe via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 28 04:49:13 PST 2026
https://github.com/YeonguChoe updated https://github.com/llvm/llvm-project/pull/183893
>From c4a086c5ffdbdbc41d225f64621df0c99fbbd01a Mon Sep 17 00:00:00 2001
From: YeonguChoe <yeongu.choe at icloud.com>
Date: Sat, 28 Feb 2026 04:41:45 -0500
Subject: [PATCH 1/2] [CIR][CodeGen] Implement BI__builtin_fpclassify function
BI__builtin_fpclassify function is not implemented in ClangIR, so fpclassify cannot be used at the moment with ClangIR. I implemented BI__builtin_fpclassify so that fpclassify can use builtin_fpclassify.
---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 66 ++++++++++++++++++-
.../CodeGenBuiltins/builtins-floating-point.c | 7 ++
2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 86d34be0a311c..5eee7a522331c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1544,8 +1544,70 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_isinf_sign:
case Builtin::BI__builtin_flt_rounds:
case Builtin::BI__builtin_set_flt_rounds:
- case Builtin::BI__builtin_fpclassify:
- return errorBuiltinNYI(*this, e, builtinID);
+ case Builtin::BI__builtin_fpclassify: {
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
+ mlir::Location Loc = getLoc(e->getBeginLoc());
+
+ mlir::Value NanLiteral = emitScalarExpr(e->getArg(0));
+ mlir::Value InfinityLiteral = emitScalarExpr(e->getArg(1));
+ mlir::Value NormalLiteral = emitScalarExpr(e->getArg(2));
+ mlir::Value SubnormalLiteral = emitScalarExpr(e->getArg(3));
+ mlir::Value ZeroLiteral = emitScalarExpr(e->getArg(4));
+ mlir::Value V = emitScalarExpr(e->getArg(5));
+
+ mlir::Type ResultTy = convertType(e->getType());
+ mlir::Block *EntryBlock = builder.getInsertionBlock();
+ mlir::Region *Region = EntryBlock->getParent();
+
+ // Create Blocks
+ mlir::Block *InfinityBlock = builder.createBlock(Region, Region->end());
+ mlir::Block *NormalBlock = builder.createBlock(Region, Region->end());
+ mlir::Block *SubnormalBlock = builder.createBlock(Region, Region->end());
+ mlir::Block *ZeroBlock = builder.createBlock(Region, Region->end());
+ mlir::Block *EndBlock = builder.createBlock(Region, Region->end());
+ EndBlock->addArgument(ResultTy, Loc);
+
+ // ^EntryBlock
+ builder.setInsertionPointToEnd(EntryBlock);
+ mlir::Value IsNan = builder.createIsFPClass(Loc, V, cir::FPClassTest::Nan);
+ cir::BrCondOp::create(builder, Loc, IsNan, EndBlock,
+ InfinityBlock, // destTrue, destFalse
+ mlir::ValueRange{NanLiteral},
+ mlir::ValueRange{}); // operandsTrue, operandsFalse
+
+ // ^InfinityBlock
+ builder.setInsertionPointToEnd(InfinityBlock);
+ mlir::Value IsInfinity =
+ builder.createIsFPClass(Loc, V, cir::FPClassTest::Infinity);
+ cir::BrCondOp::create(builder, Loc, IsInfinity, EndBlock, NormalBlock,
+ mlir::ValueRange{InfinityLiteral},
+ mlir::ValueRange{});
+
+ // ^NormalBlock
+ builder.setInsertionPointToEnd(NormalBlock);
+ mlir::Value IsNormal =
+ builder.createIsFPClass(Loc, V, cir::FPClassTest::Normal);
+ cir::BrCondOp::create(builder, Loc, IsNormal, EndBlock, SubnormalBlock,
+ mlir::ValueRange{NormalLiteral}, mlir::ValueRange{});
+
+ // ^SubnormalBlock
+ builder.setInsertionPointToEnd(SubnormalBlock);
+ mlir::Value IsSubnormal =
+ builder.createIsFPClass(Loc, V, cir::FPClassTest::Subnormal);
+ cir::BrCondOp::create(builder, Loc, IsSubnormal, EndBlock, ZeroBlock,
+ mlir::ValueRange{SubnormalLiteral},
+ mlir::ValueRange{});
+
+ // ^ZeroBlock
+ builder.setInsertionPointToEnd(ZeroBlock);
+ cir::BrOp::create(builder, Loc, EndBlock, mlir::ValueRange{ZeroLiteral});
+
+ // ^EndBlock(x)
+ builder.setInsertionPointToEnd(EndBlock);
+ mlir::Value Result = EndBlock->getArgument(0);
+
+ return RValue::get(Result);
+ }
case Builtin::BIalloca:
case Builtin::BI_alloca:
case Builtin::BI__builtin_alloca_uninitialized:
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
index be82137427ea2..f63ec9b4c76e9 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
@@ -2210,3 +2210,10 @@ double my_roundeven(double x) {
// OGCG: define{{.*}}@my_roundeven(
// OGCG: call double @llvm.roundeven.f64(
}
+
+int fpclassify(float f) {
+ return __builtin_fpclassify(0, 1, 2, 3, 4, f);
+ // CIR: %{{.*}} = cir.is_fp_class %{{.*}}, fcNan : (!cir.float) -> !cir.bool
+ // LLVM: %{{.*}} = call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 {{.*}})
+ // OGCG: %{{.*}} = fcmp uno float %{{.*}}, %{{.*}}
+}
\ No newline at end of file
>From c5e64d95968bf1600c2383b7d771fcaa9f048c74 Mon Sep 17 00:00:00 2001
From: Yeongu Choe <yeongu.choe at icloud.com>
Date: Sat, 28 Feb 2026 07:49:04 -0500
Subject: [PATCH 2/2] Fix branching logic for NaN check in CIRGenBuiltin
---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 5eee7a522331c..469f7847044b4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1571,9 +1571,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
builder.setInsertionPointToEnd(EntryBlock);
mlir::Value IsNan = builder.createIsFPClass(Loc, V, cir::FPClassTest::Nan);
cir::BrCondOp::create(builder, Loc, IsNan, EndBlock,
- InfinityBlock, // destTrue, destFalse
+ InfinityBlock,
mlir::ValueRange{NanLiteral},
- mlir::ValueRange{}); // operandsTrue, operandsFalse
+ mlir::ValueRange{});
// ^InfinityBlock
builder.setInsertionPointToEnd(InfinityBlock);
More information about the cfe-commits
mailing list