2186 Commits

Author SHA1 Message Date
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
Shilei Tian
70905e0afa
[RFC][IR] Remove Constant::isZeroValue (#181521)
`Constant::isZeroValue` currently behaves same as
`Constant::isNullValue` for all types except floating-point, where it
additionally returns true for negative zero (`-0.0`). However, in
practice, almost all callers operate on integer/pointer types where the
two are equivalent, and the few FP-relevant callers have no meaningful
dependence on the `-0.0` behavior.

This PR removes `isZeroValue` to eliminate the confusing API. All
callers are changed to `isNullValue` with no test failures.

`isZeroValue` will be reintroduced in a future change with clearer
semantics: when null pointers may have non-zero bit patterns,
`isZeroValue` will check for bitwise-all-zeros, while `isNullValue` will
check for the semantic null (which
may be non-zero).
2026-02-15 12:06:42 -05:00
Nikita Popov
fe413f70fe
[SCEV] Discard samesign when analyzing loop invariant exits (#181171)
If the predicate has samesign set, we could either perform the checks
with the unsigned predicate and return and unsigned invariant predicate,
or we could perform them with the signed predicate and return a signed
invariant predicate. The current implementation can end up mixing both,
using a signed predicate for one check and an unsigned one for the
other.

Avoid this by dropping the samesign flag.

Fixes https://github.com/llvm/llvm-project/issues/180870.
2026-02-13 12:23:31 +01:00
Florian Hahn
f8d5a003fa
[SCEV] Don't create SCEVPtrToAddr for unstable pointer representations. (#180718)
Conservatively treat unstable pointers as SCEVCouldNotCompute in
getPtrToAddrExpr, and return SCEVUnknown when constructing from IR.

This surfaced as part of the discussion in
https://github.com/llvm/llvm-project/pull/178861.

PR: https://github.com/llvm/llvm-project/pull/180718
2026-02-10 13:46:42 +00:00
Florian Hahn
7fd2056efa
[SCEV] Sink SCEVPtrToAddr to leaf SCEVUnknowns. (#174437)
Use CastSinkingRewriter for SCEVPtrToAddr expressions as well, sinking
them the same as SCEVPtrToInt expressions.

Depends on https://github.com/llvm/llvm-project/pull/174435 
and https://github.com/llvm/llvm-project/pull/158032.

PR: https://github.com/llvm/llvm-project/pull/174437
2026-01-26 19:01:38 +00:00
Florian Hahn
3fb914d851
[SCEV] Add initial support for ptrtoaddr. (#158032)
Add initial support for PtrToAddr to SCEV, including a new
SCEVPtrToAddrExpr and SCEV expansion support for it.

PR: https://github.com/llvm/llvm-project/pull/158032
2026-01-16 11:58:04 +00:00
Rahul Joshi
7d96b39c4f
[NFC][LLVM] Adopt ListSeparator/interleaved in more places (#172909)
Adopt `ListSeparator` and `interleaved` in various places instead of
manual code to print separators between loop iterations.
2026-01-12 12:18:01 -08:00
Florian Hahn
128731fbd3
[SCEV] Handle all PtrtoIntExpr construction in CastSinkingRewriter (NFC) (#174435)
Move SCEVPtrToIntSinkingRewriter out of getLosslessPtrToIntExpr to be
re-used for PtrToAddr. Also streamline code in getLosslessPtrToIntExpr
by moving zero handling to the rewriter and removing special handling
for SCEVUnknown in getLosslessPtrToIntExpr. Instead, always use the
rewriter, which will automatically handle the case where the expression
is a SCEVUnknown.

This makes it slightly easier to add support for PtrToAddr as follow-up
to https://github.com/llvm/llvm-project/pull/158032

PR: https://github.com/llvm/llvm-project/pull/174435
2026-01-12 15:11:31 +00:00
Florian Hahn
1dea577186
[SCEV] Handle URem pattern in getRangeRef. (#174456)
Check if an scAddExpr expressions represents an URem, and
if it does, use the divisor to limit the conservative range.

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

PR: https://github.com/llvm/llvm-project/pull/174456
2026-01-07 11:32:43 +00:00
Nikita Popov
8fd85ba9e6 [LLVM] Temporarily allow implicit truncation in some places
Split out from https://github.com/llvm/llvm-project/pull/171456.

This explicitly allows implicit truncation in a number of places,
prior to switching the default. This limits the scope of the
initial change.
2026-01-05 09:52:57 +01:00
Victor Chernyakin
c438773432
[LLVM][ADT] Migrate users of make_scope_exit to CTAD (#174030)
This is a followup to #173131, which introduced the CTAD functionality.
2026-01-02 20:42:56 -08:00
Florian Hahn
c43ccefc9f
[VPlan] Use PSE to construct SCEVs in getSCEVExprForVPValue (NFCI).
getSCEVExprForVPValue is used to create SCEVs for expressions from the
original loop, which may be predicated. Use PSE to construct predicated
SCEVs if possible. This matches the legacy LV code behavior.

Currently should be NFC, but will enable migrating more SCEV/cost-based
computations to VPlan.

The patch requires exposing a new getPredicatedSCEV helper to
PredicatedScalarEvolution which just takes a SCEV, to avoid needing to
go through IR values, which isn't an option for getSCEVExprForVPValue.
2025-12-21 22:39:49 +00:00
Florian Hahn
113f058d73
[SCEV] Add m_scev_UndefOrPoison (NFC). (#170740)
Add matcher for SCEVUnknown wrapping undef or poison.

PR: https://github.com/llvm/llvm-project/pull/170740
2025-12-05 11:20:46 +00:00
Florian Hahn
1054a6e9de
[SCEV] Handle non-constant start values in AddRec UDiv canonicalization. (#170474)
Follow-up to https://github.com/llvm/llvm-project/pull/169576 to enable
UDiv canonicalization if the start of the AddRec is not constant.

The fold is not restricted to constant start values, as long as we are
able to compute a constant remainder. The fold is only applied if the
subtraction of the remainder can be folded into to start expression, but
that is just to avoid creating more complex AddRecs.

For reference, the proof from #169576 is
https://alive2.llvm.org/ce/z/iu2tav

PR: https://github.com/llvm/llvm-project/pull/170474
2025-12-03 21:13:11 +00:00
Philip Reames
267865a7b5
[SCEV] Factor out utility for proving same sign of two SCEVs [nfc] (#170376)
This is a slightly different API than ConstantRange's
areInsensitiveToSignednessOfICmpPredicate. The only actual difference
(beyond naming) is the handling of empty ranges (i.e. unreachable code).
I wanted to keep the existing SCEV behavior for the unreachable code as
we should be folding that to poison, not reasoning about samesign. I
tried the other variant locally, and saw no test changes.
2025-12-03 07:31:29 -08:00
Rahul Joshi
ef49c92271
[NFC][LLVM] Namespace cleanup in ScalarEvolution (#166620) 2025-12-02 10:03:31 -08:00
Florian Hahn
5d876093b7
[SCEV] Allow udiv canonicalization of potentially-wrapping AddRecs (#169576)
Extend the {X,+,N}/C => {(X - X%N),+,N}/C canonicalization to handle
AddRecs that may wrap, when X < N <= C and both N,C are powers of 2. The
alignment and power-of-2 properties ensure division results remain
equivalent for all offsets [(X - X%N), X).

Alive2 Proof: https://alive2.llvm.org/ce/z/iu2tav

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

PR: https://github.com/llvm/llvm-project/pull/169576
2025-12-02 14:09:53 +00:00
Florian Hahn
d3fe1df194
[SCEV] Improve handling of divisibility information from loop guards. (#163021)
At the moment, the effectivness of guards that contain divisibility
information (A % B == 0 ) depends on the order of the conditions.

This patch makes using divisibility information independent of the
order, by collecting and applying the divisibility information
separately.

We first collect all conditions in a vector, then collect the
divisibility information from all guards.

When processing other guards, we apply divisibility info collected
earlier.

After all guards have been processed, we add the divisibility info,
rewriting the existing rewrite. This ensures we apply the divisibility
info to the largest rewrite expression.

This helps to improve results in a few cases, one in
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2921 and another one
in a different large C/C++ based IR corpus.

PR: https://github.com/llvm/llvm-project/pull/163021
2025-11-02 14:16:24 +00:00
Kazu Hirata
31b8ba5670
[Analysis, CodeGen] Use ArrayRef instead of const ArrayRef (NFC) (#166026)
This patch improves readability by using "ArrayRef<T>" instead of
"const ArrayRef<T>" and "const ArrayRef<T> &" in function parameter
types.
2025-11-01 23:20:19 -07:00
Florian Hahn
817b7c5e56 [SCEV] Fix switch formatting in collectFromBlock (NFC).
Fix formatting for switch, to avoid unrelated changes/formatting errors
in https://github.com/llvm/llvm-project/pull/163021.
2025-10-31 11:34:43 -07:00
Florian Hahn
a321ce3d72
[SCEV] Expose getGEPExpr without needing to pass GEPOperator* (NFC) (#164487)
Add a new getGEPExpr variant which is independent of GEPOperator*.

To be used to construct SCEVs for VPlan recipes in
https://github.com/llvm/llvm-project/pull/161276.

PR: https://github.com/llvm/llvm-project/pull/164487
2025-10-22 16:01:57 +01:00
Florian Hahn
385ea0dbc1
[SCEV] Move and clarify names of prev/next divisor helpers (NFC).
Move getPreviousSCEVDivisibleByDivisor from a lambda to a static
function and clarify the name (DividesBy -> DivisibleBy).

Split off refactoring from https://github.com/llvm/llvm-project/pull/163021.
2025-10-20 15:04:56 +01:00
Florian Hahn
eb17a8d599
[SCEV] Preserve divisor info when adding guard info for ICMP_NE via Sub. (#163250)
Follow-up to https://github.com/llvm/llvm-project/pull/160500 to
preserve divisibiltiy info when creating the UMax.

PR: https://github.com/llvm/llvm-project/pull/163250
2025-10-20 10:20:41 +01:00
Florian Hahn
a5d3522c13
[SCEV] Rewrite A - B = UMin(1, A - B) lazily for A != B loop guards. (#163787)
Follow-up to 2d027260b0f8
(https://github.com/llvm/llvm-project/pull/160500)

Creating the SCEV subtraction eagerly is very expensive. To soften the
blow, just collect a map with inequalities and check if we can apply the
subtract rewrite when rewriting SCEVAddExpr.

Restores most of the regression:

http://llvm-compile-time-tracker.com/compare.php?from=0792478e4e133be96650444f3264e89d002fc058&to=7fca35db60fe6f423ea6051b45226046c067c252&stat=instructions:u
stage1-O3: -0.10%
stage1-ReleaseThinLTO: -0.09%
stage1-ReleaseLTO-g: -0.10%
stage1-O0-g: +0.02%
stage1-aarch64-O3: -0.09%
stage1-aarch64-O0-g: +0.00%
stage2-O3: -0.17%
stage2-O0-g: -0.05%
stage2-clang: -0.07%

There is still some negative impact compared to before 2d027260b0f8, but
there's probably not much we could do reduce this even more.

Compile-time improvement with 2d027260b0f8 reverted on top of the
current PR:
http://llvm-compile-time-tracker.com/compare.php?from=7fca35db60fe6f423ea6051b45226046c067c252&to=98dd152bdfc76b30d00190d3850d89406ca3c21f&stat=instructions:u

stage1-O3: 60628M (-0.03%)
stage1-ReleaseThinLTO: 76388M (-0.04%)
stage1-ReleaseLTO-g: 89228M (-0.02%)
stage1-O0-g: 18523M (-0.03%)
stage1-aarch64-O3: 67623M (-0.03%)
stage1-aarch64-O0-g: 22595M (+0.01%)
stage2-O3: 52336M (+0.01%)
stage2-O0-g: 16174M (+0.00%)
stage2-clang: 34890032M (-0.03%)

PR: https://github.com/llvm/llvm-project/pull/163787
2025-10-18 13:32:40 +01:00
Ramkumar Ramachandra
98a6b6e78a
[SCEV] Improve code using SCEVPatternMatch (NFC) (#163946) 2025-10-17 14:49:52 +01:00
Florian Hahn
7c54c8245a
[SCEV] Use m_scev_Mul in a few more places. (NFC) (#163364)
Add a new variant of m_scev_Mul that binds a SCEVMulExpr and use it in
SCEVURem_match and also update 2 more places in ScalarEvolution.cpp that
can use m_scev_Mul as well.

PR: https://github.com/llvm/llvm-project/pull/163364
2025-10-16 17:50:01 +00:00
Florian Hahn
3b46556cb7
[SCEV] Use context instruction for SCEVUnknowns in getConstantMultiple. (#163260)
Follow-up to https://github.com/llvm/llvm-project/pull/160941.

Even if we don't have a context instruction for the caller, we should be
able to provide context instructions for SCEVUnknowns. Unless I am
missing something, SCEVUnknown only become available at the point their
underlying IR instruction has been defined. If it is an argument, it
should be safe to use the first instruction in the entry block or the
instruction itself if it wraps an instruction.

This allows getConstantMultiple to make better use of alignment
assumptions.

PR: https://github.com/llvm/llvm-project/pull/163260
2025-10-14 19:18:39 +00:00
Florian Hahn
2d027260b0
[SCEV] Collect guard info for ICMP NE w/o constants. (#160500)
When collecting information from loop guards, use UMax(1, %b - %a) for
ICMP NE %a, %b, if neither are constant.

This improves results in some cases, and will be even more useful
together with
 * https://github.com/llvm/llvm-project/pull/160012
 * https://github.com/llvm/llvm-project/pull/159942

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

PR: https://github.com/llvm/llvm-project/pull/160500
2025-10-14 14:20:34 +00:00
Florian Hahn
7f04ee19d2
[SCEV] Move URem matching to ScalarEvolutionPatternMatch.h (#163170)
Move URem matching to ScalarEvolutionPatternMatch.h so it can 
be re-used together with other matchers.

Depends on https://github.com/llvm/llvm-project/pull/163169

PR: https://github.com/llvm/llvm-project/pull/163170
2025-10-13 19:28:53 +00:00
Florian Hahn
bc4e14b6da
[SCEV] Add m_scev_Trunc pattern matcher. (#163169)
This patch adds a new m_scev_Trunc pattern matcher for SCEVTruncateExpr
and uses it in a few places to slightly simplify the code.

PR: https://github.com/llvm/llvm-project/pull/163169
2025-10-13 17:12:31 +00:00
Florian Hahn
0d1f2f439d
[SCEV] Use APInt for DividesBy when collecting loop guard info (NFC). (#163017)
Follow-up as suggested in
https://github.com/llvm/llvm-project/pull/162617.

Just use an APInt for DividesBy, as the existing code already operates
on APInt and thus handles the case of DividesBy being 1.

PR: https://github.com/llvm/llvm-project/pull/163017
2025-10-12 18:47:03 +00:00
Florian Hahn
6d905e41bc
[SCEV] Use getConstantMultiple in to get divisibility info from guards. (#162617)
Simplify and generalize the code to get a common constant multiple for
expressions when collecting guards, replacing the manual implementation.

Split off from https://github.com/llvm/llvm-project/pull/160012.

PR: https://github.com/llvm/llvm-project/pull/162617
2025-10-09 10:51:36 +01:00
Florian Hahn
c7fbe38893
[SCEV] Pass loop pred branch as context instruction to getMinTrailingZ. (#160941)
When computing the backedge taken count, we know that the expression
must be valid just before we enter the loop. Using the terminator of the
loop predecessor as context instruction for getConstantMultiple,
getMinTrailingZeros allows using information from things like alignment
assumptions.

When a context instruction is used, the result is not cached, as it is
only valid at the specific context instruction.

Compile-time looks neutral:
http://llvm-compile-time-tracker.com/compare.php?from=9be276ec75c087595ebb62fe11b35c1a90371a49&to=745980f5e1c8094ea1293cd145d0ef1390f03029&stat=instructions:u

No impact on llvm-opt-benchmark
(https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2867), but leads to
additonal unrolling in ~90 files across a C/C++ based corpus including
LLVM on AArch64 using libc++ (which emits alignment assumptions for
things like std::vector::begin).

PR: https://github.com/llvm/llvm-project/pull/160941
2025-10-08 13:04:30 +01:00
Paul Walker
9e0c0a0939
[LLVM][SCEV] udiv (mul nuw a, vscale), (mul nuw b, vscale) -> udiv a, b (#157836) 2025-10-01 15:46:12 +01:00
Paul Walker
7b8fd8f31b
[LLVM][SCEV] Look through common vscale multiplicand when simplifying compares. (#141798)
My usecase is simplifying the control flow generated by LoopVectorize
when vectorising loops whose tripcount is a function of the runtime
vector length. This can be problematic because:

* CSE is a pre-LoopVectorize transform and so it's common for an IR
function to include several calls to llvm.vscale(). (NOTE: Code
generation will typically remove the duplicates)
* Pre-LoopVectorize instcombines will rewrite some multiplies as shifts.
This leads to a mismatch between VL based maths of the scalar loop and
that created for the vector loop, which prevents some obvious
simplifications.

SCEV does not suffer these issues because it effectively does CSE during
construction and shifts are represented as multiplies.
2025-09-19 12:57:13 +01:00
Florian Hahn
f78150d2d4
Reapply "[SCEV] Fold (C1 * A /u C2) -> A /u (C2 /u C1), if C2 > C1." (#158328)
This reverts commit fd58f235f8c5bd40d98acfd8e7fb11d41de301c7.

The recommit contains an extra check to make sure that D is a multiple of
C2, if C2 > C1. This fixes the issue causing the revert fd58f235f8c. Tests
have been added in 6a726e9a4d3d0.

Original message:
If C2 >u C1 and C1 >u 1, fold to A /u (C2 /u C1).

Depends on https://github.com/llvm/llvm-project/pull/157555.

Alive2 Proof: https://alive2.llvm.org/ce/z/BWvQYN

PR: https://github.com/llvm/llvm-project/pull/157656
2025-09-17 14:28:30 +01:00
Nikita Popov
7af659d0f1
[SCEV] Don't perform implication checks with many predicates (#158652)
When adding a new predicate to a union, we currently do a bidirectional
implication for all the contained predicates. This means that the number
of implication checks is quadratic in the number of total predicates (if
they don't end up being eliminated).

Fix this by not checking for implication if the number of predicates
grows too large. The expectation is that if there is a large number of
predicates, we should be discarding them later anyway, as expanding them
would be too expensive.

Fixes https://github.com/llvm/llvm-project/issues/156114.
2025-09-16 09:24:02 +02:00
Reid Kleckner
fd58f235f8
Revert "[SCEV] Fold (C1 * A /u C2) -> A /u (C2 /u C1), if C2 > C1." (#158328)
Reverts llvm/llvm-project#157656

There are multiple reports that this is causing miscompiles in the MSan
test suite after bootstrapping and that this is causing miscompiles in
rustc. Let's revert for now, and work to capture a reproducer next week.
2025-09-12 10:15:41 -07:00
Philip Reames
6885950931
[SCEV] Fix a hang introduced by collectForPHI (#158153)
If we have a phi where one of it's source blocks is an unreachable
block, we don't want to traverse back into the unreachable region. Doing
so allows e.g. finding a trivial self loop when walking back the
predecessor chain.
2025-09-12 09:39:57 -07:00
Florian Hahn
70012fda63
[SCEV] Fold (C1 * A /u C2) -> A /u (C2 /u C1), if C2 > C1. (#157656)
If C2 >u C1 and C1 >u 1, fold to A /u (C2 /u C1).

Depends on https://github.com/llvm/llvm-project/pull/157555.

Alive2 Proof: https://alive2.llvm.org/ce/z/BWvQYN

PR: https://github.com/llvm/llvm-project/pull/157656
2025-09-11 08:08:47 +00:00
Florian Hahn
6580c9102f
[SCEV] Fold ((-1 * C1) * D / C1) -> -1 * D. (#157555)
Treat negative constants C as -1 * abs(C1) when folding multiplies and
udivs.

Alive2 Proof: https://alive2.llvm.org/ce/z/bdj9W2

PR: https://github.com/llvm/llvm-project/pull/157555
2025-09-10 13:59:14 +00:00
Florian Hahn
a1afe66f32
[SCEV] Generalize (C * A /u C) -> A fold to (C1 * A /u C2) -> C1/C2 * A. (#157159)
Generalize fold added in 74ec38fad0a1289
(https://github.com/llvm/llvm-project/pull/156730) to support multiplying and
dividing by different constants, given they are both powers-of-2 and C1 is a
multiple of C2, checked via logBase2.

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

PR: https://github.com/llvm/llvm-project/pull/157159
2025-09-09 10:41:34 +01:00
Florian Hahn
74ec38fad0
[SCEV] Fold (C * A /u C) -> A, if A is a multiple of C and C a pow-of-2. (#156730)
Alive2 Proof: https://alive2.llvm.org/ce/z/JoHJE9

PR: https://github.com/llvm/llvm-project/pull/156730
2025-09-05 08:45:13 +00:00