CGLoopInfo.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "CGLoopInfo.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/AST/Attr.h"
  11. #include "llvm/IR/BasicBlock.h"
  12. #include "llvm/IR/CFG.h"
  13. #include "llvm/IR/Constants.h"
  14. #include "llvm/IR/InstrTypes.h"
  15. #include "llvm/IR/Instructions.h"
  16. #include "llvm/IR/Metadata.h"
  17. using namespace clang::CodeGen;
  18. using namespace llvm;
  19. static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
  20. const llvm::DebugLoc &StartLoc,
  21. const llvm::DebugLoc &EndLoc, MDNode *&AccGroup) {
  22. if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
  23. Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
  24. Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
  25. Attrs.PipelineInitiationInterval == 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. if (Attrs.IsParallel) {
  111. AccGroup = MDNode::getDistinct(Ctx, {});
  112. Args.push_back(MDNode::get(
  113. Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
  114. }
  115. if (Attrs.PipelineDisabled) {
  116. Metadata *Vals[] = {
  117. MDString::get(Ctx, "llvm.loop.pipeline.disable"),
  118. ConstantAsMetadata::get(ConstantInt::get(
  119. Type::getInt1Ty(Ctx), (Attrs.PipelineDisabled == true)))};
  120. Args.push_back(MDNode::get(Ctx, Vals));
  121. }
  122. if (Attrs.PipelineInitiationInterval > 0) {
  123. Metadata *Vals[] = {
  124. MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
  125. ConstantAsMetadata::get(ConstantInt::get(
  126. Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
  127. Args.push_back(MDNode::get(Ctx, Vals));
  128. }
  129. // Set the first operand to itself.
  130. MDNode *LoopID = MDNode::get(Ctx, Args);
  131. LoopID->replaceOperandWith(0, LoopID);
  132. return LoopID;
  133. }
  134. LoopAttributes::LoopAttributes(bool IsParallel)
  135. : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
  136. UnrollEnable(LoopAttributes::Unspecified),
  137. UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
  138. InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
  139. DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
  140. PipelineInitiationInterval(0) {}
  141. void LoopAttributes::clear() {
  142. IsParallel = false;
  143. VectorizeWidth = 0;
  144. InterleaveCount = 0;
  145. UnrollCount = 0;
  146. UnrollAndJamCount = 0;
  147. VectorizeEnable = LoopAttributes::Unspecified;
  148. UnrollEnable = LoopAttributes::Unspecified;
  149. UnrollAndJamEnable = LoopAttributes::Unspecified;
  150. DistributeEnable = LoopAttributes::Unspecified;
  151. PipelineDisabled = false;
  152. PipelineInitiationInterval = 0;
  153. }
  154. LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
  155. const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
  156. : LoopID(nullptr), Header(Header), Attrs(Attrs) {
  157. LoopID =
  158. createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc, AccGroup);
  159. }
  160. void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
  161. const llvm::DebugLoc &EndLoc) {
  162. Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc));
  163. // Clear the attributes so nested loops do not inherit them.
  164. StagedAttrs.clear();
  165. }
  166. void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
  167. ArrayRef<const clang::Attr *> Attrs,
  168. const llvm::DebugLoc &StartLoc,
  169. const llvm::DebugLoc &EndLoc) {
  170. // Identify loop hint attributes from Attrs.
  171. for (const auto *Attr : Attrs) {
  172. const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
  173. const OpenCLUnrollHintAttr *OpenCLHint =
  174. dyn_cast<OpenCLUnrollHintAttr>(Attr);
  175. // Skip non loop hint attributes
  176. if (!LH && !OpenCLHint) {
  177. continue;
  178. }
  179. LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
  180. LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
  181. unsigned ValueInt = 1;
  182. // Translate opencl_unroll_hint attribute argument to
  183. // equivalent LoopHintAttr enums.
  184. // OpenCL v2.0 s6.11.5:
  185. // 0 - enable unroll (no argument).
  186. // 1 - disable unroll.
  187. // other positive integer n - unroll by n.
  188. if (OpenCLHint) {
  189. ValueInt = OpenCLHint->getUnrollHint();
  190. if (ValueInt == 0) {
  191. State = LoopHintAttr::Enable;
  192. } else if (ValueInt != 1) {
  193. Option = LoopHintAttr::UnrollCount;
  194. State = LoopHintAttr::Numeric;
  195. }
  196. } else if (LH) {
  197. auto *ValueExpr = LH->getValue();
  198. if (ValueExpr) {
  199. llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
  200. ValueInt = ValueAPS.getSExtValue();
  201. }
  202. Option = LH->getOption();
  203. State = LH->getState();
  204. }
  205. switch (State) {
  206. case LoopHintAttr::Disable:
  207. switch (Option) {
  208. case LoopHintAttr::Vectorize:
  209. // Disable vectorization by specifying a width of 1.
  210. setVectorizeWidth(1);
  211. break;
  212. case LoopHintAttr::Interleave:
  213. // Disable interleaving by speciyfing a count of 1.
  214. setInterleaveCount(1);
  215. break;
  216. case LoopHintAttr::Unroll:
  217. setUnrollState(LoopAttributes::Disable);
  218. break;
  219. case LoopHintAttr::UnrollAndJam:
  220. setUnrollAndJamState(LoopAttributes::Disable);
  221. break;
  222. case LoopHintAttr::Distribute:
  223. setDistributeState(false);
  224. break;
  225. case LoopHintAttr::PipelineDisabled:
  226. setPipelineDisabled(true);
  227. break;
  228. case LoopHintAttr::UnrollCount:
  229. case LoopHintAttr::UnrollAndJamCount:
  230. case LoopHintAttr::VectorizeWidth:
  231. case LoopHintAttr::InterleaveCount:
  232. case LoopHintAttr::PipelineInitiationInterval:
  233. llvm_unreachable("Options cannot be disabled.");
  234. break;
  235. }
  236. break;
  237. case LoopHintAttr::Enable:
  238. switch (Option) {
  239. case LoopHintAttr::Vectorize:
  240. case LoopHintAttr::Interleave:
  241. setVectorizeEnable(true);
  242. break;
  243. case LoopHintAttr::Unroll:
  244. setUnrollState(LoopAttributes::Enable);
  245. break;
  246. case LoopHintAttr::UnrollAndJam:
  247. setUnrollAndJamState(LoopAttributes::Enable);
  248. break;
  249. case LoopHintAttr::Distribute:
  250. setDistributeState(true);
  251. break;
  252. case LoopHintAttr::UnrollCount:
  253. case LoopHintAttr::UnrollAndJamCount:
  254. case LoopHintAttr::VectorizeWidth:
  255. case LoopHintAttr::InterleaveCount:
  256. case LoopHintAttr::PipelineDisabled:
  257. case LoopHintAttr::PipelineInitiationInterval:
  258. llvm_unreachable("Options cannot enabled.");
  259. break;
  260. }
  261. break;
  262. case LoopHintAttr::AssumeSafety:
  263. switch (Option) {
  264. case LoopHintAttr::Vectorize:
  265. case LoopHintAttr::Interleave:
  266. // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
  267. setParallel(true);
  268. setVectorizeEnable(true);
  269. break;
  270. case LoopHintAttr::Unroll:
  271. case LoopHintAttr::UnrollAndJam:
  272. case LoopHintAttr::UnrollCount:
  273. case LoopHintAttr::UnrollAndJamCount:
  274. case LoopHintAttr::VectorizeWidth:
  275. case LoopHintAttr::InterleaveCount:
  276. case LoopHintAttr::Distribute:
  277. case LoopHintAttr::PipelineDisabled:
  278. case LoopHintAttr::PipelineInitiationInterval:
  279. llvm_unreachable("Options cannot be used to assume mem safety.");
  280. break;
  281. }
  282. break;
  283. case LoopHintAttr::Full:
  284. switch (Option) {
  285. case LoopHintAttr::Unroll:
  286. setUnrollState(LoopAttributes::Full);
  287. break;
  288. case LoopHintAttr::UnrollAndJam:
  289. setUnrollAndJamState(LoopAttributes::Full);
  290. break;
  291. case LoopHintAttr::Vectorize:
  292. case LoopHintAttr::Interleave:
  293. case LoopHintAttr::UnrollCount:
  294. case LoopHintAttr::UnrollAndJamCount:
  295. case LoopHintAttr::VectorizeWidth:
  296. case LoopHintAttr::InterleaveCount:
  297. case LoopHintAttr::Distribute:
  298. case LoopHintAttr::PipelineDisabled:
  299. case LoopHintAttr::PipelineInitiationInterval:
  300. llvm_unreachable("Options cannot be used with 'full' hint.");
  301. break;
  302. }
  303. break;
  304. case LoopHintAttr::Numeric:
  305. switch (Option) {
  306. case LoopHintAttr::VectorizeWidth:
  307. setVectorizeWidth(ValueInt);
  308. break;
  309. case LoopHintAttr::InterleaveCount:
  310. setInterleaveCount(ValueInt);
  311. break;
  312. case LoopHintAttr::UnrollCount:
  313. setUnrollCount(ValueInt);
  314. break;
  315. case LoopHintAttr::UnrollAndJamCount:
  316. setUnrollAndJamCount(ValueInt);
  317. break;
  318. case LoopHintAttr::PipelineInitiationInterval:
  319. setPipelineInitiationInterval(ValueInt);
  320. break;
  321. case LoopHintAttr::Unroll:
  322. case LoopHintAttr::UnrollAndJam:
  323. case LoopHintAttr::Vectorize:
  324. case LoopHintAttr::Interleave:
  325. case LoopHintAttr::Distribute:
  326. case LoopHintAttr::PipelineDisabled:
  327. llvm_unreachable("Options cannot be assigned a value.");
  328. break;
  329. }
  330. break;
  331. }
  332. }
  333. /// Stage the attributes.
  334. push(Header, StartLoc, EndLoc);
  335. }
  336. void LoopInfoStack::pop() {
  337. assert(!Active.empty() && "No active loops to pop");
  338. Active.pop_back();
  339. }
  340. void LoopInfoStack::InsertHelper(Instruction *I) const {
  341. if (I->mayReadOrWriteMemory()) {
  342. SmallVector<Metadata *, 4> AccessGroups;
  343. for (const LoopInfo &AL : Active) {
  344. // Here we assume that every loop that has an access group is parallel.
  345. if (MDNode *Group = AL.getAccessGroup())
  346. AccessGroups.push_back(Group);
  347. }
  348. MDNode *UnionMD = nullptr;
  349. if (AccessGroups.size() == 1)
  350. UnionMD = cast<MDNode>(AccessGroups[0]);
  351. else if (AccessGroups.size() >= 2)
  352. UnionMD = MDNode::get(I->getContext(), AccessGroups);
  353. I->setMetadata("llvm.access.group", UnionMD);
  354. }
  355. if (!hasInfo())
  356. return;
  357. const LoopInfo &L = getInfo();
  358. if (!L.getLoopID())
  359. return;
  360. if (I->isTerminator()) {
  361. for (BasicBlock *Succ : successors(I))
  362. if (Succ == L.getHeader()) {
  363. I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
  364. break;
  365. }
  366. return;
  367. }
  368. }