xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGLoopInfo.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #include "CGLoopInfo.h"
11*0a6a1f1dSLionel Sambuc #include "llvm/IR/BasicBlock.h"
12*0a6a1f1dSLionel Sambuc #include "llvm/IR/Constants.h"
13*0a6a1f1dSLionel Sambuc #include "llvm/IR/InstrTypes.h"
14*0a6a1f1dSLionel Sambuc #include "llvm/IR/Instructions.h"
15*0a6a1f1dSLionel Sambuc #include "llvm/IR/Metadata.h"
16*0a6a1f1dSLionel Sambuc using namespace clang;
17*0a6a1f1dSLionel Sambuc using namespace CodeGen;
18*0a6a1f1dSLionel Sambuc using namespace llvm;
19*0a6a1f1dSLionel Sambuc 
createMetadata(LLVMContext & Ctx,const LoopAttributes & Attrs)20*0a6a1f1dSLionel Sambuc static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
21*0a6a1f1dSLionel Sambuc 
22*0a6a1f1dSLionel Sambuc   if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 &&
23*0a6a1f1dSLionel Sambuc       Attrs.VectorizerUnroll == 0 &&
24*0a6a1f1dSLionel Sambuc       Attrs.VectorizerEnable == LoopAttributes::VecUnspecified)
25*0a6a1f1dSLionel Sambuc     return nullptr;
26*0a6a1f1dSLionel Sambuc 
27*0a6a1f1dSLionel Sambuc   SmallVector<Metadata *, 4> Args;
28*0a6a1f1dSLionel Sambuc   // Reserve operand 0 for loop id self reference.
29*0a6a1f1dSLionel Sambuc   MDNode *TempNode = MDNode::getTemporary(Ctx, None);
30*0a6a1f1dSLionel Sambuc   Args.push_back(TempNode);
31*0a6a1f1dSLionel Sambuc 
32*0a6a1f1dSLionel Sambuc   // Setting vectorizer.width
33*0a6a1f1dSLionel Sambuc   if (Attrs.VectorizerWidth > 0) {
34*0a6a1f1dSLionel Sambuc     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
35*0a6a1f1dSLionel Sambuc                         ConstantAsMetadata::get(ConstantInt::get(
36*0a6a1f1dSLionel Sambuc                             Type::getInt32Ty(Ctx), Attrs.VectorizerWidth))};
37*0a6a1f1dSLionel Sambuc     Args.push_back(MDNode::get(Ctx, Vals));
38*0a6a1f1dSLionel Sambuc   }
39*0a6a1f1dSLionel Sambuc 
40*0a6a1f1dSLionel Sambuc   // Setting vectorizer.unroll
41*0a6a1f1dSLionel Sambuc   if (Attrs.VectorizerUnroll > 0) {
42*0a6a1f1dSLionel Sambuc     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
43*0a6a1f1dSLionel Sambuc                         ConstantAsMetadata::get(ConstantInt::get(
44*0a6a1f1dSLionel Sambuc                             Type::getInt32Ty(Ctx), Attrs.VectorizerUnroll))};
45*0a6a1f1dSLionel Sambuc     Args.push_back(MDNode::get(Ctx, Vals));
46*0a6a1f1dSLionel Sambuc   }
47*0a6a1f1dSLionel Sambuc 
48*0a6a1f1dSLionel Sambuc   // Setting vectorizer.enable
49*0a6a1f1dSLionel Sambuc   if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
50*0a6a1f1dSLionel Sambuc     Metadata *Vals[] = {
51*0a6a1f1dSLionel Sambuc         MDString::get(Ctx, "llvm.loop.vectorize.enable"),
52*0a6a1f1dSLionel Sambuc         ConstantAsMetadata::get(ConstantInt::get(
53*0a6a1f1dSLionel Sambuc             Type::getInt1Ty(Ctx),
54*0a6a1f1dSLionel Sambuc             (Attrs.VectorizerEnable == LoopAttributes::VecEnable)))};
55*0a6a1f1dSLionel Sambuc     Args.push_back(MDNode::get(Ctx, Vals));
56*0a6a1f1dSLionel Sambuc   }
57*0a6a1f1dSLionel Sambuc 
58*0a6a1f1dSLionel Sambuc   // Set the first operand to itself.
59*0a6a1f1dSLionel Sambuc   MDNode *LoopID = MDNode::get(Ctx, Args);
60*0a6a1f1dSLionel Sambuc   LoopID->replaceOperandWith(0, LoopID);
61*0a6a1f1dSLionel Sambuc   MDNode::deleteTemporary(TempNode);
62*0a6a1f1dSLionel Sambuc   return LoopID;
63*0a6a1f1dSLionel Sambuc }
64*0a6a1f1dSLionel Sambuc 
LoopAttributes(bool IsParallel)65*0a6a1f1dSLionel Sambuc LoopAttributes::LoopAttributes(bool IsParallel)
66*0a6a1f1dSLionel Sambuc     : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified),
67*0a6a1f1dSLionel Sambuc       VectorizerWidth(0), VectorizerUnroll(0) {}
68*0a6a1f1dSLionel Sambuc 
clear()69*0a6a1f1dSLionel Sambuc void LoopAttributes::clear() {
70*0a6a1f1dSLionel Sambuc   IsParallel = false;
71*0a6a1f1dSLionel Sambuc   VectorizerWidth = 0;
72*0a6a1f1dSLionel Sambuc   VectorizerUnroll = 0;
73*0a6a1f1dSLionel Sambuc   VectorizerEnable = LoopAttributes::VecUnspecified;
74*0a6a1f1dSLionel Sambuc }
75*0a6a1f1dSLionel Sambuc 
LoopInfo(BasicBlock * Header,const LoopAttributes & Attrs)76*0a6a1f1dSLionel Sambuc LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
77*0a6a1f1dSLionel Sambuc     : LoopID(nullptr), Header(Header), Attrs(Attrs) {
78*0a6a1f1dSLionel Sambuc   LoopID = createMetadata(Header->getContext(), Attrs);
79*0a6a1f1dSLionel Sambuc }
80*0a6a1f1dSLionel Sambuc 
push(BasicBlock * Header)81*0a6a1f1dSLionel Sambuc void LoopInfoStack::push(BasicBlock *Header) {
82*0a6a1f1dSLionel Sambuc   Active.push_back(LoopInfo(Header, StagedAttrs));
83*0a6a1f1dSLionel Sambuc   // Clear the attributes so nested loops do not inherit them.
84*0a6a1f1dSLionel Sambuc   StagedAttrs.clear();
85*0a6a1f1dSLionel Sambuc }
86*0a6a1f1dSLionel Sambuc 
pop()87*0a6a1f1dSLionel Sambuc void LoopInfoStack::pop() {
88*0a6a1f1dSLionel Sambuc   assert(!Active.empty() && "No active loops to pop");
89*0a6a1f1dSLionel Sambuc   Active.pop_back();
90*0a6a1f1dSLionel Sambuc }
91*0a6a1f1dSLionel Sambuc 
InsertHelper(Instruction * I) const92*0a6a1f1dSLionel Sambuc void LoopInfoStack::InsertHelper(Instruction *I) const {
93*0a6a1f1dSLionel Sambuc   if (!hasInfo())
94*0a6a1f1dSLionel Sambuc     return;
95*0a6a1f1dSLionel Sambuc 
96*0a6a1f1dSLionel Sambuc   const LoopInfo &L = getInfo();
97*0a6a1f1dSLionel Sambuc   if (!L.getLoopID())
98*0a6a1f1dSLionel Sambuc     return;
99*0a6a1f1dSLionel Sambuc 
100*0a6a1f1dSLionel Sambuc   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
101*0a6a1f1dSLionel Sambuc     for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
102*0a6a1f1dSLionel Sambuc       if (TI->getSuccessor(i) == L.getHeader()) {
103*0a6a1f1dSLionel Sambuc         TI->setMetadata("llvm.loop", L.getLoopID());
104*0a6a1f1dSLionel Sambuc         break;
105*0a6a1f1dSLionel Sambuc       }
106*0a6a1f1dSLionel Sambuc     return;
107*0a6a1f1dSLionel Sambuc   }
108*0a6a1f1dSLionel Sambuc 
109*0a6a1f1dSLionel Sambuc   if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
110*0a6a1f1dSLionel Sambuc     I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
111*0a6a1f1dSLionel Sambuc }
112