CGLoopInfo.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  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. MDNode *
  20. LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
  21. LLVMContext &Ctx = Header->getContext();
  22. SmallVector<Metadata *, 4> NewLoopProperties;
  23. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  24. NewLoopProperties.push_back(TempNode.get());
  25. NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  26. MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
  27. LoopID->replaceOperandWith(0, LoopID);
  28. return LoopID;
  29. }
  30. MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
  31. ArrayRef<Metadata *> LoopProperties,
  32. bool &HasUserTransforms) {
  33. LLVMContext &Ctx = Header->getContext();
  34. Optional<bool> Enabled;
  35. if (Attrs.PipelineDisabled)
  36. Enabled = false;
  37. else if (Attrs.PipelineInitiationInterval != 0)
  38. Enabled = true;
  39. if (Enabled != true) {
  40. SmallVector<Metadata *, 4> NewLoopProperties;
  41. if (Enabled == false) {
  42. NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  43. NewLoopProperties.push_back(
  44. MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
  45. ConstantAsMetadata::get(ConstantInt::get(
  46. llvm::Type::getInt1Ty(Ctx), 1))}));
  47. LoopProperties = NewLoopProperties;
  48. }
  49. return createLoopPropertiesMetadata(LoopProperties);
  50. }
  51. SmallVector<Metadata *, 4> Args;
  52. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  53. Args.push_back(TempNode.get());
  54. Args.append(LoopProperties.begin(), LoopProperties.end());
  55. if (Attrs.PipelineInitiationInterval > 0) {
  56. Metadata *Vals[] = {
  57. MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
  58. ConstantAsMetadata::get(ConstantInt::get(
  59. llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
  60. Args.push_back(MDNode::get(Ctx, Vals));
  61. }
  62. // No follow-up: This is the last transformation.
  63. MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
  64. LoopID->replaceOperandWith(0, LoopID);
  65. HasUserTransforms = true;
  66. return LoopID;
  67. }
  68. MDNode *
  69. LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
  70. ArrayRef<Metadata *> LoopProperties,
  71. bool &HasUserTransforms) {
  72. LLVMContext &Ctx = Header->getContext();
  73. Optional<bool> Enabled;
  74. if (Attrs.UnrollEnable == LoopAttributes::Disable)
  75. Enabled = false;
  76. else if (Attrs.UnrollEnable == LoopAttributes::Full)
  77. Enabled = None;
  78. else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
  79. Attrs.UnrollCount != 0)
  80. Enabled = true;
  81. if (Enabled != true) {
  82. // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
  83. // if unrolling is disabled.
  84. return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
  85. }
  86. SmallVector<Metadata *, 4> FollowupLoopProperties;
  87. // Apply all loop properties to the unrolled loop.
  88. FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  89. // Don't unroll an already unrolled loop.
  90. FollowupLoopProperties.push_back(
  91. MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
  92. bool FollowupHasTransforms = false;
  93. MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
  94. FollowupHasTransforms);
  95. SmallVector<Metadata *, 4> Args;
  96. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  97. Args.push_back(TempNode.get());
  98. Args.append(LoopProperties.begin(), LoopProperties.end());
  99. // Setting unroll.count
  100. if (Attrs.UnrollCount > 0) {
  101. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
  102. ConstantAsMetadata::get(ConstantInt::get(
  103. llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
  104. Args.push_back(MDNode::get(Ctx, Vals));
  105. }
  106. // Setting unroll.full or unroll.disable
  107. if (Attrs.UnrollEnable == LoopAttributes::Enable) {
  108. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
  109. Args.push_back(MDNode::get(Ctx, Vals));
  110. }
  111. if (FollowupHasTransforms)
  112. Args.push_back(MDNode::get(
  113. Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
  114. MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
  115. LoopID->replaceOperandWith(0, LoopID);
  116. HasUserTransforms = true;
  117. return LoopID;
  118. }
  119. MDNode *
  120. LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
  121. ArrayRef<Metadata *> LoopProperties,
  122. bool &HasUserTransforms) {
  123. LLVMContext &Ctx = Header->getContext();
  124. Optional<bool> Enabled;
  125. if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
  126. Enabled = false;
  127. else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
  128. Attrs.UnrollAndJamCount != 0)
  129. Enabled = true;
  130. if (Enabled != true) {
  131. SmallVector<Metadata *, 4> NewLoopProperties;
  132. if (Enabled == false) {
  133. NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  134. NewLoopProperties.push_back(MDNode::get(
  135. Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
  136. LoopProperties = NewLoopProperties;
  137. }
  138. return createPartialUnrollMetadata(Attrs, LoopProperties,
  139. HasUserTransforms);
  140. }
  141. SmallVector<Metadata *, 4> FollowupLoopProperties;
  142. FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  143. FollowupLoopProperties.push_back(
  144. MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
  145. bool FollowupHasTransforms = false;
  146. MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
  147. FollowupHasTransforms);
  148. SmallVector<Metadata *, 4> Args;
  149. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  150. Args.push_back(TempNode.get());
  151. Args.append(LoopProperties.begin(), LoopProperties.end());
  152. // Setting unroll_and_jam.count
  153. if (Attrs.UnrollAndJamCount > 0) {
  154. Metadata *Vals[] = {
  155. MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
  156. ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
  157. Attrs.UnrollAndJamCount))};
  158. Args.push_back(MDNode::get(Ctx, Vals));
  159. }
  160. if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
  161. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
  162. Args.push_back(MDNode::get(Ctx, Vals));
  163. }
  164. if (FollowupHasTransforms)
  165. Args.push_back(MDNode::get(
  166. Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
  167. Followup}));
  168. if (UnrollAndJamInnerFollowup)
  169. Args.push_back(MDNode::get(
  170. Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
  171. UnrollAndJamInnerFollowup}));
  172. MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
  173. LoopID->replaceOperandWith(0, LoopID);
  174. HasUserTransforms = true;
  175. return LoopID;
  176. }
  177. MDNode *
  178. LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
  179. ArrayRef<Metadata *> LoopProperties,
  180. bool &HasUserTransforms) {
  181. LLVMContext &Ctx = Header->getContext();
  182. Optional<bool> Enabled;
  183. if (Attrs.VectorizeEnable == LoopAttributes::Disable)
  184. Enabled = false;
  185. else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
  186. Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
  187. Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0)
  188. Enabled = true;
  189. if (Enabled != true) {
  190. SmallVector<Metadata *, 4> NewLoopProperties;
  191. if (Enabled == false) {
  192. NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  193. NewLoopProperties.push_back(
  194. MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
  195. ConstantAsMetadata::get(ConstantInt::get(
  196. llvm::Type::getInt1Ty(Ctx), 0))}));
  197. LoopProperties = NewLoopProperties;
  198. }
  199. return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
  200. }
  201. // Apply all loop properties to the vectorized loop.
  202. SmallVector<Metadata *, 4> FollowupLoopProperties;
  203. FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  204. // Don't vectorize an already vectorized loop.
  205. FollowupLoopProperties.push_back(
  206. MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
  207. bool FollowupHasTransforms = false;
  208. MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
  209. FollowupHasTransforms);
  210. SmallVector<Metadata *, 4> Args;
  211. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  212. Args.push_back(TempNode.get());
  213. Args.append(LoopProperties.begin(), LoopProperties.end());
  214. // Setting vectorize.predicate
  215. bool IsVectorPredicateEnabled = false;
  216. if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified &&
  217. Attrs.VectorizeEnable != LoopAttributes::Disable &&
  218. Attrs.VectorizeWidth < 1) {
  219. IsVectorPredicateEnabled =
  220. (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
  221. Metadata *Vals[] = {
  222. MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
  223. ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
  224. IsVectorPredicateEnabled))};
  225. Args.push_back(MDNode::get(Ctx, Vals));
  226. }
  227. // Setting vectorize.width
  228. if (Attrs.VectorizeWidth > 0) {
  229. // This implies vectorize.enable = true, but only add it when it is not
  230. // already enabled.
  231. if (Attrs.VectorizeEnable != LoopAttributes::Enable)
  232. Args.push_back(
  233. MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
  234. ConstantAsMetadata::get(ConstantInt::get(
  235. llvm::Type::getInt1Ty(Ctx), 1))}));
  236. Metadata *Vals[] = {
  237. MDString::get(Ctx, "llvm.loop.vectorize.width"),
  238. ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
  239. Attrs.VectorizeWidth))};
  240. Args.push_back(MDNode::get(Ctx, Vals));
  241. }
  242. // Setting interleave.count
  243. if (Attrs.InterleaveCount > 0) {
  244. Metadata *Vals[] = {
  245. MDString::get(Ctx, "llvm.loop.interleave.count"),
  246. ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
  247. Attrs.InterleaveCount))};
  248. Args.push_back(MDNode::get(Ctx, Vals));
  249. }
  250. // Setting vectorize.enable
  251. if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
  252. IsVectorPredicateEnabled) {
  253. Metadata *Vals[] = {
  254. MDString::get(Ctx, "llvm.loop.vectorize.enable"),
  255. ConstantAsMetadata::get(ConstantInt::get(
  256. llvm::Type::getInt1Ty(Ctx),
  257. IsVectorPredicateEnabled
  258. ? true
  259. : (Attrs.VectorizeEnable == LoopAttributes::Enable)))};
  260. Args.push_back(MDNode::get(Ctx, Vals));
  261. }
  262. if (FollowupHasTransforms)
  263. Args.push_back(MDNode::get(
  264. Ctx,
  265. {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
  266. MDNode *LoopID = MDNode::get(Ctx, Args);
  267. LoopID->replaceOperandWith(0, LoopID);
  268. HasUserTransforms = true;
  269. return LoopID;
  270. }
  271. MDNode *
  272. LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
  273. ArrayRef<Metadata *> LoopProperties,
  274. bool &HasUserTransforms) {
  275. LLVMContext &Ctx = Header->getContext();
  276. Optional<bool> Enabled;
  277. if (Attrs.DistributeEnable == LoopAttributes::Disable)
  278. Enabled = false;
  279. if (Attrs.DistributeEnable == LoopAttributes::Enable)
  280. Enabled = true;
  281. if (Enabled != true) {
  282. SmallVector<Metadata *, 4> NewLoopProperties;
  283. if (Enabled == false) {
  284. NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  285. NewLoopProperties.push_back(
  286. MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
  287. ConstantAsMetadata::get(ConstantInt::get(
  288. llvm::Type::getInt1Ty(Ctx), 0))}));
  289. LoopProperties = NewLoopProperties;
  290. }
  291. return createLoopVectorizeMetadata(Attrs, LoopProperties,
  292. HasUserTransforms);
  293. }
  294. bool FollowupHasTransforms = false;
  295. MDNode *Followup =
  296. createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
  297. SmallVector<Metadata *, 4> Args;
  298. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  299. Args.push_back(TempNode.get());
  300. Args.append(LoopProperties.begin(), LoopProperties.end());
  301. Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
  302. ConstantAsMetadata::get(ConstantInt::get(
  303. llvm::Type::getInt1Ty(Ctx),
  304. (Attrs.DistributeEnable == LoopAttributes::Enable)))};
  305. Args.push_back(MDNode::get(Ctx, Vals));
  306. if (FollowupHasTransforms)
  307. Args.push_back(MDNode::get(
  308. Ctx,
  309. {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
  310. MDNode *LoopID = MDNode::get(Ctx, Args);
  311. LoopID->replaceOperandWith(0, LoopID);
  312. HasUserTransforms = true;
  313. return LoopID;
  314. }
  315. MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
  316. ArrayRef<Metadata *> LoopProperties,
  317. bool &HasUserTransforms) {
  318. LLVMContext &Ctx = Header->getContext();
  319. Optional<bool> Enabled;
  320. if (Attrs.UnrollEnable == LoopAttributes::Disable)
  321. Enabled = false;
  322. else if (Attrs.UnrollEnable == LoopAttributes::Full)
  323. Enabled = true;
  324. if (Enabled != true) {
  325. SmallVector<Metadata *, 4> NewLoopProperties;
  326. if (Enabled == false) {
  327. NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
  328. NewLoopProperties.push_back(
  329. MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
  330. LoopProperties = NewLoopProperties;
  331. }
  332. return createLoopDistributeMetadata(Attrs, LoopProperties,
  333. HasUserTransforms);
  334. }
  335. SmallVector<Metadata *, 4> Args;
  336. TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
  337. Args.push_back(TempNode.get());
  338. Args.append(LoopProperties.begin(), LoopProperties.end());
  339. Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
  340. // No follow-up: there is no loop after full unrolling.
  341. // TODO: Warn if there are transformations after full unrolling.
  342. MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
  343. LoopID->replaceOperandWith(0, LoopID);
  344. HasUserTransforms = true;
  345. return LoopID;
  346. }
  347. MDNode *LoopInfo::createMetadata(
  348. const LoopAttributes &Attrs,
  349. llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
  350. bool &HasUserTransforms) {
  351. SmallVector<Metadata *, 3> LoopProperties;
  352. // If we have a valid start debug location for the loop, add it.
  353. if (StartLoc) {
  354. LoopProperties.push_back(StartLoc.getAsMDNode());
  355. // If we also have a valid end debug location for the loop, add it.
  356. if (EndLoc)
  357. LoopProperties.push_back(EndLoc.getAsMDNode());
  358. }
  359. assert(!!AccGroup == Attrs.IsParallel &&
  360. "There must be an access group iff the loop is parallel");
  361. if (Attrs.IsParallel) {
  362. LLVMContext &Ctx = Header->getContext();
  363. LoopProperties.push_back(MDNode::get(
  364. Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
  365. }
  366. LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
  367. AdditionalLoopProperties.end());
  368. return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
  369. }
  370. LoopAttributes::LoopAttributes(bool IsParallel)
  371. : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
  372. UnrollEnable(LoopAttributes::Unspecified),
  373. UnrollAndJamEnable(LoopAttributes::Unspecified),
  374. VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
  375. InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
  376. DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
  377. PipelineInitiationInterval(0) {}
  378. void LoopAttributes::clear() {
  379. IsParallel = false;
  380. VectorizeWidth = 0;
  381. InterleaveCount = 0;
  382. UnrollCount = 0;
  383. UnrollAndJamCount = 0;
  384. VectorizeEnable = LoopAttributes::Unspecified;
  385. UnrollEnable = LoopAttributes::Unspecified;
  386. UnrollAndJamEnable = LoopAttributes::Unspecified;
  387. VectorizePredicateEnable = LoopAttributes::Unspecified;
  388. DistributeEnable = LoopAttributes::Unspecified;
  389. PipelineDisabled = false;
  390. PipelineInitiationInterval = 0;
  391. }
  392. LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
  393. const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
  394. LoopInfo *Parent)
  395. : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
  396. Parent(Parent) {
  397. if (Attrs.IsParallel) {
  398. // Create an access group for this loop.
  399. LLVMContext &Ctx = Header->getContext();
  400. AccGroup = MDNode::getDistinct(Ctx, {});
  401. }
  402. if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
  403. Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
  404. Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
  405. Attrs.PipelineInitiationInterval == 0 &&
  406. Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
  407. Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
  408. Attrs.UnrollEnable == LoopAttributes::Unspecified &&
  409. Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
  410. Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
  411. !EndLoc)
  412. return;
  413. TempLoopID = MDNode::getTemporary(Header->getContext(), None);
  414. }
  415. void LoopInfo::finish() {
  416. // We did not annotate the loop body instructions because there are no
  417. // attributes for this loop.
  418. if (!TempLoopID)
  419. return;
  420. MDNode *LoopID;
  421. LoopAttributes CurLoopAttr = Attrs;
  422. LLVMContext &Ctx = Header->getContext();
  423. if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
  424. Parent->Attrs.UnrollAndJamCount != 0)) {
  425. // Parent unroll-and-jams this loop.
  426. // Split the transformations in those that happens before the unroll-and-jam
  427. // and those after.
  428. LoopAttributes BeforeJam, AfterJam;
  429. BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
  430. BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
  431. BeforeJam.InterleaveCount = Attrs.InterleaveCount;
  432. BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
  433. BeforeJam.DistributeEnable = Attrs.DistributeEnable;
  434. BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
  435. switch (Attrs.UnrollEnable) {
  436. case LoopAttributes::Unspecified:
  437. case LoopAttributes::Disable:
  438. BeforeJam.UnrollEnable = Attrs.UnrollEnable;
  439. AfterJam.UnrollEnable = Attrs.UnrollEnable;
  440. break;
  441. case LoopAttributes::Full:
  442. BeforeJam.UnrollEnable = LoopAttributes::Full;
  443. break;
  444. case LoopAttributes::Enable:
  445. AfterJam.UnrollEnable = LoopAttributes::Enable;
  446. break;
  447. }
  448. AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
  449. AfterJam.UnrollCount = Attrs.UnrollCount;
  450. AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
  451. AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
  452. // If this loop is subject of an unroll-and-jam by the parent loop, and has
  453. // an unroll-and-jam annotation itself, we have to decide whether to first
  454. // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
  455. // UnrollAndJam pass processes loops from inner to outer, so we apply the
  456. // inner first.
  457. BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
  458. BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
  459. // Set the inner followup metadata to process by the outer loop. Only
  460. // consider the first inner loop.
  461. if (!Parent->UnrollAndJamInnerFollowup) {
  462. // Splitting the attributes into a BeforeJam and an AfterJam part will
  463. // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
  464. // to be forwarded to the AfterJam part. We detect the situation here and
  465. // add it manually.
  466. SmallVector<Metadata *, 1> BeforeLoopProperties;
  467. if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
  468. BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
  469. BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0)
  470. BeforeLoopProperties.push_back(
  471. MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
  472. bool InnerFollowupHasTransform = false;
  473. MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
  474. InnerFollowupHasTransform);
  475. if (InnerFollowupHasTransform)
  476. Parent->UnrollAndJamInnerFollowup = InnerFollowup;
  477. }
  478. CurLoopAttr = BeforeJam;
  479. }
  480. bool HasUserTransforms = false;
  481. LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
  482. TempLoopID->replaceAllUsesWith(LoopID);
  483. }
  484. void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
  485. const llvm::DebugLoc &EndLoc) {
  486. Active.emplace_back(
  487. new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
  488. Active.empty() ? nullptr : Active.back().get()));
  489. // Clear the attributes so nested loops do not inherit them.
  490. StagedAttrs.clear();
  491. }
  492. void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
  493. ArrayRef<const clang::Attr *> Attrs,
  494. const llvm::DebugLoc &StartLoc,
  495. const llvm::DebugLoc &EndLoc) {
  496. // Identify loop hint attributes from Attrs.
  497. for (const auto *Attr : Attrs) {
  498. const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
  499. const OpenCLUnrollHintAttr *OpenCLHint =
  500. dyn_cast<OpenCLUnrollHintAttr>(Attr);
  501. // Skip non loop hint attributes
  502. if (!LH && !OpenCLHint) {
  503. continue;
  504. }
  505. LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
  506. LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
  507. unsigned ValueInt = 1;
  508. // Translate opencl_unroll_hint attribute argument to
  509. // equivalent LoopHintAttr enums.
  510. // OpenCL v2.0 s6.11.5:
  511. // 0 - enable unroll (no argument).
  512. // 1 - disable unroll.
  513. // other positive integer n - unroll by n.
  514. if (OpenCLHint) {
  515. ValueInt = OpenCLHint->getUnrollHint();
  516. if (ValueInt == 0) {
  517. State = LoopHintAttr::Enable;
  518. } else if (ValueInt != 1) {
  519. Option = LoopHintAttr::UnrollCount;
  520. State = LoopHintAttr::Numeric;
  521. }
  522. } else if (LH) {
  523. auto *ValueExpr = LH->getValue();
  524. if (ValueExpr) {
  525. llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
  526. ValueInt = ValueAPS.getSExtValue();
  527. }
  528. Option = LH->getOption();
  529. State = LH->getState();
  530. }
  531. switch (State) {
  532. case LoopHintAttr::Disable:
  533. switch (Option) {
  534. case LoopHintAttr::Vectorize:
  535. // Disable vectorization by specifying a width of 1.
  536. setVectorizeWidth(1);
  537. break;
  538. case LoopHintAttr::Interleave:
  539. // Disable interleaving by speciyfing a count of 1.
  540. setInterleaveCount(1);
  541. break;
  542. case LoopHintAttr::Unroll:
  543. setUnrollState(LoopAttributes::Disable);
  544. break;
  545. case LoopHintAttr::UnrollAndJam:
  546. setUnrollAndJamState(LoopAttributes::Disable);
  547. break;
  548. case LoopHintAttr::VectorizePredicate:
  549. setVectorizePredicateState(LoopAttributes::Disable);
  550. break;
  551. case LoopHintAttr::Distribute:
  552. setDistributeState(false);
  553. break;
  554. case LoopHintAttr::PipelineDisabled:
  555. setPipelineDisabled(true);
  556. break;
  557. case LoopHintAttr::UnrollCount:
  558. case LoopHintAttr::UnrollAndJamCount:
  559. case LoopHintAttr::VectorizeWidth:
  560. case LoopHintAttr::InterleaveCount:
  561. case LoopHintAttr::PipelineInitiationInterval:
  562. llvm_unreachable("Options cannot be disabled.");
  563. break;
  564. }
  565. break;
  566. case LoopHintAttr::Enable:
  567. switch (Option) {
  568. case LoopHintAttr::Vectorize:
  569. case LoopHintAttr::Interleave:
  570. setVectorizeEnable(true);
  571. break;
  572. case LoopHintAttr::Unroll:
  573. setUnrollState(LoopAttributes::Enable);
  574. break;
  575. case LoopHintAttr::UnrollAndJam:
  576. setUnrollAndJamState(LoopAttributes::Enable);
  577. break;
  578. case LoopHintAttr::VectorizePredicate:
  579. setVectorizePredicateState(LoopAttributes::Enable);
  580. break;
  581. case LoopHintAttr::Distribute:
  582. setDistributeState(true);
  583. break;
  584. case LoopHintAttr::UnrollCount:
  585. case LoopHintAttr::UnrollAndJamCount:
  586. case LoopHintAttr::VectorizeWidth:
  587. case LoopHintAttr::InterleaveCount:
  588. case LoopHintAttr::PipelineDisabled:
  589. case LoopHintAttr::PipelineInitiationInterval:
  590. llvm_unreachable("Options cannot enabled.");
  591. break;
  592. }
  593. break;
  594. case LoopHintAttr::AssumeSafety:
  595. switch (Option) {
  596. case LoopHintAttr::Vectorize:
  597. case LoopHintAttr::Interleave:
  598. // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
  599. setParallel(true);
  600. setVectorizeEnable(true);
  601. break;
  602. case LoopHintAttr::Unroll:
  603. case LoopHintAttr::UnrollAndJam:
  604. case LoopHintAttr::VectorizePredicate:
  605. case LoopHintAttr::UnrollCount:
  606. case LoopHintAttr::UnrollAndJamCount:
  607. case LoopHintAttr::VectorizeWidth:
  608. case LoopHintAttr::InterleaveCount:
  609. case LoopHintAttr::Distribute:
  610. case LoopHintAttr::PipelineDisabled:
  611. case LoopHintAttr::PipelineInitiationInterval:
  612. llvm_unreachable("Options cannot be used to assume mem safety.");
  613. break;
  614. }
  615. break;
  616. case LoopHintAttr::Full:
  617. switch (Option) {
  618. case LoopHintAttr::Unroll:
  619. setUnrollState(LoopAttributes::Full);
  620. break;
  621. case LoopHintAttr::UnrollAndJam:
  622. setUnrollAndJamState(LoopAttributes::Full);
  623. break;
  624. case LoopHintAttr::Vectorize:
  625. case LoopHintAttr::Interleave:
  626. case LoopHintAttr::UnrollCount:
  627. case LoopHintAttr::UnrollAndJamCount:
  628. case LoopHintAttr::VectorizeWidth:
  629. case LoopHintAttr::InterleaveCount:
  630. case LoopHintAttr::Distribute:
  631. case LoopHintAttr::PipelineDisabled:
  632. case LoopHintAttr::PipelineInitiationInterval:
  633. case LoopHintAttr::VectorizePredicate:
  634. llvm_unreachable("Options cannot be used with 'full' hint.");
  635. break;
  636. }
  637. break;
  638. case LoopHintAttr::Numeric:
  639. switch (Option) {
  640. case LoopHintAttr::VectorizeWidth:
  641. setVectorizeWidth(ValueInt);
  642. break;
  643. case LoopHintAttr::InterleaveCount:
  644. setInterleaveCount(ValueInt);
  645. break;
  646. case LoopHintAttr::UnrollCount:
  647. setUnrollCount(ValueInt);
  648. break;
  649. case LoopHintAttr::UnrollAndJamCount:
  650. setUnrollAndJamCount(ValueInt);
  651. break;
  652. case LoopHintAttr::PipelineInitiationInterval:
  653. setPipelineInitiationInterval(ValueInt);
  654. break;
  655. case LoopHintAttr::Unroll:
  656. case LoopHintAttr::UnrollAndJam:
  657. case LoopHintAttr::VectorizePredicate:
  658. case LoopHintAttr::Vectorize:
  659. case LoopHintAttr::Interleave:
  660. case LoopHintAttr::Distribute:
  661. case LoopHintAttr::PipelineDisabled:
  662. llvm_unreachable("Options cannot be assigned a value.");
  663. break;
  664. }
  665. break;
  666. }
  667. }
  668. /// Stage the attributes.
  669. push(Header, StartLoc, EndLoc);
  670. }
  671. void LoopInfoStack::pop() {
  672. assert(!Active.empty() && "No active loops to pop");
  673. Active.back()->finish();
  674. Active.pop_back();
  675. }
  676. void LoopInfoStack::InsertHelper(Instruction *I) const {
  677. if (I->mayReadOrWriteMemory()) {
  678. SmallVector<Metadata *, 4> AccessGroups;
  679. for (const auto &AL : Active) {
  680. // Here we assume that every loop that has an access group is parallel.
  681. if (MDNode *Group = AL->getAccessGroup())
  682. AccessGroups.push_back(Group);
  683. }
  684. MDNode *UnionMD = nullptr;
  685. if (AccessGroups.size() == 1)
  686. UnionMD = cast<MDNode>(AccessGroups[0]);
  687. else if (AccessGroups.size() >= 2)
  688. UnionMD = MDNode::get(I->getContext(), AccessGroups);
  689. I->setMetadata("llvm.access.group", UnionMD);
  690. }
  691. if (!hasInfo())
  692. return;
  693. const LoopInfo &L = getInfo();
  694. if (!L.getLoopID())
  695. return;
  696. if (I->isTerminator()) {
  697. for (BasicBlock *Succ : successors(I))
  698. if (Succ == L.getHeader()) {
  699. I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
  700. break;
  701. }
  702. return;
  703. }
  704. }