Skip to content

Commit b4a17b1

Browse files
authored
[DependenceAnalysis] Extending SIV to handle fusable loops (#128782)
When there is a dependency between two memory instructions in separate loops that have the same iteration space and depth, SIV will be able to test them and compute the direction and the distance of the dependency.
1 parent cfabbf0 commit b4a17b1

File tree

3 files changed

+705
-206
lines changed

3 files changed

+705
-206
lines changed

llvm/include/llvm/Analysis/DependenceAnalysis.h

Lines changed: 140 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ class LLVM_ABI Dependence {
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 have the same trip count and nesting depth,
87+
/// which helps to provide information for loop fusion candidation.
88+
/// For example, loops b and c have the same iteration count and depth:
89+
/// for (a = ...) {
90+
/// for (b = 0; b < 10; b++) {
91+
/// }
92+
/// for (c = 0; c < 10; c++) {
93+
/// }
94+
/// }
8595
struct DVEntry {
8696
enum : unsigned char {
8797
NONE = 0,
@@ -144,12 +154,25 @@ class LLVM_ABI Dependence {
144154
/// source and destination of the dependence.
145155
virtual unsigned getLevels() const { return 0; }
146156

147-
/// getDirection - Returns the direction associated with a particular level.
148-
virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; }
157+
/// getSameSDLevels - Returns the number of separate SameSD loops surrounding
158+
/// the source and destination of the dependence.
159+
virtual unsigned getSameSDLevels() const { return 0; }
149160

150-
/// getDistance - Returns the distance (or NULL) associated with a particular
151-
/// level.
152-
virtual const SCEV *getDistance(unsigned Level) const { return nullptr; }
161+
/// getDVEntry - Returns the DV entry associated with a regular or a
162+
/// SameSD level
163+
DVEntry getDVEntry(unsigned Level, bool isSameSD) const;
164+
165+
/// getDirection - Returns the direction associated with a particular
166+
/// common or SameSD level.
167+
virtual unsigned getDirection(unsigned Level, bool SameSD = false) const {
168+
return DVEntry::ALL;
169+
}
170+
171+
/// getDistance - Returns the distance (or NULL) associated with a
172+
/// particular common or SameSD level.
173+
virtual const SCEV *getDistance(unsigned Level, bool SameSD = false) const {
174+
return nullptr;
175+
}
153176

154177
/// Check if the direction vector is negative. A negative direction
155178
/// vector means Src and Dst are reversed in the actual program.
@@ -162,21 +185,32 @@ class LLVM_ABI Dependence {
162185
virtual bool normalize(ScalarEvolution *SE) { return false; }
163186

164187
/// isPeelFirst - Returns true if peeling the first iteration from
165-
/// this loop will break this dependence.
166-
virtual bool isPeelFirst(unsigned Level) const { return false; }
188+
/// this regular or SameSD loop level will break this dependence.
189+
virtual bool isPeelFirst(unsigned Level, bool SameSD = false) const {
190+
return false;
191+
}
167192

168193
/// isPeelLast - Returns true if peeling the last iteration from
169-
/// this loop will break this dependence.
170-
virtual bool isPeelLast(unsigned Level) const { return false; }
194+
/// this regular or SameSD loop level will break this dependence.
195+
virtual bool isPeelLast(unsigned Level, bool SameSD = false) const {
196+
return false;
197+
}
171198

172-
/// isSplitable - Returns true if splitting this loop will break the
173-
/// dependence.
174-
virtual bool isSplitable(unsigned Level) const { return false; }
199+
/// isSplitable - Returns true if splitting the loop will break
200+
/// the dependence.
201+
virtual bool isSplitable(unsigned Level, bool SameSD = false) const {
202+
return false;
203+
}
175204

176-
/// isScalar - Returns true if a particular level is scalar; that is,
177-
/// if no subscript in the source or destination mention the induction
178-
/// variable associated with the loop at this level.
179-
virtual bool isScalar(unsigned Level) const;
205+
/// inSameSDLoops - Returns true if this level is an SameSD level, i.e.,
206+
/// performed across two separate loop nests that have the Same Iteration and
207+
/// Depth.
208+
virtual bool inSameSDLoops(unsigned Level) const { return false; }
209+
210+
/// isScalar - Returns true if a particular regular or SameSD level is
211+
/// scalar; that is, if no subscript in the source or destination mention
212+
/// the induction variable associated with the loop at this level.
213+
virtual bool isScalar(unsigned Level, bool SameSD = false) const;
180214

181215
/// getNextPredecessor - Returns the value of the NextPredecessor field.
182216
const Dependence *getNextPredecessor() const { return NextPredecessor; }
@@ -198,6 +232,10 @@ class LLVM_ABI Dependence {
198232
/// dump - For debugging purposes, dumps a dependence to OS.
199233
void dump(raw_ostream &OS) const;
200234

235+
/// dumpImp - For debugging purposes. Dumps a dependence to OS with or
236+
/// without considering the SameSD levels.
237+
void dumpImp(raw_ostream &OS, bool SameSD = false) const;
238+
201239
protected:
202240
Instruction *Src, *Dst;
203241

@@ -238,13 +276,30 @@ class LLVM_ABI FullDependence final : public Dependence {
238276
/// source and destination of the dependence.
239277
unsigned getLevels() const override { return Levels; }
240278

279+
/// getSameSDLevels - Returns the number of separate SameSD loops surrounding
280+
/// the source and destination of the dependence.
281+
unsigned getSameSDLevels() const override { return SameSDLevels; }
282+
283+
/// getDVEntry - Returns the DV entry associated with a regular or a
284+
/// SameSD level.
285+
DVEntry getDVEntry(unsigned Level, bool isSameSD) const {
286+
if (!isSameSD) {
287+
assert(0 < Level && Level <= Levels && "Level out of range");
288+
return DV[Level - 1];
289+
} else {
290+
assert(Levels < Level && Level <= Levels + SameSDLevels &&
291+
"isSameSD level out of range");
292+
return DVSameSD[Level - Levels - 1];
293+
}
294+
}
295+
241296
/// getDirection - Returns the direction associated with a particular
242-
/// level.
243-
unsigned getDirection(unsigned Level) const override;
297+
/// common or SameSD level.
298+
unsigned getDirection(unsigned Level, bool SameSD = false) const override;
244299

245300
/// getDistance - Returns the distance (or NULL) associated with a
246-
/// particular level.
247-
const SCEV *getDistance(unsigned Level) const override;
301+
/// particular common or SameSD level.
302+
const SCEV *getDistance(unsigned Level, bool SameSD = false) const override;
248303

249304
/// Check if the direction vector is negative. A negative direction
250305
/// vector means Src and Dst are reversed in the actual program.
@@ -257,27 +312,34 @@ class LLVM_ABI FullDependence final : public Dependence {
257312
bool normalize(ScalarEvolution *SE) override;
258313

259314
/// isPeelFirst - Returns true if peeling the first iteration from
260-
/// this loop will break this dependence.
261-
bool isPeelFirst(unsigned Level) const override;
315+
/// this regular or SameSD loop level will break this dependence.
316+
bool isPeelFirst(unsigned Level, bool SameSD = false) const override;
262317

263318
/// isPeelLast - Returns true if peeling the last iteration from
264-
/// this loop will break this dependence.
265-
bool isPeelLast(unsigned Level) const override;
319+
/// this regular or SameSD loop level will break this dependence.
320+
bool isPeelLast(unsigned Level, bool SameSD = false) const override;
266321

267322
/// isSplitable - Returns true if splitting the loop will break
268323
/// the dependence.
269-
bool isSplitable(unsigned Level) const override;
324+
bool isSplitable(unsigned Level, bool SameSD = false) const override;
325+
326+
/// inSameSDLoops - Returns true if this level is an SameSD level, i.e.,
327+
/// performed across two separate loop nests that have the Same Iteration and
328+
/// Depth.
329+
bool inSameSDLoops(unsigned Level) const override;
270330

271-
/// isScalar - Returns true if a particular level is scalar; that is,
272-
/// if no subscript in the source or destination mention the induction
273-
/// variable associated with the loop at this level.
274-
bool isScalar(unsigned Level) const override;
331+
/// isScalar - Returns true if a particular regular or SameSD level is
332+
/// scalar; that is, if no subscript in the source or destination mention
333+
/// the induction variable associated with the loop at this level.
334+
bool isScalar(unsigned Level, bool SameSD = false) const override;
275335

276336
private:
277337
unsigned short Levels;
338+
unsigned short SameSDLevels;
278339
bool LoopIndependent;
279340
bool Consistent; // Init to true, then refine.
280341
std::unique_ptr<DVEntry[]> DV;
342+
std::unique_ptr<DVEntry[]> DVSameSD; // DV entries on SameSD levels
281343
friend class DependenceInfo;
282344
};
283345

@@ -406,7 +468,8 @@ class DependenceInfo {
406468
const SCEV *A;
407469
const SCEV *B;
408470
const SCEV *C;
409-
const Loop *AssociatedLoop;
471+
const Loop *AssociatedSrcLoop;
472+
const Loop *AssociatedDstLoop;
410473

411474
public:
412475
/// isEmpty - Return true if the constraint is of kind Empty.
@@ -450,19 +513,27 @@ class DependenceInfo {
450513
/// Otherwise assert.
451514
LLVM_ABI const SCEV *getD() const;
452515

453-
/// getAssociatedLoop - Returns the loop associated with this constraint.
454-
LLVM_ABI const Loop *getAssociatedLoop() const;
516+
/// getAssociatedSrcLoop - Returns the source loop associated with this
517+
/// constraint.
518+
LLVM_ABI const Loop *getAssociatedSrcLoop() const;
519+
520+
/// getAssociatedDstLoop - Returns the destination loop associated with
521+
/// this constraint.
522+
LLVM_ABI const Loop *getAssociatedDstLoop() const;
455523

456524
/// setPoint - Change a constraint to Point.
457525
LLVM_ABI void setPoint(const SCEV *X, const SCEV *Y,
458-
const Loop *CurrentLoop);
526+
const Loop *CurrentSrcLoop,
527+
const Loop *CurrentDstLoop);
459528

460529
/// setLine - Change a constraint to Line.
461530
LLVM_ABI void setLine(const SCEV *A, const SCEV *B, const SCEV *C,
462-
const Loop *CurrentLoop);
531+
const Loop *CurrentSrcLoop,
532+
const Loop *CurrentDstLoop);
463533

464534
/// setDistance - Change a constraint to Distance.
465-
LLVM_ABI void setDistance(const SCEV *D, const Loop *CurrentLoop);
535+
LLVM_ABI void setDistance(const SCEV *D, const Loop *CurrentSrcLoop,
536+
const Loop *CurrentDstLoop);
466537

467538
/// setEmpty - Change a constraint to Empty.
468539
LLVM_ABI void setEmpty();
@@ -475,6 +546,12 @@ class DependenceInfo {
475546
LLVM_ABI void dump(raw_ostream &OS) const;
476547
};
477548

549+
/// Returns true if two loops have the Same iteration Space and Depth. To be
550+
/// more specific, two loops have SameSD if they are in the same nesting
551+
/// depth and have the same backedge count. SameSD stands for Same iteration
552+
/// Space and Depth.
553+
bool haveSameSD(const Loop *SrcLoop, const Loop *DstLoop) const;
554+
478555
/// establishNestingLevels - Examines the loop nesting of the Src and Dst
479556
/// instructions and establishes their shared loops. Sets the variables
480557
/// CommonLevels, SrcLevels, and MaxLevels.
@@ -525,9 +602,21 @@ class DependenceInfo {
525602
/// e - 5
526603
/// f - 6
527604
/// g - 7 = MaxLevels
605+
/// SameSDLevels counts the number of levels after common levels that are
606+
/// not common but have the same iteration space and depth. Internally this
607+
/// is checked using haveSameSD. Assume that in this code fragment, levels c
608+
/// and e have the same iteration space and depth, but levels d and f does
609+
/// not. Then SameSDLevels is set to 1. In that case the level numbers for the
610+
/// previous code look like
611+
/// a - 1
612+
/// b - 2
613+
/// c,e - 3 = CommonLevels
614+
/// d - 4 = SrcLevels
615+
/// f - 5
616+
/// g - 6 = MaxLevels
528617
void establishNestingLevels(const Instruction *Src, const Instruction *Dst);
529618

530-
unsigned CommonLevels, SrcLevels, MaxLevels;
619+
unsigned CommonLevels, SrcLevels, MaxLevels, SameSDLevels;
531620

532621
/// mapSrcLoop - Given one of the loops containing the source, return
533622
/// its level index in our numbering scheme.
@@ -652,9 +741,9 @@ class DependenceInfo {
652741
/// If there might be a dependence, returns false.
653742
/// Sets appropriate direction and distance.
654743
bool strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
655-
const SCEV *DstConst, const Loop *CurrentLoop,
656-
unsigned Level, FullDependence &Result,
657-
Constraint &NewConstraint) const;
744+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
745+
const Loop *CurrentDstLoop, unsigned Level,
746+
FullDependence &Result, Constraint &NewConstraint) const;
658747

659748
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
660749
/// (Src and Dst) for dependence.
@@ -667,9 +756,9 @@ class DependenceInfo {
667756
/// Set consistent to false.
668757
/// Marks the dependence as splitable.
669758
bool weakCrossingSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
670-
const SCEV *DstConst, const Loop *CurrentLoop,
671-
unsigned Level, FullDependence &Result,
672-
Constraint &NewConstraint,
759+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
760+
const Loop *CurrentDstLoop, unsigned Level,
761+
FullDependence &Result, Constraint &NewConstraint,
673762
const SCEV *&SplitIter) const;
674763

675764
/// ExactSIVtest - Tests the SIV subscript pair
@@ -683,8 +772,9 @@ class DependenceInfo {
683772
/// Set consistent to false.
684773
bool exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
685774
const SCEV *SrcConst, const SCEV *DstConst,
686-
const Loop *CurrentLoop, unsigned Level,
687-
FullDependence &Result, Constraint &NewConstraint) const;
775+
const Loop *CurrentSrcLoop, const Loop *CurrentDstLoop,
776+
unsigned Level, FullDependence &Result,
777+
Constraint &NewConstraint) const;
688778

689779
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
690780
/// (Src and Dst) for dependence.
@@ -697,8 +787,9 @@ class DependenceInfo {
697787
/// Set consistent to false.
698788
/// If loop peeling will break the dependence, mark appropriately.
699789
bool weakZeroSrcSIVtest(const SCEV *DstCoeff, const SCEV *SrcConst,
700-
const SCEV *DstConst, const Loop *CurrentLoop,
701-
unsigned Level, FullDependence &Result,
790+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
791+
const Loop *CurrentDstLoop, unsigned Level,
792+
FullDependence &Result,
702793
Constraint &NewConstraint) const;
703794

704795
/// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair
@@ -712,8 +803,9 @@ class DependenceInfo {
712803
/// Set consistent to false.
713804
/// If loop peeling will break the dependence, mark appropriately.
714805
bool weakZeroDstSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
715-
const SCEV *DstConst, const Loop *CurrentLoop,
716-
unsigned Level, FullDependence &Result,
806+
const SCEV *DstConst, const Loop *CurrentSrcLoop,
807+
const Loop *CurrentDstLoop, unsigned Level,
808+
FullDependence &Result,
717809
Constraint &NewConstraint) const;
718810

719811
/// exactRDIVtest - Tests the RDIV subscript pair for dependence.

0 commit comments

Comments
 (0)