xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/CGLoopInfo.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg 
97330f729Sjoerg #include "CGLoopInfo.h"
107330f729Sjoerg #include "clang/AST/ASTContext.h"
117330f729Sjoerg #include "clang/AST/Attr.h"
12*e038c9c4Sjoerg #include "clang/AST/Expr.h"
13*e038c9c4Sjoerg #include "clang/Basic/CodeGenOptions.h"
147330f729Sjoerg #include "llvm/IR/BasicBlock.h"
157330f729Sjoerg #include "llvm/IR/CFG.h"
167330f729Sjoerg #include "llvm/IR/Constants.h"
177330f729Sjoerg #include "llvm/IR/InstrTypes.h"
187330f729Sjoerg #include "llvm/IR/Instructions.h"
197330f729Sjoerg #include "llvm/IR/Metadata.h"
207330f729Sjoerg using namespace clang::CodeGen;
217330f729Sjoerg using namespace llvm;
227330f729Sjoerg 
237330f729Sjoerg MDNode *
createLoopPropertiesMetadata(ArrayRef<Metadata * > LoopProperties)247330f729Sjoerg LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
257330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
267330f729Sjoerg   SmallVector<Metadata *, 4> NewLoopProperties;
27*e038c9c4Sjoerg   NewLoopProperties.push_back(nullptr);
287330f729Sjoerg   NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
297330f729Sjoerg 
307330f729Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
317330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
327330f729Sjoerg   return LoopID;
337330f729Sjoerg }
347330f729Sjoerg 
createPipeliningMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)357330f729Sjoerg MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
367330f729Sjoerg                                            ArrayRef<Metadata *> LoopProperties,
377330f729Sjoerg                                            bool &HasUserTransforms) {
387330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
397330f729Sjoerg 
407330f729Sjoerg   Optional<bool> Enabled;
417330f729Sjoerg   if (Attrs.PipelineDisabled)
427330f729Sjoerg     Enabled = false;
437330f729Sjoerg   else if (Attrs.PipelineInitiationInterval != 0)
447330f729Sjoerg     Enabled = true;
457330f729Sjoerg 
467330f729Sjoerg   if (Enabled != true) {
477330f729Sjoerg     SmallVector<Metadata *, 4> NewLoopProperties;
487330f729Sjoerg     if (Enabled == false) {
497330f729Sjoerg       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
507330f729Sjoerg       NewLoopProperties.push_back(
517330f729Sjoerg           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
527330f729Sjoerg                             ConstantAsMetadata::get(ConstantInt::get(
537330f729Sjoerg                                 llvm::Type::getInt1Ty(Ctx), 1))}));
547330f729Sjoerg       LoopProperties = NewLoopProperties;
557330f729Sjoerg     }
567330f729Sjoerg     return createLoopPropertiesMetadata(LoopProperties);
577330f729Sjoerg   }
587330f729Sjoerg 
597330f729Sjoerg   SmallVector<Metadata *, 4> Args;
60*e038c9c4Sjoerg   Args.push_back(nullptr);
617330f729Sjoerg   Args.append(LoopProperties.begin(), LoopProperties.end());
627330f729Sjoerg 
637330f729Sjoerg   if (Attrs.PipelineInitiationInterval > 0) {
647330f729Sjoerg     Metadata *Vals[] = {
657330f729Sjoerg         MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
667330f729Sjoerg         ConstantAsMetadata::get(ConstantInt::get(
677330f729Sjoerg             llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
687330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
697330f729Sjoerg   }
707330f729Sjoerg 
717330f729Sjoerg   // No follow-up: This is the last transformation.
727330f729Sjoerg 
737330f729Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
747330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
757330f729Sjoerg   HasUserTransforms = true;
767330f729Sjoerg   return LoopID;
777330f729Sjoerg }
787330f729Sjoerg 
797330f729Sjoerg MDNode *
createPartialUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)807330f729Sjoerg LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
817330f729Sjoerg                                       ArrayRef<Metadata *> LoopProperties,
827330f729Sjoerg                                       bool &HasUserTransforms) {
837330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
847330f729Sjoerg 
857330f729Sjoerg   Optional<bool> Enabled;
867330f729Sjoerg   if (Attrs.UnrollEnable == LoopAttributes::Disable)
877330f729Sjoerg     Enabled = false;
887330f729Sjoerg   else if (Attrs.UnrollEnable == LoopAttributes::Full)
897330f729Sjoerg     Enabled = None;
907330f729Sjoerg   else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
917330f729Sjoerg            Attrs.UnrollCount != 0)
927330f729Sjoerg     Enabled = true;
937330f729Sjoerg 
947330f729Sjoerg   if (Enabled != true) {
957330f729Sjoerg     // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
967330f729Sjoerg     // if unrolling is disabled.
977330f729Sjoerg     return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
987330f729Sjoerg   }
997330f729Sjoerg 
1007330f729Sjoerg   SmallVector<Metadata *, 4> FollowupLoopProperties;
1017330f729Sjoerg 
1027330f729Sjoerg   // Apply all loop properties to the unrolled loop.
1037330f729Sjoerg   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
1047330f729Sjoerg 
1057330f729Sjoerg   // Don't unroll an already unrolled loop.
1067330f729Sjoerg   FollowupLoopProperties.push_back(
1077330f729Sjoerg       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
1087330f729Sjoerg 
1097330f729Sjoerg   bool FollowupHasTransforms = false;
1107330f729Sjoerg   MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
1117330f729Sjoerg                                               FollowupHasTransforms);
1127330f729Sjoerg 
1137330f729Sjoerg   SmallVector<Metadata *, 4> Args;
114*e038c9c4Sjoerg   Args.push_back(nullptr);
1157330f729Sjoerg   Args.append(LoopProperties.begin(), LoopProperties.end());
1167330f729Sjoerg 
1177330f729Sjoerg   // Setting unroll.count
1187330f729Sjoerg   if (Attrs.UnrollCount > 0) {
1197330f729Sjoerg     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
1207330f729Sjoerg                         ConstantAsMetadata::get(ConstantInt::get(
1217330f729Sjoerg                             llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
1227330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
1237330f729Sjoerg   }
1247330f729Sjoerg 
1257330f729Sjoerg   // Setting unroll.full or unroll.disable
1267330f729Sjoerg   if (Attrs.UnrollEnable == LoopAttributes::Enable) {
1277330f729Sjoerg     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
1287330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
1297330f729Sjoerg   }
1307330f729Sjoerg 
1317330f729Sjoerg   if (FollowupHasTransforms)
1327330f729Sjoerg     Args.push_back(MDNode::get(
1337330f729Sjoerg         Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
1347330f729Sjoerg 
1357330f729Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
1367330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
1377330f729Sjoerg   HasUserTransforms = true;
1387330f729Sjoerg   return LoopID;
1397330f729Sjoerg }
1407330f729Sjoerg 
1417330f729Sjoerg MDNode *
createUnrollAndJamMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)1427330f729Sjoerg LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
1437330f729Sjoerg                                      ArrayRef<Metadata *> LoopProperties,
1447330f729Sjoerg                                      bool &HasUserTransforms) {
1457330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
1467330f729Sjoerg 
1477330f729Sjoerg   Optional<bool> Enabled;
1487330f729Sjoerg   if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
1497330f729Sjoerg     Enabled = false;
1507330f729Sjoerg   else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
1517330f729Sjoerg            Attrs.UnrollAndJamCount != 0)
1527330f729Sjoerg     Enabled = true;
1537330f729Sjoerg 
1547330f729Sjoerg   if (Enabled != true) {
1557330f729Sjoerg     SmallVector<Metadata *, 4> NewLoopProperties;
1567330f729Sjoerg     if (Enabled == false) {
1577330f729Sjoerg       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
1587330f729Sjoerg       NewLoopProperties.push_back(MDNode::get(
1597330f729Sjoerg           Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
1607330f729Sjoerg       LoopProperties = NewLoopProperties;
1617330f729Sjoerg     }
1627330f729Sjoerg     return createPartialUnrollMetadata(Attrs, LoopProperties,
1637330f729Sjoerg                                        HasUserTransforms);
1647330f729Sjoerg   }
1657330f729Sjoerg 
1667330f729Sjoerg   SmallVector<Metadata *, 4> FollowupLoopProperties;
1677330f729Sjoerg   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
1687330f729Sjoerg   FollowupLoopProperties.push_back(
1697330f729Sjoerg       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
1707330f729Sjoerg 
1717330f729Sjoerg   bool FollowupHasTransforms = false;
1727330f729Sjoerg   MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
1737330f729Sjoerg                                                  FollowupHasTransforms);
1747330f729Sjoerg 
1757330f729Sjoerg   SmallVector<Metadata *, 4> Args;
176*e038c9c4Sjoerg   Args.push_back(nullptr);
1777330f729Sjoerg   Args.append(LoopProperties.begin(), LoopProperties.end());
1787330f729Sjoerg 
1797330f729Sjoerg   // Setting unroll_and_jam.count
1807330f729Sjoerg   if (Attrs.UnrollAndJamCount > 0) {
1817330f729Sjoerg     Metadata *Vals[] = {
1827330f729Sjoerg         MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
1837330f729Sjoerg         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
1847330f729Sjoerg                                                  Attrs.UnrollAndJamCount))};
1857330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
1867330f729Sjoerg   }
1877330f729Sjoerg 
1887330f729Sjoerg   if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
1897330f729Sjoerg     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
1907330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
1917330f729Sjoerg   }
1927330f729Sjoerg 
1937330f729Sjoerg   if (FollowupHasTransforms)
1947330f729Sjoerg     Args.push_back(MDNode::get(
1957330f729Sjoerg         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
1967330f729Sjoerg               Followup}));
1977330f729Sjoerg 
1987330f729Sjoerg   if (UnrollAndJamInnerFollowup)
1997330f729Sjoerg     Args.push_back(MDNode::get(
2007330f729Sjoerg         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
2017330f729Sjoerg               UnrollAndJamInnerFollowup}));
2027330f729Sjoerg 
2037330f729Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
2047330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
2057330f729Sjoerg   HasUserTransforms = true;
2067330f729Sjoerg   return LoopID;
2077330f729Sjoerg }
2087330f729Sjoerg 
2097330f729Sjoerg MDNode *
createLoopVectorizeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)2107330f729Sjoerg LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
2117330f729Sjoerg                                       ArrayRef<Metadata *> LoopProperties,
2127330f729Sjoerg                                       bool &HasUserTransforms) {
2137330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
2147330f729Sjoerg 
2157330f729Sjoerg   Optional<bool> Enabled;
2167330f729Sjoerg   if (Attrs.VectorizeEnable == LoopAttributes::Disable)
2177330f729Sjoerg     Enabled = false;
2187330f729Sjoerg   else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
2197330f729Sjoerg            Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
220*e038c9c4Sjoerg            Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
221*e038c9c4Sjoerg            Attrs.VectorizeScalable != LoopAttributes::Unspecified)
2227330f729Sjoerg     Enabled = true;
2237330f729Sjoerg 
2247330f729Sjoerg   if (Enabled != true) {
2257330f729Sjoerg     SmallVector<Metadata *, 4> NewLoopProperties;
2267330f729Sjoerg     if (Enabled == false) {
2277330f729Sjoerg       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
2287330f729Sjoerg       NewLoopProperties.push_back(
2297330f729Sjoerg           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
2307330f729Sjoerg                             ConstantAsMetadata::get(ConstantInt::get(
2317330f729Sjoerg                                 llvm::Type::getInt1Ty(Ctx), 0))}));
2327330f729Sjoerg       LoopProperties = NewLoopProperties;
2337330f729Sjoerg     }
2347330f729Sjoerg     return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
2357330f729Sjoerg   }
2367330f729Sjoerg 
2377330f729Sjoerg   // Apply all loop properties to the vectorized loop.
2387330f729Sjoerg   SmallVector<Metadata *, 4> FollowupLoopProperties;
2397330f729Sjoerg   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
2407330f729Sjoerg 
2417330f729Sjoerg   // Don't vectorize an already vectorized loop.
2427330f729Sjoerg   FollowupLoopProperties.push_back(
2437330f729Sjoerg       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
2447330f729Sjoerg 
2457330f729Sjoerg   bool FollowupHasTransforms = false;
2467330f729Sjoerg   MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
2477330f729Sjoerg                                                 FollowupHasTransforms);
2487330f729Sjoerg 
2497330f729Sjoerg   SmallVector<Metadata *, 4> Args;
250*e038c9c4Sjoerg   Args.push_back(nullptr);
2517330f729Sjoerg   Args.append(LoopProperties.begin(), LoopProperties.end());
2527330f729Sjoerg 
253*e038c9c4Sjoerg   // Setting vectorize.predicate when it has been specified and vectorization
254*e038c9c4Sjoerg   // has not been disabled.
2557330f729Sjoerg   bool IsVectorPredicateEnabled = false;
256*e038c9c4Sjoerg   if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {
2577330f729Sjoerg     IsVectorPredicateEnabled =
2587330f729Sjoerg         (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
2597330f729Sjoerg 
2607330f729Sjoerg     Metadata *Vals[] = {
2617330f729Sjoerg         MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
2627330f729Sjoerg         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
2637330f729Sjoerg                                                  IsVectorPredicateEnabled))};
2647330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
2657330f729Sjoerg   }
2667330f729Sjoerg 
2677330f729Sjoerg   // Setting vectorize.width
2687330f729Sjoerg   if (Attrs.VectorizeWidth > 0) {
2697330f729Sjoerg     Metadata *Vals[] = {
2707330f729Sjoerg         MDString::get(Ctx, "llvm.loop.vectorize.width"),
2717330f729Sjoerg         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
2727330f729Sjoerg                                                  Attrs.VectorizeWidth))};
273*e038c9c4Sjoerg 
274*e038c9c4Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
275*e038c9c4Sjoerg   }
276*e038c9c4Sjoerg 
277*e038c9c4Sjoerg   if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {
278*e038c9c4Sjoerg     bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
279*e038c9c4Sjoerg     Metadata *Vals[] = {
280*e038c9c4Sjoerg         MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
281*e038c9c4Sjoerg         ConstantAsMetadata::get(
282*e038c9c4Sjoerg             ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
2837330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
2847330f729Sjoerg   }
2857330f729Sjoerg 
2867330f729Sjoerg   // Setting interleave.count
2877330f729Sjoerg   if (Attrs.InterleaveCount > 0) {
2887330f729Sjoerg     Metadata *Vals[] = {
2897330f729Sjoerg         MDString::get(Ctx, "llvm.loop.interleave.count"),
2907330f729Sjoerg         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
2917330f729Sjoerg                                                  Attrs.InterleaveCount))};
2927330f729Sjoerg     Args.push_back(MDNode::get(Ctx, Vals));
2937330f729Sjoerg   }
2947330f729Sjoerg 
295*e038c9c4Sjoerg   // vectorize.enable is set if:
296*e038c9c4Sjoerg   // 1) loop hint vectorize.enable is set, or
297*e038c9c4Sjoerg   // 2) it is implied when vectorize.predicate is set, or
298*e038c9c4Sjoerg   // 3) it is implied when vectorize.width is set to a value > 1
299*e038c9c4Sjoerg   // 4) it is implied when vectorize.scalable.enable is true
300*e038c9c4Sjoerg   // 5) it is implied when vectorize.width is unset (0) and the user
301*e038c9c4Sjoerg   //    explicitly requested fixed-width vectorization, i.e.
302*e038c9c4Sjoerg   //    vectorize.scalable.enable is false.
3037330f729Sjoerg   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
304*e038c9c4Sjoerg       (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
305*e038c9c4Sjoerg       Attrs.VectorizeWidth > 1 ||
306*e038c9c4Sjoerg       Attrs.VectorizeScalable == LoopAttributes::Enable ||
307*e038c9c4Sjoerg       (Attrs.VectorizeScalable == LoopAttributes::Disable &&
308*e038c9c4Sjoerg        Attrs.VectorizeWidth != 1)) {
309*e038c9c4Sjoerg     bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
310*e038c9c4Sjoerg     Args.push_back(
311*e038c9c4Sjoerg         MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
3127330f729Sjoerg                           ConstantAsMetadata::get(ConstantInt::get(
313*e038c9c4Sjoerg                               llvm::Type::getInt1Ty(Ctx), AttrVal))}));
3147330f729Sjoerg   }
3157330f729Sjoerg 
3167330f729Sjoerg   if (FollowupHasTransforms)
3177330f729Sjoerg     Args.push_back(MDNode::get(
3187330f729Sjoerg         Ctx,
3197330f729Sjoerg         {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
3207330f729Sjoerg 
321*e038c9c4Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
3227330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
3237330f729Sjoerg   HasUserTransforms = true;
3247330f729Sjoerg   return LoopID;
3257330f729Sjoerg }
3267330f729Sjoerg 
3277330f729Sjoerg MDNode *
createLoopDistributeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)3287330f729Sjoerg LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
3297330f729Sjoerg                                        ArrayRef<Metadata *> LoopProperties,
3307330f729Sjoerg                                        bool &HasUserTransforms) {
3317330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
3327330f729Sjoerg 
3337330f729Sjoerg   Optional<bool> Enabled;
3347330f729Sjoerg   if (Attrs.DistributeEnable == LoopAttributes::Disable)
3357330f729Sjoerg     Enabled = false;
3367330f729Sjoerg   if (Attrs.DistributeEnable == LoopAttributes::Enable)
3377330f729Sjoerg     Enabled = true;
3387330f729Sjoerg 
3397330f729Sjoerg   if (Enabled != true) {
3407330f729Sjoerg     SmallVector<Metadata *, 4> NewLoopProperties;
3417330f729Sjoerg     if (Enabled == false) {
3427330f729Sjoerg       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
3437330f729Sjoerg       NewLoopProperties.push_back(
3447330f729Sjoerg           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
3457330f729Sjoerg                             ConstantAsMetadata::get(ConstantInt::get(
3467330f729Sjoerg                                 llvm::Type::getInt1Ty(Ctx), 0))}));
3477330f729Sjoerg       LoopProperties = NewLoopProperties;
3487330f729Sjoerg     }
3497330f729Sjoerg     return createLoopVectorizeMetadata(Attrs, LoopProperties,
3507330f729Sjoerg                                        HasUserTransforms);
3517330f729Sjoerg   }
3527330f729Sjoerg 
3537330f729Sjoerg   bool FollowupHasTransforms = false;
3547330f729Sjoerg   MDNode *Followup =
3557330f729Sjoerg       createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
3567330f729Sjoerg 
3577330f729Sjoerg   SmallVector<Metadata *, 4> Args;
358*e038c9c4Sjoerg   Args.push_back(nullptr);
3597330f729Sjoerg   Args.append(LoopProperties.begin(), LoopProperties.end());
3607330f729Sjoerg 
3617330f729Sjoerg   Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
3627330f729Sjoerg                       ConstantAsMetadata::get(ConstantInt::get(
3637330f729Sjoerg                           llvm::Type::getInt1Ty(Ctx),
3647330f729Sjoerg                           (Attrs.DistributeEnable == LoopAttributes::Enable)))};
3657330f729Sjoerg   Args.push_back(MDNode::get(Ctx, Vals));
3667330f729Sjoerg 
3677330f729Sjoerg   if (FollowupHasTransforms)
3687330f729Sjoerg     Args.push_back(MDNode::get(
3697330f729Sjoerg         Ctx,
3707330f729Sjoerg         {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
3717330f729Sjoerg 
372*e038c9c4Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
3737330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
3747330f729Sjoerg   HasUserTransforms = true;
3757330f729Sjoerg   return LoopID;
3767330f729Sjoerg }
3777330f729Sjoerg 
createFullUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)3787330f729Sjoerg MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
3797330f729Sjoerg                                            ArrayRef<Metadata *> LoopProperties,
3807330f729Sjoerg                                            bool &HasUserTransforms) {
3817330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
3827330f729Sjoerg 
3837330f729Sjoerg   Optional<bool> Enabled;
3847330f729Sjoerg   if (Attrs.UnrollEnable == LoopAttributes::Disable)
3857330f729Sjoerg     Enabled = false;
3867330f729Sjoerg   else if (Attrs.UnrollEnable == LoopAttributes::Full)
3877330f729Sjoerg     Enabled = true;
3887330f729Sjoerg 
3897330f729Sjoerg   if (Enabled != true) {
3907330f729Sjoerg     SmallVector<Metadata *, 4> NewLoopProperties;
3917330f729Sjoerg     if (Enabled == false) {
3927330f729Sjoerg       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
3937330f729Sjoerg       NewLoopProperties.push_back(
3947330f729Sjoerg           MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
3957330f729Sjoerg       LoopProperties = NewLoopProperties;
3967330f729Sjoerg     }
3977330f729Sjoerg     return createLoopDistributeMetadata(Attrs, LoopProperties,
3987330f729Sjoerg                                         HasUserTransforms);
3997330f729Sjoerg   }
4007330f729Sjoerg 
4017330f729Sjoerg   SmallVector<Metadata *, 4> Args;
402*e038c9c4Sjoerg   Args.push_back(nullptr);
4037330f729Sjoerg   Args.append(LoopProperties.begin(), LoopProperties.end());
4047330f729Sjoerg   Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
4057330f729Sjoerg 
4067330f729Sjoerg   // No follow-up: there is no loop after full unrolling.
4077330f729Sjoerg   // TODO: Warn if there are transformations after full unrolling.
4087330f729Sjoerg 
4097330f729Sjoerg   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
4107330f729Sjoerg   LoopID->replaceOperandWith(0, LoopID);
4117330f729Sjoerg   HasUserTransforms = true;
4127330f729Sjoerg   return LoopID;
4137330f729Sjoerg }
4147330f729Sjoerg 
createMetadata(const LoopAttributes & Attrs,llvm::ArrayRef<llvm::Metadata * > AdditionalLoopProperties,bool & HasUserTransforms)4157330f729Sjoerg MDNode *LoopInfo::createMetadata(
4167330f729Sjoerg     const LoopAttributes &Attrs,
4177330f729Sjoerg     llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
4187330f729Sjoerg     bool &HasUserTransforms) {
4197330f729Sjoerg   SmallVector<Metadata *, 3> LoopProperties;
4207330f729Sjoerg 
4217330f729Sjoerg   // If we have a valid start debug location for the loop, add it.
4227330f729Sjoerg   if (StartLoc) {
4237330f729Sjoerg     LoopProperties.push_back(StartLoc.getAsMDNode());
4247330f729Sjoerg 
4257330f729Sjoerg     // If we also have a valid end debug location for the loop, add it.
4267330f729Sjoerg     if (EndLoc)
4277330f729Sjoerg       LoopProperties.push_back(EndLoc.getAsMDNode());
4287330f729Sjoerg   }
4297330f729Sjoerg 
430*e038c9c4Sjoerg   LLVMContext &Ctx = Header->getContext();
431*e038c9c4Sjoerg   if (Attrs.MustProgress)
432*e038c9c4Sjoerg     LoopProperties.push_back(
433*e038c9c4Sjoerg         MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
434*e038c9c4Sjoerg 
4357330f729Sjoerg   assert(!!AccGroup == Attrs.IsParallel &&
4367330f729Sjoerg          "There must be an access group iff the loop is parallel");
4377330f729Sjoerg   if (Attrs.IsParallel) {
4387330f729Sjoerg     LoopProperties.push_back(MDNode::get(
4397330f729Sjoerg         Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
4407330f729Sjoerg   }
4417330f729Sjoerg 
4427330f729Sjoerg   LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
4437330f729Sjoerg                         AdditionalLoopProperties.end());
4447330f729Sjoerg   return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
4457330f729Sjoerg }
4467330f729Sjoerg 
LoopAttributes(bool IsParallel)4477330f729Sjoerg LoopAttributes::LoopAttributes(bool IsParallel)
4487330f729Sjoerg     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
4497330f729Sjoerg       UnrollEnable(LoopAttributes::Unspecified),
4507330f729Sjoerg       UnrollAndJamEnable(LoopAttributes::Unspecified),
4517330f729Sjoerg       VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
452*e038c9c4Sjoerg       VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
453*e038c9c4Sjoerg       UnrollCount(0), UnrollAndJamCount(0),
4547330f729Sjoerg       DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
455*e038c9c4Sjoerg       PipelineInitiationInterval(0), MustProgress(false) {}
4567330f729Sjoerg 
clear()4577330f729Sjoerg void LoopAttributes::clear() {
4587330f729Sjoerg   IsParallel = false;
4597330f729Sjoerg   VectorizeWidth = 0;
460*e038c9c4Sjoerg   VectorizeScalable = LoopAttributes::Unspecified;
4617330f729Sjoerg   InterleaveCount = 0;
4627330f729Sjoerg   UnrollCount = 0;
4637330f729Sjoerg   UnrollAndJamCount = 0;
4647330f729Sjoerg   VectorizeEnable = LoopAttributes::Unspecified;
4657330f729Sjoerg   UnrollEnable = LoopAttributes::Unspecified;
4667330f729Sjoerg   UnrollAndJamEnable = LoopAttributes::Unspecified;
4677330f729Sjoerg   VectorizePredicateEnable = LoopAttributes::Unspecified;
4687330f729Sjoerg   DistributeEnable = LoopAttributes::Unspecified;
4697330f729Sjoerg   PipelineDisabled = false;
4707330f729Sjoerg   PipelineInitiationInterval = 0;
471*e038c9c4Sjoerg   MustProgress = false;
4727330f729Sjoerg }
4737330f729Sjoerg 
LoopInfo(BasicBlock * Header,const LoopAttributes & Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,LoopInfo * Parent)4747330f729Sjoerg LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
4757330f729Sjoerg                    const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
4767330f729Sjoerg                    LoopInfo *Parent)
4777330f729Sjoerg     : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
4787330f729Sjoerg       Parent(Parent) {
4797330f729Sjoerg 
4807330f729Sjoerg   if (Attrs.IsParallel) {
4817330f729Sjoerg     // Create an access group for this loop.
4827330f729Sjoerg     LLVMContext &Ctx = Header->getContext();
4837330f729Sjoerg     AccGroup = MDNode::getDistinct(Ctx, {});
4847330f729Sjoerg   }
4857330f729Sjoerg 
4867330f729Sjoerg   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
487*e038c9c4Sjoerg       Attrs.VectorizeScalable == LoopAttributes::Unspecified &&
4887330f729Sjoerg       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
4897330f729Sjoerg       Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
4907330f729Sjoerg       Attrs.PipelineInitiationInterval == 0 &&
4917330f729Sjoerg       Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
4927330f729Sjoerg       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
4937330f729Sjoerg       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
4947330f729Sjoerg       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
4957330f729Sjoerg       Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
496*e038c9c4Sjoerg       !EndLoc && !Attrs.MustProgress)
4977330f729Sjoerg     return;
4987330f729Sjoerg 
4997330f729Sjoerg   TempLoopID = MDNode::getTemporary(Header->getContext(), None);
5007330f729Sjoerg }
5017330f729Sjoerg 
finish()5027330f729Sjoerg void LoopInfo::finish() {
5037330f729Sjoerg   // We did not annotate the loop body instructions because there are no
5047330f729Sjoerg   // attributes for this loop.
5057330f729Sjoerg   if (!TempLoopID)
5067330f729Sjoerg     return;
5077330f729Sjoerg 
5087330f729Sjoerg   MDNode *LoopID;
5097330f729Sjoerg   LoopAttributes CurLoopAttr = Attrs;
5107330f729Sjoerg   LLVMContext &Ctx = Header->getContext();
5117330f729Sjoerg 
5127330f729Sjoerg   if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
5137330f729Sjoerg                  Parent->Attrs.UnrollAndJamCount != 0)) {
5147330f729Sjoerg     // Parent unroll-and-jams this loop.
5157330f729Sjoerg     // Split the transformations in those that happens before the unroll-and-jam
5167330f729Sjoerg     // and those after.
5177330f729Sjoerg 
5187330f729Sjoerg     LoopAttributes BeforeJam, AfterJam;
5197330f729Sjoerg 
5207330f729Sjoerg     BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
5217330f729Sjoerg 
5227330f729Sjoerg     BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
523*e038c9c4Sjoerg     BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
5247330f729Sjoerg     BeforeJam.InterleaveCount = Attrs.InterleaveCount;
5257330f729Sjoerg     BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
5267330f729Sjoerg     BeforeJam.DistributeEnable = Attrs.DistributeEnable;
5277330f729Sjoerg     BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
5287330f729Sjoerg 
5297330f729Sjoerg     switch (Attrs.UnrollEnable) {
5307330f729Sjoerg     case LoopAttributes::Unspecified:
5317330f729Sjoerg     case LoopAttributes::Disable:
5327330f729Sjoerg       BeforeJam.UnrollEnable = Attrs.UnrollEnable;
5337330f729Sjoerg       AfterJam.UnrollEnable = Attrs.UnrollEnable;
5347330f729Sjoerg       break;
5357330f729Sjoerg     case LoopAttributes::Full:
5367330f729Sjoerg       BeforeJam.UnrollEnable = LoopAttributes::Full;
5377330f729Sjoerg       break;
5387330f729Sjoerg     case LoopAttributes::Enable:
5397330f729Sjoerg       AfterJam.UnrollEnable = LoopAttributes::Enable;
5407330f729Sjoerg       break;
5417330f729Sjoerg     }
5427330f729Sjoerg 
5437330f729Sjoerg     AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
5447330f729Sjoerg     AfterJam.UnrollCount = Attrs.UnrollCount;
5457330f729Sjoerg     AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
5467330f729Sjoerg     AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
5477330f729Sjoerg 
5487330f729Sjoerg     // If this loop is subject of an unroll-and-jam by the parent loop, and has
5497330f729Sjoerg     // an unroll-and-jam annotation itself, we have to decide whether to first
5507330f729Sjoerg     // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
5517330f729Sjoerg     // UnrollAndJam pass processes loops from inner to outer, so we apply the
5527330f729Sjoerg     // inner first.
5537330f729Sjoerg     BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
5547330f729Sjoerg     BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
5557330f729Sjoerg 
5567330f729Sjoerg     // Set the inner followup metadata to process by the outer loop. Only
5577330f729Sjoerg     // consider the first inner loop.
5587330f729Sjoerg     if (!Parent->UnrollAndJamInnerFollowup) {
5597330f729Sjoerg       // Splitting the attributes into a BeforeJam and an AfterJam part will
5607330f729Sjoerg       // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
5617330f729Sjoerg       // to be forwarded to the AfterJam part. We detect the situation here and
5627330f729Sjoerg       // add it manually.
5637330f729Sjoerg       SmallVector<Metadata *, 1> BeforeLoopProperties;
5647330f729Sjoerg       if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
5657330f729Sjoerg           BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
566*e038c9c4Sjoerg           BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
567*e038c9c4Sjoerg           BeforeJam.VectorizeScalable == LoopAttributes::Enable)
5687330f729Sjoerg         BeforeLoopProperties.push_back(
5697330f729Sjoerg             MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
5707330f729Sjoerg 
5717330f729Sjoerg       bool InnerFollowupHasTransform = false;
5727330f729Sjoerg       MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
5737330f729Sjoerg                                              InnerFollowupHasTransform);
5747330f729Sjoerg       if (InnerFollowupHasTransform)
5757330f729Sjoerg         Parent->UnrollAndJamInnerFollowup = InnerFollowup;
5767330f729Sjoerg     }
5777330f729Sjoerg 
5787330f729Sjoerg     CurLoopAttr = BeforeJam;
5797330f729Sjoerg   }
5807330f729Sjoerg 
5817330f729Sjoerg   bool HasUserTransforms = false;
5827330f729Sjoerg   LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
5837330f729Sjoerg   TempLoopID->replaceAllUsesWith(LoopID);
5847330f729Sjoerg }
5857330f729Sjoerg 
push(BasicBlock * Header,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc)5867330f729Sjoerg void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
5877330f729Sjoerg                          const llvm::DebugLoc &EndLoc) {
5887330f729Sjoerg   Active.emplace_back(
5897330f729Sjoerg       new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
5907330f729Sjoerg                    Active.empty() ? nullptr : Active.back().get()));
5917330f729Sjoerg   // Clear the attributes so nested loops do not inherit them.
5927330f729Sjoerg   StagedAttrs.clear();
5937330f729Sjoerg }
5947330f729Sjoerg 
push(BasicBlock * Header,clang::ASTContext & Ctx,const clang::CodeGenOptions & CGOpts,ArrayRef<const clang::Attr * > Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,bool MustProgress)5957330f729Sjoerg void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
596*e038c9c4Sjoerg                          const clang::CodeGenOptions &CGOpts,
5977330f729Sjoerg                          ArrayRef<const clang::Attr *> Attrs,
5987330f729Sjoerg                          const llvm::DebugLoc &StartLoc,
599*e038c9c4Sjoerg                          const llvm::DebugLoc &EndLoc, bool MustProgress) {
6007330f729Sjoerg   // Identify loop hint attributes from Attrs.
6017330f729Sjoerg   for (const auto *Attr : Attrs) {
6027330f729Sjoerg     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
6037330f729Sjoerg     const OpenCLUnrollHintAttr *OpenCLHint =
6047330f729Sjoerg         dyn_cast<OpenCLUnrollHintAttr>(Attr);
6057330f729Sjoerg 
6067330f729Sjoerg     // Skip non loop hint attributes
6077330f729Sjoerg     if (!LH && !OpenCLHint) {
6087330f729Sjoerg       continue;
6097330f729Sjoerg     }
6107330f729Sjoerg 
6117330f729Sjoerg     LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
6127330f729Sjoerg     LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
6137330f729Sjoerg     unsigned ValueInt = 1;
6147330f729Sjoerg     // Translate opencl_unroll_hint attribute argument to
6157330f729Sjoerg     // equivalent LoopHintAttr enums.
6167330f729Sjoerg     // OpenCL v2.0 s6.11.5:
6177330f729Sjoerg     // 0 - enable unroll (no argument).
6187330f729Sjoerg     // 1 - disable unroll.
6197330f729Sjoerg     // other positive integer n - unroll by n.
6207330f729Sjoerg     if (OpenCLHint) {
6217330f729Sjoerg       ValueInt = OpenCLHint->getUnrollHint();
6227330f729Sjoerg       if (ValueInt == 0) {
6237330f729Sjoerg         State = LoopHintAttr::Enable;
6247330f729Sjoerg       } else if (ValueInt != 1) {
6257330f729Sjoerg         Option = LoopHintAttr::UnrollCount;
6267330f729Sjoerg         State = LoopHintAttr::Numeric;
6277330f729Sjoerg       }
6287330f729Sjoerg     } else if (LH) {
6297330f729Sjoerg       auto *ValueExpr = LH->getValue();
6307330f729Sjoerg       if (ValueExpr) {
6317330f729Sjoerg         llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
6327330f729Sjoerg         ValueInt = ValueAPS.getSExtValue();
6337330f729Sjoerg       }
6347330f729Sjoerg 
6357330f729Sjoerg       Option = LH->getOption();
6367330f729Sjoerg       State = LH->getState();
6377330f729Sjoerg     }
6387330f729Sjoerg     switch (State) {
6397330f729Sjoerg     case LoopHintAttr::Disable:
6407330f729Sjoerg       switch (Option) {
6417330f729Sjoerg       case LoopHintAttr::Vectorize:
6427330f729Sjoerg         // Disable vectorization by specifying a width of 1.
6437330f729Sjoerg         setVectorizeWidth(1);
644*e038c9c4Sjoerg         setVectorizeScalable(LoopAttributes::Unspecified);
6457330f729Sjoerg         break;
6467330f729Sjoerg       case LoopHintAttr::Interleave:
6477330f729Sjoerg         // Disable interleaving by speciyfing a count of 1.
6487330f729Sjoerg         setInterleaveCount(1);
6497330f729Sjoerg         break;
6507330f729Sjoerg       case LoopHintAttr::Unroll:
6517330f729Sjoerg         setUnrollState(LoopAttributes::Disable);
6527330f729Sjoerg         break;
6537330f729Sjoerg       case LoopHintAttr::UnrollAndJam:
6547330f729Sjoerg         setUnrollAndJamState(LoopAttributes::Disable);
6557330f729Sjoerg         break;
6567330f729Sjoerg       case LoopHintAttr::VectorizePredicate:
6577330f729Sjoerg         setVectorizePredicateState(LoopAttributes::Disable);
6587330f729Sjoerg         break;
6597330f729Sjoerg       case LoopHintAttr::Distribute:
6607330f729Sjoerg         setDistributeState(false);
6617330f729Sjoerg         break;
6627330f729Sjoerg       case LoopHintAttr::PipelineDisabled:
6637330f729Sjoerg         setPipelineDisabled(true);
6647330f729Sjoerg         break;
6657330f729Sjoerg       case LoopHintAttr::UnrollCount:
6667330f729Sjoerg       case LoopHintAttr::UnrollAndJamCount:
6677330f729Sjoerg       case LoopHintAttr::VectorizeWidth:
6687330f729Sjoerg       case LoopHintAttr::InterleaveCount:
6697330f729Sjoerg       case LoopHintAttr::PipelineInitiationInterval:
6707330f729Sjoerg         llvm_unreachable("Options cannot be disabled.");
6717330f729Sjoerg         break;
6727330f729Sjoerg       }
6737330f729Sjoerg       break;
6747330f729Sjoerg     case LoopHintAttr::Enable:
6757330f729Sjoerg       switch (Option) {
6767330f729Sjoerg       case LoopHintAttr::Vectorize:
6777330f729Sjoerg       case LoopHintAttr::Interleave:
6787330f729Sjoerg         setVectorizeEnable(true);
6797330f729Sjoerg         break;
6807330f729Sjoerg       case LoopHintAttr::Unroll:
6817330f729Sjoerg         setUnrollState(LoopAttributes::Enable);
6827330f729Sjoerg         break;
6837330f729Sjoerg       case LoopHintAttr::UnrollAndJam:
6847330f729Sjoerg         setUnrollAndJamState(LoopAttributes::Enable);
6857330f729Sjoerg         break;
6867330f729Sjoerg       case LoopHintAttr::VectorizePredicate:
6877330f729Sjoerg         setVectorizePredicateState(LoopAttributes::Enable);
6887330f729Sjoerg         break;
6897330f729Sjoerg       case LoopHintAttr::Distribute:
6907330f729Sjoerg         setDistributeState(true);
6917330f729Sjoerg         break;
6927330f729Sjoerg       case LoopHintAttr::UnrollCount:
6937330f729Sjoerg       case LoopHintAttr::UnrollAndJamCount:
6947330f729Sjoerg       case LoopHintAttr::VectorizeWidth:
6957330f729Sjoerg       case LoopHintAttr::InterleaveCount:
6967330f729Sjoerg       case LoopHintAttr::PipelineDisabled:
6977330f729Sjoerg       case LoopHintAttr::PipelineInitiationInterval:
6987330f729Sjoerg         llvm_unreachable("Options cannot enabled.");
6997330f729Sjoerg         break;
7007330f729Sjoerg       }
7017330f729Sjoerg       break;
7027330f729Sjoerg     case LoopHintAttr::AssumeSafety:
7037330f729Sjoerg       switch (Option) {
7047330f729Sjoerg       case LoopHintAttr::Vectorize:
7057330f729Sjoerg       case LoopHintAttr::Interleave:
7067330f729Sjoerg         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
7077330f729Sjoerg         setParallel(true);
7087330f729Sjoerg         setVectorizeEnable(true);
7097330f729Sjoerg         break;
7107330f729Sjoerg       case LoopHintAttr::Unroll:
7117330f729Sjoerg       case LoopHintAttr::UnrollAndJam:
7127330f729Sjoerg       case LoopHintAttr::VectorizePredicate:
7137330f729Sjoerg       case LoopHintAttr::UnrollCount:
7147330f729Sjoerg       case LoopHintAttr::UnrollAndJamCount:
7157330f729Sjoerg       case LoopHintAttr::VectorizeWidth:
7167330f729Sjoerg       case LoopHintAttr::InterleaveCount:
7177330f729Sjoerg       case LoopHintAttr::Distribute:
7187330f729Sjoerg       case LoopHintAttr::PipelineDisabled:
7197330f729Sjoerg       case LoopHintAttr::PipelineInitiationInterval:
7207330f729Sjoerg         llvm_unreachable("Options cannot be used to assume mem safety.");
7217330f729Sjoerg         break;
7227330f729Sjoerg       }
7237330f729Sjoerg       break;
7247330f729Sjoerg     case LoopHintAttr::Full:
7257330f729Sjoerg       switch (Option) {
7267330f729Sjoerg       case LoopHintAttr::Unroll:
7277330f729Sjoerg         setUnrollState(LoopAttributes::Full);
7287330f729Sjoerg         break;
7297330f729Sjoerg       case LoopHintAttr::UnrollAndJam:
7307330f729Sjoerg         setUnrollAndJamState(LoopAttributes::Full);
7317330f729Sjoerg         break;
7327330f729Sjoerg       case LoopHintAttr::Vectorize:
7337330f729Sjoerg       case LoopHintAttr::Interleave:
7347330f729Sjoerg       case LoopHintAttr::UnrollCount:
7357330f729Sjoerg       case LoopHintAttr::UnrollAndJamCount:
7367330f729Sjoerg       case LoopHintAttr::VectorizeWidth:
7377330f729Sjoerg       case LoopHintAttr::InterleaveCount:
7387330f729Sjoerg       case LoopHintAttr::Distribute:
7397330f729Sjoerg       case LoopHintAttr::PipelineDisabled:
7407330f729Sjoerg       case LoopHintAttr::PipelineInitiationInterval:
7417330f729Sjoerg       case LoopHintAttr::VectorizePredicate:
7427330f729Sjoerg         llvm_unreachable("Options cannot be used with 'full' hint.");
7437330f729Sjoerg         break;
7447330f729Sjoerg       }
7457330f729Sjoerg       break;
746*e038c9c4Sjoerg     case LoopHintAttr::FixedWidth:
747*e038c9c4Sjoerg     case LoopHintAttr::ScalableWidth:
7487330f729Sjoerg       switch (Option) {
7497330f729Sjoerg       case LoopHintAttr::VectorizeWidth:
750*e038c9c4Sjoerg         setVectorizeScalable(State == LoopHintAttr::ScalableWidth
751*e038c9c4Sjoerg                                  ? LoopAttributes::Enable
752*e038c9c4Sjoerg                                  : LoopAttributes::Disable);
753*e038c9c4Sjoerg         if (LH->getValue())
7547330f729Sjoerg           setVectorizeWidth(ValueInt);
7557330f729Sjoerg         break;
756*e038c9c4Sjoerg       default:
757*e038c9c4Sjoerg         llvm_unreachable("Options cannot be used with 'scalable' hint.");
758*e038c9c4Sjoerg         break;
759*e038c9c4Sjoerg       }
760*e038c9c4Sjoerg       break;
761*e038c9c4Sjoerg     case LoopHintAttr::Numeric:
762*e038c9c4Sjoerg       switch (Option) {
7637330f729Sjoerg       case LoopHintAttr::InterleaveCount:
7647330f729Sjoerg         setInterleaveCount(ValueInt);
7657330f729Sjoerg         break;
7667330f729Sjoerg       case LoopHintAttr::UnrollCount:
7677330f729Sjoerg         setUnrollCount(ValueInt);
7687330f729Sjoerg         break;
7697330f729Sjoerg       case LoopHintAttr::UnrollAndJamCount:
7707330f729Sjoerg         setUnrollAndJamCount(ValueInt);
7717330f729Sjoerg         break;
7727330f729Sjoerg       case LoopHintAttr::PipelineInitiationInterval:
7737330f729Sjoerg         setPipelineInitiationInterval(ValueInt);
7747330f729Sjoerg         break;
7757330f729Sjoerg       case LoopHintAttr::Unroll:
7767330f729Sjoerg       case LoopHintAttr::UnrollAndJam:
7777330f729Sjoerg       case LoopHintAttr::VectorizePredicate:
7787330f729Sjoerg       case LoopHintAttr::Vectorize:
779*e038c9c4Sjoerg       case LoopHintAttr::VectorizeWidth:
7807330f729Sjoerg       case LoopHintAttr::Interleave:
7817330f729Sjoerg       case LoopHintAttr::Distribute:
7827330f729Sjoerg       case LoopHintAttr::PipelineDisabled:
7837330f729Sjoerg         llvm_unreachable("Options cannot be assigned a value.");
7847330f729Sjoerg         break;
7857330f729Sjoerg       }
7867330f729Sjoerg       break;
7877330f729Sjoerg     }
7887330f729Sjoerg   }
7897330f729Sjoerg 
790*e038c9c4Sjoerg   setMustProgress(MustProgress);
791*e038c9c4Sjoerg 
792*e038c9c4Sjoerg   if (CGOpts.OptimizationLevel > 0)
793*e038c9c4Sjoerg     // Disable unrolling for the loop, if unrolling is disabled (via
794*e038c9c4Sjoerg     // -fno-unroll-loops) and no pragmas override the decision.
795*e038c9c4Sjoerg     if (!CGOpts.UnrollLoops &&
796*e038c9c4Sjoerg         (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
797*e038c9c4Sjoerg          StagedAttrs.UnrollCount == 0))
798*e038c9c4Sjoerg       setUnrollState(LoopAttributes::Disable);
799*e038c9c4Sjoerg 
8007330f729Sjoerg   /// Stage the attributes.
8017330f729Sjoerg   push(Header, StartLoc, EndLoc);
8027330f729Sjoerg }
8037330f729Sjoerg 
pop()8047330f729Sjoerg void LoopInfoStack::pop() {
8057330f729Sjoerg   assert(!Active.empty() && "No active loops to pop");
8067330f729Sjoerg   Active.back()->finish();
8077330f729Sjoerg   Active.pop_back();
8087330f729Sjoerg }
8097330f729Sjoerg 
InsertHelper(Instruction * I) const8107330f729Sjoerg void LoopInfoStack::InsertHelper(Instruction *I) const {
8117330f729Sjoerg   if (I->mayReadOrWriteMemory()) {
8127330f729Sjoerg     SmallVector<Metadata *, 4> AccessGroups;
8137330f729Sjoerg     for (const auto &AL : Active) {
8147330f729Sjoerg       // Here we assume that every loop that has an access group is parallel.
8157330f729Sjoerg       if (MDNode *Group = AL->getAccessGroup())
8167330f729Sjoerg         AccessGroups.push_back(Group);
8177330f729Sjoerg     }
8187330f729Sjoerg     MDNode *UnionMD = nullptr;
8197330f729Sjoerg     if (AccessGroups.size() == 1)
8207330f729Sjoerg       UnionMD = cast<MDNode>(AccessGroups[0]);
8217330f729Sjoerg     else if (AccessGroups.size() >= 2)
8227330f729Sjoerg       UnionMD = MDNode::get(I->getContext(), AccessGroups);
8237330f729Sjoerg     I->setMetadata("llvm.access.group", UnionMD);
8247330f729Sjoerg   }
8257330f729Sjoerg 
8267330f729Sjoerg   if (!hasInfo())
8277330f729Sjoerg     return;
8287330f729Sjoerg 
8297330f729Sjoerg   const LoopInfo &L = getInfo();
8307330f729Sjoerg   if (!L.getLoopID())
8317330f729Sjoerg     return;
8327330f729Sjoerg 
8337330f729Sjoerg   if (I->isTerminator()) {
8347330f729Sjoerg     for (BasicBlock *Succ : successors(I))
8357330f729Sjoerg       if (Succ == L.getHeader()) {
8367330f729Sjoerg         I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
8377330f729Sjoerg         break;
8387330f729Sjoerg       }
8397330f729Sjoerg     return;
8407330f729Sjoerg   }
8417330f729Sjoerg }
842