@@ -51,6 +51,16 @@ using namespace llvm;
5151
5252#define DEBUG_TYPE " loop-interchange"
5353
54+ // / @{
55+ // / Metadata attribute names
56+ static const char *const LLVMLoopInterchangeFollowupAll =
57+ " llvm.loop.interchange.followup_all" ;
58+ static const char *const LLVMLoopInterchangeFollowupOuter =
59+ " llvm.loop.interchange.followup_outer" ;
60+ static const char *const LLVMLoopInterchangeFollowupInner =
61+ " llvm.loop.interchange.followup_inner" ;
62+ // / @}
63+
5464STATISTIC (LoopsInterchanged, " Number of loops interchanged" );
5565
5666static cl::opt<int > LoopInterchangeCostThreshold (
@@ -65,6 +75,14 @@ static cl::opt<unsigned int> MaxMemInstrCount(
6575 " in the dependency matrix. Higher value may lead to more interchanges "
6676 " at the cost of compile-time" ));
6777
78+ // Whether to apply by default.
79+ // TODO: Once this pass is enabled by default, remove this option and use the
80+ // value of PipelineTuningOptions.
81+ static cl::opt<bool > OnlyWhenForced (
82+ " loop-interchange-only-when-forced" , cl::init(false ), cl::ReallyHidden,
83+ cl::desc(
84+ " Apply interchanges only when explicitly specified metadata exists" ));
85+
6886namespace {
6987
7088using LoopVector = SmallVector<Loop *, 8 >;
@@ -297,6 +315,16 @@ static bool isComputableLoopNest(ScalarEvolution *SE,
297315 return true ;
298316}
299317
318+ static std::optional<bool > findMetadata (Loop *L) {
319+ auto Value = findStringMetadataForLoop (L, " llvm.loop.interchange.enable" );
320+ if (!Value)
321+ return std::nullopt ;
322+
323+ const MDOperand *Op = *Value;
324+ assert (Op && mdconst::hasa<ConstantInt>(*Op) && " invalid metadata" );
325+ return mdconst::extract<ConstantInt>(*Op)->getZExtValue ();
326+ }
327+
300328namespace {
301329
302330// / LoopInterchangeLegality checks if it is legal to interchange the loop.
@@ -504,6 +532,10 @@ struct LoopInterchange {
504532 CostMap[LoopCosts[i].first ] = i;
505533 }
506534 }
535+
536+ if (OnlyWhenForced)
537+ return processEnabledLoop (LoopList, DependencyMatrix, CostMap);
538+
507539 // We try to achieve the globally optimal memory access for the loopnest,
508540 // and do interchange based on a bubble-sort fasion. We start from
509541 // the innermost loop, move it outwards to the best possible position
@@ -532,6 +564,8 @@ struct LoopInterchange {
532564 Loop *InnerLoop = LoopList[InnerLoopId];
533565 LLVM_DEBUG (dbgs () << " Processing InnerLoopId = " << InnerLoopId
534566 << " and OuterLoopId = " << OuterLoopId << " \n " );
567+ if (findMetadata (OuterLoop) == false || findMetadata (InnerLoop) == false )
568+ return false ;
535569 LoopInterchangeLegality LIL (OuterLoop, InnerLoop, SE, ORE);
536570 if (!LIL.canInterchangeLoops (InnerLoopId, OuterLoopId, DependencyMatrix)) {
537571 LLVM_DEBUG (dbgs () << " Not interchanging loops. Cannot prove legality.\n " );
@@ -569,6 +603,48 @@ struct LoopInterchange {
569603
570604 return true ;
571605 }
606+
607+ bool processEnabledLoop (SmallVectorImpl<Loop *> &LoopList,
608+ std::vector<std::vector<char >> &DependencyMatrix,
609+ const DenseMap<const Loop *, unsigned > &CostMap) {
610+ bool Changed = false ;
611+ for (unsigned InnerLoopId = LoopList.size () - 1 ; InnerLoopId > 0 ;
612+ InnerLoopId--) {
613+ unsigned OuterLoopId = InnerLoopId - 1 ;
614+ if (findMetadata (LoopList[OuterLoopId]) != true )
615+ continue ;
616+
617+ MDNode *MDOrigLoopID = LoopList[OuterLoopId]->getLoopID ();
618+ bool Interchanged =
619+ processLoop (LoopList[InnerLoopId], LoopList[OuterLoopId], InnerLoopId,
620+ OuterLoopId, DependencyMatrix, CostMap);
621+
622+ // TODO: Consolidate the duplicate code in `processLoopList`.
623+ if (Interchanged) {
624+ std::swap (LoopList[OuterLoopId], LoopList[InnerLoopId]);
625+ // Update the DependencyMatrix
626+ interChangeDependencies (DependencyMatrix, InnerLoopId, OuterLoopId);
627+
628+ LLVM_DEBUG (dbgs () << " Dependency matrix after interchange:\n " ;
629+ printDepMatrix (DependencyMatrix));
630+ }
631+
632+ std::optional<MDNode *> MDOuterLoopID =
633+ makeFollowupLoopID (MDOrigLoopID, {LLVMLoopInterchangeFollowupAll,
634+ LLVMLoopInterchangeFollowupOuter});
635+ if (MDOuterLoopID)
636+ LoopList[OuterLoopId]->setLoopID (*MDOuterLoopID);
637+
638+ std::optional<MDNode *> MDInnerLoopID =
639+ makeFollowupLoopID (MDOrigLoopID, {LLVMLoopInterchangeFollowupAll,
640+ LLVMLoopInterchangeFollowupInner});
641+ if (MDInnerLoopID)
642+ LoopList[InnerLoopId]->setLoopID (*MDInnerLoopID);
643+
644+ Changed |= Interchanged;
645+ }
646+ return Changed;
647+ }
572648};
573649
574650} // end anonymous namespace
0 commit comments