1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CGLoopInfo.h"
11 #include "clang/AST/Attr.h"
12 #include "clang/Sema/LoopHint.h"
13 #include "llvm/IR/BasicBlock.h"
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/InstrTypes.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/Metadata.h"
18 using namespace clang::CodeGen;
19 using namespace llvm;
20 
21 static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
22 
23   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
24       Attrs.InterleaveCount == 0 &&
25       Attrs.VectorizeEnable == LoopAttributes::Unspecified)
26     return nullptr;
27 
28   SmallVector<Metadata *, 4> Args;
29   // Reserve operand 0 for loop id self reference.
30   auto TempNode = MDNode::getTemporary(Ctx, None);
31   Args.push_back(TempNode.get());
32 
33   // Setting vectorize.width
34   if (Attrs.VectorizeWidth > 0) {
35     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
36                         ConstantAsMetadata::get(ConstantInt::get(
37                             Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
38     Args.push_back(MDNode::get(Ctx, Vals));
39   }
40 
41   // Setting interleave.count
42   if (Attrs.InterleaveCount > 0) {
43     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
44                         ConstantAsMetadata::get(ConstantInt::get(
45                             Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
46     Args.push_back(MDNode::get(Ctx, Vals));
47   }
48 
49   // Setting vectorize.enable
50   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
51     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
52                         ConstantAsMetadata::get(ConstantInt::get(
53                             Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
54                                                    LoopAttributes::Enable)))};
55     Args.push_back(MDNode::get(Ctx, Vals));
56   }
57 
58   // Set the first operand to itself.
59   MDNode *LoopID = MDNode::get(Ctx, Args);
60   LoopID->replaceOperandWith(0, LoopID);
61   return LoopID;
62 }
63 
64 LoopAttributes::LoopAttributes(bool IsParallel)
65     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
66       VectorizeWidth(0), InterleaveCount(0) {}
67 
68 void LoopAttributes::clear() {
69   IsParallel = false;
70   VectorizeWidth = 0;
71   InterleaveCount = 0;
72   VectorizeEnable = LoopAttributes::Unspecified;
73 }
74 
75 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
76     : LoopID(nullptr), Header(Header), Attrs(Attrs) {
77   LoopID = createMetadata(Header->getContext(), Attrs);
78 }
79 
80 void LoopInfoStack::push(BasicBlock *Header,
81                          ArrayRef<const clang::Attr *> Attrs) {
82   for (const auto *Attr : Attrs) {
83     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
84 
85     // Skip non loop hint attributes
86     if (!LH)
87       continue;
88 
89     LoopHintAttr::OptionType Option = LH->getOption();
90     LoopHintAttr::LoopHintState State = LH->getState();
91     switch (Option) {
92     case LoopHintAttr::Vectorize:
93     case LoopHintAttr::Interleave:
94       if (State == LoopHintAttr::AssumeSafety) {
95         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
96         setParallel(true);
97       }
98       break;
99     case LoopHintAttr::VectorizeWidth:
100     case LoopHintAttr::InterleaveCount:
101     case LoopHintAttr::Unroll:
102     case LoopHintAttr::UnrollCount:
103       // Nothing to do here for these loop hints.
104       break;
105     }
106   }
107 
108   Active.push_back(LoopInfo(Header, StagedAttrs));
109   // Clear the attributes so nested loops do not inherit them.
110   StagedAttrs.clear();
111 }
112 
113 void LoopInfoStack::pop() {
114   assert(!Active.empty() && "No active loops to pop");
115   Active.pop_back();
116 }
117 
118 void LoopInfoStack::InsertHelper(Instruction *I) const {
119   if (!hasInfo())
120     return;
121 
122   const LoopInfo &L = getInfo();
123   if (!L.getLoopID())
124     return;
125 
126   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
127     for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
128       if (TI->getSuccessor(i) == L.getHeader()) {
129         TI->setMetadata("llvm.loop", L.getLoopID());
130         break;
131       }
132     return;
133   }
134 
135   if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
136     I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
137 }
138