blob: 84c41ebc944d4efef563928a1da2007371cc33bc [file] [log] [blame]
commit e53bbd99516fc7b612df1ae08d48288d0b8784ea
Author: Zequan Wu <zequanwu@google.com>
Date: Tue Jan 12 11:22:31 2021 -0800
[IR] move nomerge attribute from function declaration/definition to callsites
Move nomerge attribute from function declaration/definition to callsites to
allow virtual function calls attach the attribute.
Differential Revision: https://reviews.llvm.org/D94537
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 2cc7203d1194..42801372189b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1985,7 +1985,9 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
NBA = Fn->getAttr<NoBuiltinAttr>();
}
- if (!AttrOnCallSite && TargetDecl->hasAttr<NoMergeAttr>())
+ // Only place nomerge attribute on call sites, never functions. This
+ // allows it to work on indirect virtual function calls.
+ if (AttrOnCallSite && TargetDecl->hasAttr<NoMergeAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoMerge);
}
@@ -5018,13 +5020,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
llvm::Attribute::StrictFP);
- // Add nomerge attribute to the call-site if the callee function doesn't have
- // the attribute.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
- if (!FD->hasAttr<NoMergeAttr>() && InNoMergeAttributedStmt)
- Attrs = Attrs.addAttribute(getLLVMContext(),
- llvm::AttributeList::FunctionIndex,
- llvm::Attribute::NoMerge);
+ // 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/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index da5b03b138bf..bee51715bdc6 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1772,9 +1772,6 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::MinSize);
}
- if (D->hasAttr<NoMergeAttr>())
- B.addAttribute(llvm::Attribute::NoMerge);
-
F->addAttributes(llvm::AttributeList::FunctionIndex, B);
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp
index d93f4a7c96d6..fc26af379fdb 100644
--- a/clang/test/CodeGen/attr-nomerge.cpp
+++ b/clang/test/CodeGen/attr-nomerge.cpp
@@ -3,7 +3,7 @@
class A {
public:
[[clang::nomerge]] A();
- [[clang::nomerge]] ~A();
+ [[clang::nomerge]] virtual ~A();
[[clang::nomerge]] void f();
[[clang::nomerge]] virtual void g();
[[clang::nomerge]] static void f1();
@@ -14,14 +14,14 @@ public:
void g() override;
};
-[[clang::nomerge]] bool bar();
+bool bar();
[[clang::nomerge]] void f(bool, bool);
void foo(int i, A *ap, B *bp) {
[[clang::nomerge]] bar();
[[clang::nomerge]] (i = 4, bar());
[[clang::nomerge]] (void)(bar());
- [[clang::nomerge]] f(bar(), bar());
+ 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"); }
@@ -37,6 +37,9 @@ void foo(int i, A *ap, B *bp) {
B b;
b.g();
+
+ A *newA = new B();
+ delete newA;
}
int g(int i);
@@ -57,37 +60,34 @@ void something_else_again() {
g(1);
}
+// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0:[0-9]+]]
+// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]]
+// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]]
// CHECK: call zeroext i1 @_Z3barv(){{$}}
// CHECK: call zeroext i1 @_Z3barv(){{$}}
-// CHECK: call zeroext i1 @_Z3barv(){{$}}
-// CHECK: call zeroext i1 @_Z3barv(){{$}}
-// CHECK: call zeroext i1 @_Z3barv(){{$}}
-// CHECK: call void @_Z1fbb({{.*}}){{$}}
-// CHECK: call void @"_ZZ3fooiP1AP1BENK3$_0clEv"{{.*}} #[[ATTR0:[0-9]+]]
-// CHECK: call zeroext i1 @_Z3barv(){{$}}
-// CHECK: call zeroext i1 @_Z3barv(){{$}}
-// CHECK: call zeroext i1 @_Z3barv(){{$}}
+// CHECK: call void @_Z1fbb({{.*}}) #[[ATTR0]]
+// CHECK: call void @"_ZZ3fooiP1AP1BENK3$_0clEv"{{.*}} #[[ATTR0]]
+// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]]
+// CHECK-LABEL: for.cond:
+// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]]
+// CHECK-LABEL: for.inc:
+// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]]
// CHECK: call void asm sideeffect "nop"{{.*}} #[[ATTR1:[0-9]+]]
// CHECK: call zeroext i1 @_Z3barv(){{$}}
// CHECK: %[[AG:.*]] = load void (%class.A*)*, void (%class.A*)**
-// CHECK-NEXT: call void %[[AG]](%class.A* nonnull dereferenceable
+// CHECK-NEXT: call void %[[AG]](%class.A* {{.*}}) #[[ATTR0]]
// CHECK: %[[BG:.*]] = load void (%class.B*)*, void (%class.B*)**
// CHECK-NEXT: call void %[[BG]](%class.B* nonnull dereferenceable
-
-
-// CHECK-DAG: declare zeroext i1 @_Z3barv() #[[ATTR2:[0-9]+]]
-// CHECK-DAG: declare void @_Z1fbb(i1 zeroext, i1 zeroext) #[[ATTR2]]
-// CHECK-DAG: declare void @_ZN1AC1Ev{{.*}} #[[ATTR2]]
-// CHECK-DAG: declare void @_ZN1A1fEv{{.*}} #[[ATTR2]]
-// CHECK-DAG: declare void @_ZN1A1gEv{{.*}} #[[ATTR2]]
-// CHECK-DAG: declare void @_ZN1A2f1Ev{{.*}} #[[ATTR2]]
-// CHECK-DAG: declare void @_ZN1AC2Ev{{.*}} #[[ATTR2]]
-// CHECK-DAG: declare void @_ZN1AD1Ev{{.*}} #[[ATTR3:[0-9]+]]
-// CHECK-DAG: declare void @_ZN1AD2Ev{{.*}} #[[ATTR3]]
-// CHECK-DAG: define{{.*}} i32 @_Z1gi(i32 %i) #[[ATTR4:[0-9]+]] {
+// CHECK: call void @_ZN1AC1Ev({{.*}}) #[[ATTR0]]
+// CHECK: call void @_ZN1A1fEv({{.*}}) #[[ATTR0]]
+// CHECK: call void @_ZN1A1gEv({{.*}}) #[[ATTR0]]
+// CHECK: call void @_ZN1A2f1Ev() #[[ATTR0]]
+// CHECK: call void @_ZN1BC1Ev({{.*}}){{$}}
+// CHECK: call void @_ZN1B1gEv({{.*}}){{$}}
+// CHECK: call void @_ZN1BC1Ev({{.*}}){{$}}
+// CHECK: %[[AG:.*]] = load void (%class.A*)*, void (%class.A*)**
+// CHECK-NEXT: call void %[[AG]](%class.A* {{.*}}) #[[ATTR1]]
+// CHECK: call void @_ZN1AD1Ev(%class.A* {{.*}}) #[[ATTR1]]
// CHECK-DAG: attributes #[[ATTR0]] = {{{.*}}nomerge{{.*}}}
// CHECK-DAG: attributes #[[ATTR1]] = {{{.*}}nomerge{{.*}}}
-// CHECK-DAG: attributes #[[ATTR2]] = {{{.*}}nomerge{{.*}}}
-// CHECK-DAG: attributes #[[ATTR3]] = {{{.*}}nomerge{{.*}}}
-// CHECK-DAG: attributes #[[ATTR4]] = {{{.*}}nomerge{{.*}}}