Ejemplo n.º 1
0
ValueToValueMapTy* MCJITHelper::generateIdentityMapping(Function* F) {
    ValueToValueMapTy* VMap = new ValueToValueMapTy();

    // arguments
    for (Function::arg_iterator argIt = F->arg_begin(), argEnd = F->arg_end(); argIt != argEnd; ++argIt) {
        (*VMap)[argIt] = argIt;
    }

    // TODO: metadata (also in the body?)

    for (Function::iterator bbIt = F->begin(), bbEnd = F->end(); bbIt != bbEnd; ++bbIt) {
        // basic blocks
        (*VMap)[bbIt] = bbIt;

        // TODO: BB.hasAddressTaken() ?

        for (BasicBlock::iterator insIt = bbIt->begin(), insEnd = bbIt->end(); insIt != insEnd; ++insIt) {
            // instructions
            (*VMap)[insIt] = insIt;

            /** Code adapted from MapValue() called by RemapInstruction() **/
            // operators
            for (User::op_iterator opIt = insIt->op_begin(), opEnd = insIt->op_end(); opIt != opEnd; ++opIt) {
                Value* v = *opIt;
                ValueToValueMapTy::iterator I = VMap->find(v);
                if (I != VMap->end() && I->second) continue; // value already exists in VMap
                (*VMap)[v] = v;
            }
        }
    }

    return VMap;
}
Ejemplo n.º 2
0
/// GlobalIsNeeded - the specific global value as needed, and
/// recursively mark anything that it uses as also needed.
void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
  // If the global is already in the set, no need to reprocess it.
  if (!AliveGlobals.insert(G))
    return;
  
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G)) {
    // If this is a global variable, we must make sure to add any global values
    // referenced by the initializer to the alive set.
    if (GV->hasInitializer())
      MarkUsedGlobalsAsNeeded(GV->getInitializer());
  } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
    // The target of a global alias is needed.
    MarkUsedGlobalsAsNeeded(GA->getAliasee());
  } else {
    // Otherwise this must be a function object.  We have to scan the body of
    // the function looking for constants and global values which are used as
    // operands.  Any operands of these types must be processed to ensure that
    // any globals used will be marked as needed.
    Function *F = cast<Function>(G);

    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
        for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
          if (GlobalValue *GV = dyn_cast<GlobalValue>(*U))
            GlobalIsNeeded(GV);
          else if (Constant *C = dyn_cast<Constant>(*U))
            MarkUsedGlobalsAsNeeded(C);
  }
}
Ejemplo n.º 3
0
void HeterotbbTransform::copy_function (Function* NF, Function* F) {
    DenseMap<const Value*, Value *> ValueMap;
    // Get the names of the parameters for old function
    for(Function::arg_iterator FI = F->arg_begin(), FE=F->arg_end(), DI=NF->arg_begin(); FE!=FI; ++FI,++DI) {
        DI->setName(FI->getName());
        ValueMap[FI]=DI;
    }

    for (Function::const_iterator BI=F->begin(),BE = F->end(); BI != BE; ++BI) {
        const BasicBlock &FBB = *BI;
        BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF);
        ValueMap[&FBB] = NFBB;
        if (FBB.hasName()) {
            NFBB->setName(FBB.getName());
            //DEBUG(dbgs()<<NFBB->getName()<<"\n");
        }
        for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) {
            Instruction *NFInst = II->clone(/*F->getContext()*/);
            if (II->hasName()) NFInst->setName(II->getName());
            const Instruction *FInst = &(*II);
            rewrite_instruction((Instruction *)FInst, NFInst, ValueMap);
            NFBB->getInstList().push_back(NFInst);
            ValueMap[II] = NFInst;
        }
    }
    // Remap the instructions again to take care of forward jumps
    for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) {
        for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) {
            int opIdx = 0;
            //DEBUG(dbgs()<<*II<<"\n");
            for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) {
                Value *V = *i;
                if (ValueMap[V] != NULL) {
                    II->setOperand(opIdx, ValueMap[V]);
                }
            }
        }
    }
    //NF->dump();

}
Ejemplo n.º 4
0
void HeterotbbTransform::gen_opt_code_per_f (Function* NF, Function* F) {
    // Get the names of the parameters for old function
    Function::arg_iterator FI = F->arg_begin();
    Argument *classname = &*FI;
    FI++;
    Argument *numiters = &*FI;

    // Set the names of the parameters for new function
    Function::arg_iterator DestI = NF->arg_begin();
    DestI->setName(classname->getName());
    Argument *class_name = &(*DestI);
    //second argument
    DestI++;
    DestI->setName(numiters->getName());
    Argument *num_iters = &(*DestI);

#ifdef EXPLICIT_REWRITE
    DenseMap<const Value*, Value *> ValueMap;
#else
    ValueToValueMapTy ValueMap;
#endif

#if EXPLICIT_REWRITE
    //get the old basic block and create a new one
    Function::const_iterator BI = F->begin();
    const BasicBlock &FB = *BI;
    BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF);
    if (FB.hasName()) {
        NFBB->setName(FB.getName());
        //DEBUG(dbgs()<<FB.getName()<<"\n");
    }
    ValueMap[&FB] = NFBB;

    ValueMap[numiters] = num_iters;
    //must create a new instruction which casts i32* back to the class name
    CastInst *StrucRevCast = CastInst::Create(Instruction::BitCast, class_name,
                             classname->getType(), classname->getName(), NFBB);
    ValueMap[classname] = StrucRevCast;


    for (BasicBlock::const_iterator II = FB.begin(), IE = FB.end(); II != IE; ++II) {
        Instruction *NFInst = II->clone(/*F->getContext()*/);
        //	DEBUG(dbgs()<<*II<<"\n");
        if (II->hasName()) NFInst->setName(II->getName());
        const Instruction *FInst = &(*II);
        rewrite_instruction((Instruction *)FInst, NFInst, ValueMap);
        NFBB->getInstList().push_back(NFInst);
        ValueMap[II] = NFInst;
    }
    BI++;

    for (Function::const_iterator /*BI=F->begin(),*/BE = F->end(); BI != BE; ++BI) {
        const BasicBlock &FBB = *BI;
        BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF);
        ValueMap[&FBB] = NFBB;
        if (FBB.hasName()) {
            NFBB->setName(FBB.getName());
            //DEBUG(dbgs()<<NFBB->getName()<<"\n");
        }
        for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) {
            Instruction *NFInst = II->clone(/*F->getContext()*/);
            if (II->hasName()) NFInst->setName(II->getName());
            const Instruction *FInst = &(*II);
            rewrite_instruction((Instruction *)FInst, NFInst, ValueMap);
            NFBB->getInstList().push_back(NFInst);
            ValueMap[II] = NFInst;
        }
    }
    // Remap the instructions again to take care of forward jumps
    for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) {
        for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) {
            int opIdx = 0;
            //DEBUG(dbgs()<<*II<<"\n");
            for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) {
                Value *V = *i;
                if (ValueMap[V] != NULL) {
                    II->setOperand(opIdx, ValueMap[V]);
                }
            }
        }
    }
#else
    Function::const_iterator BI = F->begin();
    const BasicBlock &FB = *BI;
    BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF);
    if (FB.hasName()) {
        NFBB->setName(FB.getName());
    }
    ValueMap[&FB] = NFBB;
    CastInst *StrucRevCast = CastInst::Create(Instruction::BitCast, class_name,
                             classname->getType(), classname->getName(), NFBB);
    ValueMap[classname] = StrucRevCast;
    ValueMap[numiters] = num_iters;
    CloneFunctionWithExistingBBInto(NF, NFBB, F, ValueMap, "");
#endif
}
Ejemplo n.º 5
0
bool CopyMinimizationPass::runOnFunction(Function& f)
{
  CurrentFile::set(__FILE__);
  bool changed = false ;
  if (f.isDeclaration() || f.getDFFunction() == NULL)
  {
    return changed ;
  }
  
  std::vector<Node<DFBasicBlock*>*> graph;
  
  //We need to start with an acyclic graph to do retiming on -
  //the analyzeCopyPass conveniently provides a function that returns the 
  //blocks reachable by the sink. These are the same blocks that the
  //detectLoopsPass goes through, so they should be acyclical.
  std::map<DFBasicBlock*, bool> pipeBlocks = getPipelineBlocks(f);
  std::map<DFBasicBlock*,Node<DFBasicBlock*>*> nodeMap;
  //for each block in the DFG, create a Node for it.
  //this means we need to provide a weight for the block,
  //and we also want to save it in a map for later
  for(std::map<DFBasicBlock*, bool>::iterator BB = pipeBlocks.begin(); BB != pipeBlocks.end(); ++BB)
  {
    if( BB->second == false )
      continue;
    Node<DFBasicBlock*>* node = new Node<DFBasicBlock*>(BB->first, BB->first->getPipelineLevel(), BB->first->getDelay());
    nodeMap[BB->first] = node;
    graph.push_back(node);
  }
  //for each edge in the DFG, we need to create an Edge in the graph
  for(std::map<DFBasicBlock*, bool>::iterator BB = pipeBlocks.begin(); BB != pipeBlocks.end(); ++BB)
  {
    if( BB->second == false )
      continue;
    CallInst* CI = dynamic_cast<CallInst*>(BB->first->getFirstNonPHI());
    if( isROCCCFunctionCall(CI, ROCCCNames::LoadPrevious) )
      continue;
    for(pred_iterator pred = pred_begin(BB->first); pred != pred_end(BB->first); ++pred)
    {
      assert( (*pred)->getDFBasicBlock() );
      std::map<DFBasicBlock*,Node<DFBasicBlock*>*>::iterator predNode = nodeMap.find((*pred)->getDFBasicBlock());
      if( predNode != nodeMap.end() )
      {
        assert( nodeMap[BB->first] );
        int weight = 0;
        std::map<llvm::Value*,bool> valsUsed;
        for(BasicBlock::iterator II = BB->first->begin(); II != BB->first->end(); ++II)
        {
          for(User::op_iterator OP = II->op_begin(); OP != II->op_end(); ++OP)
          {
            valsUsed[*OP] = true;
          }
        }
        for(BasicBlock::iterator PII = (*pred)->begin(); PII != (*pred)->end(); ++PII)
        {
           for(std::map<llvm::Value*,bool>::iterator VUI = valsUsed.begin(); VUI != valsUsed.end(); ++VUI)
           {
             if( isDefinition(PII, VUI->first) )
             {
               weight += getSizeInBits(VUI->first);
             }
           }
        }
        predNode->second->flowsInto(*nodeMap[BB->first], weight);
      }
      else
      {
        INTERNAL_WARNING((*pred)->getName() << " was not found!\n");
      }
    }
  }
  int minimum_copies = getTotalCopiedBits(graph);
  int num_original_copied_bits = minimum_copies;
  std::vector< Node<DFBasicBlock*>* > min_graph = createCopyOfGraph(graph);
  int iterationCount = 0;
  int minIterationCount = 0;
  LOG_MESSAGE2("Pipelining", "Register Minimization", "Bit registers needed to pipeline original graph, including both copies and pipeline boundaries: " << minimum_copies << ".\n");
  while(maxTripCount(graph) < 10)
  {
    //cout << iterationCount << " - " << maxTripCount(graph) << "\n";
    ++iterationCount;
    //display(graph);
    Edge< Node<DFBasicBlock*> >* largest = selectEdgeWithLargestWeight(graph);
    if( largest )
    {
      //LOG_MESSAGE2("Pipelining", "Register Minimization", "Edge with most bit registers needed: " << largest->source->getData() << " -> " << largest->sink->getData() << "\n");
      tightenEdge(largest);
      largest->tripCount++;
    }
    else
    {
      LOG_MESSAGE2("Pipelining", "Register Minimization", "Completely reduced.\n");
      break;
    }
    //LOG_MESSAGE2("Pipelining", "Register Minimization", "Iteration " << iterationCount << " - total number of bits registers needed: " << getTotalCopiedBits(graph) << ".\n");
    if( getTotalCopiedBits(graph) < minimum_copies )
    {
      min_graph = createCopyOfGraph(graph);
      minimum_copies = getTotalCopiedBits(graph);
      ++minIterationCount;
    }
  }
  LOG_MESSAGE2("Pipelining", "Register Minimization", "Tested " << iterationCount << " total iterations of minimizing; minimum number of bit registers needed, " << minimum_copies << ", was found after " << minIterationCount << " iterations.\n");
  //display(min_graph);
  
  if( minimum_copies != num_original_copied_bits )
  {
    for(std::vector<Node<DFBasicBlock*>*>::const_iterator GI = graph.begin(); GI != graph.end(); ++GI)
    {
      int level = (*GI)->getPosition();
      (*GI)->getData()->setPipelineLevel(level);
      (*GI)->getData()->setDataflowLevel(level);
      std::stringstream ss;
      ss << (*GI)->getData()->getName() << "_" << (*GI)->getData()->getPipelineLevel();
      (*GI)->getData()->setName(ss.str());
    }
    changed = true;
  }
  
  return changed ;
}
Ejemplo n.º 6
0
/// SimplifyDivRemOfSelect - Try to fold a divide or remainder of a select
/// instruction.
bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) {
  SelectInst *SI = cast<SelectInst>(I.getOperand(1));
  
  // div/rem X, (Cond ? 0 : Y) -> div/rem X, Y
  int NonNullOperand = -1;
  if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
    if (ST->isNullValue())
      NonNullOperand = 2;
  // div/rem X, (Cond ? Y : 0) -> div/rem X, Y
  if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
    if (ST->isNullValue())
      NonNullOperand = 1;
  
  if (NonNullOperand == -1)
    return false;
  
  Value *SelectCond = SI->getOperand(0);
  
  // Change the div/rem to use 'Y' instead of the select.
  I.setOperand(1, SI->getOperand(NonNullOperand));
  
  // Okay, we know we replace the operand of the div/rem with 'Y' with no
  // problem.  However, the select, or the condition of the select may have
  // multiple uses.  Based on our knowledge that the operand must be non-zero,
  // propagate the known value for the select into other uses of it, and
  // propagate a known value of the condition into its other users.
  
  // If the select and condition only have a single use, don't bother with this,
  // early exit.
  if (SI->use_empty() && SelectCond->hasOneUse())
    return true;
  
  // Scan the current block backward, looking for other uses of SI.
  BasicBlock::iterator BBI = &I, BBFront = I.getParent()->begin();
  
  while (BBI != BBFront) {
    --BBI;
    // If we found a call to a function, we can't assume it will return, so
    // information from below it cannot be propagated above it.
    if (isa<CallInst>(BBI) && !isa<IntrinsicInst>(BBI))
      break;
    
    // Replace uses of the select or its condition with the known values.
    for (Instruction::op_iterator I = BBI->op_begin(), E = BBI->op_end();
         I != E; ++I) {
      if (*I == SI) {
        *I = SI->getOperand(NonNullOperand);
        Worklist.Add(BBI);
      } else if (*I == SelectCond) {
        *I = NonNullOperand == 1 ? ConstantInt::getTrue(BBI->getContext()) :
                                   ConstantInt::getFalse(BBI->getContext());
        Worklist.Add(BBI);
      }
    }
    
    // If we past the instruction, quit looking for it.
    if (&*BBI == SI)
      SI = 0;
    if (&*BBI == SelectCond)
      SelectCond = 0;
    
    // If we ran out of things to eliminate, break out of the loop.
    if (SelectCond == 0 && SI == 0)
      break;
    
  }
  return true;
}
Ejemplo n.º 7
0
/**
 * Generate code for
 */
void HeteroOMPTransform::gen_code_per_f (Function* NF, Function* F, Instruction *max_threads){
	
	Function::arg_iterator FI = F->arg_begin();
	Argument *ctxname = &*FI;

	Function::arg_iterator DestI = NF->arg_begin();
	DestI->setName(ctxname->getName()); 
	Argument *ctx_name = &(*DestI);
	DestI++;
	DestI->setName("tid");
	Argument *num_iters = &(*DestI);

#ifdef EXPLICIT_REWRITE
	DenseMap<const Value*, Value *> ValueMap;
#else
	ValueToValueMapTy ValueMap;
#endif

	//get the old basic block and create a new one
	Function::const_iterator BI = F->begin();
	const BasicBlock &FB = *BI;
	BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF);
	if (FB.hasName()){
		NFBB->setName(FB.getName());
	}
	ValueMap[&FB] = NFBB;

	//ValueMap[numiters] = num_iters;
	ValueMap[ctxname] = ctx_name;

#if EXPLICIT_REWRITE
	for (BasicBlock::const_iterator II = FB.begin(), IE = FB.end(); II != IE; ++II) {
		Instruction *NFInst = II->clone(/*F->getContext()*/);
		//	DEBUG(dbgs()<<*II<<"\n");
		if (II->hasName()) NFInst->setName(II->getName());
		const Instruction *FInst = &(*II);
		rewrite_instruction((Instruction *)FInst, NFInst, ValueMap);
		NFBB->getInstList().push_back(NFInst);
		ValueMap[II] = NFInst;
	}
	BI++;

	for (Function::const_iterator /*BI=F->begin(),*/BE = F->end();BI != BE; ++BI) {
		const BasicBlock &FBB = *BI;
		BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF);
		ValueMap[&FBB] = NFBB;
		if (FBB.hasName()){
			NFBB->setName(FBB.getName());
			//DEBUG(dbgs()<<NFBB->getName()<<"\n");
		}
		for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) {
			Instruction *NFInst = II->clone(/*F->getContext()*/);
			if (II->hasName()) NFInst->setName(II->getName());
			const Instruction *FInst = &(*II);
			rewrite_instruction((Instruction *)FInst, NFInst, ValueMap);
			NFBB->getInstList().push_back(NFInst);
			ValueMap[II] = NFInst;
		}
	}
	// Remap the instructions again to take care of forward jumps
	for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) {
		for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II){
			int opIdx = 0;
			//DEBUG(dbgs()<<*II<<"\n");
			for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) {
				Value *V = *i;
				if (ValueMap[V] != NULL) {
					II->setOperand(opIdx, ValueMap[V]);
				}
			}
		}
	}
#else
	SmallVector<ReturnInst*, 8> Returns;  // Ignore returns cloned.
	CloneFunctionInto(NF, F, ValueMap, false, Returns, "");
#endif

	//max_threads->dump();
	/* Remap openmp omp_num_threads() and omp_thread_num() */ 
	/*
	 * define internal void @_Z20initialize_variablesiPfS_.omp_fn.4(i8* nocapture %.omp_data_i) nounwind ssp {
     * entry:
     * %0 = bitcast i8* %.omp_data_i to i32*           ; <i32*> [#uses=1]
     * %1 = load i32* %0, align 8                      ; <i32> [#uses=2]
     * %2 = tail call i32 @omp_get_num_threads() nounwind readnone ; <i32> [#uses=2]
     * %3 = tail call i32 @omp_get_thread_num() nounwind readnone ; <i32> [#uses=2]
	   %4 = sdiv i32 %1, %2
	   %5 = mul nsw i32 %4, %2
       %6 = icmp ne i32 %5, %1
       %7 = zext i1 %6 to i32
	 */
	vector<Instruction *> toDelete;
	for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) {
		for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II){
			if (isa<CallInst>(II)) {
				CallSite CI(cast<Instruction>(II));
				if (CI.getCalledFunction() != NULL){ 
					string called_func_name = CI.getCalledFunction()->getName();
					if (called_func_name == OMP_GET_NUM_THREADS_NAME && CI.arg_size() == 0) {
						II->replaceAllUsesWith(ValueMap[max_threads]);
						toDelete.push_back(II);
					}
					else if (called_func_name == OMP_GET_THREAD_NUM_NAME && CI.arg_size() == 0) {
						II->replaceAllUsesWith(num_iters);
						toDelete.push_back(II);
					}
				}
			}
		}
	}


	/* Delete the last branch instruction of the first basic block -- Assuming it is safe */
	Function::iterator nfBB = NF->begin();
	TerminatorInst *lastI = nfBB->getTerminator();
	BranchInst *bI;
	BasicBlock *returnBlock;
	if ((bI = dyn_cast<BranchInst>(lastI)) && bI->isConditional() && 
		(returnBlock = bI->getSuccessor(1)) && 
		(returnBlock->getName() == "return")) {
		/* modify to a unconditional branch to next basic block and not return */
		Instruction *bbI = BranchInst::Create(bI->getSuccessor(0),lastI);
		bbI->dump();
		toDelete.push_back(lastI);
	}

	//NF->dump();
	while(!toDelete.empty()) {
		Instruction *g = toDelete.back();
		//g->replaceAllUsesWith(UndefValue::get(g->getType()));
		toDelete.pop_back();
		g->eraseFromParent();
	}

	//NF->dump();
}
Ejemplo n.º 8
0
void RegionExtractor::findInputsOutputs(ValueSet &Inputs,
                                      ValueSet &Outputs) const {
  for (SetVector<BasicBlock *>::const_iterator I = Blocks.begin(),
                                               E = Blocks.end();
       I != E; ++I) {
    BasicBlock *BB = *I;

    // If a used value is defined outside the region, it's an input.  If an
    // instruction is used outside the region, it's an output.
    for (BasicBlock::iterator II = BB->begin(), IE = BB->end();
         II != IE; ++II) {
      for (User::op_iterator OI = II->op_begin(), OE = II->op_end();
           OI != OE; ++OI)
        if (definedInCaller(Blocks, *OI))
          Inputs.insert(*OI);
#if LLVM_VERSION_MINOR == 5
      for (User *U : II->users())
        if (!definedInRegion(Blocks, U)) {
#else
      for (Value::use_iterator UI = II->use_begin(), UE = II->use_end();
           UI != UE; ++UI)
        if (!definedInRegion(Blocks, *UI)) {
#endif
          Outputs.insert(II);
          break;
        }
    }
  }
}

/// severSplitPHINodes - If a PHI node has multiple inputs from outside of the
/// region, we need to split the entry block of the region so that the PHI node
/// is easier to deal with.
void RegionExtractor::severSplitPHINodes(BasicBlock *&Header) {
  unsigned NumPredsFromRegion = 0;
  unsigned NumPredsOutsideRegion = 0;

  if (Header != &Header->getParent()->getEntryBlock()) {
    PHINode *PN = dyn_cast<PHINode>(Header->begin());
    if (!PN) return; // No PHI nodes.

    // If the header node contains any PHI nodes, check to see if there is more
    // than one entry from outside the region.  If so, we need to sever the
    // header block into two.
    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
      if (Blocks.count(PN->getIncomingBlock(i)))
        ++NumPredsFromRegion;
      else
        ++NumPredsOutsideRegion;

    // If there is one (or fewer) predecessor from outside the region, we don't
    // need to do anything special.
    if (NumPredsOutsideRegion <= 1) return;
  }

  // Otherwise, we need to split the header block into two pieces: one
  // containing PHI nodes merging values from outside of the region, and a
  // second that contains all of the code for the block and merges back any
  // incoming values from inside of the region.
  BasicBlock::iterator AfterPHIs = Header->getFirstNonPHI();
  BasicBlock *NewBB = Header->splitBasicBlock(AfterPHIs,
                                              Header->getName()+".ce");

  // We only want to code extract the second block now, and it becomes the new
  // header of the region.
  BasicBlock *OldPred = Header;
  Blocks.remove(OldPred);
  Blocks.insert(NewBB);
  Header = NewBB;

  // Okay, update dominator sets. The blocks that dominate the new one are the
  // blocks that dominate TIBB plus the new block itself.
  if (DT)
    DT->splitBlock(NewBB);

  // Okay, now we need to adjust the PHI nodes and any branches from within the
  // region to go to the new header block instead of the old header block.
  if (NumPredsFromRegion) {
    PHINode *PN = cast<PHINode>(OldPred->begin());
    // Loop over all of the predecessors of OldPred that are in the region,
    // changing them to branch to NewBB instead.
    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
      if (Blocks.count(PN->getIncomingBlock(i))) {
        TerminatorInst *TI = PN->getIncomingBlock(i)->getTerminator();
        TI->replaceUsesOfWith(OldPred, NewBB);
      }

    // Okay, everything within the region is now branching to the right block, we
    // just have to update the PHI nodes now, inserting PHI nodes into NewBB.
    for (AfterPHIs = OldPred->begin(); isa<PHINode>(AfterPHIs); ++AfterPHIs) {
      PHINode *PN = cast<PHINode>(AfterPHIs);
      // Create a new PHI node in the new region, which has an incoming value
      // from OldPred of PN.
      PHINode *NewPN = PHINode::Create(PN->getType(), 1 + NumPredsFromRegion,
                                       PN->getName()+".ce", NewBB->begin());
      NewPN->addIncoming(PN, OldPred);

      // Loop over all of the incoming value in PN, moving them to NewPN if they
      // are from the extracted region.
      for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) {
        if (Blocks.count(PN->getIncomingBlock(i))) {
          NewPN->addIncoming(PN->getIncomingValue(i), PN->getIncomingBlock(i));
          PN->removeIncomingValue(i);
          --i;
        }
      }
    }
  }
}
Ejemplo n.º 9
0
bool partition::runOnLoop(Loop* L, LPPassManager &LPM) {
    
    errs() << "***************************  Loop encountered: ************************" << '\n' << L->getHeader()->getName() << '\n';
    
    if (function->getName() != "main")
        return false;


    IntegerType* int32Ty = Type::getInt32Ty(*context);
    IntegerType* int64Ty = Type::getInt64Ty(*context);
    PointerType* voidPtrTy = Type::getInt8PtrTy(*context);

    FunctionType* funcTy = FunctionType::get(int32Ty, false);
   
    Constant* func1_c;
    Function* func1;

    func1_c = module->getOrInsertFunction("func1", funcTy);
    func1 = cast<Function>(func1_c);


    Function* pro = module->getFunction("produce");
    Function* con = module->getFunction("consume");
    
    BasicBlock* func1EntryBlock = BasicBlock::Create(*context, "entry.func1", func1);
    AllocaInst* i_var = new AllocaInst(int32Ty, NULL, 4, "i", func1EntryBlock);
    
    Value* liveIn;
    BasicBlock *forCond, *forBody, *forInc;
    ValueToValueMapTy VMap;
    std::map<BasicBlock *, BasicBlock *> BlockMap;
    
    for (Loop::block_iterator BB = L->block_begin(), BBe = L->block_end(); BB != BBe; ++BB) {
        BasicBlock* func1Block = CloneBasicBlock(*BB, VMap, ".func1", func1);
        BlockMap[*BB] = func1Block;

        if ((*BB)->getName() == "for.cond") 
            forCond = func1Block;
        if ((*BB)->getName() == "for.body") 
            forBody = func1Block;
        if ((*BB)->getName() == "for.inc") 
            forInc = func1Block;

        for (BasicBlock::iterator it = func1Block->begin(), ite = func1Block->end(); it != ite; ++it) {
            for (User::op_iterator oit = it->op_begin(), oite = it->op_end(); oit != oite; ++oit) {
                if (VMap[*oit] != NULL) {
                    *oit = VMap[*oit];
                } else {
                    Constant* cons = dyn_cast<Constant>(*oit);
                    BranchInst* br = dyn_cast<BranchInst>(it);
                    if (cons == NULL && br == NULL) {
                        liveIn = *oit;
                        *oit = i_var;
                    }
                }
               
            }
        }

        if ((*BB)->getName() == "for.body") {
            Instruction* term = (*BB)->getTerminator();
            term->removeFromParent();
            for (int i = 0; i < 7; i++) {
                (*BB)->back().eraseFromParent();
            }
            term->insertAfter(&(*BB)->back());
            (*BB)->front().eraseFromParent();
            LoadInst* load = new LoadInst(liveIn, "", false, 4, term); 

            std::vector<Value *> produce_args;
            CastInst* cast = CastInst::CreateIntegerCast(load, int64Ty, true);
            cast->insertAfter(load);
            produce_args.push_back(cast);
            ConstantInt* val = ConstantInt::get(int32Ty, (uint32_t) 3);
            produce_args.push_back(val);
            CallInst::Create(pro, ArrayRef<Value*>(produce_args), "", term);

            produce_args.pop_back();
            val = ConstantInt::get(int32Ty, (uint32_t) 2);
            produce_args.push_back(val);
            CallInst::Create(pro, ArrayRef<Value*>(produce_args), "", term);
        }
    
    }

    // set branch instructions to restructure the CFG in created function
    BasicBlock* func1EndBlock = BasicBlock::Create(*context, "if.end.func1", func1); 
    BasicBlock* garbageBB = BasicBlock::Create(*context, "garbage", func1);
    ConstantInt* retVal_g = ConstantInt::get(int32Ty, (uint32_t) 0);
    ReturnInst* ret_g = ReturnInst::Create(*context, retVal_g, garbageBB);

    
    for (Function::iterator fit = func1->begin(), fite = func1->end(); fit != fite; ++fit) {
        if (fit->getTerminator() == NULL || fit->getName() == "garbage")
            continue;
      
        BranchInst* br = dyn_cast<BranchInst>(fit->getTerminator());
        int numSuccessors = br->getNumSuccessors();
        
        for (int i = 0; i < numSuccessors; i++) {
            BasicBlock* successor = br->getSuccessor(i);
            
            if (BlockMap[successor] != NULL) {
                
                br->setSuccessor(i, BlockMap[successor]);
            } 
            else {
                br->setSuccessor(i, func1EndBlock);
            }
            
        }
/*
        if (fit->getName() == "for.body.func1") {
            for (int i = 0; i < 4; i++) {
                BasicBlock::iterator it = fit->begin();
                it->moveBefore(ret_g);
            }
        }
        */
    }
    garbageBB->eraseFromParent();

    BranchInst* br = dyn_cast<BranchInst>(forBody->getTerminator());
    br->setSuccessor(0, forCond);
    forInc->eraseFromParent();


    // Create return instruction for func1EndBlock and set a branch from loop header to func1EndBlock
    ConstantInt* retVal = ConstantInt::get(int32Ty, (uint32_t) 0);
    ReturnInst* ret1 = ReturnInst::Create(*context, retVal, func1EndBlock);
    BasicBlock* loopHeader = BlockMap.at(L->getHeader());
    BranchInst* brInst = BranchInst::Create(loopHeader, func1EntryBlock);
    
    // add produce function call
    std::vector<Value *> produce_args;
    ConstantInt* val = ConstantInt::get(int64Ty, (uint64_t) 0);
    produce_args.push_back(val);
    val = ConstantInt::get(int32Ty, (uint32_t) 5);
    produce_args.push_back(val);
    CallInst::Create(pro, ArrayRef<Value*>(produce_args), "", func1EndBlock->getTerminator());
    
    // add consume function call
    int q_id = 2;
    for (Value::use_iterator uit = i_var->use_begin(), uite = i_var->use_end(); uit != uite; ++uit) {
        std::vector<Value *> consume_args;
        ConstantInt* val = ConstantInt::get(int32Ty, (uint32_t) q_id); 
        consume_args.push_back(val);
        CallInst* call = CallInst::Create(con, ArrayRef<Value*>(consume_args));
        Instruction* inst = dyn_cast<Instruction>(*uit);
        call->insertAfter(inst);
        CastInst* cast = CastInst::CreateIntegerCast(call, int32Ty, true);
        cast->insertAfter(call);
        (*uit)->replaceAllUsesWith(cast);
        inst->eraseFromParent();
        q_id++;
    }

    i_var->eraseFromParent();

    // add produce and consume function calls to main thread
    // transmit the function pointer to created function by a produce call
    BasicBlock* loopPreheader = L->getLoopPreheader();
    produce_args.clear();
    CastInst* cast = CastInst::CreatePointerCast(func1, int64Ty);
    cast->insertBefore(loopPreheader->getTerminator());
    produce_args.push_back(cast);
    val = ConstantInt::get(int32Ty, (uint32_t) 0);
    produce_args.push_back(val);
    CallInst::Create(pro, ArrayRef<Value*>(produce_args), "", loopPreheader->getTerminator());
  
    // transmit induction variable to created function by a produce call
    Instruction* load = &L->getHeader()->front();
    produce_args.clear();
    cast = CastInst::CreateIntegerCast(load, int64Ty, true);
    cast->insertAfter(load);
    produce_args.push_back(cast);
    val = ConstantInt::get(int32Ty, (uint32_t) 4);
    produce_args.push_back(val);
    CallInst::Create(pro, ArrayRef<Value*>(produce_args))->insertAfter(cast);



    return true;
}