Skip to content

Commit 4420416

Browse files
committed
[DependenceAnalysis][LoopFusion] Extending SIV to handle separate loops
When there is a dependency between two memory instructions in separate loops, SIV will be able to test them and compute the direction and the distance of the dependency. Loop fusion pass will uses this information to detect loop-carried dependencies and fuse the loops if it is legal.
1 parent 6c56160 commit 4420416

File tree

7 files changed

+760
-230
lines changed

7 files changed

+760
-230
lines changed

llvm/include/llvm/Analysis/DependenceAnalysis.h

Lines changed: 128 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,28 @@ namespace llvm {
152152
/// source and destination of the dependence.
153153
virtual unsigned getLevels() const { return 0; }
154154

155+
/// getSeparateLevels - Returns the number of separate loops surrounding
156+
/// the source and destination of the dependence.
157+
virtual unsigned getSeparateLevels() const { return 0; }
158+
159+
/// getDVEntry - Returns the DV entry associated with a regular or a
160+
/// separate level
161+
DVEntry getDVEntry(unsigned Level, bool Separate) const;
162+
155163
/// getDirection - Returns the direction associated with a particular
156-
/// level.
157-
virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; }
164+
/// level. If Separate is set to true, information about a separate
165+
/// level is provided.
166+
virtual unsigned getDirection(unsigned Level, bool Separate = false) const {
167+
return DVEntry::ALL;
168+
}
158169

159170
/// getDistance - Returns the distance (or NULL) associated with a
160-
/// particular level.
161-
virtual const SCEV *getDistance(unsigned Level) const { return nullptr; }
171+
/// particular level. If Separate is set to true, information about
172+
/// a separate level is provided.
173+
virtual const SCEV *getDistance(unsigned Level,
174+
bool Separate = false) const {
175+
return nullptr;
176+
}
162177

163178
/// Check if the direction vector is negative. A negative direction
164179
/// vector means Src and Dst are reversed in the actual program.
@@ -171,21 +186,35 @@ namespace llvm {
171186
virtual bool normalize(ScalarEvolution *SE) { return false; }
172187

173188
/// isPeelFirst - Returns true if peeling the first iteration from
174-
/// this loop will break this dependence.
175-
virtual bool isPeelFirst(unsigned Level) const { return false; }
189+
/// this loop will break this dependence. If Separate is set to true,
190+
/// information about a separate level is provided.
191+
virtual bool isPeelFirst(unsigned Level, bool Separate = false) const {
192+
return false;
193+
}
176194

177195
/// isPeelLast - Returns true if peeling the last iteration from
178-
/// this loop will break this dependence.
179-
virtual bool isPeelLast(unsigned Level) const { return false; }
196+
/// this loop will break this dependence. If Separate is set to true,
197+
/// information about a separate level is provided.
198+
virtual bool isPeelLast(unsigned Level, bool Separate = false) const {
199+
return false;
200+
}
180201

181202
/// isSplitable - Returns true if splitting this loop will break
182-
/// the dependence.
183-
virtual bool isSplitable(unsigned Level) const { return false; }
203+
/// the dependence. If Separate is set to true, information about a
204+
/// separate level is provided.
205+
virtual bool isSplitable(unsigned Level, bool Separate = false) const {
206+
return false;
207+
}
208+
209+
/// inSeparateLoops - Returns true if this level is performed across
210+
/// two separate loop nests.
211+
virtual bool inSeparateLoops(unsigned Level) const { return false; }
184212

185213
/// isScalar - Returns true if a particular level is scalar; that is,
186214
/// if no subscript in the source or destination mention the induction
187-
/// variable associated with the loop at this level.
188-
virtual bool isScalar(unsigned Level) const;
215+
/// variable associated with the loop at this level. If Separate is
216+
/// set to true, information about a separate level is provided.
217+
virtual bool isScalar(unsigned Level, bool Separate = false) const;
189218

190219
/// getNextPredecessor - Returns the value of the NextPredecessor
191220
/// field.
@@ -245,13 +274,33 @@ namespace llvm {
245274
/// source and destination of the dependence.
246275
unsigned getLevels() const override { return Levels; }
247276

277+
/// getSeparateLevels - Returns the number of separate loops surrounding
278+
/// the source and destination of the dependence.
279+
unsigned getSeparateLevels() const override { return SeparateLevels; }
280+
281+
/// getDVEntry - Returns the DV entry associated with a regular or a
282+
/// separate level
283+
DVEntry getDVEntry(unsigned Level, bool Separate) const {
284+
if (!Separate) {
285+
assert(0 < Level && Level <= Levels && "Level out of range");
286+
return DV[Level - 1];
287+
} else {
288+
assert(Levels < Level && Level <= Levels + SeparateLevels &&
289+
"Separate level out of range");
290+
return DVSeparate[Level - Levels - 1];
291+
}
292+
}
293+
248294
/// getDirection - Returns the direction associated with a particular
249-
/// level.
250-
unsigned getDirection(unsigned Level) const override;
295+
/// level. If Separate is set to true, information about a separate
296+
/// level is provided.
297+
unsigned getDirection(unsigned Level, bool Separate = false) const override;
251298

252299
/// getDistance - Returns the distance (or NULL) associated with a
253-
/// particular level.
254-
const SCEV *getDistance(unsigned Level) const override;
300+
/// particular level. If Separate is set to true, information about
301+
/// a separate level is provided.
302+
const SCEV *getDistance(unsigned Level,
303+
bool Separate = false) const override;
255304

256305
/// Check if the direction vector is negative. A negative direction
257306
/// vector means Src and Dst are reversed in the actual program.
@@ -264,27 +313,37 @@ namespace llvm {
264313
bool normalize(ScalarEvolution *SE) override;
265314

266315
/// isPeelFirst - Returns true if peeling the first iteration from
267-
/// this loop will break this dependence.
268-
bool isPeelFirst(unsigned Level) const override;
316+
/// this loop will break this dependence. If Separate is set to true,
317+
/// information about a separate level is provided.
318+
bool isPeelFirst(unsigned Level, bool Separate = false) const override;
269319

270320
/// isPeelLast - Returns true if peeling the last iteration from
271-
/// this loop will break this dependence.
272-
bool isPeelLast(unsigned Level) const override;
321+
/// this loop will break this dependence. If Separate is set to true,
322+
/// information about a separate level is provided.
323+
bool isPeelLast(unsigned Level, bool Separate = false) const override;
273324

274325
/// isSplitable - Returns true if splitting the loop will break
275-
/// the dependence.
276-
bool isSplitable(unsigned Level) const override;
326+
/// the dependence. If Separate is set to true, information about a
327+
/// separate level is provided.
328+
bool isSplitable(unsigned Level, bool Separate = false) const override;
329+
330+
/// inSeparateLoops - Returns true if this level is performed across
331+
/// two separate loop nests.
332+
bool inSeparateLoops(unsigned Level) const override;
277333

278334
/// isScalar - Returns true if a particular level is scalar; that is,
279335
/// if no subscript in the source or destination mention the induction
280-
/// variable associated with the loop at this level.
281-
bool isScalar(unsigned Level) const override;
336+
/// variable associated with the loop at this level. If Separate is
337+
/// set to true, information about a separate level is provided.
338+
bool isScalar(unsigned Level, bool Separate = false) const override;
282339

283340
private:
284341
unsigned short Levels;
342+
unsigned short SeparateLevels;
285343
bool LoopIndependent;
286344
bool Consistent; // Init to true, then refine.
287345
std::unique_ptr<DVEntry[]> DV;
346+
std::unique_ptr<DVEntry[]> DVSeparate;
288347
friend class DependenceInfo;
289348
};
290349

@@ -405,7 +464,8 @@ namespace llvm {
405464
const SCEV *A;
406465
const SCEV *B;
407466
const SCEV *C;
408-
const Loop *AssociatedLoop;
467+
const Loop *AssociatedSrcLoop;
468+
const Loop *AssociatedDstLoop;
409469

410470
public:
411471
/// isEmpty - Return true if the constraint is of kind Empty.
@@ -449,18 +509,25 @@ namespace llvm {
449509
/// Otherwise assert.
450510
const SCEV *getD() const;
451511

452-
/// getAssociatedLoop - Returns the loop associated with this constraint.
453-
const Loop *getAssociatedLoop() const;
512+
/// getAssociatedSrcLoop - Returns the source loop associated with this
513+
/// constraint.
514+
const Loop *getAssociatedSrcLoop() const;
515+
516+
/// getAssociatedDstLoop - Returns the destination loop associated with
517+
/// this constraint.
518+
const Loop *getAssociatedDstLoop() const;
454519

455520
/// setPoint - Change a constraint to Point.
456-
void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentLoop);
521+
void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentSrcLoop,
522+
const Loop *CurrentDstLoop);
457523

458524
/// setLine - Change a constraint to Line.
459-
void setLine(const SCEV *A, const SCEV *B,
460-
const SCEV *C, const Loop *CurrentLoop);
525+
void setLine(const SCEV *A, const SCEV *B, const SCEV *C,
526+
const Loop *CurrentSrcLoop, const Loop *CurrentDstLoop);
461527

462528
/// setDistance - Change a constraint to Distance.
463-
void setDistance(const SCEV *D, const Loop *CurrentLoop);
529+
void setDistance(const SCEV *D, const Loop *CurrentSrcLoop,
530+
const Loop *CurrentDstLoop);
464531

465532
/// setEmpty - Change a constraint to Empty.
466533
void setEmpty();
@@ -473,6 +540,10 @@ namespace llvm {
473540
void dump(raw_ostream &OS) const;
474541
};
475542

543+
/// Returns true if two loops are the same or they have the same tripcount
544+
/// and depth
545+
bool areLoopsSimilar(const Loop *SrcLoop, const Loop *DstLoop) const;
546+
476547
/// establishNestingLevels - Examines the loop nesting of the Src and Dst
477548
/// instructions and establishes their shared loops. Sets the variables
478549
/// CommonLevels, SrcLevels, and MaxLevels.
@@ -523,10 +594,15 @@ namespace llvm {
523594
/// e - 5
524595
/// f - 6
525596
/// g - 7 = MaxLevels
526-
void establishNestingLevels(const Instruction *Src,
527-
const Instruction *Dst);
597+
/// SeparateLevels counts the number of loop levels after the common levels
598+
/// that are not identical but are considered similar. Two levels are
599+
/// considered similar if they have the same trip count and the same
600+
/// nesting depth.
601+
/// For example, if loops `c` and `e` are similar, then they contribute to
602+
/// the SeparateLevels count and SeparateLevels is set to 1.
603+
void establishNestingLevels(const Instruction *Src, const Instruction *Dst);
528604

529-
unsigned CommonLevels, SrcLevels, MaxLevels;
605+
unsigned CommonLevels, SrcLevels, MaxLevels, SeparateLevels;
530606

531607
/// mapSrcLoop - Given one of the loops containing the source, return
532608
/// its level index in our numbering scheme.
@@ -665,13 +741,10 @@ namespace llvm {
665741
/// Returns true if any possible dependence is disproved.
666742
/// If there might be a dependence, returns false.
667743
/// Sets appropriate direction and distance.
668-
bool strongSIVtest(const SCEV *Coeff,
669-
const SCEV *SrcConst,
670-
const SCEV *DstConst,
671-
const Loop *CurrentLoop,
672-
unsigned Level,
673-
FullDependence &Result,
674-
Constraint &NewConstraint) const;
744+
bool strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
745+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
746+
const Loop *CurrentDstLoop, unsigned Level,
747+
FullDependence &Result, Constraint &NewConstraint) const;
675748

676749
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
677750
/// (Src and Dst) for dependence.
@@ -683,13 +756,10 @@ namespace llvm {
683756
/// Sets appropriate direction entry.
684757
/// Set consistent to false.
685758
/// Marks the dependence as splitable.
686-
bool weakCrossingSIVtest(const SCEV *SrcCoeff,
687-
const SCEV *SrcConst,
688-
const SCEV *DstConst,
689-
const Loop *CurrentLoop,
690-
unsigned Level,
691-
FullDependence &Result,
692-
Constraint &NewConstraint,
759+
bool weakCrossingSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
760+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
761+
const Loop *CurrentDstLoop, unsigned Level,
762+
FullDependence &Result, Constraint &NewConstraint,
693763
const SCEV *&SplitIter) const;
694764

695765
/// ExactSIVtest - Tests the SIV subscript pair
@@ -701,13 +771,10 @@ namespace llvm {
701771
/// If there might be a dependence, returns false.
702772
/// Sets appropriate direction entry.
703773
/// Set consistent to false.
704-
bool exactSIVtest(const SCEV *SrcCoeff,
705-
const SCEV *DstCoeff,
706-
const SCEV *SrcConst,
707-
const SCEV *DstConst,
708-
const Loop *CurrentLoop,
709-
unsigned Level,
710-
FullDependence &Result,
774+
bool exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
775+
const SCEV *SrcConst, const SCEV *DstConst,
776+
const Loop *CurrentSrcLoop, const Loop *CurrentDstLoop,
777+
unsigned Level, FullDependence &Result,
711778
Constraint &NewConstraint) const;
712779

713780
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
@@ -720,11 +787,9 @@ namespace llvm {
720787
/// Sets appropriate direction entry.
721788
/// Set consistent to false.
722789
/// If loop peeling will break the dependence, mark appropriately.
723-
bool weakZeroSrcSIVtest(const SCEV *DstCoeff,
724-
const SCEV *SrcConst,
725-
const SCEV *DstConst,
726-
const Loop *CurrentLoop,
727-
unsigned Level,
790+
bool weakZeroSrcSIVtest(const SCEV *DstCoeff, const SCEV *SrcConst,
791+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
792+
const Loop *CurrentDstLoop, unsigned Level,
728793
FullDependence &Result,
729794
Constraint &NewConstraint) const;
730795

@@ -738,11 +803,9 @@ namespace llvm {
738803
/// Sets appropriate direction entry.
739804
/// Set consistent to false.
740805
/// If loop peeling will break the dependence, mark appropriately.
741-
bool weakZeroDstSIVtest(const SCEV *SrcCoeff,
742-
const SCEV *SrcConst,
743-
const SCEV *DstConst,
744-
const Loop *CurrentLoop,
745-
unsigned Level,
806+
bool weakZeroDstSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
807+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
808+
const Loop *CurrentDstLoop, unsigned Level,
746809
FullDependence &Result,
747810
Constraint &NewConstraint) const;
748811

0 commit comments

Comments
 (0)