From 81986781d3f5896c6e38d050dd7bf97b019268eb Mon Sep 17 00:00:00 2001 From: liyufei2025 Date: Fri, 10 Oct 2025 13:17:36 +0800 Subject: [PATCH 1/3] loopinterchange --- .../lib/Transforms/Scalar/LoopInterchange.cpp | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index 91286ebcea33..a7f0431233bd 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -54,7 +54,7 @@ using namespace llvm; STATISTIC(LoopsInterchanged, "Number of loops interchanged"); static cl::opt LoopInterchangeCostThreshold( - "loop-interchange-threshold", cl::init(0), cl::Hidden, + "loop-interchange-threshold", cl::init(1), cl::Hidden, cl::desc("Interchange if you gain more than this number")); namespace { @@ -114,6 +114,12 @@ static bool populateDependencyMatrix(CharMatrix &DepMatrix, unsigned Level, for (I = MemInstr.begin(), IE = MemInstr.end(); I != IE; ++I) { for (J = I, JE = MemInstr.end(); J != JE; ++J) { + + if(I==J){ + LLVM_DEBUG(dbgs()<<"Skipping self-dependency analysis\n"); + continue; + } + std::vector Dep; Instruction *Src = cast(*I); Instruction *Dst = cast(*J); @@ -540,6 +546,11 @@ struct LoopInterchange { bool LoopInterchangeLegality::containsUnsafeInstructions(BasicBlock *BB) { return any_of(*BB, [](const Instruction &I) { + if (auto *St = dyn_cast(&I)) + return !St->isSimple(); + if(auto *Ld = dyn_cast(&I)) + return !Ld->isSimple(); + return I.mayHaveSideEffects() || I.mayReadFromMemory(); }); } @@ -561,15 +572,19 @@ bool LoopInterchangeLegality::tightlyNested(Loop *OuterLoop, Loop *InnerLoop) { for (BasicBlock *Succ : successors(OuterLoopHeaderBI)) if (Succ != InnerLoopPreHeader && Succ != InnerLoop->getHeader() && - Succ != OuterLoopLatch) - return false; + Succ != OuterLoopLatch){ + errs() << "first step error" << "\n"; + return false; + } LLVM_DEBUG(dbgs() << "Checking instructions in Loop header and Loop latch\n"); // We do not have any basic block in between now make sure the outer header // and outer loop latch doesn't contain any unsafe instructions. if (containsUnsafeInstructions(OuterLoopHeader) || - containsUnsafeInstructions(OuterLoopLatch)) + containsUnsafeInstructions(OuterLoopLatch)){ + errs() << "second step error" << "\n"; return false; + } // Also make sure the inner loop preheader does not contain any unsafe // instructions. Note that all instructions in the preheader will be moved to @@ -1089,7 +1104,7 @@ int LoopInterchangeProfitability::getInstrOrderCost() { } } } - return GoodOrder - BadOrder; + return GoodOrder - BadOrder; } std::optional @@ -1123,7 +1138,7 @@ LoopInterchangeProfitability::isProfitablePerInstrOrderCost() { // reordering if number of bad orders is more than good. int Cost = getInstrOrderCost(); LLVM_DEBUG(dbgs() << "Cost = " << Cost << "\n"); - if (Cost < 0 && Cost < LoopInterchangeCostThreshold) + if (Cost < 1 && Cost < LoopInterchangeCostThreshold) return std::optional(true); return std::nullopt; @@ -1712,6 +1727,8 @@ PreservedAnalyses LoopInterchangePass::run(LoopNest &LN, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U) { + + //errs()<<"the 5th try"<<"\n"; Function &F = *LN.getParent(); DependenceInfo DI(&F, &AR.AA, &AR.SE, &AR.LI); -- Gitee From 6138134c3ab94486f7c26d3d1cfe8d3edc50dda1 Mon Sep 17 00:00:00 2001 From: fanxuerun Date: Fri, 10 Oct 2025 13:25:49 +0800 Subject: [PATCH 2/3] =?UTF-8?q?loopinterchange=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index a7f0431233bd..b761e5842f52 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -49,6 +49,7 @@ using namespace llvm; + #define DEBUG_TYPE "loop-interchange" STATISTIC(LoopsInterchanged, "Number of loops interchanged"); -- Gitee From 5db040f0bb215decebe1e36418dfae5c686b4cd0 Mon Sep 17 00:00:00 2001 From: fan-xuerun <2205015378@qq.com> Date: Mon, 27 Oct 2025 15:42:41 +0800 Subject: [PATCH 3/3] loopinterchange --- .../lib/Transforms/Scalar/LoopInterchange.cpp | 176 ++++++++++++------ 1 file changed, 119 insertions(+), 57 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index b761e5842f52..b4293f6c977c 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -15,6 +15,7 @@ #include "llvm/Transforms/Scalar/LoopInterchange.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/DependenceAnalysis.h" @@ -49,13 +50,12 @@ using namespace llvm; - #define DEBUG_TYPE "loop-interchange" STATISTIC(LoopsInterchanged, "Number of loops interchanged"); static cl::opt LoopInterchangeCostThreshold( - "loop-interchange-threshold", cl::init(1), cl::Hidden, + "loop-interchange-threshold", cl::init(0), cl::Hidden, cl::desc("Interchange if you gain more than this number")); namespace { @@ -113,13 +113,8 @@ static bool populateDependencyMatrix(CharMatrix &DepMatrix, unsigned Level, ValueVector::iterator I, IE, J, JE; - for (I = MemInstr.begin(), IE = MemInstr.end(); I != IE; ++I) { - for (J = I, JE = MemInstr.end(); J != JE; ++J) { - - if(I==J){ - LLVM_DEBUG(dbgs()<<"Skipping self-dependency analysis\n"); - continue; - } + for (I = MemInstr.begin(), IE = MemInstr.end(); I < IE; ++I) { + for (J = I + 1, JE = MemInstr.end(); J < JE; ++J) { std::vector Dep; Instruction *Src = cast(*I); @@ -317,6 +312,8 @@ public: std::unique_ptr &CC); private: + int analyzeGEPGroupPattern(ArrayRef GEPGroup); + int analyzeSingleGEP(const GetElementPtrInst *GEP); int getInstrOrderCost(); std::optional isProfitablePerLoopCacheAnalysis( const DenseMap &CostMap, @@ -547,10 +544,14 @@ struct LoopInterchange { bool LoopInterchangeLegality::containsUnsafeInstructions(BasicBlock *BB) { return any_of(*BB, [](const Instruction &I) { - if (auto *St = dyn_cast(&I)) - return !St->isSimple(); - if(auto *Ld = dyn_cast(&I)) - return !Ld->isSimple(); + if (auto *LI = dyn_cast(&I)) { + if (LI->isSimple() && !LI->isVolatile()) + return false; + } + if (auto *SI = dyn_cast(&I)) { + if (SI->isSimple() && !SI->isVolatile()) + return false; + } return I.mayHaveSideEffects() || I.mayReadFromMemory(); }); @@ -574,7 +575,6 @@ bool LoopInterchangeLegality::tightlyNested(Loop *OuterLoop, Loop *InnerLoop) { for (BasicBlock *Succ : successors(OuterLoopHeaderBI)) if (Succ != InnerLoopPreHeader && Succ != InnerLoop->getHeader() && Succ != OuterLoopLatch){ - errs() << "first step error" << "\n"; return false; } @@ -583,7 +583,6 @@ bool LoopInterchangeLegality::tightlyNested(Loop *OuterLoop, Loop *InnerLoop) { // and outer loop latch doesn't contain any unsafe instructions. if (containsUnsafeInstructions(OuterLoopHeader) || containsUnsafeInstructions(OuterLoopLatch)){ - errs() << "second step error" << "\n"; return false; } @@ -1057,57 +1056,122 @@ bool LoopInterchangeLegality::canInterchangeLoops(unsigned InnerLoopId, int LoopInterchangeProfitability::getInstrOrderCost() { unsigned GoodOrder, BadOrder; BadOrder = GoodOrder = 0; + + SmallPtrSet AnalyzedGEPs; + for (BasicBlock *BB : InnerLoop->blocks()) { for (Instruction &Ins : *BB) { if (const GetElementPtrInst *GEP = dyn_cast(&Ins)) { - unsigned NumOp = GEP->getNumOperands(); - bool FoundInnerInduction = false; - bool FoundOuterInduction = false; - for (unsigned i = 0; i < NumOp; ++i) { - // Skip operands that are not SCEV-able. - if (!SE->isSCEVable(GEP->getOperand(i)->getType())) - continue; - - const SCEV *OperandVal = SE->getSCEV(GEP->getOperand(i)); - const SCEVAddRecExpr *AR = dyn_cast(OperandVal); - if (!AR) - continue; - - // If we find the inner induction after an outer induction e.g. - // for(int i=0;igetLoop() == InnerLoop) { - // We found an InnerLoop induction after OuterLoop induction. It is - // a good order. - FoundInnerInduction = true; - if (FoundOuterInduction) { - GoodOrder++; - break; - } - } - // If we find the outer induction after an inner induction e.g. - // for(int i=0;igetLoop() == OuterLoop) { - // We found an OuterLoop induction after InnerLoop induction. It is - // a bad order. - FoundOuterInduction = true; - if (FoundInnerInduction) { - BadOrder++; - break; + if (AnalyzedGEPs.count(GEP)) + continue; + + bool isPtrPtrFirstLevel = false; + if (GEP->getNumOperands() < 3) { + isPtrPtrFirstLevel = true; + } + + if (isPtrPtrFirstLevel) { + SmallVector RelatedGEPs; + RelatedGEPs.push_back(GEP); + + for (const User *U : GEP->users()) { + if (const LoadInst *Load = dyn_cast(U)) { + for (const User *LoadUser : Load->users()) { + if (const GetElementPtrInst *SecondGEP = dyn_cast(LoadUser)) { + RelatedGEPs.push_back(SecondGEP); + AnalyzedGEPs.insert(SecondGEP); + } + } } } + + int patternCost = analyzeGEPGroupPattern(RelatedGEPs); + if (patternCost > 0) GoodOrder += 1; + else if (patternCost < 0) BadOrder += 1; + + AnalyzedGEPs.insert(GEP); + } else { + int gepCost = analyzeSingleGEP(GEP); + if (gepCost > 0) GoodOrder += 1; + else if (gepCost < 0) BadOrder += 1; + + AnalyzedGEPs.insert(GEP); } } } } + return GoodOrder - BadOrder; } +int LoopInterchangeProfitability::analyzeGEPGroupPattern(ArrayRef GEPGroup) { + SmallVector AllLoopIndices; + + for (const GetElementPtrInst *GEP : GEPGroup) { + for (unsigned i = 0; i < GEP->getNumOperands(); ++i) { + Value *Index = GEP->getOperand(i); + if (!SE->isSCEVable(Index->getType())) + continue; + + const SCEV *OperandVal = SE->getSCEV(Index); + if (const SCEVAddRecExpr *AR = dyn_cast(OperandVal)) { + AllLoopIndices.push_back(AR->getLoop()); + } + } + } + + bool FoundInnerInduction = false; + bool FoundOuterInduction = false; + + for (const Loop *L : AllLoopIndices) { + if (L == InnerLoop) { + FoundInnerInduction = true; + if (FoundOuterInduction) { + return 1; // Good pattern + } + } + + if (L == OuterLoop) { + FoundOuterInduction = true; + if (FoundInnerInduction) { + return -1; // Bad pattern + } + } + } + + return 0; // Unknown pattern +} + +int LoopInterchangeProfitability::analyzeSingleGEP(const GetElementPtrInst *GEP) { + bool FoundInnerInduction = false; + bool FoundOuterInduction = false; + + for (unsigned i = 0; i < GEP->getNumOperands(); ++i) { + if (!SE->isSCEVable(GEP->getOperand(i)->getType())) + continue; + const SCEV *OperandVal = SE->getSCEV(GEP->getOperand(i)); + const SCEVAddRecExpr *AR = dyn_cast(OperandVal); + if (!AR) + continue; + + if (AR->getLoop() == InnerLoop) { + FoundInnerInduction = true; + if (FoundOuterInduction) { + return 1; + } + } + + if (AR->getLoop() == OuterLoop) { + FoundOuterInduction = true; + if (FoundInnerInduction) { + return -1; + } + } + } + + return 0; +} + std::optional LoopInterchangeProfitability::isProfitablePerLoopCacheAnalysis( const DenseMap &CostMap, @@ -1139,7 +1203,7 @@ LoopInterchangeProfitability::isProfitablePerInstrOrderCost() { // reordering if number of bad orders is more than good. int Cost = getInstrOrderCost(); LLVM_DEBUG(dbgs() << "Cost = " << Cost << "\n"); - if (Cost < 1 && Cost < LoopInterchangeCostThreshold) + if (Cost < 0 && Cost < LoopInterchangeCostThreshold) return std::optional(true); return std::nullopt; @@ -1728,8 +1792,6 @@ PreservedAnalyses LoopInterchangePass::run(LoopNest &LN, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U) { - - //errs()<<"the 5th try"<<"\n"; Function &F = *LN.getParent(); DependenceInfo DI(&F, &AR.AA, &AR.SE, &AR.LI); -- Gitee