2311 Commits

Author SHA1 Message Date
Jim Lin
b7843a2411
[RISCV][NFC] Remove duplicate setTargetDAGCombine registrations (#186928)
ISD::SRA and ISD::MUL are already registered unconditionally in the
constructor, so remove the redundant registrations from the
hasVInstructions() block. Fold the standalone SRA call into the existing
brace-initializer list.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:09:22 +08:00
Craig Topper
f572cc0e7e
[RISCV] Fold (WADDAU -C, -1, rs1, 0) -> (WSUBU rs1, C) where C > 0 (#186638) 2026-03-16 21:13:56 -07:00
Craig Topper
6b1ad6bbfd
[RISCV] Fold waddau/wsubau to waddu/wsubu when possible (#186635)
If the wide input is zero extended and only one narrow input is
used, we can fold to waddu/wsubu.
2026-03-16 09:02:37 -07: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
Kito Cheng
bcdf3c930b
[RISCV] Fix crash in combinePExtTruncate for truncate(srl) without MUL/SUB (#186141)
combinePExtTruncate is called from performTRUNCATECombine when the
P-extension is enabled. It attempts to match patterns like
truncate(srl(mul/sub(...), shamt)) and combine them into P-extension
narrowing shift instructions (e.g. PNSRLI, PNSRAI).

However, after extracting the shift input operand `Op` from the SRL
node, the function unconditionally accessed Op.getOperand(0) and
Op.getOperand(1) without first verifying that Op has at least two
operands. For example, when combining:

```
  truncate(v2i16
    srl(v2i32
      bitcast(v2i32 i64),   <-- Op = bitcast, a unary op with 1 operand
      BUILD_VECTOR <8, 8>))
```

Op is a BITCAST node (unary, only 1 operand), so accessing
Op.getOperand(1) triggers an out-of-bounds assertion:

```
  Assertion `Num < NumOperands && "Invalid child # of SDNode!"' failed.
```

Add an early return when Op has fewer than two operands.
2026-03-13 11:31:04 +08:00
Pengcheng Wang
8cfcf3384f
[RISCV] Combine vwaddu_wv+vabd(u) to vwabda(u)
Note that we only support SEW=8/16 for `vwabda(u)`.

Reviewers: mgudim, preames, mshockwave

Reviewed By: mshockwave

Pull Request: https://github.com/llvm/llvm-project/pull/184603
2026-03-11 15:00:11 +08:00
Jim Lin
2410418d06
[RISCV] Refactor lowerBUILD_VECTOR splat opcode selection to avoid duplication. NFC. (#185573)
Hoist the common ANY_EXTEND, DAG.getNode, and convertFromScalableVector
calls out of the duplicated if/else branches. Use a single IsScalar bool
to select between VMV_S_X_VL/VFMV_S_F_VL and VMV_V_X_VL/VFMV_V_F_VL.
2026-03-11 08:57:57 +08:00
Jim Lin
48473ddcc7
[RISCV] Handle sign_extend of i32 in insert_vector_elt for RV32 (#185548)
On RV32 with <N x i64> vectors, inserting a value that is a
sign_extend of an i32 only uses the lower 32 bits, so it can be
lowered without scalar legalization, same as i32 constants.
2026-03-10 13:12:55 +08:00
Craig Topper
3164d54877
[RISCV][P-ext] Custom legalize i64 SHL to WSLL(I)/WSLA(I) (#185079)
When input is zero or sign extended.
2026-03-06 15:27:57 -08:00
Craig Topper
bdec4da38d
[RISCV][P-ext] Only support sshlsat for splat immediate shift amounts. (#184886)
Fixes cannot select errors for other types of shift amounts.

I've made a new RISCVISD node that only allows an immediate operand.
It's assumed that the lowering code will only allow valid immediates so
I'm not using a TImmLeaf in the match.
2026-03-06 12:24:14 -08:00
Craig Topper
bb1d53bbd8
[RISCV][P-ext] Support vector ISD::ABS using PABD instructions. (#184822) 2026-03-06 10:21:25 -08:00
Craig Topper
b51859cb3d
[RISCV][P-ext] Recognize vector shifts with splat build_vector shift amount. (#184909)
If the shift is created during LegalizeVectorOps, the shift amount
will be created as a build_vector. Splat_vector is formed by a later
DAGCombine. LegalizeVectorOps will visit the new shift before the
splat_vector can be created. Handle this case too
2026-03-05 23:55:57 -08:00
joshua-arch1
301597950a
[RISCV] Support 'f' Inline Assembly Constraint for bfloat16 (#184566)
This patch is to add 'f' and 'cf' Inline Assembly Constraint for the `bfloat16` type, so they are passed in the floating point registers.
2026-03-05 20:21:22 -08:00
Jim Lin
eaae8e2503
[RISCV] Remove outdated TODO in isExtractSubvectorCheap (#184938)
Index 0 is already handled by an early return, so the TODO comment about
extracting index 0 from a mask vector is no longer needed.
2026-03-06 11:36:07 +08:00
Craig Topper
add7b711de
[RISCV] Add RISCVISD opcodes for PSHL/PSRL/PSRA and lower to them. (#184836)
We only support splat shift amounts. Previously we checked if the shift
amount was a splat_vector and considered it legal.

I don't think there is a guarantee that the splat_vector will stick
around as a splat_vector. It's safer if we capture the splat and create
a dedicated node with a scalar shift amount.
2026-03-05 12:41:45 -08:00
Craig Topper
3ed12eb3ff
[RISCV][P-ext] Fix cannot select error for shlsat with i8 vector argument. (#184839)
We don't have instructions for an i8 sshlat.
2026-03-05 11:00:21 -08:00
Craig Topper
efb6f542c3
[RISCV] Don't make ISD::ABDS/ABDU legal for v2i32 with P extension. (#184753)
We don't have the instructions for this so it causes a cannot select
error.
2026-03-05 08:07:48 -08:00
Craig Topper
18226e7e2e
[RISCV] Lower i8/i16/i32 scalable vector ISD::CLMUL/CLMULH with Zvbc32e. (#184465) 2026-03-04 08:29:05 -08:00
Craig Topper
80acaccbe6
[RISCV] Promote i8/i16/i32 scalable vector CLMUL to i64 CLMUL with Zvbc. (#184265)
This handles the simple case where we can widen to i64 vector
without splitting. More work will be done in follow ups.
2026-03-03 10:48:34 -08:00
Qihan Cai
75b0cf39b2
[RISCV] Add scalar saturating add/sub operations for i32 for RV64P (#184062) 2026-03-03 16:32:23 +11:00
Craig Topper
b68307569b
[RISCV] Support scalar bitreverse using P extension rev instruction. (#183245) 2026-02-25 12:42:59 -08:00
Craig Topper
118f64ad20
[RISCV] Remove -riscv-enable-p-ext-simd-codegen (#183156)
All known crashes have been fixed.

We do still need to work out how fixed length vectors are handled when V
and P are both enabled, but I don't think this option is the solution
for that.
2026-02-25 08:43:55 -08:00
Craig Topper
333ef64e38
[RISCV] Remove unnecessary And before seteq/ne in some cases. (#183221)
Fold (and X, Mask) ==/!= C -> X ==/!= sext(C, countr_one(Mask))if the
Mask is only clearing redundant sign bits.

The AND may have come from type legalization of a narrower setcc.
Type legalization will check computeNumSignBits before inserting
the AND, but sometimes the sign bits don't appear until after
op legalization. In the motivating examples, the inputs isn't known
to be sign extended until EXTRACT_VECTOR_ELT is converted to vmv.x.s.

Spotted in the before code from #182684.
2026-02-25 08:43:13 -08:00
Paul Walker
ab360b1e7e
[LLVM][TTI] Remove the isVScaleKnownToBeAPowerOfTwo hook. (#183292)
After https://github.com/llvm/llvm-project/pull/183080 this is no longer
a configurable property.

NOTE: No test changes expected beyond
llvm/test/Transforms/LoopVectorize/scalable-predication.ll which has
been removed because it only existed to verfiy the now unsupported
functionality.
2026-02-25 14:09:52 +00:00
Carlos Alberto Enciso
bc9d5b01d3
[clang][DebugInfo] Add virtuality call-site target information in DWARF. (#182510)
Given the test case:

  struct CBase {
    virtual void foo();
  };

  void bar(CBase *Base) {
    Base->foo();
  }

and using '-emit-call-site-info' with llc, the following DWARF
is produced for the indirect call 'Base->foo()':

1$: DW_TAG_structure_type "CBase"
      ...
2$:   DW_TAG_subprogram "foo"
        ...

3$: DW_TAG_subprogram "bar"
      ...
4$:   DW_TAG_call_site
        ...

We add DW_AT_LLVM_virtual_call_origin to existing call-site
information, linking indirect calls to the function-declaration
they correspond to.

4$:   DW_TAG_call_site
        ...
        DW_AT_LLVM_virtual_call_origin (2$ "_ZN5CBase3fooEv")

The new attribute DW_AT_LLVM_virtual_call_origin helps to
address the ambiguity to any consumer due to the usage of
DW_AT_call_origin.

The functionality is available to all supported debuggers and
it is generated only for DWARF version 5 or greater.
2026-02-25 05:35:07 +00:00
Craig Topper
04ca29ed54
[RISCV] Expand more TruncStore and LoadExt operations for P extension. (#182995) 2026-02-24 10:54:43 -08:00
Brandon Wu
03bb370602
[RISCV][llvm] Rename zvqdotq to zvdot4a8i (#179393)
The renaming PR is here:
https://github.com/riscv/riscv-isa-manual/pull/2576
Note that this also update the version number.
2026-02-24 04:44:07 +00:00
Craig Topper
c716009d71 [RISCV] Remove unnecessary setOperationAction for P extension. NFC
We default all vector operations to Expand for P so this one is
redundant.
2026-02-23 13:51:08 -08:00
Craig Topper
594e9fb3e3
[RISCV] Remove srl from (srl (and X, (1 << C)), C) used as czero.eqz/nez condition. (#182598)
(setne (and X, 1 << C), 0) is canonicalized to (srl (and X, (1 << C)),
C).
If this is later used as a czero.eqz/nez condition, we can remove
the srl if the and can be represented as an ANDI.
2026-02-20 18:00:07 -08:00
Craig Topper
dcd2b08222
[RISCV] Use FSHR in LowerShiftRightParts for P extension on RV64. (#181234)
We can't do the NSRLI trick on RV64, but we can use srx similar to what
we do in LowerShiftLeftParts. We need an additional fixup step for the
FSHR result that NSRLI doesn't need.

Assisted-by: claude
2026-02-19 12:47:44 -08:00
Paul Kirth
ec8b9ca47d
Revert "[clang][DebugInfo] Add virtuality call-site target informatio… (#182343)
…n in DWARF. (#167666)"

This reverts commit 418ba6e8ae2cde7924388142b8ab90c636d2c21f.

The commit caused an ICE due to hitting unreachable in
llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp:1307

Fixes #182337
2026-02-19 12:19:11 -08:00
Carlos Alberto Enciso
418ba6e8ae
[clang][DebugInfo] Add virtuality call-site target information in DWARF. (#167666)
Given the test case:

  struct CBase {
    virtual void foo();
  };

  void bar(CBase *Base) {
    Base->foo();
  }

and using '-emit-call-site-info' with llc, the following DWARF
is produced for the indirect call 'Base->foo()':

1$: DW_TAG_structure_type "CBase"
      ...
2$:   DW_TAG_subprogram "foo"
        ...

3$: DW_TAG_subprogram "bar"
      ...
4$:   DW_TAG_call_site
        ...

We add DW_AT_LLVM_virtual_call_origin to existing call-site
information, linking indirect calls to the function-declaration
they correspond to.

4$:   DW_TAG_call_site
        ...
        DW_AT_LLVM_virtual_call_origin (2$ "_ZN5CBase3fooEv")

The new attribute DW_AT_LLVM_virtual_call_origin helps to
address the ambiguity to any consumer due to the usage of
DW_AT_call_origin.

The functionality is available to all supported debuggers.
2026-02-19 14:48:59 +00:00
Craig Topper
2cb342c733
[RISCV] Add combines to form WSUBAU on RV32 with P. (#181604) 2026-02-17 15:32:47 -08:00
Craig Topper
7fd56a0d74
[RISCV] Calculate max call frame size in RISCVTargetLowering::finalizeLowering. (#181302)
I want to enable the frame pointer when the call frame size is too large
to access emergency spill slots. To do that I need to know the call
frame size early enough to reserve FP.

The code here is copied from AArch64. ARM does the same. I did not check
other targets.

Splitting this off separately because it stops us from unnecessarily
reserving the base pointer in the some RVV tests. That appears to due to
this check

(!hasReservedCallFrame(MF) && (!MFI.isMaxCallFrameSizeComputed() ||
MFI.getMaxCallFrameSize() != 0))) &&

By calculating early !MFI.isMaxCallFrameSizeComputed() is no longer true
and the size is zero.
2026-02-13 20:32:48 -08:00
Craig Topper
75cc975c2c
[RISCV] Combine ADDD(lo, hi, x, 0) -> WADDAU(lo, hi, x, 0). Combine WADDAU (WADDAU lo, hi, x, 0), y, 0 -> WADDAU lo, hi, x, y (#181396)
WADDAU is rd += zext(rs1) + zext(rs2)

If we only have 1 32-bit input can force rs2 to avoid zeroing the upper
part of a register pair to use ADDD.

Unfortunately, WADDAU clobbers rd so it might need a GPRPair copy
if we need the old value of rd. We might need to look into that in
the future. Maybe we could have convertToThreeAddress could turn
it back into ADDD+WADDU or ADDD+LI.

Assisted-by: claude
2026-02-13 13:39:57 -08:00
Craig Topper
a809d6409f
[RISCV] Remove RISCVISD::WMACC*. Match during isel. NFC (#181197)
I think we may want to be able to fold ADDD nodes independent of the MUL
in some cases. For example turning NSRAI into NSRARI.

If we fold ADDD into WMACC we would need to be able to extract it again.
Keep the nodes separate avoids this.

Code change was assisted by AI.
2026-02-12 22:06:01 -08:00
Craig Topper
664663cbbf
[RISCV] Improve 2*XLEN SHL legalization with P extension. (#181056)
For an i64 shift by a constant < 32 on RV32, we can use NSRLI
with 32-ShAmt to calculate the high half of the result.
    
For non-constant shifts, we can use SLX and some bit tricks to
avoid branches. I wanted to use the target independent code from
TargetLowering, but it currently produces worse code.

Assisted-by: claude
2026-02-11 23:32:02 -08:00
Craig Topper
db588931c5
[RISCV] Use NSRL/NSRA for legalizing i64 shifts with P extension on RV32. (#181040)
If the shift amount might be in the range [0, 31], we can use
NSRL/NSRA to shift the i64 value to compute the lower 32 bits of
the result.

If the shift amount is >= 32, the high half of the result is all
zeros or sign bits. Otherwise it is a srl/sra of the high bits.

I've handled the constant case in ReplaceNodeResults but deferred
the non-constant case to lowerShiftRightParts. This function is
not called for constants. This gives the opportunity for DAGCombine to
optimize the SRL_PARTS/SRA_PARTS if the shift amount can be proven
to be >= 32 or < 32.

Sequences were also discussed on the P extension mailing list here
https://lists.riscv.org/g/tech-p-ext/message/861

Assisted-by: claude
2026-02-11 22:37:47 -08:00
Folkert de Vries
6a81656f7d
[RISCV] improve musttail support (#170547)
Basically https://github.com/llvm/llvm-project/pull/168506 but for
riscv, so to be clear the hard work here is @heiher 's. I figured we may
as well get some extra eyeballs on this from riscv too.

Previously the riscv backend could not handle `musttail` calls with more
arguments than fit in registers, or any explicit `byval` or `sret`
parameters/return values. Those have now been implemented.

This is part of my push to get more LLVM backends to support `byval` and
`sret` parameters so that rust can stabilize guaranteed tail call
support. See also:

- https://github.com/llvm/llvm-project/pull/168956
- https://github.com/rust-lang/rust/issues/148748

---------

Co-authored-by: WANG Rui <wangrui@loongson.cn>
2026-02-11 17:27:51 +01:00
Pengcheng Wang
e84659b71b
[RISCV][CodeGen] Combine vwaddu+vabd(u) to vwabda(u)
Note that we only support SEW=8/16 for `vwabda(u)`.

Reviewers: topperc, lukel97, preames

Reviewed By: topperc, lukel97

Pull Request: https://github.com/llvm/llvm-project/pull/180162
2026-02-11 18:53:29 +08:00
Luke Lau
cd2761f7ab
[RISCV] Remove vp.reverse mask check in performVP_REVERSECombine (#180724)
Similar to #180706, the masked off lanes in vp.reverse are poison so can
be replaced with anything. Because of this, we should be able to fold a
masked vp.reverse(vp.load) into a vp.strided.load stride=-1 even when
the mask isn't all ones.
2026-02-11 09:13:42 +00:00
Luke Lau
ffe446e734
[RISCV] Relax reversed mask's mask requirement in reverse to strided load/store combine (#180706)
We have combines for vp.reverse(vp.load) -> vp.strided.load stride=-1
and vp.store(vp.reverse) -> vp.strided.store stride=-1.

If the load or store is masked, the mask needs to be also a vp.reverse
with the same EVL. However we also have the requirement that the mask's
vp.reverse is unmasked (has an all-ones mask).

vp.reverse's mask only sets masked off lanes to poison, and doesn't
affect the permutation of elements. So given those lanes are poison, I
believe the combine is valid for any mask, not just all ones.

This is split off from another patch I plan on posting to generalize
those combines to vector.splice+vector.reverse patterns, as part of
#172961
2026-02-11 16:43:02 +08:00
Craig Topper
31e1bcfd09
[RISCV] Add basic scalar support for MERGE, MVM, and MVMN from P extension (#180677)
These are 3 variations of the same operation with a different operand
tied to the destination register. We need to pick the one that
minimizes the number of mvs.

To do this we take the approach used by AArch64 to select between
BIT, BIF, and BSL which the same operations. We define a pseudo
with no tied constraint and expand it after register allocation based
on where the destination register ended up. If the destination
register is none of the operands, we'll insert a mv.

I've replaced RISCVISD::MVM with RISCVISD::MERGE and updated the operand
order accordingly. I find the MERGE name easier to read so I've made it
the canonical name.

Ideally we could use commuteInstructionImpl and the
TwoAddressInstructionPass
to select the opcode before register allocation. That only works if
you can commute exactly 2 operands and maybe change the opcode in the MI
representation of any of the forms to get to the either of the other 2
forms.
That is not possible. We'd need to define 3 more pseudoinstructions
with different permutations.

With the current approach it might be possible that we insert a mv
not because all of the operand registers we needed by later
instructions,
but because the register allocator needed to put the result in a
different register. It's possible a different allocation for other
instructions might have avoided the mv.

I wrote the patch based on the AArch64, but the tests were generated
by AI.
2026-02-10 13:39:34 -08:00
Craig Topper
f33ea53451
[RISCV] Remove redundant czero in multi-word comparisons (#180485)
When comparing multi-word integers with Zicond, we generate:
  (or (czero_eqz (lo1 < lo2), (hi1 == hi2)),
      (czero_nez (hi1 < hi2), (hi1 == hi2)))

The czero_nez is redundant because when hi1 == hi2 is true, hi1 < hi2 is
already 0. This patch adds a DAG combine to recognize:
  czero_nez (setcc X, Y, CC), (setcc X, Y, eq) -> (setcc X, Y, CC)
when CC is a strict inequality (lt, gt, ult, ugt).

This saves one instruction in 128-bit comparisons on RV64 with Zicond.

Note the czero_nez becomes a czero.eqz in the final assembly because the
seteq is replaced by an xor that produces 0 when the values are equal.

Part of #179584

Assisted-by: claude
2026-02-09 21:48:14 -08:00
Ryan Buchner
d69ccf3b34
[RISCV] Combine shuffle of shuffles to a single shuffle (#178095)
Compressing to a single shuffle doesn't remove any information and the backend can better apply specific optimizations to a single shuffle.

Addresses #176218.

---------

Co-authored-by: Luke Lau <luke_lau@igalia.com>
2026-02-09 14:48:31 -08:00
Craig Topper
e6a72a1d42
[RISCV] Combine ADDD+WMULSU to WMACCSU (#180454)
Extend the existing combineADDDToWMACC DAG combine to also match
RISCVISD::WMULSU and produce RISCVISD::WMACCSU. This is similar to
how ADDD+UMUL_LOHI is combined to WMACCU and ADDD+SMUL_LOHI is
combined to WMACC.

This patch was generated by AI, but I reviewed it.
2026-02-09 08:51:27 -08:00
Pengcheng Wang
972e73b812
[RISCV][CodeGen] Lower ISD::ABS to Zvabd instructions
We add pseudos/patterns for `vabs.v` instruction and handle the
lowering in `RISCVTargetLowering::lowerABS`.

Reviewers: topperc, 4vtomat, mshockwave, preames, lukel97, tclin914

Reviewed By: mshockwave

Pull Request: https://github.com/llvm/llvm-project/pull/180142
2026-02-09 15:21:25 +08:00
Pengcheng Wang
e992593341
[RISCV][CodeGen] Lower abds/abdu to Zvabd instructions
We directly lower `ISD::ABDS`/`ISD::ABDU` to `Zvabd` instructions.

Note that we only support SEW=8/16 for `vabd.vv`/`vabdu.vv`.

Reviewers: mshockwave, lukel97, topperc, preames, tclin914, 4vtomat

Reviewed By: lukel97, topperc

Pull Request: https://github.com/llvm/llvm-project/pull/180141
2026-02-09 15:12:22 +08:00
Craig Topper
769b734c02
[RISCV] Combine ADDD with UMUL_LOHI/SMUL_LOHI into WMACCU/WMACC (#180383)
Combine the pattern:
  ADDD(addlo, addhi, UMUL_LOHI(x, y).0, UMUL_LOHI(x, y).1)
into:
  WMACCU(x, y, addlo, addhi)

And similarly for SMUL_LOHI -> WMACC.


This patch was written with AI, but I reviewed it carefully.
2026-02-08 13:39:32 -08:00
Craig Topper
5c826f5172
[RISCV] Emit MULHU/MULHS/UMUL_LOHI/SMUL_LOHI from our custom XLen*2 expansion. (#180379)
We already do all the checks necessary in order to prioritize
MULHU/MULHS/UMUL_LOHI/SMUL_LOHI over MULHSU/WMULSU. We might as
well just emit the nodes instead of letting generic type legalization
redo the checks.

This is slightly different than the default legalization because we
don't have access to ExpandInteger so we have to emit TRUNCATES and
BUILD_PAIR. Not sure if this will result in any differences in practice.
2026-02-08 13:39:15 -08:00