[llvm-branch-commits] [clang] [CIR] Drop the redundant suffix from the inline kind mnemonic (PR #220892)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Sep 6 12:21:16 PDT 2026


https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/220892

>From fcc45379f369d0f461d3815effe64f228e747ea8 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 1/4] [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, 69 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 632b107402a19..cd0a401d9b77f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6993,8 +6993,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";
 
@@ -7021,10 +7031,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 2e675c2681b94..e3979fcd138f4 100644
--- a/clang/test/CIR/IR/enum-attrs.cir
+++ b/clang/test/CIR/IR/enum-attrs.cir
@@ -127,6 +127,17 @@ cir.func @side_effect_attr() {
                           #cir.side_effect<const>]}
 }
 
+// A bit enum, so a value can name several flags.
+
+// CHECK-LABEL: cir.func @fp_class_attr() {
+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>]}
+  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.
 
 // CHECK-LABEL: cir.func @mem_order_sync_scope_ops(%arg0: !cir.ptr<!s32i>) {
@@ -138,6 +149,15 @@ cir.func @mem_order_sync_scope_ops(%arg0: !cir.ptr<!s32i>) {
   cir.return
 }
 
+// CHECK-LABEL: cir.func @fp_class_ops(%arg0: !cir.float) {
+cir.func @fp_class_ops(%arg0: !cir.float) {
+  // CHECK: %0 = cir.is_fp_class %arg0, fcInf : (!cir.float) -> !cir.bool
+  %0 = cir.is_fp_class %arg0, fcInf : (!cir.float) -> !cir.bool
+  // CHECK: %1 = cir.is_fp_class %arg0, fcSNan|fcNegInf : (!cir.float) -> !cir.bool
+  %1 = cir.is_fp_class %arg0, fcSNan|fcNegInf : (!cir.float) -> !cir.bool
+  cir.return
+}
+
 // cir.global's linkage is the one bare keyword that cannot be checked from
 // inside a function.
 

>From 6883a31d9e8ae9949b3608de8d47eb156c729f9c 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 2/4] [CIR] Move the CIR enums off the legacy EnumAttrInfo
 hierarchy

MLIR has two enum hierarchies. `EnumAttrInfo` doubles as an `IntegerAttr`
constraint, so every CIR enum had to clear `genSpecializedAttr` to say it did
not want one. `EnumInfo` describes a C++ enum and nothing more.

Derive the CIR bases from `I32Enum`, `I64Enum` and `I32BitEnum`, and widen
`CIR_EnumAttr` to the `EnumInfo` that upstream `EnumAttr` already takes. The
flag no longer exists to clear. `FPClassTestEnum` gets unquoted printing from
`BitEnumBase` rather than overriding `printBitEnumQuoted`, and
`CIR_KnownFuncKind` drops a `parameterPrinter` the generated `operator<<`
now covers, still spelling `#cir.func_identity<"std::find">`.

AMDGPU wraps an `I32Enum` in an `EnumAttr` with this same bracketed format.
Parsing moves to the generated `FieldParser`, whose diagnostic names the
accepted spellings, so two `expected-error` lines change. Generated attribute
code drops 16 KB as 28 inlined parsers collapse into it.
---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  |  76 ++++---------
 .../clang/CIR/Dialect/IR/CIRCUDAAttrs.td      |   6 +-
 .../clang/CIR/Dialect/IR/CIREnumAttr.td       |  22 ++--
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 106 ++++++------------
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  |   4 +-
 clang/test/CIR/IR/invalid-call.cir            |   2 +-
 clang/test/CIR/IR/invalid-lang-attr.cir       |   2 +-
 7 files changed, 74 insertions(+), 144 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index f08a127dcd192..838d8975177fd 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -78,16 +78,12 @@ class CIR_UnitAttr<string name, string attrMnemonic, list<Trait> traits = []>
 
 // TODO: Add cases for other languages that Clang supports.
 
-def CIR_SourceLanguage : CIR_I32EnumAttr<"SourceLanguage", "source language", [
+def CIR_SourceLanguage : CIR_I32Enum<"SourceLanguage", "source language", [
   I32EnumAttrCase<"C", 1, "c">,
   I32EnumAttrCase<"CXX", 2, "cxx">,
   I32EnumAttrCase<"OpenCLC", 3, "opencl_c">,
   I32EnumAttrCase<"OpenCLCXX", 4, "opencl_cxx">
-]> {
-  // The enum attr class is defined in `CIR_SourceLanguageAttr` below,
-  // so that it can define extra class methods.
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_SourceLanguageAttr : CIR_EnumAttr<CIR_SourceLanguage, "lang"> {
 
@@ -123,14 +119,12 @@ def CIR_SourceLanguageAttr : CIR_EnumAttr<CIR_SourceLanguage, "lang"> {
 // ArgPassingKind + RecordLayoutAttr
 //===----------------------------------------------------------------------===//
 
-def CIR_ArgPassingKind : CIR_I32EnumAttr<
+def CIR_ArgPassingKind : CIR_I32Enum<
     "ArgPassingKind", "record argument passing eligibility", [
   I32EnumAttrCase<"CanPassInRegs", 0, "can_pass_in_regs">,
   I32EnumAttrCase<"CannotPassInRegs", 1, "cannot_pass_in_regs">,
   I32EnumAttrCase<"CanNeverPassInRegs", 2, "can_never_pass_in_regs">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_RecordLayoutAttr : CIR_Attr<"RecordLayout", "record_layout", [
     // record_align is consumed as an llvm::Align, whose constructor asserts a
@@ -732,14 +726,12 @@ def CIR_MethodAttr : CIR_ValueLikeAttr<"Method", "method"> {
 // CmpThreeWayInfoAttr
 //===----------------------------------------------------------------------===//
 
-def CIR_CmpOrdering : CIR_I32EnumAttr<
+def CIR_CmpOrdering : CIR_I32Enum<
   "CmpOrdering", "three-way comparison ordering kind", [
     I32EnumAttrCase<"Strong", 0, "strong">,
     I32EnumAttrCase<"Weak", 1, "weak">,
     I32EnumAttrCase<"Partial", 2, "partial">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", "cmp3way_info"> {
   let summary = "Holds information about a three-way comparison operation";
@@ -816,7 +808,7 @@ def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", "cmp3way_info"> {
 // FenvAttr
 //===----------------------------------------------------------------------===//
 
-def CIR_FPDynamicRoundingMode : CIR_I32EnumAttr<
+def CIR_FPDynamicRoundingMode : CIR_I32Enum<
     "FPDynamicRoundingMode", "floating-point dynamic rounding mode", [
   I32EnumAttrCase<"ToNearest", 0, "tonearest">,
   I32EnumAttrCase<"Downward", 1, "downward">,
@@ -830,10 +822,9 @@ def CIR_FPDynamicRoundingMode : CIR_I32EnumAttr<
     If the actual dynamic rounding mode differs from this value, the behavior
     is undefined.
   }];
-  let genSpecializedAttr = 0;
 }
 
-def CIR_FPExceptionMode : CIR_I32EnumAttr<
+def CIR_FPExceptionMode : CIR_I32Enum<
     "FPExceptionMode", "floating-point exception mode", [
   I32EnumAttrCase<"Unknown", 0, "unknown">,
   I32EnumAttrCase<"Masked", 1, "masked">,
@@ -844,7 +835,6 @@ def CIR_FPExceptionMode : CIR_I32EnumAttr<
     executed. If the actual exception mode differs from this value, the
     behavior is undefined.
   }];
-  let genSpecializedAttr = 0;
 }
 
 def CIR_FenvAttr : CIR_Attr<"Fenv", "fenv"> {
@@ -1351,13 +1341,11 @@ def CIR_ConstComplexAttr : CIR_ValueLikeAttr<"ConstComplex", "const_complex"> {
 // VisibilityKind
 //===----------------------------------------------------------------------===//
 
-def CIR_VisibilityKind : CIR_I32EnumAttr<"VisibilityKind", "C/C++ visibility", [
+def CIR_VisibilityKind : CIR_I32Enum<"VisibilityKind", "C/C++ visibility", [
   I32EnumAttrCase<"Default", 0, "default">,
   I32EnumAttrCase<"Hidden", 1, "hidden">,
   I32EnumAttrCase<"Protected", 2, "protected">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 //===----------------------------------------------------------------------===//
 // GloblCtorAttr
@@ -1417,14 +1405,12 @@ def CIR_GlobalDtorAttr : CIR_GlobalCtorDtor<"Dtor", "dtor"> {
 // CXX SpecialMemberAttr
 //===----------------------------------------------------------------------===//
 
-def CIR_CtorKind : CIR_I32EnumAttr<"CtorKind", "CXX Constructor Kind", [
+def CIR_CtorKind : CIR_I32Enum<"CtorKind", "CXX Constructor Kind", [
   I32EnumAttrCase<"Custom", 0, "custom">,
   I32EnumAttrCase<"Default", 1, "default">,
   I32EnumAttrCase<"Copy", 2, "copy">,
   I32EnumAttrCase<"Move", 3, "move">,
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CXXCtorAttr : CIR_Attr<"CXXCtor", "cxx_ctor"> {
   let summary = "Marks a function as a C++ constructor";
@@ -1485,12 +1471,10 @@ def CIR_CXXDtorAttr : CIR_Attr<"CXXDtor", "cxx_dtor"> {
   }];
 }
 
-def CIR_AssignKind : CIR_I32EnumAttr<"AssignKind", "CXX Assignment Operator Kind", [
+def CIR_AssignKind : CIR_I32Enum<"AssignKind", "CXX Assignment Operator Kind", [
   I32EnumAttrCase<"Copy", 0, "copy">,
   I32EnumAttrCase<"Move", 1, "move">,
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CXXAssignAttr : CIR_Attr<"CXXAssign", "cxx_assign"> {
   let summary = "Marks a function as a CXX assignment operator";
@@ -1526,16 +1510,10 @@ def CIR_CXXAssignAttr : CIR_Attr<"CXXAssign", "cxx_assign"> {
 
 // The standard library entities the identity tag can name. Each entry
 // pairs with one raised operation in CIRStdOps.td.
-def CIR_KnownFuncKind : CIR_I32EnumAttr<"KnownFuncKind",
+def CIR_KnownFuncKind : CIR_I32Enum<"KnownFuncKind",
     "known standard library entity", [
   I32EnumAttrCase<"StdFind", 1, "std::find">,
-]> {
-  let genSpecializedAttr = 0;
-  // A name like std::find is not a bare identifier, so print it as a quoted
-  // string. The enum parser already reads a quoted string back.
-  let parameterPrinter =
-      "$_printer.printKeywordOrString(" # symbolToStringFnName # "($_self))";
-}
+]>;
 
 def CIR_FuncIdentityAttr : CIR_Attr<"FuncIdentity", "func_identity"> {
   let summary = "Identifies a function as a known standard library entity";
@@ -1821,13 +1799,11 @@ def CIR_TypeInfoAttr : CIR_ValueLikeAttr<"TypeInfo", "typeinfo"> {
 // InlineKindAttr
 //===----------------------------------------------------------------------===//
 
-def CIR_InlineKind : CIR_I32EnumAttr<"InlineKind", "inlineKind", [
+def CIR_InlineKind : CIR_I32Enum<"InlineKind", "inlineKind", [
   I32EnumAttrCase<"NoInline", 1, "no_inline">,
   I32EnumAttrCase<"AlwaysInline", 2, "always_inline">,
   I32EnumAttrCase<"InlineHint", 3, "inline_hint">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_InlineKindAttr: CIR_EnumAttr<CIR_InlineKind, "inline_kind"> {
   let summary = "Inline kind attribute";
@@ -1937,7 +1913,7 @@ def CIR_BlockAddrDiffAttr
 // Side Effect
 //===----------------------------------------------------------------------===//
 
-def CIR_SideEffect : CIR_I32EnumAttr<
+def CIR_SideEffect : CIR_I32Enum<
     "SideEffect", "allowed side effects of a function", [
       I32EnumAttrCase<"All", 0, "all">,
       I32EnumAttrCase<"Pure", 1, "pure">,
@@ -1964,8 +1940,6 @@ def CIR_SideEffect : CIR_I32EnumAttr<
     %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(const)
     ```
   }];
-
-  let genSpecializedAttr = 0;
 }
 
 def CIR_SideEffectAttr : CIR_EnumAttr<CIR_SideEffect, "side_effect">;
@@ -2123,18 +2097,16 @@ def CIR_ASTVarDeclAttr : CIR_AST<"VarDecl", "var.decl", [
 // CIR-native thread-local storage kind. Cases mirror clang::VarDecl::TLSKind
 // so CIRGen can map between them, but CIR does not depend on the underlying
 // clang enumerator values.
-def CIR_TLSKind : CIR_I32EnumAttr<"TLSKind", "thread-local storage kind", [
+def CIR_TLSKind : CIR_I32Enum<"TLSKind", "thread-local storage kind", [
   I32EnumAttrCase<"None", 0, "none">,          // clang::VarDecl::TLS_None
   I32EnumAttrCase<"Static", 1, "static">,      // clang::VarDecl::TLS_Static
   I32EnumAttrCase<"Dynamic", 2, "dynamic">     // clang::VarDecl::TLS_Dynamic
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 // CIR-native template-specialization kind. Cases mirror
 // clang::TemplateSpecializationKind.
 def CIR_TemplateSpecializationKind
-    : CIR_I32EnumAttr<"TemplateSpecializationKind",
+    : CIR_I32Enum<"TemplateSpecializationKind",
                       "template specialization kind", [
   // clang::TSK_Undeclared
   I32EnumAttrCase<"Undeclared", 0, "undeclared">,
@@ -2148,9 +2120,7 @@ def CIR_TemplateSpecializationKind
   // clang::TSK_ExplicitInstantiationDefinition
   I32EnumAttrCase<"ExplicitInstantiationDefinition", 4,
                   "explicit_instantiation_definition">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_StaticLocalInfoAttr
     : CIR_Attr<"StaticLocalInfo", "static_local_info"> {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td
index 2d5f70ec9c3ad..1684615c862b2 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td
@@ -70,14 +70,12 @@ def CIR_CUDABinaryHandleAttr : CIR_Attr<
 
 // No wrapper attribute: the kind is only ever printed by
 // CIR_CUDAVarRegistrationInfoAttr's own assembly format.
-def CIR_CUDADeviceVarKind : CIR_I32EnumAttr<"CUDADeviceVarKind",
+def CIR_CUDADeviceVarKind : CIR_I32Enum<"CUDADeviceVarKind",
     "CUDA device variable kind", [
   I32EnumAttrCase<"Variable", 0>,
   I32EnumAttrCase<"Surface", 1>,   // Future
   I32EnumAttrCase<"Texture", 2>,   // Future
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 // Attribute carrying device variable registration flags
 def CIR_CUDAVarRegistrationInfoAttr : CIR_Attr<"CUDAVarRegistrationInfo", "cu.var_registration"> {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index 966ab85698325..dd3761c8250e8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -16,19 +16,24 @@
 include "mlir/IR/EnumAttr.td"
 include "clang/CIR/Dialect/IR/CIRDialect.td"
 
-class CIR_I32EnumAttr<string name, string summary, list<I32EnumAttrCase> cases>
-    : I32EnumAttr<name, summary, cases> {
+// A CIR enum describes a C++ enum and nothing else. It either gets a
+// `CIR_EnumAttr` wrapper below, or it is used as a raw parameter of some other
+// attribute, so it derives from `EnumInfo` rather than the older
+// `EnumAttrInfo`, which doubles as an `IntegerAttr` constraint and would need
+// its `genSpecializedAttr` cleared on every enum.
+class CIR_I32Enum<string name, string summary, list<EnumCase> cases>
+    : I32Enum<name, summary, cases> {
   let cppNamespace = "::cir";
 }
 
-class CIR_I64EnumAttr<string name, string summary, list<I64EnumAttrCase> cases>
-    : I64EnumAttr<name, summary, cases> {
+class CIR_I64Enum<string name, string summary, list<EnumCase> cases>
+    : I64Enum<name, summary, cases> {
   let cppNamespace = "::cir";
 }
 
-class CIR_I32BitEnumAttr<string name, string summary,
+class CIR_I32BitEnum<string name, string summary,
                          list<BitEnumCaseBase> cases>
-    : I32BitEnumAttr<name, summary, cases> {
+    : I32BitEnum<name, summary, cases> {
   let cppNamespace = "::cir";
 }
 
@@ -37,7 +42,7 @@ class CIR_I32BitEnumAttr<string name, string summary,
 // delimiters gets the dialect's own `#cir.cleanup<all>` instead. Operations
 // that want the bare keyword wrap the argument in the `enum` directive, as in
 // `enum($cleanupKind)`. Naming the argument directly prints `<all>`.
-class CIR_EnumAttr<EnumAttrInfo info, string name = "", list<Trait> traits = []>
+class CIR_EnumAttr<EnumInfo info, string name = "", list<Trait> traits = []>
     : EnumAttr<CIR_Dialect, info, name, traits> {
   let assemblyFormat = "`<` $value `>`";
 }
@@ -47,7 +52,7 @@ class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = "">
   let defaultValue = value;
 }
 
-def CIR_LangAddressSpace : CIR_I32EnumAttr<
+def CIR_LangAddressSpace : CIR_I32Enum<
   "LangAddressSpace", "language address space kind", [
   I32EnumAttrCase<"Default", 0, "default">,
   I32EnumAttrCase<"OffloadPrivate", 1, "offload_private">,
@@ -64,7 +69,6 @@ def CIR_LangAddressSpace : CIR_I32EnumAttr<
     OpenCL `__local`) before target lowering.
   }];
 
-  let genSpecializedAttr = 0;
 }
 
 #endif // CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index cd0a401d9b77f..7a9ecbe435b3f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -187,7 +187,7 @@ defvar CIR_DynamicMemoryEffects = 0;
 // CastOp
 //===----------------------------------------------------------------------===//
 
-def CIR_CastKind : CIR_I32EnumAttr<"CastKind", "cast kind", [
+def CIR_CastKind : CIR_I32Enum<"CastKind", "cast kind", [
   I32EnumAttrCase<"bitcast", 1>,
   // CK_LValueBitCast
   // CK_LValueToRValueBitCast
@@ -260,9 +260,7 @@ def CIR_CastKind : CIR_I32EnumAttr<"CastKind", "cast kind", [
   // Enums below are specific to CIR and don't have a correspondence to classic
   // codegen:
   I32EnumAttrCase<"bool_to_float", 1000>,
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CastKindAttr : CIR_EnumAttr<CIR_CastKind, "cast">;
 
@@ -413,13 +411,11 @@ def CIR_BuiltinIntCastOp : CIR_Op<"builtin_int_cast", [Pure]> {
 // DynamicCastOp
 //===----------------------------------------------------------------------===//
 
-def CIR_DynamicCastKind : CIR_I32EnumAttr<
+def CIR_DynamicCastKind : CIR_I32Enum<
   "DynamicCastKind", "dynamic cast kind", [
     I32EnumAttrCase<"Ptr", 0, "ptr">,
     I32EnumAttrCase<"Ref", 1, "ref">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_DynamicCastKindAttr
     : CIR_EnumAttr<CIR_DynamicCastKind, "dynamic_cast">;
@@ -652,7 +648,7 @@ def CIR_SignBitOp : CIR_Op<"signbit", [Pure]> {
 // C/C++ memory order definitions
 //===----------------------------------------------------------------------===//
 
-def CIR_MemOrder : CIR_I32EnumAttr<
+def CIR_MemOrder : CIR_I32Enum<
   "MemOrder", "Memory order according to C++11 memory model", [
     I32EnumAttrCase<"Relaxed", 0, "relaxed">,
     I32EnumAttrCase<"Consume", 1, "consume">,
@@ -660,9 +656,7 @@ def CIR_MemOrder : CIR_I32EnumAttr<
     I32EnumAttrCase<"Release", 3, "release">,
     I32EnumAttrCase<"AcquireRelease", 4, "acq_rel">,
     I32EnumAttrCase<"SequentiallyConsistent", 5, "seq_cst">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_MemOrderAttr : CIR_EnumAttr<CIR_MemOrder, "mem_order">;
 
@@ -670,7 +664,7 @@ def CIR_MemOrderAttr : CIR_EnumAttr<CIR_MemOrder, "mem_order">;
 // C/C++ sync scope definitions
 //===----------------------------------------------------------------------===//
 
-def CIR_SyncScopeKind : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind", [
+def CIR_SyncScopeKind : CIR_I32Enum<"SyncScopeKind", "sync scope kind", [
   I32EnumAttrCase<"SingleThread", 0, "single_thread">,
   I32EnumAttrCase<"System", 1, "system">,
   I32EnumAttrCase<"Device", 2, "device">,
@@ -691,9 +685,7 @@ def CIR_SyncScopeKind : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind", [
   I32EnumAttrCase<"OpenCLDevice", 13, "opencl_device">,
   I32EnumAttrCase<"OpenCLAllSVMDevices", 14, "opencl_all_svm_devices">,
   I32EnumAttrCase<"OpenCLSubGroup", 15, "opencl_sub_group">,
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_SyncScopeKindAttr : CIR_EnumAttr<CIR_SyncScopeKind, "sync_scope">;
 
@@ -1370,13 +1362,11 @@ def CIR_ScopeOp : CIR_RegionBranchOpBase<"scope", [
 // CleanupScopeOp
 //===----------------------------------------------------------------------===//
 
-def CIR_CleanupKind : CIR_I32EnumAttr<"CleanupKind", "cleanup kind", [
+def CIR_CleanupKind : CIR_I32Enum<"CleanupKind", "cleanup kind", [
   I32EnumAttrCase<"Normal", 1, "normal">,
   I32EnumAttrCase<"EH", 2, "eh">,
   I32EnumAttrCase<"All", 3, "all">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup"> {
   let summary = "Cleanup kind attribute";
@@ -1540,14 +1530,12 @@ def CIR_CmpThreeWayOp : CIR_Op<"cmp3way", [Pure, SameTypeOperands]> {
 // SwitchOp
 //===----------------------------------------------------------------------===//
 
-def CIR_CaseOpKind : CIR_I32EnumAttr<"CaseOpKind", "case kind", [
+def CIR_CaseOpKind : CIR_I32Enum<"CaseOpKind", "case kind", [
   I32EnumAttrCase<"Default", 0, "default">,
   I32EnumAttrCase<"Equal", 1, "equal">,
   I32EnumAttrCase<"Anyof", 2, "anyof">,
   I32EnumAttrCase<"Range", 3, "range">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CaseOpKindAttr : CIR_EnumAttr<CIR_CaseOpKind, "case">;
 
@@ -2548,7 +2536,7 @@ def CIR_ForOp : CIR_LoopOpBase<"for"> {
 // CmpOp
 //===----------------------------------------------------------------------===//
 
-def CIR_CmpOpKind : CIR_I32EnumAttr<"CmpOpKind", "compare operation kind", [
+def CIR_CmpOpKind : CIR_I32Enum<"CmpOpKind", "compare operation kind", [
   I32EnumAttrCase<"lt", 0>,
   I32EnumAttrCase<"le", 1>,
   I32EnumAttrCase<"gt", 2>,
@@ -2557,9 +2545,7 @@ def CIR_CmpOpKind : CIR_I32EnumAttr<"CmpOpKind", "compare operation kind", [
   I32EnumAttrCase<"ne", 5>,
   I32EnumAttrCase<"one", 6>,
   I32EnumAttrCase<"uno", 7>
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CmpOpKindAttr : CIR_EnumAttr<CIR_CmpOpKind, "cmp">;
 
@@ -3320,7 +3306,7 @@ def CIR_TernaryOp : CIR_RegionBranchOpBase<"ternary", [
 // lowering, specially useful for C++ support.
 
 /// An enumeration for the kinds of linkage for global values.
-def CIR_GlobalLinkageKind : CIR_I32EnumAttr<
+def CIR_GlobalLinkageKind : CIR_I32Enum<
   "GlobalLinkageKind", "linkage kind", [
     // Externally visible function
     I32EnumAttrCase<"ExternalLinkage", 0, "external">,
@@ -3345,9 +3331,7 @@ def CIR_GlobalLinkageKind : CIR_I32EnumAttr<
     I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">,
     // Tentative definitions.
     I32EnumAttrCase<"CommonLinkage", 10, "common">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_GlobalLinkageKindAttr
     : CIR_EnumAttr<CIR_GlobalLinkageKind, "linkage">;
@@ -3356,14 +3340,12 @@ def CIR_GlobalLinkageKindAttr
 // properties of a global variable will be added over time as more of ClangIR
 // is upstreamed.
 
-def CIR_TLSModel : CIR_I32EnumAttr<"TLSModel", "TLS model", [
+def CIR_TLSModel : CIR_I32Enum<"TLSModel", "TLS model", [
   I32EnumAttrCase<"GeneralDynamic", 1, "tls_dyn">,
   I32EnumAttrCase<"LocalDynamic", 2, "tls_local_dyn">,
   I32EnumAttrCase<"InitialExec", 3, "tls_init_exec">,
   I32EnumAttrCase<"LocalExec", 4, "tls_local_exec">
-  ]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_TLSModelAttr: CIR_EnumAttr<CIR_TLSModel, "tls_model"> {
   let summary = "TLS Model attribute";
@@ -4201,15 +4183,13 @@ def CIR_OptionalPriorityAttr : OptionalAttr<
 // The enumeration cases are ordered to match `llvm::CallingConv`. The values
 // are CIR-specific and are not in sync with `llvm::CallingConv` or
 // `clang::CallingConv`.
-def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", [
+def CIR_CallingConv : CIR_I32Enum<"CallingConv", "calling convention", [
   I32EnumAttrCase<"C", 0, "c">,
   I32EnumAttrCase<"PTXKernel", 1, "ptx_kernel">,
   I32EnumAttrCase<"SpirFunction", 2, "spir_function">,
   I32EnumAttrCase<"SpirKernel", 3, "spir_kernel">,
   I32EnumAttrCase<"AMDGPUKernel", 4, "amdgpu_kernel">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_CallingConvAttr : CIR_EnumAttr<CIR_CallingConv, "calling_conv">;
 
@@ -4759,14 +4739,12 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[
 // AwaitOp
 //===----------------------------------------------------------------------===//
 
-def CIR_AwaitKind : CIR_I32EnumAttr<"AwaitKind", "await kind", [
+def CIR_AwaitKind : CIR_I32Enum<"AwaitKind", "await kind", [
   I32EnumAttrCase<"Init", 0, "init">,
   I32EnumAttrCase<"User", 1, "user">,
   I32EnumAttrCase<"Yield", 2, "yield">,
   I32EnumAttrCase<"Final", 3, "final">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_AwaitKindAttr : CIR_EnumAttr<CIR_AwaitKind, "await">;
 
@@ -5459,11 +5437,9 @@ def CIR_LifetimeEndOp : CIR_Op<"lifetime.end"> {
 // InlineAsmOp
 //===----------------------------------------------------------------------===//
 
-def CIR_AsmFlavor : CIR_I32EnumAttr<"AsmFlavor", "ATT or Intel",
+def CIR_AsmFlavor : CIR_I32Enum<"AsmFlavor", "ATT or Intel",
                                     [I32EnumAttrCase<"x86_att", 0>,
-                                     I32EnumAttrCase<"x86_intel", 1>]> {
-  let genSpecializedAttr = 0;
-}
+                                     I32EnumAttrCase<"x86_intel", 1>]>;
 
 def CIR_AsmFlavorAttr : CIR_EnumAttr<CIR_AsmFlavor, "asm_flavor">;
 
@@ -6577,15 +6553,13 @@ def CIR_ComplexSubOp : CIR_ComplexBinOp<"complex.sub"> {
 // ComplexMulOp and ComplexDivOp
 //===----------------------------------------------------------------------===//
 
-def CIR_ComplexRangeKind : CIR_I32EnumAttr<
+def CIR_ComplexRangeKind : CIR_I32Enum<
   "ComplexRangeKind", "complex multiplication and division implementation", [
     I32EnumAttrCase<"Full", 0, "full">,
     I32EnumAttrCase<"Improved", 1, "improved">,
     I32EnumAttrCase<"Promoted", 2, "promoted">,
     I32EnumAttrCase<"Basic", 3, "basic">,
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_ComplexRangeKindAttr
     : CIR_EnumAttr<CIR_ComplexRangeKind, "complex_range">;
@@ -6986,21 +6960,13 @@ def FPClass_All      : I32BitEnumAttrCaseGroup<"All",
     [FPClass_Nan, FPClass_Inf, FPClass_Fin], "fcAllFlags">;
 
 def FPClassTestEnum
-    : CIR_I32BitEnumAttr<"FPClassTest", "floating-point class test flags", [
+    : CIR_I32BitEnum<"FPClassTest", "floating-point class test flags", [
   FPClass_None, FPClass_SNan, FPClass_QNan, FPClass_NegInf, FPClass_NegNorm,
   FPClass_NegSub, FPClass_NegZero, FPClass_PosZero, FPClass_PosSub,
   FPClass_PosNorm, FPClass_PosInf, FPClass_Nan, FPClass_Inf, FPClass_Norm,
   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">;
@@ -7042,15 +7008,13 @@ def CIR_IsFPClassOp : CIR_Op<"is_fp_class", [Pure]> {
 // Assume Operations
 //===----------------------------------------------------------------------===//
 
-def CIR_AssumeBundleKind : CIR_I32EnumAttr<
+def CIR_AssumeBundleKind : CIR_I32Enum<
   "AssumeBundleKind", "kind of cir.assume operand bundle", [
   I32EnumAttrCase<"None", 0>,
   I32EnumAttrCase<"Align", 1, "align">,
   I32EnumAttrCase<"SeparateStorage", 2, "separate_storage">,
   I32EnumAttrCase<"Dereferenceable", 3, "dereferenceable">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_AssumeBundleKindAttr
     : CIR_EnumAttr<CIR_AssumeBundleKind, "assume_bundle">;
@@ -8795,7 +8759,7 @@ def CIR_EndCatchOp : CIR_Op<"end_catch"> {
 // EH Operations: InitCatchParamOp
 //===----------------------------------------------------------------------===//
 
-def CIR_InitCatchKind : CIR_I32EnumAttr<
+def CIR_InitCatchKind : CIR_I32Enum<
   "InitCatchKind", "", [
     I32EnumAttrCase<"Reference", 0, "reference">,
     I32EnumAttrCase<"Pointer", 1, "pointer">,
@@ -8803,9 +8767,7 @@ def CIR_InitCatchKind : CIR_I32EnumAttr<
     I32EnumAttrCase<"Objc", 3, "objc">,
     I32EnumAttrCase<"TrivialCopy", 4, "trivial_copy">,
     I32EnumAttrCase<"NonTrivialCopy", 5, "non_trivial_copy">,
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_InitCatchKindAttr : CIR_EnumAttr<CIR_InitCatchKind, "init_catch">;
 
@@ -8920,7 +8882,7 @@ def CIR_TokenNoneOp : CIR_Op<"token.none", [
 // Atomic operations
 //===----------------------------------------------------------------------===//
 
-def CIR_AtomicFetchKind : CIR_I32EnumAttr<
+def CIR_AtomicFetchKind : CIR_I32Enum<
   "AtomicFetchKind", "Binary opcode for atomic fetch-and-update operations", [
     I32EnumAttrCase<"Add", 0, "add">,
     I32EnumAttrCase<"Sub", 1, "sub">,
@@ -8939,9 +8901,7 @@ def CIR_AtomicFetchKind : CIR_I32EnumAttr<
     I32EnumAttrCase<"Minimum", 11, "minimum">,
     I32EnumAttrCase<"MaximumNum", 12, "maximum_num">,
     I32EnumAttrCase<"MinimumNum", 13, "minimum_num">
-]> {
-  let genSpecializedAttr = 0;
-}
+]>;
 
 def CIR_AtomicFetchKindAttr
     : CIR_EnumAttr<CIR_AtomicFetchKind, "atomic_fetch">;
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index c969bdbe32239..d0bcb885bc634 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -745,7 +745,7 @@ def CIR_BitFieldType : CIR_Type<"BitField", "bitfield", [
 // What a record member holds, and whether its extent is a declared one.
 //===----------------------------------------------------------------------===//
 
-def CIR_RecordMemberKind : CIR_I32EnumAttr<
+def CIR_RecordMemberKind : CIR_I32Enum<
     "RecordMemberKind", "what a record member holds", [
   I32EnumAttrCase<"Data", 0, "data">,
   I32EnumAttrCase<"Pad", 1, "pad">,
@@ -783,8 +783,6 @@ def CIR_RecordMemberKind : CIR_I32EnumAttr<
     whose trailing member is a unit of unnamed bit-fields keeps that unit in
     its data size.
   }];
-
-  let genSpecializedAttr = 0;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/IR/invalid-call.cir b/clang/test/CIR/IR/invalid-call.cir
index e7ac24ea0bae0..c21c32563c70f 100644
--- a/clang/test/CIR/IR/invalid-call.cir
+++ b/clang/test/CIR/IR/invalid-call.cir
@@ -100,7 +100,7 @@ cir.func @f15() {
 cir.func private @f16()
 cir.func @f17() {
   // expected-error at +2{{failed to parse CIR_InlineKindAttr parameter 'value' which is to be a `::cir::InlineKind`}}
-  // expected-error at below{{expected ::cir::InlineKind to be one of: no_inline, always_inline, inline_hint}}
+  // expected-error at below{{expected one of [no_inline, always_inline, inline_hint] for inlineKind}}
   cir.call @f16() { inline_kind = #cir.inline_kind<nonsense> } : () -> () 
   cir.return
 }
diff --git a/clang/test/CIR/IR/invalid-lang-attr.cir b/clang/test/CIR/IR/invalid-lang-attr.cir
index ffe523b1ad401..793f38a2fe743 100644
--- a/clang/test/CIR/IR/invalid-lang-attr.cir
+++ b/clang/test/CIR/IR/invalid-lang-attr.cir
@@ -1,5 +1,5 @@
 // RUN: cir-opt %s -verify-diagnostics
 
-// expected-error at below {{expected ::cir::SourceLanguage to be one of}}
+// expected-error at below {{expected one of [c, cxx, opencl_c, opencl_cxx] for source language}}
 // expected-error at below {{failed to parse CIR_SourceLanguageAttr parameter 'value'}}
 module attributes {cir.lang = #cir.lang<dummy>} { }

>From efa43717bbac5541e89ec0c098763ac2b45fc522 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 3/4] [CIR] Drop dead ceremony around the CIR enum attributes

Five things that no longer earn their place in the CIR enum attribute
machinery.

CIR_CleanupKindAttr carried three. Its cppClassName restated the default
AttrDef already derives. Its skipDefaultBuilders plus hand-written
AttrBuilder existed only to default $value to CleanupKind::All, which no
caller relies on, so the generated builders stayed suppressed for nothing.
And its summary and description restated the name, overriding the enum's own
"cleanup kind" that EnumAttr would otherwise inherit. The isNormal, isEH and
isNormalAndEH helpers stay.

CIR_TLSModelAttr's summary restated its name the same way, so only that goes.
CIR_DefaultValuedEnumParameter has never had a user.

NFC.
---
 .../include/clang/CIR/Dialect/IR/CIREnumAttr.td  |  5 -----
 clang/include/clang/CIR/Dialect/IR/CIROps.td     | 16 ----------------
 2 files changed, 21 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index dd3761c8250e8..ad23afa9a56cc 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -47,11 +47,6 @@ class CIR_EnumAttr<EnumInfo info, string name = "", list<Trait> traits = []>
   let assemblyFormat = "`<` $value `>`";
 }
 
-class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = "">
-    : EnumParameter<info> {
-  let defaultValue = value;
-}
-
 def CIR_LangAddressSpace : CIR_I32Enum<
   "LangAddressSpace", "language address space kind", [
   I32EnumAttrCase<"Default", 0, "default">,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7a9ecbe435b3f..6d149e6b1ccaa 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1369,21 +1369,6 @@ def CIR_CleanupKind : CIR_I32Enum<"CleanupKind", "cleanup kind", [
 ]>;
 
 def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup"> {
-  let summary = "Cleanup kind attribute";
-  let description = [{
-    Cleanup kind attributes.
-  }];
-
-  let cppClassName = "CleanupKindAttr";
-
-  let skipDefaultBuilders = 1;
-  let builders = [
-    AttrBuilder<(ins CArg<"CleanupKind",
-                          "cir::CleanupKind::All">:$value), [{
-      return $_get($_ctxt, value);
-    }]>
-  ];
-
   let extraClassDeclaration = [{
     bool isNormal() const {
       return getValue() == CleanupKind::Normal ||
@@ -3348,7 +3333,6 @@ def CIR_TLSModel : CIR_I32Enum<"TLSModel", "TLS model", [
 ]>;
 
 def CIR_TLSModelAttr: CIR_EnumAttr<CIR_TLSModel, "tls_model"> {
-  let summary = "TLS Model attribute";
   let description = [{
      The TLS mode for the global, which comes from either the
     `tls_model` attribute, or `-ftls-model` flag.

>From fb017228ab77748de8363573c24c0f0e81f7c337 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 4/4] [CIR] Drop the redundant suffix from the inline kind
 mnemonic

inline_kind was the one CIR enum attribute mnemonic still repeating what its
C++ enum class name says. The attribute now spells
`#cir.inline<always_inline>`. The operation argument keeps the name
inline_kind, since that is the accessor name, so the printed form reads
`inline_kind = #cir.inline<always_inline>`.

The enum's summary also becomes "inline kind" rather than the camelCase
"inlineKind", which is what generated docs show now that CIR_InlineKindAttr
no longer overrides it.

25 CHECK lines change across four test files. Nine are in an
aarch64-registered-target test, unsupported in an X86-only build, but the
substitution matches the two CIR tests that do run.
---
 clang/include/clang/CIR/Dialect/IR/CIRAttrs.td |  5 ++---
 .../CIR/CodeGen/callsite-inline-attributes.cpp | 18 +++++++++---------
 clang/test/CIR/IR/inline-attrs.cir             | 12 ++++++------
 clang/test/CIR/IR/invalid-call.cir             |  4 ++--
 .../sme-inline-callees-streaming-attrs.c       | 18 +++++++++---------
 5 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 838d8975177fd..143c9f6dc3795 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1799,14 +1799,13 @@ def CIR_TypeInfoAttr : CIR_ValueLikeAttr<"TypeInfo", "typeinfo"> {
 // InlineKindAttr
 //===----------------------------------------------------------------------===//
 
-def CIR_InlineKind : CIR_I32Enum<"InlineKind", "inlineKind", [
+def CIR_InlineKind : CIR_I32Enum<"InlineKind", "inline kind", [
   I32EnumAttrCase<"NoInline", 1, "no_inline">,
   I32EnumAttrCase<"AlwaysInline", 2, "always_inline">,
   I32EnumAttrCase<"InlineHint", 3, "inline_hint">
 ]>;
 
-def CIR_InlineKindAttr: CIR_EnumAttr<CIR_InlineKind, "inline_kind"> {
-  let summary = "Inline kind attribute";
+def CIR_InlineKindAttr: CIR_EnumAttr<CIR_InlineKind, "inline"> {
   let description = [{ Inline Kind attributes.  `no_inline` and `always_inline`
     spellings correspond to the attributes of the same name, and `inline_hint`
       is the `inline` keyword in the language.}];
diff --git a/clang/test/CIR/CodeGen/callsite-inline-attributes.cpp b/clang/test/CIR/CodeGen/callsite-inline-attributes.cpp
index d9916e725ca50..272645461ed81 100644
--- a/clang/test/CIR/CodeGen/callsite-inline-attributes.cpp
+++ b/clang/test/CIR/CodeGen/callsite-inline-attributes.cpp
@@ -14,39 +14,39 @@ void caller() {
  
   [[clang::always_inline]]
   callee();
-  // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline_kind<always_inline>}
+  // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline<always_inline>}
   // LLVM: call void @_Z6calleev() #[[ALWAYSINLINE:.*]]
   [[clang::noinline]]
   callee();
-  // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline_kind<no_inline>}
+  // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline<no_inline>}
   // LLVM: call void @_Z6calleev() #[[NOINLINE:.*]]
 
   [[clang::always_inline]]
   fptr();
-  // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline_kind<always_inline>}
+  // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline<always_inline>}
   // LLVM: call void %{{.*}}() #[[ALWAYSINLINE]]
   [[clang::noinline]]
   fptr();
-  // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline_kind<no_inline>}
+  // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline<no_inline>}
   // LLVM: call void %{{.*}}() #[[NOINLINE]]
 
   [[clang::always_inline]]
   {
     callee();
-    // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline_kind<always_inline>}
+    // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline<always_inline>}
     // LLVM: call void @_Z6calleev() #[[ALWAYSINLINE]]
     fptr();
-    // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline_kind<always_inline>}
+    // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline<always_inline>}
     // LLVM: call void %{{.*}}() #[[ALWAYSINLINE]]
   }
 
   [[clang::noinline]]
   {
     callee();
-    // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline_kind<no_inline>}
+    // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline<no_inline>}
     // LLVM: call void @_Z6calleev() #[[NOINLINE]]
     fptr();
-    // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline_kind<no_inline>}
+    // CIR: cir.call %{{.*}}() {inline_kind = #cir.inline<no_inline>}
     // LLVM: call void %{{.*}}() #[[NOINLINE]]
   }
 
@@ -54,7 +54,7 @@ void caller() {
   {
     [[clang::always_inline]]
     callee();
-    // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline_kind<always_inline>}
+    // CIR: cir.call @_Z6calleev() {inline_kind = #cir.inline<always_inline>}
     // LLVM: call void @_Z6calleev() #[[ALWAYSINLINE]]
   }
 }
diff --git a/clang/test/CIR/IR/inline-attrs.cir b/clang/test/CIR/IR/inline-attrs.cir
index 5a09432532927..2e6bd83b8c727 100644
--- a/clang/test/CIR/IR/inline-attrs.cir
+++ b/clang/test/CIR/IR/inline-attrs.cir
@@ -40,12 +40,12 @@ module {
   cir.func private @callee()
 //  // CHECK-LABEL: cir.func no_inline dso_local @caller()
   cir.func no_inline dso_local @caller() {
-     cir.call @callee() {inline_kind = #cir.inline_kind<always_inline>} : () -> ()
-     // CHECK: cir.call @callee() {inline_kind = #cir.inline_kind<always_inline>} : () -> ()
-     cir.call @callee() {inline_kind = #cir.inline_kind<no_inline>} : () -> ()
-     // CHECK: cir.call @callee() {inline_kind = #cir.inline_kind<no_inline>} : () -> ()
-     cir.call @callee() {inline_kind = #cir.inline_kind<inline_hint>} : () -> ()
-     // CHECK: cir.call @callee() {inline_kind = #cir.inline_kind<inline_hint>} : () -> ()
+     cir.call @callee() {inline_kind = #cir.inline<always_inline>} : () -> ()
+     // CHECK: cir.call @callee() {inline_kind = #cir.inline<always_inline>} : () -> ()
+     cir.call @callee() {inline_kind = #cir.inline<no_inline>} : () -> ()
+     // CHECK: cir.call @callee() {inline_kind = #cir.inline<no_inline>} : () -> ()
+     cir.call @callee() {inline_kind = #cir.inline<inline_hint>} : () -> ()
+     // CHECK: cir.call @callee() {inline_kind = #cir.inline<inline_hint>} : () -> ()
      cir.call @callee() {inline_kind = 2} : () -> ()
      // CHECK: cir.call @callee() : () -> ()
      cir.call @callee() {inline_kind = 6} : () -> ()
diff --git a/clang/test/CIR/IR/invalid-call.cir b/clang/test/CIR/IR/invalid-call.cir
index c21c32563c70f..fa01b53dd07b1 100644
--- a/clang/test/CIR/IR/invalid-call.cir
+++ b/clang/test/CIR/IR/invalid-call.cir
@@ -100,7 +100,7 @@ cir.func @f15() {
 cir.func private @f16()
 cir.func @f17() {
   // expected-error at +2{{failed to parse CIR_InlineKindAttr parameter 'value' which is to be a `::cir::InlineKind`}}
-  // expected-error at below{{expected one of [no_inline, always_inline, inline_hint] for inlineKind}}
-  cir.call @f16() { inline_kind = #cir.inline_kind<nonsense> } : () -> () 
+  // expected-error at below{{expected one of [no_inline, always_inline, inline_hint] for inline kind}}
+  cir.call @f16() { inline_kind = #cir.inline<nonsense> } : () -> () 
   cir.return
 }
diff --git a/clang/test/CodeGen/AArch64/sme-inline-callees-streaming-attrs.c b/clang/test/CodeGen/AArch64/sme-inline-callees-streaming-attrs.c
index b7872dfad6551..dd9fa35c3333b 100644
--- a/clang/test/CodeGen/AArch64/sme-inline-callees-streaming-attrs.c
+++ b/clang/test/CodeGen/AArch64/sme-inline-callees-streaming-attrs.c
@@ -45,8 +45,8 @@ void caller(void) {
 //  CHECK-NEXT:   call void @fn_streaming_new_zt0
 
 // CIR-LABEL: @caller()
-// CIR: cir.call @fn() {inline_kind = #cir.inline_kind<always_inline>}
-// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline_kind<always_inline>}
+// CIR: cir.call @fn() {inline_kind = #cir.inline<always_inline>}
+// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline<always_inline>}
 // CIR: cir.call @fn_streaming()
 // CIR-NOT: inline_kind
 // CIR: cir.call @fn_locally_streaming()
@@ -75,7 +75,7 @@ FN_ATTR void caller_streaming_compatible(void) __arm_streaming_compatible {
 // CIR-LABEL: @caller_streaming_compatible()
 // CIR: cir.call @fn()
 // CIR-NOT: inline_kind
-// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline_kind<always_inline>}
+// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline<always_inline>}
 // CIR: cir.call @fn_streaming()
 // CIR-NOT: inline_kind
 // CIR: cir.call @fn_locally_streaming()
@@ -104,9 +104,9 @@ FN_ATTR void caller_streaming(void) __arm_streaming {
 // CIR-LABEL: @caller_streaming()
 // CIR: cir.call @fn()
 // CIR-NOT: inline_kind
-// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline_kind<always_inline>}
-// CIR: cir.call @fn_streaming() {inline_kind = #cir.inline_kind<always_inline>}
-// CIR: cir.call @fn_locally_streaming() {inline_kind = #cir.inline_kind<always_inline>}
+// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline<always_inline>}
+// CIR: cir.call @fn_streaming() {inline_kind = #cir.inline<always_inline>}
+// CIR: cir.call @fn_locally_streaming() {inline_kind = #cir.inline<always_inline>}
 // CIR: cir.call @fn_streaming_new_za()
 // CIR-NOT: inline_kind
 // CIR: cir.call @fn_streaming_new_zt0()
@@ -132,9 +132,9 @@ void caller_locally_streaming(void) {
 // CIR-LABEL: @caller_locally_streaming()
 // CIR: cir.call @fn()
 // CIR-NOT: inline_kind
-// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline_kind<always_inline>}
-// CIR: cir.call @fn_streaming() {inline_kind = #cir.inline_kind<always_inline>}
-// CIR: cir.call @fn_locally_streaming() {inline_kind = #cir.inline_kind<always_inline>}
+// CIR: cir.call @fn_streaming_compatible() {inline_kind = #cir.inline<always_inline>}
+// CIR: cir.call @fn_streaming() {inline_kind = #cir.inline<always_inline>}
+// CIR: cir.call @fn_locally_streaming() {inline_kind = #cir.inline<always_inline>}
 // CIR: cir.call @fn_streaming_new_za()
 // CIR-NOT: inline_kind
 // CIR: cir.call @fn_streaming_new_zt0()



More information about the llvm-branch-commits mailing list