8097 Commits

Author SHA1 Message Date
Mircea Trofin
52cb6e9d49
[ProfCheck][NFC] Make Function argument from branch weight setter optional (#166032)
This picks up from #166028, making the `Function` argument optional:
most cases don't need to provide it, but in e.g. InstCombine's case,
where the instruction (select, branch) is not attached to a function
yet, the function needs to be passed explicitly.

Co-authored-by: Florian Hahn <flo@fhahn.com>
2025-11-05 07:40:37 -08:00
Matt Arsenault
fb21f16fe6
RuntimeLibcalls: Add stub API for getting function signatures (#166290)
Eventually this should be generated by tablegen for all functions.
For now add a manually implementation for sincos_stret, which I
have an immediate use for. This will allow pulling repeated code
across targets into shared call sequence code.

Also add sqrt just to make sure we can handle adding return attributes
on the declaration.
2025-11-04 10:06:29 -08:00
Joel E. Denny
1aa86ca521
[LoopUnroll] Fix division by zero (#166258)
PR #159163's probability computation for epilogue loops does not handle
the possibility of an original loop probability of one. Runtime loop
unrolling does not make sense for such an infinite loop, and a division
by zero results. This patch works around that case.

Issue #165998.
2025-11-04 12:49:33 -05:00
Yingwei Zheng
4ce58833d3
[SimplifyCFG] Fix value enumeration of a full range (#166379)
ConstantRange uses `[-1, -1)` as the canonical form of a full set.
Therefore, the `for (APInt I = Lower; I != Upper; ++I)` idiom doesn't
work for full ranges. This patch fixes the value enumeration in
`ConstantComparesGatherer` to prevent missing values for full sets.

Closes https://github.com/llvm/llvm-project/issues/166369.
2025-11-05 01:43:05 +08:00
Yingwei Zheng
8a84b285f6
[SimplifyCFG] Eliminate dead edges of switches according to the domain of conditions (#165748)
In simplifycfg/cvp/sccp, we eliminate dead edges of switches according
to the knownbits/range info of conditions. However, these approximations
may not meet the real-world needs when the domain of condition values is
sparse. For example, if the condition can only be either -3 or 3, we
cannot prove that the condition never evaluates to 1 (knownbits:
???????1, range: [-3, 4)).
This patch adds a helper function `collectPossibleValues` to enumerate
all the possible values of V. To fix the motivating issue,
`eliminateDeadSwitchCases` will use the result to remove dead edges.

Note: In
https://discourse.llvm.org/t/missed-optimization-due-to-overflow-check/88700
I proposed a new value lattice kind to represent such values. But I find
it hard to apply because the transition becomes much complicated.

Compile-time impact looks neutral:
https://llvm-compile-time-tracker.com/compare.php?from=32d6b2139a6c8f79e074e8c6cfe0cc9e79c4c0c8&to=e47c26e3f1bf9eb062684dda4fafce58438e994b&stat=instructions:u
This patch removes many dead error-handling codes:
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/3012
Closes https://github.com/llvm/llvm-project/issues/165179.
2025-11-04 20:55:33 +08:00
Jay Foad
f037f41350
[IR] Add new function attribute nocreateundeforpoison (#164809)
Also add a corresponding intrinsic property that can be used to mark
intrinsics that do not introduce poison, for example simple arithmetic
intrinsics that propagate poison just like a simple arithmetic
instruction.

As a smoke test this patch adds the new property to
llvm.amdgcn.fmul.legacy.
2025-11-04 12:00:44 +00:00
kper
5b2f9b53bd
[SimplifyCFG]: Switch on umin replaces default (#164097)
A switch on `umin` can eliminate the default case by making the `umin`'s
constant the default case.

Proof: https://alive2.llvm.org/ce/z/_N6nfs
Fixes: https://github.com/llvm/llvm-project/issues/162111
2025-11-04 18:35:40 +08:00
Laxman Sole
6fe3eccdf4
[llvm][DebugInfo] Emit 0/1 for constant boolean values (#151225)
Previously, sign-extending a 1-bit boolean operand in `#DBG_VALUE` would
convert `true` to -1 (i.e., 0xffffffffffffffff). However, DWARF treats
booleans as unsigned values, so this resulted in the attribute
`DW_AT_const_value(0xffffffffffffffff)` being emitted. As a result, the
debugger would display the value as `255` instead of `true`.

This change modifies the behavior to use zero-extension for 1-bit values
instead, ensuring that `true` is represented as 1. Consequently, the
DWARF attribute emitted is now `DW_AT_const_value(1)`, which allows the
debugger to correctly display the boolean as `true`.
2025-11-03 13:34:44 -08:00
Robert Imschweiler
a8ea7f4580
Reapply: [AMDGPU][UnifyDivergentExitNodes][StructurizeCFG] Add support for callbr instruction with inline-asm (#152161) (#166195)
Reapply #152161 with fixed 'changed' flags.
2025-11-03 20:59:48 +01:00
Joel E. Denny
bb9bd5f263
[LoopUnroll] Fix assert fail on zeroed branch weights (#165938)
BranchProbability fails an assert when its denominator is zero.

Reported at
<https://github.com/llvm/llvm-project/pull/159163#pullrequestreview-3406318423>.
2025-11-03 10:19:12 -05:00
Mircea Trofin
6adef40e75
[SimplifyCFG] Don't propagate weights to unconditional branches in turnSwitchRangeIntoICmp (#165931)
PR #161000 introduced a bug whereby the IR would become invalid by having an unconditional branch have `!prof`​attached to it. This only became evident in PR #165744, because the IR of `test/Transforms/SimplifyCFG/pr165301.ll`​was simple enough to both (1) introduce the unconditional branch, and (2) survive in that fashion until the end of the pass (simplifycfg) and thus trip the verifier.
2025-10-31 23:10:59 +00:00
Mircea Trofin
fe8ab75b40
[SimplifyCFG] Propagate profile in simplifySwitchOfPowersOfTwo (#165804)
`simplifySwitchOfPowersOfTwo`​ converts (when applicable, see `00f5a1e30b`​) a switch to a conditional branch. Its false case goes to the `default`​ target of the former switch, and the true case goes to a BB performing a `cttz`​. We can calculate the branch weights from the branch weights of the old switch.

Issue #147390
2025-10-31 13:05:18 -07:00
Joel E. Denny
cc8ff73fba
[LoopUnroll] Fix block frequencies for epilogue (#159163)
As another step in issue #135812, this patch fixes block frequencies for
partial loop unrolling with an epilogue remainder loop. It does not
fully handle the case when the epilogue loop itself is unrolled. That
will be handled in the next patch.

For the guard and latch of each of the unrolled loop and epilogue loop,
this patch sets branch weights derived directly from the original loop
latch branch weights. The total frequency of the original loop body,
summed across all its occurrences in the unrolled loop and epilogue
loop, is the same as in the original loop. This patch also sets
`llvm.loop.estimated_trip_count` for the epilogue loop instead of
relying on the epilogue's latch branch weights to imply it.

This patch fixes branch weights in tests that PR #157754 adversely
affected.
2025-10-31 11:01:42 -04:00
Joel E. Denny
24557cce40
[LoopUnroll] Fix block frequencies when no runtime (#157754)
This patch implements the LoopUnroll changes discussed in [[RFC] Fix
Loop Transformations to Preserve Block

Frequencies](https://discourse.llvm.org/t/rfc-fix-loop-transformations-to-preserve-block-frequencies/85785)
and is thus another step in addressing issue #135812.

In summary, for the case of partial loop unrolling without a remainder
loop, this patch changes LoopUnroll to:

- Maintain branch weights consistently with the original loop for the
sake of preserving the total frequency of the original loop body.
- Store the new estimated trip count in the
`llvm.loop.estimated_trip_count` metadata, introduced by PR #148758.
- Correct the new estimated trip count (e.g., 3 instead of 2) when the
original estimated trip count (e.g., 10) divided by the unroll count
(e.g., 4) leaves a remainder (e.g., 2).

There are loop unrolling cases this patch does not fully fix, such as
partial unrolling with a remainder loop and complete unrolling, and
there are two associated tests whose branch weights this patch adversely
affects. They will be addressed in future patches that should land with
this patch.
2025-10-31 10:44:27 -04:00
Yingwei Zheng
56777e7da2
[SimplifyCFG] Avoid use-after-free when removing incoming values from PHI nodes (#165744)
`PHINode::removeIncomingValue` removes itself when there are no incoming
edges. Then we cannot use it to retrieve the next instruction.

Closes https://github.com/llvm/llvm-project/issues/165301.
2025-10-31 10:30:29 +08:00
Joel E. Denny
8d186e2195
[LoopUnroll][NFCI] Clean up remainder followup metadata handling (#165272)
Followup metadata for remainder loops is handled by two implementations,
both added by 7244852557ca6:

1. `tryToUnrollLoop` in `LoopUnrollPass.cpp`.
2. `CloneLoopBlocks` in `LoopUnrollRuntime.cpp`.

As far as I can tell, 2 is useless: I added `assert(!NewLoopID)` for the
`NewLoopID` returned by the `makeFollowupLoopID` call, and it never
fails throughout check-all for my build.

Moreover, if 2 were useful, it appears it would have a bug caused by
7cd826a321d9. That commit skips adding loop metadata to a new remainder
loop if the remainder loop itself is to be completely unrolled because
it will then no longer be a loop. However, that commit incorrectly
assumes that `UnrollRemainder` dictates complete unrolling of a
remainder loop, and thus it skips adding loop metadata even if the
remainder loop will be only partially unrolled.

To avoid further confusion here, this patch removes 2. check-all
continues to pass for my build. If 2 actually is useful, please advise
so we can create a test that covers that usage.

Near 2, this patch retains the `UnrollRemainder` guard on the
`setLoopAlreadyUnrolled` call, which adds `llvm.loop.unroll.disable` to
the remainder loop. That behavior exists both before and after
7cd826a321d9. The logic appears to be that remainder loop unrolling
(whether complete or partial) is opt-in. That is, unless
`UnrollRemainder` is true, `UnrollRuntimeLoopRemainder` skips running
remainder loop unrolling, and `llvm.loop.unroll.disable` suppresses any
later attempt at it.

This patch also extends testing of remainder loop followup metadata to
be sure remainder loop partial unrolling is handled correctly by 1.
2025-10-30 10:57:27 -04:00
Robert Imschweiler
89540114a7
[AMDGPU][FixIrreducible][UnifyLoopExits] Support callbr with inline-asm (#149308)
First batch of changes to add support for inline-asm callbr for the
AMDGPU backend.
2025-10-30 14:22:42 +01:00
Kunqiu Chen
b2fe5d1482
[SimplifyCFG] Hoist common code when succ is unreachable block (#165570)
Previously, `hoistCommonCodeFromSuccessors` returned early if one of the
succ of BB has >1 predecessors.

However, if the succ is an unreachable BB, we can relax the condition to
perform `hoistCommonCodeFromSuccessors` based on the assumption of not
reaching UB.

See discussion https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2989
for details.

Alive2 proof: https://alive2.llvm.org/ce/z/OJOw0s
Promising optimization impact:
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2995
2025-10-30 02:45:27 +08:00
Stephen Tozer
9b818afc26
[DebugInfo] Propagate DebugLoc from switch in simplifySwitchOfPowersOfTwo (#165335)
A recent commit 00f5a1e30b modified simplifySwitchOfPowersOfTwo to
generate a branch to handle the non-power-of-2 case when appropriate,
but does not set a DebugLoc on the new branch instruction; this patch
propagates the switch's DebugLoc to the new branch, as for the other
instructions generated in the same block.

Found using #107279.
2025-10-29 15:43:47 +00:00
Kunqiu Chen
356a8114ca
[PredicateInfo] Drop redundant PredicateInfo annotation (#165434)
See
https://github.com/llvm/llvm-project/pull/165419#discussion_r2470208670
for details.

The extra annotation `"; Has predicate info"` does not provide any extra
information and might poison the UTC-generated checks introduced by
#165419.
2025-10-29 19:39:49 +08:00
Yingwei Zheng
e8a1162b7b
[SimplifyCFG] Use range check in simplifyBranchOnICmpChain if possible (#165105)
In `simplifyBranchOnICmpChain`, if we can merge the comparisons into a
range check, use a conditional branch instead. This change also breaks
the cycle found in https://github.com/llvm/llvm-project/issues/165088.

Closes https://github.com/llvm/llvm-project/issues/165088.

Detailed description of the cycle:

```
define void @pr165088_cycle_1(i8 %x) {
entry:
  %switch = icmp uge i8 %x, 2
  %cond1 = icmp ugt i8 %x, 1
  %or.cond = and i1 %switch, %cond1
  br i1 %or.cond, label %block3, label %block2

block1:
  %cond2 = icmp ugt i8 %x, 1
  br i1 %cond2, label %block3, label %block2

block2:
  br label %block3

block3:
  %cond3 = icmp eq i8 %x, 0
  br i1 %cond3, label %exit, label %block1

exit:
  ret void
}
```

`simplifyBranchOnICmpChain` folds the branch in `entry` to a switch.
Then we get:
```
entry:
  switch i8 %x, label %block3 [
  i8 1, label %block2
  i8 0, label %block2
  ]

...
```

`performValueComparisonIntoPredecessorFolding` redirects the default
target `block3` into `block1` because `%x` is never zero.
```
entry:
  switch i8 %x, label %block1 [
  i8 1, label %block2
  i8 0, label %block2
  ]
...
```

Then `turnSwitchRangeIntoICmp` will convert the switch back into a
branch on icmp.
```
entry:
  %switch = icmp ult i8 %x, 2
  br i1 %switch, label %block2, label %block1
...
```

Since `block1` and `block2` share the same successor `block3`,
`performBranchToCommonDestFolding` merges the conditions of `entry` and
`block1`, resulting in the original pattern again.
2025-10-29 10:52:28 +08:00
Kunqiu Chen
535197fcef
[PredicateInfo] Reformat PT_Switch's annotation as valid comments (#165249)
Previously, PredicateInfo brutally annotated `PT_Switch` as follows:
```python
f'"; switch predicate info ... CaseValue: ... Switch: {*PS->Switch} Edge: ... RenamedOp: ..."'
```

However, the `switch` instruction in LLVM might cross >1 lines, leading
to the annotation of `PT_Switch` being **illegal comments**, e.g.,
```LLVM
; switch predicate info { CaseValue: i32 1 Switch:  switch i32 %x, label %default [
    i32 0, label %case0
    i32 1, label %case1
    i32 2, label %case0
    i32 3, label %case3
    i32 4, label %default
  ] Edge: [label %sw,label %case1], RenamedOp: %x }
  x.0 = bitcast i32 %x to i32
```

This patch removes the `switch` printing, reformating the `PT_Switch`'s
annotation as follows:
```python
f'"; switch predicate info ... CaseValue: ... Edge: ...  RenamedOp: ..."'
```
, e.g., 

```LLVM
; switch predicate info { CaseValue: i32 1 Edge: [label %sw,label %case1], RenamedOp: %x }
  x.0 = bitcast i32 %x to i32
```

It should be Okay because `CaseValue: ...` + `Edge: ...` are meaningful
enough for diagnostics, covering the necessary info provided by full
switch printing (E.g., `PT_Branch` also did not print the relevant
branch instruction).
2025-10-27 23:45:02 +08:00
Antonio Frighetto
00f5a1e30b
[SimplifyCFG] Extend simplifySwitchOfPowersOfTwo to reachable defaults
Favour a `cttz`-indexed table lookup over an indirect jump table when
the default switch case is reachable, by branching non-power-of-two
inputs to the default case.

Proofs: https://alive2.llvm.org/ce/z/HeRAtf.
2025-10-27 08:51:43 +01:00
Robert Imschweiler
6fca138118
[BasicBlockUtils] Add BasicBlock printer (#163066) 2025-10-22 17:47:14 +02:00
Kunqiu Chen
ea45fec99c
[PredicateInfo] Reserve adjacent LN_Last defs for the same phi use (#164577)
This patch fixes a missed optimization issue: predicate infos might be
lost in phi-use scenarios.

Due to the existence of and-chains, a phi-use might be associated with
multiple LN_Last predicate infos.
E.g.,
```cpp
// TWO LN_Last Predicate Info defs:
// 1. a >= 1
// 2. a < 2
if ( a < 1 || a >= 2) {
  a = 1;
}  
// PHI use of `a`
use(a)
```
However, previously, `popStackUntilDFSScope` reserved only ONE LN_Last
def for a phi use (i.e., reserve only one of `a >= 1` / `a < 2`),
although there might be multiple LN_Last defs for the same phi use.


This patch reserves the adjacent LN_Last defs if they are designated for
the same phi use.
2025-10-22 22:17:39 +08:00
aokblast
a3082c9d90
[SCCP] Support constant structure in PhiNode (#163713)
This patch adds support for constant propagation of individual structure
members through Phi nodes. Each member is handled independently,
allowing optimization opportunities when specific members become
constant.

Also, update the testcase since we are able to optimize the call
parameter now.
2025-10-19 03:57:56 +00:00
Yingwei Zheng
5d22980ed4
[LVI][SCCP] Avoid copying ValueLatticeElement (#163901)
Copying ValueLatticeElement becomes expensive after
https://github.com/llvm/llvm-project/pull/111544. This patch eliminates
some redundant copies to improve performance. The code change has been
carefully reviewed to ensure that there is no dangling reference.

Compile-time improvement:
https://llvm-compile-time-tracker.com/compare.php?from=f4359301c033694d36865c7560714164d2050240&to=4ea449bd53feef43403c35d8b815ddca752dbc17&stat=instructions%3Au
2025-10-19 00:58:05 +08:00
Kazu Hirata
b82baf0f5b
[llvm] Remove redundant control flow statements (NFC) (#163509) 2025-10-15 06:54:30 -07:00
Rahul Joshi
d9a6ed73eb
[NFC][LLVM] Fix build warning in CloneFunction.cpp (#163267) 2025-10-13 16:46:31 -07: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
Sohaib Iftikhar
f140491dcc
[LLVM][CppCompile] Fix unused variable warning after 0e025418 (#163203)
[LLVM][CppCompile] Fix unused variable warning after 0e025418

Fixes unused variable warning for libTransform with non debug builds.
Folds the unused variable into the assert.
2025-10-13 15:00:42 +00:00
Rahul Joshi
f2f9f77211
[NFC][LLVM] Code cleanup in CloneFunction.cpp (#162875)
- Use explicit types instead of auto when type is not obvious.
- Move local function out of anonymous namespace and make them static.
- Use structured bindings in some range for loops.
- Simplify PHI handling code a bit.
2025-10-13 06:15:38 -07:00
Valery Pykhtin
0e025418ab
[SSAUpdaterBulk] Add PHI simplification pass. (#150936)
This optimization is performed as a separate pass over newly inserted PHI nodes to simplify and deduplicate them. By processing PHIs separately, we avoid the complexity of tracking reference bookkeeping needed to update BBValueInfo structures during insertion.
2025-10-13 15:02:49 +02:00
Rahul Joshi
a4a0a4b9b1
[NFC][LLVM] Code cleanup in InstructionNamer.cpp (#162689)
Make file local function static and use explicit type for Arg.
2025-10-10 14:42:05 -07:00
Rahul Joshi
97031a6e09
[NFC][LLVM] Code cleanup in MisExpect.cpp (#162695)
- Make instruction arguments to the `misexpect` functions const and drop
const for `ArrayRef` arguments.
- Remove namespace llvm/misexpect surrounding all the code in .cpp file
and instead use `using namespace`.
- Change static helper functions to also use const references or
pointers when possible.
2025-10-10 05:24:42 -07:00
Rahul Joshi
ea5648b1a8
[NFC][LLVM] Code cleanup in LowerInvoke.cpp (#162691)
Fix indentation for `LowerInvokeLegacyPass` and use namespace qualifiers
for defining variables and functions in `llvm` namespace.
2025-10-10 05:24:11 -07:00
Rahul Joshi
bea786d128
[NFC][LLVM] Use namespace qualifier to define DenseMapInfo specializations (#162683)
Use `llvm::DenseMapInfo` to define `DenseMapInfo` specializations
instead of surrounding it with `namespace llvm {}`.
2025-10-10 05:23:44 -07:00
Nikita Popov
6c2781e187
[GVN] Share equality propagation for assume and condition (#161639)
GVN currently has two different implementation of equality propagation.
One of them is used for branch conditions (dominating an edge), which
performs replacements across multiple blocks. This is also used for
assumes to handle uses outside the current block.

However, uses inside the block are handled using a completely separate
implementation, which involves populating a replacement map and then
checking it for individual instructions during normal GVN. While this
approach generally makes sense, it is kind of pointless if we already do
a use walk to handle the cross-block case anyway.

This PR generalizes propagateEquality() to accept either a
BasicBlockEdge or an Instruction* and replace dominated users. This
removes the need for special handling of uses in the same block for
assumes, as they're covered by instruction dominance, and ensures that
both implementations do not go out of sync.
2025-10-10 10:58:58 +02:00
dianqk
e9205ca8cf
[SimplifyCFG] Remove all incoming values from OtherDest if OtherDest is unreachable (#162677)
Fixes #162585.

#161000 changed `br i1 true, label %if, label %else` to `br label %if`,
so we should remove one more incoming value.
2025-10-10 06:44:00 +08:00
Michael Buch
6cba572d9e
[llvm][DebugInfo][NFC] Abstract DICompileUnit::SourceLanguage to allow alternate DWARF SourceLanguage encoding (#162255)
This patch sets up `DICompileUnit` to support the DWARFv6
`DW_AT_language_name` and `DW_AT_language_version` attributes (which are
set to replace `DW_AT_language`). This patch changes the
`DICompileUnit::SourceLanguage` field type to a `DISourceLanguageName`
that encapsulates the notion of "versioned vs. unversioned name". A
"versioned" name is one that has an associated version stored separately
in `DISourceLanguageName::Version`.

This patch just changes all the clients of the `getSourceLanguage` API
to the expect a `DISourceLanguageName`. Currently they all just `assert`
(via `DISourceLanguageName::getUnversionedName`) that we're dealing with
"unversioned names" (i.e., the pre-DWARFv6 language codes). In follow-up
patches (e.g., draft is at
https://github.com/llvm/llvm-project/pull/162261), when we start
emitting versioned language codes, the `getUnversionedName` calls can
then be adjusted to `getName`.

**Implementation considerations**

* We could have added a new member to `DICompileUnit` alongside the
existing `SourceLanguage` field. I don't think this would have made the
transition any simpler (clients would still need to be aware of
"versioned" vs. "unversioned" language names). I felt that encapsulating
this inside a `DISourceLanguageName` was easier to reason about for
maintainers.
* Currently DISourceLanguageName is a `12` byte structure. We could
probably pack all the info inside a `uint64_t` (16-bits for the name,
32-bits for the version, 1-bit for answering the `hasVersionedName`).
Just to keep the prototype simple I used a `std::optional`. But since
the guts of the structure are hidden, we can always change the layout to
a more compact representation instead.

**How to review**

* The new `DISourceLanguageName` structure is defined in
`DebugInfoMetadata.h`. All the other changes fall out from changing the
`DICompileUnit::SourceLanguage` from `unsigned` to
`DISourceLanguageName`.
2025-10-08 18:27:22 +01:00
Marek Sedláček
6ccb487392
[LoopRotate] Remove canRotateDeoptimizingLatchExit and multi-rotate (#162482)
This patch removes canRotateDeoptimizingLatchExit check from loop roate
and connected multi rotation option for loop roate (-loop-rotate-multi
option).

The heuristic in canRotateDeoptimizingLatchExit returns true if any of
the loop exits are non-deoptimizing. This means if the loop has multiple
deopt exits, then without multi-rotate, we may still end up having deopt
exit at the latch. This multi-rotate option is introduced but it is off
by default. 

We have not seen any improvements downstream as well, where
we have frequent number of deoptimizations in IR. Since the original
heuristic without the multi-rotate effectively ends up being "rotate
under some conditions", but the loop may still not be in the form we
want, we should remove the heuristic and multi-rotate framework entirely

Note that the diff is big, but it's just removal of while loop and
indentation change.

After this patch I would like to continue here and propose adding a
computability check for exit count, but that will be in a separate PR.

Requests for review: @annamthomas @fhahn @davemgreen

Co-authored-by: Marek Sedlacek <msedlacek@azul.com>
2025-10-08 15:06:32 +00:00
Nikita Popov
4c82754704
[SimplifyCFG] Allow some switch optimizations early in the pipeline (#158242)
While we do not want to form actual lookup tables early, we do want to
perform some optimizations, as they may enable inlining of the much
simpler form.

Builds on https://github.com/llvm/llvm-project/pull/156477, which
originally included this change as well. This PR makes two changes on
top of it:

* Do not perform the optimization early if it requires adding a mask
check. These make the resulting IR less analyzable.
* Add a new SimplifyCFG option that controls switch-to-arithmetic
conversion separately from switch-to-lookup conversion. Enable the new
flag at the end of the function simplification pipeline. This means that
we attempt the arithmetic conversion before inlining, but avoid it in
the early pipeline, where it may lose information.
2025-10-08 14:24:29 +02:00
Joel E. Denny
6d44b9082e
[LoopUnroll] Skip remainder loop guard if skip unrolled loop (#156549)
The original loop (OL) that serves as input to LoopUnroll has basic
blocks that are arranged as follows:

```
OLPreHeader
OLHeader <-.
...        |
OLLatch ---'
OLExit
```

In this depiction, every block has an implicit edge to the next block
below, so any explicit edge indicates a conditional branch.

Given OL and unroll count N, LoopUnroll sometimes creates an unrolled
loop (UL) with a remainder loop (RL) epilogue arranged like this:

```
,-- ULGuard
|   ULPreHeader
|   ULHeader <-.
|   ...        |
|   ULLatch ---'
|   ULExit
`-> RLGuard -----.
    RLPreHeader  |
,-> RLHeader     |
|   ...          |
`-- RLLatch      |
    RLExit       |
    OLExit <-----'
```

Each UL iteration executes N OL iterations, but each RL iteration
executes 1 OL iteration. ULGuard or RLGuard checks whether the first
iteration of UL or RL should execute, respectively. If so, ULLatch or
RLLatch checks whether to execute each subsequent iteration.

Once reached, OL always executes its first iteration but not necessarily
the next N-1 iterations. Thus, ULGuard is always required before the
first UL iteration. However, when control flows from ULGuard directly to
RLGuard, the first OL iteration has yet to execute, so RLGuard is then
redundant before the first RL iteration.

Thus, this patch makes the following changes:
- Adjust ULGuard to branch to RLPreHeader instead of RLGuard, thus
eliminating RLGuard's unnecessary branch instruction for that path.
- Eliminate the creation of RLGuard phi node poison values. Without this
patch, RLGuard has such a phi node for each value that is defined by any
OL iteration and used in OLExit. The poison value is required where
ULGuard is the predecessor. The poison value indicates that control flow
from ULGuard to RLGuard to Exit has no counterpart in OL because the
first OL iteration must execute either in UL or RL.
- Simplify the CFG by not splitting ULExit and RLGuard because, without
the ULGuard predecessor, the single block can now be a dedicated UL
exit.
- To RLPreHeader, add an `llvm.assume` call that asserts the RL trip
count is non-zero. Without this patch, RLPreHeader is reachable only
when RLGuard guarantees that assertion is true. With this patch, RLGuard
guarantees it only when RLGuard is the predecessor, and the OL structure
guarantees it when ULGuard is the predecessor. If RL itself is unrolled
later, this guarantee somehow prevents ScalarEvolution from giving up
when trying to compute a maximum trip count for RL. That maximum trip
count enables the branch instruction in the final unrolled instance of
RLLatch to be eliminated. Without the `llvm.assume` call, some existing
unroll tests start to fail because that instruction is not eliminated.

The original motivation for this patch is to facilitate later patches
that fix LoopUnroll's computation of branch weights so that they
maintain the block frequency of OL's body (see #135812). Specifically,
this patch ensures RLGuard's branch weights do not affect RL's
contribution to the block frequency of OL's body in the case that
ULGuard skips UL.
2025-10-07 10:45:49 -04:00
Marco Elver
224873d7ac
[AllocToken] Introduce sanitize_alloc_token attribute and alloc_token metadata (#160131)
In preparation of adding the "AllocToken" pass, add the pre-requisite
`sanitize_alloc_token` function attribute and `alloc_token` metadata.

---

This change is part of the following series:
  1. https://github.com/llvm/llvm-project/pull/160131
  2. https://github.com/llvm/llvm-project/pull/156838
  3. https://github.com/llvm/llvm-project/pull/162098
  4. https://github.com/llvm/llvm-project/pull/162099
  5. https://github.com/llvm/llvm-project/pull/156839
  6. https://github.com/llvm/llvm-project/pull/156840
  7. https://github.com/llvm/llvm-project/pull/156841
  8. https://github.com/llvm/llvm-project/pull/156842
2025-10-07 12:51:42 +02:00
Mircea Trofin
a7b38260ce
[SimplifyCFG][profcheck] Profile propagation for indirectbr (#161747)
Handle branch weights for `indirectbr`​ simplification: if we drop branches that aren't taken, we just need to remove the corresponding branch weight (which is presumably 0).

Issue #147390
2025-10-06 12:11:24 -07:00
Yingwei Zheng
5e92e7f4c0
[SCCP] Strengthen two-instruction range checks (#162008)
This patch implements the todo discussed in
https://github.com/llvm/llvm-project/pull/158495#discussion_r2349609838.
It also fixes a regression introduced by
https://github.com/llvm/llvm-project/pull/161000. See also
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2890#discussion_r2404016316.

IR diff: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2892
2025-10-06 07:14:46 +00:00
dianqk
bbdcba9b85
[SimplifyCFG] Fold the contiguous wrapping cases into ICmp. (#161000)
Fixes #157113.

Take the following IR as an example; we know the destination of the `[1,
3]` cases is `%else`.

```llvm
define i32 @src(i8 range(i8 0, 6) %arg) {
  switch i8 %arg, label %else [
    i8 0, label %if
    i8 4, label %if
    i8 5, label %if
  ]

if:
  ret i32 0

else:
  ret i32 1
}
```

We can first try the non-wrapping range for both destinations, but I
don't see how that would be any better.

Proof: https://alive2.llvm.org/ce/z/acdWD4.
2025-10-06 04:56:43 +00:00
Mircea Trofin
5fe6479bf2
[SimplifyCFG][profcheck] Handle branch weights in simplifySwitchLookup (#161739)
The switch becomes a conditional branch, one edge going to what was the default target of the switch, the other to a BB that performs a lookup in a table. The branch weights are accurately determinable from the ones of the switch.

Issue #147390
2025-10-03 21:05:25 -07:00
Mircea Trofin
910e536fb0
[SimplifyCFG][profcheck] Synthesize profile for br (X == 0 | X == 1), T, F1 -> switch (#161549)
We cannot calculate the weights of the switch precisely, but we do know the probability of the default branch. We then split equally the remaining probability over the rest of the cases. If we did nothing, the static estimation could be considerably poorer.



Issue #147390
2025-10-03 20:00:58 -07:00
Joel E. Denny
afb262855e
[LoopPeel] Fix branch weights' effect on block frequencies (#128785)
[LoopPeel] Fix branch weights' effect on block frequencies

This patch implements the LoopPeel changes discussed in [[RFC] Fix Loop
Transformations to Preserve Block
Frequencies](https://discourse.llvm.org/t/rfc-fix-loop-transformations-to-preserve-block-frequencies/85785).

In summary, a loop's latch block can have branch weight metadata that
encodes an estimated trip count that is derived from application profile
data. Initially, the loop body's block frequencies agree with the
estimated trip count, as expected. However, sometimes loop
transformations adjust those branch weights in a way that correctly
maintains the estimated trip count but that corrupts the block
frequencies. This patch addresses that problem in LoopPeel, which it
changes to:

- Maintain branch weights consistently with the original loop for the
sake of preserving the total frequency of the original loop body.
- Store the new estimated trip count in the
`llvm.loop.estimated_trip_count` metadata, introduced by PR #148758.
2025-10-02 16:07:55 +00:00