diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1954,12 +1954,16 @@ } static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, - bool ReadOnly, bool ReadNone, const AsmStmt &S, + bool ReadOnly, bool ReadNone, bool NoMerge, + const AsmStmt &S, const std::vector &ResultRegTypes, CodeGenFunction &CGF, std::vector &RegResults) { Result.addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoUnwind); + if (NoMerge) + Result.addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoMerge); // Attach readnone and readonly attributes. if (!HasSideEffect) { if (ReadNone) @@ -2334,12 +2338,14 @@ Builder.CreateCallBr(IA, Fallthrough, Transfer, Args); EmitBlock(Fallthrough); UpdateAsmCallInst(cast(*Result), HasSideEffect, ReadOnly, - ReadNone, S, ResultRegTypes, *this, RegResults); + ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes, + *this, RegResults); } else { llvm::CallInst *Result = Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); UpdateAsmCallInst(cast(*Result), HasSideEffect, ReadOnly, - ReadNone, S, ResultRegTypes, *this, RegResults); + ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes, + *this, RegResults); } assert(RegResults.size() == ResultRegTypes.size()); diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -183,6 +183,7 @@ bool foundCallExpr() { return FoundCallExpr; } void VisitCallExpr(const CallExpr *E) { FoundCallExpr = true; } + void VisitAsmStmt(const AsmStmt *S) { FoundCallExpr = true; } void Visit(const Stmt *St) { if (!St) diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp --- a/clang/test/CodeGen/attr-nomerge.cpp +++ b/clang/test/CodeGen/attr-nomerge.cpp @@ -10,6 +10,7 @@ [[clang::nomerge]] f(bar(), bar()); [[clang::nomerge]] [] { bar(); bar(); }(); // nomerge only applies to the anonymous function call [[clang::nomerge]] for (bar(); bar(); bar()) {} + [[clang::nomerge]] { asm("nop"); } bar(); } // CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR:[0-9]+]] @@ -22,5 +23,7 @@ // CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]] // CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]] // CHECK: call zeroext i1 @_Z3barv() #[[NOMERGEATTR]] +// CHECK: call void asm {{.*}} #[[NOMERGEATTR2:[0-9]+]] // CHECK: call zeroext i1 @_Z3barv() // CHECK: attributes #[[NOMERGEATTR]] = { nomerge } +// CHECK: attributes #[[NOMERGEATTR2]] = { nomerge nounwind }