6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
//
9
- // This file implements a pass to test various loop fusion utility functions.
9
+ // This file implements a pass to test various loop fusion utilities. It is not
10
+ // meant to be a pass to perform valid fusion.
10
11
//
11
12
// ===----------------------------------------------------------------------===//
12
13
@@ -47,9 +48,9 @@ struct TestLoopFusion
47
48
llvm::cl::desc (" Enable testing of loop fusion slice computation" ),
48
49
llvm::cl::init (false )};
49
50
50
- Option<bool > clTestLoopFusionTransformation {
51
- *this , " test-loop-fusion-transformation " ,
52
- llvm::cl::desc (" Enable testing of loop fusion transformation" ),
51
+ Option<bool > clTestLoopFusionUtilities {
52
+ *this , " test-loop-fusion-utilities " ,
53
+ llvm::cl::desc (" Enable testing of loop fusion transformation utilities " ),
53
54
llvm::cl::init (false )};
54
55
};
55
56
@@ -62,10 +63,9 @@ struct TestLoopFusion
62
63
static bool testDependenceCheck (AffineForOp srcForOp, AffineForOp dstForOp,
63
64
unsigned i, unsigned j, unsigned loopDepth,
64
65
unsigned maxLoopDepth) {
65
- affine:: ComputationSliceState sliceUnion;
66
+ ComputationSliceState sliceUnion;
66
67
for (unsigned d = loopDepth + 1 ; d <= maxLoopDepth; ++d) {
67
- FusionResult result =
68
- affine::canFuseLoops (srcForOp, dstForOp, d, &sliceUnion);
68
+ FusionResult result = canFuseLoops (srcForOp, dstForOp, d, &sliceUnion);
69
69
if (result.value == FusionResult::FailBlockDependence) {
70
70
srcForOp->emitRemark (" block-level dependence preventing"
71
71
" fusion of loop nest " )
@@ -87,8 +87,7 @@ static unsigned getBlockIndex(Operation &op) {
87
87
}
88
88
89
89
// Returns a string representation of 'sliceUnion'.
90
- static std::string
91
- getSliceStr (const affine::ComputationSliceState &sliceUnion) {
90
+ static std::string getSliceStr (const ComputationSliceState &sliceUnion) {
92
91
std::string result;
93
92
llvm::raw_string_ostream os (result);
94
93
// Slice insertion point format [loop-depth, operation-block-index]
@@ -117,8 +116,8 @@ static bool testSliceComputation(AffineForOp forOpA, AffineForOp forOpB,
117
116
unsigned i, unsigned j, unsigned loopDepth,
118
117
unsigned maxLoopDepth) {
119
118
for (unsigned d = loopDepth + 1 ; d <= maxLoopDepth; ++d) {
120
- affine:: ComputationSliceState sliceUnion;
121
- FusionResult result = affine:: canFuseLoops (forOpA, forOpB, d, &sliceUnion);
119
+ ComputationSliceState sliceUnion;
120
+ FusionResult result = canFuseLoops (forOpA, forOpB, d, &sliceUnion);
122
121
if (result.value == FusionResult::Success) {
123
122
forOpB->emitRemark (" slice (" )
124
123
<< " src loop: " << i << " , dst loop: " << j << " , depth: " << d
@@ -134,22 +133,23 @@ static bool testSliceComputation(AffineForOp forOpA, AffineForOp forOpB,
134
133
135
134
// Attempts to fuse 'forOpA' into 'forOpB' at loop depths in range
136
135
// ['loopDepth' + 1, 'maxLoopDepth'].
137
- // Returns true if loops were successfully fused, false otherwise.
138
- static bool testLoopFusionTransformation (AffineForOp forOpA, AffineForOp forOpB,
139
- unsigned i, unsigned j ,
140
- unsigned loopDepth,
141
- unsigned maxLoopDepth) {
136
+ // Returns true if loops were successfully fused, false otherwise. This tests
137
+ // `fuseLoops` and `canFuseLoops` utilities.
138
+ static bool testLoopFusionUtilities (AffineForOp forOpA, AffineForOp forOpB ,
139
+ unsigned i, unsigned j, unsigned loopDepth,
140
+ unsigned maxLoopDepth) {
142
141
for (unsigned d = loopDepth + 1 ; d <= maxLoopDepth; ++d) {
143
- affine::ComputationSliceState sliceUnion;
144
- FusionResult result = affine::canFuseLoops (forOpA, forOpB, d, &sliceUnion);
145
- if (result.value == FusionResult::Success) {
146
- affine::fuseLoops (forOpA, forOpB, sliceUnion);
147
- // Note: 'forOpA' is removed to simplify test output. A proper loop
148
- // fusion pass should check the data dependence graph and run memref
149
- // region analysis to ensure removing 'forOpA' is safe.
142
+ ComputationSliceState sliceUnion;
143
+ // This check isn't a sufficient one, but necessary.
144
+ FusionResult result = canFuseLoops (forOpA, forOpB, d, &sliceUnion);
145
+ if (result.value != FusionResult::Success)
146
+ continue ;
147
+ fuseLoops (forOpA, forOpB, sliceUnion);
148
+ // Note: 'forOpA' is removed to simplify test output. A proper loop
149
+ // fusion pass should perform additional checks to check safe removal.
150
+ if (forOpA.use_empty ())
150
151
forOpA.erase ();
151
- return true ;
152
- }
152
+ return true ;
153
153
}
154
154
return false ;
155
155
}
@@ -182,15 +182,15 @@ static bool iterateLoops(ArrayRef<SmallVector<AffineForOp, 2>> depthToLoops,
182
182
183
183
void TestLoopFusion::runOnOperation () {
184
184
std::vector<SmallVector<AffineForOp, 2 >> depthToLoops;
185
- if (clTestLoopFusionTransformation ) {
185
+ if (clTestLoopFusionUtilities ) {
186
186
// Run loop fusion until a fixed point is reached.
187
187
do {
188
188
depthToLoops.clear ();
189
189
// Gather all AffineForOps by loop depth.
190
190
gatherLoops (getOperation (), depthToLoops);
191
191
192
192
// Try to fuse all combinations of src/dst loop nests in 'depthToLoops'.
193
- } while (iterateLoops (depthToLoops, testLoopFusionTransformation ,
193
+ } while (iterateLoops (depthToLoops, testLoopFusionUtilities ,
194
194
/* returnOnChange=*/ true ));
195
195
return ;
196
196
}
0 commit comments