From 000c2facbf58328e63418551489ce707c851a1a7 Mon Sep 17 00:00:00 2001
From: Prakalp Srivastava <psrivas2@illinois.edu>
Date: Wed, 14 Jun 2017 17:42:09 -0500
Subject: [PATCH] All passes working for now for sgemm visc version

---
 llvm/include/llvm/SupportVISC/VISCTimer.h     |   8 -
 .../DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp         | 133 ++++++------
 .../Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp  |  10 +-
 llvm/lib/Transforms/GenVISC/GenVISC.cpp       | 201 ++----------------
 llvm/projects/visc-rt/makefile                |   2 +-
 llvm/projects/visc-rt/visc-rt.h               |   1 -
 llvm/test/VISC/parboil/common/mk/visc.mk      |   4 +-
 7 files changed, 102 insertions(+), 257 deletions(-)

diff --git a/llvm/include/llvm/SupportVISC/VISCTimer.h b/llvm/include/llvm/SupportVISC/VISCTimer.h
index 826de6723e..4dbadbd34f 100644
--- a/llvm/include/llvm/SupportVISC/VISCTimer.h
+++ b/llvm/include/llvm/SupportVISC/VISCTimer.h
@@ -10,14 +10,6 @@
 #ifndef VISC_TIMER_HEADER
 #define VISC_TIMER_HEADER
 
-#include "llvm/Support/CommandLine.h"
-
-using namespace llvm;
-
-// VISC Command line option to use timer or not
-// static cl::opt<bool>
-// VISCTimer("visc-timers", cl::desc("Enable visc timers"));
-
 /************************** Timer Routines ***************************/
 extern "C" {
 
diff --git a/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp b/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp
index 7aeebaef5f..b9645c14af 100644
--- a/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp
+++ b/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp
@@ -31,12 +31,20 @@
 #include "llvm-c/Core.h"
 #include "llvm/SupportVISC/VISCTimer.h"
 #include "llvm/SupportVISC/DFG2LLVM.h"
+#include "llvm/SupportVISC/VISCUtils.h"
+
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/IR/UseListOrder.h"
+
 
 #include <sstream>
 
 using namespace llvm;
 using namespace builddfg;
 using namespace dfg2llvm;
+using namespace viscUtils;
 
 // VISC Command line option to use timer or not
 static cl::opt<bool>
@@ -177,10 +185,9 @@ private:
   std::string getKernelsModuleName(Module &M);
   void fixValueAddrspace(Value* V, unsigned addrspace);
   std::vector<unsigned> globalToConstantMemoryOpt(std::vector<unsigned>*, Function*);
-  void changeArgAddrspace(Function* F, unsigned i);
-  void changeArgAddrspace(Function* F, std::vector<unsigned> &Ags, unsigned i);
+  Function* changeArgAddrspace(Function* F, std::vector<unsigned> &Ags, unsigned i);
   void addCLMetadata(Function* F);
-  void transformFunctionToVoid(Function* F);
+  Function* transformFunctionToVoid(Function* F);
   void insertRuntimeCalls(DFInternalNode* N, Kernel* K, const Twine& FileName);
 
   // Virtual Functions
@@ -920,7 +927,10 @@ void CGT_NVPTX::codeGen(DFLeafNode* N) {
   // (1) Parent is the top level node i.e., Root of DFG
   //                    OR
   // (2) Parent does not have multiple instances
+  errs() << "pLevel = " << pLevel << "\n";
+  errs() << "pReplFactor = " << pReplFactor << "\n";
   if (!pLevel || !pReplFactor) {
+    errs() << "*************** Kernel Gen: 1-Level Hierarchy **************\n";
     KernelLaunchNode = PNode;
     kernel = new Kernel(NULL,
                         N,
@@ -932,7 +942,7 @@ void CGT_NVPTX::codeGen(DFLeafNode* N) {
   }
   else {
     // Converting a 2-level DFG to opencl kernel
-    DEBUG(errs() << "*************** Kernel Gen: 2-Level Hierarchy **************\n");
+    errs() << "*************** Kernel Gen: 2-Level Hierarchy **************\n";
     KernelLaunchNode = PNode->getParent();
     assert((PNode->getNumOfDim() == N->getNumOfDim()) && "Dimension number must match");
     // Contains the instructions generating the kernel configuration parameters
@@ -958,33 +968,37 @@ void CGT_NVPTX::codeGen(DFLeafNode* N) {
   // get the cloned function pointer from DFNode. Otherwise, create the cloned
   // function and add it to the DFNode GenFunc.
   Function *F_nvptx = N->getGenFunc();
-  if(F_nvptx == NULL) {
-    // Clone the function
-    ValueToValueMapTy VMap;
 
-    F_nvptx = CloneFunction(F, VMap);
-    F_nvptx->removeFromParent();
+  assert(F_nvptx == NULL && "Error: Visiting a node for which code already generated");
+  // Clone the function
+  ValueToValueMapTy VMap;
 
+  Twine FName = F->getName();
+  F_nvptx = CloneFunction(F, VMap);
+  F_nvptx->setName(FName+"_nvptx");
+  errs() << "Old Function Name: " << F->getName() << "\n";
+  errs() << "New Function Name: " << F_nvptx->getName() << "\n";
 
+  F_nvptx->removeFromParent();
 
-    // Insert the cloned function into the kernels module
-    KernelM.getFunctionList().push_back(F_nvptx);
 
 
-    //TODO: Iterate over all the instructions of F_nvptx and identify the
-    //callees and clone them into this module.
-    DEBUG(errs() << *F_nvptx->getType());
-    DEBUG(errs() << *F_nvptx);
+  // Insert the cloned function into the kernels module
+  KernelM.getFunctionList().push_back(F_nvptx);
 
-    //Add generated function info to DFNode
-    N->setGenFunc(F_nvptx, visc::GPU_TARGET);
-  } else {
-    errs() << "WARNING: Visiting a node for which code already generated!\n";
-  }
+
+  //TODO: Iterate over all the instructions of F_nvptx and identify the
+  //callees and clone them into this module.
+  DEBUG(errs() << *F_nvptx->getType());
+  DEBUG(errs() << *F_nvptx);
 
   // Transform  the function to void and remove all target dependent attributes
   // from the function
-  transformFunctionToVoid(F_nvptx);
+  F_nvptx = transformFunctionToVoid(F_nvptx);
+  
+  //Add generated function info to DFNode
+  N->setGenFunc(F_nvptx, visc::GPU_TARGET);
+
   DEBUG(errs() << "Removing all attributes from Kernel Function and adding nounwind\n");
   F_nvptx->removeAttributes(AttributeSet::FunctionIndex, F_nvptx->getAttributes().getFnAttributes());
   F_nvptx->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
@@ -1077,9 +1091,9 @@ void CGT_NVPTX::codeGen(DFLeafNode* N) {
   // constant memory, subject to size of course
   std::vector<unsigned> ConstantMemArgs = globalToConstantMemoryOpt(&GlobalMemArgs, F_nvptx);
 
-  changeArgAddrspace(F_nvptx, ConstantMemArgs, CONSTANT_ADDRSPACE);
-  changeArgAddrspace(F_nvptx, SharedMemArgs, SHARED_ADDRSPACE);
-  changeArgAddrspace(F_nvptx, GlobalMemArgs, GLOBAL_ADDRSPACE);
+  F_nvptx = changeArgAddrspace(F_nvptx, ConstantMemArgs, CONSTANT_ADDRSPACE);
+  F_nvptx = changeArgAddrspace(F_nvptx, SharedMemArgs, SHARED_ADDRSPACE);
+  F_nvptx = changeArgAddrspace(F_nvptx, GlobalMemArgs, GLOBAL_ADDRSPACE);
 
 
   // Go through all the instructions
@@ -1130,7 +1144,6 @@ void CGT_NVPTX::codeGen(DFLeafNode* N) {
         ArgDFNode = Leaf_HandleToDFNodeMap[ArgII];
         int numOfDim = ArgDFNode->getNumOfDim();
         DEBUG(errs() << "\t  Got node dimension : " << numOfDim << "\n");
-//            IntegerType* IntTy = Type::getInt32Ty(KernelM.getContext());
         IntegerType* IntTy = Type::getInt32Ty(KernelM.getContext());
         ConstantInt* numOfDimConstant = ConstantInt::getSigned(IntTy, (int64_t) numOfDim);
 
@@ -1534,25 +1547,7 @@ std::vector<unsigned> CGT_NVPTX::globalToConstantMemoryOpt(std::vector<unsigned>
   return ConstantMemArgs;
 }
 
-void CGT_NVPTX::changeArgAddrspace(Function* F, unsigned addrspace) {
-  std::vector<Type*> ArgTypes;
-  for(auto& arg: F->getArgumentList()) {
-    DEBUG(errs() << arg << "\n");
-    if(PointerType* argTy = dyn_cast<PointerType>(arg.getType())) {
-      if(argTy->getAddressSpace() == 0) {
-        fixValueAddrspace(&arg, addrspace);
-      }
-    }
-    ArgTypes.push_back(arg.getType());
-  }
-  FunctionType* FTy = FunctionType::get(F->getReturnType(), ArgTypes, false);
-  PointerType* PTy = FTy->getPointerTo(cast<PointerType>(F->getType())->getAddressSpace());
-
-  F->mutateType(PTy);
-  DEBUG(errs() << *F->getFunctionType() << "\n" <<*F << "\n");
-}
-
-void CGT_NVPTX::changeArgAddrspace(Function* F, std::vector<unsigned> &Args, unsigned addrspace) {
+Function* CGT_NVPTX::changeArgAddrspace(Function* F, std::vector<unsigned> &Args, unsigned addrspace) {
   unsigned idx = 0;
   std::vector<Type*> ArgTypes;
   for(auto& arg: F->getArgumentList()) {
@@ -1564,11 +1559,14 @@ void CGT_NVPTX::changeArgAddrspace(Function* F, std::vector<unsigned> &Args, uns
     }
     ArgTypes.push_back(arg.getType());
   }
-  FunctionType* FTy = FunctionType::get(F->getReturnType(), ArgTypes, false);
-  PointerType* PTy = FTy->getPointerTo(cast<PointerType>(F->getType())->getAddressSpace());
+  FunctionType* newFT = FunctionType::get(F->getReturnType(), ArgTypes, false);
+
+  //F->mutateType(PTy);
+  Function* newF = cloneFunction(F, newFT, false);
+  replaceNodeFunctionInIR(*F->getParent(), F, newF);
 
-  F->mutateType(PTy);
-  DEBUG(errs() << *F->getFunctionType() << "\n" <<*F << "\n");
+  DEBUG(errs() << *newF->getFunctionType() << "\n" <<*newF << "\n");
+  return newF;
 }
 
 /* Add metadata to module KernelM, for OpenCL kernels */
@@ -1599,20 +1597,28 @@ void CGT_NVPTX::addCLMetadata(Function *F) {
 
 void CGT_NVPTX::writeKernelsModule() {
 
-  char* ErrorMessage = NULL;
-  LLVMModuleRef KernelMRef = wrap(&KernelM);
+  // In addition to deleting all other functions, we also want to spiff it
+  // up a little bit.  Do this now.
+  legacy::PassManager Passes;
+
   errs() << "Writing to File --- ";
   errs() << getKernelsModuleName(M).c_str() << "\n";
-  LLVMPrintModuleToFile(KernelMRef,
-                        getKernelsModuleName(M).c_str(),
-                        &ErrorMessage);
-  if (ErrorMessage) {
-    LLVMDisposeMessage(ErrorMessage);
+  std::error_code EC;
+  tool_output_file Out(getKernelsModuleName(M).c_str(), EC, sys::fs::F_None);
+  if (EC) {
+    errs() << EC.message() << '\n';
   }
-  LLVMDisposeModule(KernelMRef);
+
+  Passes.add(
+      createPrintModulePass(Out.os()));
+
+  Passes.run(KernelM);
+
+  // Declare success.
+  Out.keep();
 }
 
-void CGT_NVPTX::transformFunctionToVoid(Function* F) {
+Function* CGT_NVPTX::transformFunctionToVoid(Function* F) {
 
   DEBUG(errs() << "Transforming function to void: " << F->getName() << "\n");
   // FIXME: Maybe do that using the Node?
@@ -1685,11 +1691,14 @@ void CGT_NVPTX::transformFunctionToVoid(Function* F) {
   // function type. We need to change the type of this function to reflect the
   // added arguments
   Type* VoidRetType = Type::getVoidTy(F->getContext());
-  FunctionType* FTy = FunctionType::get(VoidRetType, ArgTypes, F->isVarArg());
-  PointerType* PTy = PointerType::get(FTy, cast<PointerType>(F->getType())->getAddressSpace());
+  FunctionType* newFT = FunctionType::get(VoidRetType, ArgTypes, F->isVarArg());
 
   // Change the function type
-  F->mutateType(PTy);
+  //F->mutateType(PTy);
+  Function* newF = cloneFunction(F, newFT, false);
+  replaceNodeFunctionInIR(*F->getParent(), F, newF);
+  //F->eraseFromParent();
+  return newF;
 }
 
 /******************************************************************************
@@ -1917,8 +1926,8 @@ static std::string getFilenameFromModule(const Module& M) {
 // Changes the data layout of the Module to be compiled with NVPTX backend
 // TODO: Figure out when to call it, probably after duplicating the modules
 static void changeDataLayout(Module &M) {
-  std::string nvptx32_layoutStr = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64";
-  std::string nvptx64_layoutStr = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64";
+  std::string nvptx32_layoutStr = "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64";
+  std::string nvptx64_layoutStr = "e-i64:64-v16:16-v32:32-n16:32:64";
 
   if (TARGET_PTX == 32)
     M.setDataLayout(StringRef(nvptx32_layoutStr));
diff --git a/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp b/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp
index 88b464342c..6da326f701 100644
--- a/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp
+++ b/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp
@@ -163,7 +163,7 @@ void CGT_X86::initRuntimeAPI() {
   assert(LLVM_SRC_ROOT != NULL && "Define LLVM_SRC_ROOT environment variable!");
 
   Twine llvmSrcRoot = LLVM_SRC_ROOT;
-  Twine runtimeAPI = llvmSrcRoot+"/projects/visc-rt/visc-rt.ll";
+  Twine runtimeAPI = llvmSrcRoot+"/../build/projects/visc-rt/visc-rt.ll";
 
   runtimeModule = parseIRFile(runtimeAPI.str(), Err, M.getContext());
 
@@ -201,7 +201,7 @@ void CGT_X86::initRuntimeAPI() {
   Function* VI = M.getFunction("llvm.visc.init");
   assert(VI->getNumUses() == 1 && "__visc__init should only be used once");
   DEBUG(errs() << "Inserting x86 timer initialization\n");
-  Instruction* I = cast<Instruction>(*VI->use_begin());
+  Instruction* I = cast<Instruction>(*VI->user_begin());
   initializeTimerSet(I);
   switchToTimer(visc_TimerID_NONE, I);
 
@@ -210,7 +210,7 @@ void CGT_X86::initRuntimeAPI() {
   assert(VC->getNumUses() == 1 && "__visc__cleanup should only be used once");
 
   DEBUG(errs() << "Inserting x86 timer print\n");
-  I = cast<Instruction>(*VC->use_begin());
+  I = cast<Instruction>(*VC->user_begin());
   printTimerSet(I);
 
 }
@@ -220,8 +220,8 @@ void CGT_X86::initRuntimeAPI() {
 std::vector<IntrinsicInst*>* CGT_X86::getUseList(Value* GraphID) {
   std::vector<IntrinsicInst*>* UseList = new std::vector<IntrinsicInst*>();
   // It must have been loaded from memory somewhere
-  for(Value::use_iterator ui = GraphID->use_begin(),
-      ue = GraphID->use_end(); ui!=ue; ++ui) {
+  for(Value::user_iterator ui = GraphID->user_begin(),
+      ue = GraphID->user_end(); ui!=ue; ++ui) {
     if(IntrinsicInst* waitI = dyn_cast<IntrinsicInst>(*ui)) {
       UseList->push_back(waitI);
     }
diff --git a/llvm/lib/Transforms/GenVISC/GenVISC.cpp b/llvm/lib/Transforms/GenVISC/GenVISC.cpp
index 7a5d8646e5..3858684e10 100644
--- a/llvm/lib/Transforms/GenVISC/GenVISC.cpp
+++ b/llvm/lib/Transforms/GenVISC/GenVISC.cpp
@@ -23,10 +23,13 @@
 #include "llvm/Transforms/Utils/ValueMapper.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/SupportVISC/VISCUtils.h"
+
 
 #define TIMER(X) do { if (VISCTimer) { X; } } while (0)
 
 using namespace llvm;
+using namespace viscUtils;
 
 
 // VISC Command line option to use timer or not
@@ -39,7 +42,6 @@ namespace genvisc {
 
 static inline ConstantInt* getTimerID(Module&, enum visc_TimerID);
 static Function* transformReturnTypeToStruct(Function* F);
-static void replaceNodeFunctionInIR(Module &M, Function* F, Function* G);
 
 // Check if the dummy function call is a __visc__node call
 #define IS_VISC_CALL(callName) \
@@ -165,73 +167,7 @@ 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() << "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, ++new_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);
-    }
-  }
 
-  // Clone function
-  if (Returns == NULL)
-    Returns = new SmallVector<ReturnInst*, 8>();
-  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>
@@ -309,7 +245,7 @@ static Value* genCodeForReturn(CallInst* CI) {
 static void addHint(Function* F, visc::Target T) {
   // Get Module
   Module* M = F->getParent();
-  DEBUG(errs() << "Set preferred target for " << F->getName() << ": " << T << "\n");
+  DEBUG(errs() << "Set preferred target for " << F->getName() << ": ");
 
   //assert(isa<ConstantInt>(CI->getArgOperand(0))
   //&& "Argument to hint must be constant integer!");
@@ -319,12 +255,15 @@ static void addHint(Function* F, visc::Target T) {
   NamedMDNode* HintNode;
   switch (T) {
     case visc::GPU_TARGET:
+      DEBUG(errs() << "GPU Target\n");
       HintNode = M->getOrInsertNamedMetadata("visc_hint_gpu");
       break;
     case visc::SPIR_TARGET:
+      DEBUG(errs() << "SPIR Target\n");
       HintNode = M->getOrInsertNamedMetadata("visc_hint_spir");
       break;
     case visc::CPU_TARGET:
+      DEBUG(errs() << "CPU Target\n");
       HintNode = M->getOrInsertNamedMetadata("visc_hint_cpu");
       break;
     default:
@@ -1174,16 +1113,19 @@ bool GenVISC::runOnModule(Module &M) {
 
         TyList.insert(TyList.begin()+destpos, ChildReturnTy->getElementType(srcpos));
         StructType* NewReturnTy = StructType::create(Ctx, TyList, ReturnStructTy->getName(), true);
-          // Create the argument type list with added argument types
-          std::vector<Type*> ArgTypes;
-          for(Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
-                ai != ae; ++ai) {
-            ArgTypes.push_back(ai->getType());
-          }
- 
-          FunctionType* FTy = FunctionType::get(NewReturnTy, ArgTypes, F->isVarArg());
-          PointerType* PTy = FTy->getPointerTo();
-          F->mutateType(PTy);
+        // Create the argument type list with added argument types
+        std::vector<Type*> ArgTypes;
+        for(Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
+              ai != ae; ++ai) {
+          ArgTypes.push_back(ai->getType());
+        }
+
+        FunctionType* FTy = FunctionType::get(NewReturnTy, ArgTypes, F->isVarArg());
+        PointerType* PTy = FTy->getPointerTo();
+        F->mutateType(PTy);
+
+        errs() << "Function Type: " << *F->getType() << "\n";
+        errs() << "Function Type: " << *F->getFunctionType() << "\n";
         // This is certainly an internal node, and hence just one BB with one
         // return terminator instruction. Change return statement
         ReturnInst* RI = cast<ReturnInst>(F->getEntryBlock().getTerminator());
@@ -1232,7 +1174,9 @@ bool GenVISC::runOnModule(Module &M) {
           FunctionType* FTy = FunctionType::get(ReturnVal->getType(), ArgTypes, F->isVarArg());
           PointerType* PTy = FTy->getPointerTo();
           F->mutateType(PTy);
-          DEBUG(errs() << "\tNew Function Type: " << *F->getType() << "\n");
+          errs() << "\tNew Function Type: " << *F->getType() << "\n";
+          errs() << "\tNew Function Type: " << *F->getFunctionType() << "\n";
+          errs() << "\tNew Function Type: " << *F->getReturnType() << "\n";
         
         }
 
@@ -1615,106 +1559,7 @@ static Function* transformReturnTypeToStruct(Function* F) {
   return newF;
 }
 
-static bool isViscCreateNodeIntrinsic(Instruction* I) {
-  if(!isa<IntrinsicInst>(I))
-    return false;
-  IntrinsicInst* II = cast<IntrinsicInst>(I);
-  return (II->getCalledFunction()->getName()).startswith("llvm.visc.createNode");
-}
-
-// Creates a new createNode intrinsic, similar to II but with different
-// associated function F instead
-IntrinsicInst* createIdenticalCreateNodeWithDifferentFunction(Function* F,
-                                                            IntrinsicInst* II) {
-  Module* M = F->getParent();
-
-  // Find which createNode intrinsic we need to create
-  Function* CreateNodeF = Intrinsic::getDeclaration(M, II->getIntrinsicID());
-  Constant* Fp = ConstantExpr::getPointerCast(F,
-                                          Type::getInt8PtrTy(II->getContext()));
-
-  ArrayRef<Value*> CreateNodeArgs;
-  switch (II->getIntrinsicID()) {
-    case Intrinsic::visc_createNode:
-    {
-      CreateNodeArgs = ArrayRef<Value*>(Fp);
-      break;
-    }
-    case Intrinsic::visc_createNode1D:
-    {
-      Value* CreateNode1DArgs[] = {Fp, II->getArgOperand(1)};
-      CreateNodeArgs = ArrayRef<Value*>(CreateNode1DArgs, 2);
-      break;
-    }
-    case Intrinsic::visc_createNode2D:
-    {
-      Value* CreateNode2DArgs[] = {Fp, II->getArgOperand(1),
-                                       II->getArgOperand(2)};
-      CreateNodeArgs = ArrayRef<Value*>(CreateNode2DArgs, 3);
-      break;
-    }
-    case Intrinsic::visc_createNode3D:
-    {
-      Value* CreateNode3DArgs[] = {Fp, II->getArgOperand(1),
-                                       II->getArgOperand(2),
-                                       II->getArgOperand(3)};
-      CreateNodeArgs = ArrayRef<Value*>(CreateNode3DArgs, 4);
-      break;
-    }
-    default :
-      assert(false && "Unknown createNode intrinsic");
-      break;
-  }
-
-  CallInst* CI = CallInst::Create(CreateNodeF,
-                                  CreateNodeArgs,
-                                  F->getName()+".node");
-  IntrinsicInst* CreateNodeII = cast<IntrinsicInst>(CI);
-  return CreateNodeII;
-}
-
-// Assuming that the changed function is a node function, it is only used as a
-// first operand of createNode*. It is enough to iterate through all createNode*
-// calls in the program.
-static void replaceNodeFunctionInIR(Module &M, Function* F, Function* G) {
-
-  for (Module::iterator mi = M.begin(), me = M.end(); mi != me; ++mi) {
-    Function* f = &*mi;
-    DEBUG(errs() << "Function: " << f->getName() << "\n");
-
-    std::vector<Instruction*> toBeErased;
 
-    for (inst_iterator i = inst_begin(f), e = inst_end(f); i != e ; ++i) {
-      Instruction* I = &*i; // Grab pointer to Instruction
-
-      if (isViscCreateNodeIntrinsic(I)) {
-        IntrinsicInst* II = cast<IntrinsicInst>(I);
-        // The found createNode is not associated with the changed function
-        if (II->getArgOperand(0) != F)
-          continue; // skip it
-
-        // Otherwise, create a new createNode similar to the other one,
-        // but with the changed function as first operand.
-        IntrinsicInst* CreateNodeII =
-          createIdenticalCreateNodeWithDifferentFunction(G, II);
-        II->replaceAllUsesWith(CreateNodeII);
-        toBeErased.push_back(II);
-      }
-    }
-
-    for(auto I: toBeErased) {
-      DEBUG(errs() << "\tErasing " << *I << "\n");
-      I->eraseFromParent();
-    }
-  }
-
-  DEBUG(errs() << "DONE: Replacing function " << F->getName() << " with " << G->getName() << "\n");
-
-  // Remove replaced function from the module
-  F->replaceAllUsesWith(UndefValue::get(F->getType()));
-  F->eraseFromParent();
-
-}
 
 char genvisc::GenVISC::ID = 0;
 static RegisterPass<genvisc::GenVISC> X("genvisc", "Pass to generate VISC IR from LLVM IR (with dummy function calls)", false, false);
diff --git a/llvm/projects/visc-rt/makefile b/llvm/projects/visc-rt/makefile
index 1e4a2f285c..b621292c3b 100644
--- a/llvm/projects/visc-rt/makefile
+++ b/llvm/projects/visc-rt/makefile
@@ -1,4 +1,4 @@
-LLVM_SRC_ROOT = ../../..
+LLVM_SRC_ROOT = ../../../llvm
 LLVM_BUILD_ROOT = ../..
 
 OPENCL_INC_PATH = /opt/intel/opencl-sdk/include
diff --git a/llvm/projects/visc-rt/visc-rt.h b/llvm/projects/visc-rt/visc-rt.h
index a5fd214194..00e270d002 100644
--- a/llvm/projects/visc-rt/visc-rt.h
+++ b/llvm/projects/visc-rt/visc-rt.h
@@ -13,7 +13,6 @@
 #include <string>
 //#include <condition_variable>
 
-#include "llvm/Support/CommandLine.h"
 #include "llvm/SupportVISC/VISCHint.h"
 #include "llvm/SupportVISC/VISCTimer.h"
 
diff --git a/llvm/test/VISC/parboil/common/mk/visc.mk b/llvm/test/VISC/parboil/common/mk/visc.mk
index f2e6dfb33b..e3b541378d 100755
--- a/llvm/test/VISC/parboil/common/mk/visc.mk
+++ b/llvm/test/VISC/parboil/common/mk/visc.mk
@@ -10,8 +10,8 @@ CXXFLAGS=$(LANG_CXXFLAGS) $(PLATFORM_CXXFLAGS) $(APP_CXXFLAGS)
 LDFLAGS=$(LANG_LDFLAGS) $(PLATFORM_LDFLAGS) $(APP_LDFLAGS)
 
 # VISC
-LIBCLC_LIB_PATH = $(LLVM_SRC_ROOT)/../libclc/built_libs
-VISC_RT_PATH = $(LLVM_SRC_ROOT)/projects/visc-rt
+LIBCLC_LIB_PATH = $(LLVM_SRC_ROOT)/../../libclc-install/lib/clc
+VISC_RT_PATH = $(LLVM_SRC_ROOT)/../build/projects/visc-rt
 
 VISC_RT_LIB = $(VISC_RT_PATH)/visc-rt.ll
 LIBCLC_NVPTX_LIB = $(LIBCLC_LIB_PATH)/nvptx--nvidiacl.bc
-- 
GitLab