@@ -81,7 +81,8 @@ class Scheduler {
81
81
// / current assignment: the saved value will be used.
82
82
void saveEvaluationIfConflict (mlir::Region &yieldRegion,
83
83
bool leafRegionsMayOnlyRead,
84
- bool yieldIsImplicitRead = true );
84
+ bool yieldIsImplicitRead = true ,
85
+ bool evaluationsMayConflict = false );
85
86
86
87
// / Finish evaluating a group of independent regions. The current independent
87
88
// / regions effects are added to the "parent" effect list since evaluating the
@@ -117,6 +118,10 @@ class Scheduler {
117
118
118
119
// / Memory effects of the assignments being lowered.
119
120
llvm::SmallVector<mlir::MemoryEffects::EffectInstance> assignEffects;
121
+ // / Memory effects of the evaluations implied by the assignments
122
+ // / being lowered. They do not include the implicit writes
123
+ // / to the LHS of the assignments.
124
+ llvm::SmallVector<mlir::MemoryEffects::EffectInstance> assignEvaluateEffects;
120
125
// / Memory effects of the unsaved evaluation region that are controlling or
121
126
// / masking the current assignments.
122
127
llvm::SmallVector<mlir::MemoryEffects::EffectInstance>
@@ -260,6 +265,20 @@ static void gatherAssignEffects(
260
265
}
261
266
}
262
267
268
+ // / Gather the effects of evaluations implied by the given assignment.
269
+ // / These are the effects of operations from LHS and RHS.
270
+ static void gatherAssignEvaluationEffects (
271
+ hlfir::RegionAssignOp regionAssign,
272
+ bool userDefAssignmentMayOnlyWriteToAssignedVariable,
273
+ llvm::SmallVectorImpl<mlir::MemoryEffects::EffectInstance> &assignEffects) {
274
+ gatherMemoryEffects (regionAssign.getLhsRegion (),
275
+ userDefAssignmentMayOnlyWriteToAssignedVariable,
276
+ assignEffects);
277
+ gatherMemoryEffects (regionAssign.getRhsRegion (),
278
+ userDefAssignmentMayOnlyWriteToAssignedVariable,
279
+ assignEffects);
280
+ }
281
+
263
282
// ===----------------------------------------------------------------------===//
264
283
// Scheduling Implementation : finding conflicting memory effects.
265
284
// ===----------------------------------------------------------------------===//
@@ -344,11 +363,19 @@ anyWrite(llvm::ArrayRef<mlir::MemoryEffects::EffectInstance> effects) {
344
363
void Scheduler::startSchedulingAssignment (hlfir::RegionAssignOp assign,
345
364
bool leafRegionsMayOnlyRead) {
346
365
gatherAssignEffects (assign, leafRegionsMayOnlyRead, assignEffects);
366
+ // Unconditionally collect effects of the evaluations of LHS and RHS
367
+ // in case they need to be analyzed for any parent that might be
368
+ // affected by conflicts of these evaluations.
369
+ // This collection migth be skipped, if there are no such parents,
370
+ // but for the time being we run it always.
371
+ gatherAssignEvaluationEffects (assign, leafRegionsMayOnlyRead,
372
+ assignEvaluateEffects);
347
373
}
348
374
349
375
void Scheduler::saveEvaluationIfConflict (mlir::Region &yieldRegion,
350
376
bool leafRegionsMayOnlyRead,
351
- bool yieldIsImplicitRead) {
377
+ bool yieldIsImplicitRead,
378
+ bool evaluationsMayConflict) {
352
379
// If the region evaluation was previously executed and saved, the saved
353
380
// value will be used when evaluating the current assignment and this has
354
381
// no effects in the current assignment evaluation.
@@ -377,6 +404,14 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion,
377
404
// implies that it never conflicted with a prior assignment, so its value
378
405
// should be the same.)
379
406
saveEvaluation (yieldRegion, effects, /* anyWrite=*/ false );
407
+ } else if (evaluationsMayConflict &&
408
+ conflict (effects, assignEvaluateEffects)) {
409
+ // If evaluations of the assignment may conflict with the yield
410
+ // evaluations, we have to save yield evaluation.
411
+ // For example, a WHERE mask might be written by the masked assignment
412
+ // evaluations, and it has to be saved in this case:
413
+ // where (mask) r = f() ! function f modifies mask
414
+ saveEvaluation (yieldRegion, effects, anyWrite (effects));
380
415
} else {
381
416
// Can be executed while doing the assignment.
382
417
independentEvaluationEffects.append (effects.begin (), effects.end ());
@@ -444,6 +479,7 @@ void Scheduler::finishSchedulingAssignment(hlfir::RegionAssignOp assign) {
444
479
schedule.back ().memoryEffects .append (assignEffects.begin (),
445
480
assignEffects.end ());
446
481
assignEffects.clear ();
482
+ assignEvaluateEffects.clear ();
447
483
parentEvaluationEffects.clear ();
448
484
independentEvaluationEffects.clear ();
449
485
savedAnyRegionForCurrentAssignment = false ;
@@ -533,9 +569,13 @@ hlfir::buildEvaluationSchedule(hlfir::OrderedAssignmentTreeOpInterface root,
533
569
scheduler.startIndependentEvaluationGroup ();
534
570
llvm::SmallVector<mlir::Region *, 4 > yieldRegions;
535
571
parent.getLeafRegions (yieldRegions);
572
+ // TODO: is this really limited to WHERE/ELSEWHERE?
573
+ bool evaluationsMayConflict = mlir::isa<hlfir::WhereOp>(parent) ||
574
+ mlir::isa<hlfir::ElseWhereOp>(parent);
536
575
for (mlir::Region *yieldRegion : yieldRegions)
537
- scheduler.saveEvaluationIfConflict (*yieldRegion,
538
- leafRegionsMayOnlyRead);
576
+ scheduler.saveEvaluationIfConflict (*yieldRegion, leafRegionsMayOnlyRead,
577
+ /* yieldIsImplicitRead=*/ true ,
578
+ evaluationsMayConflict);
539
579
scheduler.finishIndependentEvaluationGroup ();
540
580
}
541
581
// Look for conflicts between the RHS/LHS evaluation and the assignments.
0 commit comments