Skip to content

Commit ede8ec2

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 ede8ec2

File tree

3 files changed

+576
-237
lines changed

3 files changed

+576
-237
lines changed

llvm/include/llvm/Analysis/DependenceAnalysis.h

Lines changed: 134 additions & 67 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,31 @@ 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.
218+
virtual bool inSeparateLoops(unsigned Level) const { return false; }
185219

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;
220+
/// isScalar - Returns true if a particular regular or separate level is
221+
/// scalar; that is, if no subscript in the source or destination mention
222+
/// the induction variable associated with the loop at this level.
223+
virtual bool isScalar(unsigned Level, bool Separate = false) const;
190224

191225
/// getNextPredecessor - Returns the value of the NextPredecessor
192226
/// field.
@@ -212,6 +246,10 @@ namespace llvm {
212246
///
213247
void dump(raw_ostream &OS) const;
214248

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

@@ -252,13 +290,31 @@ namespace llvm {
252290
/// source and destination of the dependence.
253291
unsigned getLevels() const override { return Levels; }
254292

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

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

263319
/// Check if the direction vector is negative. A negative direction
264320
/// vector means Src and Dst are reversed in the actual program.
@@ -271,27 +327,33 @@ namespace llvm {
271327
bool normalize(ScalarEvolution *SE) override;
272328

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

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

281337
/// isSplitable - Returns true if splitting the loop will break
282338
/// the dependence.
283-
bool isSplitable(unsigned Level) const override;
339+
bool isSplitable(unsigned Level, bool Separate = false) const override;
284340

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;
341+
/// inSeparateLoops - Returns true if this level is a separate level, i.e.,
342+
/// performed across two separate loop nests.
343+
bool inSeparateLoops(unsigned Level) const override;
344+
345+
/// isScalar - Returns true if a particular regular or separate level is
346+
/// scalar; that is, if no subscript in the source or destination mention
347+
/// the induction variable associated with the loop at this level.
348+
bool isScalar(unsigned Level, bool Separate = false) const override;
289349

290350
private:
291351
unsigned short Levels;
352+
unsigned short SeparateLevels;
292353
bool LoopIndependent;
293354
bool Consistent; // Init to true, then refine.
294355
std::unique_ptr<DVEntry[]> DV;
356+
std::unique_ptr<DVEntry[]> DVSeparate;
295357
friend class DependenceInfo;
296358
};
297359

@@ -423,7 +485,8 @@ namespace llvm {
423485
const SCEV *A;
424486
const SCEV *B;
425487
const SCEV *C;
426-
const Loop *AssociatedLoop;
488+
const Loop *AssociatedSrcLoop;
489+
const Loop *AssociatedDstLoop;
427490

428491
public:
429492
/// isEmpty - Return true if the constraint is of kind Empty.
@@ -467,19 +530,27 @@ namespace llvm {
467530
/// Otherwise assert.
468531
LLVM_ABI const SCEV *getD() const;
469532

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

473541
/// setPoint - Change a constraint to Point.
474542
LLVM_ABI void setPoint(const SCEV *X, const SCEV *Y,
475-
const Loop *CurrentLoop);
543+
const Loop *CurrentSrcLoop,
544+
const Loop *CurrentDstLoop);
476545

477546
/// setLine - Change a constraint to Line.
478547
LLVM_ABI void setLine(const SCEV *A, const SCEV *B, const SCEV *C,
479-
const Loop *CurrentLoop);
548+
const Loop *CurrentSrcLoop,
549+
const Loop *CurrentDstLoop);
480550

481551
/// setDistance - Change a constraint to Distance.
482-
LLVM_ABI void setDistance(const SCEV *D, const Loop *CurrentLoop);
552+
LLVM_ABI void setDistance(const SCEV *D, const Loop *CurrentSrcLoop,
553+
const Loop *CurrentDstLoop);
483554

484555
/// setEmpty - Change a constraint to Empty.
485556
LLVM_ABI void setEmpty();
@@ -492,6 +563,10 @@ namespace llvm {
492563
LLVM_ABI void dump(raw_ostream &OS) const;
493564
};
494565

566+
/// Returns true if two loops are the same or they have the same tripcount
567+
/// and depth
568+
bool areLoopsSimilar(const Loop *SrcLoop, const Loop *DstLoop) const;
569+
495570
/// establishNestingLevels - Examines the loop nesting of the Src and Dst
496571
/// instructions and establishes their shared loops. Sets the variables
497572
/// CommonLevels, SrcLevels, and MaxLevels.
@@ -542,10 +617,15 @@ namespace llvm {
542617
/// e - 5
543618
/// f - 6
544619
/// g - 7 = MaxLevels
545-
void establishNestingLevels(const Instruction *Src,
546-
const Instruction *Dst);
620+
/// SeparateLevels counts the number of loop levels after the common levels
621+
/// that are not identical but are considered similar. Two levels are
622+
/// considered similar if they have the same trip count and the same
623+
/// nesting depth.
624+
/// For example, if loops `c` and `e` are similar, then they contribute to
625+
/// the SeparateLevels count and SeparateLevels is set to 1.
626+
void establishNestingLevels(const Instruction *Src, const Instruction *Dst);
547627

548-
unsigned CommonLevels, SrcLevels, MaxLevels;
628+
unsigned CommonLevels, SrcLevels, MaxLevels, SeparateLevels;
549629

550630
/// mapSrcLoop - Given one of the loops containing the source, return
551631
/// its level index in our numbering scheme.
@@ -684,13 +764,10 @@ namespace llvm {
684764
/// Returns true if any possible dependence is disproved.
685765
/// If there might be a dependence, returns false.
686766
/// 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;
767+
bool strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
768+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
769+
const Loop *CurrentDstLoop, unsigned Level,
770+
FullDependence &Result, Constraint &NewConstraint) const;
694771

695772
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
696773
/// (Src and Dst) for dependence.
@@ -702,13 +779,10 @@ namespace llvm {
702779
/// Sets appropriate direction entry.
703780
/// Set consistent to false.
704781
/// 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,
782+
bool weakCrossingSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
783+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
784+
const Loop *CurrentDstLoop, unsigned Level,
785+
FullDependence &Result, Constraint &NewConstraint,
712786
const SCEV *&SplitIter) const;
713787

714788
/// ExactSIVtest - Tests the SIV subscript pair
@@ -720,13 +794,10 @@ namespace llvm {
720794
/// If there might be a dependence, returns false.
721795
/// Sets appropriate direction entry.
722796
/// 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,
797+
bool exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
798+
const SCEV *SrcConst, const SCEV *DstConst,
799+
const Loop *CurrentSrcLoop, const Loop *CurrentDstLoop,
800+
unsigned Level, FullDependence &Result,
730801
Constraint &NewConstraint) const;
731802

732803
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
@@ -739,11 +810,9 @@ namespace llvm {
739810
/// Sets appropriate direction entry.
740811
/// Set consistent to false.
741812
/// 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,
813+
bool weakZeroSrcSIVtest(const SCEV *DstCoeff, const SCEV *SrcConst,
814+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
815+
const Loop *CurrentDstLoop, unsigned Level,
747816
FullDependence &Result,
748817
Constraint &NewConstraint) const;
749818

@@ -757,11 +826,9 @@ namespace llvm {
757826
/// Sets appropriate direction entry.
758827
/// Set consistent to false.
759828
/// 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,
829+
bool weakZeroDstSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
830+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
831+
const Loop *CurrentDstLoop, unsigned Level,
765832
FullDependence &Result,
766833
Constraint &NewConstraint) const;
767834

0 commit comments

Comments
 (0)