|  | //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "CGLoopInfo.h" | 
|  | #include "llvm/IR/BasicBlock.h" | 
|  | #include "llvm/IR/Constants.h" | 
|  | #include "llvm/IR/InstrTypes.h" | 
|  | #include "llvm/IR/Instructions.h" | 
|  | #include "llvm/IR/Metadata.h" | 
|  | using namespace clang; | 
|  | using namespace CodeGen; | 
|  | using namespace llvm; | 
|  |  | 
|  | static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) { | 
|  |  | 
|  | if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 && | 
|  | Attrs.VectorizerUnroll == 0 && | 
|  | Attrs.VectorizerEnable == LoopAttributes::VecUnspecified) | 
|  | return nullptr; | 
|  |  | 
|  | SmallVector<Metadata *, 4> Args; | 
|  | // Reserve operand 0 for loop id self reference. | 
|  | MDNode *TempNode = MDNode::getTemporary(Ctx, None); | 
|  | Args.push_back(TempNode); | 
|  |  | 
|  | // Setting vectorizer.width | 
|  | if (Attrs.VectorizerWidth > 0) { | 
|  | Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"), | 
|  | ConstantAsMetadata::get(ConstantInt::get( | 
|  | Type::getInt32Ty(Ctx), Attrs.VectorizerWidth))}; | 
|  | Args.push_back(MDNode::get(Ctx, Vals)); | 
|  | } | 
|  |  | 
|  | // Setting vectorizer.unroll | 
|  | if (Attrs.VectorizerUnroll > 0) { | 
|  | Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"), | 
|  | ConstantAsMetadata::get(ConstantInt::get( | 
|  | Type::getInt32Ty(Ctx), Attrs.VectorizerUnroll))}; | 
|  | Args.push_back(MDNode::get(Ctx, Vals)); | 
|  | } | 
|  |  | 
|  | // Setting vectorizer.enable | 
|  | if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) { | 
|  | Metadata *Vals[] = { | 
|  | MDString::get(Ctx, "llvm.loop.vectorize.enable"), | 
|  | ConstantAsMetadata::get(ConstantInt::get( | 
|  | Type::getInt1Ty(Ctx), | 
|  | (Attrs.VectorizerEnable == LoopAttributes::VecEnable)))}; | 
|  | Args.push_back(MDNode::get(Ctx, Vals)); | 
|  | } | 
|  |  | 
|  | // Set the first operand to itself. | 
|  | MDNode *LoopID = MDNode::get(Ctx, Args); | 
|  | LoopID->replaceOperandWith(0, LoopID); | 
|  | MDNode::deleteTemporary(TempNode); | 
|  | return LoopID; | 
|  | } | 
|  |  | 
|  | LoopAttributes::LoopAttributes(bool IsParallel) | 
|  | : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified), | 
|  | VectorizerWidth(0), VectorizerUnroll(0) {} | 
|  |  | 
|  | void LoopAttributes::clear() { | 
|  | IsParallel = false; | 
|  | VectorizerWidth = 0; | 
|  | VectorizerUnroll = 0; | 
|  | VectorizerEnable = LoopAttributes::VecUnspecified; | 
|  | } | 
|  |  | 
|  | LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs) | 
|  | : LoopID(nullptr), Header(Header), Attrs(Attrs) { | 
|  | LoopID = createMetadata(Header->getContext(), Attrs); | 
|  | } | 
|  |  | 
|  | void LoopInfoStack::push(BasicBlock *Header) { | 
|  | Active.push_back(LoopInfo(Header, StagedAttrs)); | 
|  | // Clear the attributes so nested loops do not inherit them. | 
|  | StagedAttrs.clear(); | 
|  | } | 
|  |  | 
|  | void LoopInfoStack::pop() { | 
|  | assert(!Active.empty() && "No active loops to pop"); | 
|  | Active.pop_back(); | 
|  | } | 
|  |  | 
|  | void LoopInfoStack::InsertHelper(Instruction *I) const { | 
|  | if (!hasInfo()) | 
|  | return; | 
|  |  | 
|  | const LoopInfo &L = getInfo(); | 
|  | if (!L.getLoopID()) | 
|  | return; | 
|  |  | 
|  | if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) { | 
|  | for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i) | 
|  | if (TI->getSuccessor(i) == L.getHeader()) { | 
|  | TI->setMetadata("llvm.loop", L.getLoopID()); | 
|  | break; | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory()) | 
|  | I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID()); | 
|  | } |