66//
77// ===----------------------------------------------------------------------===//
88//
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.
1011//
1112// ===----------------------------------------------------------------------===//
1213
@@ -47,9 +48,9 @@ struct TestLoopFusion
4748 llvm::cl::desc (" Enable testing of loop fusion slice computation" ),
4849 llvm::cl::init (false )};
4950
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 " ),
5354 llvm::cl::init (false )};
5455};
5556
@@ -62,10 +63,9 @@ struct TestLoopFusion
6263static bool testDependenceCheck (AffineForOp srcForOp, AffineForOp dstForOp,
6364 unsigned i, unsigned j, unsigned loopDepth,
6465 unsigned maxLoopDepth) {
65- affine:: ComputationSliceState sliceUnion;
66+ ComputationSliceState sliceUnion;
6667 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);
6969 if (result.value == FusionResult::FailBlockDependence) {
7070 srcForOp->emitRemark (" block-level dependence preventing"
7171 " fusion of loop nest " )
@@ -87,8 +87,7 @@ static unsigned getBlockIndex(Operation &op) {
8787}
8888
8989// Returns a string representation of 'sliceUnion'.
90- static std::string
91- getSliceStr (const affine::ComputationSliceState &sliceUnion) {
90+ static std::string getSliceStr (const ComputationSliceState &sliceUnion) {
9291 std::string result;
9392 llvm::raw_string_ostream os (result);
9493 // Slice insertion point format [loop-depth, operation-block-index]
@@ -117,8 +116,8 @@ static bool testSliceComputation(AffineForOp forOpA, AffineForOp forOpB,
117116 unsigned i, unsigned j, unsigned loopDepth,
118117 unsigned maxLoopDepth) {
119118 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);
122121 if (result.value == FusionResult::Success) {
123122 forOpB->emitRemark (" slice (" )
124123 << " src loop: " << i << " , dst loop: " << j << " , depth: " << d
@@ -134,22 +133,23 @@ static bool testSliceComputation(AffineForOp forOpA, AffineForOp forOpB,
134133
135134// Attempts to fuse 'forOpA' into 'forOpB' at loop depths in range
136135// ['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) {
142141 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 ())
150151 forOpA.erase ();
151- return true ;
152- }
152+ return true ;
153153 }
154154 return false ;
155155}
@@ -182,15 +182,15 @@ static bool iterateLoops(ArrayRef<SmallVector<AffineForOp, 2>> depthToLoops,
182182
183183void TestLoopFusion::runOnOperation () {
184184 std::vector<SmallVector<AffineForOp, 2 >> depthToLoops;
185- if (clTestLoopFusionTransformation ) {
185+ if (clTestLoopFusionUtilities ) {
186186 // Run loop fusion until a fixed point is reached.
187187 do {
188188 depthToLoops.clear ();
189189 // Gather all AffineForOps by loop depth.
190190 gatherLoops (getOperation (), depthToLoops);
191191
192192 // Try to fuse all combinations of src/dst loop nests in 'depthToLoops'.
193- } while (iterateLoops (depthToLoops, testLoopFusionTransformation ,
193+ } while (iterateLoops (depthToLoops, testLoopFusionUtilities ,
194194 /* returnOnChange=*/ true ));
195195 return ;
196196 }
0 commit comments