@@ -82,6 +82,17 @@ class LLVM_ABI Dependence {
82
82
// / Dependence::DVEntry - Each level in the distance/direction vector
83
83
// / has a direction (or perhaps a union of several directions), and
84
84
// / perhaps a distance.
85
+ // / The dependency information could be across a single loop level or across
86
+ // / two separate levels that are candidates for fusion. Two levels are
87
+ // / considered fusable if they can be interpreted as a single fused loop,
88
+ // / i.e., have the same trip count and the same nesting depth.
89
+ // / For example, loops b and c are similar and considered as fusable loops:
90
+ // / for (a = ...) {
91
+ // / for (b = 0; b < 10; b++) {
92
+ // / }
93
+ // / for (c = 0; c < 10; c++) {
94
+ // / }
95
+ // / }
85
96
struct DVEntry {
86
97
enum : unsigned char {
87
98
NONE = 0 ,
@@ -144,12 +155,25 @@ class LLVM_ABI Dependence {
144
155
// / source and destination of the dependence.
145
156
virtual unsigned getLevels () const { return 0 ; }
146
157
147
- // / getDirection - Returns the direction associated with a particular level.
148
- virtual unsigned getDirection (unsigned Level) const { return DVEntry::ALL; }
158
+ // / getFusableLevels - Returns the number of fusable loops surrounding
159
+ // / the source and destination of the dependence.
160
+ virtual unsigned getFusableLevels () const { return 0 ; }
149
161
150
- // / getDistance - Returns the distance (or NULL) associated with a particular
151
- // / level.
152
- virtual const SCEV *getDistance (unsigned Level) const { return nullptr ; }
162
+ // / getDVEntry - Returns the DV entry associated with a regular or a
163
+ // / fusable level
164
+ DVEntry getDVEntry (unsigned Level, bool Fusable) const ;
165
+
166
+ // / getDirection - Returns the direction associated with a particular
167
+ // / common or fusable level.
168
+ virtual unsigned getDirection (unsigned Level, bool Fusable = false ) const {
169
+ return DVEntry::ALL;
170
+ }
171
+
172
+ // / getDistance - Returns the distance (or NULL) associated with a
173
+ // / particular common or fusable level.
174
+ virtual const SCEV *getDistance (unsigned Level, bool Fusable = false ) const {
175
+ return nullptr ;
176
+ }
153
177
154
178
// / Check if the direction vector is negative. A negative direction
155
179
// / vector means Src and Dst are reversed in the actual program.
@@ -162,21 +186,32 @@ class LLVM_ABI Dependence {
162
186
virtual bool normalize (ScalarEvolution *SE) { return false ; }
163
187
164
188
// / 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 ; }
189
+ // / this regular or fusable loop level will break this dependence.
190
+ virtual bool isPeelFirst (unsigned Level, bool Fusable = false ) const {
191
+ return false ;
192
+ }
167
193
168
194
// / 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 ; }
195
+ // / this regular or fusable loop level will break this dependence.
196
+ virtual bool isPeelLast (unsigned Level, bool Fusable = false ) const {
197
+ return false ;
198
+ }
171
199
172
- // / isSplitable - Returns true if splitting this loop will break the
173
- // / dependence.
174
- virtual bool isSplitable (unsigned Level) const { return false ; }
200
+ // / isSplitable - Returns true if splitting the loop will break
201
+ // / the dependence.
202
+ virtual bool isSplitable (unsigned Level, bool Fusable = false ) const {
203
+ return false ;
204
+ }
175
205
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 ;
206
+ // / inFusableLoops - Returns true if this level is a fusable level, i.e.,
207
+ // / performed across two separate loop nests that are treated like a single
208
+ // / fused loop.
209
+ virtual bool inFusableLoops (unsigned Level) const { return false ; }
210
+
211
+ // / isScalar - Returns true if a particular regular or fusable level is
212
+ // / scalar; that is, if no subscript in the source or destination mention
213
+ // / the induction variable associated with the loop at this level.
214
+ virtual bool isScalar (unsigned Level, bool Fusable = false ) const ;
180
215
181
216
// / getNextPredecessor - Returns the value of the NextPredecessor field.
182
217
const Dependence *getNextPredecessor () const { return NextPredecessor; }
@@ -198,6 +233,10 @@ class LLVM_ABI Dependence {
198
233
// / dump - For debugging purposes, dumps a dependence to OS.
199
234
void dump (raw_ostream &OS) const ;
200
235
236
+ // / dumpImp - For debugging purposes. Dumps a dependence to OS with or
237
+ // / without considering the fusable levels.
238
+ void dumpImp (raw_ostream &OS, bool Fusable = false ) const ;
239
+
201
240
protected:
202
241
Instruction *Src, *Dst;
203
242
@@ -238,13 +277,30 @@ class LLVM_ABI FullDependence final : public Dependence {
238
277
// / source and destination of the dependence.
239
278
unsigned getLevels () const override { return Levels; }
240
279
280
+ // / getFusableLevels - Returns the number of fusable loops surrounding
281
+ // / the source and destination of the dependence.
282
+ unsigned getFusableLevels () const override { return FusableLevels; }
283
+
284
+ // / getDVEntry - Returns the DV entry associated with a regular or a
285
+ // / fusable level
286
+ DVEntry getDVEntry (unsigned Level, bool Fusable) const {
287
+ if (!Fusable) {
288
+ assert (0 < Level && Level <= Levels && " Level out of range" );
289
+ return DV[Level - 1 ];
290
+ } else {
291
+ assert (Levels < Level && Level <= Levels + FusableLevels &&
292
+ " Fusable level out of range" );
293
+ return DVFusable[Level - Levels - 1 ];
294
+ }
295
+ }
296
+
241
297
// / getDirection - Returns the direction associated with a particular
242
- // / level.
243
- unsigned getDirection (unsigned Level) const override ;
298
+ // / common or fusable level.
299
+ unsigned getDirection (unsigned Level, bool Fusable = false ) const override ;
244
300
245
301
// / getDistance - Returns the distance (or NULL) associated with a
246
- // / particular level.
247
- const SCEV *getDistance (unsigned Level) const override ;
302
+ // / particular common or fusable level.
303
+ const SCEV *getDistance (unsigned Level, bool Fusable = false ) const override ;
248
304
249
305
// / Check if the direction vector is negative. A negative direction
250
306
// / vector means Src and Dst are reversed in the actual program.
@@ -257,27 +313,34 @@ class LLVM_ABI FullDependence final : public Dependence {
257
313
bool normalize (ScalarEvolution *SE) override ;
258
314
259
315
// / isPeelFirst - Returns true if peeling the first iteration from
260
- // / this loop will break this dependence.
261
- bool isPeelFirst (unsigned Level) const override ;
316
+ // / this regular or fusable loop level will break this dependence.
317
+ bool isPeelFirst (unsigned Level, bool Fusable = false ) const override ;
262
318
263
319
// / isPeelLast - Returns true if peeling the last iteration from
264
- // / this loop will break this dependence.
265
- bool isPeelLast (unsigned Level) const override ;
320
+ // / this regular or fusable loop level will break this dependence.
321
+ bool isPeelLast (unsigned Level, bool Fusable = false ) const override ;
266
322
267
323
// / isSplitable - Returns true if splitting the loop will break
268
324
// / the dependence.
269
- bool isSplitable (unsigned Level) const override ;
325
+ bool isSplitable (unsigned Level, bool Fusable = false ) const override ;
326
+
327
+ // / inFusableLoops - Returns true if this level is a fusable level, i.e.,
328
+ // / performed across two fusable loop nests that are treated like a single
329
+ // / fused loop.
330
+ bool inFusableLoops (unsigned Level) const override ;
270
331
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 ;
332
+ // / isScalar - Returns true if a particular regular or fusable level is
333
+ // / scalar; that is, if no subscript in the source or destination mention
334
+ // / the induction variable associated with the loop at this level.
335
+ bool isScalar (unsigned Level, bool Fusable = false ) const override ;
275
336
276
337
private:
277
338
unsigned short Levels;
339
+ unsigned short FusableLevels;
278
340
bool LoopIndependent;
279
341
bool Consistent; // Init to true, then refine.
280
342
std::unique_ptr<DVEntry[]> DV;
343
+ std::unique_ptr<DVEntry[]> DVFusable;
281
344
friend class DependenceInfo ;
282
345
};
283
346
@@ -406,7 +469,8 @@ class DependenceInfo {
406
469
const SCEV *A;
407
470
const SCEV *B;
408
471
const SCEV *C;
409
- const Loop *AssociatedLoop;
472
+ const Loop *AssociatedSrcLoop;
473
+ const Loop *AssociatedDstLoop;
410
474
411
475
public:
412
476
// / isEmpty - Return true if the constraint is of kind Empty.
@@ -450,19 +514,27 @@ class DependenceInfo {
450
514
// / Otherwise assert.
451
515
LLVM_ABI const SCEV *getD () const ;
452
516
453
- // / getAssociatedLoop - Returns the loop associated with this constraint.
454
- LLVM_ABI const Loop *getAssociatedLoop () const ;
517
+ // / getAssociatedSrcLoop - Returns the source loop associated with this
518
+ // / constraint.
519
+ LLVM_ABI const Loop *getAssociatedSrcLoop () const ;
520
+
521
+ // / getAssociatedDstLoop - Returns the destination loop associated with
522
+ // / this constraint.
523
+ LLVM_ABI const Loop *getAssociatedDstLoop () const ;
455
524
456
525
// / setPoint - Change a constraint to Point.
457
526
LLVM_ABI void setPoint (const SCEV *X, const SCEV *Y,
458
- const Loop *CurrentLoop);
527
+ const Loop *CurrentSrcLoop,
528
+ const Loop *CurrentDstLoop);
459
529
460
530
// / setLine - Change a constraint to Line.
461
531
LLVM_ABI void setLine (const SCEV *A, const SCEV *B, const SCEV *C,
462
- const Loop *CurrentLoop);
532
+ const Loop *CurrentSrcLoop,
533
+ const Loop *CurrentDstLoop);
463
534
464
535
// / setDistance - Change a constraint to Distance.
465
- LLVM_ABI void setDistance (const SCEV *D, const Loop *CurrentLoop);
536
+ LLVM_ABI void setDistance (const SCEV *D, const Loop *CurrentSrcLoop,
537
+ const Loop *CurrentDstLoop);
466
538
467
539
// / setEmpty - Change a constraint to Empty.
468
540
LLVM_ABI void setEmpty ();
@@ -475,6 +547,10 @@ class DependenceInfo {
475
547
LLVM_ABI void dump (raw_ostream &OS) const ;
476
548
};
477
549
550
+ // / Returns true if two loops are the same or they have the same tripcount
551
+ // / and depth
552
+ bool areLoopsSimilar (const Loop *SrcLoop, const Loop *DstLoop) const ;
553
+
478
554
// / establishNestingLevels - Examines the loop nesting of the Src and Dst
479
555
// / instructions and establishes their shared loops. Sets the variables
480
556
// / CommonLevels, SrcLevels, and MaxLevels.
@@ -525,9 +601,22 @@ class DependenceInfo {
525
601
// / e - 5
526
602
// / f - 6
527
603
// / g - 7 = MaxLevels
604
+ // / FusableLevels counts the number of levels after common levels that are
605
+ // / not common but are similar, meaning that they have the same tripcount and
606
+ // / depth. Assume that in this code fragment, levels c and e are similar. In
607
+ // / this case only the loop nests at the next level after common levels are
608
+ // / similar, and FusableLevels is set to 1. If there are similar loop nests,
609
+ // / we could use the APIs with considering them as fused loops. In that case
610
+ // / the level numbers for the 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
528
617
void establishNestingLevels (const Instruction *Src, const Instruction *Dst);
529
618
530
- unsigned CommonLevels, SrcLevels, MaxLevels;
619
+ unsigned CommonLevels, SrcLevels, MaxLevels, FusableLevels ;
531
620
532
621
// / mapSrcLoop - Given one of the loops containing the source, return
533
622
// / its level index in our numbering scheme.
@@ -652,9 +741,9 @@ class DependenceInfo {
652
741
// / If there might be a dependence, returns false.
653
742
// / Sets appropriate direction and distance.
654
743
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 ;
658
747
659
748
// / weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
660
749
// / (Src and Dst) for dependence.
@@ -667,9 +756,9 @@ class DependenceInfo {
667
756
// / Set consistent to false.
668
757
// / Marks the dependence as splitable.
669
758
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,
673
762
const SCEV *&SplitIter) const ;
674
763
675
764
// / ExactSIVtest - Tests the SIV subscript pair
@@ -683,8 +772,9 @@ class DependenceInfo {
683
772
// / Set consistent to false.
684
773
bool exactSIVtest (const SCEV *SrcCoeff, const SCEV *DstCoeff,
685
774
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 ;
688
778
689
779
// / weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
690
780
// / (Src and Dst) for dependence.
@@ -697,8 +787,9 @@ class DependenceInfo {
697
787
// / Set consistent to false.
698
788
// / If loop peeling will break the dependence, mark appropriately.
699
789
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,
702
793
Constraint &NewConstraint) const ;
703
794
704
795
// / weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair
@@ -712,8 +803,9 @@ class DependenceInfo {
712
803
// / Set consistent to false.
713
804
// / If loop peeling will break the dependence, mark appropriately.
714
805
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,
717
809
Constraint &NewConstraint) const ;
718
810
719
811
// / exactRDIVtest - Tests the RDIV subscript pair for dependence.
0 commit comments