[clang] e36076e - [clang] Add nomerge function attribute to clang
Zequan Wu via cfe-commits
cfe-commits at lists.llvm.org
Thu May 21 17:07:48 PDT 2020
Author: Zequan Wu
Date: 2020-05-21T17:07:39-07:00
New Revision: e36076ee3a2ebc6013372d9b71e6bb09e8612366
URL: https://github.com/llvm/llvm-project/commit/e36076ee3a2ebc6013372d9b71e6bb09e8612366
DIFF: https://github.com/llvm/llvm-project/commit/e36076ee3a2ebc6013372d9b71e6bb09e8612366.diff
LOG: [clang] Add nomerge function attribute to clang
Differential Revision: https://reviews.llvm.org/D79121
Added:
clang/test/CodeGen/attr-nomerge.cpp
clang/test/Sema/attr-nomerge.cpp
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CGStmt.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Sema/SemaStmtAttr.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 833b862cfb5f..a691e2332ff7 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1275,6 +1275,11 @@ def FallThrough : StmtAttr {
let Documentation = [FallthroughDocs];
}
+def NoMerge : StmtAttr {
+ let Spellings = [Clang<"nomerge">];
+ let Documentation = [NoMergeDocs];
+}
+
def FastCall : DeclOrTypeAttr {
let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
Keyword<"_fastcall">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index e3308cd74874..5222c92c42a0 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -350,6 +350,20 @@ that appears to be capable of returning to its caller.
}];
}
+def NoMergeDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+If a statement is marked ``nomerge`` and contains call experessions, those call
+expressions inside the statement will not be merged during optimization. This
+attribute can be used to prevent the optimizer from obscuring the source
+location of certain calls. For example, it will prevent tail merging otherwise
+identical code sequences that raise an exception or terminate the program. Tail
+merging normally reduces the precision of source location information, making
+stack traces less useful for debugging. This attribute gives the user control
+over the tradeoff between code size and debug information precision.
+ }];
+}
+
def AssertCapabilityDocs : Documentation {
let Category = DocCatFunction;
let Heading = "assert_capability, assert_shared_capability";
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d415802916b6..845e329033c3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2762,6 +2762,10 @@ def warn_auto_var_is_id : Warning<
InGroup<DiagGroup<"auto-var-id">>;
// Attributes
+def warn_nomerge_attribute_ignored_in_stmt: Warning<
+ "%0 attribute is ignored because there exists no call expression inside the "
+ "statement">,
+ InGroup<IgnoredAttributes>;
def err_nsobject_attribute : Error<
"'NSObject' attribute is for pointer types only">;
def err_attributes_are_not_compatible : Error<
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 6831f8248225..c324b9fa501e 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4822,6 +4822,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
llvm::Attribute::StrictFP);
+ // Add call-site nomerge attribute if exists.
+ if (InNoMergeAttributedStmt)
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoMerge);
+
// Apply some call-site-specific attributes.
// TODO: work this into building the attribute set.
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index ceecbd4dc137..3559e77fc764 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -25,6 +25,7 @@
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -608,6 +609,13 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
+ bool nomerge = false;
+ for (const auto *A : S.getAttrs())
+ if (A->getKind() == attr::NoMerge) {
+ nomerge = true;
+ break;
+ }
+ SaveAndRestore<bool> save_nomerge(InNoMergeAttributedStmt, nomerge);
EmitStmt(S.getSubStmt(), S.getAttrs());
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 731317aac0dc..2b5871dbb116 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -595,6 +595,9 @@ class CodeGenFunction : public CodeGenTypeCache {
/// region.
bool IsInPreservedAIRegion = false;
+ /// True if the current statement has nomerge attribute.
+ bool InNoMergeAttributedStmt = false;
+
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
llvm::Value *BlockPointer = nullptr;
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 3d91893b4065..e9d3c755eb23 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
@@ -170,6 +171,44 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
return LoopHintAttr::CreateImplicit(S.Context, Option, State, ValueExpr, A);
}
+namespace {
+class CallExprFinder : public ConstEvaluatedExprVisitor<CallExprFinder> {
+ bool FoundCallExpr = false;
+
+public:
+ typedef ConstEvaluatedExprVisitor<CallExprFinder> Inherited;
+
+ CallExprFinder(Sema &S, const Stmt *St) : Inherited(S.Context) { Visit(St); }
+
+ bool foundCallExpr() { return FoundCallExpr; }
+
+ void VisitCallExpr(const CallExpr *E) { FoundCallExpr = true; }
+
+ void Visit(const Stmt *St) {
+ if (!St)
+ return;
+ ConstEvaluatedExprVisitor<CallExprFinder>::Visit(St);
+ }
+};
+} // namespace
+
+static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+ NoMergeAttr NMA(S.Context, A);
+ if (S.CheckAttrNoArgs(A))
+ return nullptr;
+
+ CallExprFinder CEF(S, St);
+
+ if (!CEF.foundCallExpr()) {
+ S.Diag(St->getBeginLoc(), diag::warn_nomerge_attribute_ignored_in_stmt)
+ << NMA.getSpelling();
+ return nullptr;
+ }
+
+ return ::new (S.Context) NoMergeAttr(S.Context, A);
+}
+
static void
CheckForIncompatibleAttributes(Sema &S,
const SmallVectorImpl<const Attr *> &Attrs) {
@@ -335,6 +374,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
return handleOpenCLUnrollHint(S, St, A, Range);
case ParsedAttr::AT_Suppress:
return handleSuppressAttr(S, St, A, Range);
+ case ParsedAttr::AT_NoMerge:
+ return handleNoMergeAttr(S, St, A, Range);
default:
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp
new file mode 100644
index 000000000000..284ce7827966
--- /dev/null
+++ b/clang/test/CodeGen/attr-nomerge.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -S -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
+
+bool bar();
+void f(bool, bool);
+
+void foo(int i) {
+ [[clang::nomerge]] bar();
+ [[clang::nomerge]] (i = 4, bar());
+ [[clang::nomerge]] (void)(bar());
+ [[clang::nomerge]] f(bar(), bar());
+ [[clang::nomerge]] [] { bar(); bar(); }(); // nomerge only applies to the anonymous function call
+ [[clang::nomerge]] for (bar(); bar(); bar()) {}
+ bar();
+}
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR:[0-9]+]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call void @_Z1fbb({{.*}}) #[[NOMERGEATTR]]
+// CHECK: call void @"_ZZ3fooiENK3$_0clEv"(%class.anon* %ref.tmp) #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]]
+// CHECK: call zeroext i1 @_Z3barv()
+// CHECK: attributes #[[NOMERGEATTR]] = { nomerge }
diff --git a/clang/test/Sema/attr-nomerge.cpp b/clang/test/Sema/attr-nomerge.cpp
new file mode 100644
index 000000000000..175153c7753e
--- /dev/null
+++ b/clang/test/Sema/attr-nomerge.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+void bar();
+
+void foo() {
+ [[clang::nomerge]] bar();
+ [[clang::nomerge(1, 2)]] bar(); // expected-error {{'nomerge' attribute takes no arguments}}
+ int x;
+ [[clang::nomerge]] x = 10; // expected-warning {{nomerge attribute is ignored because there exists no call expression inside the statement}}
+
+ [[clang::nomerge]] label: bar(); // expected-error {{'nomerge' attribute cannot be applied to a declaration}}
+
+}
+
+int f();
+
+[[clang::nomerge]] static int i = f(); // expected-error {{'nomerge' attribute cannot be applied to a declaration}}
More information about the cfe-commits
mailing list