@@ -51,6 +51,16 @@ using namespace llvm;
51
51
52
52
#define DEBUG_TYPE " loop-interchange"
53
53
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
+
54
64
STATISTIC (LoopsInterchanged, " Number of loops interchanged" );
55
65
56
66
static cl::opt<int > LoopInterchangeCostThreshold (
@@ -65,6 +75,14 @@ static cl::opt<unsigned int> MaxMemInstrCount(
65
75
" in the dependency matrix. Higher value may lead to more interchanges "
66
76
" at the cost of compile-time" ));
67
77
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
+
68
86
namespace {
69
87
70
88
using LoopVector = SmallVector<Loop *, 8 >;
@@ -297,6 +315,16 @@ static bool isComputableLoopNest(ScalarEvolution *SE,
297
315
return true ;
298
316
}
299
317
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
+
300
328
namespace {
301
329
302
330
// / LoopInterchangeLegality checks if it is legal to interchange the loop.
@@ -504,6 +532,10 @@ struct LoopInterchange {
504
532
CostMap[LoopCosts[i].first ] = i;
505
533
}
506
534
}
535
+
536
+ if (OnlyWhenForced)
537
+ return processEnabledLoop (LoopList, DependencyMatrix, CostMap);
538
+
507
539
// We try to achieve the globally optimal memory access for the loopnest,
508
540
// and do interchange based on a bubble-sort fasion. We start from
509
541
// the innermost loop, move it outwards to the best possible position
@@ -532,6 +564,8 @@ struct LoopInterchange {
532
564
Loop *InnerLoop = LoopList[InnerLoopId];
533
565
LLVM_DEBUG (dbgs () << " Processing InnerLoopId = " << InnerLoopId
534
566
<< " and OuterLoopId = " << OuterLoopId << " \n " );
567
+ if (findMetadata (OuterLoop) == false || findMetadata (InnerLoop) == false )
568
+ return false ;
535
569
LoopInterchangeLegality LIL (OuterLoop, InnerLoop, SE, ORE);
536
570
if (!LIL.canInterchangeLoops (InnerLoopId, OuterLoopId, DependencyMatrix)) {
537
571
LLVM_DEBUG (dbgs () << " Not interchanging loops. Cannot prove legality.\n " );
@@ -569,6 +603,48 @@ struct LoopInterchange {
569
603
570
604
return true ;
571
605
}
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
+ }
572
648
};
573
649
574
650
} // end anonymous namespace
0 commit comments