94 Commits

Author SHA1 Message Date
Congzhe
fbe6d79465
[LoopFusion] Fix out-of-date LoopInfo being used during fusion (#189452)
This is fix for
[187902](https://github.com/llvm/llvm-project/issues/187902), where
`LoopInfo` is not in a valid state at the beginning of `ScalarEvolution::createSCEVIter`.

The reason for the bug is that, `mergeLatch()` is called at a place
where control flow and dominator trees have been updated but `LoopInfo`
has not completed the update yet. `mergeLatch()` calls into
`ScalarEvolution` that uses `LoopInfo`, where out-of-date `LoopInfo` would
result in crash or unpredictable results.

This patch moves `mergeLatch()` to the place where `LoopInfo` has
completed its update and hence is in a valid state.
2026-04-06 16:35:28 -04:00
Afonso Rafael (Gafanhoto)
9096c9cda3
[LoopFusion] Remove the InvalidDependencies duplicates (#187744)
If the function dependencesAllowFusion returns false, in fuseCandidates
the reportLoopFusion function is used to increment InvalidDependencies
and to emit a OptimizationRemarkMissed. If both dependencesAllowFusion
and reportLoopFusion increment InvalidDependencies, statistics will
appear duplicated
2026-03-23 16:13:46 -04:00
Ehsan Amiri
d8545a4868
[LoopFusion] Use DA by default for dependence analysis (#187309)
Loop Fusion includes some internal dependence analysis code. Currently
the pass uses both DA and internal code and chooses the best result. The
goal is to use DA for all dependence analysis requirements in fusion.
This patch changes the default value. Removing the code will be done
separately later.
2026-03-18 12:53:19 -04:00
Alexis Engelke
c6811cd170
[Transforms/Scalar][NFC] Drop uses of BranchInst (#186592)
I ended up relaxing some of the checks that LoopInterchange made, the
assumptions that certain instructions were branches seemed to not be
used at all.
2026-03-14 18:12:26 +01:00
Alireza Torabian
ce9d033c51
[LoopFusion] Fusing with loop-invariant non-anti dependency (#186459)
It is safe to fuse if there is any loop-invariant non-anti dependency.
2026-03-13 20:22:21 +00: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
Afonso Rafael (Gafanhoto)
9cc615a2f5
[LoopFusion] remove else after return (NFC) (#184993)
A bit of a small nitpick, close it if unnecessary. (clang-tidy warnings)
2026-03-06 19:19:33 +00:00
Ehsan Amiri
9143f210ce
[LoopFusion] Correction in the comments (NFC) (#184689)
The comments in the code should have been updated following the change
in https://github.com/llvm/llvm-project/pull/183353. This PR addresses
that issue.
2026-03-05 16:54:23 -05:00
Ehsan Amiri
9ab13eef8d
[LoopFusion] clear FusionCandidates more often (#183353)
A LoopVector contains all the loops with the same parent loop (or all
loops with no parent). Once loop fusion is done with the transformation
for candidates extracted from one LoopVector we can safely clear
FusionCandidates. This avoids unnecssary work and results in more
meaningful statistics.
2026-02-25 14:57:02 -05:00
Ehsan Amiri
fafaaa165b
[LoopFusion] Improve collectFusionCandidates() (#182571)
The order of visiting loops in collectFusionCandidates() guarantees that
a new member can only possibly be added to the end of a set.

Also currently `NumFusionCandidates` counts any loop that is added to a
candidate set. Usually large majority of candidate sets have a single
members so they are not really candidates for fusion. Only the second
member of a candidate set and the ones that come after that could be
counted as fusion candidates.
2026-02-20 15:32:34 -05:00
Justin Fargnoli
7c8a13ab79
[LoopPeel] change peelLoop's return type from bool to void (#177488) 2026-01-23 10:49:03 -08:00
Alireza Torabian
599c2731b3
[LoopFusion] Forget cached SCEV values after the fusion (#177455)
This patch fixes the issue #115279. After the fusion, some of the cached
SCEV values such as the induction variable may not be valid anymore and
need to be forgotten.
2026-01-22 19:50:21 -05:00
Congzhe
1286de408c
[LoopFusion] Optimize away Phi nodes that are sunk from the 2nd loop preheader (#176503)
Fixed issue #165087.

When we sink phis from the 2nd loop preheader to the exit block, we 
optimize it a bit further, i.e., propagate the uses of each phi node with 
its incoming value and optimize away the phis. Deleted `fixPHINodes()`
too because the phis are already optimized away and there is no point 
processing `fixPHINodes()`.
2026-01-22 16:12:12 -05:00
Alireza Torabian
5ab966aacb
[LoopFusion] Non-loop block must be the immediate successor of exit (#175034)
Loop fusion assumes the non-loop block of a guarded adjacent loop is the
immediate successor of its exit block. This patch ensures this condition
is hold and fixes the crash #166356.
2026-01-08 17:07:15 -05:00
Alireza Torabian
9bc38df587
[LoopFusion] Simplifying the legality checks (#171889)
Considering that the current loop fusion only supports adjacent loops,
we are able to simplify the checks in this pass. By removing
`isControlFlowEquivalent` check, this patch fixes multiple issues
including #166560, #166535, #165031, #80301 and #168263.

Now only the sequential/adjacent candidates are collected in the same
list. This patch is the implementation of approach 2 discussed in post
#171207.
2025-12-12 15:09:34 -05:00
Alireza Torabian
025e431e74
[LoopFusion] Forget loop and block dispositions after latch merge (#166233)
Merging the latches of loops may affect the dispositions, so they should
be forgotten after the merge. This patch fixed the crash in loop fusion
[#164082](https://github.com/llvm/llvm-project/issues/164082).
2025-11-04 16:48:39 -05:00
Rahul Joshi
62adc83c91
[NFC][LLVM] Namespace cleanup in LoopFuse (#163758)
Additionally, make the `Loop` argument to `printLoop` const.
2025-10-16 15:06:05 -07:00
Alireza Torabian
d6072986cd
[LoopFusion] Detecting legal dependencies for fusion using DA info (#146383)
Loop fusion pass will use the information provided by the recent
DA patch to fuse additional legal loops, including those with
forward loop-carried dependencies.
2025-09-25 17:53:26 -04:00
Madhur Amilkanthwar
90de4a4ac9
[LoopFusion] Fix sink instructions (#147501)
If we have instructions in second loop's preheader which can be sunk, we
should also be adjusting PHI nodes to receive values from the fused loop's latch block.

Fixes #128600
2025-07-28 12:08:43 +05:30
Florian Hahn
3fcfce4c5e
Reapply "[LoopPeel] Implement initial peeling off the last loop iteration. (#139551)"
This reverts the revert commit bf92b127d2637948f53d11a187e865aa10e2e74c.

This adds missing initialization of PeelLast in gatherPeelingPreferences.

Original message:
Generalize countToEliminateCompares to also consider peeling off the
last iteration if it eliminates a compare.

At the moment, codegen for peeling off the last iteration is quite
restrictive and callers have to make sure that the exit condition can be
adjusted when peeling and that the loop executes at least 2 iterations.

Both will be relaxed in follow-ups.

PR: https://github.com/llvm/llvm-project/pull/139551
2025-05-17 10:51:05 +01:00
Florian Hahn
bf92b127d2
Revert "[LoopPeel] Implement initial peeling off the last loop iteration. (#139551)"
This reverts commit bb10c3ba7f77d40a7fbfd4ac815015d3a4ae476a.

Also reverts 4f663cca15f2b53c2bc6a84d1b1f5bd81679356d:
  Revert "[LoopPeel] Make sure PeelLast is always initialized."

Revert for now to bring msan bots back to green

 https://lab.llvm.org/buildbot/#/builders/164/builds/9992
 https://lab.llvm.org/buildbot/#/builders/94/builds/7158
2025-05-16 08:33:12 +01:00
Florian Hahn
bb10c3ba7f
[LoopPeel] Implement initial peeling off the last loop iteration. (#139551)
Generalize countToEliminateCompares to also consider peeling off the
last iteration if it eliminates a compare.

At the moment, codegen for peeling off the last iteration is quite
restrictive and callers have to make sure that the exit condition can be
adjusted when peeling and that the loop executes at least 2 iterations.

Both will be relaxed in follow-ups.

PR: https://github.com/llvm/llvm-project/pull/139551
2025-05-15 19:15:48 +01:00
Pedro Lobo
950bc6cd77
[LoopFuse] Change placeholder from undef to poison (#131535)
Use `poison` instead of `undef` as a placeholder for phi entries of
unreachable predecessors.
2025-03-16 22:44:39 +00:00
Alireza Torabian
3c74430320
[DependenceAnalysis][NFC] Removing PossiblyLoopIndependent parameter (#124615)
Parameter PossiblyLoopIndependent has lost its intended purpose. This
flag is always set to true in all cases when depends() is called, hence
we want to reconsider the utility of this variable and remove it from
the function signature entirely. This is an NFC patch.
2025-02-11 16:23:28 -05: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
Kazu Hirata
94f9cbbe49
[Scalar] Remove unused includes (NFC) (#114645)
Identified with misc-include-cleaner.
2024-11-02 08:32:26 -07:00
Vitaly Buka
5ce47a5813
Reland "[Support] Assert that DomTree nodes share parent" (#102782)
A dominance query of a block that is in a different function is
ill-defined, so assert that getNode() is only called for blocks that are
in the same function.

There are three cases, where this behavior did occur. LoopFuse didn't
explicitly do this, but didn't invalidate the SCEV block dispositions,
leaving dangling pointers to free'ed basic blocks behind, causing
use-after-free. We do, however, want to be able to dereference basic
blocks inside the dominator tree, so that we can refer to them by a
number stored inside the basic block.

Reverts #102780
Reland #101198
Fixes #102784

Co-authored-by: Alexis Engelke <engelke@in.tum.de>
2024-08-13 11:56:02 +02:00
Vitaly Buka
3c3df1bef8
Revert "[Support] Assert that DomTree nodes share parent" (#102780)
Reverts llvm/llvm-project#101198

Breaks multiple bots:
https://lab.llvm.org/buildbot/#/builders/72/builds/2103
https://lab.llvm.org/buildbot/#/builders/164/builds/1909
https://lab.llvm.org/buildbot/#/builders/66/builds/2706
2024-08-10 18:36:09 -07:00
Alexis Engelke
8101d1863c
[Support] Assert that DomTree nodes share parent (#101198)
A dominance query of a block that is in a different function is
ill-defined, so assert that getNode() is only called for blocks that are
in the same function.

There are two cases, where this behavior did occur. LoopFuse didn't
explicitly do this, but didn't invalidate the SCEV block dispositions,
leaving dangling pointers to free'ed basic blocks behind, causing
use-after-free. We do, however, want to be able to dereference basic
blocks inside the dominator tree, so that we can refer to them by a
number stored inside the basic block.
2024-08-10 18:19:05 +02:00
Nuno Lopes
7d33d4720f [LoopFuse] Use poison instead of undef as placeholder for phi entry of unreachable predecessor [NFC] 2024-06-30 11:59:58 +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
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
Fangrui Song
111fcb0df0 [llvm] Fix duplicate word typos. NFC
Those fixes were taken from https://reviews.llvm.org/D137338
2023-09-01 18:25:16 -07:00
Bjorn Pettersson
a20f7efbc5 Remove several no longer needed includes. NFCI
Mostly removing includes of InitializePasses.h and Pass.h in
passes that no longer has support for the legacy PM.
2023-04-17 13:54:19 +02:00
Fangrui Song
c1eb3db780 [LoopFuse] Remove legacy pass
Following recent changes to remove non-core legacy passes.
2023-02-14 23:53:39 -08:00
Kazu Hirata
b53e0d1b34 Use std::nullopt instead of None in comments (NFC) 2023-01-14 13:53:40 -08:00
Ramkrishnan Narayanan Komala
7f15907acc [LoopFusion] Sorting of undominated FusionCandidates crashes
This patch tries to fix [[ https://github.com/llvm/llvm-project/issues/56263 | issue ]].

If two **FusionCandidates** are in same level of dominator tree then, they will not be dominates each other. But they are control flow equivalent. To sort those FusionCandidates **nonStrictlyPostDominate** check is needed.

Reviewed By: Narutoworld

Differential Revision: https://reviews.llvm.org/D139993
2023-01-11 23:15:40 -05:00
luxufan
aca7441c7a [LoopFusion] Exit early if one of fusion candidate has guarded branch but the another has not
Fixes: https://github.com/llvm/llvm-project/issues/59024

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D138269
2023-01-03 23:18:58 +08:00
Anna Thomas
05b060b0b0 [LoopPeel] Expose ValueMap of last peeled iteration. NFC
The value map of last peeled iteration is computed within peelLoop API.
This patch exposes it for callers of peelLoop.
While this is not currently used by upstream passes, we have a usecase
downstream which benefits from this API update. Future users of peelLoop
can also use the ValueMap if needed.

Similar value maps are exposed by other loop utilities such as loop
cloning.

Differential Revision: https://reviews.llvm.org/D138228
2022-12-19 09:55:29 -05:00
Nikita Popov
04d652994d [SCEV] Return ArrayRef for SCEV operands() (NFC)
Use a consistent type for the operands() methods of different SCEV
types. Also make the API consistent by only providing operands(),
rather than also providin op_begin() and op_end() for some of them.
2022-12-16 15:36:19 +01:00
Joshua Cao
5004320590 [LoopFusion] sink second loop PHIs
Fixes https://github.com/llvm/llvm-project/issues/59023

PHI nodes that are in the second loop only have the first loop as its
predecessor. These PHI nodes should be sunk to the end of the fused
loop. If the second loop uses the PHI, then the loops cannot be fused.

I don't think this should happen in typical compilation workflows.
The PHI will be in a dedicated exit block of the first loop following
LCSSA transformations.

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D139812
2022-12-13 10:13:39 -08:00
Fangrui Song
3152156334 [Transforms/Scalar] llvm::Optional => std::optional 2022-12-13 08:05:14 +00:00
Kazu Hirata
343de6856e [Transforms] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-02 21:11:37 -08:00
Mengxuan Cai
ec210f3942 [LoopFuse] Ensure inner loops are in loop simplified form under new PM
LoopInfo doesn't give all loops in a loop nest, it gives top level loops
only. While isLoopSimplifyForm() only checkes for the outter most loop of a
loop nest. As a result, inner loops that are not in simplied form can
not be simplified with the original code.

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D137672
2022-11-11 15:55:59 -05:00
Mengxuan Cai
eda3c93486 [LoopFuse] Ensure loops are in loop simplified form under new PM
Loop Fusion (Function Pass) requires loops in simplified form. With
legacy-pm, loop-simplify pass is added as a dependency for loop-fusion.
But the new pass manager does not always ensure this format. This patch
tries to invoke simplifyLoop() on loops that are not in simplified form
only for new PM.

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D136781
2022-10-31 11:46:28 -04:00
Max Kazantsev
21a9abc1ce [LoopFuse] Drop loop dispositions before reassigning blocks to other loop
This bug was found by recent improvement in SCEV verifier. The code in LoopFuse
directly reassigns blocks to be a part of a different loop, which should automatically
invalidate all related cached loop dispositions.

Differential Revision: https://reviews.llvm.org/D134173
Reviewed By: nikic
2022-09-19 17:43:06 +07:00
Aaron Kogon
ae05b9dc30 Sink/hoist memory instructions between loop fusion candidates
Currently, instructions in the preheader of the second of two fusion
candidates are sunk and hoisted whenever possible, to try to allow the
loops to fuse. Memory instructions are skipped, and are never sunk or
hoisted. This change adds memory instructions for sinking/hoisting
consideration.

This change uses DependenceAnalysis to check if a mem inst in the
preheader of FC1 depends on an instruction in FC0's header, across
which it will be hoisted, or FC1's header, across which it will be
sunk. We reject cases where the dependency is a data hazard.

Differential Revision: https://reviews.llvm.org/D131606
2022-09-07 07:42:00 -04:00
Kazu Hirata
258531b7ac Remove redundant initialization of Optional (NFC) 2022-08-20 21:18:28 -07:00
Kazu Hirata
6b1bc80188 [Scalar] Qualify auto in range-based for loops (NFC)
Identified with readability-qualified-auto.
2022-08-20 21:18:25 -07:00
Kazu Hirata
0e37ef0186 [Transforms] Fix comment typos (NFC) 2022-08-07 23:55:24 -07:00