Skip to content

Commit c68f98a

Browse files
committed
[DependenceAnalysis] 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.
1 parent 637e92b commit c68f98a

File tree

3 files changed

+597
-238
lines changed

3 files changed

+597
-238
lines changed

llvm/include/llvm/Analysis/DependenceAnalysis.h

Lines changed: 145 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ namespace llvm {
8282
/// Dependence::DVEntry - Each level in the distance/direction vector
8383
/// has a direction (or perhaps a union of several directions), and
8484
/// perhaps a distance.
85+
/// The dependency information could be across a single loop level or across
86+
/// two separate levels that are similar. Two levels are considered similar
87+
/// if they can be interpreted as a single fused loop, i.e., have the same
88+
/// trip count and the same nesting depth.
89+
/// For example, loops b and c are similar and considered as separate loops:
90+
/// for (a = ...) {
91+
/// for (b = 0; b < 10; b++) {
92+
/// }
93+
/// for (c = 0; c < 10; c++) {
94+
/// }
95+
/// }
8596
struct DVEntry {
8697
enum : unsigned char {
8798
NONE = 0,
@@ -153,13 +164,26 @@ namespace llvm {
153164
/// source and destination of the dependence.
154165
virtual unsigned getLevels() const { return 0; }
155166

167+
/// getSeparateLevels - Returns the number of separate loops surrounding
168+
/// the source and destination of the dependence.
169+
virtual unsigned getSeparateLevels() const { return 0; }
170+
171+
/// getDVEntry - Returns the DV entry associated with a regular or a
172+
/// separate level
173+
DVEntry getDVEntry(unsigned Level, bool Separate) const;
174+
156175
/// getDirection - Returns the direction associated with a particular
157-
/// level.
158-
virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; }
176+
/// common or separate level.
177+
virtual unsigned getDirection(unsigned Level, bool Separate = false) const {
178+
return DVEntry::ALL;
179+
}
159180

160181
/// getDistance - Returns the distance (or NULL) associated with a
161-
/// particular level.
162-
virtual const SCEV *getDistance(unsigned Level) const { return nullptr; }
182+
/// particular common or separate level.
183+
virtual const SCEV *getDistance(unsigned Level,
184+
bool Separate = false) const {
185+
return nullptr;
186+
}
163187

164188
/// Check if the direction vector is negative. A negative direction
165189
/// vector means Src and Dst are reversed in the actual program.
@@ -172,21 +196,32 @@ namespace llvm {
172196
virtual bool normalize(ScalarEvolution *SE) { return false; }
173197

174198
/// isPeelFirst - Returns true if peeling the first iteration from
175-
/// this loop will break this dependence.
176-
virtual bool isPeelFirst(unsigned Level) const { return false; }
199+
/// this regular or separate loop level will break this dependence.
200+
virtual bool isPeelFirst(unsigned Level, bool Separate = false) const {
201+
return false;
202+
}
177203

178204
/// isPeelLast - Returns true if peeling the last iteration from
179-
/// this loop will break this dependence.
180-
virtual bool isPeelLast(unsigned Level) const { return false; }
205+
/// this regular or separate loop level will break this dependence.
206+
virtual bool isPeelLast(unsigned Level, bool Separate = false) const {
207+
return false;
208+
}
181209

182-
/// isSplitable - Returns true if splitting this loop will break
210+
/// isSplitable - Returns true if splitting the loop will break
183211
/// the dependence.
184-
virtual bool isSplitable(unsigned Level) const { return false; }
212+
virtual bool isSplitable(unsigned Level, bool Separate = false) const {
213+
return false;
214+
}
215+
216+
/// inSeparateLoops - Returns true if this level is a separate level, i.e.,
217+
/// performed across two separate loop nests that are treated like a single
218+
/// fused loop.
219+
virtual bool inSeparateLoops(unsigned Level) const { return false; }
185220

186-
/// isScalar - Returns true if a particular level is scalar; that is,
187-
/// if no subscript in the source or destination mention the induction
188-
/// variable associated with the loop at this level.
189-
virtual bool isScalar(unsigned Level) const;
221+
/// isScalar - Returns true if a particular regular or separate level is
222+
/// scalar; that is, if no subscript in the source or destination mention
223+
/// the induction variable associated with the loop at this level.
224+
virtual bool isScalar(unsigned Level, bool Separate = false) const;
190225

191226
/// getNextPredecessor - Returns the value of the NextPredecessor
192227
/// field.
@@ -212,6 +247,10 @@ namespace llvm {
212247
///
213248
void dump(raw_ostream &OS) const;
214249

250+
/// dumpImp - For debugging purposes. Dumps a dependence to OS with or
251+
/// without considering the separate levels.
252+
void dumpImp(raw_ostream &OS, bool Separate = false) const;
253+
215254
protected:
216255
Instruction *Src, *Dst;
217256

@@ -252,13 +291,31 @@ namespace llvm {
252291
/// source and destination of the dependence.
253292
unsigned getLevels() const override { return Levels; }
254293

294+
/// getSeparateLevels - Returns the number of separate loops surrounding
295+
/// the source and destination of the dependence.
296+
unsigned getSeparateLevels() const override { return SeparateLevels; }
297+
298+
/// getDVEntry - Returns the DV entry associated with a regular or a
299+
/// separate level
300+
DVEntry getDVEntry(unsigned Level, bool Separate) const {
301+
if (!Separate) {
302+
assert(0 < Level && Level <= Levels && "Level out of range");
303+
return DV[Level - 1];
304+
} else {
305+
assert(Levels < Level && Level <= Levels + SeparateLevels &&
306+
"Separate level out of range");
307+
return DVSeparate[Level - Levels - 1];
308+
}
309+
}
310+
255311
/// getDirection - Returns the direction associated with a particular
256-
/// level.
257-
unsigned getDirection(unsigned Level) const override;
312+
/// common or separate level.
313+
unsigned getDirection(unsigned Level, bool Separate = false) const override;
258314

259315
/// getDistance - Returns the distance (or NULL) associated with a
260-
/// particular level.
261-
const SCEV *getDistance(unsigned Level) const override;
316+
/// particular common or separate level.
317+
const SCEV *getDistance(unsigned Level,
318+
bool Separate = false) const override;
262319

263320
/// Check if the direction vector is negative. A negative direction
264321
/// vector means Src and Dst are reversed in the actual program.
@@ -271,27 +328,34 @@ namespace llvm {
271328
bool normalize(ScalarEvolution *SE) override;
272329

273330
/// isPeelFirst - Returns true if peeling the first iteration from
274-
/// this loop will break this dependence.
275-
bool isPeelFirst(unsigned Level) const override;
331+
/// this regular or separate loop level will break this dependence.
332+
bool isPeelFirst(unsigned Level, bool Separate = false) const override;
276333

277334
/// isPeelLast - Returns true if peeling the last iteration from
278-
/// this loop will break this dependence.
279-
bool isPeelLast(unsigned Level) const override;
335+
/// this regular or separate loop level will break this dependence.
336+
bool isPeelLast(unsigned Level, bool Separate = false) const override;
280337

281338
/// isSplitable - Returns true if splitting the loop will break
282339
/// the dependence.
283-
bool isSplitable(unsigned Level) const override;
340+
bool isSplitable(unsigned Level, bool Separate = false) const override;
284341

285-
/// isScalar - Returns true if a particular level is scalar; that is,
286-
/// if no subscript in the source or destination mention the induction
287-
/// variable associated with the loop at this level.
288-
bool isScalar(unsigned Level) const override;
342+
/// inSeparateLoops - Returns true if this level is a separate level, i.e.,
343+
/// performed across two separate loop nests that are treated like a single
344+
/// fused loop.
345+
bool inSeparateLoops(unsigned Level) const override;
346+
347+
/// isScalar - Returns true if a particular regular or separate level is
348+
/// scalar; that is, if no subscript in the source or destination mention
349+
/// the induction variable associated with the loop at this level.
350+
bool isScalar(unsigned Level, bool Separate = false) const override;
289351

290352
private:
291353
unsigned short Levels;
354+
unsigned short SeparateLevels;
292355
bool LoopIndependent;
293356
bool Consistent; // Init to true, then refine.
294357
std::unique_ptr<DVEntry[]> DV;
358+
std::unique_ptr<DVEntry[]> DVSeparate;
295359
friend class DependenceInfo;
296360
};
297361

@@ -423,7 +487,8 @@ namespace llvm {
423487
const SCEV *A;
424488
const SCEV *B;
425489
const SCEV *C;
426-
const Loop *AssociatedLoop;
490+
const Loop *AssociatedSrcLoop;
491+
const Loop *AssociatedDstLoop;
427492

428493
public:
429494
/// isEmpty - Return true if the constraint is of kind Empty.
@@ -467,19 +532,27 @@ namespace llvm {
467532
/// Otherwise assert.
468533
LLVM_ABI const SCEV *getD() const;
469534

470-
/// getAssociatedLoop - Returns the loop associated with this constraint.
471-
LLVM_ABI const Loop *getAssociatedLoop() const;
535+
/// getAssociatedSrcLoop - Returns the source loop associated with this
536+
/// constraint.
537+
LLVM_ABI const Loop *getAssociatedSrcLoop() const;
538+
539+
/// getAssociatedDstLoop - Returns the destination loop associated with
540+
/// this constraint.
541+
LLVM_ABI const Loop *getAssociatedDstLoop() const;
472542

473543
/// setPoint - Change a constraint to Point.
474544
LLVM_ABI void setPoint(const SCEV *X, const SCEV *Y,
475-
const Loop *CurrentLoop);
545+
const Loop *CurrentSrcLoop,
546+
const Loop *CurrentDstLoop);
476547

477548
/// setLine - Change a constraint to Line.
478549
LLVM_ABI void setLine(const SCEV *A, const SCEV *B, const SCEV *C,
479-
const Loop *CurrentLoop);
550+
const Loop *CurrentSrcLoop,
551+
const Loop *CurrentDstLoop);
480552

481553
/// setDistance - Change a constraint to Distance.
482-
LLVM_ABI void setDistance(const SCEV *D, const Loop *CurrentLoop);
554+
LLVM_ABI void setDistance(const SCEV *D, const Loop *CurrentSrcLoop,
555+
const Loop *CurrentDstLoop);
483556

484557
/// setEmpty - Change a constraint to Empty.
485558
LLVM_ABI void setEmpty();
@@ -492,6 +565,10 @@ namespace llvm {
492565
LLVM_ABI void dump(raw_ostream &OS) const;
493566
};
494567

568+
/// Returns true if two loops are the same or they have the same tripcount
569+
/// and depth
570+
bool areLoopsSimilar(const Loop *SrcLoop, const Loop *DstLoop) const;
571+
495572
/// establishNestingLevels - Examines the loop nesting of the Src and Dst
496573
/// instructions and establishes their shared loops. Sets the variables
497574
/// CommonLevels, SrcLevels, and MaxLevels.
@@ -542,10 +619,23 @@ namespace llvm {
542619
/// e - 5
543620
/// f - 6
544621
/// g - 7 = MaxLevels
545-
void establishNestingLevels(const Instruction *Src,
546-
const Instruction *Dst);
547-
548-
unsigned CommonLevels, SrcLevels, MaxLevels;
622+
/// SeparateLevels counts the number of levels after common levels that are
623+
/// not common but are similar, meaning that they have the same tripcount
624+
/// and depth. Assume that in this code fragment, levels c and e are
625+
/// similar. In this case only the loop nests at the next level after
626+
/// common levels are similar, and SeparateLevel is set to 1.
627+
/// If there are similar loop nests, we could use the APIs with considering
628+
/// them as fused loops. In that case the level numbers for the previous
629+
/// code look like
630+
/// a - 1
631+
/// b - 2
632+
/// c,e - 3 = CommonLevels
633+
/// d - 4 = SrcLevels
634+
/// f - 5
635+
/// g - 6 = MaxLevels
636+
void establishNestingLevels(const Instruction *Src, const Instruction *Dst);
637+
638+
unsigned CommonLevels, SrcLevels, MaxLevels, SeparateLevels;
549639

550640
/// mapSrcLoop - Given one of the loops containing the source, return
551641
/// its level index in our numbering scheme.
@@ -684,13 +774,10 @@ namespace llvm {
684774
/// Returns true if any possible dependence is disproved.
685775
/// If there might be a dependence, returns false.
686776
/// Sets appropriate direction and distance.
687-
bool strongSIVtest(const SCEV *Coeff,
688-
const SCEV *SrcConst,
689-
const SCEV *DstConst,
690-
const Loop *CurrentLoop,
691-
unsigned Level,
692-
FullDependence &Result,
693-
Constraint &NewConstraint) const;
777+
bool strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
778+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
779+
const Loop *CurrentDstLoop, unsigned Level,
780+
FullDependence &Result, Constraint &NewConstraint) const;
694781

695782
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
696783
/// (Src and Dst) for dependence.
@@ -702,13 +789,10 @@ namespace llvm {
702789
/// Sets appropriate direction entry.
703790
/// Set consistent to false.
704791
/// Marks the dependence as splitable.
705-
bool weakCrossingSIVtest(const SCEV *SrcCoeff,
706-
const SCEV *SrcConst,
707-
const SCEV *DstConst,
708-
const Loop *CurrentLoop,
709-
unsigned Level,
710-
FullDependence &Result,
711-
Constraint &NewConstraint,
792+
bool weakCrossingSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
793+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
794+
const Loop *CurrentDstLoop, unsigned Level,
795+
FullDependence &Result, Constraint &NewConstraint,
712796
const SCEV *&SplitIter) const;
713797

714798
/// ExactSIVtest - Tests the SIV subscript pair
@@ -720,13 +804,10 @@ namespace llvm {
720804
/// If there might be a dependence, returns false.
721805
/// Sets appropriate direction entry.
722806
/// Set consistent to false.
723-
bool exactSIVtest(const SCEV *SrcCoeff,
724-
const SCEV *DstCoeff,
725-
const SCEV *SrcConst,
726-
const SCEV *DstConst,
727-
const Loop *CurrentLoop,
728-
unsigned Level,
729-
FullDependence &Result,
807+
bool exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
808+
const SCEV *SrcConst, const SCEV *DstConst,
809+
const Loop *CurrentSrcLoop, const Loop *CurrentDstLoop,
810+
unsigned Level, FullDependence &Result,
730811
Constraint &NewConstraint) const;
731812

732813
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
@@ -739,11 +820,9 @@ namespace llvm {
739820
/// Sets appropriate direction entry.
740821
/// Set consistent to false.
741822
/// If loop peeling will break the dependence, mark appropriately.
742-
bool weakZeroSrcSIVtest(const SCEV *DstCoeff,
743-
const SCEV *SrcConst,
744-
const SCEV *DstConst,
745-
const Loop *CurrentLoop,
746-
unsigned Level,
823+
bool weakZeroSrcSIVtest(const SCEV *DstCoeff, const SCEV *SrcConst,
824+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
825+
const Loop *CurrentDstLoop, unsigned Level,
747826
FullDependence &Result,
748827
Constraint &NewConstraint) const;
749828

@@ -757,11 +836,9 @@ namespace llvm {
757836
/// Sets appropriate direction entry.
758837
/// Set consistent to false.
759838
/// If loop peeling will break the dependence, mark appropriately.
760-
bool weakZeroDstSIVtest(const SCEV *SrcCoeff,
761-
const SCEV *SrcConst,
762-
const SCEV *DstConst,
763-
const Loop *CurrentLoop,
764-
unsigned Level,
839+
bool weakZeroDstSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
840+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
841+
const Loop *CurrentDstLoop, unsigned Level,
765842
FullDependence &Result,
766843
Constraint &NewConstraint) const;
767844

0 commit comments

Comments
 (0)