Commit graph

2228 commits

Author SHA1 Message Date
Florian Hahn
814a883c3c
[SCEV] Remove ptrtoint expression (NFC). (#212038)
Follow-up to https://github.com/llvm/llvm-project/pull/180244 to remove
the now unused SCEVPtrToIntExpr.

PR: https://github.com/llvm/llvm-project/pull/212038
2026-07-26 21:28:16 +01:00
Florian Hahn
f5652b9800
[SCEV] Store type of expression inline, compute up front (NFC). (#211891)
Add SCEV::Type to store the expressions immutable type. This slightly
increases object size for most sub-types, but avoids more expensive
recomputing of the type repeatedly.

Improves compile time slightly overall, more in SCEV-heavy workloads.

 * stage1-O3: -0.08%
 * stage1-ReleaseThinLTO: -0.07%
 * stage1-ReleaseLTO-g: -0.07%
 * stage1-aarch64-O3: -0.07%
 * stage2-O3: -0.08%


https://llvm-compile-time-tracker.com/compare.php?from=f9b12955f891bb086d12309d89656821d776e858&to=0e8df1e93422960640d0efd460212a463700a64a&stat=instructions:u

It looks like there's no notable increase in max-rss
https://llvm-compile-time-tracker.com/compare.php?from=f9b12955f891bb086d12309d89656821d776e858&to=0e8df1e93422960640d0efd460212a463700a64a&stat=max-rss

PR: https://github.com/llvm/llvm-project/pull/211891
2026-07-26 09:47:01 +00:00
Florian Hahn
4c3a4f1180
[SCEV] Use DenseMap for constant lookup, bypassing FoldingSet (NFC) (#212022)
Looking up/contructing SCEVConstants is a very frequent operation, with
a notable amount of compile-time spent in SCEV.

Add a new DenseMap, mapping IR constants to SCEVConstant. Constants are
already uniqued, so the pointer based lookup is notably faster than the
folding-set lookup.

The cache is used as fast early-exit, and the SCEVConstants are still
added to the folding set for completeness.

Compile-time impact
 * stage1-O3: -0.23%
 * stage1-ReleaseThinLTO: -0.21%
 * stage1-ReleaseLTO-g: -0.19%
 * stage1-aarch64-O3: -0.20%
 * stage2-O3: -0.10%


https://llvm-compile-time-tracker.com/compare.php?from=8a6a039eb31f33749cfe251a5985b335e9a09681&to=4146ff3be6be4c9d9bb10399a83658690222252e&stat=instructions:u

PR: https://github.com/llvm/llvm-project/pull/212022
2026-07-25 17:46:45 +01:00
Vitaly Buka
b9c05ca60a
[SCEV] Fix MSan uninitialized value in createSCEV (#211996)
In #180244 (8e76c3f0d2), handling of Instruction::Sub in
createSCEV declared PtrLHS and PtrRHS as uninitialized local variables.
When only one side matched m_PtrToInt, the other variable remained
uninitialized. Passing it by value to GetOp copied uninitialized shadow
bytes, causing MemorySanitizer to report use-of-uninitialized-value.

Initialize PtrLHS and PtrRHS to nullptr upon declaration.

Assisted-by: Gemini
2026-07-25 08:23:02 +00:00
Florian Hahn
2ac96dbb3a
[SCEV] Add missing scPtrToAddr to getCastExpr. (#211899)
https://github.com/llvm/llvm-project/pull/180244 (8e76c3f0d2) missed
adding scPtrToAddr to getCastExpr, causing `Not a SCEV cast expression!`
on some of the AMDGPU bots, including
 https://lab.llvm.org/buildbot/#/builders/10/builds/32555.

Add missing case to handle PtrToAddr.
2026-07-24 20:45:40 +00:00
Florian Hahn
8e76c3f0d2
[SCEV] Use SCEVPtrToAddr instead of SCEVPtrToInt in SCEV. (#180244)
Use SCEVPtrToAddr instead of SCEVPtrToInt for pointer -> int
conversion in SCEV, like when computing trip count expressions.

getPtrToIntExpr now also creates SCEVPtrToAddrExpr.

Removal of SCEVPtrToIntExpr out of this PR, to limit the scope and
will be done as NFC follow-up.

PR: https://github.com/llvm/llvm-project/pull/180244
2026-07-24 20:20:48 +01:00
Aleksandr Popov
65bd2df84b
[SCEV] Tighten loop guards range check idiom (#210387)
Previously, the idiom matcher derived the clamp range only from the raw
`(LHS + C1) u< C2` form and rejected wrapped or full ranges.

Intersect the derived range with the known unsigned range of `LHSUnknown`.
This can reduce wrapped or full ranges to a usable interval and allows the
matcher to extract clamps in more cases.

Related to https://github.com/llvm/llvm-project/issues/208778
2026-07-20 18:19:01 +02:00
Jinsong Ji
b2d3db9bfb
[SCEV] Derive element size from the access's own pointer address space (#209824)
ScalarEvolution::getElementSize always derived the element-size SCEV
using a generic address-space-0 pointer index type. On targets whose
data layout uses different pointer index widths per address space (for
example, where some address spaces use 32-bit pointers and others
64-bit), a load/store through a narrow address space produced an access
function SCEV of one width but an element-size SCEV of another.

Delinearization then called SCEVDivision::divide with numerator and
denominator of mismatched types, tripping the assertion added in
a9d295d615 once the implicit sign-extension was removed in
23a32bcedb.

Derive the index type from the memory access's actual pointer operand
address space so the element-size SCEV matches the width of the access
function's SCEV.
2026-07-20 11:17:38 -04:00
Florian Hahn
e16e6077cb
[SCEV] Use m_scev_AffineAddRec in get{Zero,Sign}ExtendExprImpl (NFC) (#210082)
It's a small win in number of lines, and reduces the nesting level a
bit.

Suggested in https://github.com/llvm/llvm-project/pull/208805

PR: https://github.com/llvm/llvm-project/pull/210082
2026-07-20 15:21:16 +01:00
Florian Hahn
0c5b2258f0
[SCEV] Infer no-wrap flags for shl by a constant. (#208434)
Treat `shl %a, C` as `mul %a, 1 << C` in
getStrengthenedNoWrapFlagsFromBinOp
if possible.

Only transfer NSW from shl to mul, if the shift amount is < Bitwidth -
1, otherwise the result would be more poisonous.

Alive2 proofs: https://alive2.llvm.org/ce/z/iBPpkv

Compile-time impact in noise:
https://llvm-compile-time-tracker.com/compare.php?from=a037729976f91dc11b41a76834dfca9d8812c4fe&to=2050d622aed5606774f0902b352bbb2142e654e1&stat=instructions:u

PR: https://github.com/llvm/llvm-project/pull/208434
2026-07-18 12:36:42 +00:00
Aleksandr Popov
2b68eb4d70
[SCEV][NFCI] Refactor LoopGuards range check matching (#210362)
Parameterize MatchRangeCheckIdiom over (Predicate, LHS, RHS) so it can
be reused for other predicates discovered during guard collection.

Hoist AddRewrite / GetMaybeRewritten above it and use them in place of
the inline try_emplace, so range-check rewrites chain onto existing ones
the same way other rewrites do.
2026-07-17 23:59:40 +02:00
Florian Hahn
9a2d9c7fef
[SCEV] Try to fold ZExt/SExt of AddRec before existing lookup. (#208805)
Move AddRec fold for ZExt & SExt before existing SCEV lookup. This can
improve results, when we constructed SCEV for a ZExt/SExt during earlier
analysis and flags on the operand AddRec have not been
refined/strengthend yet.

This improves results in some cases and fixes a regression here:
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/654#discussion_r3554885279.

On a large C/C++ corpus with 32k bitcode files, ~2% more IVs get
widened, removing a large number of ZExt instructions.

Compile-time impact in the noise

https://llvm-compile-time-tracker.com/compare.php?from=167d65906cc3c636221158abe8289ab4a03dfc7d&to=381abca0d5ead4443d86287d754f47c21396a9be&stat=instructions:u
2026-07-17 11:46:21 +00:00
Aleksandr Popov
8a94ef9467
[SCEV] Prove umin(Ops) u< RHS by checking individual operands (#207729)
Teach IsKnownPredicateViaMinOrMax to handle ICMP_ULT/UGT for
SCEVUMinExpr. Since umin(Ops) u<= each Op by definition, proving Op u<
RHS for any single operand is sufficient to establish umin(Ops) u< RHS
by transitivity.

This unblocks loop vectorization for early-exit loops whose trip count
is a umin of a buffer length and an iteration bound.

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

Alive2 proof: https://alive2.llvm.org/ce/z/9DjA2f
2026-07-08 16:54:41 +02:00
Aleksandr Popov
fc5798ef92
[SCEV] Cancel common addend/multiplier in SimplifyICmpOperands (#205014)
Simplify:
```
  (K + A) pred (K + B)  ->  A pred B
  (C * A) pred (C * B)  ->  A pred B
```

when no-wrap flags allow it: NSW for signed predicates, NUW for
unsigned. Also requires C > 0 for signed in the multiplication case.

For equality comparisons, `(K + A) eq/ne (K + B)` simplifies to `A eq/ne
B` without requiring any no-wrap flags.

Alive2 proofs: https://alive2.llvm.org/ce/z/KmyqsD
2026-07-01 17:10:16 +02:00
Timur Golubovich
9e0aa61f75
[SCEV] Prove implied conditions via matching SCEV differences (#201839)
Add isImpliedCondOperandsViaMatchingDiff to fold equality comparisons
when getMinusSCEV(LHS, RHS) == getMinusSCEV(FoundLHS, FoundRHS).
This handles correlated IV comparisons in loops with multiple pointer
IVs sharing the same stride.
2026-07-01 09:26:36 +02:00
Nikita Popov
34ed491f63
[SCEV] Infer addrec nowrap flags during range analysis (#202964)
When we're computing the range of the addrec, we already have to reason
about whether it wraps, so we may as well determine the nowrap flags at
the same time.

This is more precise than the previous logic that took the addrec range
and checked whether adding a step to it does not wrap. For example, an
`{0,+,1}` addrec with a full range can still be non-wrapping.

Note that I removed some assertions in the SCEV printed that predicated
exit counts actually have predicates. Due to SCEV's query order
dependence, this can happen, also prior to this change, see for example
https://llvm.godbolt.org/z/cWK1MMEqv. While this indicates suboptimal
results, it's not a bug, and we should not assert.

Fixes https://github.com/llvm/llvm-project/issues/200788.
2026-06-24 10:42:58 +00:00
Florian Hahn
871990a01e
[LAA] Collect no-wrap predicates separately in getPtrStride/isNoWrap. (#203787)
Add an overload of getPtrStride and update isNoWrap to collect no-wrap
SCEV predicates in a vector, and have the caller add them to PSE if
needed.

This also requires to explicitly build the wrap predicate via
ScalarEvolution::getWrapPredicate (clearing statically implied flags)
rather than going through PredicatedScalarEvolution::setNoOverflow,
which can now be removed together with the flags map.

This also requires generalizing SCEVUnionPredicate::implies so a wrap
predicate can be recognized as implied by an existing wrap predicate
after applying equal predicates, avoiding redundant predicates when the
collected predicates are committed.

The only functional changes is re-ordering of runtime check groups in a
single test case; no functional IR changes across a large IR corpus (32k
modules)

To be used to avoid adding unnecessary wrap predicates during interleave
group analysis: https://github.com/llvm/llvm-project/pull/200807

PR: https://github.com/llvm/llvm-project/pull/203787
2026-06-22 22:07:49 +02:00
Nikita Popov
168666950e
[IR] Make CanBeFreed calculation optional (NFC) (#203490)
Make the CanBeFreed argument of getPointerDereferenceableBytes() a
pointer, so that nullptr can be passed if we're not interested in
whether frees are possible or not.

Nearly all places don't actually care about frees, including BasicAA,
which is the hottest caller of this API. This improves compile-time when
deref-at-point semantics are enabled.

I've kept the argument required so that callers still have to make an
explicit choice to ignore frees. (I'd be open to making it optional
though, given that only a single caller actually cares...)
2026-06-12 17:36:47 +02:00
carlobertolli
9ce63d09cf
[AMDGPU][SCEV] Tighten max backedge-taken count for shift recurrence loops. (#197292)
Application code on AMDGPUs often uses the following pattern:

for (int i = blockDim.x / 2; i >= 1; i >>= 1)
  if (threadIdx.x < i) {
    <STMT based on threadIdx.x>
  }
  __syncthreads();
}

but this is currently not unrolled by LLVM for two reasons:
1. We overestimate the loop count with the number of bits in the
iteration variable (32).
2. Runtime unrolling is not applicable because of convergent
instructions.

For the specific pattern above, we can compute a tighter bound by using
range information, which for blockDim.x is (0,1025) and already emitted
by clang, resulting in 10 as upper bound as opposed to 32.
The next step in unrolling the loop is to adjust the threshold used to
control full loop unrolling with convergent instructions.

Assisted-by: Cursor
2026-06-11 14:19:36 -05:00
Daemon
024f39cbef
[SCEV] Avoid redundant stack push/pop in createSCEVIter (#199352)
This patch simplifies the iterative worklist handling in createSCEVIter.

In the previous implementation, a `Value` that could not be materialized
immediately would typically be pushed onto the stack twice and popped
twice: first in the initial unvisited state, and then again after being
re-queued in the visited state once its operands had to be processed
first.

This change avoids that redundant re-queue step by updating the existing
stack entry in place before pushing unresolved operands. Use
`setInt(true)` to update the existing `Stack` entry in place instead of
pushing a separate `(V, true)` entry. This saves one
`emplace_back`/`pop_back` pair for each `Value`, and reduces memory
consumption of the `Stack` worklist.
2026-06-11 20:32:30 +02:00
Mingjie Xu
0411e39a35
[SCEV] Speed up forgetLoop by avoiding def-use walk for loop-header PHIs (#201572)
Every cached SCEV varies with Loop `L` transitively contains an
`AddRec`, and every `AddRec` for the loop is recorded in `LoopUsers[L]`.
`forgetMemoizedResults` already closes this set transitively through
`SCEVUsers` and `ExprValueMap`.
Therefore `forgetLoop` does not need to walk the def-use chain starting
from header PHIs, it only needs to initialize `ToForget` with
`LoopUsers[L]` and explicitly remove each header PHI's entries from
`ValueExprMap` and `ConstantEvolutionLoopExitValue`, push its cached
SCEVs into `ToForget`.
As a side effect, cached SCEVs that reside in the loop body but do not
depend on any `AddRec` for the loop (e.g. a `SCEVUnknown` for an icmp)
are no longer invalidated.
2026-06-10 09:31:30 +08:00
Kevin McAfee
cc377f71c3
[SCEV] Batch common-factor folding in getAddExpr (#184258)
The existing pairwise common-factor fold in getAddExpr handles two
patterns:
  `W + X + (X * Y * Z)  -->  W + (X * ((Y*Z)+1))`
  `X + (A*B*C) + (A*D*E) --> X + (A*(B*C+D*E))`

Both fold exactly two terms sharing a common factor, then re-enter
getAddExpr() with the partially-simplified Ops. When n terms share a
common factor X, this requires n-1 re-entries through the full
getAddExpr normalization pipeline.

Replace this with a single-pass scan that collects all terms sharing the
common factor and folds them in one shot:
  `A1*X + A2*X + ... + An*X  -->  X * (A1 + A2 + ... + An)`

This reduces the number of top-level re-entries into getAddExpr() for
this fold from n-1 to 1, improving compile time for expressions with
many terms sharing a common factor.

Note that in some cases this change causes benign operand order
changes.
2026-06-04 20:42:55 +00:00
Thurston Dang
7d27cf7c2b
Revert "[SCEV] Fix ScalarEvolution::getBackedgeTakenInfo when L not found" (#201640)
Reverts llvm/llvm-project#201502 due to buildbot breakage:
https://lab.llvm.org/buildbot/#/builders/187/builds/20579
2026-06-04 10:24:41 -07:00
Thurston Dang
b7e08b6467
[SCEV] Fix ScalarEvolution::getBackedgeTakenInfo when L not found (#201502)
By the end of ScalarEvolution::getBackEdgeTakenInfo():
```
  ...
  BackedgeTakenInfo Result = computeBackedgeTakenCount(L);

  if (Result.hasAnyInfo()) {
    // Invalidate any expression using an addrec in this loop.
    ...
  }

  return BackedgeTakenCounts.find(L)->second = std::move(Result);
```
BackedgeTakenCounts may no longer contain an entry for L, resulting in a
crash (https://github.com/llvm/llvm-project/issues/195176). This patch
fixes the issue by inserting the entry if it does not exist (and
otherwise keeping the same behavior).

This adds a regression test (crash on opt 19.1.0 onwards e.g.,
https://godbolt.org/z/Wq3n3rEqT), metarenamed from
https://github.com/dtcxzyw/llvm-autoreduce/issues/106, which in turn was
derived from https://github.com/llvm/llvm-project/issues/195176.
2026-06-04 09:33:10 -07:00
Florian Hahn
dbab3f7177
[VPlan] Move IV predicate handling to VPlan. (#192876) 2026-06-02 04:40:12 +03:00
Oliver Stannard
da4e5cc928
[SCEV] Canonicalise round-up idiom when some bits known (#197126)
Since #174380, instcombine can clear some set bits in the added constant
in expressions like this, when A has some known-clear low order bits.
  (A + 15) & ~15

This transformation is valid, but can make it harder for later passes to
recognise this idiom for rounding up to a power of 2. This is causing
the ARM MVE tail predication pass to fail on loops with a trip count
which is a multiple of a small power of 2.

The fix is to reverse the transformation when building SCEV expressions,
canonicalising to always use the largest valid value for the added
constant.

Alive proofs:
https://alive2.llvm.org/ce/z/hhndoW
https://alive2.llvm.org/ce/z/_JYVat
2026-05-28 14:29:09 +01:00
Fangrui Song
6302439f5a
[llvm,clang] Don't assume non-erased DenseMap entries remain valid after erase. NFC (#198982)
In preparation for switching DenseMap from tombstone deletion to
backward-shift deletion, update call sites that reuse an iterator or a
bucket reference after erasing another entry from the same map.

These work under tombstone deletion because unrelated buckets stay put,
but backward-shift deletion relocates entries to close the gap.

Add DenseMap::remove_if, similar to SmallPtrSet::remove_if, as
replacement for erase-while-iterating, and use it where applicable.

Aided by Claude Opus 4.7
2026-05-24 10:25:38 -07:00
Florian Hahn
d755b04e38
[SCEV] Fold zext(C+A)<nsw> -> (sext(C) + zext(A))<nsw> if possible. (#142599)
Simplify zext(C+A)<nsw> -> (sext(C) + zext(A))<nsw> if
 * zext (C + A)<nsw> >=s 0 and
 * A >=s V.

For now this is limited to cases where the first operand is a constant,
so the SExt can be folded to a new constant. This can be relaxed in the
future.

The initial version checks for non-negative manually to limit compile-time,
supporting only A = smax(C2, ..) where C2 >= abs(C)

Alive2 proof of the general pattern and the test changes in zext-nuw.ll
(times out in the online instance but verifies locally)

https://alive2.llvm.org/ce/z/_BtyGy

PR: github.com/llvm/llvm-project/pull/142599
2026-05-22 21:33:46 +01:00
Ming Yan
cc169110c5
Reapply "[SCEV] Introduce loop-uniform SCEV classification." (#196357)
This reverts commit 45d94f67b8.

This recommit contains a small fix: when `loop-computable` are mixed
with `loop-uniform`, it returns `loop-variant (unknown)`.

Original message:
This patch extends `ScalarEvolution::LoopDisposition` with a new
`LoopUniform` state to describe SCEVs that are invariant across all
iterations of a given loop, but may still depend on inner-loop induction
variables.

Unlike `LoopInvariant`, which requires the value to be fully invariant
with respect to the loop, LoopUniform captures expressions that do not
depend on the loop’s own induction variables, yet may vary in nested
loops. This distinction is useful for analyses and optimizations that
reason about per-iteration stability at a specific loop level.

Example:
```
for (i)
  for (j)
    dep(j);       // uniform w.r.t. i
    dep(i, j);    // not uniform w.r.t. i
```

This enables us to more precisely reason about the behavior of SCEV in
the context of nested loops, which is very useful for optimizations such
as `LoopUnrollAndJam` and `OuterLoopVectorization`.

PR: https://github.com/llvm/llvm-project/pull/194304
2026-05-18 18:08:32 +08:00
Florian Hahn
ffffe9c169
[SCEV] Remove ControlsOnlyExit only used for unsimplified IR. (#195052)
ControlsOnlyExit is only set to true for And/Or with a neutral element,
i.e. unsimplified IR. Remove the complexity, relying on IR
simplifications instead.

Follow-up to https://github.com/llvm/llvm-project/pull/194831.

It appears as if we do not hit the un-optimized IR in practice
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/236

PR: https://github.com/llvm/llvm-project/pull/195052
2026-05-14 17:02:37 +00:00
Victor Mustya
f47a2749d4
[SCEV] Propagate nuw/nsw flags from or disjoint (#197236)
The Scalar Evolution analysis converts the `or disjoint` instruction
into a synthetic add with the `IsNSW` and `IsNUW` flags set, but the
real instruction reference set to `nullptr`. The flags propagation logic
only reads the real instruction flags, when the instruction reference is
present. This behavior silently ignores the flags for the synthetic add,
which can lead to missed optimization opportunities.

This patch inserts the pointer to the actual instruction into the
`BinaryOp` object created for the synthetic add. It also adjust the
flags handling logic to threat the `disjoint` flag as both `nuw` and
`nsw` as if they were set on the `add` instruction.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 09:47:51 -07:00
Fangrui Song
0a181a1c0a
Use auto for DenseMap/SmallDenseMap iterator variables. NFC (#196883)
To match the prevailing style.
2026-05-11 07:20:21 +00:00
Martin Storsjö
45d94f67b8
Revert "[SCEV] Introduce loop-uniform SCEV classification." (#196297)
Reverts llvm/llvm-project#194304, as it caused failed asserts - see that
PR for reproducers.
2026-05-07 12:51:49 +00:00
Nikita Popov
f4e42fb59b
[SCEV] Merge udiv exact logic into general udiv logic (#195840)
The udiv exact handling for constant RHS is already partially handling
in the generic udiv code:

8a0c5d3f43/llvm/lib/Analysis/ScalarEvolution.cpp (L3641-L3657)

Move two remaining folds there as well:
 * `(%a * %b)<nuw> / %b` to `%a`
 * `(A*GCD * %b)<nuw> / (C*GCD)` to `(A * %b)<nuw> / C`

Removing common factors from a multiply does not require exact if the
multiply is nuw (and conversely, being exact is not sufficient without
nuw).

This makes getUDivExactExpr() equivalent to getUDivExpr(). I've retained
the method for now in case we want to add exact specific logic in the
future.

Proof: https://alive2.llvm.org/ce/z/iQeb6v
2026-05-07 09:43:58 +02:00
Nikolas Klauser
3d6a7bf32d
[InstCombine] Drop alignment assumptions more aggressively (#196060)
`computeKnownBits` gets a context instruction now, which allows dropping
assumes based on previous assumes.
2026-05-07 09:03:59 +02:00
Ming Yan
a257e2aa4e
[SCEV] Introduce loop-uniform SCEV classification. (#194304)
This patch extends `ScalarEvolution::LoopDisposition` with a new
`LoopUniform` state to describe SCEVs that are invariant across all
iterations of a given loop, but may still depend on inner-loop induction
variables.

Unlike `LoopInvariant`, which requires the value to be fully invariant
with respect to the loop, LoopUniform captures expressions that do not
depend on the loop’s own induction variables, yet may vary in nested
loops. This distinction is useful for analyses and optimizations that
reason about per-iteration stability at a specific loop level.

Example:
```
for (i)
  for (j)
    dep(j);       // uniform w.r.t. i
    dep(i, j);    // not uniform w.r.t. i
```

This enables us to more precisely reason about the behavior of SCEV in
the context of nested loops, which is very useful for optimizations such
as `LoopUnrollAndJam` and `OuterLoopVectorization`.
2026-05-06 17:00:48 +08:00
Florian Hahn
b689f8b7c6
[SCEV] Limit ControlsOnlyExit logic to BinOps with neutral elements. (#194831)
As far as I can tell, ControlsOnlyExit is used during reasoning to
assume
that we stay in the loop as long as the condition is true/false, and are
guaranteed to exit otherwise.

But unless I am missing something, a sub-condition of an AND/OR never
solely controls the exit, whether we exit always depends on both
conditions.

Pass false to ControlsOnlyExit, as otherwise we would incorrectly assume
that we must exit if either conditions is true, when we would only exit
if both are true.

For now, ControlsOnlyExit is only used for the neutral element case, it
may be worth removing this.

Alive2 proof of IndVars mis-compile: https://alive2.llvm.org/ce/z/kWs4hE

PR: https://github.com/llvm/llvm-project/pull/194831
2026-04-30 09:21:15 +00:00
Florian Hahn
9dd1eb49f7
[SCEV] Bail out on wider AddRecs in SCEVWrapPrediacte::implies. (#191498)
NSSW/NUSW on a wider AddRec does not imply NSSW/NUSW on a narrower
AddRec.

Fixes https://github.com/llvm/llvm-project/issues/191382.
2026-04-11 14:15:09 +00:00
Florian Hahn
ff4c6fe24e
[SCEV] Move NoWrapFlags definition outside SCEV scope, use for SCEVUse. (#190199)
The patch moves out of SCEV's scope so they can be re-used for SCEVUse.
SCEVUse gets an additional getNoWrapFlags helper that returns the union
of the expressions SCEV flags and the use-specific flags.

SCEVExpander has been updated to use this new helper.

In order to avoid other changes, the original names are exposed via
constexpr in SCEV. Not sure if there's a nicer way. One alternative
would be to define the enum in struct, and have SCEV inherit from it.

The patch also clarifies that the SCEVUse flags encode NUW/NSW, and
hides getInt, setInt, etc to avoid potential mis-use.

PR: https://github.com/llvm/llvm-project/pull/190199
2026-04-04 15:03:36 +00:00
Florian Hahn
7edf8a7b51
[SCEV] Replace some hasFlags calls with hasNo(Un)SignedWrap (NFC). (#190352)
This is slightly more compact and reduces diff when switching to enum
class (https://github.com/llvm/llvm-project/pull/190199).

PR: https://github.com/llvm/llvm-project/pull/190352
2026-04-03 16:09:40 +00:00
Florian Hahn
97dbf38c9c
[SCEVExpander] Add SCEVUseVisitor and use it in SCEVExpander (NFC) (#188863)
Add SCEVUseVisitor, a new visitor class where all visit methods receive
a SCEVUse instead of a const SCEV*. Use it for SCEVExpander, so it can
use use-specific flags in the future.

PR: https://github.com/llvm/llvm-project/pull/188863
2026-04-02 15:08:01 +00:00
Florian Hahn
3b1125b1ed
[SCEV] Add canonical SCEV pointer and construct canonical SCEVs (NFC) (#188858)
Add a canonical SCEV pointer to SCEV, to support comparing SCEVs for
equality, even with different use-specific flags.

Currently this should be NFC, as nothing yet sets use flags.

Compile-time impact:
https://llvm-compile-time-tracker.com/compare.php?from=13f1fd006243f756417c3ae992342c0674e3f04e&to=e7f46bcf8bef62c619380fbcccbe6073300b69fe&stat=instructions:u

+0.03% - +0.05% on stage1 configs
-0.03% surprisingly for stage2-O3

PR: https://github.com/llvm/llvm-project/pull/188858
2026-04-01 11:43:40 +00:00
Florian Hahn
dfafee7a47
[SCEV] Convert more interfaces to use SCEVUse (NFC). (#185045)
Convert more interfaces to SCEVUse, following up to
https://github.com/llvm/llvm-project/pull/91961.

PR: https://github.com/llvm/llvm-project/pull/185045
2026-03-19 17:02:48 +00:00
Alexis Engelke
43ec60eee5
Reland "[DomTree] Assert non-null block for pre-dom tree" (#187005)
Reland #186790 with fix for SCEV. A loop can have more than one latch,
in which case getLoopLatch returns null.
2026-03-17 14:10:04 +00:00
Alexis Engelke
e8a4050263
[IR] Drop BasicBlockEdge::isSingleEdge (#186767)
This was only called on CondBr instructions, where it is always faster
to access the successors directly than to use successors().

Multi-edges don't dominate anything, so this rare case is often already
handled by dominates().

There is also a very small (hardly measurable) performance
improvement here (it did show up in profiles at 0.03% or so).
2026-03-16 13:28:48 +01:00
Eli Friedman
7bc3bb0196
[ScalarEvolution] Limit recursion in getRangeRef for PHI nodes. (#152823)
Restrict PHI nodes that getRangeRef is allowed to recursively examine so
we don't need a "visited" set. And fix createSCEVIter so it creates all
the relevant SCEV nodes before getRangeRef tries to examine them.

The tests that are affected have induction variables that aren't
AddRecs. (Other cases are theoretically affected, but don't seem to show
up in our tests.)
2026-03-13 16:27:39 -07:00
Florian Hahn
f8734a5e10
[SCEV] Introduce SCEVUse, use it instead of const SCEV * (NFCI). (#91961)
This patch introduces SCEVUse, which is a tagged pointer containing the
used const SCEV *, plus extra bits to store NUW/NSW flags that are only
valid at the specific use.

This was suggested by @nikic as an alternative
to https://github.com/llvm/llvm-project/pull/90742.

This patch just updates most SCEV infrastructure to operate on SCEVUse
instead of const SCEV *. It does not introduce any code that makes use
of the use-specific flags yet which I'll share as follow-ups.

Compile-time impact: https://llvm-compile-time-tracker.com/compare.php?from=ee34eb6edccdebc2a752ffecdde5faae6b0d5593&to=5a7727d7819414d2acbc5b6ab740f0fc2363e842&stat=instructions%3Au
2026-03-13 16:23:06 +00:00
Alexis Engelke
94da4039cb
[Analysis][NFC] Drop use of BranchInst (#186374)
Largely straight-forward replacement.
2026-03-13 13:42:19 +00:00
Luke Lau
e7bc02d9a4
[SCEV] Always return true for isKnownToBeAPowerOfTwo for SCEVVScale (#183693)
After #183080 vscale is always a power of two, so we don't need to check
for the vscale_range attribute.
2026-02-27 10:41:54 +00:00
Nikita Popov
b205396086
[IR] Add ConstantExpr::getPtrAdd() (#181365)
Add a ConstantExpr::getPtrAdd() API that creates a getelementptr i8
constant expression, similar to IRBuilder::CreatePtrAdd(). In the future
this will create a ptradd expression.
2026-02-16 11:10:15 +01:00