Skip to content

Commit 3d0c300

Browse files
committed
[ClR] Set optnone attrbiute for functions.
Summary: Setting the Optnone attribute for CIR functions and progating it all the way down to LLVM IR for those not supposed to be optimized.
1 parent e60037a commit 3d0c300

File tree

6 files changed

+115
-2
lines changed

6 files changed

+115
-2
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ class CIR_Attr<string name, string attrMnemonic, list<Trait> traits = []>
2626
let mnemonic = attrMnemonic;
2727
}
2828

29+
class CIR_Unit_Attr<string name, string attrMnemonic, list<Trait> traits = []>
30+
: CIR_Attr<name, attrMnemonic, traits> {
31+
let returnType = "bool";
32+
let defaultValue = "false";
33+
let valueType = NoneType;
34+
let isOptional = 1;
35+
}
36+
2937
//===----------------------------------------------------------------------===//
3038
// NullAttr
3139
//===----------------------------------------------------------------------===//
@@ -351,4 +359,13 @@ def ASTFunctionDeclAttr : ASTDecl<"FunctionDecl", "fndecl">;
351359
def ASTVarDeclAttr : ASTDecl<"VarDecl", "vardecl">;
352360
def ASTRecordDeclAttr : ASTDecl<"RecordDecl", "recdecl">;
353361

362+
363+
def OptnoneAttr : CIR_Unit_Attr<"Optnone", "optnone"> {
364+
let storageType = [{ OptnoneAttr }];
365+
}
366+
367+
def NoInlineAttr : CIR_Attr<"NoInline", "noInline"> {
368+
let storageType = [{ NoInlineAttr }];
369+
}
370+
354371
#endif // MLIR_CIR_DIALECT_CIR_ATTRS

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,9 @@ CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
16641664
builder.getContext(), mlir::cir::GlobalLinkageKind::ExternalLinkage));
16651665
mlir::SymbolTable::setSymbolVisibility(
16661666
f, mlir::SymbolTable::Visibility::Private);
1667+
1668+
setCodegenAttributesForFunc(f, FD);
1669+
16671670
if (!curCGF)
16681671
theModule.push_back(f);
16691672
}
@@ -1689,6 +1692,27 @@ mlir::Location CIRGenModule::getLocForFunction(const clang::FunctionDecl *FD) {
16891692
return theModule->getLoc();
16901693
}
16911694

1695+
void CIRGenModule::setCodegenAttributesForFunc(FuncOp f,
1696+
const clang::FunctionDecl *FD) {
1697+
llvm::SmallVector<mlir::Attribute, 4> attrs;
1698+
1699+
// Track whether we need to add the optnone attribute,
1700+
// starting with the default for this optimization level.
1701+
bool ShouldAddOptNone =
1702+
!codeGenOpts.DisableO0ImplyOptNone && codeGenOpts.OptimizationLevel == 0;
1703+
ShouldAddOptNone &= !FD->hasAttr<MinSizeAttr>();
1704+
ShouldAddOptNone &= !FD->hasAttr<AlwaysInlineAttr>();
1705+
1706+
if ((ShouldAddOptNone || FD->hasAttr<OptimizeNoneAttr>())) {
1707+
attrs.push_back(mlir::cir::OptnoneAttr::get(builder.getContext()));
1708+
1709+
// OptimizeNone implies noinline; we should not be inlining such functions.
1710+
attrs.push_back(mlir::cir::NoInlineAttr::get(builder.getContext()));
1711+
}
1712+
1713+
f->setAttr("cir.funcAttr", mlir::ArrayAttr::get(builder.getContext(), attrs));
1714+
}
1715+
16921716
/// If the specified mangled name is not in the module,
16931717
/// create and return a CIR Function with the specified type. If there is
16941718
/// something in the module with the specified name, return it potentially

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ class CIRGenModule : public CIRGenTypeCache {
518518

519519
mlir::Location getLocForFunction(const clang::FunctionDecl *FD);
520520

521+
void setCodegenAttributesForFunc(mlir::cir::FuncOp f,
522+
const clang::FunctionDecl *FD);
523+
521524
// TODO: CodeGen also passes an AttributeList here. We'll have to match that
522525
// in CIR
523526
mlir::cir::FuncOp

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
1314
#include "mlir/IR/DialectRegistry.h"
1415
#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
16+
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
17+
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
1518
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1619
#include "clang/CIR/Passes.h"
1720

@@ -34,6 +37,20 @@ class CIRDialectLLVMIRTranslationInterface
3437
amendOperation(mlir::Operation *op, mlir::NamedAttribute attribute,
3538
mlir::LLVM::ModuleTranslation &moduleTranslation) const final {
3639
// TODO: Implement this
40+
auto func = dyn_cast<mlir::LLVM::LLVMFuncOp>(op);
41+
if (!func)
42+
return mlir::success();
43+
llvm::Function *llvmFunc = moduleTranslation.lookupFunction(func.getName());
44+
if (attribute.getName() == "cir.funcAttr") {
45+
auto arrayAttr = attribute.getValue().dyn_cast<mlir::ArrayAttr>();
46+
assert(arrayAttr && " cir.funcAttr should be an array.");
47+
for (auto attr : arrayAttr) {
48+
if (auto optnone = attr.dyn_cast<mlir::cir::OptnoneAttr>())
49+
llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
50+
else if (auto optnone = attr.dyn_cast<mlir::cir::NoInlineAttr>())
51+
llvmFunc->addFnAttr(llvm::Attribute::NoInline);
52+
}
53+
}
3754
return mlir::success();
3855
}
3956
};

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

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,28 @@ class CIRFuncLowering : public mlir::OpConversionPattern<mlir::cir::FuncOp> {
655655
public:
656656
using OpConversionPattern<mlir::cir::FuncOp>::OpConversionPattern;
657657

658+
/// Returns the name used for the linkage attribute. This *must* correspond to
659+
/// the name of the attribute in ODS.
660+
static StringRef getLinkageAttrNameString() { return "linkage"; }
661+
662+
/// Only retain those attributes that are not constructed by
663+
/// `LLVMFuncOp::build`. If `filterArgAttrs` is set, also filter out argument
664+
/// attributes.
665+
static void filterFuncAttributes(mlir::cir::FuncOp func,
666+
bool filterArgAndResAttrs,
667+
SmallVectorImpl<mlir::NamedAttribute> &result) {
668+
for (const auto &attr : func->getAttrs()) {
669+
if (attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
670+
attr.getName() == func.getFunctionTypeAttrName() ||
671+
attr.getName() == getLinkageAttrNameString() ||
672+
(filterArgAndResAttrs &&
673+
(attr.getName() == func.getArgAttrsAttrName() ||
674+
attr.getName() == func.getResAttrsAttrName())))
675+
continue;
676+
result.push_back(attr);
677+
}
678+
}
679+
658680
mlir::LogicalResult
659681
matchAndRewrite(mlir::cir::FuncOp op, OpAdaptor adaptor,
660682
mlir::ConversionPatternRewriter &rewriter) const override {
@@ -690,9 +712,14 @@ class CIRFuncLowering : public mlir::OpConversionPattern<mlir::cir::FuncOp> {
690712
Loc = FusedLoc.getLocations()[0];
691713
}
692714
assert(Loc.isa<mlir::FileLineColLoc>() && "expected single location here");
715+
693716
auto linkage = convertLinkage(op.getLinkage());
694-
auto fn = rewriter.create<mlir::LLVM::LLVMFuncOp>(Loc, op.getName(),
695-
llvmFnTy, linkage);
717+
SmallVector<mlir::NamedAttribute, 4> attributes;
718+
filterFuncAttributes(op, /*filterArgAndResAttrs=*/false, attributes);
719+
720+
auto fn = rewriter.create<mlir::LLVM::LLVMFuncOp>(
721+
Loc, op.getName(), llvmFnTy, linkage, false, mlir::LLVM::CConv::C,
722+
attributes);
696723

697724
rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
698725
if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,

clang/test/CIR/CodeGen/optnone.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR-O0
3+
// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-llvm %s -o %t.ll
4+
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM-O0
5+
6+
// RUN: %clang_cc1 -O2 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-cir %s -o %t2.cir
7+
// RUN: FileCheck --input-file=%t2.cir %s -check-prefix=CIR-O2
8+
// RUN: %clang_cc1 -O2 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-llvm %s -o %t2.ll
9+
// RUN: FileCheck --input-file=%t2.ll %s -check-prefix=LLVM-O2
10+
11+
int s0(int a, int b) {
12+
int x = a + b;
13+
if (x > 0)
14+
x = 0;
15+
else
16+
x = 1;
17+
return x;
18+
}
19+
20+
// CIR-O0: cir.func @_Z2s0ii(%arg0:{{.*}}, %arg1:{{.*}} -> {{.*}} attributes {cir.funcAttr = [#cir.optnone, #cir.noInline]}
21+
// CIR-O2-NOT: cir.func @_Z2s0ii(%arg0:{{.*}}, %arg1:{{.*}} -> {{.*}} attributes {cir.funcAttr = [#cir.optnone, #cir.noInline]}
22+
23+
// LLVM-O0: define i32 @_Z2s0ii(i32 %0, i32 %1) #[[#ATTR:]]
24+
// LLVM-O0: attributes #[[#ATTR]] = { noinline optnone }
25+
// LLVM-O2-NOT: attributes #[[#]] = { noinline optnone }

0 commit comments

Comments
 (0)