CGLoopInfo.cpp 12 KB

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