881 Commits

Author SHA1 Message Date
Kazu Hirata
07eb7b7692
[llvm] Replace SmallSet with SmallPtrSet (NFC) (#154068)
This patch replaces SmallSet<T *, N> with SmallPtrSet<T *, N>.  Note
that SmallSet.h "redirects" SmallSet to SmallPtrSet for pointer
element types:

  template <typename PointeeType, unsigned N>
class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N>
{};

We only have 140 instances that rely on this "redirection", with the
vast majority of them under llvm/. Since relying on the redirection
doesn't improve readability, this patch replaces SmallSet with
SmallPtrSet for pointer element types.
2025-08-18 07:01:29 -07:00
Nikita Popov
fb632ed237
[GVN] Handle provenance when propagating assume equality (#151953)
If we have a known `p == p2` equality, we cannot replace `p2` with `p`
unless they are known to have the same provenance. GVN handles this when
propagating equalities from conditions, but not for assumes, as these go
through a different code path for uses in the same block.

Call canReplacePointersInUseIfEqual() before performing the replacement.
This is subject to the usual approximations (e.g. that we always allow
replacement with a dereferenceable constant and null).

This restriction does not appear to have any impact in practice.
2025-08-05 09:18:43 +02:00
Nikita Popov
e044cc50ee
[GVN] Handle not in equality propagation (#151942)
Look through `not` when propagating equalities in GVN. Usually these
will be canonicalized away, but they may be retained due to multi-use or
involvement in logical expressions.

Fixes https://github.com/llvm/llvm-project/issues/143529.
2025-08-05 09:11:24 +02:00
Nikita Popov
4b5b36e5c4 [GVN] Avoid creating lifetime of non-alloca
There is a larger problem here in that we should not be performing
arbitrary pointer replacements for assumes. This is handled for
branches, but assume goes through a different code path.

Fixes https://github.com/llvm/llvm-project/issues/151785.
2025-08-04 12:06:40 +02:00
Madhur Amilkanthwar
3eb07996b1
[GVN][NFCI] Use early return in phiTranslateImpl() (#149273) 2025-07-18 10:07:47 +05:30
Madhur Amilkanthwar
8b553c4951
Revert "[GVN][NFC] Use early return in phiTranslateImpl() (#149268)" (#149270)
This reverts commit 1d398a96dc6b58d15d289c71e2d9f229a0ba719b.
2025-07-17 13:44:26 +05:30
Madhur Amilkanthwar
1d398a96dc
[GVN][NFC] Use early return in phiTranslateImpl() (#149268) 2025-07-17 13:22:06 +05:30
Jeremy Morse
5b8c15c6e7
[DebugInfo] Remove getPrevNonDebugInstruction (#148859)
With the advent of intrinsic-less debug-info, we no longer need to
scatter calls to getPrevNonDebugInstruction around the codebase. Remove
most of them -- there are one or two that have the "SkipPseudoOp" flag
turned on, however they don't seem to be in positions where skipping
anything would be reasonable.
2025-07-16 11:41:32 +01:00
Jeremy Morse
9eb0020555
[DebugInfo][RemoveDIs] Remove a swathe of debug-intrinsic code (#144389)
Seeing how we can't generate any debug intrinsics any more: delete a
variety of codepaths where they're handled. For the most part these are
plain deletions, in others I've tweaked comments to remain coherent, or
added a type to (what was) type-generic-lambdas.

This isn't all the DbgInfoIntrinsic call sites but it's most of the
simple scenarios.

Co-authored-by: Nikita Popov <github@npopov.com>
2025-06-17 15:55:14 +01:00
Antonio Frighetto
d3f13a0732
[GVN] MemorySSA for GVN: embed the memory state in symbolic expressions (#123218)
While migrating towards MemorySSA, account for the memory state modeled
by MemorySSA by hashing it, when computing the symbolic expressions for
the memory operations. Likewise, when phi-translating while walking the
CFG for PRE possibilities, see if the value number of an operand may be
refined with one of the value from the incoming edges of the MemoryPhi
associated to the current phi.

Co-authored-by: Momchil Velikov <momchil.velikov@arm.com>
2025-06-17 12:30:47 +02:00
Matt Arsenault
1f4b172985
GVN: Fix trying to inspect uselist of constants when emitting remark (#144009) 2025-06-13 16:46:20 +09:00
Yash Solanki
73a351e7d4
[llvm][GVN] Propagate trunc nuw to i1 equalities (#143273)
This patch adds to GVN's `propagateEquality()` to reason about equality
constraints through `trunc nuw iN to i1`.

Given:
  %tr = trunc nuw iN %v to i1

We can deduce that if `%tr == true`, then `%v == 1`, and if `%tr ==
false`, then `%v == 0`. This is valid because `nuw` guarantees that
truncation didn't lose unsigned bits, so `%v` must have been either 0 or
1.

The patch adds logic to propagate this information via the GVN worklist.
This enables further simplification opportunities downstream, such as
folding redundant stores or conditionals that depend on `%v`.

Includes a test case in `GVN/trunc-nuw-equality.ll`.

Resolves #142744
2025-06-08 18:58:16 +02:00
Madhur Amilkanthwar
015093d628
[GVN] Improve processBlock for instruction erasure (#131753)
This patch deletes the instructions immediately in core GVN processing by using the appropriate
iterators. Thus, it avoids collecting the instructions in a vector and then
doing the erasure.
2025-05-06 13:55:10 +05:30
Kazu Hirata
26d71f9ef2
[Transforms] Use range-based for loops (NFC) (#138476) 2025-05-04 16:08:31 -07:00
Kazu Hirata
b01e25deba
[llvm] Call hash_combine_range with ranges (NFC) (#136511) 2025-04-20 16:36:03 -07:00
Antonio Frighetto
460d628d90 [GVN] Clean up unused argument, unify style, modernize syntax (NFC)
Finalize code style overhaul in GVN, following up to
2a0946bc0dffca89d16cd9d5208ec9416ed8100e and 9deed7d2ef3a147c4e8410910967fde601359039.
2025-03-28 15:59:28 +01:00
Kazu Hirata
cde58bfc16
[Transforms] Use range constructors of *Set (NFC) (#133203) 2025-03-27 07:51:58 -07:00
Kazu Hirata
0dcc201ac4
[Transforms] Use *Set::insert_range (NFC) (#132056)
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently
gained C++23-style insert_range.  This patch replaces:

  Dest.insert(Src.begin(), Src.end());

with:

  Dest.insert_range(Src);

This patch does not touch custom begin like succ_begin for now.
2025-03-19 15:35:01 -07:00
Madhur Amilkanthwar
9deed7d2ef
[GVN][NFC] Fix some more coding standard violations (#130046) 2025-03-06 15:33:02 +05:30
Madhur Amilkanthwar
dddfd77f65
[GVN][NFC] Fix some variables as per coding standards (#129489) 2025-03-03 20:14:01 +05:30
Madhur Amilkanthwar
2a0946bc0d
[GVN][NFC] Match coding standards (#128683)
As per LLVM coding standards
"Variable names should be nouns (as they represent state).
 The name should be camel case, and start with an upper
 case letter (e.g. Leader or Boats)."
2025-02-25 15:45:26 +05:30
Lou
c75b251103
[GVN] Load-store forwaring of scalable store to fixed load. (#124748)
When storing a scalable vector and loading a fixed-size vector, where
the
scalable vector is known to be larger based on vscale_range, perform
store-to-load forwarding through temporary @llvm.vector.extract calls.
InstCombine then folds the insert/extract pair away.

The usecase is shown in https://godbolt.org/z/KT3sMrMbd, which shows
that clang generates IR that matches this pattern when the
"arm_sve_vector_bits" attribute is used:

```c
typedef svfloat32_t svfloat32_fixed_t
__attribute__((arm_sve_vector_bits(512)));

struct svfloat32_wrapped_t {
  svfloat32_fixed_t v;
};

static inline svfloat32_wrapped_t
add(svfloat32_wrapped_t a, svfloat32_wrapped_t b) {
  return {svadd_f32_x(svptrue_b32(), a.v, b.v)};
}

svfloat32_wrapped_t
foo(svfloat32_wrapped_t a, svfloat32_wrapped_t b) {
  // The IR pattern this patch matches is generated for this return:
  return add(a, b);
}
```
2025-01-30 11:49:42 +01:00
Jeremy Morse
6292a808b3
[NFC][DebugInfo] Use iterator-flavour getFirstNonPHI at many call-sites (#123737)
As part of the "RemoveDIs" project, BasicBlock::iterator now carries a
debug-info bit that's needed when getFirstNonPHI and similar feed into
instruction insertion positions. Call-sites where that's necessary were
updated a year ago; but to ensure some type safety however, we'd like to
have all calls to getFirstNonPHI use the iterator-returning version.

This patch changes a bunch of call-sites calling getFirstNonPHI to use
getFirstNonPHIIt, which returns an iterator. All these call sites are
where it's obviously safe to fetch the iterator then dereference it. A
follow-up patch will contain less-obviously-safe changes.

We'll eventually deprecate and remove the instruction-pointer
getFirstNonPHI, but not before adding concise documentation of what
considerations are needed (very few).

---------

Co-authored-by: Stephen Tozer <Melamoto@gmail.com>
2025-01-24 13:27:56 +00:00
Jeremy Morse
8e70273509
[NFC][DebugInfo] Use iterator moveBefore at many call-sites (#123583)
As part of the "RemoveDIs" project, BasicBlock::iterator now carries a
debug-info bit that's needed when getFirstNonPHI and similar feed into
instruction insertion positions. Call-sites where that's necessary were
updated a year ago; but to ensure some type safety however, we'd like to
have all calls to moveBefore use iterators.

This patch adds a (guaranteed dereferenceable) iterator-taking
moveBefore, and changes a bunch of call-sites where it's obviously safe
to change to use it by just calling getIterator() on an instruction
pointer. A follow-up patch will contain less-obviously-safe changes.

We'll eventually deprecate and remove the instruction-pointer
insertBefore, but not before adding concise documentation of what
considerations are needed (very few).
2025-01-24 10:53:11 +00:00
Antonio Frighetto
7a0f75c738 Reapply "[GVN] MemorySSA for GVN: add optional AllowMemorySSA"
Original commit: eb63cd62a4a1907dbd58f12660efd8244e7d81e9

Previously reverted due to non-negligible compile-time impact in
stage1-ReleaseLTO-g scenario. The issue has been addressed by
always reusing previously computed MemorySSA results, and request
new ones only when `isMemorySSAEnabled` is set.

Co-authored-by: Momchil Velikov <momchil.velikov@arm.com>
2025-01-14 10:03:47 +01:00
Nikita Popov
c39500f88c Revert "[GVN] MemorySSA for GVN: add optional AllowMemorySSA"
This reverts commit eb63cd62a4a1907dbd58f12660efd8244e7d81e9.

This changes the preservation behavior for MSSA when the new flag
is not enabled.
2025-01-10 12:57:00 +01:00
Momchil Velikov
eb63cd62a4 [GVN] MemorySSA for GVN: add optional AllowMemorySSA
Preparatory work to migrate from MemoryDependenceAnalysis
towards MemorySSA in GVN.

Co-authored-by: Antonio Frighetto <me@antoniofrighetto.com>
2025-01-10 10:43:12 +01:00
Stephen Tozer
f37bc8cfbf
[DebugInfo][GVN] Propagate DebugLoc from load-of-select to select (#114233)
When replacing a load from a selected pointer with a select of the known
stored values, we currently assign no DebugLoc to the select; this patch
propagates the load's DebugLoc to the new select, since it is a direct
replacement.
2024-11-15 17:07:33 +00:00
macurtis-amd
eea8b44aaa
[GVN] Handle empty attrs in Expression == (#115761) 2024-11-12 09:08:06 -06:00
Yingwei Zheng
984bca9d1f
[GVN][NewGVN] Take call attributes into account in expressions (#114545)
Drop `canBeReplacedBy` and take call attributes into account in
expressions.
Address comment
https://github.com/llvm/llvm-project/pull/114011#pullrequestreview-2409772313.
2024-11-08 16:00:48 +08:00
Ramkumar Ramachandra
cd16b077bf
IR: introduce CmpInst::isEquivalence (#111979)
Steal impliesEquivalanceIf{True,False} (sic) from GVN, and extend it for
floating-point constant vectors, and accounting for denormal values.
Since InstCombine also performs GVN-like replacements, introduce
CmpInst::isEquivalence, and remove the corresponding code in GVN, with
the intent of using it in more places.

The code in GVN also has a bad FIXME saying that the optimization may be
valid in the nsz case, but this is not the case.

Alive2 proof: https://alive2.llvm.org/ce/z/vEaK8M
2024-11-04 15:54:59 +00:00
Yingwei Zheng
f16bff1261
[GVN][NewGVN][Local] Handle attributes for function calls after CSE (#114011)
This patch intersects attributes of two calls to avoid introducing UB.
It also skips incompatible call pairs in GVN/NewGVN. However, I cannot
provide negative tests for these changes.

Fixes https://github.com/llvm/llvm-project/issues/113997.
2024-11-01 12:44:33 +08:00
Jeremy Morse
96f37ae453
[NFC] Use initial-stack-allocations for more data structures (#110544)
This replaces some of the most frequent offenders of using a DenseMap that
cause a malloc, where the typical element-count is small enough to fit in
an initial stack allocation.

Most of these are fairly obvious, one to highlight is the collectOffset
method of GEP instructions: if there's a GEP, of course it's going to have
at least one offset, but every time we've called collectOffset we end up
calling malloc as well for the DenseMap in the MapVector.
2024-09-30 23:15:18 +01:00
Nikita Popov
9df71d7673
[IR] Add getDataLayout() helpers to Function and GlobalValue (#96919)
Similar to https://github.com/llvm/llvm-project/pull/96902, this adds
`getDataLayout()` helpers to Function and GlobalValue, replacing the
current `getParent()->getDataLayout()` pattern.
2024-06-28 08:36:49 +02:00
Nikita Popov
2d209d964a
[IR] Add getDataLayout() helpers to BasicBlock and Instruction (#96902)
This is a helper to avoid writing `getModule()->getDataLayout()`. I
regularly try to use this method only to remember it doesn't exist...

`getModule()->getDataLayout()` is also a common (the most common?)
reason why code has to include the Module.h header.
2024-06-27 16:38:15 +02:00
Owen Anderson
d529e780f3
[GVN] Refactor the LeaderTable structure into a properly encapsulated data structure (#88347)
Hide the details of the one-off linked list used to implement the leader
lists by
wrapping them in iterators, and then use that to reimplement a number of
traversals
using standard algorithms and range-based for-loops.

No functional change intended.
2024-04-26 02:37:54 -06:00
Usman Nadeem
b10e4b82e6
[GVN] Restrict equality propagation for pointers (#82458)
This patch does the following:

Adds the following functions:
- replaceDominatedUsesWithIf() that takes a callback.

- canReplacePointersIfEqual(...) returns true if the underlying object
is the same, and for null and const dereferencable pointer replacements.

- canReplacePointersIfEqualInUse(...) returns true for the above as well
as if the use is in icmp/ptrtoint or phi/selects feeding into them.

Updates GVN using the functions above so that the pointer replacements
are only made using the above API.

https://reviews.llvm.org/D143129
2024-04-24 08:59:42 -07:00
Enna1
ef9446bd2d
[GVN] lazily update dominator tree when merge unconditional branches in function (#88477)
With this change, the wall time for of GVN pass decreased from
873,745.492 ms to 367,375.304 ms in an our internal testcase.
2024-04-14 11:01:02 +08:00
Jeremy Morse
2fe81edef6 [NFC][RemoveDIs] Insert instruction using iterators in Transforms/
As part of the RemoveDIs project we need LLVM to insert instructions using
iterators wherever possible, so that the iterators can carry a bit of
debug-info. This commit implements some of that by updating the contents of
llvm/lib/Transforms/Utils to always use iterator-versions of instruction
constructors.

There are two general flavours of update:
 * Almost all call-sites just call getIterator on an instruction
 * Several make use of an existing iterator (scenarios where the code is
   actually significant for debug-info)
The underlying logic is that any call to getFirstInsertionPt or similar
APIs that identify the start of a block need to have that iterator passed
directly to the insertion function, without being converted to a bare
Instruction pointer along the way.

Noteworthy changes:
 * FindInsertedValue now takes an optional iterator rather than an
   instruction pointer, as we need to always insert with iterators,
 * I've added a few iterator-taking versions of some value-tracking and
   DomTree methods -- they just unwrap the iterator. These are purely
   convenience methods to avoid extra syntax in some passes.
 * A few calls to getNextNode become std::next instead (to keep in the
   theme of using iterators for positions),
 * SeparateConstOffsetFromGEP has it's insertion-position field changed.
   Noteworthy because it's not a purely localised spelling change.

All this should be NFC.
2024-03-05 15:12:22 +00:00
Kazu Hirata
fc15731183 [Transforms] Use a range-based for loop (NFC) 2024-01-28 18:03:35 -08:00
Kazu Hirata
03dc806b12 [Transforms] Use {DenseMap,SmallPtrSet}::contains (NFC) 2023-12-22 14:51:22 -08:00
Nikita Popov
7f1733a252
[GVN] Fix use-after-free in load PRE with select available value (#69314)
replaceValuesPerBlockEntry() only handled simple and coerced load
values, however the load may also be referenced by a select value.

Additionally, I suspect that the previous code might have been incorrect
if a load had an offset, as it always constructed the AvailableValue
from scratch.

Fixes https://github.com/llvm/llvm-project/issues/69301.
2023-10-19 09:08:59 +02:00
Nikita Popov
fa5884770a [GVN] Always require LoopInfo
GVN behavior depends on LoopInfo in multiple ways, most notably
as a dependency for loop load PRE. As this is not a preserved-only
analysis, using a cached analysis is inappropriate.

In the actual optimization pipeline LoopInfo is always available
at the point GVN runs, but this will ensure it stays this way
even if the pipeline changes.
2023-10-11 11:28:26 +02:00
Jay Foad
b78f3ea7df
Clean up strange uses of getAnalysisIfAvailable (#65729)
After a pass calls addRequired<X>() it is strange to call
getAnalysisIfAvailable<X>() because analysis X should always be
available. Use getAnalysis<X>() instead.
2023-10-11 09:53:00 +01:00
Christian Sigg
c64a098ee4
[GVN] Fix after 46aac949bc
replaceUsersOf -> removeUsersOf
2023-10-05 11:31:35 +02:00
Nikita Popov
46aac949bc [GVN] Remove users from ICF when RAUWing loads
When performing store to load forwarding, replacing users of the
load may turn an indirect call into one with a known callee, in
which case it might become willreturn, invalidating cached ICF
information. Avoid this by removing users.

This is a bit more aggressive than strictly necessary (e.g. this
shouldn't be necessary when doing load-load CSE), but better safe
than sorry.

Fixes https://github.com/llvm/llvm-project/issues/48805.
2023-10-05 11:21:33 +02:00
Nikita Popov
18e77760ce [GVN] Also remove phi nodes from VN table (PR65447)
Followup to D158849: We also need to remove the phi node from the
VN table, which is not handled by removeInstruction().

Fixes https://github.com/llvm/llvm-project/issues/65447.
2023-09-15 11:50:34 +02:00
Nikita Popov
7c229f6e85 [GVN] Invalidate MDA when deduplicating phi nodes
Duplicate phi nodes were being directly removed, without
invalidating MDA. This could result in a new phi node being
allocated at the same address, incorrectly reusing a cache entry.

Fix this by optionally allowing EliminateDuplicatePHINodes() to
collect phi nodes to remove into a vector, which allows GVN to
handle removal itself.

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

Differential Revision: https://reviews.llvm.org/D158849
2023-09-15 07:04:32 +02:00
Sergey Kachkov
4b14148d24
[GVN] Skip debug instructions in findDominatingValue function (#65977)
findDominatingValue has a search limit, and when it is reached, optimization is
not applied. This patch fixes the issue that this limit also takes into account
debug intrinsics, so the result of optimization can depend from the presence of
debug info.
2023-09-13 11:23:26 +03:00
Jeremy Morse
6942c64e81 [NFC][RemoveDIs] Prefer iterator-insertion over instructions
Continuing the patch series to get rid of debug intrinsics [0], instruction
insertion needs to be done with iterators rather than instruction pointers,
so that we can communicate information in the iterator class. This patch
adds an iterator-taking insertBefore method and converts various call sites
to take iterators. These are all sites where such debug-info needs to be
preserved so that a stage2 clang can be built identically; it's likely that
many more will need to be changed in the future.

At this stage, this is just changing the spelling of a few operations,
which will eventually become signifiant once the debug-info bearing
iterator is used.

[0] https://discourse.llvm.org/t/rfc-instruction-api-changes-needed-to-eliminate-debug-intrinsics-from-ir/68939

Differential Revision: https://reviews.llvm.org/D152537
2023-09-11 11:48:45 +01:00