779 Commits

Author SHA1 Message Date
hanbeom
a750fcb52b
[GVN] Check IndirectBr in Predecessor Terminators (#151188)
Critical edges with an IndirectBr terminator cannot be split. 
Add a check it to prevent assertion failures.

Fixes: #150229
2025-08-11 09:25:52 +02:00
Nikita Popov
c23b4fbdbb
[IR] Remove size argument from lifetime intrinsics (#150248)
Now that #149310 has restricted lifetime intrinsics to only work on
allocas, we can also drop the explicit size argument. Instead, the size
is implied by the alloca.

This removes the ability to only mark a prefix of an alloca alive/dead.
We never used that capability, so we should remove the need to handle
that possibility everywhere (though many key places, including stack
coloring, did not actually respect this).
2025-08-08 11:09:34 +02:00
Madhur Amilkanthwar
13daf3b70c
[GVN-PRE][Tests] Add MSSA coverage to some more tests [4/N] (#151919)
This should be the final PR for tests under PRE.
2025-08-07 11:16:07 +05:30
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
da11c1d594 [GVN] Generate test checks (NFC) 2025-08-04 14:26:59 +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
Antonio Frighetto
3eda63c958
[GVN] Add MemorySSA coverage to tests (NFC)
Test check lines have been regenerated by ensuring parity between
MemDep and MemorySSA, while migrating towards the latter.
2025-08-01 15:10:58 +02:00
Madhur Amilkanthwar
4ee6943eeb
[GVN][Tests] Add MSSA coverage to some PRE tests 3/N (#150603)
Previous patch in this series
https://github.com/llvm/llvm-project/pull/137814
2025-07-30 10:52:33 +05:30
Nikita Popov
2c6eec219d [Tests] Avoid lifetime intrinsics on non-allocas (NFC)
Don't rely on auto-upgrade, instead either remove unnecessary
casts or remove no longer applicable tests.
2025-07-23 15:05:43 +02:00
Nikita Popov
92c55a315e
[IR] Only allow lifetime.start/end on allocas (#149310)
lifetime.start and lifetime.end are primarily intended for use on
allocas, to enable stack coloring and other liveness optimizations. This
is necessary because all (static) allocas are hoisted into the entry
block, so lifetime markers are the only way to convey the actual
lifetimes.

However, lifetime.start and lifetime.end are currently *allowed* to be
used on non-alloca pointers. We don't actually do this in practice, but
just the mere fact that this is possible breaks the core purpose of the
lifetime markers, which is stack coloring of allocas. Stack coloring can
only work correctly if all lifetime markers for an alloca are
analyzable.

* If a lifetime marker may operate on multiple allocas via a select/phi,
we don't know which lifetime actually starts/ends and handle it
incorrectly (https://github.com/llvm/llvm-project/issues/104776).
* Stack coloring operates on the assumption that all lifetime markers
are visible, and not, for example, hidden behind a function call or
escaped pointer. It's not possible to change this, as part of the
purpose of lifetime markers is that they work even in the presence of
escaped pointers, where simple use analysis is insufficient.

I don't think there is any way to have coherent semantics for lifetime
markers on allocas, while also permitting them on arbitrary pointer
values.

This PR restricts lifetimes to operate on allocas only. As a followup, I
will also drop the size argument, which is superfluous if we always
operate on an alloca. (This change also renders various code handling
lifetime markers on non-alloca dead. I plan to clean up that kind of
code after dropping the size argument as well.)

In practice, I've only found a few places that currently produce
lifetimes on non-allocas:

* CoroEarly replaces the promise alloca with the result of an intrinsic,
which will later be replaced back with an alloca. I think this is the
only place where there is some legitimate loss of functionality, but I
don't think this is particularly important (I don't think we'd expect
the promise in a coroutine to admit useful lifetime optimization.)
* SafeStack moves unsafe allocas onto a separate frame. We can safely
drop lifetimes here, as SafeStack performs its own stack coloring.
* Similar for AddressSanitizer, it also moves allocas into separate
memory.
* LSR sometimes replaces the lifetime argument with a GEP chain of the
alloca (where the offsets ultimately cancel out). This is just
unnecessary. (Fixed separately in
https://github.com/llvm/llvm-project/pull/149492.)
* InferAddrSpaces sometimes makes lifetimes operate on an addrspacecast
of an alloca. I don't think this is necessary.
2025-07-21 15:04:50 +02:00
Madhur Amilkanthwar
2320cddfc2
Reapply "[GVN] memoryssa implies no-memdep (#149473)" (#149767)
Enabling one of MemorySSA or MD implies the other is off.

Already approved in https://github.com/llvm/llvm-project/pull/149473 but
I had to revert as I missed updating one test.
2025-07-21 14:05:29 +05:30
Madhur Amilkanthwar
f79d6b319d
Revert "[GVN] memoryssa implies no-memdep (#149473)" (#149766)
This reverts commit 60d2d94db253a9fdc7bd111120c803f808564b30.
2025-07-21 11:04:54 +05:30
Madhur Amilkanthwar
60d2d94db2
[GVN] memoryssa implies no-memdep (#149473)
Enabling one of MemorySSA or MD implies the other is off.
2025-07-21 10:48:03 +05:30
Kunqiu Chen
a6e1700fa6
[Utils][Local] Preserve !nosanitize in combineMetadata when merging instructions (#148376)
`combineMetadata` helper currently drops `!nosanitize` metadata when
merging two instructions, even if both originally carried `!nosanitize`.

This is problematic because `!nosanitize` is a key mechanism used by
sanitizer (e.g., ASan) to suppress instrumentation. Removing it can lead
to unintended sanitizer behavior.

This patch adds `nosanitize` to the whitelist in combineMetadata,
preserving it only if both instructions carry `!nosanitize`; otherwise,
it is dropped. This patch also adds corresponding tests in a test file
and regenerates it.

---
### Details

**Example (see [Godbolt](https://godbolt.org/z/83P5eWczx) for
details**):

```llvm
%v1 = load i32, ptr %p, !nosanitize
%v2 = load i32, ptr %p, !nosanitize
```
When merged via `combineMetadata(%v1, %v2, ...)`, the resulting
instruction loses its `!nosanitize` metadata.

Tools such as UBSan and AFL rely on `nosanitize` to prevent unwanted
transformations or checks. However, the current implementation of
combineMetadata mistakenly drops !nosanitize. This may lead to
unintended behavior during optimization.

For example, under `-fsanitize=address,undefined -O2`, IR emitted by
UBSan may lose its `!nosanitize` metadata due to the incorrect metadata
merging in optimization. As a result, ASan could unexpectedly instrument
those instructions.
> Note: due to the current UBSan handlers having relatively
coarse-grained attributes, this specific case is difficult to reproduce
end-to-end from source code—UBSan currently inhibits such optimizations
(refer to #135135 for details).

Still, I believe it's necessary to fix this now, to support future
versions of UBSan that might allow such optimizations, and to support
third-party tools (such as AFL-based fuzzers) that rely on the presence
of !nosanitize.
2025-07-14 15:45:08 +08:00
Jon Roelofs
526310e916
[Remarks] Elaborate on called intrinsics (#143985) 2025-06-17 10:10:51 -07:00
Matt Arsenault
1f4b172985
GVN: Fix trying to inspect uselist of constants when emitting remark (#144009) 2025-06-13 16:46:20 +09:00
Nikita Popov
bc7fafbeea
[AA] Take read-only provenance captures into account (#143097)
Update the AA CaptureAnalysis providers to return CaptureComponents, so
we can distinguish between full provenance and read-only provenance
captures.

Use this to restrict "other" memory effects on call from ModRef to Ref.

Ideally we would also apply the same reasoning for escape sources, but
the current API cannot actually convey the necessary information (we can
only say NoAlias or MayAlias, not MayAlias but only via Ref).
2025-06-12 14:13:15 +02: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
Nikita Popov
7d4464599f [GVN] Add test with different captures attributes (NFC) 2025-06-06 11:24:24 +02:00
Madhur Amilkanthwar
40778822f7
[GVN][NFC] Add MSSA checks in tests 2/N (#137814)
The previous patch in this series is #130261
2025-05-15 10:29:41 +05:30
Philip Reames
15c2f79153 [DSE/GVN] Continue to improve memset.pattern testing [nfc]
This batch reveals two missed optimizations, but only one of which
is regression as compared to the memset_patternN libcall family.
2025-05-05 09:25:23 -07:00
Snehasish Kumar
2007dcfeb8
Reapply [Metadata] Preserve MD_prof when merging instructions when one is missing. (#135418)
Preserve branch weight metadata when merging instructions if one of the
instructions is missing metadata. This is similar in behaviour to what
we do today for other types of metadata such as mmra, memprof and
callsite metadata.

Also add a legality check when merging prof metadata based on
instruction type. Without this check GVN PRE optimizations result in
prof metadata on phi nodes which break the module verifier.

Build failure caught by
https://lab.llvm.org/buildbot/#/builders/113/builds/6621
```
!9185 = !{!"branch_weights", i32 3912, i32 802}
Wrong number of operands
!9185 = !{!"branch_weights", i32 3912, i32 802}
fatal error: error in backend: Broken module found, compilation aborted!
```

Reverts #134200 with additional changes.
2025-04-17 08:22:19 -07:00
Matt Arsenault
b37476f99c PHITransAddr: Avoid looking at constant use lists (#134689)
Avoids asserts in GVN
2025-04-13 16:58:57 +02:00
Yingwei Zheng
db27a0af5e
[AMDGPU][InstCombine][InstSimplify] Pre-commit tests for PR130742 (#135305)
https://github.com/llvm/llvm-project/pull/130742#discussion_r1993055149
2025-04-11 12:42:14 +08:00
Madhur Amilkanthwar
ad0827d364
[GVN] Add MemorySSA checks in tests 1/N (#130261)
Add MemorySSA checks in some GVN tests. This is first patch of the series and many more might come based on tests pass/fail.
2025-03-21 12:00:22 +05:30
Madhur Amilkanthwar
a6adb63d35
[GVN][NFC] Remove triple from some tests (#129724)
These tests should not require triple.
2025-03-05 09:12:29 +05:30
Madhur Amilkanthwar
b7f31044f3
[GVN][NFC] Remove unnecessary assembly output from test (#129670)
This test doesn't check any output from opt, so it can be safely
`disable-output` and thus less redirections.
2025-03-04 14:29:49 +05:30
Madhur Amilkanthwar
9fefc013db
[GVN/PRE] Remove triple from GVN/PRE tests (#129073)
The tests in GVN/PRE need not to depend on target triple. Removing the
triple dependence from all the tests in this directory.
2025-02-28 11:43:45 +05:30
Nikita Popov
d8b2e432d6
[IR] Remove mul constant expression (#127046)
Remove support for the mul constant expression, which has previously
already been marked as undesirable. This removes the APIs to create mul
expressions and updates tests to stop using mul expressions.

Part of:
https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179
2025-02-14 09:28:57 +01:00
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
Nikita Popov
29441e4f5f
[IR] Convert from nocapture to captures(none) (#123181)
This PR removes the old `nocapture` attribute, replacing it with the new
`captures` attribute introduced in #116990. This change is
intended to be essentially NFC, replacing existing uses of `nocapture`
with `captures(none)` without adding any new analysis capabilities.
Making use of non-`none` values is left for a followup.

Some notes:
* `nocapture` will be upgraded to `captures(none)` by the bitcode
   reader.
* `nocapture` will also be upgraded by the textual IR reader. This is to
   make it easier to use old IR files and somewhat reduce the test churn in
   this PR.
* Helper APIs like `doesNotCapture()` will check for `captures(none)`.
* MLIR import will convert `captures(none)` into an `llvm.nocapture`
   attribute. The representation in the LLVM IR dialect should be updated
   separately.
2025-01-29 16:56:47 +01:00
Stephen Tozer
822f74a911
[Clang] Cleanup docs and comments relating to -fextend-variable-liveness (#124767)
This patch contains a number of changes relating to the above flag;
primarily it updates comment references to the old flag names,
"-fextend-lifetimes" and "-fextend-this-ptr" to refer to the new names,
"-fextend-variable-liveness[={all,this}]". These changes are all NFC.

This patch also removes the explicit -fextend-this-ptr-liveness flag
alias, and shortens the help-text for the main flag; these are both
changes that were meant to be applied in the initial PR (#110000), but
due to some user-error on my part they were not included in the merged
commit.
2025-01-28 18:25:32 +00:00
David Green
775d0f36f7
[GVN] Handle scalable vectors with the same size in VNCoercion (#123984)
This allows us to forward to a load even if the types do not match
(nxv4i32 vs nxv2i64 for example). Scalable types are allowed in
canCoerceMustAliasedValueToLoad so long as the size (minelts *
scalarsize) is the same, and some follow-on code is adjusted to make
sure it handles scalable sizes correctly. Methods like
analyzeLoadFromClobberingWrite and analyzeLoadFromClobberingStore still
do nothing for scalable vectors, as Offsets and mismatching types are
not supported.
2025-01-23 18:43:50 +00:00
David Green
6d4e72abb8 [GVN] Add extra vscale tests with different types. NFC 2025-01-23 17:36:06 +00:00
Nikita Popov
10f315dc9c
[ConstantFolding] Infer getelementptr nuw flag (#119214)
Infer nuw from nusw and nneg. This is the constant expression variant of
https://github.com/llvm/llvm-project/pull/111144.

Proof: https://alive2.llvm.org/ce/z/ihztLy
2024-12-09 16:44:05 +01:00
Paul Walker
a88653a2cd
[LLVM][IR] When evaluating GEP offsets don't assume ConstantInt is a scalar. (#117162) 2024-12-04 12:45:30 +00:00
Nikita Popov
5b0f4f2cb0
[BasicAA] Treat returns_twice functions as clobbering unescaped objects (#117902)
Effectively this models all the accesses that occur between the first
and second return as happening at the point of the call.

Fixes https://github.com/llvm/llvm-project/issues/116668.
2024-12-03 09:55:12 +01:00
Nikita Popov
611f5b8ff9 [GVN] Add test for #116668 (NFC) 2024-11-27 17:23:23 +01:00
Florian Hahn
46a08579f2
[Local] Only intersect alias.scope,noalias & parallel_loop if inst moves (#117716)
Preserve !alias.scope, !noalias and !mem.parallel_loop_access metadata
on the replacement instruction, if it does not move. In that case, the
program would be UB, if the aliasing property encoded in the metadata
does not hold. This makes use of the clarification re aliasing metadata
implying UB if the property does not hold: #116220

Same as #115868, but for !alias.scope, !noalias and
!mem.parallel_loop_access.


PR: https://github.com/llvm/llvm-project/pull/117716
2024-11-26 20:39:53 +00:00
Arthur Eubanks
6f68d039a5
[MemDepAnalysis] Don't reuse NonLocalPointerDeps cache if memory location size differs (#116936)
As seen in #111585, we can end up using a previous cache entry where the
size was too large and was UB.

Compile time impact:
https://llvm-compile-time-tracker.com/compare.php?from=6a863f7e2679a60f2f38ae6a920d0b6e1a2c1690&to=faccf4e1f47fcd5360a438de2a56d02b770ad498&stat=instructions:u.

Fixes #111585.
2024-11-21 09:25:10 -08:00
Florian Hahn
0bb1b68330
[Local] Only intersect tbaa metadata if instr moves. (#116682)
Preserve tbaa metadata on the replacement instruction, if it does not
move. In that case, the program would be UB, if the aliasing property
encoded in the metadata does not hold.

This makes use of the clarification re tbaa metadata implying UB if the
property does not hold: https://github.com/llvm/llvm-project/pull/116220

Same as https://github.com/llvm/llvm-project/pull/115868, but for !tbaa

PR: https://github.com/llvm/llvm-project/pull/116682
2024-11-20 19:31:16 +00: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
Lee Wei
88ad44ec43
[llvm] Remove br i1 undef from some regression tests [NFC] (#115817)
This PR removes tests with `br i1 undef` under `llvm/tests/G*`.
There were a few tests that I couldn't fix to pass lit. I'll come back
and fix those later.
2024-11-12 09:11:47 +00: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
Paul Walker
38fffa630e
[LLVM][IR] Use splat syntax when printing Constant[Data]Vector. (#112548) 2024-11-06 11:53:33 +00: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
Ramkumar Ramachandra
148a8fef10
GVN/test: regen a test with UTC (NFC) (#111365) 2024-10-08 15:09:10 +01:00