[llvm-branch-commits] [clang] [CIR] Migrate the FPClassTest bit enum and unquote its flags (PR #220888)
Henrich Lauko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Sep 3 05:46:03 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/220888
>From 5b9809d17295a428a794ad22b9d6a2af5f670f92 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Thu, 3 Sep 2026 12:44:31 +0000
Subject: [PATCH] [CIR] Migrate the FPClassTest bit enum and unquote its flags
cir.is_fp_class printed its flags inconsistently. Single-bit values came out
bare, as in `fcSNan`, while group values and combinations came out quoted, as
in `"fcInf"` and `"fcSNan|fcNegInf"`. That comes from I32BitEnumAttr setting
printBitEnumQuoted, which EnumAttr.td keeps only for backwards compatibility.
Clearing the bit and using the `enum` directive selects the separator-aware
parser and printer, so every value now spells unquoted:
cir.is_fp_class %x, fcSNan|fcNegInf : (!cir.float) -> !cir.bool
The enum also drops its specialized IntegerAttr for a CIR_EnumAttr wrapper,
giving it the standalone spelling `#cir.fp_class<fcSNan|fcNegInf>`. This
changes operation syntax, so it updates 37 CHECK lines.
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 14 ++++++-
.../CIR/CodeGenBuiltins/builtin-fpclassify.c | 40 +++++++++----------
.../CIR/CodeGenBuiltins/builtin-isfpclass.c | 32 +++++++--------
.../CIR/CodeGenBuiltins/builtin-isinf-sign.c | 2 +-
clang/test/CIR/IR/enum-attrs.cir | 20 +++++++++-
5 files changed, 67 insertions(+), 41 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index ad4e6600cddf1..4fe1c5a696e1d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6955,8 +6955,18 @@ def FPClassTestEnum
FPClass_Sub, FPClass_Zero, FPClass_PosFin, FPClass_NegFin, FPClass_Fin,
FPClass_Pos, FPClass_Neg, FPClass_All]> {
let printBitEnumPrimaryGroups = 1;
+
+ // I32BitEnumAttr turns this on for backwards compatibility, which makes the
+ // operation printer quote every value that is not a single bit. Turning it
+ // off, together with the `enum` directive on cir.is_fp_class, gets a
+ // separator-aware parser and printer that spell every value unquoted.
+ let printBitEnumQuoted = 0;
+
+ let genSpecializedAttr = 0;
}
+def CIR_FPClassTestAttr : CIR_EnumAttr<FPClassTestEnum, "fp_class">;
+
def CIR_IsFPClassOp : CIR_Op<"is_fp_class", [Pure]> {
let summary = "Corresponding to the `__builtin_fpclassify` builtin function in clang";
@@ -6983,10 +6993,10 @@ def CIR_IsFPClassOp : CIR_Op<"is_fp_class", [Pure]> {
}];
let arguments = (ins CIR_AnyFloatType:$src,
- FPClassTestEnum:$flags);
+ CIR_FPClassTestAttr:$flags);
let results = (outs CIR_BoolType:$result);
let assemblyFormat = [{
- $src `,` $flags `:` functional-type($src, $result) attr-dict
+ $src `,` enum($flags) `:` functional-type($src, $result) attr-dict
}];
}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c b/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c
index abdfe67e8527c..780f242bbef59 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-fpclassify.c
@@ -15,16 +15,16 @@ void test_fpclassify_nan(){
float nanValue = 0.0f / 0.0f;
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
FP_SUBNORMAL, FP_ZERO, nanValue);
-// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, "fcZero" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, fcZero : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_ZERO]], true {
// CIR: cir.const #cir.int<96> : !s32i
-// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, "fcNan" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, fcNan : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_NAN]], true {
// CIR: cir.const #cir.int<3> : !s32i
-// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, "fcInf" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, fcInf : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_INF]], true {
// CIR: cir.const #cir.int<516> : !s32i
-// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, "fcNormal" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, fcNormal : (!cir.float) -> !cir.bool
// CIR: %[[NORMAL_VAL:.+]] = cir.const #cir.int<264> : !s32i
// 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
@@ -84,16 +84,16 @@ void test_fpclassify_inf(){
float infValue = 1.0f / 0.0f;
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
FP_SUBNORMAL, FP_ZERO, infValue);
-// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, "fcZero" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, fcZero : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_ZERO]], true {
// CIR: cir.const #cir.int<96> : !s32i
-// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, "fcNan" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, fcNan : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_NAN]], true {
// CIR: cir.const #cir.int<3> : !s32i
-// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, "fcInf" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, fcInf : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_INF]], true {
// CIR: cir.const #cir.int<516> : !s32i
-// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, "fcNormal" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, fcNormal : (!cir.float) -> !cir.bool
// CIR: %[[NORMAL_VAL:.+]] = cir.const #cir.int<264> : !s32i
// 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
@@ -152,16 +152,16 @@ void test_fpclassify_normal(){
float normalValue = 1.0f;
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
FP_SUBNORMAL, FP_ZERO, normalValue);
-// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, "fcZero" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, fcZero : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_ZERO]], true {
// CIR: cir.const #cir.int<96> : !s32i
-// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, "fcNan" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, fcNan : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_NAN]], true {
// CIR: cir.const #cir.int<3> : !s32i
-// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, "fcInf" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, fcInf : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_INF]], true {
// CIR: cir.const #cir.int<516> : !s32i
-// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, "fcNormal" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, fcNormal : (!cir.float) -> !cir.bool
// CIR: %[[NORMAL_VAL:.+]] = cir.const #cir.int<264> : !s32i
// 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
@@ -221,16 +221,16 @@ void test_fpclassify_subnormal(){
float subnormalValue = 1.0e-40f;
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
FP_SUBNORMAL, FP_ZERO, subnormalValue);
-// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, "fcZero" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, fcZero : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_ZERO]], true {
// CIR: cir.const #cir.int<96> : !s32i
-// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, "fcNan" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, fcNan : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_NAN]], true {
// CIR: cir.const #cir.int<3> : !s32i
-// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, "fcInf" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, fcInf : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_INF]], true {
// CIR: cir.const #cir.int<516> : !s32i
-// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, "fcNormal" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, fcNormal : (!cir.float) -> !cir.bool
// CIR: %[[NORMAL_VAL:.+]] = cir.const #cir.int<264> : !s32i
// 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
@@ -290,16 +290,16 @@ void test_fpclassify_zero(){
float zeroValue = 0.0f;
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
FP_SUBNORMAL, FP_ZERO, zeroValue);
-// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, "fcZero" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_ZERO:.+]] = cir.is_fp_class %{{.+}}, fcZero : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_ZERO]], true {
// CIR: cir.const #cir.int<96> : !s32i
-// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, "fcNan" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NAN:.+]] = cir.is_fp_class %{{.+}}, fcNan : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_NAN]], true {
// CIR: cir.const #cir.int<3> : !s32i
-// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, "fcInf" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_INF:.+]] = cir.is_fp_class %{{.+}}, fcInf : (!cir.float) -> !cir.bool
// CIR: cir.ternary(%[[IS_INF]], true {
// CIR: cir.const #cir.int<516> : !s32i
-// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, "fcNormal" : (!cir.float) -> !cir.bool
+// CIR: %[[IS_NORMAL:.+]] = cir.is_fp_class %{{.+}}, fcNormal : (!cir.float) -> !cir.bool
// CIR: %[[NORMAL_VAL:.+]] = cir.const #cir.int<264> : !s32i
// 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
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-isfpclass.c b/clang/test/CIR/CodeGenBuiltins/builtin-isfpclass.c
index 880e5e444aff8..6157a3c293a5f 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-isfpclass.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-isfpclass.c
@@ -10,55 +10,55 @@ int finite(double);
void test_is_finite(__fp16 *H, float F, double D, long double LD) {
volatile int res;
res = __builtin_isinf(*H);
- // CIR: cir.is_fp_class %{{.*}}, "fcInf" : (!cir.f16) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcInf : (!cir.f16) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (inf) */ i32 516)
// OGCG: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (inf) */ i32 516)
res = __builtin_isinf(F);
- // CIR: cir.is_fp_class %{{.*}}, "fcInf" : (!cir.float) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcInf : (!cir.float) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (inf) */ i32 516)
// OGCG: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (inf) */ i32 516)
res = __builtin_isinf(D);
- // CIR: cir.is_fp_class %{{.*}}, "fcInf" : (!cir.double) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcInf : (!cir.double) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f64(double {{.*}}, /* (inf) */ i32 516)
// OGCG: call i1 @llvm.is.fpclass.f64(double {{.*}}, /* (inf) */ i32 516)
res = __builtin_isinf(LD);
- // CIR: cir.is_fp_class %{{.*}}, "fcInf" : (!cir.long_double<!cir.f80>) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcInf : (!cir.long_double<!cir.f80>) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f80(x86_fp80 {{.*}}, /* (inf) */ i32 516)
// OGCG: call i1 @llvm.is.fpclass.f80(x86_fp80 {{.*}}, /* (inf) */ i32 516)
res = __builtin_isfinite(*H);
- // CIR: cir.is_fp_class %{{.*}}, "fcFinite" : (!cir.f16) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcFinite : (!cir.f16) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (zero sub norm) */ i32 504)
// OGCG: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (zero sub norm) */ i32 504)
res = __builtin_isfinite(F);
- // CIR: cir.is_fp_class %{{.*}}, "fcFinite" : (!cir.float) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcFinite : (!cir.float) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (zero sub norm) */ i32 504)
// OGCG: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (zero sub norm) */ i32 504)
res = finite(D);
- // CIR: cir.is_fp_class %{{.*}}, "fcFinite" : (!cir.double) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcFinite : (!cir.double) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f64(double {{.*}}, /* (zero sub norm) */ i32 504)
// OGCG: call i1 @llvm.is.fpclass.f64(double %20, /* (zero sub norm) */ i32 504)
res = __builtin_isnormal(*H);
- // CIR: cir.is_fp_class %{{.*}}, "fcNormal" : (!cir.f16) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcNormal : (!cir.f16) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (norm) */ i32 264)
// OGCG: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (norm) */ i32 264)
res = __builtin_isnormal(F);
- // CIR: cir.is_fp_class %{{.*}}, "fcNormal" : (!cir.float) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcNormal : (!cir.float) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (norm) */ i32 264)
// OGCG: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (norm) */ i32 264)
res = __builtin_issubnormal(F);
- // CIR: cir.is_fp_class %{{.*}}, "fcSubnormal" : (!cir.float) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcSubnormal : (!cir.float) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (sub) */ i32 144)
// OGCG: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (sub) */ i32 144)
res = __builtin_iszero(F);
- // CIR: cir.is_fp_class %{{.*}}, "fcZero" : (!cir.float) -> !cir.bool
+ // CIR: cir.is_fp_class %{{.*}}, fcZero : (!cir.float) -> !cir.bool
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (zero) */ i32 96)
// OGCG: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (zero) */ i32 96)
res = __builtin_issignaling(F);
@@ -72,7 +72,7 @@ _Bool check_isfpclass_finite(float x) {
}
// CIR: cir.func {{.*}}@check_isfpclass_finite
-// CIR: cir.is_fp_class %{{.*}}, "fcFinite" : (!cir.float)
+// CIR: cir.is_fp_class %{{.*}}, fcFinite : (!cir.float)
// LLVM: @check_isfpclass_finite
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (zero sub norm) */ i32 504)
// OGCG: @check_isfpclass_finite
@@ -83,7 +83,7 @@ _Bool check_isfpclass_nan_f32(float x) {
}
// CIR: cir.func {{.*}}@check_isfpclass_nan_f32
-// CIR: cir.is_fp_class %{{.*}}, "fcNan" : (!cir.float)
+// CIR: cir.is_fp_class %{{.*}}, fcNan : (!cir.float)
// LLVM: @check_isfpclass_nan_f32
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (nan) */ i32 3)
// OGCG: @check_isfpclass_nan_f32
@@ -107,7 +107,7 @@ _Bool check_isfpclass_zero_f16(_Float16 x) {
}
// CIR: cir.func {{.*}}@check_isfpclass_zero_f16
-// CIR: cir.is_fp_class %{{.*}}, "fcZero" : (!cir.f16)
+// CIR: cir.is_fp_class %{{.*}}, fcZero : (!cir.f16)
// LLVM: @check_isfpclass_zero_f16
// LLVM: call i1 @llvm.is.fpclass.f16(half {{.*}}, /* (zero) */ i32 96)
// OGCG: @check_isfpclass_zero_f16
@@ -118,7 +118,7 @@ _Bool check_isfpclass_snan_neginf(double x) {
}
// CIR: cir.func {{.*}}@check_isfpclass_snan_neginf
-// CIR: cir.is_fp_class %{{.*}}, "fcSNan|fcNegInf" : (!cir.double)
+// CIR: cir.is_fp_class %{{.*}}, fcSNan|fcNegInf : (!cir.double)
// LLVM: @check_isfpclass_snan_neginf
// LLVM: call i1 @llvm.is.fpclass.f64(double {{.*}}, /* (snan ninf) */ i32 5)
// OGCG: @check_isfpclass_snan_neginf
@@ -129,7 +129,7 @@ _Bool check_isfpclass_multi(float x) {
}
// CIR: cir.func {{.*}}@check_isfpclass_multi
-// CIR: cir.is_fp_class %{{.*}}, "fcNegative|fcPositive|fcQNan" : (!cir.float)
+// CIR: cir.is_fp_class %{{.*}}, fcNegative|fcPositive|fcQNan : (!cir.float)
// LLVM: @check_isfpclass_multi
// LLVM: call i1 @llvm.is.fpclass.f32(float {{.*}}, /* (qnan inf zero sub norm) */ i32 1022)
// OGCG: @check_isfpclass_multi
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c b/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c
index 91c2e13096dc4..ffe9bea037391 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c
@@ -8,7 +8,7 @@
int test_float_isinf_sign(float x) {
// CIR-LABEL: test_float_isinf_sign
// CIR: %[[ARG:.*]] = cir.load align(4) %{{.*}} : !cir.ptr<!cir.float>, !cir.float
- // CIR: %[[IS_INF:.*]] = cir.is_fp_class %[[ARG]], "fcInf" : (!cir.float) -> !cir.bool
+ // CIR: %[[IS_INF:.*]] = cir.is_fp_class %[[ARG]], fcInf : (!cir.float) -> !cir.bool
// CIR: %[[IS_NEG:.*]] = cir.signbit %[[ARG]] : !cir.float -> !cir.bool
// CIR: %[[C_0:.*]] = cir.const #cir.int<0> : !s32i
// CIR: %[[C_1:.*]] = cir.const #cir.int<1> : !s32i
diff --git a/clang/test/CIR/IR/enum-attrs.cir b/clang/test/CIR/IR/enum-attrs.cir
index aafc58e792678..da6d2e59dbda9 100644
--- a/clang/test/CIR/IR/enum-attrs.cir
+++ b/clang/test/CIR/IR/enum-attrs.cir
@@ -142,21 +142,37 @@ cir.func @side_effect_attr() {
// CHECK: cir.func @side_effect_attr() {
// CHECK: cir.return {cir.test = [#cir.side_effect<all>, #cir.side_effect<pure>, #cir.side_effect<const>]}
+// A bit enum, so a value can name several flags.
+cir.func @fp_class_attr() {
+ cir.return {cir.test = [#cir.fp_class<fcNone>,
+ #cir.fp_class<fcSNan>,
+ #cir.fp_class<fcInf>,
+ #cir.fp_class<fcSNan|fcNegInf>]}
+}
+
+// CHECK: cir.func @fp_class_attr() {
+// CHECK: cir.return {cir.test = [#cir.fp_class<fcNone>, #cir.fp_class<fcSNan>, #cir.fp_class<fcInf>, #cir.fp_class<fcSNan|fcNegInf>]}
+
// The operations themselves keep printing a bare keyword.
cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i,
- %arg2: !cir.ptr<!s32i>) {
+ %arg2: !cir.ptr<!s32i>,
+ %arg3: !cir.float) {
%0 = cir.cast bitcast %arg0 : !s32i -> !s32i
%1 = cir.cmp lt %arg0, %arg1 : !s32i
%2 = cir.load syncscope(system) atomic(seq_cst) %arg2 : !cir.ptr<!s32i>, !s32i
cir.atomic.fence syncscope(system) seq_cst
+ %3 = cir.is_fp_class %arg3, fcInf : (!cir.float) -> !cir.bool
+ %4 = cir.is_fp_class %arg3, fcSNan|fcNegInf : (!cir.float) -> !cir.bool
cir.return
}
-// CHECK: cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i, %arg2: !cir.ptr<!s32i>) {
+// CHECK: cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i, %arg2: !cir.ptr<!s32i>, %arg3: !cir.float) {
// CHECK: %0 = cir.cast bitcast %arg0 : !s32i -> !s32i
// CHECK: %1 = cir.cmp lt %arg0, %arg1 : !s32i
// CHECK: %2 = cir.load syncscope(system) atomic(seq_cst) %arg2 : !cir.ptr<!s32i>, !s32i
// CHECK: cir.atomic.fence syncscope(system) seq_cst
+// CHECK: %3 = cir.is_fp_class %arg3, fcInf : (!cir.float) -> !cir.bool
+// CHECK: %4 = cir.is_fp_class %arg3, fcSNan|fcNegInf : (!cir.float) -> !cir.bool
// cir.global's linkage is the one bare keyword that cannot be checked from
// inside a function.
More information about the llvm-branch-commits
mailing list