2265 Commits

Author SHA1 Message Date
Alexis Engelke
9a2f23e1a4
[CodeGen] Use separate MBB number for analyses (#187086)
Block numbers are updated too frequently, which makes it difficult to
keep analyses up to date. Therefore, introduce a second number per basic
block that is used for analyses and is renumbered less often. This frees
analyses from providing somewhat efficient facilities for dealing with
changed block numbers, making it simpler to implement in e.g. LoopInfo
or CycleInfo.

(Currently, "less often" means not at all, but we might want to renumber
after certain passes if the numbering gets too sparse and no analyses
are preserved anyway.)

When we introduced a more general use of block numbers some time ago,
using the existing numbers seemed to be a somewhat obvious choice, but I
now think that this was a bad decision, as it conflates a number that is
used for ordering with a number that should be more stable.

MachineBasicBlock isn't particularly size-optimized and there's a fair
amount of padding where we can add another number.

There should be no performance impact,
2026-03-18 07:35:36 +01:00
hanbeom
1fee51c40b
[WebAssembly] Fold sign-extending shifts into signed loads in FastISel (#185906)
WebAssembly FastISel currently fails to fold sign-extension patterns
composed of zero-extending loads followed by shift operations. This
results in redundant shift and constant instructions in the output.

Before:
  i32.load8_u $push3=, 0($0)
  i32.const $push0=, 24
  i32.shl $push1=, $pop3, $pop0
  i32.const $push4=, 24
  i32.shr_s $push2=, $pop1, $pop4

The matched shift instruction sequence is removed and safely folded into
a single sign-extending load, erasing the dead code via the
MachineBasicBlock iterator.

After:
  i32.load8_s $push0=, 0($0)

Fixed: #184302
2026-03-18 10:30:00 +09:00
Folkert de Vries
b861a289d7
[WebAssembly] combine bitmask with setcc <X>, 0, setlt (#179065)
The rust `simd_bitmask` intrinsic is UB when the lanes of its input are
not either `0` or `!0`, presumably so that the implementation can be
more efficient because it could look at any bit. To get the "mask of
MSB" behavior of webassembly's `bitmask`, we would like to simply first
compare with a zero vector.

```llvm
define i32 @example(<2 x i64> noundef %v) {
entry:
  %1 = icmp slt <16 x i8> %v, zeroinitializer
  %2 = bitcast <16 x i1> %1 to i16
  %3 = zext i16 %2 to i32
  ret i32 %3
}
```

On x86_64, this additional comparison optimizes away, but for wasm it
does not.

https://godbolt.org/z/T5sPejocs

This PR adds a new combine, so that instead of emitting 

```asm
example:
        local.get       0
        v128.const      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        i8x16.lt_s
        i8x16.bitmask
        end_function
```

we just emit 

```
example:
        local.get       0
        i8x16.bitmask
        end_function
```
2026-03-17 11:21:39 +00:00
Derek Schuff
18d85a33cc
[WebAssembly] Support acquire-release atomics in CodeGen (#184900)
Set the correct memory ordering for relaxed atomics after ISel. This
allows
SelectionDAG to keep the simple generic selection for target-independent
AtomicLoad nodes, but keeps the ordering immediate correct in the MIR.
Notably, the MachineMemOperand still has the original memory ordering
and MIR passes would use that rather than the ordering immedate to make
their code motion decisions (if we had any for Wasm, which we don't).
2026-03-16 09:11:54 -07:00
hanbeom
cb681fc4b6
[WebAssembly] Lower wide vector shifts by constant to extmul pairs (#184007)
Wide vector multiplications by power-of-2 constants were 
canonicalized to v8i32 shl nodes. Generic legalizers then split these
into separate 128-bit extend and shift operations, bypassing
WebAssembly's native extended multiplication patterns.

Before:
    mul v8i32:t1, <4096, ...>
    => shl v8i32:t1, <12, ...>
    => split into independent 128-bit extend + shift sequences

WebAssembly SIMD has no native wide vector shifts, but it does
support 128-bit extended multiplications. Lowering these nodes
directly to extmul_low/extmul_high pairs keeps them in native 128-bit
form and improves DAG matching.

After:
mul v8i32:t1, <4096, ...>
    => concat_vectors (extmul_low  t1, c), (extmul_high t1, c)

This preserves the original vector width while utilizing the native
128-bit SIMD pipeline.

Fixed: https://github.com/llvm/llvm-project/issues/179143
2026-03-16 21:06:40 +09:00
Alexis Engelke
4a2e1692dd
[WebAssembly][NFC] Rename and test FastISel selectBr (#186577)
selectBr only handles conditional branches and also wasn't tested.
Clarify the name and add test that enforces that there's no fallback.
2026-03-14 19:01:53 +01: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
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
hanbeom
f2f5845f19
[WebAssembly][FastISel] Fold AND mask operations into ZExt load (#183743)
FastISel emits separate load and AND instructions for bitmasking.
(before) %1:i32 = LOAD_I32 %addr; %2:i32 = AND_I32 %1, 255

Fold AND masks into ZExt loads by verifying operands with
maskTrailingOnes. A getFoldedLoadOpcode wrapper is implemented
to manage dispatching logic for better extensibility.
(after) %1:i32 = LOAD8_U_I32 %addr

Fixed: https://github.com/llvm/llvm-project/issues/180783
2026-03-11 11:30:48 +09:00
Derek Schuff
e950a806f0
[WebAssembly] Look through freeze nodes when folding vector load + ext (#185143)
When folding loads with extensions, the extension operand can be a freeze node
in addition to a load. We can look through it to do the desirability check.

Fixes #184676
2026-03-10 19:15:53 -07:00
Derek Schuff
1324ea1b22
[WebAssembly] Fold any/alltrue SIMD boolean reductions with eqz (#184704)
Existing ISel patterns match setne/seteq following SIMD boolean reductions
any_true and all_true, and drop the ones that are redundant (because the
reductions always return 1 or 0). This adds patterns to also produce eqz
instructions instead of a comparison with a const.
2026-03-09 22:54:25 +00:00
Demetrius Kanios
b87cf50b6c
[WebAssembly] Remove the wasm-disable-fix-irreducible-control-flow-pass switch (#185072)
This removes the `wasm-disable-fix-irreducible-control-flow-pass`
switch.

It was originally added in #67715 as a way to avoid the potentially
absurd compile times the pass used to bring. However with the successful
merge of #184441, the pass itself has been fixed to avoid this issue.

Given that, it is no longer necessary nor desirable to keep this switch.
2026-03-06 12:48:38 -08:00
Sy Brand
ae4e71241f
[MC][WebAssembly] Allow strings for import modules and names in asm (#182896)
Current tooling for the WebAssembly component model uses import modules
and names such as `$root` and `[thread-index]`. Importing these from
assembly files requires support for non-valid identifiers in
`.import_name` and `.import_module` directives. This PR adds support for
specifying those as strings, e.g.:

```asm
	.import_module __wasm_component_model_builtin_thread_index, "$root"
	.import_name __wasm_component_model_builtin_thread_index, "[thread-index]"
```
2026-03-06 12:43:09 -08:00
Nikita Popov
f90b783c3f
[WebAssembly] Do not form minnum/maxnum (#184796)
For wasm, forming minnum/maxnum style ISD nodes is non-profitable,
because (in cases where any float min/max support exists at all), it has
pmin/pmax instructions that correspond to the fcmp+select semantics, or
relaxed_fmin/relaxed_fmax (for the nnan+nsz case) with even loser
semantics.

As such, return false from isProfitableToCombineMinNumMaxNum(), and also
respect that hook in the SDAGBuilder.
2026-03-06 09:05:51 +01:00
Demetrius Kanios
0a76568db0
[WebAssembly] Reapply "[WebAssembly] Incorporate SCCs into WebAssemblyFixIrreducibleControlFlow" (#181755) (#184441)
Re-application of #181755.

Includes fixes to issues found after the original's merge.
2026-03-05 11:13:43 -08:00
Derek Schuff
ade43a54d4
[WebAssembly] MC support for acquire-release atomics (#183656)
Initial support for acquire-release atomics, specified as part of
https://github.com/WebAssembly/shared-everything-threads

This adds an ordering operand to atomic loads, stores, RMWs,
wait/notify,
and fences. It currently defaults to 0 and ISel is not updated yet, so
atomics produced by the compiler will still always be seqcst.

Asm parsing and printing, binary emission and disassembly are all
updated. Binary emission will always use the old encoding because the
encoding is smaller, and to get backwards compatibility for free.
2026-03-04 20:10:14 +00:00
hanbeom
3bb4a506c5
[WebAssembly] Print type signature and table for call_indirect (#179120)
Update WebAssemblyInstPrinter.cpp to correctly print type
and table operands for both register and stack modes.
2026-03-04 18:00:42 +09:00
Derek Schuff
87a4b36fbe
[WebAssembly] Use MVT::i32 instead of i1 in performAnyAllCombine (#183866)
The CombineSetCC helpers and performAnyAllCombine generate MVT::i1
results.
However MVT::i1 is an illegal type in WebAssembly, and this combiner can
run either before or after legalization. Directly creating the intrinsic
and negating its result using XOR instead of i1 and a NOT operation
avoids this problem.

Fixes #183842
2026-03-03 15:19:23 -08:00
hanbeom
637bb0e377
[WebAssembly][FastISel] Call materializeLoadStoreOperands in load fold (#184203)
The `tryToFoldLoadIntoMI` function omitted materializing base registers
for addresses before folding sign-extend instructions into loads. This
left `$noreg` as the base register, crashing subsequent passes.

WebAssembly memory instructions structurally require a valid base
register. Calling the existing `materializeLoadStoreOperands` function
ensures that a `CONST 0` virtual register is generated when addressing
global variables directly without a pre-existing base register.

(before) %1:i32 = LOAD8_S_I32_A32 0, @ch, $noreg ... -> CRASH (after)
%3:i32 = CONST_I32 0
         %1:i32 = LOAD8_S_I32_A32 0, @ch, %3:i32 ... -> Folded safely
2026-03-04 03:39:17 +09:00
Demetrius Kanios
5395d26689
Revert "[WebAssembly] Incorporate SCCs into WebAssemblyFixIrreducibleControlFlow (#181755)" (#183872)
This reverts commit c05e323be7caaadff6fdd09a2336be60e3041af1.

Changes failed Emscripten tests.
2026-02-28 01:46:08 +00:00
Aiden Grossman
c2f66f2a94 [WebAseembly] Fix -Wunused-variable in #181755
This variable ends up being unused in builds without assertions. Mark it
[[maybe_unused]] per the coding standards.
2026-02-27 21:13:04 +00:00
Demetrius Kanios
c05e323be7
[WebAssembly] Incorporate SCCs into WebAssemblyFixIrreducibleControlFlow (#181755)
Rather than mapping out full "reachability" between blocks in a region
to find loops and using `LoopBlocks` to find the bodies of said loops,
use SCCs (strongly-connected components) to provide this information.

This brings in LLVM's generic `SCCIterator` (which uses Tarjan's
algorithm) as the implementation for sorting the basic blocks of the CFG
into their SCCs.

This PR greatly reduces the compile-time footprint of the pass, making
memory use and time taken negliable where it might have previously
caused stalls and OOM before (e.g. #47793,
usagi-coffee/tree-sitter-abl#114)

------

Supersedes #179722

Fixes #47793
Fixes #165041 (probably)

Thanks to @jkbz64 for the initial investigations (w/ AI; see #179722)
into why this pass was slow and memory consuming and showing that SCCs
were the key.

Also thanks to the Cheerp compiler project for bringing `SCCIterator` to
light in this context ([blog
post](https://cheerp.io/blog/control-flow#fix-the-irreducible-control-flow),
[implementation](https://github.com/leaningtech/cheerp-compiler/blob/master/llvm/lib/CheerpUtils/FixIrreducibleControlFlow.cpp)).
2026-02-27 10:52:01 -08:00
hanbeom
4147cd29e1
[WebAssembly][FastISel] Emit signed loads for sext of i8/i16/i32 (#182767)
FastISel currently defaults to unsigned loads for i8/i16/i32 types,
leaving any sign-extension to be handled by a separate instruction. This
patch optimizes this by folding the SExtInst into the LoadInst, directly
emitting a signed load (e.g., i32.load8_s).

When a load has a single SExtInst use, selectLoad emits a signed load
and safely removes the redundantly emitted SExtInst.

Fixed: #180783
2026-02-27 18:31:33 +09:00
Folkert de Vries
90144c2df0
[WebAssembly] optimize ext + shuffle + add into addext (#182849)
cc https://github.com/llvm/llvm-project/issues/179143

This adds a second pattern: we already recognize "shuffle + extend +
add" as `addext`, this adds another pattern for "extend + shuffle +
add", which can come up when programs are optimized.
2026-02-25 14:04:42 +01:00
Demetrius Kanios
d269c36baf
[WebAssembly] Optimize WebAssemblyCFGSort's post sort verifications. (#182458)
Currently, the post-sort verifications `WebAssemblyCFGSort` does in
assertion builds is quite expensive. Given the example of
[usagi-coffee/tree-sitter-abl](https://github.com/usagi-coffee/tree-sitter-abl),
we have one MASSIVE function with nearly 120K blocks. Sorting this is
fast, but the verifications after take some 40+ seconds (on my machine).

The culprit was the manipulation of the region `OnStack`. I've tried to
replace that with interval based verifications to make sure the regions
are well formed, well nested, and that the numbers of the blocks within
a region are within the interval of the numbers of the header and bottom
of the region.

This brings the aforementioned example down to well under a second spent
in the pass in an assertions build.
2026-02-24 11:06:11 -08:00
Heejin Ahn
1bc2446c78
[WebAssembly] Use generic CPU by default in llvm-mc (#181460)
Other tools, such as `llc`, use `generic` cpu by default, if you don't
give any `-mcpu`:

75f738b0b2/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp (L38-L39)

But `llvm-mc` didn't do that. This makes `generic` also the default CPU
for `llvm-mc`.
2026-02-24 00:39:14 -08:00
Hood Chatham
7d9d392a1f
[WebAssembly] Fix SELECT_CC lowering for reference types (#181622)
SELECT_CC nodes with externref or funcref return types were not being
expanded, causing "Cannot select" errors during instruction selection.

This adds SELECT_CC to the list of operations that should be expanded
for reference types, similar to how it's already handled for scalar
types (i32, i64, f32, f64). This allows the SELECT_CC to be lowered to a
SELECT node, which already has instruction patterns defined in
WebAssemblyInstrRef.td.
2026-02-19 09:14:29 -08:00
Jay Foad
27144f4c2e
[TableGen] Return int32_t from InstrMapping table lookup functions. NFC. (#182079)
Since #182059 there is only one case in which these functions return -1,
so callers no longer need to distinguish between (int64_t)-1 and
(uint32_t)-1, so we can go back to a 32-bit return value like it was
before #180954.
2026-02-18 18:49:58 +00:00
Benjamin Maxwell
88c0a1db85
Revert "[WebAssembly] Mark extract.last.active as having invalid cost." (#181545)
The failures should have been resolved with
https://github.com/llvm/llvm-project/pull/180290 (which also added
WebAssembly tests).

This reverts commit
811fb223af.

---

This is the same as #180942, but with a `lit.local.cfg` added to the
CostModel test folder.
2026-02-16 08:55:25 +00:00
Benjamin Maxwell
0ad941a98b
Revert "Revert "[WebAssembly] Mark extract.last.active as having invalid cost."" (#181342)
Reverts llvm/llvm-project#180942

Looks like something changed the cost model. Will investigate later.
2026-02-13 09:50:30 +00:00
Benjamin Maxwell
0f8325c9a9
Revert "[WebAssembly] Mark extract.last.active as having invalid cost." (#180942)
The failures should have been resolved with #180290 (which also added
WebAssembly tests).

This reverts commit 811fb223af2b3e2d68c99b346f4b75dcf3de3417.
2026-02-13 09:21:46 +00:00
Heejin Ahn
c1e90fa663
[WebAssembly] Error on Wasm SjLj if +exception-handling is missing (#181070)
This checks every user function of `setjmp` or `longjmp` and if any of
them does not have `+exception-handling` target feature, errors out.

Hopefully this gives a clearer error message to the users in case they
do not provide consistent SjLj flags at compile time vs. link time.

Closes #178135 and closes
https://github.com/emscripten-core/emscripten/issues/26165.
2026-02-12 13:33:18 -08:00
sstipano
5ec5701db3
Reapply "[MC][TableGen] Expand Opcode field of MCInstrDesc" (#180321) (#180954)
Difference from the previous version is that this one doesn't actually
encode opcodes in matcher tables as 32 bits, but still as 16 bits.
2026-02-12 09:17:02 +01:00
Sam Clegg
11c2613342
[WebAssembly] Add initial support for compact imports proposal (#176617)
This change adds initial support to libObject for reading compact
imports and support for writing compact imports in the linker.

There is minimal testing here since to tools like lllvm-readobj, and
obj2yaml don't currently report compact imports any differently.

See https://github.com/WebAssembly/compact-import-section
2026-02-10 10:57:45 -08:00
Vladimir Vereschaka
19d681177f
Revert "[MC][TableGen] Expand Opcode field of MCInstrDesc" (#180321)
Reverts llvm/llvm-project#179652

This PR causes the out-of-memory build failures on many Windows
builders.
2026-02-06 21:58:50 -08:00
Demetrius Kanios
4919e0da50
[WebAssembly][FastISel] Make use of sign-ext proposals instructions when available (#179855)
Enables FastISel to use the dedicated sign-extension instructions
(rather than shl, shr) when available.
2026-02-06 12:41:39 -08:00
sstipano
13d8870d45
[MC][TableGen] Expand Opcode field of MCInstrDesc (#179652)
Increase width of Opcode to `int` from `short` to allow more capacity.
2026-02-06 20:21:48 +01:00
Demetrius Kanios
9976e5702f
[WebAssembly][GlobalISel] Part 1 - Setup skeleton (#178796)
This PR is the first step towards bringing GlobalISel to the Wasm
backend.

Split from #157161
2026-02-06 18:38:56 +00:00
Derek Schuff
c3db52701e
[MC][Wasm] Emit useful error message when encountering common symbols (#179586)
We don't currently support common symbols for Wasm, and we currently
emit a generic error with a backtrace. Instead, don't crash, and report
the names of the offending symbols.
2026-02-06 00:40:25 +00:00
hanbeom
22f53531d7
[WebAssembly] Combine shuffle and signed extend to extend_high (#179166)
Fold shuffles and bitcasts feeding extend_low_s into extend_high_s.
This enables i32x4.dot_i16x8_s selection and removes redundant shuffles.

Fixed: https://github.com/llvm/llvm-project/issues/179145
2026-02-03 17:02:53 +09:00
Nicolai Hähnle
6f0b873f1c
[CodeGen] Refactor targets to override the new getTgtMemIntrinsic overload (NFC) (#175844)
This is a fairly mechanical change. Instead of returning true/false,
we either keep the Infos vector empty or push one entry.
2026-02-02 17:40:02 -08:00
Anshul Nigham
85545d4c84
[NewPM] Port MachineDominanceFrontierAnalysis (#177709) 2026-02-01 22:02:45 -08:00
Demetrius Kanios
95ac9314df
[WebAssembly] Prevent FastISel from trying to select funcref calls (#178742)
Before, Wasm FastISel treated all indirect calls the same, causing
miscompilations at O0 when trying to call a funcref (`call ptr
addrspace(20)`), as it would treat the funcref as a normal `ptr`

This adds a check so it falls back to ISelDAG when encountering calls
outside addrspace 0 (which covers direct calls and indirect calls
through normal function pointers).

Related: #140933
2026-01-30 12:05:15 -08:00
Damian Heaton
762ba885f9
[LV] Add support for llvm.vector.partial.reduce.fadd (#163975)
Allows the Loop Vectorizer to generate `llvm.vector.partial.reduce.fadd`
intrinsics when sequences which match its requirements are found.
2026-01-28 15:05:34 +00:00
hanbeom
16d8d4b84e
[WebAssembly] Fix crash in ReplaceNodeResults for ANY_EXTEND_VECTOR_INREG (#178374)
Fixes a crash during type legalization by allowing
ISD::ANY_EXTEND_VECTOR_INREG to fall back to default expansion instead
of hitting llvm_unreachable.

Fixed: #177209
2026-01-28 20:45:04 +09:00
Sam Parker
1e0114c21d
[WebAssembly] Zero and NaN checks for min/max (#177968)
Custom lower FMINNUM, FMINIMUMNUM, FMAXNUM and FMAXIMUMNUM to generate
relaxed_min and relaxed_max when the inputs cannot be NaN or signed
zero.

Tablegen patterns have also been modified to check the above conditions
when trying to match relaxed min/max using the pmin/pmax pattern.
2026-01-28 09:25:41 +00:00
Florian Hahn
b794baf8e7
[TTI] Add VectorInstrContext for context-aware insert/extract costs. (#175982)
This commit introduces the VectorInstrContext (VIC) infrastructure to
improve cost estimates for insert/extracts based on the context
instruction in which the insert/extract is used.

This is similar to CastContextHint, and allows providing context on how
the insert/extract is going to be used before creating IR. This is
useful in the LoopVectorizer, where costs need to estimated before
creating IR.

The new hint currently only replaces an existing check in AArch64,
but new uses will be introduced in follow-ups, including
https://github.com/llvm/llvm-project/pull/177201.

PR: https://github.com/llvm/llvm-project/pull/175982
2026-01-27 16:30:29 +00:00
Anutosh Bhat
2503ffbdf3
[WebAssembly] Fix exception handling initialization order in TargetMachine constructor (#177542)
The WebAssemblyTargetMachine constructor had an ordering issue where
initAsmInfo() was called before basicCheckForEHAndSjLj(). This caused
problems in incremental compilation scenarios where:

1. `initAsmInfo()` sets `MCAsmInfo` exception type based on
`Options.ExceptionModel`
2. But `Options.ExceptionModel` might still be None at this point
3. `basicCheckForEHAndSjLj()` runs later and updates
`Options.ExceptionModel`
   based on command-line flags like `-wasm-enable-eh`
4. `MCAsmInfo` retains the incorrect exception type (`None` instead of
`Wasm`)
5. This prevents WebAssembly exception handling passes from running

The fix swaps the order so basicCheckForEHAndSjLj() runs first to
establish the correct exception model before initAsmInfo() configures
MCAsmInfo based on that model.

This enables WebAssembly exception handling to work correctly in
clang-repl and other incremental compilation scenarios.
2026-01-24 06:26:02 +00: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
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