13832 Commits

Author SHA1 Message Date
Justin Fargnoli
45412b6790
[LoopUnrollPass] Indent LLVM_DEBUG() messages based on our depth in the tryToUnrollLoop() call graph (#178945)
Unify the ad-hoc use of whitespace in `LLVM_DEBUG()` messages. 

This approach should also make it easier to see which loop debug
messages correspond to and which part of the loop unrolling heuristics
each message corresponds to.
2026-02-11 17:59:42 +00:00
Florian Hahn
54177e95d1
[Matrix] Use tiled loops automatically for large kernels. (#179325)
Update LowerMatrixIntrinsics to use tiled loops automatically in for
larger matrixes. The fully unrolled codegen creates a huge amount of
code, which performs noticably worse then the tiled loop nest variant.

We new try to estimate the number of instructions needed for the
multiply, and if it is too large, tiled loops are used. The current
threshold is anything roughly larger than 6x6x6 double multiply.

Eventually I think we want to only generate tiled loops. This patch is a
first step, trying to opt in for cases where we know it is beneficial.
Checked on AArch64, but should help on other architectures similarly,
and also drastically reduce binary size + compile time.

PR: https://github.com/llvm/llvm-project/pull/179325
2026-02-11 15:36:34 +00:00
Anshil Gandhi
4f551b55ae
[IndVarSimplify] Add safety check for getTruncateExpr in genLoopLimit (#172234)
getTruncateExpr may not always return a SCEVAddRecExpr when truncating
loop bounds. Add a check to verify the result type before casting, and
bail out of the transformation if the cast would be invalid.

This prevents potential crashes from invalid casts when dealing with
complex loop bounds.

Co-authored by Michael Rowan

Resolves [#153090](https://github.com/llvm/llvm-project/issues/153090)
2026-02-11 10:08:41 +00:00
Manasij Mukherjee
0fdf9b9676
[ConstraintElim] Infer linear constraints from udiv and urem (#180689)
urem x, n: result < n (remainder is always less than divisor)
urem x, n: result <= x (remainder is at most the dividend)
udiv x, n: result <= x (quotient is at most the dividend)

https://alive2.llvm.org/ce/z/ezzsjQ
2026-02-10 22:25:13 +08:00
Aiden Grossman
ec059d81aa
[DSE] Handle variable offsets with sized dead_on_return (#180364)
With a sized dead_on_return, we need to not eliminate stores if there
are to a pointer with a variable offset from the underlying object
marked dead_on_return. This manifested as an assertion failure as
BaseValue/V ended up not being equal. It's possible we could do a range
analysis to try and prove the variable offset stays within bounds, but
this case seems to come up relatively rarely (only reproducible with a
UBSan build of LLVM) and is probably not worth the compile time.

Fixes #180361.
2026-02-07 11:43:56 -08:00
Hongyu Chen
8b5e95b1fd
[InferAddressSpaces] Initialize op(generic const, generic const, ...) -> generic (#172143)
Fixes #171890
If the pointer operands of an instruction are all constants with generic
AS, we always infer the AS of the instruction as uninitialized finally.
And the rewrite process will skip cloning the instruction, producing
invalid IR.
This patch fixes it by inferring the AS of this kind of instruction as
flat. Maybe we can fold the operator with all constants to get better
performance, but I think this case is rare in the real world.
2026-02-08 01:20:19 +08:00
Florian Hahn
e8908215de
[LSR] Support SCEVPtrToAddr in SCEVDbgValueBuilder.
Allow SCEVPtrToAddr as cast in assertion in SCEVDbgValueBuilder.
SCEVPtrToAddr is handled similarly to SCEVPtrToInt.

Fixes a crash with debug info after bd40d1de9c9ee, which started to
generate ptrtoaddr instead of ptrtoint expressions.
2026-02-07 14:02:45 +00:00
int-zjt
0b3934d677
[SROA] Avoid redundant .oldload generation when memset fully covers a partition (#179643)
In our internal (ByteDance) builds we frequently hit very large
`DeadPhiWeb`s that cause serious compile-time slowdowns, especially in
some auto-generated code where a single file can take 20+ minutes to
compile. There were previous attempts to reduce `DeadPhiWeb` in
`InstCombine` (e.g. llvm/llvm-project#108876 and
llvm/llvm-project#158057), but in our workload we still see a lot of
time spent later in the pipeline (notably `JumpThreading` and
`CorrelatedValuePropagation`).

After digging into our cases, a big chunk of the `DeadPhiWeb` comes from
SROA rewriting `memset`s. We often end up with patterns like:
```
%.sroa.xxx.oldload = load <ty>, ptr %.sroa.xxx
%unused = ptrtoint ptr %.sroa.xxx.oldload to i64   ; or a bitcast-like use
store <ty> <new_value>, ptr %.sroa.xxx
```
Even if `%unused` is cleaned up by later DCE-style passes, the
load/store shape can still make `PromoteMem2Reg` conservatively treat
many blocks as live-in when computing IDF. With cyclic CFGs this can
easily create large, sticky dead phi webs, and the rest of the pipeline
pays for it.

The core issue is that `visitMemSetInst` was using the slice’s original
offsets (`BeginOffset`/`EndOffset`) when deciding whether it needs to
merge with an `.oldload` to preserve bytes not written by the `memset`.
First, there was a typo in the original condition (`EndOffset !=
NewAllocaBeginOffset` instead of `EndOffset != NewAllocaEndOffset`),
which effectively made the check always true and forced the merge path
in most cases. Second, even if the typo is fixed, comparing the original
slice range against the partition bounds is still too strict: cases
where the `memset` contains the partition (e.g. a large `memset` over
the whole alloca while the partition is just a subrange) would still be
misclassified as requiring an `.oldload`. Both issues lead to many
redundant loads and downstream dead phi webs.

This change switches the check to use the already-computed intersection
offsets (`NewBeginOffset`/`NewEndOffset`) against the partition bounds,
so we only generate `.oldload` when the `memset` actually writes only
part of the partition:
```diff
-      if (IntTy && (BeginOffset != NewAllocaBeginOffset ||
-                    EndOffset != NewAllocaBeginOffset)) {
+      if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
+                    NewEndOffset != NewAllocaEndOffset)) {
    ; emit oldload + insertInteger merge
  }
```
In our workload this cuts down a lot of pointless `.oldload`s and helps
reduce the size of dead phi webs seen after `mem2reg`, improving compile
time without changing semantics (partial overwrites still merge, full
overwrites don’t).
2026-02-05 09:51:55 +08:00
jeanPerier
2b887ce604
[SimpleLoopUnswitch][NFC] move quadratic asserts under EXPENSIVE_CHECKS (#144887)
Three asserts/checks in SimpleLoopUnswitchPass are quite expensive on IR
containing many deeply nested loop nests.
Their cost is not linear with the number of loop nests and these asserts
quickly become the most significant cost of the whole compilation.

This patch move some of the asserts under `EXPENSIVE_CHECKS` and leaves the one
line 1080 unguarded. 

This problem was exposed with flang because of Fortran
multidimensional arrays and array expressions. In some programs, half of the end to
end compilation time was spent in those asserts.
2026-02-04 09:45:26 +01:00
Eli Friedman
a2c7c6032f
Revert "[SeparateConstOffsetFromGEP] Decompose constant xor operand if possible" (#179339)
A miscompile was found (see #175724), and it's complicated to fix. We're
going to revert for now, and look at reimplementing a fixed version
later.
2026-02-03 17:03:14 +05:30
Steffen Larsen
c7408d17fa
[AMDGPU][SROA] Unify cast chain implementations (#177945)
The AMDGPU promote alloca pass is missing a conversion link when casting
between vectors of pointers and pointers or vectors of pointers with
different number of elements. This causes codegen to crash due to
invalid casts being generated. To address this, this commit adds the
missing conversion link.

In addition to this, the commit moves the common load/store cast logic
into a new function `createLoadStoreCastChain`.

---------

Signed-off-by: Steffen Holst Larsen <HolstLarsen.Steffen@amd.com>
Co-authored-by: Steffen Holst Larsen <HolstLarsen.Steffen@amd.com>
2026-02-03 11:12:02 +00:00
Justin Fargnoli
7889f729ac
[LoopUnroll] Remove preceding whitespace in loop peeling optimization remark (#178951) 2026-02-02 09:32:57 -08:00
Nikita Popov
fd1e37b653
[IR] Remove Before argument from splitBlock APIs (NFC) (#179195)
We never need to use this conditionally (and it doesn't really make
sense, as the behavior is substantially different). Force the use of
separate APIs instead of a boolean argument.
2026-02-02 10:50:58 +00:00
Justin Fargnoli
91856eaf5a
[LoopUnrollPass] Add comment explaining the use of UP.DefaultUnrollRuntimeCount in shouldPartialUnroll (NFC) (#178817) 2026-01-30 10:30:29 -08:00
Justin Fargnoli
3f67996201
[LoopUnrollPass] Fix spelling mistake in computeUnrollCount description (NFC) (#178816) 2026-01-30 10:16:06 -08:00
Justin Fargnoli
7710d213e9
[LoopUnrollPass] Remove unhelpful comment in shouldPragmaUnroll (NFC) (#178814)
The note the comment is making should be obvious based on the structure
of the pass. Additionally, it is grammatically incorrect and has
spelling errors.
2026-01-30 10:15:19 -08:00
Marcos Maronas
1dbc70542c
[SimplifyCFG] Increase iterative simplification convergence limit. (#178406)
a9b0776a81
added an assertion to avoid infinite loops. However, the limit seems
arbitrary, there is no justification for it neither in the code nor in
the commit message, so I think this can be increased.
2026-01-30 14:46:07 +00:00
Antonio Frighetto
034e5d6f86
[MemCpyOpt] Extend performMemCpyToMemSetOptzn to partially memset'd region
While doing memset-to-memcpy forwarding, take into account memset
that covers memory regions from a given offset, and the leading
bytes of such a region are undef.

Fixes: https://github.com/llvm/llvm-project/issues/172326.
2026-01-30 10:09:08 +01:00
Yingying Wang
40ebbb6362
[LoopInterchange] Initialize new_var to InitValue on first iteration (#178370)
Fixed a bug found during testing:
- If it is the first iteration, `new_var` should be initialized to
'InitValue'.
2026-01-29 21:36:46 +09:00
Ramkumar Ramachandra
d3b3940a71
[ConstraintElim] Use try_emplace to improve code (NFC) (#178186) 2026-01-27 14:13:39 +00:00
Jameson Nash
a460c8e8da
[NFCI][SROA] reduce calls to getAllocatedType() (#177437)
Replace repeated calls with getAllocationSize() and cached NewAllocaTy.
In AllocaSliceRewriter, the allocated type is already stored in the
NewAllocaTy member variable and now passed directly there. This change
replaces the remaining direct calls to `NewAI.getAllocatedType()` with
the cached NewAllocaTy to simplify and DRY the code.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 00:03:55 -05:00
Jameson Nash
cbb2aa1704
[NFCI] Replace getAllocatedType with tracked value type in RewriteStatepointsForGC (#177440)
The allocas in RewriteStatepointsForGC are created with
LiveValue->getType(), so we can use Def->getType() (which equals the
alloca's type) instead of querying getAllocatedType().

Changes:
- Load instructions now use Def->getType() directly
- The ToClobber vector now stores (Type*, AllocaInst*) pairs to track
the original value's type for creating null constants

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 22:43:19 -05:00
Ramkumar Ramachandra
e516dd1bf2
[ConstraintElim] Strip IsKnownNonNegative (NFC) (#177993)
The IsKnownNonNegative field is redundant, as the use of ValueTracking's
isKnownNonNegative subsumes this.

Proof: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/3390
2026-01-26 19:57:13 +00:00
Aiden Grossman
6277359e5a [DSE] Mark BaseValue Variable [[maybe_unused]]
It is only used within an assertion but we cannot inline the call as it
is needed to get the offset from the base pointer for the function to
work.
2026-01-23 21:39:20 +00:00
Aiden Grossman
fbc970bb0e Revert "[LLVM] Update assert to removed unused variable warning. (#177632)"
This reverts commit fdb05bbf62b8d4fc8dc7ce1f1cfa570f3265a8ae.

This was causing failures in release-mode builds because the
GetPointerBaseWithConstantOffset call would never be run which leads to
ValueOffset being uninitialized and thus the behavior of the function is
unpredictable.
2026-01-23 21:39:20 +00:00
cmtice
fdb05bbf62
[LLVM] Update assert to removed unused variable warning. (#177632)
Remove the variable definition and move the function call directly into
the assert statement. Otherwise builds with -Werror that don't use
asserts would fail.
2026-01-23 19:03:09 +00:00
Justin Fargnoli
7c8a13ab79
[LoopPeel] change peelLoop's return type from bool to void (#177488) 2026-01-23 10:49:03 -08:00
Aiden Grossman
0145a643cc
[DSE] Make DSE eliminate stores to objects with a sized dead_on_return
dead_on_return is made optionally sized in #171712. This patch adds
handling in DSE so that we can actually eliminate stores to pointer
parameters marked with a sized dead_on_return attribute. We do not
eliminate stores where the store may overlap with bytes that are not
known to be dead after return.

Reviewers: nikic, antoniofrighetto, alinas, aeubanks

Pull Request: https://github.com/llvm/llvm-project/pull/173694
2026-01-23 07:40:44 -08:00
Nikolas Klauser
17a17fa81c
[PredicateInfo] Extract information from assume operand bundles (#177349) 2026-01-23 15:20:39 +01: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
Arthur Eubanks
f8c4974963
Revert "[MemCpyOpt] support offset slices for performStackMoveOptzn and processMemCpy (#176436)" (#177482)
This reverts commit 019eb855dd6a18a8f7ae5dd86abf6bc3ad0d9fa4.

Causes miscompiles, see original PR and #177185

Fixes https://github.com/llvm/llvm-project/issues/177185
2026-01-22 22:34:35 +00: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
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
Jameson Nash
d10b2b566a
[NFCI] replace getValueType with new getGlobalSize query (#177186)
Returns uint64_t to simplify callers. The goal is eventually replace
getValueType with this query, which should return the known minimum
reference-able size, as provided (instead of a Type) during create.
Additionally the common isSized query would be replaced with an
isExactKnownSize query to test if that size is an exact definition.
2026-01-22 13:55:53 -05:00
Yingying Wang
ee95ebe396
[LoopInterchange] Support the inner-loop reduction via Reduction2Mem (#172970)
Following our
[discussion](https://discourse.llvm.org/t/rfc-plan-to-improve-loopinterchange-by-undoing-simple-reductions/89071),
I ported GCC’s undo_simple_reduction into LLVM.

**Key changes**

- Implement an Reduction2Memory step in LoopInterchange to support the
reduction in the inner loop.
- The feature is behind an option `-loop-interchange-reduction-to-mem`
and is OFF by default. With the feature off, the pass behaves as before
(minimal impact).
- Add a regression test.

**Validation & performance**

- No compile or semantic errors observed on SPEC2006 and SPEC2017 with
the new feature enabled for validation.
- With options: `-da-disable-delinearization-checks` and
`-loop-interchange-reduction-to-mem`
  - SPEC2006 410.bwaves on x86 (Intel i9-11900K, Rocket Lake): **+6%**
  - SPEC2017 603.bwaves_s on x86 (Intel i9-11900K, Rocket Lake): **+6%**
  - SPEC2006 410.bwaves on SpacemiT Key Stone K1: **+29%**
  - SPEC2006 410.bwaves on KMH RTL: **+56%**
  - SPEC2017 603.bwaves_s on KMH RTL: **+24%**

**Note**

- Reduction2Memory only runs when legality and profitability checks
indicate the interchange will actually be performed. If interchange is
illegal or not profitable, no reduction2mem is applied.

---------

Co-authored-by: ict-ql <168183727+ict-ql@users.noreply.github.com>
Co-authored-by: Lin Wang <wanglulin@ict.ac.cn>
Co-authored-by: Ryotaro Kasuga <kasuga.ryotaro@fujitsu.com>
2026-01-22 13:07:52 +01:00
Aiden Grossman
e2d7cd685d
[IR] Make dead_on_return attribute optionally sized
This patch makes the dead_on_return parameter attribute optionally require a number
of bytes to be passed in to specify the number of bytes known to be dead
upon function return/unwind. This is aimed at enabling annotating the
this pointer in C++ destructors with dead_on_return in clang. We need
this to handle cases like the following:

```
struct X {
  int n;
  ~X() {
    this[n].n = 0;
  }
};
void f() {
  X xs[] = {42, -1};
}
```

Where we only certain that sizeof(X) bytes are dead upon return of ~X.
Otherwise DSE would be able to eliminate the store in ~X which would not
be correct.

This patch only does the wiring within IR. Future patches will make
clang emit correct sizing information and update DSE to only delete
stores to objects marked dead_on_return that are provably in bounds of
the number of bytes specified to be dead_on_return.

Reviewers: nikic, alinas, antoniofrighetto

Pull Request: https://github.com/llvm/llvm-project/pull/171712
2026-01-21 08:22:05 -08:00
Jameson Nash
2458387ac1
[NFC] replace getValueType with more specific getFunctionType (#177175)
When trivially valid already, use the more specific method, instead of
casting the result of the less specific method.
2026-01-21 10:30:09 -05:00
Jameson Nash
019eb855dd
[MemCpyOpt] support offset slices for performStackMoveOptzn and processMemCpy (#176436)
In particular, support offset of src, since offset of dest will be a
followup change when dest is allowed to be not full-sized with copy.

Extracted from https://github.com/llvm/llvm-project/pull/150792
2026-01-19 16:45:31 -05:00
Jameson Nash
ba2bd3fbba
Use AllocaInst::getAllocationSize instead of manual size calculations (#176486)
Replace patterns that manually compute allocation sizes by multiplying
getTypeAllocSize(getAllocatedType()) by the array size with calls to the
getAllocationSize(DL) API, which handles this correctly and concisely,
returning nullopt for VLAs.

This fixes several places that were not accounting for array allocations
when computing sizes, simplifies code that was doing this manually, and
adds some explicit isFixed checks where implied convert was being used.

This PR is because now that we have opaque pointers, I hate that some
AllocaInst still has type information being consumed by some passes
instead of just using the size, since passes rarely handle that type
information well or correctly. I hope this will grow into a sequence of
commits to slowly eliminate uses of getAllocatedType from AllocaInst.
And similarly later to remove type information from GlobalValue too (it
can be replaced with just dereferenceable bytes, similar to arguments).

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:55:52 -05:00
Alexis Engelke
284ef1b4ac
[Support][NFCI] Store DomTree children as linked list (#176409)
Reduce the size of a DomTreeNodeBase from 80 to 56 bytes by not storing
the children in a SmallVector. Instead, store children as forward-linked
list. This also avoids extra allocations for nodes with many children.
Additionally, DomTreeNodeBase is now trivially destructible.

A lot of code depends on the order of nodes in the dominator tree, so
make sure that the order is the same when inserting nodes. (Not having
to do this would save 8 bytes per node.)

NewGVN uses the order of nodes in the dominator tree in a way that is
not entirely clear to me (https://reviews.llvm.org/D28129). I kept the
semantics as, but now this is the only external user of
addChild/removeChild, which actually should be private.

https://llvm-compile-time-tracker.com/compare.php?from=263802c56b4db3fc9b6ed9fd313499cb03ca44da&to=43e0c0c5b663b3a4067252fc0addbaccefd0014d&stat=instructions:u
2026-01-17 21:09:49 +01:00
Andreas Jonson
70e6e17675
[InferAlign] Eliminate trunc ptr to log2(align) pattern (#176562)
Fold trunc ptrtoint/ptrtoaddr to N -> 0 when all N bits are zero due to
alignment.

To Avoid regression due to icmp_ne(and(x,1),0) -> trunc(x) fold
https://github.com/llvm/llvm-project/issues/172888

Proof: https://alive2.llvm.org/ce/z/ZS-QJL
2026-01-17 17:00:07 +01:00
Oxygen
9671aae8d5
[DSE][Verifier] Respect the calling convention of the function specified by "alloc-variant-zeroed" (#175911)
Require that the calling convention between the zeroed and non-zeroed
variants is the same, and set it appropriate in the DSE transform.
2026-01-16 15:45:40 +00:00
Jameson Nash
94ffc754d2
[MemCpyOpt] keep src/dest alloca ordering (#176012)
Rather than test dominator of every use, just check which of src or dest
is first, and use that insert location. This minimizes unnecessary
dominator queries while also helping to preserve the order of allocas
(for better code readability / diff).

Extracted from PR optimization improvement series at
https://github.com/llvm/llvm-project/pull/150792
2026-01-14 15:18:37 -05:00
Jameson Nash
d275182924
[MemCpyOpt] allow memcpy-to-memcpy optimization with smaller dest than src (#176010)
Resize the alloca if needed to a common size, as long as the dest was
still fully initialized by the copy.

Extracted from PR optimization improvement series at
https://github.com/llvm/llvm-project/pull/150792 (included all tests
additions from there as well)
2026-01-14 15:16:11 -05:00
Robert Imschweiler
71cc38736c
[InferAddressSpaces] Handle unconverted ptrmask (#140802)
In case a ptrmask cannot be converted to the new address space due to an
unknown mask value, this needs to be detcted and an addrspacecast is
needed to not hinder a future use of the unconverted return value of
ptrmask. Otherwise, users of this value will become invalid by receiving
a nullptr as an operand.

This LLVM defect was identified via the AMD Fuzzing project.

(See https://reviews.llvm.org/D80129 for an explanation of why some
ptrmasks are impossible to convert to other addrspaces.)
2026-01-14 09:10:05 +01:00
Ramkumar Ramachandra
d69335bac9
[LLVM] Clean up code using [not_]equal_to (NFC) (#175824)
Use llvm::[not_]equal_to landed in d2a521750 ([ADT] Introduce
bind_{front,back}, [not_]equal_to, #175056) across LLVM for cleaner
code.
2026-01-13 21:19:39 +00:00
Björn Pettersson
1c305aebd6
[SROA] Use shufflevector instead of select for vector blend (#175756)
A patch from May 2013, commit 1e211913b56f390, changed SROA into using a
select instruction to perform vector blend. Idea was that using a select
was the canonical form, and that we optimize select better than
shufflevector.

This patch is changing SROA back into using shufflevector instead of
select when doing the blend (inserting a smaller vector into a larger
vector).

Motivation:
Nowadays InstCombine is canonicalizing this kind of vector blends, using
vector select instructions, into a shufflevector instruction. So it is
assumed that shufflevector is the canonical form now. It is also assumed
that we are better at optimizing shufflevector today, compared to back
in 2013.

Commit f26710d97d9c272be8a55 includes links to a discussion from 2016
(https://discourse.llvm.org/t/ir-canonicalization-vector-select-or-shufflevector/42257/6)
about picking shufflevector as the canonical form.
2026-01-13 18:06:00 +00:00
Austin Jiang
e6cdfb75ac
Fix typos and spelling errors across codebase (#156270)
Corrected various spelling mistakes such as 'occurred', 'receiver',
'initialized', 'length', and others in comments, variable names,
function names, and documentation throughout the project. These
changes improve code readability and maintain consistency in naming
and documentation.

Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2026-01-13 11:52:46 -05:00
Nikita Popov
ed36bff246
[SeparateConstOffsetFromGEP] Perform offset calculations on APInt (#175732)
In general, GEP offset calculations are allowed to overflow (if no
poison flags are set). Using int64_t for this purpose can result in C
level signed integer overflow, which is UB. It also means that we
incorrectly model whether some offsets are zero, and thus generate
redundant zero-index GEPs.

Change the code to track offsets in APInts of the pointer index size,
like we do in other places (like accumulateConstantOffset etc).
2026-01-13 10:43:14 +00:00
Nikita Popov
4b8a8e5f14 [SeparateConstOffsetFromGEP] Allow truncation of offset
It's okay if the offset calculation overflows and we have to
truncate.

However, this should really be doing all the offset calculations on
correctly-sized APInts. For the case where the overflow occurs
on 64-bit indices, this would trigger signed integer overflow UB.

Fixes issue reported at:
https://github.com/llvm/llvm-project/pull/171456#issuecomment-3741522625
2026-01-13 10:48:38 +01:00