Shrink libllvmgcc.dylib by another 23K
[oota-llvm.git] / lib / Transforms / Scalar / LowerGC.cpp
index ce67d0e7a177395244b3279ca01c5003b87cb57d..40f6bc3c4aefe6943db9916b801f228e075fe336 100644 (file)
 #include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #include "llvm/Pass.h"
-#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Support/Visibility.h"
 using namespace llvm;
 
 namespace {
-  class LowerGC : public FunctionPass {
+  class VISIBILITY_HIDDEN LowerGC : public FunctionPass {
     /// GCRootInt, GCReadInt, GCWriteInt - The function prototypes for the
     /// llvm.gcread/llvm.gcwrite/llvm.gcroot intrinsics.
     Function *GCRootInt, *GCReadInt, *GCWriteInt;
@@ -47,7 +47,7 @@ namespace {
     /// had zero roots.
     const Type *MainRootRecordType;
   public:
-    LowerGC() : GCRootInt(0), GCReadInt(0), GCWriteInt(0), 
+    LowerGC() : GCRootInt(0), GCReadInt(0), GCWriteInt(0),
                 GCRead(0), GCWrite(0), RootChain(0), MainRootRecordType(0) {}
     virtual bool doInitialization(Module &M);
     virtual bool runOnFunction(Function &F);
@@ -109,10 +109,11 @@ bool LowerGC::doInitialization(Module &M) {
   // If the program is using read/write barriers, find the implementations of
   // them from the GC runtime library.
   if (GCReadInt)        // Make:  sbyte* %llvm_gc_read(sbyte**)
-    GCRead = M.getOrInsertFunction("llvm_gc_read", VoidPtr, VoidPtrPtr, 0);
+    GCRead = M.getOrInsertFunction("llvm_gc_read", VoidPtr, VoidPtr, VoidPtrPtr,
+                                   (Type *)0);
   if (GCWriteInt)       // Make:  void %llvm_gc_write(sbyte*, sbyte**)
     GCWrite = M.getOrInsertFunction("llvm_gc_write", Type::VoidTy,
-                                    VoidPtr, VoidPtrPtr, 0);
+                                    VoidPtr, VoidPtr, VoidPtrPtr, (Type *)0);
 
   // If the program has GC roots, get or create the global root list.
   if (GCRootInt) {
@@ -125,8 +126,9 @@ bool LowerGC::doInitialization(Module &M) {
     if (RootChain == 0) {
       // If the root chain does not exist, insert a new one with linkonce
       // linkage!
-      RootChain = new GlobalVariable(PRLTy, false, GlobalValue::LinkOnceLinkage,
-                                     Constant::getNullValue(RootListTy),
+      RootChain = new GlobalVariable(PRLTy, false,
+                                     GlobalValue::LinkOnceLinkage,
+                                     Constant::getNullValue(PRLTy),
                                      "llvm_gc_root_chain", &M);
     } else if (RootChain->hasExternalLinkage() && RootChain->isExternal()) {
       RootChain->setInitializer(Constant::getNullValue(PRLTy));
@@ -140,19 +142,18 @@ bool LowerGC::doInitialization(Module &M) {
 /// not have the specified type, insert a cast.
 static void Coerce(Instruction *I, unsigned OpNum, Type *Ty) {
   if (I->getOperand(OpNum)->getType() != Ty) {
-    Constant *C = dyn_cast<Constant>(I->getOperand(OpNum));
-    if (C && !isa<GlobalValue>(I->getOperand(OpNum)))
+    if (Constant *C = dyn_cast<Constant>(I->getOperand(OpNum)))
       I->setOperand(OpNum, ConstantExpr::getCast(C, Ty));
     else {
-      CastInst *C = new CastInst(I->getOperand(OpNum), Ty, "", I);
-      I->setOperand(OpNum, C);
+      CastInst *CI = new CastInst(I->getOperand(OpNum), Ty, "", I);
+      I->setOperand(OpNum, CI);
     }
   }
 }
 
 /// runOnFunction - If the program is using GC intrinsics, replace any
 /// read/write intrinsics with the appropriate read/write barrier calls, then
-/// inline them.  Finally, build the data structures for 
+/// inline them.  Finally, build the data structures for
 bool LowerGC::runOnFunction(Function &F) {
   // Quick exit for programs that are not using GC mechanisms.
   if (!GCRootInt && !GCReadInt && !GCWriteInt) return false;
@@ -183,14 +184,17 @@ bool LowerGC::runOnFunction(Function &F) {
               CI->setOperand(0, GCWrite);
               // Insert casts of the operands as needed.
               Coerce(CI, 1, VoidPtr);
-              Coerce(CI, 2, VoidPtrPtr);
+              Coerce(CI, 2, VoidPtr);
+              Coerce(CI, 3, VoidPtrPtr);
             } else {
-              Coerce(CI, 1, VoidPtrPtr);
+              Coerce(CI, 1, VoidPtr);
+              Coerce(CI, 2, VoidPtrPtr);
               if (CI->getType() == VoidPtr) {
                 CI->setOperand(0, GCRead);
               } else {
                 // Create a whole new call to replace the old one.
                 CallInst *NC = new CallInst(GCRead, CI->getOperand(1),
+                                            CI->getOperand(2),
                                             CI->getName(), CI);
                 Value *NV = new CastInst(NC, CI->getType(), "", CI);
                 CI->replaceAllUsesWith(NV);
@@ -199,13 +203,10 @@ bool LowerGC::runOnFunction(Function &F) {
               }
             }
 
-            // Now that we made the replacement, inline expand the call if
-            // possible, otherwise things will be too horribly expensive.
-            InlineFunction(CI);
             MadeChange = true;
           }
       }
-  
+
   // If there are no GC roots in this function, then there is no need to create
   // a GC list record for it.
   if (GCRoots.empty()) return MadeChange;
@@ -260,7 +261,7 @@ bool LowerGC::runOnFunction(Function &F) {
     Par[3] = Zero;
     Value *RootPtrPtr = new GetElementPtrInst(AI, Par, "RootEntPtr", IP);
     new StoreInst(Null, RootPtrPtr, IP);
-    
+
     // Each occurrance of the llvm.gcroot intrinsic now turns into an
     // initialization of the slot with the address and a zeroing out of the
     // address specified.
@@ -298,7 +299,7 @@ bool LowerGC::runOnFunction(Function &F) {
     UnwindInst *UI = new UnwindInst(Cleanup);
     PrevPtr = new LoadInst(PrevPtrPtr, "prevptr", UI);
     new StoreInst(PrevPtr, RootChain, UI);
-  
+
     // Loop over all of the function calls, turning them into invokes.
     while (!NormalCalls.empty()) {
       CallInst *CI = NormalCalls.back();
@@ -311,7 +312,7 @@ bool LowerGC::runOnFunction(Function &F) {
       // Remove the unconditional branch inserted at the end of the CBB.
       CBB->getInstList().pop_back();
       NewBB->getInstList().remove(CI);
-      
+
       // Create a new invoke instruction.
       Value *II = new InvokeInst(CI->getCalledValue(), NewBB, Cleanup,
                                  std::vector<Value*>(CI->op_begin()+1,