[PATCH] D53242: [Inliner] Only remove functions with a COMDAT when it's safe to do so

Aaron Hill via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 12 22:10:42 PDT 2018


Aaron1011 created this revision.
Aaron1011 added reviewers: pcc, tejohnson.
Herald added subscribers: llvm-commits, eraman.

Currently, Inliner will sometimes delete functions in a COMDAT without checking to see if the COMDAT has any other members.
As described in https://reviews.llvm.org/D53234, this is an invalid treatment of COMDAT members, and can lead to issues when using MD_Associated metadata.

I've modified Inliner to ensure that deletion of inlined functions in a COMDAT is always delayed until 'removeDeadFunctions', where the proper checks are performed.
Additionally, I've modified 'removeDeadFunctions' to always process functions with a COMDAT via 'filterDeadComdatFunctions', regardless of their linkage.

I've added a test case to check that the presence of other members in a COMDAT prevents Inliner from deleting a function.

While adding some extra LLVM_DEBUG prints, I found and fixed a bug with printing unnamed COMDATs. It's a one-line fix, so I didn't think it was worth moving into its own patch.


Repository:
  rL LLVM

https://reviews.llvm.org/D53242

Files:
  lib/IR/AsmWriter.cpp
  lib/Transforms/IPO/Inliner.cpp
  test/Transforms/Inline/comdat-ipo.ll


Index: test/Transforms/Inline/comdat-ipo.ll
===================================================================
--- test/Transforms/Inline/comdat-ipo.ll
+++ test/Transforms/Inline/comdat-ipo.ll
@@ -1,6 +1,16 @@
 ; RUN: opt -inline -S < %s | FileCheck %s
 ; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
 
+$c = comdat any
+
+; CHECK: @comdat_global = global i32 0, comdat($c)
+ at comdat_global = global i32 0, comdat($c)
+
+; CHECK: define internal void @comdat_function() comdat($c) {
+define internal void @comdat_function() comdat($c) {
+  ret void
+}
+
 define i32 @caller() {
 ; CHECK-LABEL: @caller(
 ; CHECK-NEXT:  %val2 = call i32 @linkonce_callee(i32 42)
Index: lib/Transforms/IPO/Inliner.cpp
===================================================================
--- lib/Transforms/IPO/Inliner.cpp
+++ lib/Transforms/IPO/Inliner.cpp
@@ -710,7 +710,12 @@
           // The function may be apparently dead, but if there are indirect
           // callgraph references to the node, we cannot delete it yet, this
           // could invalidate the CGSCC iterator.
-          CG[Callee]->getNumReferences() == 0) {
+          CG[Callee]->getNumReferences() == 0 &&
+          // Functions in a COMDAT require special handling
+          // to ensure that we always drop either all or none
+          // of its members. This is handled by 'removeDeadFunctions',
+          // which will be called later.
+          !Callee->hasComdat()) {
         LLVM_DEBUG(dbgs() << "    -> Deleting dead function: "
                           << Callee->getName() << "\n");
         CallGraphNode *CalleeNode = CG[Callee];
@@ -807,14 +812,17 @@
 
     // It is unsafe to drop a function with discardable linkage from a COMDAT
     // without also dropping the other members of the COMDAT.
-    // The inliner doesn't visit non-function entities which are in COMDAT
-    // groups so it is unsafe to do so *unless* the linkage is local.
-    if (!F->hasLocalLinkage()) {
-      if (F->hasComdat()) {
-        DeadFunctionsInComdats.push_back(F);
-        continue;
-      }
+    // If the function has a comdat, we delay removing it
+    // so that we can check to see if we're going to drop the other COMDAT
+    // members.
+    LLVM_DEBUG(dbgs() << "Preparing to delete function: " << F->getName());
+    if (F->hasComdat()) {
+      // Printing a COMDAT also prints a newline
+      LLVM_DEBUG(dbgs() << " with COMDAT: " << *F->getComdat());
+      DeadFunctionsInComdats.push_back(F);
+      continue;
     }
+    LLVM_DEBUG(dbgs() << "\n");
 
     RemoveCGN(CGN);
   }
Index: lib/IR/AsmWriter.cpp
===================================================================
--- lib/IR/AsmWriter.cpp
+++ lib/IR/AsmWriter.cpp
@@ -4067,7 +4067,7 @@
 }
 
 void Comdat::print(raw_ostream &ROS, bool /*IsForDebug*/) const {
-  PrintLLVMName(ROS, getName(), ComdatPrefix);
+  PrintLLVMName(ROS, Name != nullptr ? getName() : "<unnamed>", ComdatPrefix);
   ROS << " = comdat ";
 
   switch (getSelectionKind()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D53242.169542.patch
Type: text/x-patch
Size: 2997 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181013/b8733721/attachment-0001.bin>


More information about the llvm-commits mailing list