/* in addition to the original condition of the loop, insert one cond on the virtual iterator, given the linf and lsup bounds for the chunk this cond exits and returns to the decision block to start a new chunk */ BasicBlock *insertChunkCond(Loop *&L, LoopInfo *LI, Value *vi, Value *lsup, BasicBlock *dcb, Value *vi_dcb_val, PHINode *&phi_vi) { BasicBlock *H = L->getHeader(); BasicBlock *newCond = BasicBlock::Create( H->getContext(), Twine("__kernel__" + H->getName().str() + "_viCond"), H->getParent(), H); std::vector<BasicBlock *> Lblocks = L->getBlocks(); BasicBlock *exitBlock = BasicBlock::Create( H->getContext(), Twine(H->getName().str() + "_exitChunk"), H->getParent(), H); BranchInst::Create(dcb, exitBlock); phi_vi = PHINode::Create(Type::getInt64Ty(H->getContext()), 2, "vi_value", newCond); phi_vi->addIncoming(vi_dcb_val, dcb); LoadInst *load_lsup = new LoadInst(lsup, "lsup_value", newCond); ICmpInst *cmp = new ICmpInst(*newCond, ICmpInst::ICMP_SLT, phi_vi, load_lsup, vi->getName() + "_cmp"); // Make sure all predecessors now go to our new condition std::vector<TerminatorInst *> termInstrs; BasicBlock *lp = L->getLoopPredecessor(); for (auto it = pred_begin(H), end = pred_end(H); it != end; ++it) { if ((*it) == lp) { // Original entry should be redirected to dcb TerminatorInst *tinstr = (*it)->getTerminator(); for (auto it = tinstr->op_begin(), end = tinstr->op_end(); it != end; ++it) { Use *use = &*it; if (use->get() == H) { use->set(dcb); } } } else { termInstrs.push_back((*it)->getTerminator()); } } for (auto &tinstr : termInstrs) { for (auto it = tinstr->op_begin(), end = tinstr->op_end(); it != end; ++it) { Use *use = &*it; if (use->get() == H) { use->set(newCond); } } } BranchInst::Create(H, exitBlock, cmp, newCond); // update loop info if (L != LI->getLoopFor(newCond)) { L->addBasicBlockToLoop(newCond, *LI); } L->moveToHeader(newCond); Loop *Lp = L->getParentLoop(); if (Lp) Lp->addBasicBlockToLoop(exitBlock, *LI); return newCond; }