1312 Commits

Author SHA1 Message Date
Mitchel Dickerson
f932646bf6
[SimplifyCFG][PGO] Add missing overflow check to ConstantFoldTerminator (#178964)
Branch weight metadata can overflow when folding large branch weights.
Updated branch weights to uint64_t, added check for overflow, and then
set branch weights using setFittedBranchWeights to ensure branch weight
metadata is not lost.
2026-02-11 01:17:12 +00:00
dianqk
956770a9cb
[SimplifyCFG] Fix null pointer dereference in foldCondBranchOnValueKnownInPredecessorImpl (#178835) 2026-01-30 18:04:50 +08:00
Matt Arsenault
6934ed51b3
IR: Add !nofpclass metadata (#177140)
This adds the analogous metadata to the nofpclass attribute
to assert values are not a certain set of floating-point classes.
This allows the same information to be expressed if a function
argument is passed indirectly. This matches the bitmask encoding
of nofpclass.

I also think this should be allowed for stores to symmetrically handle
sret, but leave that for later.

Alternatively we could add a more expressive !fprange metadata,
but that would be much more complex. It's useful to match the attribute,
and more annotations can always be added.

Fixes #133560
2026-01-22 20:49:34 +01:00
Mingjie Xu
fac9472593
[IR] Reland Optimize PHINode::removeIncomingValue() and PHINode::removeIncomingValueIf() to use the swapping strategy. (#174274)
Reland #171963, #172639 and #173444, they are reverted in
86b9f90b9574b3a7d15d28a91f6316459dcfa046 because of introducing
non-determinism in compiles.
The non-determinism has been fixed in
9b8addffa70cee5b2acc5454712d9cf78ce45710.
2026-01-04 09:24:53 +08:00
Walter Lee
86b9f90b95
Revert 159f1c048e08a8780d92858cfc80e723c90235e3 (#173893)
This causes non-determinism in compiles.

From nikic: "FYI the non-determinism is also visible on
llvm-opt-benchmark. Maybe repeatedly running test cases from
299446d99f
could reproduce the issue..."

Also revert dependent 796fafeff92fe5d2d20594859e92607116e30a16 and
e135447bda617125688b71d33480d131d1076a72.
2025-12-29 20:23:13 -05:00
Mingjie Xu
159f1c048e
[IR] Optimize PHINode::removeIncomingValue() by swapping removed incoming value with the last incoming value. (#171963)
Current implementation uses `std::copy` to shift all incoming values
after the removed index. This patch optimizes
`PHINode::removeIncomingValue()` by replacing the linear shift of
incoming values with a swap-with-last strategy.

After this change, the relative order of incoming values after removal
is not preserved.

This improves compile-time for PHI nodes with many predecessors.

Depends:
https://github.com/llvm/llvm-project/pull/171955
https://github.com/llvm/llvm-project/pull/171956
https://github.com/llvm/llvm-project/pull/171960
https://github.com/llvm/llvm-project/pull/171962
2025-12-17 19:44:01 +08:00
Alexis Engelke
6813f8f037
[IR] Don't store switch case values as operands
SwitchInst case values must be ConstantInt, which have no use list.
Therefore it is not necessary to store these as Use, instead store them
more efficiently as a simple array of pointers after the uses, similar
to how PHINode stores basic blocks.

After this change, the successors of all terminators are stored
consecutively in the operand list. This is preparatory work for
improving the performance of successor access.

Add new C API functions so that switch case values remain accessible
from bindings for other languages.

While this could also be achieved by merely changing the order of
operands (i.e., first all successors, then all constants), doing so
would increase the asymptotic runtime of addCase from O(1) to O(n)
(i.e., adding n cases would be O(n^2)), because it would need to shift
all constants by one slot. Having null/invalid operands is also a bad
idea and would cause much more breakage.

Pull Request: https://github.com/llvm/llvm-project/pull/170984
2025-12-11 18:38:39 +01:00
Kunqiu Chen
fa2eabd770
[SimplifyCFG] Hoist common code for switch multi-case destinations (#165700)
Previously, hoistCommonCodeFromSuccessors did not support hoisting
common code for multi-case destinations of `switch`.

However, if all the predecessors of a given Succ are the same (i.e.,
multi-case destination), it is safe to hoist the common code from Succ
to Pred, which is what this PR does.

See discussion
https://github.com/llvm/llvm-project/pull/165570#discussion_r2473290327.
Alive2 proof: https://alive2.llvm.org/ce/z/cYuczq
Optimization Impact:
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/3003
2025-12-06 14:44:58 +08:00
Lucie Choi
9ffd2e40c1
[SimplifyCFG] Fix SimplifyCFG pass to skip folding when both blocks contain convergence loop/entry intrinsics. (#166452)
Fixes a bug https://github.com/llvm/llvm-project/issues/165642. [Similar
fix](https://github.com/llvm/llvm-project/pull/165643) is being made in
`IndVarSimplify` pass to account for convergence tokens.

[LLVM
Spec](https://llvm.org/docs/ConvergentOperations.html#llvm-experimental-convergence-loop)
states that only a single loop / entry convergence token can be included
in a basic block.

This PR fixes the issue in `SimplifyCFG` pass so that when a basic block
and its predecessor both contain such convergence intrinsics, it skips
merging the two blocks.
2025-11-30 06:57:06 +09:00
Yingwei Zheng
76c69ca29c
[ValueTracking] Bail out on non-immediate constant expressions (#168084)
In https://github.com/llvm/llvm-project/pull/165748 constant expressions
were allowed in `collectPossibleValues` because we are still using
insertelement + shufflevector idioms to represent a scalable vector
splat. However, it also accepts some unresolved constants like ptrtoint
of globals or pointer difference between two globals. Absolutely we can
ask the user to check this case with the constant folding API. However,
since we don't observe the real-world usefulness of handling constant
expressions, I decide to be more conservative and only handle immediate
constants in the helper function. With this patch, we don't need to
touch the SimplifyCFG part, as the values can only be either ConstantInt
or undef/poison values (NB: switch on undef condition is UB).

Fix the miscompilation reported by
https://github.com/llvm/llvm-project/pull/165748#issuecomment-3532245218
2025-11-15 21:14:29 +08:00
Kunqiu Chen
a0e222f7c7
[SimplifyCFG] Simplify uncond br with icmp & select (#165580)
Previously, SimplifyCFG only simplified unconditional branches when they
met a pattern (`swicth` -> `icmp` -> `br` -> `phi`) as follows:
```LLVM
   switch i8 %A, label %DEFAULT [ i8 1, label %end    i8 2, label %end ]
DEFAULT:
   %tmp = icmp eq i8 %A, 92
   br label %end
end:
   ... = phi i1 [ true, %entry ], [ %tmp, %DEFAULT ], [ true, %entry ]
```

This PR supports a new and more generic pattern (`switch` -> `icmp` ->
`select` -> `br` -> `phi` ) to simplify unconditional branches as
follows:
```LLVM
; BEFORE
case1:
  switch i32 %x, label %DEFAULT [ 
    i32 0, label %end    
    i32 1, label %case2 
  ]
case2:
  br label %end
DEFAULT:
  %tmp = icmp eq i32 %x, 2
  %val = select i1 %tmp, i32 V3, i32 V4
  br label %end
end:
  ... = phi i32 [ V1, %case1 ], [ V2, %case2 ], [ %val, %DEFAULT ]
```

We prefer to split the edge to 'end' so that there are TWO entries of
V3/V4 to the PHI, merging the icmp & select into the switch, as follows:
```LLVM
; AFTER
case1:
  switch i32 %x, label %DEFAULT [
    i32 0, label %end
    i32 1, label %case2
    i32 2, label %case3
  ]
case2:
  br label %end
case3:
  br label %end
DEFAULT:
  br label %end
end:
  ... = phi i32 [ V1, %case1 ], [ V2, %case2 ], [ V3, %case3 ], [ V4, %DEFAULT]
```

Alive2 Proof: https://alive2.llvm.org/ce/z/jYHM4f
Promising Optimization Impact:
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/3006
2025-11-08 20:52:19 +08:00
Mircea Trofin
f76c132230
[SimplifyCFG] Fix weight calculation for simplifySwitchOfPowersOfTwo (#165956)
Continued from #165804

This maintains the BFI of the default branch. Originally `10/63`​, post-pass, it ends up being `5/63 + 58/63 * 5/58`​(first term is from `PROF`​, second is the probability of going to the switch lookup times the probability, there, of taking the default branch)

Issue #147390
2025-11-05 12:02:33 -08: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
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
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
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
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
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
Antonio Frighetto
29346628e9
[SimplifyCFG] Precommit tests for PR161807 (NFC) 2025-10-27 08:51:20 +01:00
paperchalice
f8b81b45ba
[test][Transforms] Remove unsafe-fp-math uses part 3 (NFC) (#164787)
Post cleanup for #164534.
2025-10-24 18:49:45 +08:00
paperchalice
3656f6f226
[CodeGen] Remove -enable-unsafe-fp-math option (#164559)
Hope this can unblock #105746.
2025-10-22 15:40:31 +08:00
Nikita Popov
573ca36753
[IR] Replace alignment argument with attribute on masked intrinsics (#163802)
The `masked.load`, `masked.store`, `masked.gather` and `masked.scatter`
intrinsics currently accept a separate alignment immarg. Replace this
with an `align` attribute on the pointer / vector of pointers argument.

This is the standard representation for alignment information on
intrinsics, and is already used by all other memory intrinsics. This
means the signatures now match llvm.expandload, llvm.vp.load, etc.
(Things like llvm.memcpy used to have a separate alignment argument as
well, but were already migrated a long time ago.)

It's worth noting that the masked.gather and masked.scatter intrinsics
previously accepted a zero alignment to indicate the ABI type alignment
of the element type. This special case is gone now: If the align
attribute is omitted, the implied alignment is 1, as usual. If ABI
alignment is desired, it needs to be explicitly emitted (which the
IRBuilder API already requires anyway).
2025-10-20 08:50:09 +00: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
Marco Elver
6359980f5b
[AllocToken, Clang] Implement TypeHashPointerSplit mode (#156840)
Implement the TypeHashPointerSplit mode: This mode assigns a token ID
based on the hash of the allocated type's name, where the top half
ID-space is reserved for types that contain pointers and the bottom half
for types that do not contain pointers.

This mode with max tokens of 2 (`-falloc-token-max=2`) may also
be valuable for heap hardening strategies that simply separate pointer
types from non-pointer types.

Make it the new default mode.

Link: https://discourse.llvm.org/t/rfc-a-framework-for-allocator-partitioning-hints/87434

---

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-08 21:58:37 +02: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
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
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
Nikita Popov
63ca8483d0
[IR] Introduce !captures metadata (#160913)
This introduces `!captures` metadata on stores, which looks like this:

```
store ptr %x, ptr %y, !captures !{!"address", !"read_provenance"}
```

The semantics are the same as replacing the store with a call like this:
```
call void @llvm.store(ptr captures(address, read_provenance) %x, ptr %y)
```

This metadata is intended for annotation by frontends -- it's not
something we can feasibly infer at this point, as it would require
analyzing uses of the pointer stored in memory.

The motivating use case for this is Rust's `println!()` machinery, which
involves storing a reference to the value inside a structure. This means
that printing code (including conditional debugging code), can inhibit
optimizations because the pointer escapes. With the new metadata we can
annotate this as a read-only capture, which has less impact on
optimizations.
2025-10-01 08:58:47 +02:00
Antonio Frighetto
5ff9f7b886
[SimplifyCFG] Ensure selects have not been constant folded in foldSwitchToSelect
Make sure selects do exist prior to assigning weights to edges.

Fixes: https://github.com/llvm/llvm-project/issues/161137.
2025-09-29 14:36:56 +02:00
Mircea Trofin
d2f14bcaa5
[profcheck][SimplifyCFG] Propagate !prof from switch to select (#159645)
Propagate `!prof`​ from `switch`​ instructions.

Issue #147390
2025-09-26 14:16:21 -07:00
Alexander Richardson
d03bfc6c0a
[SimplifyCFG] Avoid using isNonIntegralPointerType()
This is an overly broad check, the transformation made here can be done
safely for pointers with index!=repr width. This fixes the codegen
regression introduced by https://github.com/llvm/llvm-project/pull/105735
and should be beneficial for AMDGPU code-generation once the datalayout
there no longer uses the overly strict `ni:` specifier.

Reviewed By: arsenm

Pull Request: https://github.com/llvm/llvm-project/pull/159890
2025-09-23 11:23:19 -07:00
Alexander Richardson
dde000a7d6
[DataLayout][LangRef] Split non-integral and unstable pointer properties
This commit adds finer-grained versions of isNonIntegralAddressSpace() and
isNonIntegralPointerType() where the current semantics prohibit
introduction of both ptrtoint and inttoptr instructions. The current
semantics are too strict for some targets (e.g. AMDGPU/CHERI) where
ptrtoint has a stable value, but the pointer has additional metadata.
Currently, marking a pointer address space as non-integral also marks it
as having an unstable bitwise representation (e.g. when pointers can be
changed by a copying GC). This property inhibits a lot of
optimizations that are perfectly legal for other non-integral pointers
such as fat pointers or CHERI capabilities that have a well-defined
bitwise representation but can't be created with only an address.

This change splits the properties of non-integral pointers and allows
for address spaces to be marked as unstable or non-integral (or both)
independently using the 'p' part of the DataLayout string.
A 'u' following the p marks the address space as unstable and specifying
a index width != representation width marks it as non-integral.
Finally, we also add an 'e' flag to mark pointers with external state
(such as the CHERI capability validity) state. These pointers require
special handling of loads and stores in addition to being non-integral.

This does not change the checks in any of the passes yet - we
currently keep the existing non-integral behaviour. In the future I plan
to audit calls to DL.isNonIntegral[PointerType]() and replace them with
the DL.mustNotIntroduce{IntToPtr,PtrToInt}() checks that allow for more
optimizations.

RFC: https://discourse.llvm.org/t/rfc-finer-grained-non-integral-pointer-properties/83176

Reviewed By: nikic, krzysz00

Pull Request: https://github.com/llvm/llvm-project/pull/105735
2025-09-23 11:16:47 -07:00
Gábor Spaits
0a47e8c2fc
Reland [BasicBlockUtils] Handle funclets when detaching EH pad blocks (#159379)
Fixes #148052 .

Last PR did not account for the scenario, when more than one instruction
used the `catchpad` label.
In that case I have deleted uses, which were already "choosen to be
iterated over" by the early increment iterator. This issue was not
visible in normal release build on x86, but luckily later on the address
sanitizer build it has found it on the buildbot.

Here is the diff from the last version of this PR: #158435
```diff
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 91e245e5e8f5..1dd8cb4ee584 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -106,7 +106,8 @@ void llvm::detachDeadBlocks(ArrayRef<BasicBlock *> BBs,
       // first block, the we would have possible cleanupret and catchret
       // instructions with poison arguments, which wouldn't be valid.
       if (isa<FuncletPadInst>(I)) {
-        for (User *User : make_early_inc_range(I.users())) {
+        SmallPtrSet<BasicBlock *, 4> UniqueEHRetBlocksToDelete;
+        for (User *User : I.users()) {
           Instruction *ReturnInstr = dyn_cast<Instruction>(User);
           // If we have a cleanupret or catchret block, replace it with just an
           // unreachable. The other alternative, that may use a catchpad is a
@@ -114,33 +115,12 @@ void llvm::detachDeadBlocks(ArrayRef<BasicBlock *> BBs,
           if (isa<CatchReturnInst>(ReturnInstr) ||
               isa<CleanupReturnInst>(ReturnInstr)) {
             BasicBlock *ReturnInstrBB = ReturnInstr->getParent();
-            // This catchret or catchpad basic block is detached now. Let the
-            // successors know it.
-            // This basic block also may have some predecessors too. For
-            // example the following LLVM-IR is valid:
-            //
-            //   [cleanuppad_block]
-            //            |
-            //    [regular_block]
-            //            |
-            //   [cleanupret_block]
-            //
-            // The IR after the cleanup will look like this:
-            //
-            //   [cleanuppad_block]
-            //            |
-            //    [regular_block]
-            //            |
-            //     [unreachable]
-            //
-            // So regular_block will lead to an unreachable block, which is also
-            // valid. There is no need to replace regular_block with unreachable
-            // in this context now.
-            // On the other hand, the cleanupret/catchret block's successors
-            // need to know about the deletion of their predecessors.
-            emptyAndDetachBlock(ReturnInstrBB, Updates, KeepOneInputPHIs);
+            UniqueEHRetBlocksToDelete.insert(ReturnInstrBB);
           }
         }
+        for (BasicBlock *EHRetBB :
+             make_early_inc_range(UniqueEHRetBlocksToDelete))
+          emptyAndDetachBlock(EHRetBB, Updates, KeepOneInputPHIs);
       }
     }
```
2025-09-19 17:00:17 -07:00
Gábor Spaits
88c64f76ed
Revert "Reland "[BasicBlockUtils] Handle funclets when detaching EH p… (#159292)
…ad blocks" (#158435)"

This reverts commit 41cef78227eb909181cb9360099b2d92de8d649f.
2025-09-17 09:44:17 +00:00
Gábor Spaits
41cef78227
Reland "[BasicBlockUtils] Handle funclets when detaching EH pad blocks" (#158435)
When removing EH Pad blocks, the value defined by them becomes poison. These poison values are then used by `catchret` and `cleanupret`, which is invalid. This commit replaces those unreachable `catchret` and `cleanupret` instructions with `unreachable`.
2025-09-17 09:47:29 +02:00
William Moses
c44e015b49
[SimplifyCFG] Refine metadata handling during instruction hoisting (#158448)
Co-authored-by: Nikita Popov <npopov@redhat.com>
2025-09-14 22:50:42 -05:00
Arthur Eubanks
b30c29c893
Revert "[BasicBlockUtils] Handle funclets when detaching EH pad blocks" (#158364)
Reverts llvm/llvm-project#157363

Causes crashes, see
https://github.com/llvm/llvm-project/pull/157363#issuecomment-3286783238
2025-09-14 19:58:48 +00:00
Mircea Trofin
9e33997242
[IR] Add MD_prof to the Keep list of dropUBImplyingAttrsAndMetadata (#154635)
`MD_prof` is safe to keep when e.g. hoisting instructions.

Issue #147390
2025-09-12 15:04:38 -07:00
Mircea Trofin
889c289a40
[SimplfyCFG] Set MD_prof for select used for certain conditional simplifications (#154426)
There’s a pattern where a branch is conditioned on a conjunction or disjunction that ends up being modeled as a `select`​ where the first operand is set to `true`​ or the second to `false`​. If the branch has known branch weights, they can be copied to the `select`​. This is worth doing in case later the `select`​ gets transformed to something else (i.e. if we know the profile, we should propagate it).

Issue #147390
2025-09-12 07:50:44 -07:00
Gábor Spaits
43561ad204
[BasicBlockUtils] Handle funclets when detaching EH pad blocks (#157363)
Fixes #148052 .

When removing EH Pad blocks, the value defined by them becomes poison. These poison values are then used by `catchret` and `cleanupret`, which is invalid. This commit replaces those unreachable `catchret` and `cleanupret` instructions with `unreachable`.
2025-09-11 22:52:16 +02:00
Mircea Trofin
3097688a47
[SimplifyCFG] Set branch weights when merging conditional store to address (#154841) 2025-09-11 13:21:59 -07:00
Jessica Del
89d86b626c
SimplifyCFG: Enable switch replacements in more cases (#156477)
In some cases, we can replace a switch with simpler instructions or a
lookup table.
For instance, if every case results in the same value, we can simply
replace the switch
with that single value.

However, lookup tables are not always supported. 
Targets, function attributes and compiler options can deactivate lookup
table creation.
Currently, even simpler switch replacements like the single value
optimization do not
get applied, because we only enable these transformations if lookup
tables are enabled.

This PR enables the other kinds of replacements, even if lookup tables
are not supported.
First, it checks if the potential replacements are lookup tables.
If they are, then check if lookup tables are supported and whether to
continue.
If they are not, then we can apply the other transformations.

Originally, lookup table creation was delayed until late stages of the
compilation pipeline, because
it can result in difficult-to-analyze code and prevent other
optimizations.
As a side effect of this change, we can also enable the simpler
optimizations much earlier in the
compilation process.
2025-09-09 16:24:52 +02:00