[llvm] 1c2531c - [Attributor][FIX] Delete all unreachable static functions

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 27 20:08:43 PDT 2020


Author: Johannes Doerfert
Date: 2020-10-27T22:07:55-05:00
New Revision: 1c2531c9e16412ba2bb2f8e594d7effa48e9d22e

URL: https://github.com/llvm/llvm-project/commit/1c2531c9e16412ba2bb2f8e594d7effa48e9d22e
DIFF: https://github.com/llvm/llvm-project/commit/1c2531c9e16412ba2bb2f8e594d7effa48e9d22e.diff

LOG: [Attributor][FIX] Delete all unreachable static functions

Before we used to only mark unreachable static functions as dead if all
uses were known dead. Now we optimistically assume uses to be dead until
proven otherwise.

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/IPO/Attributor.h
    llvm/lib/Transforms/IPO/Attributor.cpp
    llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
    llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll
    llvm/test/Transforms/Attributor/liveness.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 17b0916a131e..84677815533b 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -1574,6 +1574,10 @@ struct Attributor {
   /// Rewrites function signitures and updates the call graph.
   ChangeStatus cleanupIR();
 
+  /// Identify internal functions that are effectively dead, thus not reachable
+  /// from a live entry point. The functions are added to ToBeDeletedFunctions.
+  void identifyDeadInternalFunctions();
+
   /// Run `::update` on \p AA and track the dependences queried while doing so.
   /// Also adjust the state if we know further updates are not necessary.
   ChangeStatus updateAA(AbstractAttribute &AA);

diff  --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 29d860a6ceac..6efc22093331 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -1165,6 +1165,48 @@ ChangeStatus Attributor::manifestAttributes() {
   return ManifestChange;
 }
 
+void Attributor::identifyDeadInternalFunctions() {
+  // Identify dead internal functions and delete them. This happens outside
+  // the other fixpoint analysis as we might treat potentially dead functions
+  // as live to lower the number of iterations. If they happen to be dead, the
+  // below fixpoint loop will identify and eliminate them.
+  SmallVector<Function *, 8> InternalFns;
+  for (Function *F : Functions)
+    if (F->hasLocalLinkage())
+      InternalFns.push_back(F);
+
+  SmallPtrSet<Function *, 8> LiveInternalFns;
+  bool FoundLiveInternal = true;
+  while (FoundLiveInternal) {
+    FoundLiveInternal = false;
+    for (unsigned u = 0, e = InternalFns.size(); u < e; ++u) {
+      Function *F = InternalFns[u];
+      if (!F)
+        continue;
+
+      bool AllCallSitesKnown;
+      if (checkForAllCallSites(
+              [&](AbstractCallSite ACS) {
+                Function *Callee = ACS.getInstruction()->getFunction();
+                return ToBeDeletedFunctions.count(Callee) ||
+                       (Functions.count(Callee) && Callee->hasLocalLinkage() &&
+                        !LiveInternalFns.count(Callee));
+              },
+              *F, true, nullptr, AllCallSitesKnown)) {
+        continue;
+      }
+
+      LiveInternalFns.insert(F);
+      InternalFns[u] = nullptr;
+      FoundLiveInternal = true;
+    }
+  }
+
+  for (unsigned u = 0, e = InternalFns.size(); u < e; ++u)
+    if (Function *F = InternalFns[u])
+      ToBeDeletedFunctions.insert(F);
+}
+
 ChangeStatus Attributor::cleanupIR() {
   TimeTraceScope TimeScope("Attributor::cleanupIR");
   // Delete stuff at the end to avoid invalid references and a nice order.
@@ -1277,43 +1319,14 @@ ChangeStatus Attributor::cleanupIR() {
     DetatchDeadBlocks(ToBeDeletedBBs, nullptr);
   }
 
-  // Identify dead internal functions and delete them. This happens outside
-  // the other fixpoint analysis as we might treat potentially dead functions
-  // as live to lower the number of iterations. If they happen to be dead, the
-  // below fixpoint loop will identify and eliminate them.
-  SmallVector<Function *, 8> InternalFns;
-  for (Function *F : Functions)
-    if (F->hasLocalLinkage())
-      InternalFns.push_back(F);
-
-  bool FoundDeadFn = true;
-  while (FoundDeadFn) {
-    FoundDeadFn = false;
-    for (unsigned u = 0, e = InternalFns.size(); u < e; ++u) {
-      Function *F = InternalFns[u];
-      if (!F)
-        continue;
-
-      bool AllCallSitesKnown;
-      if (!checkForAllCallSites(
-              [this](AbstractCallSite ACS) {
-                return ToBeDeletedFunctions.count(
-                    ACS.getInstruction()->getFunction());
-              },
-              *F, true, nullptr, AllCallSitesKnown))
-        continue;
-
-      ToBeDeletedFunctions.insert(F);
-      InternalFns[u] = nullptr;
-      FoundDeadFn = true;
-    }
-  }
+  identifyDeadInternalFunctions();
 
   // Rewrite the functions as requested during manifest.
   ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
 
   for (Function *Fn : CGModifiedFunctions)
-    CGUpdater.reanalyzeFunction(*Fn);
+    if (!ToBeDeletedFunctions.count(Fn))
+      CGUpdater.reanalyzeFunction(*Fn);
 
   for (Function *Fn : ToBeDeletedFunctions) {
     if (!Functions.count(Fn))

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
index 19b36c52552b..e7b215791934 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
@@ -5,17 +5,6 @@
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
 
 define internal fastcc i32 @term_SharingList(i32* %Term, i32* %List) nounwind {
-; IS__TUNIT____: Function Attrs: nounwind
-; IS__TUNIT____-LABEL: define {{[^@]+}}@term_SharingList
-; IS__TUNIT____-SAME: (i32* [[TERM:%.*]], i32* [[LIST:%.*]]) [[ATTR0:#.*]] {
-; IS__TUNIT____-NEXT:  entry:
-; IS__TUNIT____-NEXT:    br i1 false, label [[BB:%.*]], label [[BB5:%.*]]
-; IS__TUNIT____:       bb:
-; IS__TUNIT____-NEXT:    [[TMP0:%.*]] = call fastcc i32 @term_SharingList(i32* null, i32* [[LIST]]) [[ATTR0]]
-; IS__TUNIT____-NEXT:    unreachable
-; IS__TUNIT____:       bb5:
-; IS__TUNIT____-NEXT:    ret i32 0
-;
 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@term_SharingList
 ; IS__CGSCC____-SAME: () [[ATTR0:#.*]] {
@@ -40,7 +29,7 @@ bb5:		; preds = %entry
 define i32 @term_Sharing(i32* %Term) nounwind {
 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@term_Sharing
-; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TERM:%.*]]) [[ATTR1:#.*]] {
+; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TERM:%.*]]) [[ATTR0:#.*]] {
 ; IS__TUNIT____-NEXT:  entry:
 ; IS__TUNIT____-NEXT:    br i1 false, label [[BB_I:%.*]], label [[BB14:%.*]]
 ; IS__TUNIT____:       bb.i:

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll b/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll
index 7cd8585afb68..55c2464241fb 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll
@@ -4,12 +4,25 @@
 ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
 define internal void @foo(i32 %X) {
-; CHECK-LABEL: define {{[^@]+}}@foo
-; CHECK-SAME: (i32 [[X:%.*]]) {
-; CHECK-NEXT:    call void @foo(i32 [[X]])
-; CHECK-NEXT:    ret void
+; IS__CGSCC____-LABEL: define {{[^@]+}}@foo
+; IS__CGSCC____-SAME: (i32 [[X:%.*]]) {
+; IS__CGSCC____-NEXT:    call void @foo(i32 [[X]])
+; IS__CGSCC____-NEXT:    ret void
 ;
   call void @foo( i32 %X )
   ret void
 }
 
+define void @bar() {
+; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
+; IS__TUNIT____-LABEL: define {{[^@]+}}@bar
+; IS__TUNIT____-SAME: () [[ATTR0:#.*]] {
+; IS__TUNIT____-NEXT:    ret void
+;
+; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
+; IS__CGSCC____-LABEL: define {{[^@]+}}@bar
+; IS__CGSCC____-SAME: () [[ATTR0:#.*]] {
+; IS__CGSCC____-NEXT:    ret void
+;
+  ret void
+}

diff  --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll
index e521af858add..50c093af962d 100644
--- a/llvm/test/Transforms/Attributor/liveness.ll
+++ b/llvm/test/Transforms/Attributor/liveness.ll
@@ -705,16 +705,16 @@ cond.end:                                               ; preds = %cond.if, %con
 @a2 = common global i8 0, align 16
 
 define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
-; CHECK-LABEL: define {{[^@]+}}@f1
-; CHECK-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
-; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
-; CHECK:       3:
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call i8* @f2(i8* nonnull @a1)
-; CHECK-NEXT:    br label [[TMP5]]
-; CHECK:       5:
-; CHECK-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
-; CHECK-NEXT:    ret i8* [[TMP6]]
+; IS__CGSCC____-LABEL: define {{[^@]+}}@f1
+; IS__CGSCC____-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
+; IS__CGSCC____-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
+; IS__CGSCC____-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
+; IS__CGSCC____:       3:
+; IS__CGSCC____-NEXT:    [[TMP4:%.*]] = tail call i8* @f2(i8* nonnull @a1)
+; IS__CGSCC____-NEXT:    br label [[TMP5]]
+; IS__CGSCC____:       5:
+; IS__CGSCC____-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
+; IS__CGSCC____-NEXT:    ret i8* [[TMP6]]
 ;
   %2 = icmp eq i8* %0, null
   br i1 %2, label %3, label %5
@@ -729,19 +729,19 @@ define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
 }
 
 define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
-; CHECK-LABEL: define {{[^@]+}}@f2
-; CHECK-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
-; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
-; CHECK:       3:
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull [[TMP0]])
-; CHECK-NEXT:    br label [[TMP7:%.*]]
-; CHECK:       5:
-; CHECK-NEXT:    [[TMP6:%.*]] = tail call i8* @f3(i8* nonnull @a2)
-; CHECK-NEXT:    br label [[TMP7]]
-; CHECK:       7:
-; CHECK-NEXT:    [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
-; CHECK-NEXT:    ret i8* [[TMP8]]
+; IS__CGSCC____-LABEL: define {{[^@]+}}@f2
+; IS__CGSCC____-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
+; IS__CGSCC____-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
+; IS__CGSCC____-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
+; IS__CGSCC____:       3:
+; IS__CGSCC____-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull [[TMP0]])
+; IS__CGSCC____-NEXT:    br label [[TMP7:%.*]]
+; IS__CGSCC____:       5:
+; IS__CGSCC____-NEXT:    [[TMP6:%.*]] = tail call i8* @f3(i8* nonnull @a2)
+; IS__CGSCC____-NEXT:    br label [[TMP7]]
+; IS__CGSCC____:       7:
+; IS__CGSCC____-NEXT:    [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
+; IS__CGSCC____-NEXT:    ret i8* [[TMP8]]
 ;
   %2 = icmp eq i8* %0, null
   br i1 %2, label %5, label %3
@@ -761,16 +761,16 @@ define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
 }
 
 define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
-; CHECK-LABEL: define {{[^@]+}}@f3
-; CHECK-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
-; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
-; CHECK:       3:
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull @a2)
-; CHECK-NEXT:    br label [[TMP5]]
-; CHECK:       5:
-; CHECK-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
-; CHECK-NEXT:    ret i8* [[TMP6]]
+; IS__CGSCC____-LABEL: define {{[^@]+}}@f3
+; IS__CGSCC____-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
+; IS__CGSCC____-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
+; IS__CGSCC____-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
+; IS__CGSCC____:       3:
+; IS__CGSCC____-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull @a2)
+; IS__CGSCC____-NEXT:    br label [[TMP5]]
+; IS__CGSCC____:       5:
+; IS__CGSCC____-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
+; IS__CGSCC____-NEXT:    ret i8* [[TMP6]]
 ;
   %2 = icmp eq i8* %0, null
   br i1 %2, label %3, label %5


        


More information about the llvm-commits mailing list