[llvm] r268468 - [GlobalDCE, Misc] Don't remove functions referenced by ifuncs

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Tue May 3 17:20:49 PDT 2016


Author: majnemer
Date: Tue May  3 19:20:48 2016
New Revision: 268468

URL: http://llvm.org/viewvc/llvm-project?rev=268468&view=rev
Log:
[GlobalDCE, Misc] Don't remove functions referenced by ifuncs

We forgot to consider the target of ifuncs when considering if a
function was alive or dead.

N.B. Also update a few auxiliary tools like bugpoint and
verify-uselistorder.

This fixes PR27593.

Added:
    llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll
Modified:
    llvm/trunk/include/llvm/IR/GlobalAlias.h
    llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h
    llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
    llvm/trunk/lib/Transforms/Utils/SplitModule.cpp
    llvm/trunk/tools/bugpoint/CrashDebugger.cpp
    llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp

Modified: llvm/trunk/include/llvm/IR/GlobalAlias.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalAlias.h?rev=268468&r1=268467&r2=268468&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalAlias.h (original)
+++ llvm/trunk/include/llvm/IR/GlobalAlias.h Tue May  3 19:20:48 2016
@@ -78,21 +78,6 @@ public:
     return getIndirectSymbol();
   }
 
-  const GlobalObject *getBaseObject() const {
-    return const_cast<GlobalAlias *>(this)->getBaseObject();
-  }
-  GlobalObject *getBaseObject() {
-    return dyn_cast<GlobalObject>(getAliasee()->stripInBoundsOffsets());
-  }
-
-  const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
-    return const_cast<GlobalAlias *>(this)->getBaseObject(DL, Offset);
-  }
-  GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
-    return dyn_cast<GlobalObject>(
-        getAliasee()->stripAndAccumulateInBoundsConstantOffsets(DL, Offset));
-  }
-
   static bool isValidLinkage(LinkageTypes L) {
     return isExternalLinkage(L) || isLocalLinkage(L) ||
       isWeakLinkage(L) || isLinkOnceLinkage(L);

Modified: llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h?rev=268468&r1=268467&r2=268468&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h (original)
+++ llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h Tue May  3 19:20:48 2016
@@ -49,6 +49,22 @@ public:
     return getOperand(0);
   }
 
+  const GlobalObject *getBaseObject() const {
+    return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject();
+  }
+  GlobalObject *getBaseObject() {
+    return dyn_cast<GlobalObject>(getIndirectSymbol()->stripInBoundsOffsets());
+  }
+
+  const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
+    return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject(DL, Offset);
+  }
+  GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
+    return dyn_cast<GlobalObject>(
+        getIndirectSymbol()->stripAndAccumulateInBoundsConstantOffsets(DL,
+                                                                       Offset));
+  }
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Value *V) {
     return V->getValueID() == Value::GlobalAliasVal ||

Modified: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp?rev=268468&r1=268467&r2=268468&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp Tue May  3 19:20:48 2016
@@ -32,6 +32,7 @@ using namespace llvm;
 
 STATISTIC(NumAliases  , "Number of global aliases removed");
 STATISTIC(NumFunctions, "Number of functions removed");
+STATISTIC(NumIFuncs,    "Number of indirect functions removed");
 STATISTIC(NumVariables, "Number of global variables removed");
 
 namespace {
@@ -118,6 +119,13 @@ PreservedAnalyses GlobalDCEPass::run(Mod
       GlobalIsNeeded(&GA);
   }
 
+  for (GlobalIFunc &GIF : M.ifuncs()) {
+    Changed |= RemoveUnusedGlobalValue(GIF);
+    // Externally visible ifuncs are needed.
+    if (!GIF.isDiscardableIfUnused())
+      GlobalIsNeeded(&GIF);
+  }
+
   // Now that all globals which are needed are in the AliveGlobals set, we loop
   // through the program, deleting those which are not alive.
   //
@@ -152,6 +160,14 @@ PreservedAnalyses GlobalDCEPass::run(Mod
       GA.setAliasee(nullptr);
     }
 
+  // The third pass drops targets of ifuncs which are dead...
+  std::vector<GlobalIFunc*> DeadIFuncs;
+  for (GlobalIFunc &GIF : M.ifuncs())
+    if (!AliveGlobals.count(&GIF)) {
+      DeadIFuncs.push_back(&GIF);
+      GIF.setResolver(nullptr);
+    }
+
   if (!DeadFunctions.empty()) {
     // Now that all interferences have been dropped, delete the actual objects
     // themselves.
@@ -182,6 +198,16 @@ PreservedAnalyses GlobalDCEPass::run(Mod
     Changed = true;
   }
 
+  // Now delete any dead aliases.
+  if (!DeadIFuncs.empty()) {
+    for (GlobalIFunc *GIF : DeadIFuncs) {
+      RemoveUnusedGlobalValue(*GIF);
+      M.getIFuncList().erase(GIF);
+    }
+    NumIFuncs += DeadIFuncs.size();
+    Changed = true;
+  }
+
   // Make sure that all memory is released
   AliveGlobals.clear();
   SeenConstants.clear();

Modified: llvm/trunk/lib/Transforms/Utils/SplitModule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SplitModule.cpp?rev=268468&r1=268467&r2=268468&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SplitModule.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SplitModule.cpp Tue May  3 19:20:48 2016
@@ -47,7 +47,7 @@ static void addNonConstUser(ClusterMapTy
   if (const Instruction *I = dyn_cast<Instruction>(U)) {
     const GlobalValue *F = I->getParent()->getParent();
     GVtoClusterMap.unionSets(GV, F);
-  } else if (isa<GlobalAlias>(U) || isa<Function>(U) ||
+  } else if (isa<GlobalIndirectSymbol>(U) || isa<Function>(U) ||
              isa<GlobalVariable>(U)) {
     GVtoClusterMap.unionSets(GV, cast<GlobalValue>(U));
   } else {
@@ -107,8 +107,8 @@ static void findPartitions(Module *M, Cl
 
     // For aliases we should not separate them from their aliasees regardless
     // of linkage.
-    if (GlobalAlias *GA = dyn_cast<GlobalAlias>(&GV)) {
-      if (const GlobalObject *Base = GA->getBaseObject())
+    if (auto *GIS = dyn_cast<GlobalIndirectSymbol>(&GV)) {
+      if (const GlobalObject *Base = GIS->getBaseObject())
         GVtoClusterMap.unionSets(&GV, Base);
     }
 
@@ -205,8 +205,8 @@ static void externalize(GlobalValue *GV)
 
 // Returns whether GV should be in partition (0-based) I of N.
 static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) {
-  if (auto GA = dyn_cast<GlobalAlias>(GV))
-    if (const GlobalObject *Base = GA->getBaseObject())
+  if (auto *GIS = dyn_cast<GlobalIndirectSymbol>(GV))
+    if (const GlobalObject *Base = GIS->getBaseObject())
       GV = Base;
 
   StringRef Name;
@@ -236,6 +236,8 @@ void llvm::SplitModule(
       externalize(&GV);
     for (GlobalAlias &GA : M->aliases())
       externalize(&GA);
+    for (GlobalIFunc &GIF : M->ifuncs())
+      externalize(&GIF);
   }
 
   // This performs splitting without a need for externalization, which might not

Added: llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll?rev=268468&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll Tue May  3 19:20:48 2016
@@ -0,0 +1,13 @@
+; RUN: opt -S -globaldce < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at if = ifunc void (), void ()* @fn
+
+define internal void @fn() {
+entry:
+  ret void
+}
+
+; CHECK-DAG: @if = ifunc void (), void ()* @fn
+; CHECK-DAG: define internal void @fn(

Modified: llvm/trunk/tools/bugpoint/CrashDebugger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/bugpoint/CrashDebugger.cpp?rev=268468&r1=268467&r2=268468&view=diff
==============================================================================
--- llvm/trunk/tools/bugpoint/CrashDebugger.cpp (original)
+++ llvm/trunk/tools/bugpoint/CrashDebugger.cpp Tue May  3 19:20:48 2016
@@ -264,8 +264,8 @@ bool ReduceCrashingFunctions::TestFuncs(
     std::vector<GlobalValue*> ToRemove;
     // First, remove aliases to functions we're about to purge.
     for (GlobalAlias &Alias : M->aliases()) {
-      Constant *Root = Alias.getAliasee()->stripPointerCasts();
-      Function *F = dyn_cast<Function>(Root);
+      GlobalObject *Root = Alias.getBaseObject();
+      Function *F = dyn_cast_or_null<Function>(Root);
       if (F) {
         if (Functions.count(F))
           // We're keeping this function.

Modified: llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp?rev=268468&r1=268467&r2=268468&view=diff
==============================================================================
--- llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp (original)
+++ llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp Tue May  3 19:20:48 2016
@@ -191,6 +191,8 @@ ValueMapping::ValueMapping(const Module
     map(&G);
   for (const GlobalAlias &A : M.aliases())
     map(&A);
+  for (const GlobalIFunc &IF : M.ifuncs())
+    map(&IF);
   for (const Function &F : M)
     map(&F);
 
@@ -200,6 +202,8 @@ ValueMapping::ValueMapping(const Module
       map(G.getInitializer());
   for (const GlobalAlias &A : M.aliases())
     map(A.getAliasee());
+  for (const GlobalIFunc &IF : M.ifuncs())
+    map(IF.getResolver());
   for (const Function &F : M) {
     if (F.hasPrefixData())
       map(F.getPrefixData());
@@ -463,6 +467,8 @@ static void changeUseLists(Module &M, Ch
     changeValueUseList(&G);
   for (GlobalAlias &A : M.aliases())
     changeValueUseList(&A);
+  for (GlobalIFunc &IF : M.ifuncs())
+    changeValueUseList(&IF);
   for (Function &F : M)
     changeValueUseList(&F);
 
@@ -472,6 +478,8 @@ static void changeUseLists(Module &M, Ch
       changeValueUseList(G.getInitializer());
   for (GlobalAlias &A : M.aliases())
     changeValueUseList(A.getAliasee());
+  for (GlobalIFunc &IF : M.ifuncs())
+    changeValueUseList(IF.getResolver());
   for (Function &F : M) {
     if (F.hasPrefixData())
       changeValueUseList(F.getPrefixData());




More information about the llvm-commits mailing list