zequanwu created this revision.
zequanwu added reviewers: asbirlea, rnk.
zequanwu added projects: LLVM, clang.
Herald added subscribers: cfe-commits, hiraditya.
We want to add a way to avoid tail calls to noreturn function from being
merged.
This patch add nomerge to disable the optimization in IR level.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D78659
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/lib/CodeGen/CGCall.cpp
llvm/include/llvm/IR/Attributes.td
llvm/include/llvm/IR/InstrTypes.h
llvm/lib/IR/Attributes.cpp
llvm/lib/IR/Verifier.cpp
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
===================================================================
--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -1287,6 +1287,10 @@
if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2))
return Changed;
+ // If any of the two call sites has nomerge attribute, stop hoisting.
+ if (C1->cannotMerge() || C2->cannotMerge())
+ return Changed;
+
if (isa<DbgInfoIntrinsic>(I1) || isa<DbgInfoIntrinsic>(I2)) {
assert (isa<DbgInfoIntrinsic>(I1) && isa<DbgInfoIntrinsic>(I2));
// The debug location is an integral part of a debug info intrinsic
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -1509,6 +1509,7 @@
/// Return true if this attribute kind only applies to functions.
static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
switch (Kind) {
+ case Attribute::NoMerge:
case Attribute::NoReturn:
case Attribute::NoSync:
case Attribute::WillReturn:
Index: llvm/lib/IR/Attributes.cpp
===================================================================
--- llvm/lib/IR/Attributes.cpp
+++ llvm/lib/IR/Attributes.cpp
@@ -368,6 +368,8 @@
return "noinline";
if (hasAttribute(Attribute::NonLazyBind))
return "nonlazybind";
+ if (hasAttribute(Attribute::NoMerge))
+ return "nomerge";
if (hasAttribute(Attribute::NonNull))
return "nonnull";
if (hasAttribute(Attribute::NoRedZone))
Index: llvm/include/llvm/IR/InstrTypes.h
===================================================================
--- llvm/include/llvm/IR/InstrTypes.h
+++ llvm/include/llvm/IR/InstrTypes.h
@@ -1717,6 +1717,9 @@
addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
}
+ /// Determine if the invoke cannot be tail merged.
+ bool cannotMerge() const { return hasFnAttr(Attribute::NoMerge); }
+
/// Determine if the invoke is convergent
bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
void setConvergent() {
Index: llvm/include/llvm/IR/Attributes.td
===================================================================
--- llvm/include/llvm/IR/Attributes.td
+++ llvm/include/llvm/IR/Attributes.td
@@ -97,6 +97,9 @@
/// Function is called early and/or often, so lazy binding isn't worthwhile.
def NonLazyBind : EnumAttr<"nonlazybind">;
+/// Disable tail merge for this function
+def NoMerge : EnumAttr<"nomerge">;
+
/// Pointer is known to be not null.
def NonNull : EnumAttr<"nonnull">;
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1905,6 +1905,8 @@
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
if (TargetDecl->hasAttr<ConvergentAttr>())
FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+ if (TargetDecl->hasAttr<NoMergeAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::NoMerge);
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
AddAttributesFromFunctionProtoType(
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -350,6 +350,14 @@
}];
}
+def NoMergeDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+A function declared as ``nomerge`` shall not be tail merged at call sites during
+optimization phase.
+ }];
+}
+
def AssertCapabilityDocs : Documentation {
let Category = DocCatFunction;
let Heading = "assert_capability, assert_shared_capability";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1793,6 +1793,13 @@
let Documentation = [Undocumented];
}
+def NoMerge : InheritableAttr {
+ let Spellings = [Clang<"nomerge">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NoMergeDocs];
+ let SimpleHandler = 1;
+}
+
def NoInstrumentFunction : InheritableAttr {
let Spellings = [GCC<"no_instrument_function">];
let Subjects = SubjectList<[Function]>;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits