14888 Commits

Author SHA1 Message Date
Simon Pilgrim
207598a827
[DAG] Add command line option and TLI hook to enable DAG topological sorting (#188636)
The very first step towards #83422 - which will move DAG combines to be
processed in topological order.

There is a lot of churn on existing tests that need to be addressed
before this can be switched on globally, this patch gives the ability to
enable it both on a per-target basis, and via a command line option to
assist with testing and triage.

At the moment I'm focusing on addressing the x86 regressions (example in
the patch's basic test coverage) as that's the target I'm most familiar
with and will help with many other targets as well, but there might be
other/simpler targets that would benefit from earlier handling.
2026-03-27 07:40:53 +00:00
Osama Abdelkader
0959a2a4bd
Enable generic overlapping optimization for memmove (#177885)
Fixes: #165948
2026-03-27 07:22:05 +00:00
Craig Topper
e43ce53014
[TargetLowering][RISCV] Prefer (S/U)MUL_LOHI over MULH(S/U) in expandMULO. (#188870)
The RISC-V P extension adds WMUL and WMULU instruction that produce
a full 64-bit product in 2 GPRs. The base ISA already had MULH and
MULHU.
2026-03-26 21:12:00 -07:00
Craig Topper
13f1fd0062
[TargetLowering] Remove AllowTruncation from matchUnaryPredicate in BuildExactSDIV/BuildExactUDIV. (#188785)
After #187378 these are no longer tested. I'm concerned that we can
create illegal scalar types after type legalization. I don't know how to
test this now so I'd like to remove support until it is needed and can
be tested.
2026-03-26 13:13:38 -07:00
Craig Topper
0ebef5e5e2
[DAGCombine] Enable div by constant optimization for odd sized vectors before type legalization. (#188313)
If we we are going to legalize to a vector with the same element type
and mulh or mul_lohi are supported, allow the optimization before type
legalization.

RISC-V will widen vectors using vp.udiv/sdiv that doesn't support
division by constant optimization. In addition, type legalization will create
a build_vector with undef elements making it hard to match after type
legalization.

Other targets may need to widen by a combination of vector and scalar
divisions to avoid traps if we widen a vector with garbage.

I had to enable the MULHU->SRL DAG combine before type legalization to
prevent regressions. After type legalization, the multiply constant
build_vector will have undef elements and the combine won't trigger.
2026-03-26 09:16:46 -07:00
Craig Topper
bbd69eec1d
[TargetLowering] In prepareUREMEqFold/prepareSREMEqFold, fix K=-1 for i64 elements. (#188600)
K is an unsigned, it will be zero extended to uint64_t for
the APInt constructor. If the ShSVT has more than 32 bits, we won't
create an all ones ConstantSDNode.

To fix this, explicitly push an all ones constant to KAmts. This
also fixes an APInt ImplicitTrunc.

This allows turnVectorIntoSplatVector to work for this case.
2026-03-26 08:04:04 -07:00
Neil Phan
a6a66a4e69
[DAG] Define computeConstantRange for VSCALE folding (#176027)
Resolves #175150 

Defines computeConstantRange and computeConstantRangeIncludingKnownBits
in the SelectionDAG. Currently only handles `ISD::VSCALE` operation
related to #174708.

Test cases were constructed to test varying VSCALE ranges on AArch64.
Further testing can be implemented as needed by review.
2026-03-25 20:32:09 +00:00
Craig Topper
db1811283d
[TargetLowering] Use APInt::setAllBits() instead of assigning -1. (#188566)
The -1 has 'int' type. The APInt assignment operator takes uint64_t.
Fortunately, due to C rules, the -1 will be converted to an all ones
uint64_t. Unfortunately, if the APInt has more than 64 bits, the upper
words will be zeroed. I don't think we have any testing of that today.

Use setAllBits to avoid the subtle cast and fix the bits > 64 issue.

K still has its own issue that needs to be fixed.
2026-03-25 13:18:03 -07:00
Craig Topper
61533e7e75
[TargetLowering] Update comments for prepareUREMEqFold to show non-zero comparison constants are allowed. NFC (#188550) 2026-03-25 11:39:04 -07:00
Craig Topper
4a352bb60d
[TargetLowering] Use APInt::abs in prepareSREMEqFold. NFC (#188551) 2026-03-25 11:38:17 -07:00
Craig Topper
d362bd7b9d
[TargetLowering] use APInt::getLowBitsSet instead of APInt::getAllOnes+zext. (#188384) 2026-03-25 09:09:04 -07:00
Antonio Frighetto
27abb7f29b
[SDAG] Follow target boolean semantics in PromoteIntOp_VECTOR_FIND_LAST_ACTIVE
Before handling `VECTOR_FIND_LAST_ACTIVE` expansion, ensure the vector
mask elements get extended accordingly, after the vector mask type is
promoted to its legal type.

Fixes: https://github.com/llvm/llvm-project/issues/187875.
2026-03-25 16:53:29 +01:00
zGoldthorpe
11bc6e8776
[SelectionDAG] Add known bit for ISD::FABS (#188335)
Absolute value always clears the sign bit, so make that knowh to
selectionDAG's `computeKnownBits`.
2026-03-24 14:53:06 -06:00
Craig Topper
52296eab79
[TargetLowering] In BuildSDIV, avoid creating build_vector with illegal scalar types after type legalization. (#188280)
Code is based on a similar code in BuildUDIV.
2026-03-24 12:27:10 -07:00
Simon Pilgrim
3deca2dc32
[KnownBits] KnownBits::add - add optional arg indicating a X+X self add pattern (#188078)
Compute knownbits for ADD(X,X) as SHL(X,1)

Followup to #186461
2026-03-24 17:12:55 +00:00
Craig Topper
ff07361fdf
[TargetLowering] In expandDIVREMByConstant, combine shift by trailing zeros with chunk shifts. (#188086)
This reduces the number of generated instructions in some cases.

While I was there, I changed an Add to a Disjoint OR since DAGCombine
was going to do it anyway.
2026-03-24 07:57:58 -07:00
Luke Lau
7d39664a6a
Revert "[SelectionDAG] Expand CTTZ_ELTS[_ZERO_POISON] and handle splitting" (#188220)
Reverts llvm/llvm-project#185605

Buildbot failures caused by ISel crashes in
https://lab.llvm.org/buildbot/#/builders/157/builds/45416 and
https://lab.llvm.org/buildbot/#/builders/10/builds/25156
2026-03-24 11:35:14 +00:00
Luke Lau
fe105347e2
[SelectionDAG] Expand CTTZ_ELTS[_ZERO_POISON] and handle splitting (#185605)
Currently a cttz.elts of e.g. nxv32i1 will get expanded to a reduction
of nxv32i64 or equivalent, but we can split it into two legal nxv16i1
cttz.elts once we have dedicated SelectionDAG nodes.

This implements the splitting for them the same way we implement type
splitting for vp.cttz.elts, i.e. check if the low result is VF, and if
so add it to the result of the high result. It also implements operand
type promotion for NEON which needs to promote i1 vectors to something
larger first.

We also need to move expansion into LegalizeVectorOps so it doesn't get
expanded before type legalization can do splitting. This uses
LegalizeVectorOps in case the scalar reduction type, which depends on
the minimum bitwidth needed to store the result, still needs type
promotion.

The TTI costs should be updated after this to reflect the more efficient
codegen, but that is deferred to another PR.
2026-03-24 10:11:46 +00:00
Alexey Merzlyakov
d607d6f78f
[LegalizeTypes] Keep non-negative info in SUB(CTLZ) (#186338)
When legalizing CTLZ for a wider type with a SUB bit-width compensation,
the result for a zero-defined case can have an extra bit that exceeds
the maximum value of the original type width. Unlike CTLS, which covers
all bits within its type width, CTLZ leads to producing undefined
KnownBits. So, after subtraction, the KnownBits could represent a
negative value, which prevents subsequent optimizations.

This patch ensures that non-negative information is preserved during the
SUB(CTLZ) expansion, so that KnownBits after SUB will take a stricter
range within the type width, thus allowing further combine optimizations
following by SUB. Particularly, this enables the DAG Combiner to remove
unnecessary AND instructions for CTLZ output type conversion.

Fixes #136516

---------

Co-authored-by: Simon Pilgrim <git@redking.me.uk>
2026-03-24 09:17:17 +01:00
Elvis Wang
494b98236f
[TargetLowering][RISCV] Using index type for step vector in expandVectorFindLastActive (#187984)
This patch change the type of the step vector lowered from
`expandVectorFindLastActive` from `e8` to the index type of the target
machine.

This can help the index out of bound issue when the VLEN is large.

Note that after this patch, there are still some issue in
expandVectorFindLastActive.
2026-03-24 09:37:25 +08:00
Xinlong Chen
b670265b58
[DAG] ComputeKnownBits - set low bit to zero for ADD(X,X) (#186461)
ADD(X,X) is equivalent to SHL(X,1), so bit[0] is always zero.

This allows downstream folds like `and(add(x,x), 1) -> 0`.

Fixes #186091
2026-03-23 16:10:36 +00:00
Craig Topper
0afc30f8d5
[TargetLowering] Add helper to create FSHR like operation in expandDIVREMByConstant. NFC (#187979) 2026-03-23 08:49:38 -07:00
Craig Topper
c75b8a1649
[TargetLowering] Avoid unnecessary nodes in the chunk loop in expandDIVREMByConstant (#187967)
We don't need an AND on the last iteration. If we shifted the dividend
due to trailing zeros in the divisor, we don't need a chunk that only
contains shifted in zeros.
2026-03-23 08:48:59 -07:00
Abdullah Sarkar
364f8d4239
[DAG] isKnownNeverZero - add ISD::VECTOR_SHUFFLE handling (#187855)
Fixes #183351
2026-03-23 12:53:49 +00:00
Max Graey
7c6996fc8f
[ValueType][NFC] Add widenIntegerElementType method (#187816)
Fixes #187805
2026-03-23 09:43:47 +00:00
Craig Topper
f146677396
[TargetLowering] Refactor expandDIVREMByConstant to share more code. NFC (#187582)
Make the (1 << HBitWidth) % Divisor == 1 path a special case within
the recently added chunk summing algorithm. This allows us to
share the trailing zero shifting code.

While there make some comment improvements and avoid creating
unnecessary nodes.
2026-03-21 11:23:16 -07:00
Craig Topper
c1df6937ba
[TargetLowering] Use legally typed shifts to split chunks in expandDIVREMByConstant. (#187567)
This replaces LegalVT with HiLoVT and LegalWidth with HBitWidth as
they are the same for all current uses.
    
Then we rewrite the shifts to operate on LL and LH.
    
There's a slight regression on RISC-V due to different node creation
order leading to different DAG combine order. I have other refactoring
I'd like to explore then I may try to fix that.
2026-03-21 09:31:20 -07:00
Craig Topper
343b566b57
[TargetLowering] Move the MULH/MUL_LOHI legality checks to the beginning of BuildSDIV/UDIV. NFCI (#187780)
This groups the type and operation legality checks to the beginning. The
rest of the code can focus on the transformation.
2026-03-20 14:52:28 -07:00
Craig Topper
3eecb98b37
[TargetLowering] Separate some of the control for the i32->i64 optimization out of BuildUDIVPattern. (#187739)
Check the type before we call getOperationAction. Give BuildUDIVPattern
only AllowWiden and a WideSVT.

Update variable names and comments to avoid spreading "64" to too many
places.
2026-03-20 14:52:09 -07:00
Nikita Popov
f064a9979f
[DAGCombine] Optimize away cond ? 1 : 0 post-legalization (#186771)
Selects of the form `cond ? 1 : 0` are created during unrolling of
setcc+vselect. Currently these are not optimized away post-legalization
even if fully redundant. Having these extra selects sitting between
things can prevent other folds from applying.

Enabling this requires some mitigations in the ARM backend, in
particular in the interaction with MVE support. There's two changes
here:

* Form CSINV/CSNEG/CSINC from CMOV, rather than only creating it during
SELECT_CC lowering. (After this change, the lowering in SELECT_CC can be
dropped without test changes, let me know if I should do that.)
* Support pushing negations through CMOV in more cases, in particular if
the operands are constant or the negation can be handled by flipping
lshr/ashr.

Additionally, in the X86 backend, try to simplify CMOV to SETCC if only the
low bit is demanded.
2026-03-20 16:23:18 +01:00
Craig Topper
b6543c98d7 [TargetLowering] Make sure LL/LH are always initialized in expandDIVREMByConstant
This is quick fix to fix some reported failures.
2026-03-19 11:48:07 -07:00
jeanPerier
76f7252571
[FastISel] generate FAKE_USE for llvm.fake.use (#187116)
FastISel was dropping llvm.fake.use because they are not meant to be
generated at O0 with clang.

This patch adds support in FastISel to generate FAKE_USE for llvm.fake.use.
The handling is simpler than in SelectionDagBuilder because no attempt is made to
get rid of useless FAKE_USE (e.g. for constant SSA values) to keep FastISel simple.

The motivation is that flang will generate llvm.fake.use for function arguments under
`-g` (and O0) because Fortran arguments are not copied to the stack (they are
reference like arguments in most cases) and one should be able to access these
variables from the debugger at any point of the function, even after their last use in the
function.
2026-03-19 14:06:26 +01:00
Shivam Gupta
796b218edd
[LegalizeTypes] Expand UDIV/UREM by constant via chunk summation (#146238)
This patch improves the lowering of 128-bit unsigned division and
remainder by constants (UDIV/UREM) by avoiding a fallback to libcall
(__udivti3/uremti3) for specific divisors.

When a divisor D satisfies the condition (1 << ChunkWidth) % D == 1, the
128-bit value is split into fixed-width chunks (e.g., 30-bit) and summed
before applying a smaller UDIV/UREM. This transformation is based on the
"remainder by summing digits" trick described in Hacker’s Delight.

This fixes #137514 for some constants.
2026-03-19 17:58:54 +05:30
Paul Walker
7663802125
[LLVM][DAGCombiner] Limit extract_subvec(extract_subvec()) combine to vectors of the same type. (#187334)
The index operand of ISD::EXTRACT_SUBVECTOR is implicitly scaled by
vscale, which is effectively always one for fixed-length vectors. When
combining nested extracts we must ensure all use the same implicit
scaling otherwise the transform is not equivalent.

Fixes https://github.com/llvm/llvm-project/issues/186563
2026-03-19 11:14:30 +00:00
Craig Topper
291359be68
[SelectionDAG] Move the call to BuildExactSDIV and BuildExactUDIV to the top of BuildSDIV/BuildUDIV. (#187378)
This moves it above the type legality check. The legality check we use
for the main division by constant algorithm is probably not right for
BuildExactSDIV and BuildExactSDIV. These checks are largely about the
legality of MUL_LOHI/MULH which are not used for the exact case.

This patch removes the legal type check for the exact case. If we do
need a check it's probably better to have a specific version in
BuildExactSDIV and BuildExactSDIV.

I'm hoping to do some refactoring of the legality checks in
BuildSDIV/BuildUDIV so separating them makes this easier.
2026-03-18 19:54:47 -07:00
Craig Topper
9dd2e3792a
[DAGCombiner] Move the XORHandle in rebuildSetCC inside the while loop. (#187189)
If N was changed on the previous loop iteration, we need the handle to
point at the new N.

Fixes #186969.
2026-03-18 09:30:05 -07:00
Pengcheng Wang
2734c46153
[DAG] Add back SelectionDAG::dump() without parameter (#187001)
Usually `dump()`s are without parameter, so the practice is calling
`XXX::dump()` when debugging.

But we will get an error like below after #161097:

```
error: <user expression 128>:1:10: too few arguments to function call,
expected 1, have 0
    1 | DAG.dump()
      | ~~~~~~~~ ^
```

So to not surprise users, I added back the `SelectionDAG::dump()`
without parameter.
2026-03-18 18:34:03 +08:00
gonzalobg
ea8fb06f24
[atomicrmw] fminimumnum/fmaximumnum support (#187030)
Adds support for `atomicrmw` `fminimumnum`/`fmaximumnum` operations.
These were added to C++ in P3008, and are exposed in libc++ in #186716 .
Adding LLVM IR support for these unblocks work in both backends with HW
support, and frontends.
2026-03-18 09:35:49 +01:00
Demetrius Kanios
351501799a
[CodeGen] Improve getLoadExtAction and friends (#181104)
Alternative approach to the same goals as #162407

This takes `TargetLoweringBase::getLoadExtAction`, renames it to
`TargetLoweringBase::getLoadAction`, merges `getAtomicLoadExtAction`
into it, and adds more inputs for relavent information (alignment,
address space).

The `isLoadExtLegal[OrCustom]` helpers are also modified in a matching
manner.

This is fully backwards compatible, with the existing `setLoadExtAction`
working as before. But this allows targets to override a new hook to
allow the query to make more use of the information. The hook
`getCustomLoadAction` is called with all the parameters whenever the
table lookup yields `LegalizeAction::Custom`, and can return any other
action it wants.
2026-03-17 23:40:19 -07:00
Craig Topper
ded656b467
[TargetLowering][X86] Directly emit FSHR from expandDIVREMByConstant when Legal. (#186863) 2026-03-16 16:48:34 -07:00
Pedro Lobo
57568c288d
[Reland][IR] Add initial support for the byte type (#186888)
This patch relands https://github.com/llvm/llvm-project/pull/178666. The
original version caused CI failures due to the missing target triple in
`llvm/test/CodeGen/X86/byte-constants.ll`. CI should be green now.
2026-03-16 23:32:24 +00:00
Luke Lau
7a8903566d
[SelectionDAG] Add CTTZ_ELTS[_ZERO_POISON] nodes. NFCI (#185600)
Currently llvm.experimental.cttz.elts are directly lowered from the
intrinsic.

If the type isn't legal then the target tells SelectionDAGBuilder to
expand it into a reduction, but this means we can't split the operation.
E.g. it's possible to split a cttz.elts nxv32i1 into two nxv16i1,
instead of expanding it into a nxv32i64 reduction.

vp.cttz.elts can be split because it has a dedicated SelectionDAG node.

This adds CTTZ_ELTS and CTTZ_ELTS[_ZERO_POISON] nodes and just enough
legalization to get tests passing. A follow up patch will add splitting
and move the expansion into LegalizeDAG.
2026-03-16 14:39:35 +08:00
Pedro Lobo
70cd2acbd3
Revert "[IR] Add initial support for the byte type" (#186713)
Reverts llvm/llvm-project#178666 to unblock CI.
`CodeGen/X86/byte-constants.ll` is at fault. 
Will look into it and hopefully fix it by tomorrow.
2026-03-15 23:29:21 +00:00
Pedro Lobo
80f2ef70f5
[IR] Add initial support for the byte type (#178666)
Following the [byte type RFC](https://discourse.llvm.org/t/rfc-add-a-new-byte-type-to-llvm-ir/89522)
and the discussions within the [LLVM IR Formal Specification WG](https://discourse.llvm.org/t/rfc-forming-a-working-group-on-formal-specification-for-llvm/89056), this PR introduces initial support for the byte type in LLVM. This PR:
- Adds the byte type to LLVM's type system
- Extends the `bitcast` instruction to accept the byte operands
- Adds parsing tests for all new functionality
- Fixes failing regressions tests (IR2Vec and IRNormalizer)

---------

Co-authored-by: George Mitenkov <georgemitenk0v@gmail.com>
2026-03-15 21:56:06 +00:00
Iasonaskrpr
b44434474e
Improved ISD::SRL handling in isKnownToBeAPowerOfTwo (#182562)
Fixes #181651

Added DemandedElts argument to isConstOrConstSplat and to
isKnowTobePowerOfTwo calls and OrZero || isKnownNeverZero(Val, Depth) is
checked before isKnowTobePowerOfTwo. Also added unit tests.
2026-03-14 18:49:08 +00:00
Alexis Engelke
01571f1b4a
[CodeGen] Drop uses of BranchInst (#186391)
Largely a straight-forward replacement with occasional simplifcations.

For AMDGPU, I assumed that unconditional branches are always uniform and
therefore "simplified"/changed AMDGPUAnnotateUniformValues to only
annotate conditional branches.

Target-specific FastISel only selects conditional branches,
unconditional branches are already handled by the non-target-specific
code.
2026-03-13 21:51:38 +00:00
Gergo Stomfai
0fb8f7f9c3
[DAG] Fold away identity FSHL and FSHR patterns (#185667)
Fold away identity FSHL and FSHR patterns

Came up in #185175, this seems to be the cleanest way to get rid of this
pattern

Alive2 proofs:
`fshl(lshr(x, amnt), shl(c, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/AEzthY
`fshl(lshr(x, amnt), fshl(x, _, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/oDpaqF
`fshl(lshr(x, amnt), fshr(x, _, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/aCxQch
`fshl(fshr(_, x, amnt), shl(c, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/89NQME
`fshl(fshr(_, x, amnt), fshl(x, _, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/KdR3Mp
`fshl(fshr(_, x, amnt), fshr(x, _, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/2Gkc7m
`fshl(fshl(_, x, BW - amnt), shl(c, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/LNjr_R
`fshl(fshl(_, x, BW - amnt), fshl(x, _, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/cwGjhL
`fshl(fshl(_, x, BW - amnt), fshr(x, _, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/UChZW4
`fshr(lshr(x, BW - amnt), shl(c, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/uiSBEQ
`fshr(lshr(x, BW - amnt), fshl(x, _, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/11pXpJ
`fshr(lshr(x, BW - amnt), fshr(x, _, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/7mvxH7
`fshr(fshr(_, x, BW - amnt), shl(c, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/ybswip
`fshr(fshr(_, x, BW - amnt), fshl(x, _, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/fNUQQv
`fshr(fshr(_, x, BW - amnt), fshr(x, _, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/9bFnec
`fshr(fshl(_, x, amnt), shl(c, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/vuYAYn
`fshr(fshl(_, x, amnt), fshl(x, _, amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/kP94MG
`fshr(fshl(_, x, amnt), fshr(x, _, BW - amnt), amnt) -> x`:
✓ https://alive2.llvm.org/ce/z/X8u__v
2026-03-12 11:21:29 +00:00
Simon Pilgrim
9a8147b553
Revert "[SDAG] (abs (add nsw a, -b)) -> (abds a, b)" (#17580) (#186068)
Reverts llvm/llvm-project#175801 while #185467 miscompilation is being investigated
2026-03-12 10:35:24 +00:00
Alexis Engelke
4fd826d1f9
[IR] Split Br into UncondBr and CondBr (#184027)
BranchInst currently represents both unconditional and conditional
branches. However, these are quite different operations that are often
handled separately. Therefore, split them into separate opcodes and
classes to allow distinguishing these operations in the type system.
Additionally, this also slightly improves compile-time performance.
2026-03-11 12:31:10 +00:00
Craig Topper
53a2fd99aa
[DAGCombiner] Combine (fshl A, B, S) | (fshr C, D, BW-S) --> (fshl (A|C), (B|D), S) (#180889)
This is similar to the FSHL/FSHR handling in
hoistLogicOpWithSameOpcodeHands.
Here the opcodes aren't exactly the same, but the operations are
equivalent.

Fixes regressions from #180888
2026-03-10 18:53:40 -07:00