3851 Commits

Author SHA1 Message Date
Simon Pilgrim
497ea1d849 [DAG] tryToFoldExtendSelectLoad - reuse existing SDLoc. NFC. 2024-07-18 16:19:15 +01:00
Lawrence Benson
177ce1900f
[LLVM] Add llvm.experimental.vector.compress intrinsic (#92289)
This PR adds a new vector intrinsic `@llvm.experimental.vector.compress`
to "compress" data within a vector based on a selection mask, i.e., it
moves all selected values (i.e., where `mask[i] == 1`) to consecutive
lanes in the result vector. A `passthru` vector can be provided, from
which remaining lanes are filled.

The main reason for this is that the existing
`@llvm.masked.compressstore` has very strong constraints in that it can
only write values that were selected, resulting in guard branches for
all targets except AVX-512 (and even there the AMD implementation is
_very_ slow). More instruction sets support "compress" logic, but only
within registers. So to store the values, an additional store is needed.
But this combination is likely significantly faster on many target as it
avoids branches.

In follow up PRs, my plan is to add target-specific lowerings for x86,
SVE, and possibly RISCV. I also want to combine this with a store
instruction, as this is probably a common case and we can avoid some
memory writes in that case.

See [discussion in
forum](https://discourse.llvm.org/t/new-intrinsic-for-masked-vector-compress-without-store/78663)
for initial discussion on the design.
2024-07-17 14:24:24 +02:00
Joseph Huber
c05126bdfc
[LLVM][LTO] Factor out RTLib calls and allow them to be dropped (#98512)
Summary:
The LTO pass and LLD linker have logic in them that forces extraction
and prevent internalization of needed runtime calls. However, these
currently take all RTLibcalls into account, even if the target does not
support them. The target opts-out of a libcall if it sets its name to
nullptr. This patch pulls this logic out into a class in the header so
that LTO / lld can use it to determine if a symbol actually needs to be
kept.

This is important for targets like AMDGPU that want to be able to use
`lld` to perform the final link step, but does not want the overhead of
uncalled functions. (This adds like a second to the link time trivially)
2024-07-16 06:22:09 -05:00
Simon Pilgrim
290537238b [X86] visitADDLike - pull out repeated SDLoc. NFC. 2024-07-15 17:20:58 +01:00
Simon Pilgrim
3560e1d0ce [DAG] visitADDLike - convert (A-B)+(C-D) --> (A+C)-(B+D) fold to sd_match. NFC. 2024-07-15 17:20:58 +01:00
Simon Pilgrim
ba8792b667 [X86] visitFCOPYSIGN - pull out repeated SDLoc. NFC. 2024-07-15 16:34:21 +01:00
Simon Pilgrim
61a4e1e70f
[DAG] Add SDPatternMatch::m_SetCC and update some combines to use it (#98646)
The plan is to add more TernaryOp in the future (SELECT/VSELECT and FMA in particular)
2024-07-14 17:18:43 +01:00
Kazu Hirata
66cd2e0f9a
[CodeGen] Use range-based for loops (NFC) (#98706) 2024-07-13 13:29:47 -07:00
AtariDreams
4f8b2fff6d
[DAG] Use break instead of continue to leave do while (false) loop (NFC) (#97966) 2024-07-10 20:51:06 +04:00
Craig Topper
33112cbf59 [DAGCombiner] Remove unnecessary assert from getShiftAmountTy wrapper. NFC
The same assert appears in the TargetLowering function.

Refine comment to describe as a convenience wrapper and leave it to
TargetLowering documentation to explain.
2024-07-04 19:05:54 -07:00
Craig Topper
8419da8bd4
[SelectionDAG] Remove LegalTypes argument from getShiftAmountConstant. (#97653)
#97645 proposed to remove LegalTypes from getShiftAmountTy. This patches
removes it from getShiftAmountConstant which is one of the callers of
getShiftAmountTy.
2024-07-04 18:33:25 -07:00
Craig Topper
3141c11fe8
[SelectionDAG] Remove LegalTypes argument from getShiftAmountTy. NFC (#97757)
This argument is no longer used inside the function. Remove it from the
interface.
2024-07-04 15:24:54 -07:00
Craig Topper
34fe032fdb
[DAGCombiner] Use getShiftAmountConstant where possible. (#97683)
In #97645, I proposed removing the LegalTypes operand to
TargetLowering::getShiftAmountTy. This means we don't need to use the
DAGCombiner wrapper for getShiftAmountTy that manages this flag. Now we
can use getShiftAmountConstant and let it call
TargetLowering::getShiftAmountTy.
2024-07-04 08:44:50 -07:00
Craig Topper
a3c5c83273 [DAGCombiner] Remove unneeded getValueType() calls in visitMULHS/MULHU. NFC
We have an existing VT variable that should match N0.getValueType.
2024-07-03 13:35:04 -07:00
Simon Pilgrim
163d00c666 [DAG] Pull out repeated SDLoc in SELECT/SETCC folds. NFC. 2024-07-01 18:03:46 +01:00
Matt Arsenault
8eee6d33f7
DAG: Call SimplifyDemandedBits on copysign value operand (#97180)
So far the only cases that seem to benefit are the weird
copysign with different typed inputs.
2024-07-01 12:29:11 +02:00
Matt Arsenault
db9252b115
DAG: Call SimplifyDemandedBits on fcopysign sign value (#97151)
Math library code has quite a few places with complex bit
logic that are ultimately fed into a copysign. This helps
avoid some regressions in a future patch.

This assumes the position in the float type, which should
at least be valid for IEEE types. Not sure if we need to guard
against ppc_fp128 or anything else weird.

There appears to be some value in simplifying the value operand
as well, but I'll address that separately.
2024-07-01 12:19:17 +02:00
Nikita Popov
f2f18459d4 Revert "Intrinsic: introduce minimumnum and maximumnum (#93841)"
As far as I can tell, this pull request was not approved, and
did not go through an RFC on discourse.

This reverts commit 89881480030f48f83af668175b70a9798edca2fb.
This reverts commit 225d8fc8eb24fb797154c1ef6dcbe5ba033142da.
2024-06-21 08:34:04 +02:00
YunQiang Su
8988148003
Intrinsic: introduce minimumnum and maximumnum (#93841)
Currently, on different platform, the behaivor of llvm.minnum is
different if one operand is sNaN:

When we compare sNaN vs NUM:

ARM/AArch64/PowerPC: follow the IEEE754-2008's minNUM: return qNaN.
RISC-V/Hexagon follow the IEEE754-2019's minimumNumber: return NUM. X86:
Returns NUM but not same with IEEE754-2019's minimumNumber as
     +0.0 is not always greater than -0.0.
MIPS/LoongArch/Generic: return NUM.
LIBCALL: returns qNaN.

So, let's introduce llvm.minmumnum/llvm.maximumnum, which always follow
IEEE754-2019's minimumNumber/maximumNumber.

Half-fix: #93033
2024-06-21 11:53:08 +08:00
Simon Pilgrim
7e3507e2f5 [DAG] visitAVG - avoid duplication in the avg(ext(x), ext(y)) -> ext(avg(x, y)) folds
m_BinOp doesn't need a compile time opcode - so we can merge these into signed/unsigned cases.
2024-06-17 18:01:12 +01:00
Paul Walker
f06d96995a
[LLVM][DAGCombiner] Extend coverage for insert_subv(undef, extract_subv(A, 0), 0) (#95242)
There is an existing combine to remove the need for extract_subv that
requires matching vector types (all fixed or all scalable).

The combine doesn't need this restriction and so I've changed it to use
ValueType's "knownBits??" interface that supports mixed vector types. In
doing so we also need extra guards to prevent invalid operations (e.g.
extracting a scalable vector from a fixed length vector).
2024-06-17 12:26:04 +01:00
Simon Pilgrim
213e308633 [DAG] Fold Y = sra (X, size(X)-1); mul (or (Y, 1), X) -> (abs X)
Similar to InstCombine implementation except we don't have to handle the NSW/is_int_min_poison case.
2024-06-15 21:10:00 +01:00
c8ef
08fae467e4
[DAG] fold avgs(sext(x), sext(y)) -> sext(avgs(x, y)) (#95365)
Follow up of #95134.

Context:
https://github.com/llvm/llvm-project/pull/95134#issuecomment-2162825594.
2024-06-14 21:53:29 +08:00
Simon Pilgrim
b1484f7de0 [DAG] visitAVG - use X/Y SDValue args to match the fold comment. NFC. 2024-06-12 16:32:35 +01:00
Simon Pilgrim
ea2ee5dc2f
[DAG] Add legalization handling for AVGCEIL/AVGFLOOR nodes (#92096)
Always match AVG patterns pre-legalization, and use TargetLowering::expandAVG to expand again during legalization.

I've removed the X86 custom AVGCEILU pattern detection and replaced with combines to try and convert other AVG nodes to AVGCEILU.
2024-06-12 14:11:07 +01:00
c8ef
0e346eeac6
[DAG] fold avgu(zext(x), zext(y)) -> zext(avgu(x, y)) (#95134)
close: #86301
2024-06-12 12:58:49 +01:00
David Green
a284bdb311 [DAG] Fold fdiv X, c2 -> fmul X, 1/c2 without AllowReciprocal if exact (#93882)
This moves the combine of fdiv by constant to fmul out of an
'if (Options.UnsafeFPMath || Flags.hasAllowReciprocal()' block,
so that it triggers if the divide is exact. An extra check for
Recip.isDenormal() is added as multiple places make reference
to it being unsafe or slow on certain platforms.
2024-06-09 12:28:20 +01:00
Yingwei Zheng
d9507a3e10
[DAGCombine] Fix miscompilation caused by PR94008 (#94850)
The pr description in #94008 mismatches with the code.
> + When VT is smaller than ShiftVT, it is safe to use trunc.
> + When VT is larger than ShiftVT, it is safe to use zext iff
`is_zero_poison` is true (i.e., `opcode == ISD::CTTZ_ZERO_UNDEF`). See
also the counterexample `src_shl_cttz2 -> tgt_shl_cttz2` in the alive2
    proofs.

Closes #94824.
2024-06-08 21:40:57 +08:00
Quentin Colombet
25506f4864
[SDISel][Combine] Constant fold FP16_TO_FP (#94790)
In some case, constant can survive early constant folding optimization
because they are hidden behind several layers of type changes.

E.g., consider the following sequence (extracted from the arm test that
this commit changes):
```
    t2: v1f16 = BUILD_VECTOR ConstantFP:f16<APFloat(0)>
    t4: v1f16 = insert_vector_elt t2, ConstantFP:f16<APFloat(0)>, Constant:i32<0>
  t5: f16 = bitcast t4
t6: f32 = fp_extend t5
```

Because the constant (APFloat(0)) is hidden behind a <1 x ty> type, all
the constant folding that normally happen for scalar nodes when using
`SelectionDAG::getNode` are blocked.

As a result the constant manages to survive as an actual conversion
instruction down to the select phase:
```
t11: f32 = fp16_to_fp Constant:i32<0>
```

With the change in this patch, we try to do constant folding one more
time during dag combine, which in the motivating example result in the
much better sequence:
```
t7: ch = CopyToReg t0, Register:f32 %0, ConstantFP:f32<0.000000e+00>
```

Note: I'm sure we have this problem in a lot of other places. Generally
speaking I believe SDISel is not that good with <1 x ty> compared to
pure scalar. However, I only changed what I could easily test.
2024-06-08 11:31:13 +02:00
aengelke
74d62c2f73
[CodeGen][SDAG] Remove CombinedNodes SmallPtrSet (#94609)
This "small" set grows quite large and it's more performant to store
whether a node has been combined before in the node itself.

As this information is only relevant for nodes that are currently not in
the worklist, add a second state to the CombinerWorklistIndex (-2) to
indicate that a node is currently not in a worklist, but was combined
before.

This brings a substantial performance improvement.
2024-06-07 13:17:27 +02:00
Simon Pilgrim
af3ffff34f
[DAG] Always allow folding XOR patterns to ABS pre-legalization (#94601)
Removes residual ARM handling for vXi64 ABS nodes to prevent infinite loops.
2024-06-07 11:02:50 +01:00
Simon Pilgrim
03a2fe9a75 [DAG] visitSUB - update the ABS matching code to use SDPatternMatch and hasOperation.
Avoids the need to explicitly test both commuted variants and doesn't match custom lowering after legalization.

Cleanup for #94504
2024-06-06 10:06:57 +01:00
aengelke
6150e84cfc
[CodeGen][SDAG] Remove Combiner WorklistMap (#92900)
DenseMap for pointer lookup is expensive, and this is only used for
deduplication and index lookup. Instead, store the worklist index in the
node itself.

This brings a substantial performance improvement.
2024-06-05 17:58:08 +02:00
Yingwei Zheng
47fd32f81c
[DAGCombine] Fix type mismatch in (shl X, cttz(Y)) -> (mul (Y & -Y), X) (#94008)
Proof: https://alive2.llvm.org/ce/z/J7GBMU

Same as https://github.com/llvm/llvm-project/pull/92753, the types of
LHS and RHS in shift nodes may differ.
+ When VT is smaller than ShiftVT, it is safe to use trunc.
+ When VT is larger than ShiftVT, it is safe to use zext iff
`is_zero_poison` is true (i.e., `opcode == ISD::CTTZ_ZERO_UNDEF`). See
also the counterexample `src_shl_cttz2 -> tgt_shl_cttz2` in the alive2
proofs.

Fixes issue
https://github.com/llvm/llvm-project/pull/85066#issuecomment-2142553617.
2024-06-01 19:04:55 +08:00
Jay Foad
b1be480b03 [DAGCombiner] Move CanReassociate down to first use. NFC. 2024-05-31 09:44:47 +01:00
Jianjian Guan
db6de1a20f
[DAGCombiner][VP] Add DAGCombine for VP_MUL (#80105)
Use visitMUL to combine VP_MUL, share most logic of MUL with VP_MUL.

Migrate from https://reviews.llvm.org/D121187
2024-05-31 10:17:11 +08:00
Yingwei Zheng
9e8ecce88e
[DAGCombine] Transform shl X, cttz(Y) to mul (Y & -Y), X if cttz is unsupported (#85066)
This patch fold `shl X, cttz(Y)` to `mul (Y & -Y), X` if cttz is
unsupported by the target.
Alive2: https://alive2.llvm.org/ce/z/AtLN5Y
Fixes https://github.com/llvm/llvm-project/issues/84763.
2024-05-29 18:26:54 +08:00
Matt Arsenault
16a5fd3fdb
DAG: Use flags in isLegalToCombineMinNumMaxNum (#93555) 2024-05-28 18:57:38 +02:00
Shengchen Kan
eeb2f72a49
[SelectionDAG][X86] Fix the assertion failure in Release build after #91747 (#93434)
In #91747, we changed the SDNode from `X86ISD::SUB` (FROM) to
`X86ISD::CCMP`
(TO) in the DAGCombine. The value type of `X86ISD::SUB` can be `i8, i32`
while the value type of `X86ISD::CCMP` is i32. This breaks the
assumption
that the value type should match after the combine and triggers the
error

```
SelectionDAG.cpp:10942: void
llvm::SelectionDAG::transferDbgValues(llvm::SDValue, llvm::SDValue,
unsigned int, unsigned int, bool): Assertion `FromNode && ToNode &&
"Can't modify dbg values"' failed.
```

when running tests

llvm/test/CodeGen/X86/apx/ccmp.ll
llvm/test/CodeGen/X86/apx/ctest.ll

in Release build when LLVM_ENABLE_ASSERTIONS is on.

In this patch, we fix it by creating a merged value.
2024-05-27 11:33:23 +08:00
Shengchen Kan
331eb8a004
[X86][CodeGen] Support lowering for CCMP/CTEST (#91747)
DAG combine for `CCMP` and `CTESTrr`:

```
and/or(setcc(cc0, flag0), setcc(cc1, sub (X, Y)))
->
setcc(cc1, ccmp(X, Y, ~cflags/cflags, cc0/~cc0, flag0))

and/or(setcc(cc0, flag0), setcc(cc1, cmp (X, 0)))
 ->
setcc(cc1, ctest(X, X, ~cflags/cflags, cc0/~cc0, flag0))
```
 where `cflags` is determined by `cc1`.

Generic DAG combine:
```
cmp(setcc(cc, X), 0)
brcond ne
->
X
brcond cc

sub(setcc(cc, X), 1)
brcond ne
->
X
brcond ~cc
```

Post DAG transform:  `ANDrr/rm + CTESTrr -> CTESTrr/CTESTmr`


Pattern match for `CTESTri`:
```
X= and A, B
ctest(X, X, cflags, cc0/, flag0)
->
ctest(A, B, cflags, cc0/, flag0)
```

`CTESTmi` is already handled by the memory folding mechanism in MIR.
2024-05-26 18:32:23 +08:00
Simon Pilgrim
729fdb6bb6 [DAG] visitFunnelShift - pull out repeated SDLoc. 2024-05-24 14:50:42 +01:00
Simon Pilgrim
7273ad1238 [DAG] visitABD - rewrite "(abs x, 0)" folds to use SDPatternMatch
No need for this to be vector specific, and its more likely that scalar cases will appear after #92576
2024-05-19 11:49:51 +01:00
Simon Pilgrim
9f5c8de386 [DAG] visitAVG - rewrite "fold (avgfloor x, 0) -> x >> 1" to use SDPatternMatch
No need for this to be vector specific, and its more likely that scalar cases will appear after #92096
2024-05-19 11:30:20 +01:00
David Green
4c98f5b439
[DAG] Use copysign in frem power-2 fold. (#91751)
As a small addition to #91148, this uses copysign to produce the correct
sign for zero when converting frem to div/trunc/mul when we do not know
that the input is positive (and we care about sign bits). The copysign
lets us get the sign of zero correct.

In testing, the only case this produced different results than fmod was:
frem -inf, 4.0 -> nan vs -nan
2024-05-18 22:50:19 +01:00
Patrick O'Neill
4ab2ac22d0
[DAGCombiner] Mark vectors as not AllAddOne/AllSubOne on type mismatch (#92195)
Fixes #92193.
2024-05-15 12:39:28 -07:00
Simon Pilgrim
7f3e3785d0 Fix MSVC "result of 32-bit shift implicitly converted to 64 bits" warning. NFC. 2024-05-10 22:40:23 +01:00
Simon Pilgrim
7e6879b245 [X86] scalarizeExtractedBinop - reuse existing SDLoc. NFC. 2024-05-10 22:40:23 +01:00
David Green
8fc9e3d577
[DAG] Lower frem of power-2 using div/trunc/mul+sub (#91148)
If we are lowering a frem and the divisor is known to be an integer power-2, we
can use the formula 'frem = x - trunc(x / d) * d'. This avoids the more
expensive call to fmod. The results are identical as fmod so long as d is a
power-2 (so the mul does not round incorrectly), and the sign of the return is
either always positive or not important for zeroes (nsz).

Unfortunately Alive2 does not handle this well at the moment. I was using
exhaustive checking to test this:
(https://gist.github.com/davemgreen/6078015f30d3bacd1e9572f8db5d4b64).

I found this in cpythons implementation of float_pow. I currently added it as a
DAG combine for frem with power-2 fp constants.
2024-05-10 14:58:48 +01:00
David Green
23b673e5b4
[DAG][AArch64] Handle vscale addressing modes in reassociationCanBreakAddressingModePattern (#89908)
reassociationCanBreakAddressingModePattern tries to prevent bad add
reassociations that would break adrressing mode patterns. This adds
support for vscale offset addressing modes, making sure we don't break
patterns that already exist. It does not optimize _to_ the correct
addressing modes yet, but prevents us from optimizating _away_ from
them.
2024-05-10 09:27:02 +01:00
David Green
fcf945f4ed
[DAG] Fold add(mul(add(A, CA), CM), CB) -> add(mul(A, CM), CM*CA+CB) (#90860)
This is useful when the inner add has multiple uses, and so cannot be
canonicalized by pushing the constants down through the mul. This patch
adds patterns for both `add(mul(add(A, CA), CM), CB)` and with an extra add
`add(add(mul(add(A, CA), CM), B) CB)` as the second can come up when
lowering geps.
2024-05-08 22:11:18 +01:00