Skip to content

Commit 697e3be

Browse files
authored
[CIR] Make InlineKind explicit attribute on FuncOp (#2040)
This remove the attribute from extra attributes and removes now unnecessery specialized attribute.
1 parent 060c675 commit 697e3be

26 files changed

+165
-141
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,27 +1196,10 @@ def CIR_ExtraFuncAttr : CIR_Attr<"ExtraFuncAttributes", "extra"> {
11961196
//===----------------------------------------------------------------------===//
11971197

11981198
def CIR_InlineKind : CIR_I32EnumAttr<"InlineKind", "inlineKind", [
1199-
I32EnumAttrCase<"NoInline", 1, "no">,
1200-
I32EnumAttrCase<"AlwaysInline", 2, "always">,
1201-
I32EnumAttrCase<"InlineHint", 3, "hint">
1202-
]> {
1203-
let genSpecializedAttr = 0;
1204-
}
1205-
1206-
def CIR_InlineAttr : CIR_EnumAttr<CIR_InlineKind, "inline"> {
1207-
let summary = "Inline attribute";
1208-
let description = [{
1209-
Inline attributes represents user directives.
1210-
}];
1211-
1212-
let cppClassName = "InlineAttr";
1213-
1214-
let extraClassDeclaration = [{
1215-
bool isNoInline() const { return getValue() == InlineKind::NoInline; };
1216-
bool isAlwaysInline() const { return getValue() == InlineKind::AlwaysInline; };
1217-
bool isInlineHint() const { return getValue() == InlineKind::InlineHint; };
1218-
}];
1219-
}
1199+
I32EnumAttrCase<"NoInline", 1, "no_inline">,
1200+
I32EnumAttrCase<"AlwaysInline", 2, "always_inline">,
1201+
I32EnumAttrCase<"InlineHint", 3, "inline_hint">
1202+
]>;
12201203

12211204
//===----------------------------------------------------------------------===//
12221205
// Unit Function Attributes

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4099,6 +4099,7 @@ def FuncOp : CIR_Op<"func", [
40994099
TypeAttrOf<CIR_FuncType>:$function_type,
41004100
UnitAttr:$builtin,
41014101
UnitAttr:$coroutine,
4102+
OptionalAttr<CIR_InlineKind>:$inline_kind,
41024103
UnitAttr:$lambda,
41034104
UnitAttr:$no_proto,
41044105
UnitAttr:$dso_local,

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,26 +2883,22 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(const Decl *decl,
28832883

28842884
assert(!MissingFeatures::stackProtector());
28852885

2886-
auto existingInlineAttr = dyn_cast_if_present<cir::InlineAttr>(
2887-
attrs.get(cir::InlineAttr::getMnemonic()));
2888-
bool isNoInline = existingInlineAttr && existingInlineAttr.isNoInline();
2889-
bool isAlwaysInline =
2890-
existingInlineAttr && existingInlineAttr.isAlwaysInline();
2886+
std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2887+
bool isNoInline =
2888+
existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2889+
bool isAlwaysInline = existingInlineKind &&
2890+
*existingInlineKind == cir::InlineKind::AlwaysInline;
28912891

28922892
if (!decl) {
28932893
// Non-entry HLSL functions must always be inlined.
28942894
if (getLangOpts().HLSL && !isNoInline) {
2895-
auto attr = cir::InlineAttr::get(&getMLIRContext(),
2896-
cir::InlineKind::AlwaysInline);
2897-
attrs.set(attr.getMnemonic(), attr);
2895+
f.setInlineKind(cir::InlineKind::AlwaysInline);
28982896
} else if (!isAlwaysInline && codeGenOpts.getInlining() ==
28992897
CodeGenOptions::OnlyAlwaysInlining) {
29002898
// If we don't have a declaration to control inlining, the function isn't
29012899
// explicitly marked as alwaysinline for semantic reasons, and inlining is
29022900
// disabled, mark the function as noinline.
2903-
auto attr =
2904-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2905-
attrs.set(attr.getMnemonic(), attr);
2901+
f.setInlineKind(cir::InlineKind::NoInline);
29062902
}
29072903

29082904
f.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
@@ -2932,19 +2928,15 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(const Decl *decl,
29322928

29332929
// Non-entry HLSL functions must always be inlined.
29342930
if (getLangOpts().HLSL && !isNoInline && !decl->hasAttr<NoInlineAttr>()) {
2935-
auto attr =
2936-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline);
2937-
attrs.set(attr.getMnemonic(), attr);
2931+
f.setInlineKind(cir::InlineKind::AlwaysInline);
29382932
} else if ((shouldAddOptNone || decl->hasAttr<OptimizeNoneAttr>()) &&
29392933
!isAlwaysInline) {
29402934
// Add optnone, but do so only if the function isn't always_inline.
29412935
auto optNoneAttr = cir::OptNoneAttr::get(&getMLIRContext());
29422936
attrs.set(optNoneAttr.getMnemonic(), optNoneAttr);
29432937

29442938
// OptimizeNone implies noinline; we should not be inlining such functions.
2945-
auto noInlineAttr =
2946-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2947-
attrs.set(noInlineAttr.getMnemonic(), noInlineAttr);
2939+
f.setInlineKind(cir::InlineKind::NoInline);
29482940

29492941
// We still need to handle naked functions even though optnone subsumes
29502942
// much of their semantics.
@@ -2961,21 +2953,15 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(const Decl *decl,
29612953
llvm_unreachable("NYI");
29622954
} else if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
29632955
// Add noinline if the function isn't always_inline.
2964-
auto attr =
2965-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2966-
attrs.set(attr.getMnemonic(), attr);
2956+
f.setInlineKind(cir::InlineKind::NoInline);
29672957
} else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
29682958
// (noinline wins over always_inline, and we can't specify both in IR)
2969-
auto attr =
2970-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline);
2971-
attrs.set(attr.getMnemonic(), attr);
2959+
f.setInlineKind(cir::InlineKind::AlwaysInline);
29722960
} else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
29732961
// If we're not inlining, then force everything that isn't always_inline
29742962
// to carry an explicit noinline attribute.
29752963
if (!isAlwaysInline) {
2976-
auto attr =
2977-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2978-
attrs.set(attr.getMnemonic(), attr);
2964+
f.setInlineKind(cir::InlineKind::NoInline);
29792965
}
29802966
} else {
29812967
// Otherwise, propagate the inline hint attribute and potentially use its
@@ -2994,15 +2980,11 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(const Decl *decl,
29942980
return any_of(pattern->redecls(), checkRedeclForInline);
29952981
};
29962982
if (checkForInline(fd)) {
2997-
auto attr = cir::InlineAttr::get(&getMLIRContext(),
2998-
cir::InlineKind::InlineHint);
2999-
attrs.set(attr.getMnemonic(), attr);
2983+
f.setInlineKind(cir::InlineKind::InlineHint);
30002984
} else if (codeGenOpts.getInlining() ==
30012985
CodeGenOptions::OnlyHintInlining &&
30022986
!fd->isInlined() && !isAlwaysInline) {
3003-
auto attr =
3004-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
3005-
attrs.set(attr.getMnemonic(), attr);
2987+
f.setInlineKind(cir::InlineKind::NoInline);
30062988
}
30072989
}
30082990
}

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,42 @@ void parseVisibilityAttr(OpAsmParser &parser, cir::VisibilityAttr &visibility) {
267267
visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
268268
}
269269

270+
//===----------------------------------------------------------------------===//
271+
// InlineKindAttr (FIXME: remove once FuncOp uses assembly format)
272+
//===----------------------------------------------------------------------===//
273+
274+
ParseResult parseInlineKindAttr(OpAsmParser &parser,
275+
cir::InlineKindAttr &inlineKindAttr) {
276+
// Static list of possible inline kind keywords
277+
static constexpr llvm::StringRef keywords[] = {"no_inline", "always_inline",
278+
"inline_hint"};
279+
280+
// Parse the inline kind keyword (optional)
281+
llvm::StringRef keyword;
282+
if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
283+
// Not an inline kind keyword, leave inlineKindAttr empty
284+
return success();
285+
}
286+
287+
// Parse the enum value from the keyword
288+
auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
289+
if (!inlineKindResult) {
290+
return parser.emitError(parser.getCurrentLocation(), "expected one of [")
291+
<< llvm::join(llvm::ArrayRef(keywords), ", ")
292+
<< "] for inlineKind, got: " << keyword;
293+
}
294+
295+
inlineKindAttr =
296+
::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
297+
return success();
298+
}
299+
300+
void printInlineKindAttr(OpAsmPrinter &p, cir::InlineKindAttr inlineKindAttr) {
301+
if (inlineKindAttr) {
302+
p << " " << stringifyInlineKind(inlineKindAttr.getValue());
303+
}
304+
}
305+
270306
//===----------------------------------------------------------------------===//
271307
// CIR Custom Parsers/Printers
272308
//===----------------------------------------------------------------------===//
@@ -2646,6 +2682,7 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
26462682

26472683
auto builtinNameAttr = getBuiltinAttrName(state.name);
26482684
auto coroutineNameAttr = getCoroutineAttrName(state.name);
2685+
auto inlineKindNameAttr = getInlineKindAttrName(state.name);
26492686
auto lambdaNameAttr = getLambdaAttrName(state.name);
26502687
auto visNameAttr = getSymVisibilityAttrName(state.name);
26512688
auto noProtoNameAttr = getNoProtoAttrName(state.name);
@@ -2658,6 +2695,14 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
26582695
if (::mlir::succeeded(
26592696
parser.parseOptionalKeyword(coroutineNameAttr.strref())))
26602697
state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
2698+
2699+
// Parse optional inline kind attribute
2700+
cir::InlineKindAttr inlineKindAttr;
2701+
if (failed(parseInlineKindAttr(parser, inlineKindAttr)))
2702+
return failure();
2703+
if (inlineKindAttr)
2704+
state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2705+
26612706
if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
26622707
state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
26632708
if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
@@ -2892,6 +2937,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
28922937
if (getCoroutine())
28932938
p << " coroutine";
28942939

2940+
printInlineKindAttr(p, getInlineKindAttr());
2941+
28952942
if (getLambda())
28962943
p << " lambda";
28972944

@@ -2941,14 +2988,26 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
29412988
function_interface_impl::printFunctionAttributes(
29422989
p, *this,
29432990
// These are all omitted since they are custom printed already.
2944-
{getAliaseeAttrName(), getBuiltinAttrName(), getCoroutineAttrName(),
2945-
getDsoLocalAttrName(), getExtraAttrsAttrName(),
2946-
getFunctionTypeAttrName(), getGlobalCtorPriorityAttrName(),
2947-
getGlobalDtorPriorityAttrName(), getLambdaAttrName(),
2948-
getLinkageAttrName(), getCallingConvAttrName(), getNoProtoAttrName(),
2949-
getSymVisibilityAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2950-
getComdatAttrName(), getGlobalVisibilityAttrName(),
2951-
getAnnotationsAttrName(), getCxxSpecialMemberAttrName()});
2991+
{getAliaseeAttrName(),
2992+
getBuiltinAttrName(),
2993+
getCoroutineAttrName(),
2994+
getDsoLocalAttrName(),
2995+
getExtraAttrsAttrName(),
2996+
getFunctionTypeAttrName(),
2997+
getGlobalCtorPriorityAttrName(),
2998+
getGlobalDtorPriorityAttrName(),
2999+
getInlineKindAttrName(),
3000+
getLambdaAttrName(),
3001+
getLinkageAttrName(),
3002+
getCallingConvAttrName(),
3003+
getNoProtoAttrName(),
3004+
getSymVisibilityAttrName(),
3005+
getArgAttrsAttrName(),
3006+
getResAttrsAttrName(),
3007+
getComdatAttrName(),
3008+
getGlobalVisibilityAttrName(),
3009+
getAnnotationsAttrName(),
3010+
getCxxSpecialMemberAttrName()});
29523011

29533012
if (auto aliaseeName = getAliasee()) {
29543013
p << " alias(";

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2370,6 +2370,7 @@ void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
23702370
name == getLinkageAttrNameString() ||
23712371
name == func.getCallingConvAttrName() ||
23722372
name == func.getDsoLocalAttrName() ||
2373+
name == func.getInlineKindAttrName() ||
23732374
(filterArgAndResAttrs && (name == func.getArgAttrsAttrName() ||
23742375
name == func.getResAttrsAttrName())))
23752376
continue;
@@ -2492,6 +2493,21 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
24922493
llvmFnTy, linkage, isDsoLocal, cconv,
24932494
mlir::SymbolRefAttr(), attributes);
24942495

2496+
if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2497+
switch (*inlineKind) {
2498+
case cir::InlineKind::NoInline:
2499+
fn.setNoInline(true);
2500+
break;
2501+
case cir::InlineKind::AlwaysInline:
2502+
fn.setAlwaysInline(true);
2503+
break;
2504+
case cir::InlineKind::InlineHint:
2505+
fn.setInlineHint(true);
2506+
break;
2507+
default:
2508+
llvm_unreachable("Unknown inline kind");
2509+
}
2510+
}
24952511
// Lower CIR attributes for arguments.
24962512
for (unsigned index = 0; index < fnType.getNumInputs(); index++) {
24972513
mlir::DictionaryAttr cirAttrs = op.getArgAttrDict(index);

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,7 @@ class CIRDialectLLVMIRTranslationInterface
100100
if (auto extraAttr = mlir::dyn_cast<cir::ExtraFuncAttributesAttr>(
101101
attribute.getValue())) {
102102
for (auto attr : extraAttr.getElements()) {
103-
if (auto inlineAttr =
104-
mlir::dyn_cast<cir::InlineAttr>(attr.getValue())) {
105-
if (inlineAttr.isNoInline())
106-
llvmFunc->addFnAttr(llvm::Attribute::NoInline);
107-
else if (inlineAttr.isAlwaysInline())
108-
llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
109-
else if (inlineAttr.isInlineHint())
110-
llvmFunc->addFnAttr(llvm::Attribute::InlineHint);
111-
else
112-
llvm_unreachable("Unknown inline kind");
113-
} else if (mlir::dyn_cast<cir::OptNoneAttr>(attr.getValue())) {
103+
if (mlir::dyn_cast<cir::OptNoneAttr>(attr.getValue())) {
114104
llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
115105
} else if (mlir::dyn_cast<cir::NoThrowAttr>(attr.getValue())) {
116106
llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);

clang/test/CIR/CodeGen/OpenCL/convergent.cl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,23 @@
66
// In ClangIR for OpenCL, all functions should be marked convergent.
77
// In LLVM IR, it is initially assumed convergent, but can be deduced to not require it.
88

9-
// CIR: #fn_attr[[CONV_NOINLINE_ATTR:[0-9]*]] = #cir<extra({convergent = #cir.convergent, inline = #cir.inline<no>
10-
// CIR-NEXT: #fn_attr[[CONV_DECL_ATTR:[0-9]*]] = #cir<extra({convergent = #cir.convergent
9+
// CIR: #fn_attr = #cir<extra({convergent = #cir.convergent
1110

1211
__attribute__((noinline))
1312
void non_convfun(void) {
1413
volatile int* p;
1514
*p = 0;
1615
}
17-
// CIR: cir.func{{.*}} @non_convfun(){{.*}} extra(#fn_attr[[CONV_NOINLINE_ATTR]])
16+
// CIR: cir.func no_inline @non_convfun(){{.*}} extra(#fn_attr)
1817
// LLVM: define{{.*}} spir_func void @non_convfun() local_unnamed_addr #[[NON_CONV_ATTR:[0-9]+]]
1918
// LLVM: ret void
2019

2120
// External functions should be assumed convergent.
2221
void f(void);
23-
// CIR: cir.func{{.+}} @f(){{.*}} extra(#fn_attr[[CONV_DECL_ATTR]])
22+
// CIR: cir.func{{.+}} @f(){{.*}} extra(#fn_attr)
2423
// LLVM: declare spir_func void @f() local_unnamed_addr #[[CONV_ATTR:[0-9]+]]
2524
void g(void);
26-
// CIR: cir.func{{.+}} @g(){{.*}} extra(#fn_attr[[CONV_DECL_ATTR]])
25+
// CIR: cir.func{{.+}} @g(){{.*}} extra(#fn_attr)
2726
// LLVM: declare spir_func void @g() local_unnamed_addr #[[CONV_ATTR]]
2827

2928
// Test two if's are merged and non_convfun duplicated.
@@ -36,7 +35,7 @@ void test_merge_if(int a) {
3635
g();
3736
}
3837
}
39-
// CIR: cir.func{{.*}} @test_merge_if{{.*}} extra(#fn_attr[[CONV_DECL_ATTR]])
38+
// CIR: cir.func{{.*}} @test_merge_if{{.*}} extra(#fn_attr)
4039

4140
// The LLVM IR below is equivalent to:
4241
// if (a) {
@@ -67,7 +66,7 @@ void test_merge_if(int a) {
6766

6867

6968
void convfun(void) __attribute__((convergent));
70-
// CIR: cir.func{{.+}} @convfun(){{.*}} extra(#fn_attr[[CONV_DECL_ATTR]])
69+
// CIR: cir.func{{.+}} @convfun(){{.*}} extra(#fn_attr)
7170
// LLVM: declare spir_func void @convfun() local_unnamed_addr #[[CONV_ATTR]]
7271

7372
// Test two if's are not merged.
@@ -80,7 +79,7 @@ void test_no_merge_if(int a) {
8079
g();
8180
}
8281
}
83-
// CIR: cir.func{{.*}} @test_no_merge_if{{.*}} extra(#fn_attr[[CONV_DECL_ATTR]])
82+
// CIR: cir.func{{.*}} @test_no_merge_if{{.*}} extra(#fn_attr)
8483

8584
// LLVM-LABEL: define{{.*}} spir_func void @test_no_merge_if
8685
// LLVM: %[[tobool:.+]] = icmp eq i32 %[[ARG:.+]], 0

clang/test/CIR/CodeGen/call-extra-attrs.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ int s2(int a, int b) {
1818
return s1(a, b);
1919
}
2020

21-
// CIR: #fn_attr = #cir<extra({inline = #cir.inline<no>, nothrow = #cir.nothrow, optnone = #cir.optnone})>
21+
// CIR: #fn_attr = #cir<extra({nothrow = #cir.nothrow, optnone = #cir.optnone})>
2222
// CIR: #fn_attr1 = #cir<extra({nothrow = #cir.nothrow})>
2323

24-
// CIR: cir.func {{.*}} @_Z2s0ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr)
25-
// CIR: cir.func {{.*}} @_Z2s1ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr)
24+
// CIR: cir.func{{.*}} no_inline {{.*}} @_Z2s0ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr)
25+
// CIR: cir.func{{.*}} no_inline {{.*}} @_Z2s1ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr)
2626
// CIR: cir.call @_Z2s0ii(%{{.*}}, %{{.*}}) : ({{.*}}, {{.*}}) -> {{.*}} extra(#fn_attr1)
2727
// CIR: cir.func {{.*}} @_Z2s2ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr)
2828
// CHECK-NOT: cir.call @_Z2s1ii(%{{.*}}, %{{.*}}) : ({{.*}}, {{.*}}) -> {{.*}} extra(#fn_attr{{.*}})

clang/test/CIR/CodeGen/conditional-cleanup.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ namespace test7 {
8282

8383
// CIR_EH-DAG: #[[$ATTR_0:.+]] = #cir.bool<false> : !cir.bool
8484
// CIR_EH-DAG: #[[$ATTR_1:.+]] = #cir<extra({nothrow = #cir.nothrow})>
85-
// CIR_EH-DAG: #[[$ATTR_2:.+]] = #cir<extra({inline = #cir.inline<no>, optnone = #cir.optnone})>
8685
// CIR_EH-DAG: #[[$ATTR_3:.+]] = #cir.bool<true> : !cir.bool
8786

8887
// CIR_EH-LABEL: @_ZN5test74testEv

0 commit comments

Comments
 (0)