aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/AliasAnalysis.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-06-06[AA] Merge isNonEscapingLocalObject() into SimpleCaptureAnalysis (NFC) (#142971)Nikita Popov1-2/+2
isNonEscapingLocalObject() is only used by SimpleCaptureAnalysis and tightly integrated with its implementation (in particular its cache), so inline and simplify the implementation.
2025-05-15[AA] Change RunEarly to be a Boolean Flag in ExternalAAWrapper (#139158)Chengjun1-4/+4
Change the previous runEarly virtual function in ExternalAAWrapper to be a boolean flag.
2025-05-07[AA] Move Target Specific AA before BasicAA (#125965)Chengjun1-8/+29
In this change, NVPTX AA is moved before Basic AA to potentially improve compile time. Additionally, it introduces a flag in the `ExternalAAWrapper` that allows other backends to run their target-specific AA passes before Basic AA, if desired. The change works for both New Pass Manager and Legacy Pass Manager. Original implementation by Princeton Ferro <pferro@nvidia.com>
2025-05-05[AA] Assert that alias() arguments are pointers (#138242)Nikita Popov1-0/+3
Assert instead of returning NoAlias for non-pointers. This makes sure that people don't confuse alias (working on locations) with getModRefInfo (working on instructions).
2025-04-21[LLVM] Cleanup pass initialization for Analysis passes (#135858)Rahul Joshi1-9/+3
- Do not call pass initialization from pass constructors. - Instead, pass initialization should happen in the `initializeAnalysis` function. - https://github.com/llvm/llvm-project/issues/111767
2025-04-18[FlattenCFG] Fix an Imprecise Usage of AA (#128117)Chengjun1-0/+20
In current `FlattenCFG`, using `isNoAlias` for two instructions is imprecise. For example, when passing a store instruction and a load instruction directly into `AA->isNoAlias`, it will always return `NoAlias`. This happens because when checking the types of the two Values, the store instruction (which has a `void` type) causes the analysis to return `NoAlias`. For instructions, we should use `getModRefInfo` instead of `isNoAlias`, as aliasing is a concept of memory locations. In this patch, `AAResults::getModRefInfo` is supported to take in two instructions. It will check whether two instructions may access the same memory location or not. And in `FlattenCFG`, we use this new helper function to do the check instead of `isNoAlias`. Unit tests and lit tests are also included to this patch.
2025-03-19[AA][BasicAA] Move more call logic to BasicAA (#131144)Nikita Popov1-32/+0
Currently, the handling for calls is split between AA and BasicAA in an awkward way. BasicAA does argument alias analysis for non-escaping objects (but without considering MemoryEffects), while AA handles the generic case using MemoryEffects. However, fundamentally, both of these are really trying to do the same thing. The new merged logic first tries to remove the OtherMR component of the memory effects, which includes accesses to escaped memory. If a function-local object does not escape, OtherMR can be set to NoModRef. Then we perform the argument scan in basically the same way as AA previously did. However, we also need to look at the operand bundles. To support that, I've adjusted getArgModRefInfo to accept operand bundle arguments.
2025-03-13[CaptureTracking][AA] Only consider provenance captures (#130777)Nikita Popov1-5/+7
For the purposes of alias analysis, we should only consider provenance captures, not address captures. To support this, change (or add) CaptureTracking APIs to accept a Mask and StopFn argument. The Mask determines which components we are interested in (for AA that would be Provenance). The StopFn determines when we can abort the walk early. Currently, we want to do this as soon as any of the components in the Mask is captured. The purpose of making this a separate predicate is that in the future we will also want to distinguish between capturing full provenance and read-only provenance. In that case, we can only stop early once full provenance is captured. The earliest escape analysis does not get a StopFn, because it must always inspect all captures.
2025-03-03[NFC]Make file-local cl::opt global variables static (#126486)chrisPyr1-3/+2
#125983
2025-02-27Reapply [CaptureTracking][FunctionAttrs] Add support for CaptureInfo ↵Nikita Popov1-4/+16
(#125880) (#128020) Relative to the previous attempt this includes two fixes: * Adjust callCapturesBefore() to not skip captures(ret: address, provenance) arguments, as these will not count as a capture at the call-site. * When visiting uses during stack slot optimization, don't skip the ModRef check for passthru captures. Calls can both modref and be passthru for captures. ------ This extends CaptureTracking to support inferring non-trivial CaptureInfos. The focus of this patch is to only support FunctionAttrs, other users of CaptureTracking will be updated in followups. The key API changes here are: * DetermineUseCaptureKind() now returns a UseCaptureInfo where the UseCC component specifies what is captured at that Use and the ResultCC component specifies what may be captured via the return value of the User. Usually only one or the other will be used (corresponding to previous MAY_CAPTURE or PASSTHROUGH results), but both may be set for call captures. * The CaptureTracking::captures() extension point is passed this UseCaptureInfo as well and then can decide what to do with it by returning an Action, which is one of: Stop: stop traversal. ContinueIgnoringReturn: continue traversal but don't follow the instruction return value. Continue: continue traversal and follow the instruction return value if it has additional CaptureComponents. For now, this patch retains the (unsound) special logic for comparison of null with a dereferenceable pointer. I'd like to switch key code to take advantage of address/address_is_null before dropping it. This PR mainly intends to introduce necessary API changes and basic inference support, there are various possible improvements marked with TODOs.
2025-02-24[CaptureTracking] Remove StoreCaptures parameter (NFC)Nikita Popov1-2/+1
The implementation doesn't use it, and is unlikely to use it in the future. The places that do set StoreCaptures=false, do so incorrectly and would be broken if the parameter actually did anything.
2025-02-19Revert "Reapply [CaptureTracking][FunctionAttrs] Add support for CaptureInfo ↵Nico Weber1-9/+3
(#125880)" This reverts commit 0fab404ee874bc5b0c442d1841c7d2005c3f8729. Seems to break LTO builds of clang on Windows, see comments on https://github.com/llvm/llvm-project/pull/125880
2025-02-19[AA] Consider extractvalue and extractelement as escape sources (#127640)Nikita Popov1-0/+6
CaptureTracking considers insertions into aggregates and vectors as captures. As such, extractions from aggregates and vectors are escape sources. A non-escaping identified local cannot alias with the result of an extractvalue/extractelement. Fixes https://github.com/llvm/llvm-project/issues/126670.
2025-02-14Reapply [CaptureTracking][FunctionAttrs] Add support for CaptureInfo (#125880)Nikita Popov1-3/+9
Relative to the previous attempt, this adjusts isEscapeSource() to not treat calls with captures(ret: address, provenance) or similar arguments as escape sources. This addresses the miscompile reported at: https://github.com/llvm/llvm-project/pull/125880#issuecomment-2656632577 The implementation uses a helper function on CallBase to make this check a bit more efficient (e.g. by skipping the byval checks) as checking attributes on all arguments if fairly expensive. ------ This extends CaptureTracking to support inferring non-trivial CaptureInfos. The focus of this patch is to only support FunctionAttrs, other users of CaptureTracking will be updated in followups. The key API changes here are: * DetermineUseCaptureKind() now returns a UseCaptureInfo where the UseCC component specifies what is captured at that Use and the ResultCC component specifies what may be captured via the return value of the User. Usually only one or the other will be used (corresponding to previous MAY_CAPTURE or PASSTHROUGH results), but both may be set for call captures. * The CaptureTracking::captures() extension point is passed this UseCaptureInfo as well and then can decide what to do with it by returning an Action, which is one of: Stop: stop traversal. ContinueIgnoringReturn: continue traversal but don't follow the instruction return value. Continue: continue traversal and follow the instruction return value if it has additional CaptureComponents. For now, this patch retains the (unsound) special logic for comparison of null with a dereferenceable pointer. I'd like to switch key code to take advantage of address/address_is_null before dropping it. This PR mainly intends to introduce necessary API changes and basic inference support, there are various possible improvements marked with TODOs.
2025-01-13[FunctionAttrs] Treat byval calls as only reading ptrs (#122618)Alex MacLean1-3/+1
Since byval arguments are passed via a hidden copy of the pointee, they do not have the same semantics as normal pointer arguments. The callee cannot capture or write to the pointer and the copy is a read of the pointer.
2024-12-09[AA] Export the isBaseOfObject() API (NFC)Nikita Popov1-0/+8
This is also useful outside BasicAA.
2024-11-05[Analysis] Remove unused includes (NFC) (#114936)Kazu Hirata1-2/+0
Identified with misc-include-cleaner.
2024-09-30[SimplifyCFG] Use isWritableObject() API (#110127)Nikita Popov1-1/+4
SimplifyCFG store speculation currently has some homegrown code to check for a writable object, handling the alloca special case only. Switch it to use the generic isWritableObject() API, which means that we also support byval arguments, allocator return values, and writable arguments. I've adjusted isWritableObject() to also check for the noalias attribute when handling writable. Otherwise, I don't think that we can generalize from at-entry writability. This was not relevant for previous uses of the function, because they'd already require noalias for other reasons anyway.
2024-09-20[AA] Take account of C++23's stricter rules for forward declarations (NFC) ↵Jonathan Tanner1-0/+2
(#109416) C++23 has stricter rules for forward declarations around std::unique_ptr, this means that the inline declaration of the constructor was failing under clang in C++23 mode, switching to an out-of-line definition of the constructor fixes this. This was fairly major impact as it blocked inclusion of a lot of headers under clang in C++23 mode. Fixes #106597.
2024-08-21[NFC][Support] Move ModRef/MemoryEffects printers to their own file (#105367)Rahul Joshi1-36/+0
- Move raw_ostream << operators for `ModRef` and `MemoryEffects` to a new ModRef.cpp file under llvm/Support (instead of AliasAnalysis.cpp) - This enables calling these operators from `Core` files like Instructions.cpp (for instance for debugging). Currently, they live in `LLVMAnalysis` which cannot be linked with `Core`.
2024-01-17[BasicAA] Remove incorrect rule about constant pointers (#76815)Nikita Popov1-0/+5
BasicAA currently says that any Constant cannot alias an identified local object. This is not correct if the local object escaped, as it's possible to create a pointer to the escaped object using an inttoptr constant expression base. To compensate for this, make sure that inttoptr constant expressions are treated as escape sources, just like inttoptr instructions. This ensures that the optimization can still be applied if the local object is non-escaping. This is sufficient to still optimize the original motivating case from c53e2ecf0296a55d3c33c19fb70a3aa7f81f2732. Fixes https://github.com/llvm/llvm-project/issues/76789.
2023-12-14[IR] Add dead_on_unwind attribute (#74289)Nikita Popov1-1/+1
Add the `dead_on_unwind` attribute, which states that the caller will not read from this argument if the call unwinds. This allows eliding stores that could otherwise be visible on the unwind path, for example: ``` declare void @may_unwind() define void @src(ptr noalias dead_on_unwind %out) { store i32 0, ptr %out call void @may_unwind() store i32 1, ptr %out ret void } define void @tgt(ptr noalias dead_on_unwind %out) { call void @may_unwind() store i32 1, ptr %out ret void } ``` The optimization is not valid without `dead_on_unwind`, because the `i32 0` value might be read if `@may_unwind` unwinds. This attribute is primarily intended to be used on sret arguments. In fact, I previously wanted to change the semantics of sret to include this "no read after unwind" property (see D116998), but based on the feedback there it is better to keep these attributes orthogonal (sret is an ABI attribute, dead_on_unwind is an optimization attribute). This is a reboot of that change with a separate attribute.
2023-11-01[IR] Add writable attributeNikita Popov1-3/+11
This adds a writable attribute, which in conjunction with dereferenceable(N) states that a spurious store of N bytes is introduced on function entry. This implies that this many bytes are writable without trapping or introducing data races. See https://llvm.org/docs/Atomics.html#optimization-outside-atomic for why the second point is important. This attribute can be added to sret arguments. I believe Rust will also be able to use it for by-value (moved) arguments. Rust likely won't be able to use it for &mut arguments (tree borrows does not appear to allow spurious stores). In this patch the new attribute is only used by LICM scalar promotion. However, the actual motivation for this is to fix a correctness issue in call slot optimization, which needs this attribute to avoid optimization regressions. Followup to the discussion on D157499. Differential Revision: https://reviews.llvm.org/D158081
2023-08-16[LICM][AA] Move isWritableObject() to AA (NFC)Nikita Popov1-0/+17
Move this helper from LICM to AA, so it can be reused.
2023-07-03[MemoryEffects][NFCI] Make the MemoryEffects class reusableJohannes Doerfert1-7/+7
In a follow up we will reuse the logic in MemoryEffectsBase to merge AAMemoryLocation and AAMemoryBehavior without duplicating all the bit fiddling code already available in MemoryEffectsBase. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D153305
2023-06-10[Analysis] Remove unused function createAAResultsWrapperPassKazu Hirata1-4/+0
The last use was removed by: commit 934c82d31801e65aa3bbe99a0e64f903621c2e04 Author: Florian Hahn <flo@fhahn.com> Date: Fri Feb 24 13:39:32 2023 +0100
2023-05-31[Analysis] Remove unused class LegacyAARGetterKazu Hirata1-23/+0
The last use was removed by: commit fa6ea7a419f37befbed04368bcb8af4c718facbb Author: Arthur Eubanks <aeubanks@google.com> Date: Mon Mar 20 11:18:35 2023 -0700 Once we remove it, createLegacyPMAAResults and createLegacyPMAAResults become unused, so this patch removes them as well. Differential Revision: https://reviews.llvm.org/D151787
2023-03-21[AlwaysInliner] Make legacy pass like the new passArthur Eubanks1-11/+0
The legacy pass is only used in AMDGPU codegen, which doesn't care about running it in call graph order (it actually has to work around that fact). Make the legacy pass a module pass and share code with the new pass. This allows us to remove the legacy inliner infrastructure. Reviewed By: mtrofin Differential Revision: https://reviews.llvm.org/D146446
2022-12-15[AA] Allow for flow-sensitive analyses.David Goldblatt1-12/+13
All current analyses ignore the context. We make the argument mandatory for analyses, but optional for the query interface. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D136512
2022-12-14[Analysis] llvm::Optional => std::optionalFangrui Song1-1/+1
2022-12-12[AA] Remove CFL AA passesNikita Popov1-16/+0
The CFL Steens/Anders alias analysis passes are not enabled by default, and to the best of my knowledge have no pathway towards ever being enabled by default. The last significant interest in these passes seems to date back to 2016. Given the little maintenance these have seen in recent times, I also have very little confidence in the correctness of these passes. I don't think we should keep these in-tree. Differential Revision: https://reviews.llvm.org/D139703
2022-12-02[Analysis] Use std::nullopt instead of None (NFC)Kazu Hirata1-1/+1
This patch mechanically replaces None with std::nullopt where the compiler would warn if None were deprecated. The intent is to reduce the amount of manual work required in migrating from Optional to std::optional. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-11-02[AA] Remove some overloads (NFC)Nikita Popov1-58/+0
Having all these instruction-specific overloads does not seem to provide any compile-time benefit, so drop them in favor of the generic methods accepting "const Instruction *". Only leave behind the per-instruction AAQI overloads, which are part of the internal implementation.
2022-11-01[AA] Add missing const qualifier (NFC)Nikita Popov1-2/+3
2022-10-31[AliasAnalysis] Introduce getModRefInfoMask() as a generalization of ↵Patrick Walton1-28/+35
pointsToConstantMemory(). The pointsToConstantMemory() method returns true only if the memory pointed to by the memory location is globally invariant. However, the LLVM memory model also has the semantic notion of *locally-invariant*: memory that is known to be invariant for the life of the SSA value representing that pointer. The most common example of this is a pointer argument that is marked readonly noalias, which the Rust compiler frequently emits. It'd be desirable for LLVM to treat locally-invariant memory the same way as globally-invariant memory when it's safe to do so. This patch implements that, by introducing the concept of a *ModRefInfo mask*. A ModRefInfo mask is a bound on the Mod/Ref behavior of an instruction that writes to a memory location, based on the knowledge that the memory is globally-constant memory (in which case the mask is NoModRef) or locally-constant memory (in which case the mask is Ref). ModRefInfo values for an instruction can be combined with the ModRefInfo mask by simply using the & operator. Where appropriate, this patch has modified uses of pointsToConstantMemory() to instead examine the mask. The most notable optimization change I noticed with this patch is that now redundant loads from readonly noalias pointers can be eliminated across calls, even when the pointer is captured. Internally, before this patch, AliasAnalysis was assigning Ref to reads from constant memory; now AA can assign NoModRef, which is a tighter bound. Differential Revision: https://reviews.llvm.org/D136659
2022-10-21[ObjCARC] Remove legacy PM versions of optimization passesArthur Eubanks1-9/+0
This doesn't touch objc-arc-contract because that's in the codegen pipeline. However, this does move its corresponding initialize function into initializeCodegen(). Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D135041
2022-10-19[AA] Rename getModRefBehavior() to getMemoryEffects() (NFC)Nikita Popov1-11/+11
Follow up on D135962, renaming the method name to match the new type name.
2022-10-19[AA] Rename uses of FunctionModRefBehavior (NFC)Nikita Popov1-19/+17
Followup to D135962 to rename remaining uses of FunctionModRefBehavior to MemoryEffects. Does not touch API names yet, but also updates variables names FMRB/MRB to ME, to match the new type name.
2022-10-06[AA] Pass AAResults through AAQueryInfoNikita Popov1-29/+18
Currently, AAResultBase (from which alias analysis providers inherit) stores a reference back to the AAResults aggregation it is part of, so it can perform recursive alias analysis queries via getBestAAResults(). This patch removes the back-reference from AAResultBase to AAResults, and instead passes the used aggregation through the AAQueryInfo. This can be used to perform recursive AA queries using the full aggregation. Differential Revision: https://reviews.llvm.org/D94363
2022-10-06[AA] Thread AAQI through getModRefBehavior() (NFC)Nikita Popov1-6/+12
This is in preparation for D94363, as we will need AAQI to perform the recursive call to the function variant.
2022-09-22[AA] Model operand bundles more preciselyNikita Popov1-23/+25
Based on D130896, we can model operand bundles more precisely. In addition to the baseline ModRefBehavior, a reading/clobbering operand bundle may also read/write all locations. For example, a memcpy with deopt bundle can read any memory, but only write argument memory. This means that getModRefInfo() for memcpy with a pointer that does not alias the arguments results in Ref, rather than ModRef, without the need to implement any special handling. Differential Revision: https://reviews.llvm.org/D130980
2022-09-14[AA] Tracking per-location ModRef info in FunctionModRefBehavior (NFCI)Nikita Popov1-25/+59
Currently, FunctionModRefBehavior tracks whether the function reads or writes memory (ModRefInfo) and which locations it can access (argmem, inaccessiblemem and other). This patch changes it to track ModRef information per-location instead. To give two examples of why this is useful: * D117095 highlights a weakness of ModRef modelling in the presence of operand bundles. For a memcpy call with deopt operand bundle, we want to say that it can read any memory, but only write argument memory. This would allow them to be treated like any other calls. However, we currently can't express this and have to say that it can read or write any memory. * D127383 would ideally be modelled as a separate threadid location, where threadid Refs outside pre-split coroutines can be ignored (like other accesses to constant memory). The current representation does not allow modelling this precisely. The patch as implemented is intended to be NFC, but there are some obvious opportunities for improvements and simplification. To fully capitalize on this we would also want to change the way we represent memory attributes on functions, but that's a larger change, and I think it makes sense to separate out the FunctionModRefBehavior refactoring. Differential Revision: https://reviews.llvm.org/D130896
2022-08-03[AA] Make ModRefInfo a bitmask enum (NFC)Nikita Popov1-18/+15
Mark ModRefInfo as a bitmask enum, which allows using normal & and | operators on it. This supersedes various functions like unionModRef() and intersectModRef(). I think this makes the code cleaner than going through helper functions... Differential Revision: https://reviews.llvm.org/D130870
2022-08-01[AA] Drop setModAndRef() function (NFC)Nikita Popov1-1/+1
Without the "must" state, this function is pointless, because we can just directly create a ModRef instead.
2022-08-01[AA] Do not track Must in ModRefInfoNikita Popov1-56/+5
getModRefInfo() queries currently track whether the result is a MustAlias on a best-effort basis. The only user of this functionality is the optimized memory access type in MemorySSA -- which in turn has no users. Given that this functionality has not found a user since it was introduced five years ago (in D38862), I think we should drop it again. The context is that I'm working to separate FunctionModRefBehavior to track mod/ref for different location kinds (like argmem or inaccessiblemem) separately, and the fact that ModRefInfo also has an unrelated Must flag makes this quite awkward, especially as this means that NoModRef is not a zero value. If we want to retain the functionality, I would probably split getModRefInfo() results into a part that just contains the ModRef information, and a separate part containing a (best-effort) AliasResult. Differential Revision: https://reviews.llvm.org/D130713
2022-06-24[AA] Export isEscapeSource() API (NFC)Nikita Popov1-0/+22
Export API that was previously private to BasicAliasAnalysis and will be used in D127202.
2022-06-18[llvm] Use value_or instead of getValueOr (NFC)Kazu Hirata1-1/+1
2022-03-01Cleanup includes: LLVMAnalysisserge-sans-paille1-1/+0
Number of lines output by preprocessor: before: 1065940348 after: 1065307662 Discourse thread: https://discourse.llvm.org/t/include-what-you-use-include-cleanup Differential Revision: https://reviews.llvm.org/D120659
2022-01-26[LICM] Generalize unwinding check during scalar promotionNikita Popov1-0/+23
This extract a common isNotVisibleOnUnwind() helper into AliasAnalysis, which handles allocas, byval arguments and noalias calls. After D116998 this could also handle sret arguments. We have similar logic in DSE and MemCpyOpt, which will be switched to use this helper as well. The noalias call case is a bit different from the others, because it also requires that the object is not captured. The caller is responsible for doing the appropriate check. Differential Revision: https://reviews.llvm.org/D117000
2022-01-05Rename doesNotReadMemory to onlyWritesMemory globally [NFC]Philip Reames1-2/+2
The naming has come up as a source of confusion in several recent reviews. onlyWritesMemory is consist with onlyReadsMemory which we use for the corresponding readonly case as well.