91 Commits

Author SHA1 Message Date
Johannes Doerfert
335e137267
[Attributor][FIX] Track returned pointer offsets (#110534)
If the pointer returned by a function is not "the base pointer" but has
an offset, we need to track the offset such that users can apply it to
their offset chain when they create accesses.
This was reported by @ye-luo and reduced test cases are included. The
OffsetInfo was moved and the container was replaced with a set to avoid
excessive growth. Otherwise, the patch just replaces the "returns
pointer" flag with the "returned offsets", and deals with the applying
to offsets at the call site.

---------

Co-authored-by: Johannes Doerfert <jdoerfert@llnl.gov>
2024-10-01 12:41:15 -05:00
Johannes Doerfert
56a033462e
[Attributor] Keep track of reached returns in AAPointerInfo (#107479)
Instead of visiting call sites in Attribute::checkForAllUses, we now
keep track of returns in AAPointerInfo and use the call site return
information as required. This way, the user of
AAPointerInfo(CallSite)Argument can determine if the call return should
be visited. We do not collect them as "may accesses" in the
AAPointerInfo(CallSite)Argument itself in case a return user is found.
2024-09-10 08:13:21 -07:00
Johannes Doerfert
e6dece9f69
[Attributor][FIX] Mark "may" accesses through call sites as such (#107439)
Before, we kept the call site access kind (may/must) when we translated
the access. However, the pointer we access it through (by passing it to
the callee) might not be the underlying object. We have similar logic
when we add store and load accesses.
2024-09-05 13:33:58 -07:00
Johannes Doerfert
3726f9c575
[Attributor][NFC] Pre-commits for #107439 (#107457) 2024-09-05 13:10:37 -07:00
Johannes Doerfert
8266d47cd1
[Attributor] Improve AAUnderlyingObjects (#104835)
- Allocas and GlobalValues cannot be simplified, so we should not try.
- If we never used any assumed state, the AAUnderlyingObjects doesn't
require an additional update.
- If we have seen an object (or it's underlying object) before, we do
not need to inspect it anymore.

The original logic for "SeenObjects" was flawed and caused us to add
intermediate values to the underlying object list if a PHI or select
instruction referenced the same underlying object twice. The test
changes are all instances of this situation and we now correctly derive
`memory(none)` for the functions that only access stack memory.

---------

Co-authored-by: Shilei Tian <i@tianshilei.me>
2024-08-20 12:05:20 -07:00
Nikita Popov
2d69827c5c [Transforms] Convert tests to opaque pointers (NFC) 2024-02-05 11:57:34 +01:00
Nikita Popov
658b260dbf [Attributor] Don't construct pretty GEPs
Bring this in line with other transforms like ArgPromotion/SROA/
SCEVExpander and always produce canonical i8 GEPs.
2023-12-22 16:48:13 +01:00
Johannes Doerfert
9a80ebe63c [Attributor] Simplify assumptions "stores"
When we add an assumption about memory to the AAPointerInfo bins, we
should simplify the assumed value, like we do for stores.
2023-08-23 15:14:14 -07:00
Johannes Doerfert
010e3b84f9 [Attributor][NFC] Precommit test 2023-08-23 15:14:14 -07:00
Johannes Doerfert
fa367d159a [IR] Mark llvm.assume as memory(inaccessiblemem: write)
It was `inaccessiblemem: readwrite` before, no need for the read.
No real benefit is expected but it can help debugging and other efforts.

Differential Revision: https://reviews.llvm.org/D156478
2023-07-31 13:44:52 -07:00
Johannes Doerfert
55544518c6 [Attributor] Allow IR-attr deduction for non-IPO amendable functions
If the function is non-IPO amendable we do skip most attributes/AAs.
However, if an AA has a isImpliedByIR that can deduce the attribute from
other attributes, we can run those. For now, we manually enable them,
if we have more later we can use some automation/flag.
2023-07-14 13:54:04 -07:00
Johannes Doerfert
59fd610558 [Attributor] Port AANoUndef to the isImpliedByIR interface 2023-07-09 16:04:20 -07:00
Johannes Doerfert
aae749b275 [Attributor] Port AANoAlias to the isImpliedByIR interface
As part of this we do not annotate literal `null` and `undef/poison` as
`noalias` anymore. This was not really needed anyway.
2023-07-09 16:04:20 -07:00
Johannes Doerfert
02a4fcec6b [Attributor] Port AANonNull to the isImpliedByIR interface
AANonNull is now the first AA that is always queried via the new APIs
and not created manually. Others will follow shortly to avoid trivial
AAs whenever possible.

This commit introduced some helper logic that will make it simpler to
port the next one. It also untangles AADereferenceable and AANonNull
such that the former does not keep a handle on the latter. Finally,
we stop deducing `nonnull` for `undef`, which was incorrect.
2023-07-09 16:04:19 -07:00
Johannes Doerfert
369930bc20 [Attributor] Manifest attributes implied by the IR
If an attribute is implied by the IR we do not (always) create an AA
anymore. To keep test coverage, and given the lack of a good heuristic
to decide otherwise, we will now also manifest such attributes.
2023-07-03 16:05:17 -07:00
Johannes Doerfert
b672c602c7 [Attributor][NFCI] Merge MemoryEffects explicitly
We had some custom handling for existing MemoryEffects but we now move
it to the place we check other existing attributes before we manifest
new ones. If we later decide to curb duplication (of attributes on the
call site and callee), we can do that at a single location and for all
attributes.

The test changes basically add known `memory` callee information to the
call sites.
2023-07-03 11:57:29 -07:00
Johannes Doerfert
badafc53c6 [Attributor] Check IR attributes before creating new AAs
Instead of creating an AA for an IR attribute we can first check if it
is implied/known. If so, we can save the time to create the AA, figure
out it is implied, fix it, and later manifest it in the IR
(redundantly). Other IR attributes can be added to the list in
`AA::hasAssumedIRAttr` later on, for now we support 8 different ones.
2023-06-23 17:21:21 -07:00
Johannes Doerfert
23dafbb1e5 [Attributor] Remove the iteration count verification
It was never really useful to track #iterations, though it helped during
the initial development. What we should track, in a follow up, are
potentially #updates. That is also what we should restrict instead of
the #iterations.
2023-06-23 16:32:36 -07:00
Johannes Doerfert
87d13b8776 [Attributor][NFC] Precommit vector write range tests 2023-06-05 16:53:45 -07:00
Johannes Doerfert
dbbe9b3776 [Attributor] Create AAMustProgress for the mustprogress attribute
Derive the mustprogress attribute based on the willreturn attribute
or the fact that all callers are mustprogress.

Differential Revision: https://reviews.llvm.org/D94740
2023-06-05 16:33:52 -07:00
Johannes Doerfert
0fc63d4e64 [Attributor][FIX] Ensure loop PHI replacements are dynamically unique
Similar to loads, PHIs can be used to introduce non-dynamically unique
values into the simplification "algorithm". We need to check that PHIs
do not carry such a value from one iteration into the next as can cause
downstream reasoning to fail, e.g., downstream could think a comparison
is equal because the simplified values are equal while they are defined
in different loop iterations. Similarly, instructions in cycles are now
conservatively treated as non-dynamically unique. We could do better but
I'll leave that for the future.

The change in AAUnderlyingObjects allows us to ignore dynamically unique
when we simply look for underlying objects. The user of that AA should
be aware that the result might not be a dynamically unique value.
2023-03-20 17:44:24 -07:00
Johannes Doerfert
a51ad873bf [OpenMP][FIX] Properly check assume only uses
We improved our simplification and this exposed a bug in the store
elimination. A load that had dead uses and assume uses was thought to be
used by assumes only. Consequently we also deleted the "dead use users".
This was a problem because a dead use just means we will not use the
load there. The user might still be needed.

Exposed by OvO, reported by @ye-luo.
2023-01-31 06:13:54 -08:00
Nikita Popov
436576a95f [Attributor] Convert some tests to opaque pointers (NFC)
Check lines were regenerated for these.

The alignment changes in byval-2. look suspicious at first glance,
but actually only propagate pre-existing UB.
2023-01-11 14:59:06 +01:00
Johannes Doerfert
31ad4dbcb9 Reapply "[Attributor] Introduce AA[Intra/Inter]Reachability"
This reverts commit e425a4c45618fcfa8ffb13be4ddfaa5d28aa38f1 after the
memory leak has been fixed.
2023-01-10 12:29:24 -08:00
Johannes Doerfert
1b9ba5856a [Attributor] Allow cfg reasoning for thread-local objects
If an object (=memory) is thread-local we do not need to worry about
threading effects.
2023-01-09 16:40:20 -08:00
Shilei Tian
acd22b2751 [AAUnderlyingObjects] Introduce an AA for getting underlying objects of a pointer
This patch introduces a new AA `AAUnderlyingObjects`. It is basically like a wrapper
AA of the function `AA::getAssumedUnderlyingObjects`, but it can recursively do
query if the underlying object is an indirect access, such as a phi node or a select
instruction.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D141164
2023-01-08 16:45:50 -05:00
Nikita Popov
e44b11d9b6 [ValueTracking] Treat branch on undef as UB as well
We were already treating branch on poison as UB, but branch on
undef is also UB. Move the checks into the correct function.

From LangRef for br:

> If ‘cond’ is poison or undef, this instruction has undefined behavior.

From LangRef for switch:

> If ‘value’ is poison or undef, this instruction has undefined behavior.

There is a minor regression in dont-distribute-phi.ll, apparently
we handle that pattern in logical but not bitwise form.
2023-01-02 12:34:23 +01:00
Sameer Sahasrabuddhe
e467a42943 [Attributor] potential constant values for PHI and Load
AAPotentialConstantValues now works for PHI and Load by simply examinig
AAPotentialValues for the instruction itself.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D140371
2022-12-21 15:59:00 +05:30
Mitch Phillips
e425a4c456 Revert "[Attributor] Introduce AA[Intra/Inter]Reachability"
This reverts commit fc21f2d7bae2e0be630470cc7ca9323ed5859892.

This patch broke the ASan buildbot. See
https://reviews.llvm.org/rGfc21f2d7bae2e0be630470cc7ca9323ed5859892 for
more information.
2022-12-16 17:56:48 -08:00
Johannes Doerfert
fc21f2d7ba [Attributor] Introduce AA[Intra/Inter]Reachability
We had two AAs for reachability but it was very cumbersome to extend
them. We also had some fallback to use LLVM-core mechanisms and cache
the result. The new design shares the query code and interface nicely
between AAIntraFnReachability and AAInterFnReachability.

As part of the rewrite we also added the ExclusionSet to the queries.
2022-12-13 19:38:15 -08:00
Johannes Doerfert
8be3133ecd [OpenMP][FIX] Remove unsound reasoning about written to values
Even if a value is for sure written we need to visit the call sites as
they might end up inside the function that reads and writes the value.
In a follow up we can introduce correct reasoning to avoid the backwards
traversal in this case and instead check if any call site between the
write and the read might reach a potential write we want to exclude.
2022-12-13 18:44:20 -08:00
Sameer Sahasrabuddhe
6a2305484e [AAPointerInfo] track multiple constant offsets for each use
An expression of the form `gep(base, select(pred, const1, const2))` can result
in a set of offsets instead of just one. PointerInfo can now track these sets
instead of conservatively modeling them as Unknown. In general, AAPointerInfo
now uses AAPotentialConstantValues to examine the operands of the GEP.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D138646
2022-12-13 22:27:25 +05:30
Sameer Sahasrabuddhe
2fdeb27790 Revert "[AAPointerInfo] track multiple constant offsets for each use"
Assertion fired in openmp-offload-amdgpu-runtime:
https://lab.llvm.org/buildbot/#/builders/193/builds/23177

This reverts commit c2a0baad1fbb21fe111fef83ec93c2d7923b9b0c.
2022-12-12 15:39:18 +05:30
Sameer Sahasrabuddhe
c2a0baad1f [AAPointerInfo] track multiple constant offsets for each use
An expression of the form `gep(base, select(pred, const1, const2))` can result
in a set of offsets instead of just one. PointerInfo can now track these sets
instead of conservatively modeling them as Unknown. In general, AAPointerInfo
now uses AAPotentialConstantValues to examine the operands of the GEP.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D138646
2022-12-12 13:36:45 +05:30
Johannes Doerfert
142e38007d [OpenMP][FIX] Do not use reachability reasoning in parallel contexts
Similar to dominance reasoning, we cannot use CFG reachability if the
instructions might be executed by different threads. A follow up will
improve our sensitivity for situations when it is OK to use graph
reasoning.
2022-12-09 14:27:55 -08:00
Sameer Sahasrabuddhe
376d0469b9 [AAPointerInfo] refactor how offsets and Access objects are tracked
This restores commit b756096b0cbef0918394851644649b3c28a886e2, which was
originally reverted in 00b09a7b18abb253d36b3d3e1c546007288f6e89.

AAPointerInfo now maintains a list of all Access objects that it owns, along
with the following maps:

- OffsetBins: OffsetAndSize -> { Access }
- InstTupleMap: RemoteI x LocalI -> Access

A RemoteI is any instruction that accesses memory. RemoteI is different from
LocalI if and only if LocalI is a call; then RemoteI is some instruction in the
callgraph starting from LocalI.

Motivation: When AAPointerInfo recomputes the offset for an instruction, it sets
the value to Unknown if the new offset is not the same as the old offset. The
instruction must now be moved from its current bin to the bin corresponding to
the new offset. This happens for example, when:

- A PHINode has operands that result in different offsets.
- The same remote inst is reachable from the same local inst via different paths
  in the callgraph:

```
               A (local inst)
               |
               B
              / \
             C1  C2
              \ /
               D (remote inst)

```
This fixes a bug where a store is incorrectly eliminated in a lit test.

Reviewed By: jdoerfert, ye-luo

Differential Revision: https://reviews.llvm.org/D136526
2022-11-15 18:52:11 +05:30
Nikita Popov
304f1d59ca [IR] Switch everything to use memory attribute
This switches everything to use the memory attribute proposed in
https://discourse.llvm.org/t/rfc-unify-memory-effect-attributes/65579.
The old argmemonly, inaccessiblememonly and inaccessiblemem_or_argmemonly
attributes are dropped. The readnone, readonly and writeonly attributes
are restricted to parameters only.

The old attributes are auto-upgraded both in bitcode and IR.
The bitcode upgrade is a policy requirement that has to be retained
indefinitely. The IR upgrade is mainly there so it's not necessary
to update all tests using memory attributes in this patch, which
is already large enough. We could drop that part after migrating
tests, or retain it longer term, to make it easier to import IR
from older LLVM versions.

High-level Function/CallBase APIs like doesNotAccessMemory() or
setDoesNotAccessMemory() are mapped transparently to the memory
attribute. Code that directly manipulates attributes (e.g. via
AttributeList) on the other hand needs to switch to working with
the memory attribute instead.

Differential Revision: https://reviews.llvm.org/D135780
2022-11-04 10:21:38 +01:00
Ye Luo
00b09a7b18 Revert "[AAPointerInfo] refactor how offsets and Access objects are tracked"
This reverts commit b756096b0cbef0918394851644649b3c28a886e2.
See regression https://github.com/llvm/llvm-project/issues/58774
2022-11-03 00:01:51 -05:00
Sameer Sahasrabuddhe
b756096b0c [AAPointerInfo] refactor how offsets and Access objects are tracked
AAPointerInfo now maintains a list of all Access objects that it owns, along
with the following maps:

- OffsetBins: OffsetAndSize -> { Access }
- InstTupleMap: RemoteI x LocalI -> Access

A RemoteI is any instruction that accesses memory. RemoteI is different from
LocalI if and only if LocalI is a call; then RemoteI is some instruction in the
callgraph starting from LocalI.

Motivation: When AAPointerInfo recomputes the offset for an instruction, it sets
the value to Unknown if the new offset is not the same as the old offset. The
instruction must now be moved from its current bin to the bin corresponding to
the new offset. This happens for example, when:

- A PHINode has operands that result in different offsets.
- The same remote inst is reachable from the same local inst via different paths
  in the callgraph:

```
               A (local inst)
               |
               B
              / \
             C1  C2
              \ /
               D (remote inst)

```
This fixes a bug where a store is incorrectly eliminated in a lit test.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D136526
2022-11-01 09:57:12 +05:30
Nikita Popov
6e504d637d [ValueTracking] Handle constant exprs in isKnownNonZero()
Handle constant expressions by falling through to the general
operator-based code. In particular, this adds support for bitcast
and GEP expressions.
2022-10-04 11:58:07 +02:00
Sameer Sahasrabuddhe
3f078b308b [AAPointerInfo] OffsetInfo: Unassigned is distinct from Unknown
A User like the PHINode may be visited multiple times for the same pointer along
different def-use edges. The uninitialized state of OffsetInfo at the first
visit needs to be distinct from the Unknown value that may be assigned after
processing the PHINode. Without that, a PHINode with all inputs Unknown is never
followed to its uses. This results in incorrect optimization because some
interfering accessess are missed.

Differential Revision: https://reviews.llvm.org/D134704
2022-09-28 20:31:36 +05:30
Nikita Popov
846709b287 [Attribute] Clean up test prefixes (NFC)
Now that the legacy PM is no longer tested, the huge matrix of
test prefixes used by attributor tests is no longer needed and very
confusing for the casual reader. Reduce the prefixes down to just
CHECK, TUNIT and CGSCC.
2022-09-23 11:08:11 +02:00
Sebastian Peryt
99c9b37d11 [NFC][1/n] Remove -enable-new-pm=0 flags from lit tests
This is the first patch in a series intended for removing flag
-enable-new-pm=0 from lit tests. This is part of a bigger
effort of completely removing legacy code related to legacy
pass manager in favor of currently default new pass manager.

In this patch flag has been removed only from tests where no significant
change has been required because checks has been duplicated for
both PMs.

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D134150
2022-09-19 09:57:37 -07:00
Johannes Doerfert
b65471d715 [Attributor][FIX] Visit same instructions with different scopes
If we collect potential values we need to visit a value even if we have
seen it before if the scope is different. The scope is part of the
result after all. Test included.

Fixes https://github.com/llvm/llvm-project/issues/56753

Differential Revision: https://reviews.llvm.org/D131597
2022-08-10 16:02:12 -05:00
Augie Fackler
85063090e9 MemoryBuiltins: remove malloc-family funcs from list
We no longer need specialized knowledge of these allocator functions in
this file since we have the correct attributes available now.

As far as I can tell the changes in the attributor tests are due to
things getting more consistent on alloc-family once we remove the static
list entries.

The two test changes in NewGVN merit extra scrutiny: NewGVN appears to
be _extremely_ sensitive to the inaccessiblememonly for reasons that
are beyond me. As a result, I had-enumerated all the attributes on
allocation functions in those two tests instead of using -inferattrs.
I assumed that the two -disable-simplify-libcalls tests there no
longer are sensible since the function declaration now includes all the
relevant attributes.

Differential Revision: https://reviews.llvm.org/D130107
2022-07-25 17:29:01 -04:00
Johannes Doerfert
6b7eae11f1 [Attributor][FIX] HasBeenWrittenTo logic should only be used for reads
If we look at a write, we should not enact the "has been written to"
logic introduced to avoid spurious write -> read dependences. Doing so
lead to elimination of stores we needed, which is obviously bad.
2022-07-22 23:57:57 -05:00
Johannes Doerfert
a50b9f9f1f [Attributor][FIX] Handle non-recursive but re-entrant functions properly
If a function is non-recursive we only performed intra-procedural
reasoning for reachability (via AA::isPotentiallyReachable). However,
if it is re-entrant that doesn't mean we can't reach. Instead of this
problematic logic in the reachability reasoning we utilize logic in
AAPointerInfo. If a location is for sure written by a function it can
be re-entrant or recursive we know only intra-procedural reasoning is
sufficient.
2022-07-22 00:00:56 -05:00
Johannes Doerfert
62f7888d6d [Attributor] Dominating must-write accesses allow unknown initial values
If we have a dominating must-write access we do not need to know the
initial value of some object to perform reasoning about the potential
values. The dominating must-write has overwritten the initial value.
2022-07-21 23:08:43 -05:00
Johannes Doerfert
dfac030271 [Intrinsics] Add nocallback to the memset/cpy/move intrinsics
These were forgotten when D118680 was applied. Similar to D125937.

Differential Revision: https://reviews.llvm.org/D129516
2022-07-21 22:52:46 -05:00
Johannes Doerfert
ad98ef8be4 [Attributor] Deal with complex PHI nodes better during AAPointerInfo
We were quite conservative when it came to PHI node handling to avoid
recursive reasoning. Now we check more direct if we have seen a PHI
already or not. This allows non-recursive PHI chains to be handled.

This also exposed a bug as we did only model the effect of one loop
traversal. `phi_no_store_3` has been adapted to show how we would have
used `undef` instead of `1` before. With this patch we don't replace
it at all, which is expected as we do not argue about loop iterations
(or alignments).
2022-07-20 17:34:50 -05:00