zequanwu updated this revision to Diff 265648. zequanwu retitled this revision from "Add nomerge function attribute to clang" to "Add nomerge statement attribute to clang". zequanwu edited the summary of this revision. zequanwu added a comment.
update test case. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D79121/new/ https://reviews.llvm.org/D79121 Files: 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 clang/test/CodeGen/attr-nomerge.cpp clang/test/Sema/attr-nomerge.cpp
Index: clang/test/Sema/attr-nomerge.cpp =================================================================== --- /dev/null +++ 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}} Index: clang/test/CodeGen/attr-nomerge.cpp =================================================================== --- /dev/null +++ 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 } Index: clang/lib/Sema/SemaStmtAttr.cpp =================================================================== --- clang/lib/Sema/SemaStmtAttr.cpp +++ 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 @@ 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 @@ 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 Index: clang/lib/CodeGen/CodeGenFunction.h =================================================================== --- clang/lib/CodeGen/CodeGenFunction.h +++ clang/lib/CodeGen/CodeGenFunction.h @@ -595,6 +595,9 @@ /// region. bool IsInPreservedAIRegion = false; + /// True if the current statement has nomerge attribute. + bool InNoMergeAttributedStmt = false; + const CodeGen::CGBlockInfo *BlockInfo = nullptr; llvm::Value *BlockPointer = nullptr; Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ 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::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()); } Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -4822,6 +4822,12 @@ 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. Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2762,6 +2762,10 @@ 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< Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -350,6 +350,20 @@ }]; } +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"; Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -1275,6 +1275,11 @@ let Documentation = [FallthroughDocs]; } +def NoMerge : StmtAttr { + let Spellings = [Clang<"nomerge">]; + let Documentation = [NoMergeDocs]; +} + def FastCall : DeclOrTypeAttr { let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">, Keyword<"_fastcall">];
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits