[llvm-branch-commits] [clang] [CIR] Migrate seven operation enums off IntegerAttr (PR #220883)
Henrich Lauko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Sep 3 05:46:05 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/220883
>From 1d80d944e920971580634bb2dd3e9a54efc33670 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 seven operation enums off IntegerAttr
CastKind, DynamicCastKind, CmpOpKind, ComplexRangeKind, InitCatchKind,
CaseOpKind and AwaitKind generated IntegerAttr subclasses. The operations
printed them symbolically, but in an attribute dictionary `cir.cast bitcast`
was stored as `kind = 1 : i32`.
Each enum now sets genSpecializedAttr = 0 and gains a CIR_EnumAttr wrapper,
and the operations wrap the argument in `enum()` to keep the bare keyword,
giving spellings like `#cir.cast<bitcast>`. Mnemonics drop the suffix the C++
class name carries. DynamicCastKind spells out `dynamic_cast`, since
`dyn_cast` is taken by the operation and by `#cir.dyn_cast_info`.
CUDADeviceVarKind gets no wrapper, being only a raw parameter of
CIR_CUDAVarRegistrationInfoAttr.
Operation syntax is unchanged, and enum-attrs.cir covers the new spellings.
---
.../clang/CIR/Dialect/IR/CIRCUDAAttrs.td | 7 +-
clang/include/clang/CIR/Dialect/IR/CIROps.td | 82 ++++++++++++------
clang/test/CIR/IR/enum-attrs.cir | 86 +++++++++++++++++++
3 files changed, 147 insertions(+), 28 deletions(-)
create mode 100644 clang/test/CIR/IR/enum-attrs.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td
index 73dd7baaa5caa..2d5f70ec9c3ad 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td
@@ -68,14 +68,15 @@ def CIR_CUDABinaryHandleAttr : CIR_Attr<
let assemblyFormat = "`<` $name `>`";
}
-// Enum for device variable kinds
-def CIR_CUDADeviceVarKind : I32EnumAttr<"CUDADeviceVarKind",
+// No wrapper attribute: the kind is only ever printed by
+// CIR_CUDAVarRegistrationInfoAttr's own assembly format.
+def CIR_CUDADeviceVarKind : CIR_I32EnumAttr<"CUDADeviceVarKind",
"CUDA device variable kind", [
I32EnumAttrCase<"Variable", 0>,
I32EnumAttrCase<"Surface", 1>, // Future
I32EnumAttrCase<"Texture", 2>, // Future
]> {
- let cppNamespace = "::cir";
+ let genSpecializedAttr = 0;
}
// Attribute carrying device variable registration flags
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 8ccd086a146fb..4d807f88715c2 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -242,7 +242,11 @@ 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">;
def CIR_CastOp : CIR_Op<"cast", !listconcat([
DeclareOpInterfaceMethods<PromotableOpInterface>
@@ -302,12 +306,12 @@ def CIR_CastOp : CIR_Op<"cast", !listconcat([
```
}];
- let arguments = (ins CIR_CastKind:$kind, CIR_AnyType:$src,
+ let arguments = (ins CIR_CastKindAttr:$kind, CIR_AnyType:$src,
OptionalAttr<CIR_FenvAttr>:$fenv);
let results = (outs CIR_AnyType:$result);
let assemblyFormat = [{
- $kind $src `:` type($src) `->` type($result) attr-dict
+ enum($kind) $src `:` type($src) `->` type($result) attr-dict
}];
let builders = [
@@ -395,7 +399,12 @@ def CIR_DynamicCastKind : CIR_I32EnumAttr<
"DynamicCastKind", "dynamic cast kind", [
I32EnumAttrCase<"Ptr", 0, "ptr">,
I32EnumAttrCase<"Ref", 1, "ref">
-]>;
+]> {
+ let genSpecializedAttr = 0;
+}
+
+def CIR_DynamicCastKindAttr
+ : CIR_EnumAttr<CIR_DynamicCastKind, "dynamic_cast">;
def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
let summary = "Perform dynamic cast on record pointers";
@@ -450,7 +459,7 @@ def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
}];
let arguments = (ins
- CIR_DynamicCastKind:$kind,
+ CIR_DynamicCastKindAttr:$kind,
CIR_PtrToRecordType:$src,
OptionalAttr<CIR_DynamicCastInfoAttr>:$info,
UnitAttr:$relative_layout
@@ -461,7 +470,7 @@ def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
);
let assemblyFormat = [{
- $kind (`relative_layout` $relative_layout^)? $src
+ enum($kind) (`relative_layout` $relative_layout^)? $src
`:` qualified(type($src)) `->` qualified(type($result))
(qualified($info)^)? attr-dict
}];
@@ -1513,7 +1522,11 @@ def CIR_CaseOpKind : CIR_I32EnumAttr<"CaseOpKind", "case kind", [
I32EnumAttrCase<"Equal", 1, "equal">,
I32EnumAttrCase<"Anyof", 2, "anyof">,
I32EnumAttrCase<"Range", 3, "range">
-]>;
+]> {
+ let genSpecializedAttr = 0;
+}
+
+def CIR_CaseOpKindAttr : CIR_EnumAttr<CIR_CaseOpKind, "case">;
def CIR_CaseOp : CIR_Op<"case", [
DeclareOpInterfaceMethods<RegionBranchOpInterface, ["getSuccessorInputs"]>,
@@ -1537,10 +1550,11 @@ def CIR_CaseOp : CIR_Op<"case", [
Each case region must be explicitly terminated.
}];
- let arguments = (ins ArrayAttr:$value, CIR_CaseOpKind:$kind);
+ let arguments = (ins ArrayAttr:$value, CIR_CaseOpKindAttr:$kind);
let regions = (region AnyRegion:$caseRegion);
- let assemblyFormat = "`(` $kind `,` $value `)` $caseRegion attr-dict";
+ let assemblyFormat =
+ "`(` enum($kind) `,` $value `)` $caseRegion attr-dict";
let skipDefaultBuilders = 1;
let builders = [
@@ -2522,7 +2536,11 @@ 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">;
def CIR_CmpOp : CIR_Op<"cmp",
!listconcat([SameTypeOperands], CIR_FenvOpTraits)> {
@@ -2561,7 +2579,7 @@ def CIR_CmpOp : CIR_Op<"cmp",
}];
let arguments = (ins
- CIR_CmpOpKind:$kind,
+ CIR_CmpOpKindAttr:$kind,
CIR_ComparableType:$lhs,
CIR_ComparableType:$rhs,
OptionalAttr<CIR_FenvAttr>:$fenv
@@ -2570,7 +2588,7 @@ def CIR_CmpOp : CIR_Op<"cmp",
let results = (outs CIR_BoolType:$result);
let assemblyFormat = [{
- $kind $lhs `,` $rhs `:` type($lhs) attr-dict
+ enum($kind) $lhs `,` $rhs `:` type($lhs) attr-dict
}];
let builders = [
@@ -4718,7 +4736,11 @@ def CIR_AwaitKind : CIR_I32EnumAttr<"AwaitKind", "await kind", [
I32EnumAttrCase<"User", 1, "user">,
I32EnumAttrCase<"Yield", 2, "yield">,
I32EnumAttrCase<"Final", 3, "final">
-]>;
+]> {
+ let genSpecializedAttr = 0;
+}
+
+def CIR_AwaitKindAttr : CIR_EnumAttr<CIR_AwaitKind, "await">;
def CIR_AwaitOp : CIR_Op<"await",[
DeclareOpInterfaceMethods<RegionBranchOpInterface, ["getSuccessorInputs"]>,
@@ -4774,12 +4796,12 @@ def CIR_AwaitOp : CIR_Op<"await",[
as part of the enclosing await scope.
}];
- let arguments = (ins CIR_AwaitKind:$kind);
+ let arguments = (ins CIR_AwaitKindAttr:$kind);
let regions = (region SizedRegion<1>:$ready,
SizedRegion<1>:$suspend,
SizedRegion<1>:$resume);
let assemblyFormat = [{
- `(` $kind `,`
+ `(` enum($kind) `,`
`ready` `:` $ready `,`
`suspend` `:` $suspend `,`
`resume` `:` $resume `,`
@@ -5919,7 +5941,7 @@ def CIR_VecCmpOp : CIR_Op<"vec.cmp",
}];
let arguments = (ins
- CIR_CmpOpKind:$kind,
+ CIR_CmpOpKindAttr:$kind,
CIR_VectorType:$lhs,
CIR_VectorType:$rhs,
OptionalAttr<CIR_FenvAttr>:$fenv
@@ -5928,7 +5950,7 @@ def CIR_VecCmpOp : CIR_Op<"vec.cmp",
let results = (outs CIR_VectorType:$result);
let assemblyFormat = [{
- `(` $kind `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
+ `(` enum($kind) `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
qualified(type($result)) attr-dict
}];
@@ -6502,20 +6524,26 @@ def CIR_ComplexRangeKind : CIR_I32EnumAttr<
I32EnumAttrCase<"Improved", 1, "improved">,
I32EnumAttrCase<"Promoted", 2, "promoted">,
I32EnumAttrCase<"Basic", 3, "basic">,
-]>;
+]> {
+ let genSpecializedAttr = 0;
+}
+
+def CIR_ComplexRangeKindAttr
+ : CIR_EnumAttr<CIR_ComplexRangeKind, "complex_range">;
class CIR_ComplexRangeBinOp<string mnemonic>
: CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
let arguments = (ins
CIR_ComplexType:$lhs,
CIR_ComplexType:$rhs,
- CIR_ComplexRangeKind:$range
+ CIR_ComplexRangeKindAttr:$range
);
let results = (outs CIR_ComplexType:$result);
let assemblyFormat = [{
- $lhs `,` $rhs `range` `(` $range `)` `:` qualified(type($result)) attr-dict
+ $lhs `,` $rhs `range` `(` enum($range) `)` `:` qualified(type($result))
+ attr-dict
}];
let hasLLVMLowering = false;
@@ -8703,7 +8731,11 @@ 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">;
def CIR_InitCatchParamOp : CIR_Op<"init_catch_param"> {
let summary = "Initialize a catch parameter from the exception pointer";
@@ -8733,11 +8765,11 @@ def CIR_InitCatchParamOp : CIR_Op<"init_catch_param"> {
let arguments = (ins
CIR_PointerType:$exn_ptr,
CIR_PointerType:$param_addr,
- CIR_InitCatchKind:$kind
+ CIR_InitCatchKindAttr:$kind
);
let assemblyFormat = [{
- $kind $exn_ptr `to` $param_addr `:`
+ enum($kind) $exn_ptr `to` $param_addr `:`
qualified(type($exn_ptr)) `,` qualified(type($param_addr)) attr-dict
}];
@@ -8783,12 +8815,12 @@ def CIR_ConstructCatchParamOp : CIR_Op<"construct_catch_param", [
let arguments = (ins
CIR_EhTokenType:$eh_token,
CIR_PointerType:$param_addr,
- CIR_InitCatchKind:$kind,
+ CIR_InitCatchKindAttr:$kind,
OptionalAttr<FlatSymbolRefAttr>:$copy_fn
);
let assemblyFormat = [{
- $kind $eh_token `to` $param_addr `using` ($copy_fn^)? `:`
+ enum($kind) $eh_token `to` $param_addr `using` ($copy_fn^)? `:`
qualified(type($param_addr)) attr-dict
}];
diff --git a/clang/test/CIR/IR/enum-attrs.cir b/clang/test/CIR/IR/enum-attrs.cir
new file mode 100644
index 0000000000000..0e0238c690dbc
--- /dev/null
+++ b/clang/test/CIR/IR/enum-attrs.cir
@@ -0,0 +1,86 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+// Enum attributes that operations print as a bare keyword must still have a
+// readable standalone spelling for when they show up in an attribute
+// dictionary. These used to be IntegerAttr subclasses, which printed as
+// `2 : i32`.
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+cir.func @cast_attr() {
+ cir.return {cir.test = [#cir.cast<bitcast>, #cir.cast<integral>,
+ #cir.cast<bool_to_float>]}
+}
+
+// CHECK: cir.func @cast_attr() {
+// CHECK: cir.return {cir.test = [#cir.cast<bitcast>, #cir.cast<integral>, #cir.cast<bool_to_float>]}
+
+cir.func @dynamic_cast_attr() {
+ cir.return {cir.test = [#cir.dynamic_cast<ptr>,
+ #cir.dynamic_cast<ref>]}
+}
+
+// CHECK: cir.func @dynamic_cast_attr() {
+// CHECK: cir.return {cir.test = [#cir.dynamic_cast<ptr>, #cir.dynamic_cast<ref>]}
+
+cir.func @cmp_attr() {
+ cir.return {cir.test = [#cir.cmp<lt>, #cir.cmp<eq>,
+ #cir.cmp<uno>]}
+}
+
+// CHECK: cir.func @cmp_attr() {
+// CHECK: cir.return {cir.test = [#cir.cmp<lt>, #cir.cmp<eq>, #cir.cmp<uno>]}
+
+cir.func @complex_range_attr() {
+ cir.return {cir.test = [#cir.complex_range<full>,
+ #cir.complex_range<basic>]}
+}
+
+// CHECK: cir.func @complex_range_attr() {
+// CHECK: cir.return {cir.test = [#cir.complex_range<full>, #cir.complex_range<basic>]}
+
+cir.func @init_catch_attr() {
+ cir.return {cir.test = [#cir.init_catch<reference>,
+ #cir.init_catch<non_trivial_copy>]}
+}
+
+// CHECK: cir.func @init_catch_attr() {
+// CHECK: cir.return {cir.test = [#cir.init_catch<reference>, #cir.init_catch<non_trivial_copy>]}
+
+cir.func @case_attr() {
+ cir.return {cir.test = [#cir.case<default>, #cir.case<anyof>,
+ #cir.case<range>]}
+}
+
+// CHECK: cir.func @case_attr() {
+// CHECK: cir.return {cir.test = [#cir.case<default>, #cir.case<anyof>, #cir.case<range>]}
+
+cir.func @await_attr() {
+ cir.return {cir.test = [#cir.await<init>, #cir.await<final>]}
+}
+
+// CHECK: cir.func @await_attr() {
+// CHECK: cir.return {cir.test = [#cir.await<init>, #cir.await<final>]}
+
+cir.func @tls_model_attr() {
+ cir.return {cir.test = [#cir.tls_model<tls_dyn>,
+ #cir.tls_model<tls_local_exec>]}
+}
+
+// CHECK: cir.func @tls_model_attr() {
+// CHECK: cir.return {cir.test = [#cir.tls_model<tls_dyn>, #cir.tls_model<tls_local_exec>]}
+
+// The operations themselves keep printing a bare keyword.
+cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i) {
+ %0 = cir.cast bitcast %arg0 : !s32i -> !s32i
+ %1 = cir.cmp lt %arg0, %arg1 : !s32i
+ cir.return
+}
+
+// CHECK: cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i) {
+// CHECK: %0 = cir.cast bitcast %arg0 : !s32i -> !s32i
+// CHECK: %1 = cir.cmp lt %arg0, %arg1 : !s32i
+
+}
More information about the llvm-branch-commits
mailing list