CGLoopInfo.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. #include "CGLoopInfo.h"
  10. #include "clang/AST/ASTContext.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. static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
  21. llvm::DebugLoc Location) {
  22. if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
  23. Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
  24. Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
  25. Attrs.UnrollEnable == LoopAttributes::Unspecified &&
  26. Attrs.DistributeEnable == LoopAttributes::Unspecified &&
  27. !Location)
  28. return nullptr;
  29. SmallVector<Metadata *, 4> Args;
  30. // Reserve operand 0 for loop id self reference.
  31. auto TempNode = MDNode::getTemporary(Ctx, None);
  32. Args.push_back(TempNode.get());
  33. // If we have a valid debug location for the loop, add it.
  34. if (Location)
  35. Args.push_back(Location.getAsMDNode());
  36. // Setting vectorize.width
  37. if (Attrs.VectorizeWidth > 0) {
  38. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
  39. ConstantAsMetadata::get(ConstantInt::get(
  40. Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
  41. Args.push_back(MDNode::get(Ctx, Vals));
  42. }
  43. // Setting interleave.count
  44. if (Attrs.InterleaveCount > 0) {
  45. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
  46. ConstantAsMetadata::get(ConstantInt::get(
  47. Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
  48. Args.push_back(MDNode::get(Ctx, Vals));
  49. }
  50. // Setting interleave.count
  51. if (Attrs.UnrollCount > 0) {
  52. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
  53. ConstantAsMetadata::get(ConstantInt::get(
  54. Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
  55. Args.push_back(MDNode::get(Ctx, Vals));
  56. }
  57. // Setting vectorize.enable
  58. if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
  59. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
  60. ConstantAsMetadata::get(ConstantInt::get(
  61. Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
  62. LoopAttributes::Enable)))};
  63. Args.push_back(MDNode::get(Ctx, Vals));
  64. }
  65. // Setting unroll.full or unroll.disable
  66. if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
  67. std::string Name;
  68. if (Attrs.UnrollEnable == LoopAttributes::Enable)
  69. Name = "llvm.loop.unroll.enable";
  70. else if (Attrs.UnrollEnable == LoopAttributes::Full)
  71. Name = "llvm.loop.unroll.full";
  72. else
  73. Name = "llvm.loop.unroll.disable";
  74. Metadata *Vals[] = {MDString::get(Ctx, Name)};
  75. Args.push_back(MDNode::get(Ctx, Vals));
  76. }
  77. if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
  78. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
  79. ConstantAsMetadata::get(ConstantInt::get(
  80. Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
  81. LoopAttributes::Enable)))};
  82. Args.push_back(MDNode::get(Ctx, Vals));
  83. }
  84. // Set the first operand to itself.
  85. MDNode *LoopID = MDNode::get(Ctx, Args);
  86. LoopID->replaceOperandWith(0, LoopID);
  87. return LoopID;
  88. }
  89. LoopAttributes::LoopAttributes(bool IsParallel)
  90. : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
  91. UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
  92. InterleaveCount(0), UnrollCount(0),
  93. DistributeEnable(LoopAttributes::Unspecified) {}
  94. void LoopAttributes::clear() {
  95. IsParallel = false;
  96. VectorizeWidth = 0;
  97. InterleaveCount = 0;
  98. UnrollCount = 0;
  99. VectorizeEnable = LoopAttributes::Unspecified;
  100. UnrollEnable = LoopAttributes::Unspecified;
  101. DistributeEnable = LoopAttributes::Unspecified;
  102. }
  103. LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
  104. llvm::DebugLoc Location)
  105. : LoopID(nullptr), Header(Header), Attrs(Attrs) {
  106. LoopID = createMetadata(Header->getContext(), Attrs, Location);
  107. }
  108. void LoopInfoStack::push(BasicBlock *Header, llvm::DebugLoc Location) {
  109. Active.push_back(LoopInfo(Header, StagedAttrs, Location));
  110. // Clear the attributes so nested loops do not inherit them.
  111. StagedAttrs.clear();
  112. }
  113. void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
  114. ArrayRef<const clang::Attr *> Attrs,
  115. llvm::DebugLoc Location) {
  116. // Identify loop hint attributes from Attrs.
  117. for (const auto *Attr : Attrs) {
  118. const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
  119. const OpenCLUnrollHintAttr *OpenCLHint =
  120. dyn_cast<OpenCLUnrollHintAttr>(Attr);
  121. // Skip non loop hint attributes
  122. if (!LH && !OpenCLHint) {
  123. continue;
  124. }
  125. LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
  126. LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
  127. unsigned ValueInt = 1;
  128. // Translate opencl_unroll_hint attribute argument to
  129. // equivalent LoopHintAttr enums.
  130. // OpenCL v2.0 s6.11.5:
  131. // 0 - full unroll (no argument).
  132. // 1 - disable unroll.
  133. // other positive integer n - unroll by n.
  134. if (OpenCLHint) {
  135. ValueInt = OpenCLHint->getUnrollHint();
  136. if (ValueInt == 0) {
  137. State = LoopHintAttr::Full;
  138. } else if (ValueInt != 1) {
  139. Option = LoopHintAttr::UnrollCount;
  140. State = LoopHintAttr::Numeric;
  141. }
  142. } else if (LH) {
  143. auto *ValueExpr = LH->getValue();
  144. if (ValueExpr) {
  145. llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
  146. ValueInt = ValueAPS.getSExtValue();
  147. }
  148. Option = LH->getOption();
  149. State = LH->getState();
  150. }
  151. switch (State) {
  152. case LoopHintAttr::Disable:
  153. switch (Option) {
  154. case LoopHintAttr::Vectorize:
  155. // Disable vectorization by specifying a width of 1.
  156. setVectorizeWidth(1);
  157. break;
  158. case LoopHintAttr::Interleave:
  159. // Disable interleaving by speciyfing a count of 1.
  160. setInterleaveCount(1);
  161. break;
  162. case LoopHintAttr::Unroll:
  163. setUnrollState(LoopAttributes::Disable);
  164. break;
  165. case LoopHintAttr::Distribute:
  166. setDistributeState(false);
  167. break;
  168. case LoopHintAttr::UnrollCount:
  169. case LoopHintAttr::VectorizeWidth:
  170. case LoopHintAttr::InterleaveCount:
  171. llvm_unreachable("Options cannot be disabled.");
  172. break;
  173. }
  174. break;
  175. case LoopHintAttr::Enable:
  176. switch (Option) {
  177. case LoopHintAttr::Vectorize:
  178. case LoopHintAttr::Interleave:
  179. setVectorizeEnable(true);
  180. break;
  181. case LoopHintAttr::Unroll:
  182. setUnrollState(LoopAttributes::Enable);
  183. break;
  184. case LoopHintAttr::Distribute:
  185. setDistributeState(true);
  186. break;
  187. case LoopHintAttr::UnrollCount:
  188. case LoopHintAttr::VectorizeWidth:
  189. case LoopHintAttr::InterleaveCount:
  190. llvm_unreachable("Options cannot enabled.");
  191. break;
  192. }
  193. break;
  194. case LoopHintAttr::AssumeSafety:
  195. switch (Option) {
  196. case LoopHintAttr::Vectorize:
  197. case LoopHintAttr::Interleave:
  198. // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
  199. setParallel(true);
  200. setVectorizeEnable(true);
  201. break;
  202. case LoopHintAttr::Unroll:
  203. case LoopHintAttr::UnrollCount:
  204. case LoopHintAttr::VectorizeWidth:
  205. case LoopHintAttr::InterleaveCount:
  206. case LoopHintAttr::Distribute:
  207. llvm_unreachable("Options cannot be used to assume mem safety.");
  208. break;
  209. }
  210. break;
  211. case LoopHintAttr::Full:
  212. switch (Option) {
  213. case LoopHintAttr::Unroll:
  214. setUnrollState(LoopAttributes::Full);
  215. break;
  216. case LoopHintAttr::Vectorize:
  217. case LoopHintAttr::Interleave:
  218. case LoopHintAttr::UnrollCount:
  219. case LoopHintAttr::VectorizeWidth:
  220. case LoopHintAttr::InterleaveCount:
  221. case LoopHintAttr::Distribute:
  222. llvm_unreachable("Options cannot be used with 'full' hint.");
  223. break;
  224. }
  225. break;
  226. case LoopHintAttr::Numeric:
  227. switch (Option) {
  228. case LoopHintAttr::VectorizeWidth:
  229. setVectorizeWidth(ValueInt);
  230. break;
  231. case LoopHintAttr::InterleaveCount:
  232. setInterleaveCount(ValueInt);
  233. break;
  234. case LoopHintAttr::UnrollCount:
  235. setUnrollCount(ValueInt);
  236. break;
  237. case LoopHintAttr::Unroll:
  238. case LoopHintAttr::Vectorize:
  239. case LoopHintAttr::Interleave:
  240. case LoopHintAttr::Distribute:
  241. llvm_unreachable("Options cannot be assigned a value.");
  242. break;
  243. }
  244. break;
  245. }
  246. }
  247. /// Stage the attributes.
  248. push(Header, Location);
  249. }
  250. void LoopInfoStack::pop() {
  251. assert(!Active.empty() && "No active loops to pop");
  252. Active.pop_back();
  253. }
  254. void LoopInfoStack::InsertHelper(Instruction *I) const {
  255. if (!hasInfo())
  256. return;
  257. const LoopInfo &L = getInfo();
  258. if (!L.getLoopID())
  259. return;
  260. if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
  261. for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
  262. if (TI->getSuccessor(i) == L.getHeader()) {
  263. TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
  264. break;
  265. }
  266. return;
  267. }
  268. if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
  269. I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
  270. }