diff --git a/llvm/lib/Transforms/GenVISC/GenVISC.cpp b/llvm/lib/Transforms/GenVISC/GenVISC.cpp
index 34d66354e574a5dae05132f6bbb8edbf176b4bb8..37e7f2e9a389ac6be095b1c4e7bddf4c19eabece 100644
--- a/llvm/lib/Transforms/GenVISC/GenVISC.cpp
+++ b/llvm/lib/Transforms/GenVISC/GenVISC.cpp
@@ -20,6 +20,9 @@
 #include "llvm/SupportVISC/VISCHint.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 
 #define TIMER(X) do { if (VISCTimer) { X; } } while (0)
 
@@ -161,6 +164,76 @@ static unsigned getNumericValue(Value* V) {
   return cast<ConstantInt>(V)->getZExtValue();
 }
 
+// Create new function F' as a copy of old function F with a new signature.
+// The following two most used cases are handled by this function.
+// 1. When some extra arguments need to be added to this function
+//    - Here we can map the old function arguments to
+//      new ones
+// 2. When each pointer argument needs an additional size argument
+//    - Here, in the absence of VMap, we map the arguments in order, skipping
+//      over extra pointer arguments.
+// The function returns the list of return instructions to the caller to fix in
+// case the return type is also changed.
+static Function* cloneFunction(Function* F, FunctionType* newFT, bool
+    isAddingPtrSizeArg, SmallVectorImpl<ReturnInst*> &Returns = NULL) {
+
+  errs() << "Cloning Function: " << F->getName() << "\n";
+  errs() << "Old Function Type: " << *F->getFunctionType() << "\n";
+  errs() << "New Function Type: " << *newFT << "\n";
+
+  assert(F->getFunctionType()->getNumParams() <= newFT->getNumParams()
+      && "This function assumes that the new function has more arguments than the old function!");
+
+  // Create Function of specified type
+  Function* newF = Function::Create(newFT, F->getLinkage(), F->getName()+"_cloned", F->getParent());
+  ValueToValueMapTy VMap;
+  errs() << "No value map provided. Creating default value map\n";
+  errs() << "Old Function Type: " << *F->getType() << "\n";
+  errs() << "New Function Type: " << *newF->getType() << "\n";
+  if(isAddingPtrSizeArg) {
+    errs() << "Case 1: Pointer arg followed by a i64 size argument in new function\n";
+    Function::arg_iterator new_ai = newF->arg_begin();
+    for(Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end();
+        ai != ae; ++ai) {
+      errs() << ai->getArgNo() << ". " << *ai << " : " << *new_ai << "\n";
+      assert(ai->getType() == new_ai->getType() && "Arguments type do not match!");
+      VMap[&*ai] = &*new_ai;
+      new_ai->takeName(&*ai);
+      if(ai->getType()->isPointerTy()) {
+        std::string oldName = new_ai->getName();
+        // If the current argument is pointer type, the next argument in new
+        // function would be an i64 type containing the data size of this
+        // argument. Hence, skip the next arguement in new function.
+        ++new_ai;
+        new_ai->setName("bytes_"+oldName);
+      }
+      ++new_ai;
+    }
+  }
+  else {
+    errs() << "Case 2: Extra arguments are added at the end of old function\n";
+    Function::arg_iterator new_ai = newF->arg_begin();
+    for(Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end();
+        ai != ae; ++ai) {
+      assert(ai->getType() == new_ai->getType() && "Arguments type do not match!");
+      VMap[&*ai] = &*new_ai;
+      if(ai->getType()->isPointerTy()) {
+        // If the current argument is pointer type, the next argument in new
+        // function would be an i64 type containing the data size of this
+        // argument. Hence, skip the next arguement in new function.
+        ++new_ai;
+      }
+      ++new_ai;
+    }
+  }
+
+  // Clone function
+  CloneFunctionInto(newF, F, VMap, false, Returns);
+  errs() << *newF << "\n";
+
+  return newF;
+}
+
 // Add <numArgs> to the argument list of Function <F>. The names for these arguments
 // should be put in the string array <names>. Ideally the length of <names>
 // array should be numArgs. But, even when the length is not numArgs the
@@ -168,13 +241,6 @@ static unsigned getNumericValue(Value* V) {
 // intuitive.
 static void addArgs(Function* F, unsigned numArgs, std::string names[]) {
   if(numArgs == 0) return; // Return if not arguments are to be added.
-  // Add the extra arguments to the Function argument list
-  for (unsigned i = 0; i < numArgs; ++i) {
-    new Argument(Type::getInt32Ty(F->getContext()), names[i%names->size()], F);
-  }
-
-  // Now, we should change the type of the function F to reflect the added
-  // arguments.
 
   // Create the argument type list with added argument types
   std::vector<Type*> ArgTypes;
@@ -185,11 +251,22 @@ static void addArgs(Function* F, unsigned numArgs, std::string names[]) {
   // Adding new arguments to the function argument list, would not change the
   // function type. We need to change the type of this function to reflect the
   // added arguments
+  for(int i = 0; i < numArgs; ++i) {
+    ArgTypes.push_back(Type::getInt32Ty(F->getContext()));
+  }
   FunctionType* FTy = FunctionType::get(F->getReturnType(), ArgTypes, F->isVarArg());
-  PointerType* PTy = PointerType::get(FTy, cast<PointerType>(F->getType())->getAddressSpace());
 
   // Change the function type
-  F->mutateType(PTy);
+  Function* newF = cloneFunction(F, newFT, false);
+
+  // Add names to the extra arguments to the Function argument list
+  int numOldArgs = F->getFunctionType()->getNumParams();
+  for(Function::arg_iterator ai = newF->arg_begin(), ae = newF->arg_end();
+      ai != ae; ++ai) {
+    if (ai->getArgNo() < numOldArgs)
+      continue;
+    ai->setName(names[(ai->getArgNo() - numOldArgs) % names->size()]);
+  }
 }
 
 
@@ -1366,33 +1443,19 @@ void GenVISC::genKernel(Function* KernelF, CallInst* CI, StructType* RetTy) {
 
   // Change arguments and types
   // Create the argument type list with added argument types
-  Function::ArgumentListType& argList = KernelF->getArgumentList();
+  //Function::ArgumentListType& argList = KernelF->getArgumentList();
   std::vector<Type*> argTypes;
   // Insert an i32 argument after every pointer argument. However adding an
   // argument does not change the attribute list of function and so the
   // arguments need to be shifted accordingly.
-  bool shiftAttr = false;
+  //bool shiftAttr = false;
   for(Function::arg_iterator ai = KernelF->arg_begin(), ae = KernelF->arg_end();
       ai != ae; ++ai) {
 
     argTypes.push_back(ai->getType());
-    DEBUG(errs() << "Adding Arguments" << *ai << "\n");
-    if(shiftAttr) {
-      // If argument was added in the last iteration, shift the attributes to
-      // fix the mapping of arguments and attributes. Set the flag to false.
-      shiftAttr = false;
-      shiftAttributes(ai, 1, KernelF);
-    }
     if(ai->getType()->isPointerTy()) {
-      // If the current argument is a pointer argument, insert a i32 argument after
-      // it to denote the size of the pointer as required by visc
-      Argument* arg = new Argument(Type::getInt64Ty(KernelF->getContext()),
-                                   "bytes_"+ai->getName());
-      argList.insertAfter(ai, arg);
-      // Set shiftAttr flag to true to denote that the argument was added and
-      // the attributes need to be shifted in the next iteration for correct
-      // mapping of arguments and their attributes.
-      shiftAttr = true;
+      // If it is a pointer argument, add an i64 type next
+      argTypes.push_back(Type::getInt64Ty(KernelF->getContext()));
     }
 
   }
@@ -1403,7 +1466,7 @@ void GenVISC::genKernel(Function* KernelF, CallInst* CI, StructType* RetTy) {
   PointerType* PTy = PointerType::get(FTy, cast<PointerType>(KernelF->getType())->getAddressSpace());
 
   // Change the function type
-  KernelF->mutateType(PTy);
+  KernelF = cloneFunction(KernelF, FTy, true);
   DEBUG(errs() << *KernelF << "\n");
 
   // Replace ret void instruction with ret %RetTy undef
@@ -1540,7 +1603,7 @@ static inline ConstantInt* getTimerID(Module& M, enum visc_TimerID timer) {
   return ConstantInt::get(Type::getInt32Ty(M.getContext()), timer);
 }
 
-static void transformReturnTypeToStruct(Function* F) {
+static Function* transformReturnTypeToStruct(Function* F) {
   // Currently only works for void return types
   DEBUG(errs() << "Transforming return type of function to Struct: " << F->getName() << "\n");
   if(!F->getReturnType()->isVoidTy()) {
@@ -1556,11 +1619,11 @@ static void transformReturnTypeToStruct(Function* F) {
   
   StructType* RetTy = StructType::create(F->getContext(), None, "emptyStruct", true);
   FunctionType* FTy = FunctionType::get(RetTy, ArgTypes, F->isVarArg());
-  PointerType* PTy = FTy->getPointerTo();
-  F->mutateType(PTy);
+  
+  SmallVector<ReturnInst*, 8> Returns;
+  Function* newF = cloneFunction(F, FTy, false, Returns);
   // Replace ret void instruction with ret %RetTy undef
-  for(auto& BB: F->getBasicBlockList()) {
-    if(ReturnInst* RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
+  for(auto RI: Returns) {
       DEBUG(errs() << "Found return inst: "<< *RI << "\n");
       ReturnInst* newRI = ReturnInst::Create(F->getContext(), UndefValue::get(RetTy));
       ReplaceInstWithInst(RI, newRI);