* Codegen of GEPs dramatically improved by folding multiplies and adds
* Function pointers implemented correctly using appropriate stubs

Contributed by Nate Begeman.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15133 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PowerPC/PowerPCAsmPrinter.cpp b/lib/Target/PowerPC/PowerPCAsmPrinter.cpp
index d920137..feec9ed 100644
--- a/lib/Target/PowerPC/PowerPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PowerPCAsmPrinter.cpp
@@ -19,6 +19,7 @@
 #define DEBUG_TYPE "asmprinter"
 #include "PowerPC.h"
 #include "PowerPCInstrInfo.h"
+#include "PowerPCTargetMachine.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
@@ -47,7 +48,7 @@
     /// Target machine description which we query for reg. names, data
     /// layout, etc.
     ///
-    TargetMachine &TM;
+    PowerPCTargetMachine &TM;
 
     /// Name-mangler for global names.
     ///
@@ -55,8 +56,8 @@
     std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
     std::set<std::string> Strings;
 
-    Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm), labelNumber(0)
-      { }
+    Printer(std::ostream &o, TargetMachine &tm) : O(o), 
+      TM(reinterpret_cast<PowerPCTargetMachine&>(tm)), labelNumber(0) { }
 
     /// Cache of mangled name for current function. This is
     /// recalculated at the beginning of each call to
@@ -131,7 +132,7 @@
     } else if (isprint(C)) {
       O << C;
     } else {
-      switch(C) {
+      switch (C) {
       case '\b': O << "\\b"; break;
       case '\f': O << "\\f"; break;
       case '\n': O << "\\n"; break;
@@ -167,7 +168,7 @@
     O << Mang->getValueName(GV);
   else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
     const TargetData &TD = TM.getTargetData();
-    switch(CE->getOpcode()) {
+    switch (CE->getOpcode()) {
     case Instruction::GetElementPtr: {
       // generate a symbolic expression for the byte address
       const Constant *ptrVal = CE->getOperand(0);
@@ -450,20 +451,25 @@
     if (!elideOffsetKeyword) {
       GlobalValue *GV = MO.getGlobal();
       std::string Name = Mang->getValueName(GV);
+
       // Dynamically-resolved functions need a stub for the function
       Function *F = dyn_cast<Function>(GV);
-      if (F && F->isExternal()) {
+      if (F && F->isExternal() &&
+          TM.CalledFunctions.find(F) != TM.CalledFunctions.end()) {
         FnStubs.insert(Name);
         O << "L" << Name << "$stub";
-      } else {
-        GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
-        // External global variables need a non-lazily-resolved stub
-        if (GVar && GVar->isExternal()) {
-          GVStubs.insert(Name);
-          O << "L" << Name << "$non_lazy_ptr";
-        } else 
-          O << Mang->getValueName(GV);
+        return;
       }
+            
+      // External global variables need a non-lazily-resolved stub
+      if (GV->hasInternalLinkage() == false &&
+          TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
+        GVStubs.insert(Name);
+        O << "L" << Name << "$non_lazy_ptr";
+        return;
+      }
+            
+      O << Mang->getValueName(GV);
     }
     return;
     
@@ -613,10 +619,10 @@
           (I->hasInternalLinkage() || I->hasWeakLinkage())) {
         SwitchSection(O, CurSection, ".data");
         if (I->hasInternalLinkage())
-          O << "\t.lcomm " << name << "," << TD.getTypeSize(C->getType())
+          O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
             << "," << (unsigned)TD.getTypeAlignment(C->getType());
         else 
-          O << "\t.comm " << name << "," << TD.getTypeSize(C->getType());
+          O << ".comm " << name << "," << TD.getTypeSize(C->getType());
         O << "\t\t; ";
         WriteAsOperand(O, I, true, true, &M);
         O << "\n";
@@ -661,8 +667,7 @@
   if (LinkOnceStubs.begin() != LinkOnceStubs.end())
     O << ".data\n.align 2\n";
   for (std::set<std::string>::iterator i = LinkOnceStubs.begin(), 
-         e = LinkOnceStubs.end(); i != e; ++i)
-  {
+         e = LinkOnceStubs.end(); i != e; ++i) {
     O << *i << "$non_lazy_ptr:\n"
       << "\t.long\t" << *i << '\n';
   }
@@ -671,31 +676,32 @@
   for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 
        i != e; ++i)
   {
-    O << "\t.picsymbol_stub\n";
+    O << ".data\n";
+    O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
+    O << "\t.align 2\n";
     O << "L" << *i << "$stub:\n";
     O << "\t.indirect_symbol " << *i << "\n";
     O << "\tmflr r0\n";
-    O << "\tbl L0$" << *i << "\n";
+    O << "\tbcl 20,31,L0$" << *i << "\n";
     O << "L0$" << *i << ":\n";
     O << "\tmflr r11\n";
     O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
     O << "\tmtlr r0\n";
-    O << "\tlwz r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
+    O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
     O << "\tmtctr r12\n";
-    O << "\taddi r11,r11,lo16(L" << *i << "$lazy_ptr - L0$" << *i << ")\n";
     O << "\tbctr\n";
     O << ".data\n";
     O << ".lazy_symbol_pointer\n";
     O << "L" << *i << "$lazy_ptr:\n";
-    O << ".indirect_symbol " << *i << "\n";
-    O << ".long dyld_stub_binding_helper\n";
+    O << "\t.indirect_symbol " << *i << "\n";
+    O << "\t.long dyld_stub_binding_helper\n";
   }
 
   O << "\n";
 
   // Output stubs for external global variables
   if (GVStubs.begin() != GVStubs.end())
-    O << ".data\n\t.non_lazy_symbol_pointer\n";
+    O << ".data\n.non_lazy_symbol_pointer\n";
   for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 
        i != e; ++i) {
     O << "L" << *i << "$non_lazy_ptr:\n";