@@ -28,6 +28,67 @@ using namespace mlir;
2828
2929#define DEBUG_TYPE " fir-alias-analysis"
3030
31+ // ===----------------------------------------------------------------------===//
32+ // AliasAnalysis: alias helpers
33+ // ===----------------------------------------------------------------------===//
34+
35+ static bool tryClassifyAllocateFromEffects (mlir::Operation *op,
36+ mlir::Value candidate, bool allowValueScoped, bool allowOpScoped,
37+ mlir::Value &v, mlir::Operation *&defOp,
38+ fir::AliasAnalysis::SourceKind &type) {
39+ auto iface = llvm::dyn_cast<mlir::MemoryEffectOpInterface>(op);
40+ if (!iface)
41+ return false ;
42+
43+ llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4 > effects;
44+ iface.getEffects (effects);
45+
46+ if (allowValueScoped) {
47+ for (mlir::MemoryEffects::EffectInstance &e : effects) {
48+ if (mlir::isa<mlir::MemoryEffects::Allocate>(e.getEffect ()) &&
49+ e.getValue () && e.getValue () == candidate) {
50+ v = candidate;
51+ defOp = op;
52+ type = fir::AliasAnalysis::SourceKind::Allocate;
53+ return true ;
54+ }
55+ }
56+ }
57+
58+ if (!allowOpScoped)
59+ return false ;
60+
61+ bool hasOpScopedAlloc = llvm::any_of (
62+ effects, [](const mlir::MemoryEffects::EffectInstance &e) {
63+ return !e.getValue () &&
64+ mlir::isa<mlir::MemoryEffects::Allocate>(e.getEffect ());
65+ });
66+ if (!hasOpScopedAlloc)
67+ return false ;
68+
69+ bool opIsViewLike =
70+ (bool )mlir::dyn_cast_or_null<mlir::ViewLikeOpInterface>(op);
71+ auto isMemoryRefLikeType = [](mlir::Type type) {
72+ return fir::isa_ref_type (type) || mlir::isa<mlir::BaseMemRefType>(type) ||
73+ mlir::isa<mlir::LLVM::LLVMPointerType>(type);
74+ };
75+ bool hasMemOperands = llvm::any_of (op->getOperands (), [&](mlir::Value o) {
76+ return isMemoryRefLikeType (o.getType ());
77+ });
78+ if (opIsViewLike || hasMemOperands)
79+ return false ;
80+
81+ for (mlir::Value res : op->getResults ()) {
82+ if (res == candidate && isMemoryRefLikeType (res.getType ())) {
83+ v = candidate;
84+ defOp = op;
85+ type = fir::AliasAnalysis::SourceKind::Allocate;
86+ return true ;
87+ }
88+ }
89+ return false ;
90+ }
91+
3192// ===----------------------------------------------------------------------===//
3293// AliasAnalysis: alias
3394// ===----------------------------------------------------------------------===//
@@ -544,43 +605,22 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
544605 type = SourceKind::Indirect;
545606 }
546607 };
608+
609+ // Helper to detect memory-ref-like types.
610+ auto isMemoryRefLikeType = [](mlir::Type t) {
611+ return fir::isa_ref_type (t) || mlir::isa<mlir::BaseMemRefType>(t) ||
612+ mlir::isa<mlir::LLVM::LLVMPointerType>(t);
613+ };
614+
547615 while (defOp && !breakFromLoop) {
548616 ty = defOp->getResultTypes ()[0 ];
549617
550- // Effect-based detection using op-scoped Allocate with conservative
551- // heuristics (ignore value-scoped signals per request).
552- if (auto memIface = llvm::dyn_cast<mlir::MemoryEffectOpInterface>(defOp)) {
553- llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4 > effects;
554- memIface.getEffects (effects);
555- bool sawOpScopedAlloc = false ;
556- for (auto &ei : effects) {
557- bool isAlloc = mlir::isa<mlir::MemoryEffects::Allocate>(ei.getEffect ());
558- if (!ei.getValue () && isAlloc) {
559- sawOpScopedAlloc = true ;
560- }
561- }
562- if (sawOpScopedAlloc) {
563- auto isMemoryRefLikeType = [](mlir::Type t) {
564- return fir::isa_ref_type (t) || mlir::isa<mlir::BaseMemRefType>(t) ||
565- mlir::isa<mlir::LLVM::LLVMPointerType>(t);
566- };
567- bool opIsViewLike = (bool )mlir::dyn_cast_or_null<mlir::ViewLikeOpInterface>(defOp);
568- bool hasMemOperands = llvm::any_of (defOp->getOperands (), [&](mlir::Value opnd) {
569- return isMemoryRefLikeType (opnd.getType ());
570- });
571- if (!opIsViewLike && !hasMemOperands) {
572- for (mlir::Value res : defOp->getResults ()) {
573- if (res == v && isMemoryRefLikeType (res.getType ())) {
574- type = SourceKind::Allocate;
575- breakFromLoop = true ;
576- break ;
577- }
578- }
579- if (breakFromLoop)
580- break ;
581- }
582- }
583- }
618+ // Effect-based detection (op-scoped heuristic only at this level).
619+ if (tryClassifyAllocateFromEffects (defOp, v,
620+ /* allowValueScoped=*/ false ,
621+ /* allowOpScoped=*/ true ,
622+ v, defOp, type))
623+ break ;
584624
585625 llvm::TypeSwitch<Operation *>(defOp)
586626 .Case <hlfir::AsExprOp>([&](auto op) {
@@ -666,61 +706,14 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
666706 if (global) {
667707 type = SourceKind::Global;
668708 } else {
669- auto def = llvm::cast<mlir::Value>(boxSrc.origin .u );
709+ mlir::Value def = llvm::cast<mlir::Value>(boxSrc.origin .u );
670710 bool classified = false ;
671- if (auto defDefOp = def.getDefiningOp ()) {
672- if (auto defIface =
673- llvm::dyn_cast<mlir::MemoryEffectOpInterface>(defDefOp)) {
674- llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4 > eff;
675- defIface.getEffects (eff);
676- // Prefer value-scoped Allocate on the underlying storage.
677- for (auto &e : eff) {
678- if (mlir::isa<mlir::MemoryEffects::Allocate>(e.getEffect ()) &&
679- e.getValue () && e.getValue () == def) {
680- v = def;
681- defOp = v.getDefiningOp ();
682- type = SourceKind::Allocate;
683- classified = true ;
684- break ;
685- }
686- }
687- // Heuristic for op-scoped Allocate at the underlying defining op.
688- if (!classified) {
689- bool sawOpScopedAlloc = llvm::any_of (
690- eff, [](auto &e) {
691- return !e.getValue () &&
692- mlir::isa<mlir::MemoryEffects::Allocate>(
693- e.getEffect ());
694- });
695- if (sawOpScopedAlloc) {
696- auto isMemoryRefLikeType = [](mlir::Type t) {
697- return fir::isa_ref_type (t) ||
698- mlir::isa<mlir::BaseMemRefType>(t) ||
699- mlir::isa<mlir::LLVM::LLVMPointerType>(t);
700- };
701- bool opIsViewLike = (bool )mlir::dyn_cast_or_null<
702- mlir::ViewLikeOpInterface>(defDefOp);
703- bool hasMemOperands = llvm::any_of (
704- defDefOp->getOperands (), [&](mlir::Value opnd) {
705- return isMemoryRefLikeType (opnd.getType ());
706- });
707- if (!opIsViewLike && !hasMemOperands) {
708- for (mlir::Value res : defDefOp->getResults ()) {
709- if (res == def && isMemoryRefLikeType (res.getType ())) {
710- v = def;
711- defOp = v.getDefiningOp ();
712- type = SourceKind::Allocate;
713- classified = true ;
714- break ;
715- }
716- }
717- }
718- }
719- }
720- }
721- }
722- if (!classified)
723- classifyFallbackFrom (def);
711+ if (auto defDefOp = def.getDefiningOp ())
712+ classified = tryClassifyAllocateFromEffects (
713+ defDefOp, def,
714+ /* allowValueScoped=*/ true , /* allowOpScoped=*/ true ,
715+ v, defOp, type);
716+ if (!classified) classifyFallbackFrom (def);
724717 }
725718 breakFromLoop = true ;
726719 return ;
0 commit comments