[llvm-commits] [llvm] r124182 - in /llvm/trunk: lib/Transforms/IPO/MergeFunctions.cpp test/Transforms/MergeFunc/fold-weak.ll

Nick Lewycky nicholas at mxc.ca
Tue Jan 25 00:56:50 PST 2011


Author: nicholas
Date: Tue Jan 25 02:56:50 2011
New Revision: 124182

URL: http://llvm.org/viewvc/llvm-project?rev=124182&view=rev
Log:
Teach mergefunc how to emit aliases safely again -- but keep it turned it off
for now. It's controlled by the HasGlobalAliases variable which is not attached
to any flag yet.

Modified:
    llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
    llvm/trunk/test/Transforms/MergeFunc/fold-weak.ll

Modified: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp?rev=124182&r1=124181&r2=124182&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp Tue Jan 25 02:56:50 2011
@@ -68,6 +68,7 @@
 
 STATISTIC(NumFunctionsMerged, "Number of functions merged");
 STATISTIC(NumThunksWritten, "Number of thunks generated");
+STATISTIC(NumAliasesWritten, "Number of aliases generated");
 STATISTIC(NumDoubleWeak, "Number of new functions created");
 
 /// ProfileFunction - Creates a hash-code for the function which is the same
@@ -164,7 +165,8 @@
 class MergeFunctions : public ModulePass {
 public:
   static char ID;
-  MergeFunctions() : ModulePass(ID) {
+  MergeFunctions()
+    : ModulePass(ID), HasGlobalAliases(false) {
     initializeMergeFunctionsPass(*PassRegistry::getPassRegistry());
   }
 
@@ -189,21 +191,34 @@
   /// queue the functions.
   void RemoveUsers(Value *V);
 
+  /// Replace all direct calls of Old with calls of New. Will bitcast New if
+  /// necessary to make types match.
+  void replaceDirectCallers(Function *Old, Function *New);
+
   /// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G
   /// may be deleted, or may be converted into a thunk. In either case, it
   /// should never be visited again.
   void MergeTwoFunctions(Function *F, Function *G);
 
+  /// WriteThunkOrAlias - Replace G with a thunk or an alias to F. Deletes G.
+  void WriteThunkOrAlias(Function *F, Function *G);
+
   /// WriteThunk - Replace G with a simple tail call to bitcast(F). Also
   /// replace direct uses of G with bitcast(F). Deletes G.
   void WriteThunk(Function *F, Function *G);
 
+  /// WriteAlias - Replace G with an alias to F. Deletes G.
+  void WriteAlias(Function *F, Function *G);
+
   /// The set of all distinct functions. Use the Insert and Remove methods to
   /// modify it.
   FnSetType FnSet;
 
   /// TargetData for more accurate GEP comparisons. May be NULL.
   TargetData *TD;
+
+  /// Whether or not the target supports global aliases.
+  bool HasGlobalAliases;
 };
 
 }  // end anonymous namespace
@@ -587,22 +602,39 @@
   return true;
 }
 
+/// Replace direct callers of Old with New.
+void MergeFunctions::replaceDirectCallers(Function *Old, Function *New) {
+  Constant *BitcastNew = ConstantExpr::getBitCast(New, Old->getType());
+  for (Value::use_iterator UI = Old->use_begin(), UE = Old->use_end();
+       UI != UE;) {
+    Value::use_iterator TheIter = UI;
+    ++UI;
+    CallSite CS(*TheIter);
+    if (CS && CS.isCallee(TheIter)) {
+      Remove(CS.getInstruction()->getParent()->getParent());
+      TheIter.getUse().set(BitcastNew);
+    }
+  }
+}
+
+void MergeFunctions::WriteThunkOrAlias(Function *F, Function *G) {
+  if (HasGlobalAliases && G->hasUnnamedAddr()) {
+    if (G->hasExternalLinkage() || G->hasLocalLinkage() ||
+        G->hasWeakLinkage()) {
+      WriteAlias(F, G);
+      return;
+    }
+  }
+
+  WriteThunk(F, G);
+}
+
 /// WriteThunk - Replace G with a simple tail call to bitcast(F). Also replace
 /// direct uses of G with bitcast(F). Deletes G.
 void MergeFunctions::WriteThunk(Function *F, Function *G) {
   if (!G->mayBeOverridden()) {
     // Redirect direct callers of G to F.
-    Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType());
-    for (Value::use_iterator UI = G->use_begin(), UE = G->use_end();
-         UI != UE;) {
-      Value::use_iterator TheIter = UI;
-      ++UI;
-      CallSite CS(*TheIter);
-      if (CS && CS.isCallee(TheIter)) {
-        Remove(CS.getInstruction()->getParent()->getParent());
-        TheIter.getUse().set(BitcastF);
-      }
-    }
+    replaceDirectCallers(G, F);
   }
 
   // If G was internal then we may have replaced all uses of G with F. If so,
@@ -645,31 +677,53 @@
   ++NumThunksWritten;
 }
 
+/// WriteAlias - Replace G with an alias to F and delete G.
+void MergeFunctions::WriteAlias(Function *F, Function *G) {
+  Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType());
+  GlobalAlias *GA = new GlobalAlias(G->getType(), G->getLinkage(), "",
+                                    BitcastF, G->getParent());
+  F->setAlignment(std::max(F->getAlignment(), G->getAlignment()));
+  GA->takeName(G);
+  GA->setVisibility(G->getVisibility());
+  RemoveUsers(G);
+  G->replaceAllUsesWith(GA);
+  G->eraseFromParent();
+
+  DEBUG(dbgs() << "WriteAlias: " << GA->getName() << '\n');
+  ++NumAliasesWritten;
+}
+
 /// MergeTwoFunctions - Merge two equivalent functions. Upon completion,
 /// Function G is deleted.
 void MergeFunctions::MergeTwoFunctions(Function *F, Function *G) {
   if (F->mayBeOverridden()) {
     assert(G->mayBeOverridden());
 
-    // Make them both thunks to the same internal function.
-    Function *H = Function::Create(F->getFunctionType(), F->getLinkage(), "",
-                                   F->getParent());
-    H->copyAttributesFrom(F);
-    H->takeName(F);
-    RemoveUsers(F);
-    F->replaceAllUsesWith(H);
+    if (HasGlobalAliases) {
+      // Make them both thunks to the same internal function.
+      Function *H = Function::Create(F->getFunctionType(), F->getLinkage(), "",
+                                     F->getParent());
+      H->copyAttributesFrom(F);
+      H->takeName(F);
+      RemoveUsers(F);
+      F->replaceAllUsesWith(H);
 
-    unsigned MaxAlignment = std::max(G->getAlignment(), H->getAlignment());
+      unsigned MaxAlignment = std::max(G->getAlignment(), H->getAlignment());
 
-    WriteThunk(F, G);
-    WriteThunk(F, H);
+      WriteAlias(F, G);
+      WriteAlias(F, H);
 
-    F->setAlignment(MaxAlignment);
-    F->setLinkage(GlobalValue::PrivateLinkage);
+      F->setAlignment(MaxAlignment);
+      F->setLinkage(GlobalValue::PrivateLinkage);
+    } else {
+      // We can't merge them. Instead, pick one and update all direct callers
+      // to call it and hope that we improve the instruction cache hit rate.
+      replaceDirectCallers(G, F);
+    }
 
     ++NumDoubleWeak;
   } else {
-    WriteThunk(F, G);
+    WriteThunkOrAlias(F, G);
   }
 
   ++NumFunctionsMerged;

Modified: llvm/trunk/test/Transforms/MergeFunc/fold-weak.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/MergeFunc/fold-weak.ll?rev=124182&r1=124181&r2=124182&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/MergeFunc/fold-weak.ll (original)
+++ llvm/trunk/test/Transforms/MergeFunc/fold-weak.ll Tue Jan 25 02:56:50 2011
@@ -1,6 +1,10 @@
 ; RUN: opt < %s -mergefunc -S > %t
 ; RUN: grep {define weak} %t | count 2
 ; RUN: grep {call} %t | count 2
+; XFAIL: *
+
+; This test is off for a bit as we change this particular sort of folding to
+; only apply on ELF systems and not Mach-O systems.
 
 define weak i32 @sum(i32 %x, i32 %y) {
   %sum = add i32 %x, %y





More information about the llvm-commits mailing list