https://github.com/YeonguChoe updated 
https://github.com/llvm/llvm-project/pull/190848

>From 7e4320f5e120bc32d94572c6cd2e7d1c06942bbd Mon Sep 17 00:00:00 2001
From: YeonguChoe <[email protected]>
Date: Tue, 7 Apr 2026 16:31:28 -0400
Subject: [PATCH 1/2] [Clang] Implement __builtin_fpclassify

- __builtin_fpclassify is a function classify floating point value into one of 
FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL and FP_ZERO.

- Applied LLVM IR output to FileCheck test files using __builtin_fpclassify 
function.
---
 clang/lib/CodeGen/CGBuiltin.cpp               |  88 +++--
 .../CIR/CodeGenBuiltins/builtin-fpclassify.c  | 329 +++++-------------
 clang/test/CodeGen/builtin-fpclassify.c       |  92 +++++
 .../test/Headers/nvptx_device_math_macro.cpp  |   8 +-
 4 files changed, 224 insertions(+), 293 deletions(-)
 create mode 100644 clang/test/CodeGen/builtin-fpclassify.c

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4d74d681cd320..b260a36e877b5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4415,60 +4415,58 @@ 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 *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));
-    llvm::Type *Ty = ConvertType(E->getArg(5)->getType());
 
-    // Create Result
-    BasicBlock *Begin = Builder.GetInsertBlock();
-    BasicBlock *End = createBasicBlock("fpclassify_end", this->CurFn);
+    BasicBlock *Entry = Builder.GetInsertBlock();
+    BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", CurFn);
+    BasicBlock *NotInfinite =
+        createBasicBlock("fpclassify_not_infinite", 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()), 4,
-                        "fpclassify_result");
+    PHINode *Result = Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 
5,
+                                        "fpclassify_result");
 
-    // if (V==0) return FP_ZERO
-    Builder.SetInsertPoint(Begin);
-    Value *IsZero = Builder.CreateFCmpOEQ(V, Constant::getNullValue(Ty),
-                                          "iszero");
-    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);
+    // Entry Block
+    Builder.SetInsertPoint(Entry);
+    Value *IsNan = Builder.createIsFPClass(V, FPClassTest::fcNan);
+    Result->addIncoming(NanLiteral, Entry);
     Builder.CreateCondBr(IsNan, End, NotNan);
-    Result->addIncoming(NanLiteral, NotZero);
 
-    // if (fabs(V) == infinity) return FP_INFINITY
+    // NotNan Block
     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);
-    Builder.CreateCondBr(IsInf, End, NotInf);
-    Result->addIncoming(InfLiteral, NotNan);
-
-    // if (fabs(V) >= MIN_NORMAL) return FP_NORMAL else FP_SUBNORMAL
-    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)));
+    Value *IsInfinite = Builder.createIsFPClass(V, FPClassTest::fcInf);
+    Result->addIncoming(InfiniteLiteral, NotNan);
+    Builder.CreateCondBr(IsInfinite, End, NotInfinite);
+
+    // NotInfinite Block
+    Builder.SetInsertPoint(NotInfinite);
+    Value *IsNormal = Builder.createIsFPClass(V, FPClassTest::fcNormal);
+    Result->addIncoming(NormalLiteral, NotInfinite);
+    Builder.CreateCondBr(IsNormal, End, NotNormal);
+
+    // NotNormal Block
+    Builder.SetInsertPoint(NotNormal);
+    Value *IsSubnormal = Builder.createIsFPClass(V, FPClassTest::fcSubnormal);
+    Result->addIncoming(SubnormalLiteral, NotNormal);
+    Builder.CreateCondBr(IsSubnormal, End, NotSubnormal);
+
+    // NotSubnormal Block
+    Builder.SetInsertPoint(NotSubnormal);
+    Result->addIncoming(ZeroLiteral, NotSubnormal);
     Builder.CreateBr(End);
-    Result->addIncoming(NormalResult, NotInf);
 
-    // return Result
+    // End Block
     Builder.SetInsertPoint(End);
     return RValue::get(Result);
   }
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c 
b/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c
index bad83c4f0ef4c..39e1b35ba7e1b 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c
@@ -29,55 +29,23 @@ void test_fpclassify_nan(){
 // CIR: %[[SUBNORMAL_VAL:.+]] = cir.const #cir.int<144> : !s32i
 // CIR: cir.select if %[[IS_NORMAL]] then %[[NORMAL_VAL]] else 
%[[SUBNORMAL_VAL]] : (!cir.bool, !s32i, !s32i) -> !s32i
 
-// LLVM: %[[VAL:.*]] = load float, ptr
-// LLVM-NEXT: %[[IS_ZERO:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 96)
-// LLVM-NEXT: br i1 %[[IS_ZERO]], label %[[BB_ZERO:.*]], label 
%[[BB_NOT_ZERO:.*]]
-// LLVM: [[BB_ZERO]]:
-// LLVM-NEXT: br label %[[BB_RET:.*]]
-// LLVM: [[BB_NOT_ZERO]]:
-// LLVM-NEXT: %[[IS_NAN:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 3)
-// LLVM-NEXT: br i1 %[[IS_NAN]], label %[[BB_NAN:.*]], label %[[BB_NOT_NAN:.*]]
-// LLVM: [[BB_NAN]]:
-// LLVM-NEXT: br label %[[BB_MERGE1:.*]]
-// LLVM: [[BB_NOT_NAN]]:
-// LLVM-NEXT: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 516)
-// LLVM-NEXT: br i1 %[[IS_INF]], label %[[BB_INF:.*]], label %[[BB_NOT_INF:.*]]
-// LLVM: [[BB_INF]]:
-// LLVM-NEXT: br label %[[BB_MERGE2:.*]]
-// LLVM: [[BB_NOT_INF]]:
-// LLVM-NEXT: %[[IS_NORMAL:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 264)
-// LLVM-NEXT: %[[NORMAL_OR_SUBNORMAL:.*]] = select i1 %[[IS_NORMAL]], i32 264, 
i32 144
-// LLVM-NEXT: br label %[[BB_MERGE2]]
-// LLVM: [[BB_MERGE2]]:
-// LLVM-NEXT: %[[PHI_INF_SEL:.*]] = phi i32 [ %[[NORMAL_OR_SUBNORMAL]], 
%[[BB_NOT_INF]] ], [ 516, %[[BB_INF]] ]
-// LLVM-NEXT: br label %[[BB_CONT1:.*]]
-// LLVM: [[BB_CONT1]]:
-// LLVM-NEXT: br label %[[BB_MERGE1]]
-// LLVM: [[BB_MERGE1]]:
-// LLVM-NEXT: %[[PHI_NAN_SEL:.*]] = phi i32 [ %[[PHI_INF_SEL]], %[[BB_CONT1]] 
], [ 3, %[[BB_NAN]] ]
-// LLVM-NEXT: br label %[[BB_CONT2:.*]]
-// LLVM: [[BB_CONT2]]:
-// LLVM-NEXT: br label %[[BB_RET]]
-// LLVM: [[BB_RET]]:
-// LLVM-NEXT: %[[PHI_FINAL:.*]] = phi i32 [ %[[PHI_NAN_SEL]], %[[BB_CONT2]] ], 
[ 96, %[[BB_ZERO]] ]
-// LLVM-NEXT: br label %[[BB_EXIT:.*]]
-// LLVM: [[BB_EXIT]]:
-
-// OGCG: %[[CMP_ZERO:.+]] = fcmp oeq float %[[VAL:.+]],
-// OGCG-NEXT: br i1 %[[CMP_ZERO]], label %[[BB_RET:.+]], label 
%[[BB_NOT_ZERO:.+]]
-// OGCG: [[BB_RET]]:
-// OGCG-NEXT: %[[PHI:.+]] = phi i32 [ 96, %[[BB_ENTRY:.+]] ], [ 3, 
%[[BB_NOT_ZERO]] ], [ 516, %[[BB_NOT_NAN:.+]] ], [ %[[SEL:.+]], 
%[[BB_NOT_INF:.+]] ]
-// OGCG: [[BB_NOT_ZERO]]:
-// OGCG-NEXT: %[[CMP_NAN:.+]] = fcmp uno float %[[VAL]], %[[VAL]]
-// OGCG-NEXT: br i1 %[[CMP_NAN]], label %[[BB_RET]], label %[[BB_NOT_NAN]]
-// OGCG: [[BB_NOT_NAN]]:
-// OGCG-NEXT: %[[FABS:.+]] = call float @llvm.fabs.f32(float %[[VAL]])
-// OGCG-NEXT: %[[CMP_INF:.+]] = fcmp oeq float %[[FABS]],
-// OGCG-NEXT: br i1 %[[CMP_INF]], label %[[BB_RET]], label %[[BB_NOT_INF]]
-// OGCG: [[BB_NOT_INF]]:
-// OGCG-NEXT: %[[CMP_NORMAL:.+]] = fcmp uge float %[[FABS]],
-// OGCG-NEXT: %[[SEL]] = select i1 %[[CMP_NORMAL]], i32 264, i32 144
-// OGCG-NEXT: br label %[[BB_RET]]
+// LLVM: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// LLVM: br i1 %[[FPCLASS1]]
+// LLVM: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS2]]
+// LLVM: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS3]]
+// LLVM: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: phi i32
+
+// OGCG: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// OGCG: br i1 %[[FPCLASS1]]
+// OGCG: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS2]]
+// OGCG: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS3]]
+// OGCG: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: phi i32
 }
 
 void test_fpclassify_inf(){
@@ -98,54 +66,23 @@ void test_fpclassify_inf(){
 // CIR: %[[SUBNORMAL_VAL:.+]] = cir.const #cir.int<144> : !s32i
 // CIR: cir.select if %[[IS_NORMAL]] then %[[NORMAL_VAL]] else 
%[[SUBNORMAL_VAL]] : (!cir.bool, !s32i, !s32i) -> !s32i
 
-// LLVM: %[[VAL:.+]] = load float, ptr
-// LLVM-NEXT: %[[IS_ZERO:.+]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 96)
-// LLVM-NEXT: br i1 %[[IS_ZERO]], label %[[BB_ZERO:.+]], label 
%[[BB_NOT_ZERO:.+]]
-// LLVM: [[BB_ZERO]]:
-// LLVM-NEXT: br label %[[BB_RET:.+]]
-// LLVM: [[BB_NOT_ZERO]]:
-// LLVM-NEXT: %[[IS_NAN:.+]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 3)
-// LLVM-NEXT: br i1 %[[IS_NAN]], label %[[BB_NAN:.+]], label %[[BB_NOT_NAN:.+]]
-// LLVM: [[BB_NAN]]:
-// LLVM-NEXT: br label %[[BB_MERGE1:.+]]
-// LLVM: [[BB_NOT_NAN]]:
-// LLVM-NEXT: %[[IS_INF:.+]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 516)
-// LLVM-NEXT: br i1 %[[IS_INF]], label %[[BB_INF:.+]], label %[[BB_NOT_INF:.+]]
-// LLVM: [[BB_INF]]:
-// LLVM-NEXT: br label %[[BB_MERGE2:.+]]
-// LLVM: [[BB_NOT_INF]]:
-// LLVM-NEXT: %[[IS_NORMAL:.+]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 264)
-// LLVM-NEXT: %[[SEL:.+]] = select i1 %[[IS_NORMAL]], i32 264, i32 144
-// LLVM-NEXT: br label %[[BB_MERGE2]]
-// LLVM: [[BB_MERGE2]]:
-// LLVM-NEXT: %[[PHI1:.+]] = phi i32 [ %[[SEL]], %[[BB_NOT_INF]] ], [ 516, 
%[[BB_INF]] ]
-// LLVM-NEXT: br label %[[BB_CONT1:.+]]
-// LLVM: [[BB_CONT1]]:
-// LLVM-NEXT: br label %[[BB_MERGE1]]
-// LLVM: [[BB_MERGE1]]:
-// LLVM-NEXT: %[[PHI2:.+]] = phi i32 [ %[[PHI1]], %[[BB_CONT1]] ], [ 3, 
%[[BB_NAN]] ]
-// LLVM-NEXT: br label %[[BB_CONT2:.+]]
-// LLVM: [[BB_CONT2]]:
-// LLVM-NEXT: br label %[[BB_RET]]
-// LLVM: [[BB_RET]]:
-// LLVM-NEXT: %[[PHI3:.+]] = phi i32 [ %[[PHI2]], %[[BB_CONT2]] ], [ 96, 
%[[BB_ZERO]] ]
-// LLVM-NEXT: br label
-
-// OGCG: %[[CMP_ZERO:.+]] = fcmp oeq float %[[VAL:.+]],
-// OGCG-NEXT: br i1 %[[CMP_ZERO]], label %[[BB_RET:.+]], label 
%[[BB_NOT_ZERO:.+]]
-// OGCG: [[BB_RET]]:
-// OGCG-NEXT: %[[PHI:.+]] = phi i32 [ 96, %[[BB_ENTRY:.+]] ], [ 3, 
%[[BB_NOT_ZERO]] ], [ 516, %[[BB_NOT_NAN:.+]] ], [ %[[SEL:.+]], 
%[[BB_NOT_INF:.+]] ]
-// OGCG: [[BB_NOT_ZERO]]:
-// OGCG-NEXT: %[[CMP_NAN:.+]] = fcmp uno float %[[VAL]], %[[VAL]]
-// OGCG-NEXT: br i1 %[[CMP_NAN]], label %[[BB_RET]], label %[[BB_NOT_NAN]]
-// OGCG: [[BB_NOT_NAN]]:
-// OGCG-NEXT: %[[FABS:.+]] = call float @llvm.fabs.f32(float %[[VAL]])
-// OGCG-NEXT: %[[CMP_INF:.+]] = fcmp oeq float %[[FABS]],
-// OGCG-NEXT: br i1 %[[CMP_INF]], label %[[BB_RET]], label %[[BB_NOT_INF]]
-// OGCG: [[BB_NOT_INF]]:
-// OGCG-NEXT: %[[CMP_NORMAL:.+]] = fcmp uge float %[[FABS]],
-// OGCG-NEXT: %[[SEL]] = select i1 %[[CMP_NORMAL]], i32 264, i32 144
-// OGCG-NEXT: br label %[[BB_RET]]
+// LLVM: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// LLVM: br i1 %[[FPCLASS1]]
+// LLVM: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS2]]
+// LLVM: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS3]]
+// LLVM: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: phi i32
+
+// OGCG: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// OGCG: br i1 %[[FPCLASS1]]
+// OGCG: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS2]]
+// OGCG: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS3]]
+// OGCG: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: phi i32
 }
 
 void test_fpclassify_normal(){
@@ -166,55 +103,23 @@ void test_fpclassify_normal(){
 // CIR: %[[SUBNORMAL_VAL:.+]] = cir.const #cir.int<144> : !s32i
 // CIR: cir.select if %[[IS_NORMAL]] then %[[NORMAL_VAL]] else 
%[[SUBNORMAL_VAL]] : (!cir.bool, !s32i, !s32i) -> !s32i
 
-// LLVM: %[[VAL:.*]] = load float, ptr
-// LLVM-NEXT: %[[IS_ZERO:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 96)
-// LLVM-NEXT: br i1 %[[IS_ZERO]], label %[[BB_ZERO:.*]], label 
%[[BB_NOT_ZERO:.*]]
-// LLVM: [[BB_ZERO]]:
-// LLVM-NEXT: br label %[[BB_RET:.*]]
-// LLVM: [[BB_NOT_ZERO]]:
-// LLVM-NEXT: %[[IS_NAN:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 3)
-// LLVM-NEXT: br i1 %[[IS_NAN]], label %[[BB_NAN:.*]], label %[[BB_NOT_NAN:.*]]
-// LLVM: [[BB_NAN]]:
-// LLVM-NEXT: br label %[[BB_MERGE1:.*]]
-// LLVM: [[BB_NOT_NAN]]:
-// LLVM-NEXT: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 516)
-// LLVM-NEXT: br i1 %[[IS_INF]], label %[[BB_INF:.*]], label %[[BB_NOT_INF:.*]]
-// LLVM: [[BB_INF]]:
-// LLVM-NEXT: br label %[[BB_MERGE2:.*]]
-// LLVM: [[BB_NOT_INF]]:
-// LLVM-NEXT: %[[IS_NORMAL:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 264)
-// LLVM-NEXT: %[[NORMAL_OR_SUBNORMAL:.*]] = select i1 %[[IS_NORMAL]], i32 264, 
i32 144
-// LLVM-NEXT: br label %[[BB_MERGE2]]
-// LLVM: [[BB_MERGE2]]:
-// LLVM-NEXT: %[[PHI_INF_SEL:.*]] = phi i32 [ %[[NORMAL_OR_SUBNORMAL]], 
%[[BB_NOT_INF]] ], [ 516, %[[BB_INF]] ]
-// LLVM-NEXT: br label %[[BB_CONT1:.*]]
-// LLVM: [[BB_CONT1]]:
-// LLVM-NEXT: br label %[[BB_MERGE1]]
-// LLVM: [[BB_MERGE1]]:
-// LLVM-NEXT: %[[PHI_NAN_SEL:.*]] = phi i32 [ %[[PHI_INF_SEL]], %[[BB_CONT1]] 
], [ 3, %[[BB_NAN]] ]
-// LLVM-NEXT: br label %[[BB_CONT2:.*]]
-// LLVM: [[BB_CONT2]]:
-// LLVM-NEXT: br label %[[BB_RET]]
-// LLVM: [[BB_RET]]:
-// LLVM-NEXT: %[[PHI_FINAL:.*]] = phi i32 [ %[[PHI_NAN_SEL]], %[[BB_CONT2]] ], 
[ 96, %[[BB_ZERO]] ]
-// LLVM-NEXT: br label %[[BB_EXIT:.*]]
-// LLVM: [[BB_EXIT]]:
-
-// OGCG: %[[CMP_ZERO:.+]] = fcmp oeq float %[[VAL:.+]],
-// OGCG-NEXT: br i1 %[[CMP_ZERO]], label %[[BB_RET:.+]], label 
%[[BB_NOT_ZERO:.+]]
-// OGCG: [[BB_RET]]:
-// OGCG-NEXT: %[[PHI:.+]] = phi i32 [ 96, %[[BB_ENTRY:.+]] ], [ 3, 
%[[BB_NOT_ZERO]] ], [ 516, %[[BB_NOT_NAN:.+]] ], [ %[[SEL:.+]], 
%[[BB_NOT_INF:.+]] ]
-// OGCG: [[BB_NOT_ZERO]]:
-// OGCG-NEXT: %[[CMP_NAN:.+]] = fcmp uno float %[[VAL]], %[[VAL]]
-// OGCG-NEXT: br i1 %[[CMP_NAN]], label %[[BB_RET]], label %[[BB_NOT_NAN]]
-// OGCG: [[BB_NOT_NAN]]:
-// OGCG-NEXT: %[[FABS:.+]] = call float @llvm.fabs.f32(float %[[VAL]])
-// OGCG-NEXT: %[[CMP_INF:.+]] = fcmp oeq float %[[FABS]],
-// OGCG-NEXT: br i1 %[[CMP_INF]], label %[[BB_RET]], label %[[BB_NOT_INF]]
-// OGCG: [[BB_NOT_INF]]:
-// OGCG-NEXT: %[[CMP_NORMAL:.+]] = fcmp uge float %[[FABS]],
-// OGCG-NEXT: %[[SEL]] = select i1 %[[CMP_NORMAL]], i32 264, i32 144
-// OGCG-NEXT: br label %[[BB_RET]]
+// LLVM: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// LLVM: br i1 %[[FPCLASS1]]
+// LLVM: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS2]]
+// LLVM: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS3]]
+// LLVM: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: phi i32
+
+// OGCG: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// OGCG: br i1 %[[FPCLASS1]]
+// OGCG: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS2]]
+// OGCG: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS3]]
+// OGCG: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: phi i32
 }
 
 void test_fpclassify_subnormal(){
@@ -235,55 +140,23 @@ void test_fpclassify_subnormal(){
 // CIR: %[[SUBNORMAL_VAL:.+]] = cir.const #cir.int<144> : !s32i
 // CIR: cir.select if %[[IS_NORMAL]] then %[[NORMAL_VAL]] else 
%[[SUBNORMAL_VAL]] : (!cir.bool, !s32i, !s32i) -> !s32i
 
-// LLVM: %[[VAL:.*]] = load float, ptr
-// LLVM-NEXT: %[[IS_ZERO:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 96)
-// LLVM-NEXT: br i1 %[[IS_ZERO]], label %[[BB_ZERO:.*]], label 
%[[BB_NOT_ZERO:.*]]
-// LLVM: [[BB_ZERO]]:
-// LLVM-NEXT: br label %[[BB_RET:.*]]
-// LLVM: [[BB_NOT_ZERO]]:
-// LLVM-NEXT: %[[IS_NAN:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 3)
-// LLVM-NEXT: br i1 %[[IS_NAN]], label %[[BB_NAN:.*]], label %[[BB_NOT_NAN:.*]]
-// LLVM: [[BB_NAN]]:
-// LLVM-NEXT: br label %[[BB_MERGE1:.*]]
-// LLVM: [[BB_NOT_NAN]]:
-// LLVM-NEXT: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 516)
-// LLVM-NEXT: br i1 %[[IS_INF]], label %[[BB_INF:.*]], label %[[BB_NOT_INF:.*]]
-// LLVM: [[BB_INF]]:
-// LLVM-NEXT: br label %[[BB_MERGE2:.*]]
-// LLVM: [[BB_NOT_INF]]:
-// LLVM-NEXT: %[[IS_NORMAL:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 264)
-// LLVM-NEXT: %[[NORMAL_OR_SUBNORMAL:.*]] = select i1 %[[IS_NORMAL]], i32 264, 
i32 144
-// LLVM-NEXT: br label %[[BB_MERGE2]]
-// LLVM: [[BB_MERGE2]]:
-// LLVM-NEXT: %[[PHI_INF_SEL:.*]] = phi i32 [ %[[NORMAL_OR_SUBNORMAL]], 
%[[BB_NOT_INF]] ], [ 516, %[[BB_INF]] ]
-// LLVM-NEXT: br label %[[BB_CONT1:.*]]
-// LLVM: [[BB_CONT1]]:
-// LLVM-NEXT: br label %[[BB_MERGE1]]
-// LLVM: [[BB_MERGE1]]:
-// LLVM-NEXT: %[[PHI_NAN_SEL:.*]] = phi i32 [ %[[PHI_INF_SEL]], %[[BB_CONT1]] 
], [ 3, %[[BB_NAN]] ]
-// LLVM-NEXT: br label %[[BB_CONT2:.*]]
-// LLVM: [[BB_CONT2]]:
-// LLVM-NEXT: br label %[[BB_RET]]
-// LLVM: [[BB_RET]]:
-// LLVM-NEXT: %[[PHI_FINAL:.*]] = phi i32 [ %[[PHI_NAN_SEL]], %[[BB_CONT2]] ], 
[ 96, %[[BB_ZERO]] ]
-// LLVM-NEXT: br label %[[BB_EXIT:.*]]
-// LLVM: [[BB_EXIT]]:
-
-// OGCG: %[[CMP_ZERO:.+]] = fcmp oeq float %[[VAL:.+]],
-// OGCG-NEXT: br i1 %[[CMP_ZERO]], label %[[BB_RET:.+]], label 
%[[BB_NOT_ZERO:.+]]
-// OGCG: [[BB_RET]]:
-// OGCG-NEXT: %[[PHI:.+]] = phi i32 [ 96, %[[BB_ENTRY:.+]] ], [ 3, 
%[[BB_NOT_ZERO]] ], [ 516, %[[BB_NOT_NAN:.+]] ], [ %[[SEL:.+]], 
%[[BB_NOT_INF:.+]] ]
-// OGCG: [[BB_NOT_ZERO]]:
-// OGCG-NEXT: %[[CMP_NAN:.+]] = fcmp uno float %[[VAL]], %[[VAL]]
-// OGCG-NEXT: br i1 %[[CMP_NAN]], label %[[BB_RET]], label %[[BB_NOT_NAN]]
-// OGCG: [[BB_NOT_NAN]]:
-// OGCG-NEXT: %[[FABS:.+]] = call float @llvm.fabs.f32(float %[[VAL]])
-// OGCG-NEXT: %[[CMP_INF:.+]] = fcmp oeq float %[[FABS]],
-// OGCG-NEXT: br i1 %[[CMP_INF]], label %[[BB_RET]], label %[[BB_NOT_INF]]
-// OGCG: [[BB_NOT_INF]]:
-// OGCG-NEXT: %[[CMP_NORMAL:.+]] = fcmp uge float %[[FABS]],
-// OGCG-NEXT: %[[SEL]] = select i1 %[[CMP_NORMAL]], i32 264, i32 144
-// OGCG-NEXT: br label %[[BB_RET]]
+// LLVM: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// LLVM: br i1 %[[FPCLASS1]]
+// LLVM: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS2]]
+// LLVM: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS3]]
+// LLVM: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: phi i32
+
+// OGCG: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// OGCG: br i1 %[[FPCLASS1]]
+// OGCG: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS2]]
+// OGCG: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS3]]
+// OGCG: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: phi i32
 }
 
 void test_fpclassify_zero(){
@@ -304,53 +177,21 @@ void test_fpclassify_zero(){
 // CIR: %[[SUBNORMAL_VAL:.+]] = cir.const #cir.int<144> : !s32i
 // CIR: cir.select if %[[IS_NORMAL]] then %[[NORMAL_VAL]] else 
%[[SUBNORMAL_VAL]] : (!cir.bool, !s32i, !s32i) -> !s32i
 
-// LLVM: %[[VAL:.*]] = load float, ptr
-// LLVM-NEXT: %[[IS_ZERO:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 96)
-// LLVM-NEXT: br i1 %[[IS_ZERO]], label %[[BB_ZERO:.*]], label 
%[[BB_NOT_ZERO:.*]]
-// LLVM: [[BB_ZERO]]:
-// LLVM-NEXT: br label %[[BB_RET:.*]]
-// LLVM: [[BB_NOT_ZERO]]:
-// LLVM-NEXT: %[[IS_NAN:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 3)
-// LLVM-NEXT: br i1 %[[IS_NAN]], label %[[BB_NAN:.*]], label %[[BB_NOT_NAN:.*]]
-// LLVM: [[BB_NAN]]:
-// LLVM-NEXT: br label %[[BB_MERGE1:.*]]
-// LLVM: [[BB_NOT_NAN]]:
-// LLVM-NEXT: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 516)
-// LLVM-NEXT: br i1 %[[IS_INF]], label %[[BB_INF:.*]], label %[[BB_NOT_INF:.*]]
-// LLVM: [[BB_INF]]:
-// LLVM-NEXT: br label %[[BB_MERGE2:.*]]
-// LLVM: [[BB_NOT_INF]]:
-// LLVM-NEXT: %[[IS_NORMAL:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], 
i32 264)
-// LLVM-NEXT: %[[NORMAL_OR_SUBNORMAL:.*]] = select i1 %[[IS_NORMAL]], i32 264, 
i32 144
-// LLVM-NEXT: br label %[[BB_MERGE2]]
-// LLVM: [[BB_MERGE2]]:
-// LLVM-NEXT: %[[PHI_INF_SEL:.*]] = phi i32 [ %[[NORMAL_OR_SUBNORMAL]], 
%[[BB_NOT_INF]] ], [ 516, %[[BB_INF]] ]
-// LLVM-NEXT: br label %[[BB_CONT1:.*]]
-// LLVM: [[BB_CONT1]]:
-// LLVM-NEXT: br label %[[BB_MERGE1]]
-// LLVM: [[BB_MERGE1]]:
-// LLVM-NEXT: %[[PHI_NAN_SEL:.*]] = phi i32 [ %[[PHI_INF_SEL]], %[[BB_CONT1]] 
], [ 3, %[[BB_NAN]] ]
-// LLVM-NEXT: br label %[[BB_CONT2:.*]]
-// LLVM: [[BB_CONT2]]:
-// LLVM-NEXT: br label %[[BB_RET]]
-// LLVM: [[BB_RET]]:
-// LLVM-NEXT: %[[PHI_FINAL:.*]] = phi i32 [ %[[PHI_NAN_SEL]], %[[BB_CONT2]] ], 
[ 96, %[[BB_ZERO]] ]
-// LLVM-NEXT: br label %[[BB_EXIT:.*]]
-// LLVM: [[BB_EXIT]]:
-
-// OGCG: %[[CMP_ZERO:.+]] = fcmp oeq float %[[VAL:.+]],
-// OGCG-NEXT: br i1 %[[CMP_ZERO]], label %[[BB_RET:.+]], label 
%[[BB_NOT_ZERO:.+]]
-// OGCG: [[BB_RET]]:
-// OGCG-NEXT: %[[PHI:.+]] = phi i32 [ 96, %[[BB_ENTRY:.+]] ], [ 3, 
%[[BB_NOT_ZERO]] ], [ 516, %[[BB_NOT_NAN:.+]] ], [ %[[SEL:.+]], 
%[[BB_NOT_INF:.+]] ]
-// OGCG: [[BB_NOT_ZERO]]:
-// OGCG-NEXT: %[[CMP_NAN:.+]] = fcmp uno float %[[VAL]], %[[VAL]]
-// OGCG-NEXT: br i1 %[[CMP_NAN]], label %[[BB_RET]], label %[[BB_NOT_NAN]]
-// OGCG: [[BB_NOT_NAN]]:
-// OGCG-NEXT: %[[FABS:.+]] = call float @llvm.fabs.f32(float %[[VAL]])
-// OGCG-NEXT: %[[CMP_INF:.+]] = fcmp oeq float %[[FABS]],
-// OGCG-NEXT: br i1 %[[CMP_INF]], label %[[BB_RET]], label %[[BB_NOT_INF]]
-// OGCG: [[BB_NOT_INF]]:
-// OGCG-NEXT: %[[CMP_NORMAL:.+]] = fcmp uge float %[[FABS]],
-// OGCG-NEXT: %[[SEL]] = select i1 %[[CMP_NORMAL]], i32 264, i32 144
-// OGCG-NEXT: br label %[[BB_RET]]
+// LLVM: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// LLVM: br i1 %[[FPCLASS1]]
+// LLVM: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS2]]
+// LLVM: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: br i1 %[[FPCLASS3]]
+// LLVM: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// LLVM: phi i32
+
+// OGCG: %[[FPCLASS1:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL:.*]], 
i32 {{.*}})
+// OGCG: br i1 %[[FPCLASS1]]
+// OGCG: %[[FPCLASS2:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS2]]
+// OGCG: %[[FPCLASS3:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: br i1 %[[FPCLASS3]]
+// OGCG: %[[FPCLASS4:.*]] = call i1 @llvm.is.fpclass.f32(float %[[VAL]], i32 
{{.*}})
+// OGCG: phi i32
 }
diff --git a/clang/test/CodeGen/builtin-fpclassify.c 
b/clang/test/CodeGen/builtin-fpclassify.c
new file mode 100644
index 0000000000000..d9ae3d1a5218a
--- /dev/null
+++ b/clang/test/CodeGen/builtin-fpclassify.c
@@ -0,0 +1,92 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | 
FileCheck %s
+
+#define FP_NAN 3
+#define FP_INFINITE 516
+#define FP_ZERO 96
+#define FP_SUBNORMAL 144
+#define FP_NORMAL 264
+
+void test_fpclassify_nan() {
+  float nanValue = 0.0f / 0.0f;
+  __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO,
+                       nanValue);
+// CHECK-LABEL: entry:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 3)
+// CHECK: br i1 %{{.*}}, label %fpclassify_end, label %fpclassify_not_nan
+// CHECK-LABEL: fpclassify_not_nan:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 516)
+// CHECK-LABEL: fpclassify_not_infinite:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 264)
+// CHECK-LABEL: fpclassify_not_normal:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 144)
+// CHECK-LABEL: fpclassify_end:
+// CHECK: %fpclassify_result = phi i32 [ 3, %entry ], [ 516, 
%fpclassify_not_nan ], [ 264, %fpclassify_not_infinite ], [ 144, 
%fpclassify_not_normal ], [ 96, %fpclassify_not_subnormal ]
+}
+
+void test_fpclassify_inf() {
+  float infValue = 1.0f / 0.0f;
+  __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO,
+                       infValue);
+// CHECK-LABEL: entry:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 3)
+// CHECK: br i1 %{{.*}}, label %fpclassify_end, label %fpclassify_not_nan
+// CHECK-LABEL: fpclassify_not_nan:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 516)
+// CHECK-LABEL: fpclassify_not_infinite:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 264)
+// CHECK-LABEL: fpclassify_not_normal:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 144)
+// CHECK-LABEL: fpclassify_end:
+// CHECK: %fpclassify_result = phi i32 [ 3, %entry ], [ 516, 
%fpclassify_not_nan ], [ 264, %fpclassify_not_infinite ], [ 144, 
%fpclassify_not_normal ], [ 96, %fpclassify_not_subnormal ]
+}
+
+void test_fpclassify_normal() {
+  float normalValue = 1.0f;
+  __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO,
+                       normalValue);
+// CHECK-LABEL: entry:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 3)
+// CHECK: br i1 %{{.*}}, label %fpclassify_end, label %fpclassify_not_nan
+// CHECK-LABEL: fpclassify_not_nan:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 516)
+// CHECK-LABEL: fpclassify_not_infinite:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 264)
+// CHECK-LABEL: fpclassify_not_normal:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 144)
+// CHECK-LABEL: fpclassify_end:
+// CHECK: %fpclassify_result = phi i32 [ 3, %entry ], [ 516, 
%fpclassify_not_nan ], [ 264, %fpclassify_not_infinite ], [ 144, 
%fpclassify_not_normal ], [ 96, %fpclassify_not_subnormal ]
+}
+
+void test_fpclassify_subnormal() {
+  float subnormalValue = 1.0e-40f;
+  __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO,
+                       subnormalValue);
+// CHECK-LABEL: entry:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 3)
+// CHECK: br i1 %{{.*}}, label %fpclassify_end, label %fpclassify_not_nan
+// CHECK-LABEL: fpclassify_not_nan:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 516)
+// CHECK-LABEL: fpclassify_not_infinite:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 264)
+// CHECK-LABEL: fpclassify_not_normal:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 144)
+// CHECK-LABEL: fpclassify_end:
+// CHECK: %fpclassify_result = phi i32 [ 3, %entry ], [ 516, 
%fpclassify_not_nan ], [ 264, %fpclassify_not_infinite ], [ 144, 
%fpclassify_not_normal ], [ 96, %fpclassify_not_subnormal ]
+}
+
+void test_fpclassify_zero() {
+  float zeroValue = 0.0f;
+  __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO,
+                       zeroValue);
+// CHECK-LABEL: entry:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 3)
+// CHECK: br i1 %{{.*}}, label %fpclassify_end, label %fpclassify_not_nan
+// CHECK-LABEL: fpclassify_not_nan:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 516)
+// CHECK-LABEL: fpclassify_not_infinite:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 264)
+// CHECK-LABEL: fpclassify_not_normal:
+// CHECK: call i1 @llvm.is.fpclass.f32(float %{{.*}}, i32 144)
+// CHECK-LABEL: fpclassify_end:
+// CHECK: %fpclassify_result = phi i32 [ 3, %entry ], [ 516, 
%fpclassify_not_nan ], [ 264, %fpclassify_not_infinite ], [ 144, 
%fpclassify_not_normal ], [ 96, %fpclassify_not_subnormal ]
+}
diff --git a/clang/test/Headers/nvptx_device_math_macro.cpp 
b/clang/test/Headers/nvptx_device_math_macro.cpp
index 3faf527daf113..e360401e0e2d3 100644
--- a/clang/test/Headers/nvptx_device_math_macro.cpp
+++ b/clang/test/Headers/nvptx_device_math_macro.cpp
@@ -8,10 +8,10 @@
 #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
   return (std::fpclassify(a) != FP_ZERO);
+// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 {{.*}})
+// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 {{.*}})
+// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 {{.*}})
+// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 {{.*}})
 }
 #pragma omp end declare target

>From b13bbd7198eb3ccdc88bff4f59ee382cef06f51f Mon Sep 17 00:00:00 2001
From: YeonguChoe <[email protected]>
Date: Tue, 7 Apr 2026 17:23:44 -0400
Subject: [PATCH 2/2] Change FileCheck test code that uses fpclassify

---
 clang/test/CodeGen/strictfp_builtins.c | 43 ++++++++++++++------------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/clang/test/CodeGen/strictfp_builtins.c 
b/clang/test/CodeGen/strictfp_builtins.c
index 58815c7de4fa9..6cb76e431bea7 100644
--- a/clang/test/CodeGen/strictfp_builtins.c
+++ b/clang/test/CodeGen/strictfp_builtins.c
@@ -28,26 +28,26 @@ void p(char *str, int x) {
 
 // CHECK-LABEL: @test_fpclassify(
 // CHECK-NEXT:  entry:
-// 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:    {{.*}} = alloca double, align 8
+// CHECK-NEXT:    store double {{.*}}, ptr {{.*}}, align 8
+// CHECK-NEXT:    {{.*}} = load double, ptr {{.*}}, align 8
+// CHECK-NEXT:    {{.*}} = call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) 
#[[ATTR4]]
+// CHECK-NEXT:    br i1 {{.*}}, label {{.*}}, label {{.*}}
+// CHECK:       fpclassify_not_nan:
+// CHECK-NEXT:    {{.*}} = call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 
516) #[[ATTR4]]
+// CHECK-NEXT:    br i1 {{.*}}, label {{.*}}, label {{.*}}
+// CHECK:       fpclassify_not_infinite:
+// CHECK-NEXT:    {{.*}} = call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 
264) #[[ATTR4]]
+// CHECK-NEXT:    br i1 {{.*}}, label {{.*}}, label {{.*}}
+// CHECK:       fpclassify_not_normal:
+// CHECK-NEXT:    {{.*}} = call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 
144) #[[ATTR4]]
+// CHECK-NEXT:    br i1 {{.*}}, label {{.*}}, label {{.*}}
+// CHECK:       fpclassify_not_subnormal:
+// CHECK-NEXT:    br label {{.*}}
 // 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:    call void @p(ptr noundef @.str.1, i32 noundef 
[[FPCLASSIFY_RESULT]]) #[[ATTR4]]
+// CHECK-NEXT:    {{.*}} = phi i32 [ 0, {{.*}} ], [ 1, {{.*}} ], [ 2, {{.*}} 
], [ 3, {{.*}} ], [ 4, {{.*}} ]
+// CHECK-NEXT:    call void @p(ptr noundef @.str.1, i32 noundef {{.*}}) 
#[[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:       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 label [[FPCLASSIFY_END]]
 //
 void test_fpclassify(double d) {
   P(fpclassify, (0, 1, 2, 3, 4, d));
@@ -156,7 +156,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]]) 
#[[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
@@ -234,3 +234,8 @@ void test_isnormal(double d) {
 
   return;
 }
+
+//.
+//. CHECK: attributes #[[ATTR4]] = { strictfp }
+//. CHECK: attributes #[[ATTR5]] = { strictfp memory(none) }
+//.

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to