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