]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
MFV r289003:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / CodeGen / CGLoopInfo.cpp
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.VectorizerWidth == 0 &&
24       Attrs.VectorizerUnroll == 0 &&
25       Attrs.VectorizerEnable == LoopAttributes::VecUnspecified)
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 vectorizer.width
34   if (Attrs.VectorizerWidth > 0) {
35     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
36                         ConstantAsMetadata::get(ConstantInt::get(
37                             Type::getInt32Ty(Ctx), Attrs.VectorizerWidth))};
38     Args.push_back(MDNode::get(Ctx, Vals));
39   }
40
41   // Setting vectorizer.unroll
42   if (Attrs.VectorizerUnroll > 0) {
43     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
44                         ConstantAsMetadata::get(ConstantInt::get(
45                             Type::getInt32Ty(Ctx), Attrs.VectorizerUnroll))};
46     Args.push_back(MDNode::get(Ctx, Vals));
47   }
48
49   // Setting vectorizer.enable
50   if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
51     Metadata *Vals[] = {
52         MDString::get(Ctx, "llvm.loop.vectorize.enable"),
53         ConstantAsMetadata::get(ConstantInt::get(
54             Type::getInt1Ty(Ctx),
55             (Attrs.VectorizerEnable == LoopAttributes::VecEnable)))};
56     Args.push_back(MDNode::get(Ctx, Vals));
57   }
58
59   // Set the first operand to itself.
60   MDNode *LoopID = MDNode::get(Ctx, Args);
61   LoopID->replaceOperandWith(0, LoopID);
62   return LoopID;
63 }
64
65 LoopAttributes::LoopAttributes(bool IsParallel)
66     : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified),
67       VectorizerWidth(0), VectorizerUnroll(0) {}
68
69 void LoopAttributes::clear() {
70   IsParallel = false;
71   VectorizerWidth = 0;
72   VectorizerUnroll = 0;
73   VectorizerEnable = LoopAttributes::VecUnspecified;
74 }
75
76 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
77     : LoopID(nullptr), Header(Header), Attrs(Attrs) {
78   LoopID = createMetadata(Header->getContext(), Attrs);
79 }
80
81 void LoopInfoStack::push(BasicBlock *Header,
82                          ArrayRef<const clang::Attr *> Attrs) {
83   for (const auto *Attr : Attrs) {
84     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
85
86     // Skip non loop hint attributes
87     if (!LH)
88       continue;
89
90     LoopHintAttr::OptionType Option = LH->getOption();
91     LoopHintAttr::LoopHintState State = LH->getState();
92     switch (Option) {
93     case LoopHintAttr::Vectorize:
94     case LoopHintAttr::Interleave:
95       if (State == LoopHintAttr::AssumeSafety) {
96         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
97         setParallel(true);
98       }
99       break;
100     case LoopHintAttr::VectorizeWidth:
101     case LoopHintAttr::InterleaveCount:
102     case LoopHintAttr::Unroll:
103     case LoopHintAttr::UnrollCount:
104       // Nothing to do here for these loop hints.
105       break;
106     }
107   }
108
109   Active.push_back(LoopInfo(Header, StagedAttrs));
110   // Clear the attributes so nested loops do not inherit them.
111   StagedAttrs.clear();
112 }
113
114 void LoopInfoStack::pop() {
115   assert(!Active.empty() && "No active loops to pop");
116   Active.pop_back();
117 }
118
119 void LoopInfoStack::InsertHelper(Instruction *I) const {
120   if (!hasInfo())
121     return;
122
123   const LoopInfo &L = getInfo();
124   if (!L.getLoopID())
125     return;
126
127   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
128     for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
129       if (TI->getSuccessor(i) == L.getHeader()) {
130         TI->setMetadata("llvm.loop", L.getLoopID());
131         break;
132       }
133     return;
134   }
135
136   if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
137     I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
138 }