MLIR: alias classes for globals, and alloc-like effect handling - #3191
Open
burakSemih wants to merge 3 commits into
Open
burakSemih wants to merge 3 commits into
burakSemih wants to merge 3 commits into
Conversation
added 3 commits
September 8, 2026 01:28
…y path getEffectsForExternalCall synthesizes an Allocate effect for "calloc" and "_Znwm" as well as for "malloc", but isAliasTransferFullyDescribedByMemoryEffects named only "malloc", so the two lists disagreed about which calls are fully described by their memory effects. Name all three in both places.
The alias and points-to transfer functions treated an operation as a fresh allocation only when it carried exactly one memory effect. That is the right shape for memref.alloc and llvm.alloca, but it rejects any operation that allocates and also carries an effect on a resource that is not addressable memory -- a runtime handle, a communication resource -- even though such an effect cannot say anything about aliasing. Factor the test into a helper that ignores effects on non-addressable resources and requires a single freshly allocated pointer-like result, and use it both in PointsToPointerAnalysis::visitOperation and in isAliasTransferFullyDescribedByMemoryEffects. A value-less read effect on a non-addressable resource likewise no longer forces the conservative "global read" path. No in-tree operation changes behaviour: every allocator currently modelled has a single effect and so takes the same path as before.
AliasAnalysis had no transfer function for llvm.mlir.addressof, so the result lattice stayed undefined. An alias query involving the address of a global then tripped the "incomplete alias analysis" assertion in AliasClassLattice::alias, and in a build without assertions compared two empty class sets and silently answered NoAlias. Give the address of a global its own alias class, keyed on the symbol so that every llvm.mlir.addressof of the same global lands in the same class -- the LLVM importer emits one addressof per use, so several addresses of one global is the common case rather than a corner one. Globals get a unique class regardless of linkage: a global is a distinct object even when it is defined in another module, so its address cannot point into a different global. Addresses of functions and of aliases keep the shared entry class when they may be defined elsewhere.
Collaborator
Author
|
Probably @pengmai would be best for reviewing this. Happy for any feedback ;) |
pengmai
reviewed
Sep 24, 2026
Comment on lines
+262
to
+263
| static Value getSingleFreshAllocatedPointerLikeResultIfEffectOnlyAllocLike( | ||
| Operation *op, ArrayRef<MemoryEffects::EffectInstance> effects) { |
Member
There was a problem hiding this comment.
Two questions regarding the signature of this function:
- Can we return a
std::optional<Value>rather than a potentially nullValue? - Can we extract the
effectsfrom theop? This could potentially be called with effects that don't come from the op, unless that is intended.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AliasAnalysishas no transfer function forllvm.mlir.addressof, so the resultlattice stays undefined. An alias query involving the address of a global then
trips
in
AliasClassLattice::alias, and in a build without assertions compares twoempty class sets and quietly answers
NoAlias— the right answer for twodistinct globals, by accident, and the wrong one for two addresses of the same
global.
This gives the address of a global its own alias class. Three commits, each
buildable on its own:
isAliasTransferFullyDescribedByMemoryEffectsnamed onlymallocwhilegetEffectsForExternalCallalready synthesized anAllocateeffect forcallocand_Znwmtoo. Name all three in both places.effect. That fits
memref.allocandllvm.alloca, but rejects an operationthat allocates and carries an effect on a resource that is not addressable
memory — a runtime handle, a communication resource — even though such an
effect says nothing about aliasing. Factored into a helper that ignores
effects on non-addressable resources. No in-tree operation changes behaviour;
every allocator currently modelled has a single effect.
llvm.mlir.addressoftransfer function itself, plustest/MLIR/AliasAnalysis/globals.mlir.Keying on the symbol
The class is cached on the symbol operation, not on the
addressofresult, soevery
llvm.mlir.addressof @gin the module lands in the same class. Keying onthe result value instead gives two addresses of one global two distinct classes
and hence
NoAlias, which is wrong — and it is the common case rather than acorner one, since the LLVM importer emits one
addressofper use.Globals get a unique class regardless of linkage
A global is a distinct object even when its definition lives in another module,
so taking its address cannot produce a pointer into a different global.
External linkage does not change that, and folding external globals together
would lose precision for no soundness benefit.
Addresses of functions and of
llvm.mlir.aliasare treated differently: theykeep the shared entry class when they may be defined elsewhere.
One consequence worth flagging
Because argument classes and global classes are disjoint, the address of a
global is now
NoAliaswith an unannotated pointer argument. That asserts noincoming pointer points into a global, which a caller passing
&gviolates.I have left it that way deliberately, for two reasons. The analysis already
answered
NoAliashere before this patch — via the undefined lattice above — sothis is not a new answer, only a deliberate one where there used to be an
accident. And widening it means putting globals into the entry class, which
costs exactly the global-vs-global precision this patch is for.
The alternative would be to give externally-visible globals both their own class
and the entry class, so they stay distinct from each other but may-alias
incoming pointers. Happy to do that instead if you would rather have the
conservative answer; it is a small change and I would add the test alongside it.
test/MLIR/AliasAnalysis/globals.mlirpins the current behaviour either way.There is also a
TODOin the patch aboutunnamed_addr: a global markedunnamed_addrhas no meaningful identity and may be merged with an equivalentconstant, so strictly it should not get a unique class. Not handled here.
Testing
test/MLIR/AliasAnalysis/globals.mlircovers two external globals, two internalglobals, mixed linkage, two addresses of the same global within a function and
across two functions, the address of an external function, and global vs.
argument.
Ran the full
test/MLIRsuite against this branch and againstmain: 228 pass,and the one failure (
ReverseMode/func_call_write.mlir) fails onmaintoo.Each of the three commits builds warning-free, and both touched files are clean
under
clang-format16.