blob: 63de2d98fd7f50c565c4fff1f8973fa4677f9848 [file] [log] [blame]
Alexander Musman515ad8c2014-05-22 08:54:05 +00001//===---- 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"
Tyler Nowicki9d268e12015-06-11 23:23:17 +000011#include "clang/AST/Attr.h"
12#include "clang/Sema/LoopHint.h"
Alexander Musman515ad8c2014-05-22 08:54:05 +000013#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"
Tyler Nowicki4e8e9002015-06-08 23:27:35 +000018using namespace clang::CodeGen;
Alexander Musman515ad8c2014-05-22 08:54:05 +000019using namespace llvm;
20
21static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
22
Tyler Nowickida46d0e2015-07-14 23:03:09 +000023 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
24 Attrs.InterleaveCount == 0 &&
25 Attrs.VectorizeEnable == LoopAttributes::Unspecified)
Alexander Musman515ad8c2014-05-22 08:54:05 +000026 return nullptr;
27
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000028 SmallVector<Metadata *, 4> Args;
Alexander Musman515ad8c2014-05-22 08:54:05 +000029 // Reserve operand 0 for loop id self reference.
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000030 auto TempNode = MDNode::getTemporary(Ctx, None);
31 Args.push_back(TempNode.get());
Alexander Musman515ad8c2014-05-22 08:54:05 +000032
Tyler Nowickida46d0e2015-07-14 23:03:09 +000033 // Setting vectorize.width
34 if (Attrs.VectorizeWidth > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000035 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
36 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000037 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000038 Args.push_back(MDNode::get(Ctx, Vals));
39 }
40
Tyler Nowickida46d0e2015-07-14 23:03:09 +000041 // Setting interleave.count
42 if (Attrs.InterleaveCount > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000043 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
44 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000045 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000046 Args.push_back(MDNode::get(Ctx, Vals));
47 }
48
Tyler Nowickida46d0e2015-07-14 23:03:09 +000049 // 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)))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000055 Args.push_back(MDNode::get(Ctx, Vals));
56 }
57
Alexander Musman515ad8c2014-05-22 08:54:05 +000058 // Set the first operand to itself.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000059 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +000060 LoopID->replaceOperandWith(0, LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +000061 return LoopID;
62}
63
64LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +000065 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
66 VectorizeWidth(0), InterleaveCount(0) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +000067
68void LoopAttributes::clear() {
69 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +000070 VectorizeWidth = 0;
71 InterleaveCount = 0;
72 VectorizeEnable = LoopAttributes::Unspecified;
Alexander Musman515ad8c2014-05-22 08:54:05 +000073}
74
75LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
76 : LoopID(nullptr), Header(Header), Attrs(Attrs) {
77 LoopID = createMetadata(Header->getContext(), Attrs);
78}
79
David Majnemer03a90562015-06-12 00:17:26 +000080void LoopInfoStack::push(BasicBlock *Header,
81 ArrayRef<const clang::Attr *> Attrs) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +000082 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
Alexander Musman515ad8c2014-05-22 08:54:05 +0000108 Active.push_back(LoopInfo(Header, StagedAttrs));
109 // Clear the attributes so nested loops do not inherit them.
110 StagedAttrs.clear();
111}
112
113void LoopInfoStack::pop() {
114 assert(!Active.empty() && "No active loops to pop");
115 Active.pop_back();
116}
117
118void 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}