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