-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CIR] Align inline-kind FuncOp attribute with incubator #170050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Switches to more efficient explicit enum property instead of a wrapped storage, simplifying the string representation. The attribute is now placed before the symbol name for consistency with other FuncOp attributes. FileCheck patterns are also simplified to match only the attributes under test.
|
@llvm/pr-subscribers-clang Author: Henrich Lauko (xlauko) ChangesSwitches to more efficient explicit enum property instead of a wrapped storage, simplifying the string representation. The attribute is now placed before the symbol name for consistency with other FuncOp attributes. FileCheck patterns are also simplified to match only the attributes under test. Patch is 100.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170050.diff 48 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 12bc9cf7b5b04..98d4636dafc29 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1085,44 +1085,10 @@ def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
//===----------------------------------------------------------------------===//
def CIR_InlineKind : CIR_I32EnumAttr<"InlineKind", "inlineKind", [
- I32EnumAttrCase<"NoInline", 1, "never">,
- I32EnumAttrCase<"AlwaysInline", 2, "always">,
- I32EnumAttrCase<"InlineHint", 3, "hint">
-]> {
- let genSpecializedAttr = 0;
-}
-
-def CIR_InlineAttr : CIR_EnumAttr<CIR_InlineKind, "inline"> {
- let summary = "Inline attribute";
- let description = [{
- Inline attribute represents user directives for inlining behavior.
- This attribute is only used by `cir.func` operations.
-
- Values:
- - `never`: Prevents the function from being inlined (__attribute__((noinline)))
- - `always`: Forces the function to be inlined (__attribute__((always_inline)))
- - `hint`: Suggests the function should be inlined (inline keyword)
-
- Example:
- ```
- cir.func @noinline_func(%arg0: !s32i) -> !s32i inline(never) {
- cir.return %arg0 : !s32i
- }
- cir.func @always_inline_func() -> !s32i inline(always) {
- %0 = cir.const #cir.int<42> : !s32i
- cir.return %0 : !s32i
- }
- ```
- }];
-
- let cppClassName = "InlineAttr";
-
- let extraClassDeclaration = [{
- bool isNoInline() const { return getValue() == InlineKind::NoInline; };
- bool isAlwaysInline() const { return getValue() == InlineKind::AlwaysInline; };
- bool isInlineHint() const { return getValue() == InlineKind::InlineHint; };
- }];
-}
+ I32EnumAttrCase<"NoInline", 1, "no_inline">,
+ I32EnumAttrCase<"AlwaysInline", 2, "always_inline">,
+ I32EnumAttrCase<"InlineHint", 3, "inline_hint">
+]>;
//===----------------------------------------------------------------------===//
// CatchAllAttr & UnwindAttr
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5f5fab6f12300..11422d31df0ad 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2564,9 +2564,9 @@ def CIR_FuncOp : CIR_Op<"func", [
Similarly, for global destructors both `global_dtor` and
`global_dtor(<priority>)` are available.
- The `inline(never)` keyword marks a function that should not be inlined.
- The `inline(always)` keyword marks a function that should always be inlined.
- The `inline(hint)` keyword suggests that the function should be inlined.
+ The `no_inline` attribute marks a function that should not be inlined.
+ The `always_inline` attribute marks a function that should always be inlined.
+ The `inline_hint` attribute suggests that the function should be inlined.
Example:
@@ -2580,7 +2580,10 @@ def CIR_FuncOp : CIR_Op<"func", [
// Linkage information
cir.func linkonce_odr @some_method(...)
- ```
+
+ // Inline information
+ cir.func no_inline @some_method(...)
+
// Builtin function
cir.func builtin @__builtin_coro_end(!cir.ptr<i8>, !cir.bool) -> !cir.bool
// Coroutine
@@ -2592,25 +2595,26 @@ def CIR_FuncOp : CIR_Op<"func", [
```
}];
- let arguments = (ins SymbolNameAttr:$sym_name,
- CIR_VisibilityAttr:$global_visibility,
- TypeAttrOf<CIR_FuncType>:$function_type,
- UnitAttr:$builtin,
- UnitAttr:$coroutine,
- UnitAttr:$lambda,
- UnitAttr:$no_proto,
- UnitAttr:$dso_local,
- DefaultValuedAttr<CIR_GlobalLinkageKind,
- "cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
- OptionalAttr<CIR_InlineAttr>:$inline_kind,
- OptionalAttr<StrAttr>:$sym_visibility,
- UnitAttr:$comdat,
- OptionalAttr<DictArrayAttr>:$arg_attrs,
- OptionalAttr<DictArrayAttr>:$res_attrs,
- OptionalAttr<FlatSymbolRefAttr>:$aliasee,
- CIR_OptionalPriorityAttr:$global_ctor_priority,
- CIR_OptionalPriorityAttr:$global_dtor_priority,
- OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member
+ let arguments = (ins
+ SymbolNameAttr:$sym_name,
+ CIR_VisibilityAttr:$global_visibility,
+ TypeAttrOf<CIR_FuncType>:$function_type,
+ UnitAttr:$builtin,
+ UnitAttr:$coroutine,
+ OptionalAttr<CIR_InlineKind>:$inline_kind,
+ UnitAttr:$lambda,
+ UnitAttr:$no_proto,
+ UnitAttr:$dso_local,
+ DefaultValuedAttr<CIR_GlobalLinkageKind,
+ "cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
+ OptionalAttr<StrAttr>:$sym_visibility,
+ UnitAttr:$comdat,
+ OptionalAttr<DictArrayAttr>:$arg_attrs,
+ OptionalAttr<DictArrayAttr>:$res_attrs,
+ OptionalAttr<FlatSymbolRefAttr>:$aliasee,
+ CIR_OptionalPriorityAttr:$global_ctor_priority,
+ CIR_OptionalPriorityAttr:$global_dtor_priority,
+ OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member
);
let regions = (region AnyRegion:$body);
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4065124f8f568..1c2b83e6094f3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1870,8 +1870,7 @@ CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
&cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
clone.setSymVisibility("private");
- clone.setInlineKindAttr(cir::InlineAttr::get(
- &cgm.getMLIRContext(), cir::InlineKind::AlwaysInline));
+ clone.setInlineKind(cir::InlineKind::AlwaysInline);
}
return CIRGenCallee::forDirect(clone, gd);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 809c24f8aa670..03bbfbffce717 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1975,7 +1975,6 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
bool isAlwaysInline = existingInlineKind &&
*existingInlineKind == cir::InlineKind::AlwaysInline;
-
if (!decl) {
assert(!cir::MissingFeatures::hlsl());
@@ -1984,8 +1983,7 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
// If inlining is disabled and we don't have a declaration to control
// inlining, mark the function as 'noinline' unless it is explicitly
// marked as 'alwaysinline'.
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
}
return;
@@ -2002,19 +2000,16 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
// Handle inline attributes
if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
// Add noinline if the function isn't always_inline.
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
} else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
// Don't override AlwaysInline with NoInline, or vice versa, since we can't
// specify both in IR.
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline));
+ f.setInlineKind(cir::InlineKind::AlwaysInline);
} else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
// If inlining is disabled, force everything that isn't always_inline
// to carry an explicit noinline attribute.
if (!isAlwaysInline) {
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
}
} else {
// Otherwise, propagate the inline hint attribute and potentially use its
@@ -2036,13 +2031,11 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
return any_of(pattern->redecls(), checkRedeclForInline);
};
if (checkForInline(fd)) {
- f.setInlineKindAttr(cir::InlineAttr::get(&getMLIRContext(),
- cir::InlineKind::InlineHint));
+ f.setInlineKind(cir::InlineKind::InlineHint);
} else if (codeGenOpts.getInlining() ==
CodeGenOptions::OnlyHintInlining &&
!fd->isInlined() && !isAlwaysInline) {
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
}
}
}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index d505ca141d383..7479dc0ef1554 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -220,6 +220,41 @@ void parseVisibilityAttr(OpAsmParser &parser, cir::VisibilityAttr &visibility) {
visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
}
+//===----------------------------------------------------------------------===//
+// InlineKindAttr (FIXME: remove once FuncOp uses assembly format)
+//===----------------------------------------------------------------------===//
+
+ParseResult parseInlineKindAttr(OpAsmParser &parser,
+ cir::InlineKindAttr &inlineKindAttr) {
+ // Static list of possible inline kind keywords
+ static constexpr llvm::StringRef keywords[] = {"no_inline", "always_inline",
+ "inline_hint"};
+
+ // Parse the inline kind keyword (optional)
+ llvm::StringRef keyword;
+ if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
+ // Not an inline kind keyword, leave inlineKindAttr empty
+ return success();
+ }
+
+ // Parse the enum value from the keyword
+ auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
+ if (!inlineKindResult) {
+ return parser.emitError(parser.getCurrentLocation(), "expected one of [")
+ << llvm::join(llvm::ArrayRef(keywords), ", ")
+ << "] for inlineKind, got: " << keyword;
+ }
+
+ inlineKindAttr =
+ ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
+ return success();
+}
+
+void printInlineKindAttr(OpAsmPrinter &p, cir::InlineKindAttr inlineKindAttr) {
+ if (inlineKindAttr) {
+ p << " " << stringifyInlineKind(inlineKindAttr.getValue());
+ }
+}
//===----------------------------------------------------------------------===//
// CIR Custom Parsers/Printers
//===----------------------------------------------------------------------===//
@@ -1753,6 +1788,7 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
+ mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
@@ -1765,6 +1801,14 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
if (::mlir::succeeded(
parser.parseOptionalKeyword(coroutineNameAttr.strref())))
state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
+
+ // Parse optional inline kind attribute
+ cir::InlineKindAttr inlineKindAttr;
+ if (failed(parseInlineKindAttr(parser, inlineKindAttr)))
+ return failure();
+ if (inlineKindAttr)
+ state.addAttribute(inlineKindNameAttr, inlineKindAttr);
+
if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
@@ -1890,36 +1934,6 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
}).failed())
return failure();
- // Parse optional inline kind: inline(never|always|hint)
- if (parser.parseOptionalKeyword("inline").succeeded()) {
- if (parser.parseLParen().failed())
- return failure();
-
- llvm::StringRef inlineKindStr;
- const std::array<llvm::StringRef, cir::getMaxEnumValForInlineKind()>
- allowedInlineKindStrs{
- cir::stringifyInlineKind(cir::InlineKind::NoInline),
- cir::stringifyInlineKind(cir::InlineKind::AlwaysInline),
- cir::stringifyInlineKind(cir::InlineKind::InlineHint),
- };
- if (parser.parseOptionalKeyword(&inlineKindStr, allowedInlineKindStrs)
- .failed())
- return parser.emitError(parser.getCurrentLocation(),
- "expected 'never', 'always', or 'hint'");
-
- std::optional<InlineKind> inlineKind =
- cir::symbolizeInlineKind(inlineKindStr);
- if (!inlineKind)
- return parser.emitError(parser.getCurrentLocation(),
- "invalid inline kind");
-
- state.addAttribute(getInlineKindAttrName(state.name),
- cir::InlineAttr::get(builder.getContext(), *inlineKind));
-
- if (parser.parseRParen().failed())
- return failure();
- }
-
// Parse the optional function body.
auto *body = state.addRegion();
OptionalParseResult parseResult = parser.parseOptionalRegion(
@@ -2014,6 +2028,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
if (getCoroutine())
p << " coroutine";
+ printInlineKindAttr(p, getInlineKindAttr());
+
if (getLambda())
p << " lambda";
@@ -2069,10 +2085,6 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p << "(" << globalDtorPriority.value() << ")";
}
- if (cir::InlineAttr inlineAttr = getInlineKindAttr()) {
- p << " inline(" << cir::stringifyInlineKind(inlineAttr.getValue()) << ")";
- }
-
// Print the body if this is not an external function.
Region &body = getOperation()->getRegion(0);
if (!body.empty()) {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0c34d87734c3e..c572eb820b385 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1978,10 +1978,10 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
assert(!cir::MissingFeatures::opFuncMultipleReturnVals());
- if (auto inlineKind = op.getInlineKind()) {
- fn.setNoInline(inlineKind == cir::InlineKind::NoInline);
- fn.setInlineHint(inlineKind == cir::InlineKind::InlineHint);
- fn.setAlwaysInline(inlineKind == cir::InlineKind::AlwaysInline);
+ if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
+ fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
+ fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
+ fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
}
fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
diff --git a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
index 19362cf79b107..66891f9e1ad78 100644
--- a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
+++ b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
@@ -82,7 +82,7 @@ int check_load(st1 *s1) {
return s1->b;
}
-// CIR: cir.func dso_local @check_load
+// CIR: cir.func {{.*}} @check_load
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st1>>, !cir.ptr<!rec_st1>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "b"} : !cir.ptr<!rec_st1> -> !cir.ptr<!u16i>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b, [[MEMBER]] {is_volatile} : !cir.ptr<!u16i>) -> !u32i
@@ -114,7 +114,7 @@ int check_load_exception(st3 *s3) {
return s3->b;
}
-// CIR: cir.func dso_local @check_load_exception
+// CIR: cir.func {{.*}} @check_load_exception
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][2] {name = "b"} : !cir.ptr<!rec_st3> -> !cir.ptr<!u8i>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b1, [[MEMBER]] {is_volatile} : !cir.ptr<!u8i>) -> !u32i
@@ -151,7 +151,7 @@ int clip_load_exception2(clip *c) {
return c->a;
}
-// CIR: cir.func dso_local @clip_load_exception2
+// CIR: cir.func {{.*}} @clip_load_exception2
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_a1, [[MEMBER]] {is_volatile} : !cir.ptr<!cir.array<!u8i x 3>>) -> !s32i
@@ -178,7 +178,7 @@ void check_store(st2 *s2) {
s2->a = 1;
}
-// CIR: cir.func dso_local @check_store
+// CIR: cir.func {{.*}} @check_store
// CIR: [[CONST:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !s16i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st2>>, !cir.ptr<!rec_st2>
@@ -209,7 +209,7 @@ void check_store_exception(st3 *s3) {
s3->b = 2;
}
-// CIR: cir.func dso_local @check_store_exception
+// CIR: cir.func {{.*}} @check_store_exception
// CIR: [[CONST:%.*]] = cir.const #cir.int<2> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !u32i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>
@@ -239,7 +239,7 @@ void clip_store_exception2(clip *c) {
c->a = 3;
}
-// CIR: cir.func dso_local @clip_store_exception2
+// CIR: cir.func {{.*}} @clip_store_exception2
// CIR: [[CONST:%.*]] = cir.const #cir.int<3> : !s32i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>
@@ -261,7 +261,7 @@ void check_store_second_member (st4 *s4) {
s4->b = 1;
}
-// CIR: cir.func dso_local @check_store_second_member
+// CIR: cir.func {{.*}} @check_store_second_member
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[ONE]] : !s32i -> !u64i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st4>>, !cir.ptr<!rec_st4>
diff --git a/clang/test/CIR/CodeGen/address-space-conversion.cpp b/clang/test/CIR/CodeGen/address-space-conversion.cpp
index ca026be60ee71..9ce1f5e4b8e24 100644
--- a/clang/test/CIR/CodeGen/address-space-conversion.cpp
+++ b/clang/test/CIR/CodeGen/address-space-conversion.cpp
@@ -11,7 +11,7 @@ using pi2_t = int __attribute__((address_space(2))) *;
using ri1_t = int __attribute__((address_space(1))) &;
using ri2_t = int __attribute__((address_space(2))) &;
-// CIR: cir.func dso_local @{{.*test_ptr.*}}
+// CIR: cir.func {{.*}} @{{.*test_ptr.*}}
// LLVM: define dso_local void @{{.*test_ptr.*}}
// OGCG: define dso_local void @{{.*test_ptr.*}}
void test_ptr() {
@@ -30,7 +30,7 @@ void test_ptr() {
// OGCG-NEXT: store ptr addrspace(2) %{{.*}}, ptr %{{.*}}
}
-// CIR: cir.func dso_local @{{.*test_ref.*}}
+// CIR: cir.func {{.*}} @{{.*test_ref.*}}
// LLVM: define dso_local void @{{.*test_ref.*}}
// OGCG: define dso_local void @{{.*test_ref.*}}
void test_ref() {
@@ -56,7 +56,7 @@ void test_ref() {
// OGCG-NEXT: store ptr addrspace(2) %{{.*}}, ptr %{{.*}}
}
-// CIR: cir.func dso_local @{{.*test_nullptr.*}}
+// CIR: cir.func {{.*}} @{{.*test_nullptr.*}}
// LLVM: define dso_local void @{{.*test_nullptr.*}}
// OGCG: define dso_local void @{{.*test_nullptr.*}}
void test_nullptr() {
@@ -74,7 +74,7 @@ void test_nullptr() {
// OGCG-NEXT: store ptr addrspace(2) nu...
[truncated]
|
|
@llvm/pr-subscribers-clangir Author: Henrich Lauko (xlauko) ChangesSwitches to more efficient explicit enum property instead of a wrapped storage, simplifying the string representation. The attribute is now placed before the symbol name for consistency with other FuncOp attributes. FileCheck patterns are also simplified to match only the attributes under test. Patch is 100.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170050.diff 48 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 12bc9cf7b5b04..98d4636dafc29 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1085,44 +1085,10 @@ def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
//===----------------------------------------------------------------------===//
def CIR_InlineKind : CIR_I32EnumAttr<"InlineKind", "inlineKind", [
- I32EnumAttrCase<"NoInline", 1, "never">,
- I32EnumAttrCase<"AlwaysInline", 2, "always">,
- I32EnumAttrCase<"InlineHint", 3, "hint">
-]> {
- let genSpecializedAttr = 0;
-}
-
-def CIR_InlineAttr : CIR_EnumAttr<CIR_InlineKind, "inline"> {
- let summary = "Inline attribute";
- let description = [{
- Inline attribute represents user directives for inlining behavior.
- This attribute is only used by `cir.func` operations.
-
- Values:
- - `never`: Prevents the function from being inlined (__attribute__((noinline)))
- - `always`: Forces the function to be inlined (__attribute__((always_inline)))
- - `hint`: Suggests the function should be inlined (inline keyword)
-
- Example:
- ```
- cir.func @noinline_func(%arg0: !s32i) -> !s32i inline(never) {
- cir.return %arg0 : !s32i
- }
- cir.func @always_inline_func() -> !s32i inline(always) {
- %0 = cir.const #cir.int<42> : !s32i
- cir.return %0 : !s32i
- }
- ```
- }];
-
- let cppClassName = "InlineAttr";
-
- let extraClassDeclaration = [{
- bool isNoInline() const { return getValue() == InlineKind::NoInline; };
- bool isAlwaysInline() const { return getValue() == InlineKind::AlwaysInline; };
- bool isInlineHint() const { return getValue() == InlineKind::InlineHint; };
- }];
-}
+ I32EnumAttrCase<"NoInline", 1, "no_inline">,
+ I32EnumAttrCase<"AlwaysInline", 2, "always_inline">,
+ I32EnumAttrCase<"InlineHint", 3, "inline_hint">
+]>;
//===----------------------------------------------------------------------===//
// CatchAllAttr & UnwindAttr
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5f5fab6f12300..11422d31df0ad 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2564,9 +2564,9 @@ def CIR_FuncOp : CIR_Op<"func", [
Similarly, for global destructors both `global_dtor` and
`global_dtor(<priority>)` are available.
- The `inline(never)` keyword marks a function that should not be inlined.
- The `inline(always)` keyword marks a function that should always be inlined.
- The `inline(hint)` keyword suggests that the function should be inlined.
+ The `no_inline` attribute marks a function that should not be inlined.
+ The `always_inline` attribute marks a function that should always be inlined.
+ The `inline_hint` attribute suggests that the function should be inlined.
Example:
@@ -2580,7 +2580,10 @@ def CIR_FuncOp : CIR_Op<"func", [
// Linkage information
cir.func linkonce_odr @some_method(...)
- ```
+
+ // Inline information
+ cir.func no_inline @some_method(...)
+
// Builtin function
cir.func builtin @__builtin_coro_end(!cir.ptr<i8>, !cir.bool) -> !cir.bool
// Coroutine
@@ -2592,25 +2595,26 @@ def CIR_FuncOp : CIR_Op<"func", [
```
}];
- let arguments = (ins SymbolNameAttr:$sym_name,
- CIR_VisibilityAttr:$global_visibility,
- TypeAttrOf<CIR_FuncType>:$function_type,
- UnitAttr:$builtin,
- UnitAttr:$coroutine,
- UnitAttr:$lambda,
- UnitAttr:$no_proto,
- UnitAttr:$dso_local,
- DefaultValuedAttr<CIR_GlobalLinkageKind,
- "cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
- OptionalAttr<CIR_InlineAttr>:$inline_kind,
- OptionalAttr<StrAttr>:$sym_visibility,
- UnitAttr:$comdat,
- OptionalAttr<DictArrayAttr>:$arg_attrs,
- OptionalAttr<DictArrayAttr>:$res_attrs,
- OptionalAttr<FlatSymbolRefAttr>:$aliasee,
- CIR_OptionalPriorityAttr:$global_ctor_priority,
- CIR_OptionalPriorityAttr:$global_dtor_priority,
- OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member
+ let arguments = (ins
+ SymbolNameAttr:$sym_name,
+ CIR_VisibilityAttr:$global_visibility,
+ TypeAttrOf<CIR_FuncType>:$function_type,
+ UnitAttr:$builtin,
+ UnitAttr:$coroutine,
+ OptionalAttr<CIR_InlineKind>:$inline_kind,
+ UnitAttr:$lambda,
+ UnitAttr:$no_proto,
+ UnitAttr:$dso_local,
+ DefaultValuedAttr<CIR_GlobalLinkageKind,
+ "cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
+ OptionalAttr<StrAttr>:$sym_visibility,
+ UnitAttr:$comdat,
+ OptionalAttr<DictArrayAttr>:$arg_attrs,
+ OptionalAttr<DictArrayAttr>:$res_attrs,
+ OptionalAttr<FlatSymbolRefAttr>:$aliasee,
+ CIR_OptionalPriorityAttr:$global_ctor_priority,
+ CIR_OptionalPriorityAttr:$global_dtor_priority,
+ OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member
);
let regions = (region AnyRegion:$body);
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4065124f8f568..1c2b83e6094f3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1870,8 +1870,7 @@ CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
&cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
clone.setSymVisibility("private");
- clone.setInlineKindAttr(cir::InlineAttr::get(
- &cgm.getMLIRContext(), cir::InlineKind::AlwaysInline));
+ clone.setInlineKind(cir::InlineKind::AlwaysInline);
}
return CIRGenCallee::forDirect(clone, gd);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 809c24f8aa670..03bbfbffce717 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1975,7 +1975,6 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
bool isAlwaysInline = existingInlineKind &&
*existingInlineKind == cir::InlineKind::AlwaysInline;
-
if (!decl) {
assert(!cir::MissingFeatures::hlsl());
@@ -1984,8 +1983,7 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
// If inlining is disabled and we don't have a declaration to control
// inlining, mark the function as 'noinline' unless it is explicitly
// marked as 'alwaysinline'.
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
}
return;
@@ -2002,19 +2000,16 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
// Handle inline attributes
if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
// Add noinline if the function isn't always_inline.
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
} else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
// Don't override AlwaysInline with NoInline, or vice versa, since we can't
// specify both in IR.
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline));
+ f.setInlineKind(cir::InlineKind::AlwaysInline);
} else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
// If inlining is disabled, force everything that isn't always_inline
// to carry an explicit noinline attribute.
if (!isAlwaysInline) {
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
}
} else {
// Otherwise, propagate the inline hint attribute and potentially use its
@@ -2036,13 +2031,11 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
return any_of(pattern->redecls(), checkRedeclForInline);
};
if (checkForInline(fd)) {
- f.setInlineKindAttr(cir::InlineAttr::get(&getMLIRContext(),
- cir::InlineKind::InlineHint));
+ f.setInlineKind(cir::InlineKind::InlineHint);
} else if (codeGenOpts.getInlining() ==
CodeGenOptions::OnlyHintInlining &&
!fd->isInlined() && !isAlwaysInline) {
- f.setInlineKindAttr(
- cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
+ f.setInlineKind(cir::InlineKind::NoInline);
}
}
}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index d505ca141d383..7479dc0ef1554 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -220,6 +220,41 @@ void parseVisibilityAttr(OpAsmParser &parser, cir::VisibilityAttr &visibility) {
visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
}
+//===----------------------------------------------------------------------===//
+// InlineKindAttr (FIXME: remove once FuncOp uses assembly format)
+//===----------------------------------------------------------------------===//
+
+ParseResult parseInlineKindAttr(OpAsmParser &parser,
+ cir::InlineKindAttr &inlineKindAttr) {
+ // Static list of possible inline kind keywords
+ static constexpr llvm::StringRef keywords[] = {"no_inline", "always_inline",
+ "inline_hint"};
+
+ // Parse the inline kind keyword (optional)
+ llvm::StringRef keyword;
+ if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
+ // Not an inline kind keyword, leave inlineKindAttr empty
+ return success();
+ }
+
+ // Parse the enum value from the keyword
+ auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
+ if (!inlineKindResult) {
+ return parser.emitError(parser.getCurrentLocation(), "expected one of [")
+ << llvm::join(llvm::ArrayRef(keywords), ", ")
+ << "] for inlineKind, got: " << keyword;
+ }
+
+ inlineKindAttr =
+ ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
+ return success();
+}
+
+void printInlineKindAttr(OpAsmPrinter &p, cir::InlineKindAttr inlineKindAttr) {
+ if (inlineKindAttr) {
+ p << " " << stringifyInlineKind(inlineKindAttr.getValue());
+ }
+}
//===----------------------------------------------------------------------===//
// CIR Custom Parsers/Printers
//===----------------------------------------------------------------------===//
@@ -1753,6 +1788,7 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
+ mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
@@ -1765,6 +1801,14 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
if (::mlir::succeeded(
parser.parseOptionalKeyword(coroutineNameAttr.strref())))
state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
+
+ // Parse optional inline kind attribute
+ cir::InlineKindAttr inlineKindAttr;
+ if (failed(parseInlineKindAttr(parser, inlineKindAttr)))
+ return failure();
+ if (inlineKindAttr)
+ state.addAttribute(inlineKindNameAttr, inlineKindAttr);
+
if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
@@ -1890,36 +1934,6 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
}).failed())
return failure();
- // Parse optional inline kind: inline(never|always|hint)
- if (parser.parseOptionalKeyword("inline").succeeded()) {
- if (parser.parseLParen().failed())
- return failure();
-
- llvm::StringRef inlineKindStr;
- const std::array<llvm::StringRef, cir::getMaxEnumValForInlineKind()>
- allowedInlineKindStrs{
- cir::stringifyInlineKind(cir::InlineKind::NoInline),
- cir::stringifyInlineKind(cir::InlineKind::AlwaysInline),
- cir::stringifyInlineKind(cir::InlineKind::InlineHint),
- };
- if (parser.parseOptionalKeyword(&inlineKindStr, allowedInlineKindStrs)
- .failed())
- return parser.emitError(parser.getCurrentLocation(),
- "expected 'never', 'always', or 'hint'");
-
- std::optional<InlineKind> inlineKind =
- cir::symbolizeInlineKind(inlineKindStr);
- if (!inlineKind)
- return parser.emitError(parser.getCurrentLocation(),
- "invalid inline kind");
-
- state.addAttribute(getInlineKindAttrName(state.name),
- cir::InlineAttr::get(builder.getContext(), *inlineKind));
-
- if (parser.parseRParen().failed())
- return failure();
- }
-
// Parse the optional function body.
auto *body = state.addRegion();
OptionalParseResult parseResult = parser.parseOptionalRegion(
@@ -2014,6 +2028,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
if (getCoroutine())
p << " coroutine";
+ printInlineKindAttr(p, getInlineKindAttr());
+
if (getLambda())
p << " lambda";
@@ -2069,10 +2085,6 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p << "(" << globalDtorPriority.value() << ")";
}
- if (cir::InlineAttr inlineAttr = getInlineKindAttr()) {
- p << " inline(" << cir::stringifyInlineKind(inlineAttr.getValue()) << ")";
- }
-
// Print the body if this is not an external function.
Region &body = getOperation()->getRegion(0);
if (!body.empty()) {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0c34d87734c3e..c572eb820b385 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1978,10 +1978,10 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
assert(!cir::MissingFeatures::opFuncMultipleReturnVals());
- if (auto inlineKind = op.getInlineKind()) {
- fn.setNoInline(inlineKind == cir::InlineKind::NoInline);
- fn.setInlineHint(inlineKind == cir::InlineKind::InlineHint);
- fn.setAlwaysInline(inlineKind == cir::InlineKind::AlwaysInline);
+ if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
+ fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
+ fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
+ fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
}
fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
diff --git a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
index 19362cf79b107..66891f9e1ad78 100644
--- a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
+++ b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
@@ -82,7 +82,7 @@ int check_load(st1 *s1) {
return s1->b;
}
-// CIR: cir.func dso_local @check_load
+// CIR: cir.func {{.*}} @check_load
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st1>>, !cir.ptr<!rec_st1>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "b"} : !cir.ptr<!rec_st1> -> !cir.ptr<!u16i>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b, [[MEMBER]] {is_volatile} : !cir.ptr<!u16i>) -> !u32i
@@ -114,7 +114,7 @@ int check_load_exception(st3 *s3) {
return s3->b;
}
-// CIR: cir.func dso_local @check_load_exception
+// CIR: cir.func {{.*}} @check_load_exception
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][2] {name = "b"} : !cir.ptr<!rec_st3> -> !cir.ptr<!u8i>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b1, [[MEMBER]] {is_volatile} : !cir.ptr<!u8i>) -> !u32i
@@ -151,7 +151,7 @@ int clip_load_exception2(clip *c) {
return c->a;
}
-// CIR: cir.func dso_local @clip_load_exception2
+// CIR: cir.func {{.*}} @clip_load_exception2
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_a1, [[MEMBER]] {is_volatile} : !cir.ptr<!cir.array<!u8i x 3>>) -> !s32i
@@ -178,7 +178,7 @@ void check_store(st2 *s2) {
s2->a = 1;
}
-// CIR: cir.func dso_local @check_store
+// CIR: cir.func {{.*}} @check_store
// CIR: [[CONST:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !s16i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st2>>, !cir.ptr<!rec_st2>
@@ -209,7 +209,7 @@ void check_store_exception(st3 *s3) {
s3->b = 2;
}
-// CIR: cir.func dso_local @check_store_exception
+// CIR: cir.func {{.*}} @check_store_exception
// CIR: [[CONST:%.*]] = cir.const #cir.int<2> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !u32i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>
@@ -239,7 +239,7 @@ void clip_store_exception2(clip *c) {
c->a = 3;
}
-// CIR: cir.func dso_local @clip_store_exception2
+// CIR: cir.func {{.*}} @clip_store_exception2
// CIR: [[CONST:%.*]] = cir.const #cir.int<3> : !s32i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>
@@ -261,7 +261,7 @@ void check_store_second_member (st4 *s4) {
s4->b = 1;
}
-// CIR: cir.func dso_local @check_store_second_member
+// CIR: cir.func {{.*}} @check_store_second_member
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[ONE]] : !s32i -> !u64i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st4>>, !cir.ptr<!rec_st4>
diff --git a/clang/test/CIR/CodeGen/address-space-conversion.cpp b/clang/test/CIR/CodeGen/address-space-conversion.cpp
index ca026be60ee71..9ce1f5e4b8e24 100644
--- a/clang/test/CIR/CodeGen/address-space-conversion.cpp
+++ b/clang/test/CIR/CodeGen/address-space-conversion.cpp
@@ -11,7 +11,7 @@ using pi2_t = int __attribute__((address_space(2))) *;
using ri1_t = int __attribute__((address_space(1))) &;
using ri2_t = int __attribute__((address_space(2))) &;
-// CIR: cir.func dso_local @{{.*test_ptr.*}}
+// CIR: cir.func {{.*}} @{{.*test_ptr.*}}
// LLVM: define dso_local void @{{.*test_ptr.*}}
// OGCG: define dso_local void @{{.*test_ptr.*}}
void test_ptr() {
@@ -30,7 +30,7 @@ void test_ptr() {
// OGCG-NEXT: store ptr addrspace(2) %{{.*}}, ptr %{{.*}}
}
-// CIR: cir.func dso_local @{{.*test_ref.*}}
+// CIR: cir.func {{.*}} @{{.*test_ref.*}}
// LLVM: define dso_local void @{{.*test_ref.*}}
// OGCG: define dso_local void @{{.*test_ref.*}}
void test_ref() {
@@ -56,7 +56,7 @@ void test_ref() {
// OGCG-NEXT: store ptr addrspace(2) %{{.*}}, ptr %{{.*}}
}
-// CIR: cir.func dso_local @{{.*test_nullptr.*}}
+// CIR: cir.func {{.*}} @{{.*test_nullptr.*}}
// LLVM: define dso_local void @{{.*test_nullptr.*}}
// OGCG: define dso_local void @{{.*test_nullptr.*}}
void test_nullptr() {
@@ -74,7 +74,7 @@ void test_nullptr() {
// OGCG-NEXT: store ptr addrspace(2) nu...
[truncated]
|

Switches to more efficient explicit enum property instead of a wrapped storage, simplifying the string representation. The attribute is now placed before the symbol name for consistency with other FuncOp attributes. FileCheck patterns are also simplified to match only the attributes under test.