@@ -347,12 +347,23 @@ conflict(llvm::ArrayRef<mlir::MemoryEffects::EffectInstance> effectsA,
347347 anyRAWorWAW (effectsB, effectsA, aliasAnalysis);
348348}
349349
350- // / Could there be any write effects in "effects"?
350+ // / Could there be any write effects in "effects" affecting memory storages
351+ // / that are not local to the current region.
351352static bool
352- anyWrite (llvm::ArrayRef<mlir::MemoryEffects::EffectInstance> effects) {
353+ anyNonLocalWrite (llvm::ArrayRef<mlir::MemoryEffects::EffectInstance> effects,
354+ mlir::Region ®ion) {
353355 return llvm::any_of (
354- effects, [](const mlir::MemoryEffects::EffectInstance &effect) {
355- return mlir::isa<mlir::MemoryEffects::Write>(effect.getEffect ());
356+ effects, [®ion](const mlir::MemoryEffects::EffectInstance &effect) {
357+ if (mlir::isa<mlir::MemoryEffects::Write>(effect.getEffect ())) {
358+ if (mlir::Value v = effect.getValue ()) {
359+ v = getStorageSource (v);
360+ if (v.getDefiningOp <fir::AllocaOp>() ||
361+ v.getDefiningOp <fir::AllocMemOp>())
362+ return !region.isAncestor (v.getParentRegion ());
363+ }
364+ return true ;
365+ }
366+ return false ;
356367 });
357368}
358369
@@ -393,9 +404,13 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion,
393404 if (entity && hlfir::isFortranVariableType (entity->get ().getType ()))
394405 effects.emplace_back (mlir::MemoryEffects::Read::get (), entity);
395406 }
396- if (!leafRegionsMayOnlyRead && anyWrite (effects)) {
397- // Region with write effect must be executed only once: save it the first
398- // time it is encountered.
407+ if (!leafRegionsMayOnlyRead && anyNonLocalWrite (effects, yieldRegion)) {
408+ // Region with write effect must be executed only once (unless all writes
409+ // affect storages allocated inside the region): save it the first time it
410+ // is encountered.
411+ LLVM_DEBUG (llvm::dbgs ()
412+ << " saving eval because write effect prevents re-evaluation"
413+ << " \n " ;);
399414 saveEvaluation (yieldRegion, effects, /* anyWrite=*/ true );
400415 } else if (conflict (effects, assignEffects)) {
401416 // Region that conflicts with the current assignments must be fully
@@ -411,7 +426,8 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion,
411426 // For example, a WHERE mask might be written by the masked assignment
412427 // evaluations, and it has to be saved in this case:
413428 // where (mask) r = f() ! function f modifies mask
414- saveEvaluation (yieldRegion, effects, anyWrite (effects));
429+ saveEvaluation (yieldRegion, effects,
430+ anyNonLocalWrite (effects, yieldRegion));
415431 } else {
416432 // Can be executed while doing the assignment.
417433 independentEvaluationEffects.append (effects.begin (), effects.end ());
0 commit comments