summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
AgeCommit message (Collapse)Author
2025-11-20[WebAssembly] Lower ANY_EXTEND_VECTOR_INREG (#167529)Sam Parker
Treat it in the same manner of zero_extend_vector_inreg and generate an extend_low_u if possible. This is to try an prevent expensive shuffles from being generated instead. computeKnownBitsForTargetNode has also been updated to specify known zeros on extend_low_u.
2025-11-19CodeGen: Add subtarget to TargetLoweringBase constructor (#168620)Matt Arsenault
Currently LibcallLoweringInfo is defined inside of TargetLowering, which is owned by the subtarget. Pass in the subtarget so we can construct LibcallLoweringInfo with the subtarget. This is a temporary step that should be revertable in the future, after LibcallLoweringInfo is moved out of TargetLowering.
2025-11-17[WebAssembly] Truncate extra bits of large elements in BUILD_VECTOR (#167223)Hongyu Chen
Fixes https://github.com/llvm/llvm-project/issues/165713 This patch handles out-of-bound vector elements and truncates extra bits.
2025-11-06[WebAssembly] vf32 to vi8, vi16 lowering (#164644)Sam Parker
Avoid scalarizing the conversion and use trunc_sat and narrow instead.
2025-11-05[WebAssembly] TableGen-erate SDNode descriptions (#166259)Sergei Barannikov
This allows SDNodes to be validated against their expected type profiles and reduces the number of changes required to add a new node. CALL and RET_CALL do not have a description in td files, and it is not currently possible to add one as these nodes have both variable operands and variable results. This also fixes a subtle bug detected by the enabled verification functionality. `LOCAL_GET` is declared with `SDNPHasChain` property, and thus should have both a chain operand and a chain result. The original code created a node without a chain result, which caused a check in `SDNodeInfo::verifyNode()` to fail. Part of #119709. Pull Request: https://github.com/llvm/llvm-project/pull/166259
2025-10-22[WebAssembly] [Codegen] Add pattern for relaxed min max from ↵Jasmine Tang
fminimum/fmaximum over v4f32 and v2f64 (#162948) Related to #55932
2025-10-14[WebAssembly] Optimize lowering of constant-sized memcpy and memset (#163294)Derek Schuff
We currently emit a check that the size operand isn't zero, to avoid executing the wasm memory.copy instruction when it would trap. But this isn't necessary if the operand is a constant. Fixes #163245
2025-10-13Wasm fmuladd relaxed (#163177)Sam Parker
Reland #161355, after fixing up the cross-projects-tests for the wasm simd intrinsics. Original commit message: Lower v4f32 and v2f64 fmuladd calls to relaxed_madd instructions. If we have FP16, then lower v8f16 fmuladds to FMA. I've introduced an ISD node for fmuladd to maintain the rounding ambiguity through legalization / combine / isel.
2025-10-13Revert "[WebAssembly] Lower fmuladd to madd and nmadd" (#163171)Sam Parker
Reverts llvm/llvm-project#161355 Looks like I've broken some intrinsic code generation.
2025-10-13[WebAssembly] Lower fmuladd to madd and nmadd (#161355)Sam Parker
Lower v4f32 and v2f64 fmuladd calls to relaxed_madd instructions. If we have FP16, then lower v8f16 fmuladds to FMA. I've introduced an ISD node for fmuladd to maintain the rounding ambiguity through legalization / combine / isel.
2025-10-07[WebAssembly] Check intrinsic argument count before Any/All combine (#162163)Derek Schuff
This code is activated on all INTRINSIC_WO_CHAIN but only handles a selection. However it was trying to read the arguments before checking which intrinsic it was handling. This fails for intrinsics that have no arguments.
2025-09-30[WebAssembly] Use partial_reduce_mla ISD nodes (#161184)Sam Parker
Addresssing issue #160847. Move away from combining the intrinsic call and instead lower the ISD nodes, using tablegen for pattern matching.
2025-09-17[IR] NFC: Remove 'experimental' from partial.reduce.add intrinsic (#158637)Sander de Smalen
The partial reduction intrinsics are no longer experimental, because they've been used in production for a while and are unlikely to change.
2025-09-12[WebAssembly] Support partial-reduce accumulator (#158060)Sam Parker
We currently only support partial.reduce.add in the case where we are performing a multiply-accumulate. Now add support for any partial reduction where the input is being extended, where we can take advantage of extadd_pairwise.
2025-09-10[WebAssembly] extadd_pairwise for PartialReduce (#157669)Sam Parker
Avoid using extends, and adding the high and low half and use extadd_pairwise instead.
2025-08-27[WebAssembly] v8i8 mul support (#151145)Sam Parker
During DAG combine, promote the operands to v8i16 by concanting with an undef vector and then use extmul_low to perform the mul at i16. Finally, shuffle the low bytes out of the i16 elements into the result vector.
2025-08-22[WebAssembly] Add support for avgr_u in loops (#153252)Jasmine Tang
Fixes https://github.com/llvm/llvm-project/issues/150550. With the test case ``` void f(unsigned char *x, unsigned char *y, int n) { // should have been vectorized into avgr_u instead of seperated vectorized add and logical right shift for (int i = 0; i < n; i++) x[i] = (x[i] + y[i] + 1) / 2; } ``` the backend failed to recognize that this can be reduced to avgr_u since the loop vectorizer doesn't transform into the existing pattern in tablegen. This PR sets AVGCEIL_U as legal for v8i16 and v16i8 and selects it to avgr_u in the tablegen file.
2025-08-15[WebAssembly] Reapply #149461 with correct CondCode in combine of SETCC ↵Jasmine Tang
(#153703) This PR reapplies https://github.com/llvm/llvm-project/pull/149461 In the original `combineVectorSizedSetCCEquality`, the result of setcc is being negated by returning setcc with the same cond code, leading to wrong logic. For example, with ```llvm %cmp_16 = call i32 @memcmp(ptr %a, ptr %b, i32 16) %res = icmp eq i32 %cmp_16, 0 ``` the original PR producese all_true and then also compares the result equal to 0 (using the same SETEQ in the returning setcc), meaning that semantically, it effectively is calling icmp ne. Instead, the PR should have use SETNE in the returning setcc, this way, all true return 1, then it is compared again ne 0, which is equivalent to icmp eq.
2025-08-13[CodeGen] Remove default ctors for InputArg and OutputArg (#153205)Nikita Popov
These make it easy to forget to initialize some members, like the newly added OrigTy. Force these to always go through the ctor instead.
2025-08-13Revert "[WebAssembly] Combine i128 to v16i8 for setcc & expand memcmp for 16 ↵Jasmine Tang
byte loads with simd128" (#153360) Reverts llvm/llvm-project#149461 The first test w/ memcmp in `test/neon/test_neon_wasm_simd.cpp` in the Emscripten test suite has failed. This PR applies a revert so I can take a closer look at it Test case link: https://github.com/emscripten-core/emscripten/blob/main/test/neon/test_neon_wasm_simd.cpp Compile option: `em++ test_neon_wasm_simd.cpp -O2 -mfpu=neon -msimd128 -o something.js` Original comment report: https://github.com/llvm/llvm-project/pull/149461#issuecomment-3181652746
2025-08-12[WebAssembly] Combine i128 to v16i8 for setcc & expand memcmp for 16 byte ↵Jasmine Tang
loads with simd128 (#149461) Fixes https://github.com/llvm/llvm-project/issues/149230 Previously, even with simd enabled via `-mattr=+simd128`, the compiler cannot utilize v128 to optimize loads and setcc of i128, instead legalizing it to consecutive i64s. This PR then adds support for setcc of i128 by converting them to v16i8's anytrue and alltrue; consequently, this benefits memcmp of 16 bytes or more (when simd128 is present). The check for enabling this optimization is if the comparison operand is either a load or an integer in i128, with the comparison code being either `EQ | NE`, without `NoImplicitFloat` function flag. Inspiration taken from RISCV's isel lowering.
2025-08-07[CodeGen] Move IsFixed into ArgFlags (NFCI) (#152319)Nikita Popov
The information whether a specific argument is vararg or fixed is currently stored separately from all the other argument information in ArgFlags. This means that it is not accessible from CCAssign, and backends have developed all kinds of workarounds for how they can access it after all. Move this information to ArgFlags to make it directly available in all relevant places. I've opted to invert this and store it as IsVarArg, as I think that both makes the meaning more obvious and provides for a better default (which is IsVarArg=false).
2025-07-29[WebAssembly] v16i8 mul support (#150209)Sam Parker
During target DAG combine, use two i16x8.extmul_low_i8x16 and a shuffle for v16i8 mul. On my AArch64 machine, using V8, I observe a 3.14% geomean improvement across 65 benchmarks, including: 9.2% for spec2017.x264, 6% for libyuv and 1.8% for ncnn.
2025-07-25[WebAssembly] Added vectorized version of fexp10 to the supported list (#150564)Jasmine Tang
Fixes https://github.com/llvm/llvm-project/issues/117200. The default behavior in TargetLoweringBase is only scalar floats on fexp are supported by default, not the vectorized version. This PR adds `ISD::FEXP10` to the supported list.
2025-07-22[WebAssembly,llvm] Add llvm.wasm.ref.test.func intrinsic (#147486)Hood Chatham
This adds an llvm intrinsic for WebAssembly to test the type of a function. It is intended for adding a future clang builtin ` __builtin_wasm_test_function_pointer_signature` so we can test whether calling a function pointer will fail with function signature mismatch. Since the type of a function pointer is just `ptr` we can't figure out the expected type from that. The way I figured out to encode the type was by passing 0's of the appropriate type to the intrinsic. The first argument gives the expected type of the return type and the later values give the expected type of the arguments. So ```llvm @llvm.wasm.ref.test.func(ptr %func, float 0.000000e+00, double 0.000000e+00, i32 0) ``` tests if `%func` is of type `(double, i32) -> (i32)`. It will lower to: ```wat local.get $func table.get $__indirect_function_table ref.test (double, i32) -> (i32) ``` To indicate the function should be void, I somewhat arbitrarily picked `token poison`, so the following tests for `(i32) -> ()`: ```llvm @llvm.wasm.ref.test.func(ptr %func, token poison, i32 0) ``` To lower this intrinsic, we need some place to put the type information. With `encodeFunctionSignature()` we encode the signature information into an `APInt`. We decode it in `lowerEncodedFunctionSignature` in `WebAssemblyMCInstLower.cpp`.
2025-07-21[WebAssembly] Optimize convert_iKxN_u into convert_iKxN_s (#149609)Arseny Kapoulkine
convert_iKxN_s is canonicalized into convert_iKxN_u when the argument is known to have sign bit 0. This results in emitting Wasm opcodes that, on some targets (like x86_64), are dramatically slower than signed versions on major engines. Similarly to X86, we now fix this up in isel when the instruction has nonneg flag from canonicalization or if we know the source has zero sign bit. Fixes #149457.
2025-07-20[WebAssembly] Add support for memcmp expansion (#148298)Jasmine Tang
Fixes https://github.com/llvm/llvm-project/issues/61400 Added test case in llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
2025-07-07DAG: Remove verifyReturnAddressArgumentIsConstant (#147240)Matt Arsenault
The intrinsic argument is already marked with immarg so non-constant values are rejected by the IR verifier.
2025-07-01[WebAssembly] Fold any/alltrue (setcc x, 0, eq/ne) to [not] any/alltrue x ↵jjasmine
(#144741) Fixes https://github.com/llvm/llvm-project/issues/50142, a miss of further vectorization, where we can only achieve zext (xor (any_true), -1). Now in test case simd-setcc-reductions, it's converted to all_true. Also fixes https://github.com/llvm/llvm-project/issues/145177, which is all_true (setcc x, 0, eq) -> not any_true any_true (setcc x, 0, ne) -> any_true all_true (setcc x, 0, ne) -> all_true --------- Co-authored-by: badumbatish <--show-origin>
2025-07-01[WebAssembly] [Backend] Wasm optimize illegal bitmask (#145627)jjasmine
[WebAssembly] [Backend] Wasm optimize illegal bitmask for #131980. Currently, the case for illegal bitmask (v32i8 or v64i8) is that at the SelectionDag level, two (four) vectors of v128 will be concatenated together, then they'll all be SETCC by the same pseudo illegal instruction, which requires expansion later on. I opt for SETCC-ing them seperately, bitcast and zext them and then add them up together in the end. --------- Co-authored-by: badumbatish <--show-origin>
2025-06-25[WebAssembly] Refactor PerformSETCCCombine (#144875)Sam Parker
Extract the logic into a templated helper function.
2025-06-16WebAssembly: Move runtime libcall setting out of TargetLowering (#142624)Matt Arsenault
RuntimeLibcallInfo needs to be correct outside of codegen contexts.
2025-05-18[llvm] Remove unused local variables (NFC) (#140422)Kazu Hirata
2025-05-01[Target] Use llvm::max_element (NFC) (#137926)Kazu Hirata
2025-03-31[WebAssembly] Add a missing `break` statement (#133783)Alex Crichton
This fixes an issue introduced in #132430 where a `break;` statement was accidentally missing causing unintended fall-through.
2025-03-31[WebAssembly] Add more lowerings for wide-arithmetic (#132430)Alex Crichton
This commit is the result of investigation and discussion on WebAssembly/wide-arithmetic#6 where alternatives to the `i64.add128` instruction were discussed but ultimately deferred to a future proposal. In spite of this though I wanted to apply a few changes to the LLVM backend here with `wide-arithmetic` enabled for a few minor changes: * A lowering for the `ISD::UADDO` node is added which uses `add128` where the upper bits of the two operands are constant zeros and the result of the 128-bit addition is the result of the overflowing addition. * The high bits of a `I64_ADD128` node are now flagged as "known zero" if the upper bits of the inputs are also zero, assisting this `UADDO` lowering to ensure the backend knows that the carry result is a 1-bit result. A few tests were then added to showcase various lowerings for various operations that can be done with wide-arithmetic. They don't all optimize super well at this time but I wanted to add them as a reference here regardless to have them on-hand for future evaluations if necessary.
2025-03-21[WebAssembly] Lower wide SIMD i8 muls (#130785)Sam Parker
Currently, 'wide' i32 simd multiplication, with extended i8 elements, will perform the multiplication with i32 So, for IR like the following: ``` %wide.a = sext <8 x i8> %a to <8 x i32> %wide.b = sext <8 x i8> %a to <8 x i32> %mul = mul <8 x i32> %wide.a, %wide.b ret <8 x i32> %mul ``` We would generate the following sequence: ``` i16x8.extend_low_i8x16_s $push6=, $1 local.tee $push5=, $3=, $pop6 i32x4.extmul_low_i16x8_s $push0=, $pop5, $3 v128.store 0($0), $pop0 i8x16.shuffle $push1=, $1, $1, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 i16x8.extend_low_i8x16_s $push4=, $pop1 local.tee $push3=, $1=, $pop4 i32x4.extmul_low_i16x8_s $push2=, $pop3, $1 v128.store 16($0), $pop2 return ``` But now we perform the multiplication with i16, resulting in: ``` i16x8.extmul_low_i8x16_s $push3=, $1, $1 local.tee $push2=, $1=, $pop3 i32x4.extend_high_i16x8_s $push0=, $pop2 v128.store 16($0), $pop0 i32x4.extend_low_i16x8_s $push1=, $1 v128.store 0($0), $pop1 return ```
2025-02-25[WebAssembly] Use the same lowerings for f16x8 as other float vectors. (#127897)Brendan Dahl
This fixes failures to select the various compare operations that weren't being expanded for f16x8.
2025-02-25[WebAssembly] Support shuffle for F16x8 vectors. (#127857)Brendan Dahl
2025-02-19[CodeGen] Use __extendhfsf2 and __truncsfhf2 by default (#126880)Nikita Popov
The standard libcalls for half to float and float to half conversion are __extendhfsf2 and __truncsfhf2. However, LLVM currently uses __gnu_h2f_ieee and __gnu_f2h_ieee instead. As far as I can tell, these libcalls are an ARM-ism and only provided by libgcc on that platform. compiler-rt always provides both libcalls. Use the standard libcalls by default, and only use the __gnu libcalls on ARM.
2025-02-17[WebAssembly] Recognise EXTEND_HIGH (#123325)Sam Parker
When lowering EXTEND_VECTOR_INREG, check whether the operand is a shuffle that is moving the top half of a vector into the lower half. If so, we can EXTEND_HIGH the input to the shuffle instead.
2025-02-03[WebAssembly] Autovec support for dot (#123207)Sam Parker
Enable the use of partial.reduce.add that we can lower to dot or a tree of (add (extmul_low_u, extmul_high_u)) for the unsigned case. We support both v8i16 and v16i8 inputs.
2025-01-20[Mips] Fix compiler crash when returning fp128 after calling a functi… ↵yingopq
(#117525) …on returning { i8, i128 } Fixes https://github.com/llvm/llvm-project/issues/96432.
2024-12-21[SelectionDAG] Virtualize isTargetStrictFPOpcode / isTargetMemoryOpcode ↵Sergei Barannikov
(#119969) With this change, targets are no longer required to put memory / strict-fp opcodes after special `ISD::FIRST_TARGET_MEMORY_OPCODE`/`ISD::FIRST_TARGET_STRICTFP_OPCODE` markers. This will also allow autogenerating `isTargetMemoryOpcode`/`isTargetStrictFPOpcode (#119709). Pull Request: https://github.com/llvm/llvm-project/pull/119969
2024-12-09Reapply "[DAGCombiner] Add support for scalarising extracts of a vector ↵David Sherwood
setcc (#117566)" (#118823) [Reverts d57892a2a153ab71a796f07e39d939eae6910c21] For IR like this: %icmp = icmp ult <4 x i32> %a, splat (i32 5) %res = extractelement <4 x i1> %icmp, i32 1 where there is only one use of %icmp we can take a similar approach to what we already do for binary ops such add, sub, etc. and convert this into %ext = extractelement <4 x i32> %a, i32 1 %res = icmp ult i32 %ext, 5 For AArch64 targets at least the scalar boolean result will almost certainly need to be in a GPR anyway, since it will probably be used by branches for control flow. I've tried to reuse existing code in scalarizeExtractedBinop to also work for setcc. NOTE: The optimisations don't apply for tests such as extract_icmp_v4i32_splat_rhs in the file CodeGen/AArch64/extract-vector-cmp.ll because scalarizeExtractedBinOp only works if one of the input operands is a constant. --------- Co-authored-by: Paul Walker <paul.walker@arm.com>
2024-12-04Revert "[DAGCombiner] Add support for scalarising extracts of a vector ↵Vitaly Buka
setcc" (#118693) Reverts llvm/llvm-project#117566 Breaks libc++ tests with HWASAN https://lab.llvm.org/buildbot/#/builders/55/builds/3959
2024-12-04[DAGCombiner] Add support for scalarising extracts of a vector setcc (#117566)David Sherwood
For IR like this: %icmp = icmp ult <4 x i32> %a, splat (i32 5) %res = extractelement <4 x i1> %icmp, i32 1 where there is only one use of %icmp we can take a similar approach to what we already do for binary ops such add, sub, etc. and convert this into %ext = extractelement <4 x i32> %a, i32 1 %res = icmp ult i32 %ext, 5 For AArch64 targets at least the scalar boolean result will almost certainly need to be in a GPR anyway, since it will probably be used by branches for control flow. I've tried to reuse existing code in scalarizeExtractedBinop to also work for setcc. NOTE: The optimisations don't apply for tests such as extract_icmp_v4i32_splat_rhs in the file CodeGen/AArch64/extract-vector-cmp.ll because scalarizeExtractedBinOp only works if one of the input operands is a constant.
2024-12-02[WebAssembly] Define call-indirect-overlong and bulk-memory-opt features ↵Dan Gohman
(#117087) This defines some new target features. These are subsets of existing features that reflect implementation concerns: - "call-indirect-overlong" - implied by "reference-types"; just the overlong encoding for the `call_indirect` immediate, and not the actual reference types. - "bulk-memory-opt" - implied by "bulk-memory": just `memory.copy` and `memory.fill`, and not the other instructions in the bulk-memory proposal. This is split out from https://github.com/llvm/llvm-project/pull/112035. --------- Co-authored-by: Heejin Ahn <aheejin@gmail.com>
2024-11-26[WebAssembly] Implement %llvm.thread.pointer intrinsic (#117817)Sam Clegg
We can simply use the `__tls_base` global for this which is guaranteed to be non-zero and unique per thread. Fixes: #117433
2024-11-25Revert "[DAGCombiner] Add support for scalarising extracts of a vector setcc ↵David Sherwood
(#116031)" (#117556) This reverts commit 22ec44f509ff266b581dbb490d7b040473b7c31a.