203 Commits

Author SHA1 Message Date
Jim Lin
84b5e9f8db
[RISCV] Add used callee-saved registers as implicit/implicit-def registers to save/restore call (#180133)
We should add used callee-saved registers as implicit used to save
libcall and as implicit defined to restore libcall. It likes what we did
for CM_PUSH/CM_POPRET. That can help to construct correct dataflow. In
entry bb, save libcall implicitly uses the callee-saved registers which
live in. And in return bb, restore libcall implicitly defines the
callee-saved registers which live out.
2026-02-09 10:00:32 +08:00
Christudasan Devadasan
9e1606026c
[CodeGen][InlineSpiller] Add SubReg argument to loadRegFromStackSlot for subreg-reload (#175581)
This preparatory patch introduces an additional argument to the target hook
loadRegFromStackSlot. Ths is essential for targets to handle subregister-specific
reload in the future. See how this is used for AMDGPU target with PR #175002.
2026-01-13 08:21:58 +05:30
Alex Bradbury
d1c466f487
[RISCV][NFC] Use appendLEB128 in RISCVFrameLowering (#173198)
We can slightly simplify the callers by using appendLEB128 with an
appropriate sign argument.
2025-12-22 07:58:58 +00:00
Alex Bradbury
a8dc57f0d7
[RISCV][NFCI] Refactor appendScalableVectorExpression and callers to use StackOffset (#173193)
Rather than passing around separate FixedOffset and ScalableOffset
integers, we can use StackOffset instead.
2025-12-22 06:55:57 +00:00
Philip Reames
49a7772be5
[CodeGen] Replace (Min,Max)CSFrameIndex with flag on frame object [NFCI] (#170905)
This removes the tracking of the MinCSFrameIndex, and MaxCSFrameIndex markers, simplifying the target API. This brings the tracking for callee save spill slots in line with how we handle other properties of stack locations.

A couple notes:
1) This requires doing scans of the entire object range, but we have other such instances in the code already, so I doubt this will matter in practice.
2) This removes the requirement that callee saved spill slots be contiguous in the frame index identified space.

I marked this as NFCI because if prior code violated the contiguous range assumption - I can't find a case where we did - then this change might adjust frame layout in some edge cases.

The motivation for this is mostly code readability, but I might use this as a primitive for something in an upcoming patch series around shrink wrapping. Haven't decided yet.
2025-12-06 14:00:55 -08:00
Mikhail Gudim
6886d4945f
[RISCV] Add an option to enable CFIInstrInserter. (#164477) 2025-11-18 02:46:43 -05:00
Matt Arsenault
1f3f522866
CodeGen: Remove TRI arguments from stack load/store hooks (#158240)
This is directly available in TargetInstrInfo
2025-11-10 16:24:39 -08:00
Craig Topper
ff11b93bb8
[RISCV] Correct the CFA offsets for stack probing. (#166616)
We need to take into account that we may have already done a FirstSPAdjust.

Fixes #164805.
2025-11-06 07:09:52 -08:00
Craig Topper
62791b4377
[RISCV] Replace uses of RISCV::NoRegister with Register() or isValid. NFC (#161781) 2025-10-03 08:53:58 -07:00
Benjamin Maxwell
9f5abd38dd
[Codegen] Add a separate stack ID for scalable predicates (#142390)
This splits out "ScalablePredicateVector" from the "ScalableVector"
StackID this is primarily to allow easy differentiation between vectors
and predicates (without inspecting instructions).

This new stack ID is not used in many places yet, but will be used in a
later patch to mark stack slots that are known to contain predicates.

Co-authored-by: Kerry McLaughlin <kerry.mclaughlin@arm.com>
2025-10-02 14:43:07 +01:00
Jesse Huang
9bbf22ccda
[RISCV] Loosen the requirement of shadow stack codegen to Zimop (#152251)
Zicfiss (Shadow Stack) instructions are implemented using the encoding
space defined in the "Zimop" May-Be-Operations Extension, where the
instruction behaviors turn into NOP if Zimop is implemented but the
redefining extension does not present.
This means we can safely loosen the codegen requirement of shadow stack
to Zimop, in that those processors with Zimop but no Zicfiss can still
execute the instructions without problem.

This patch add new pseudo instructions to model MOPs that are expanded
into Zicfiss instructios, and change to emit them in the codegen
2025-09-09 12:18:06 +08:00
Kazu Hirata
83cb8b7bef
[llvm] Use a range-based for loop instead of {std,llvm}::for_each (NFC) (#150841)
LLVM Coding Standards discourages {std,llvm}::for_each unless we
already have a callable.
2025-07-27 10:43:52 -07:00
Brandon Wu
24bf4aea0c
[RISCV][llvm] Handle vector callee saved register correctly (#149467)
In TargetFrameLowering::determineCalleeSaves, any vector register is
marked
as saved if any of its subregister is clobbered, this is not correct in
vector registers. We only want the vector register to be marked as saved
only if all of its subregisters are clobbered.
This patch handles vector callee saved registers in target hook.
2025-07-21 17:49:34 -07:00
Sergei Barannikov
6112ebde0c
[RISCV] Guard CFI emission code with MF.needsFrameMoves() (#136060)
Currently, AsmPrinter skips CFI instructions created by a backend if
they are not needed. I'd like to change that so that it always
prints/encodes CFI instructions if a backend created them.

This change should slightly (perhaps negligibly) improve compile time as
post-PEI passes no longer need to skip over these instructions in
no-exceptions no-debug builds, and will allow to simplify convoluted
logic in AsmPrinter once other targets stop emitting CFI instructions
when they are not needed (that's my final goal).

The changes in a test seem to be caused by slightly different post-RA
scheduling in the absence of CFI instructions.
2025-07-18 16:49:30 +03:00
Raphael Moreira Zinsly
1db9eb2320
[RISCV] Pass the MachineInstr flag as argument to allocateStack (#147531)
When not in the prologue we do not want to set the FrameSetup flag, by
passing the flag as argument we can use allocateStack correctly on those
cases.
This fixes the allocation and probe in eliminateCallFramePseudoInstr.
2025-07-15 08:09:18 -07:00
Sam Elliott
a6eb5eee38
[RISCV][NFC] Remove hasStdExtCOrZca (#145139)
As of 20b5728b7b1ccc4509a316efb270d46cc9526d69, C always enables Zca, so
the check `C || Zca` is equivalent to just checking for `Zca`.

This replaces any uses of `HasStdExtCOrZca` with a new `HasStdExtZca`
(with the same assembler description, to avoid changes in error
messages), and simplifies everywhere where C++ needed to check for
either C or Zca.

The Subtarget function is just deprecated for the moment.
2025-06-23 10:49:47 -07:00
Kazu Hirata
1ecc291cd4
[RISCV] Use llvm::is_contained (NFC) (#141372) 2025-05-24 14:46:55 -07:00
Craig Topper
555d68f3db
[RISCV] Use implicit def/use of SP for PROBED_STACKALLOC*. (#139153) 2025-05-16 14:43:22 -07:00
Raphael Moreira Zinsly
52af23f950
[RISCV] Add stack probing in eliminateCallFramePseudoInstr (#139731)
Stack clash protection code was missing from
RISCVFrameLowering::eliminateCallFramePseudoInstr, calling allocateStack
fixes it.
This patch also fixes the tests in stack-probing-dynamic.ll that should
be testing the stack allocation before a function call.
2025-05-16 09:41:34 -07:00
Sam Elliott
4e175b8896
[RISCV] Fix Defs/Uses for SiFive CLIC Support (#137724)
The expensive checks bots found issues with #132481, due to not setting
defs/uses correctly. In 31bd7a507152 I added verify flags, so that the
failure is reproduced without requiring expensive checks, and xfailed
the test.

This change:
- Ensures that registers are correctly marked as defs/uses.
- Removes the xfail.
- Leaves the tests with `-verify-machineinstrs` which should have been
present originally.
2025-04-28 19:35:11 -07:00
Sam Elliott
3f46af98ca
[RISCV] Support Push/Pop with Xqci (#134191)
The `qc.c.mienter` and `qc.c.mienter.nest` instructions, broadly only
save the argument and temporary registers. The exceptions are that they
also save `fp` (`s0`) to construct a frame chain from the signal handler
to the frame below, and they also save `ra`. They are designed this way
so that (if needed) push and pop instructions can be used to save the
callee-saved registers.

This patch implements this optimisation, constructing the following
rather than a long sequence of `sw` and `lw` instructions for saving the
callee-saved registers:

```asm
  qc.c.mienter
  qc.cm.push {ra, s0-sN}, -M
  ...
  qc.cm.pop {ra, s0-sN}, M
  qc.c.mileaveret
```

There are some carefully-worked-out details here, especially around CFI
information. For any register saved by both `qc.c.mienter(.nest)` and
the push (which is `ra` and `s0` at most), we point the CFI information
at the version saved by `qc.c.mienter(.nest)`. This ensures the CFI
points at the same `fp` copy as a frame pointer unwinder would find.
2025-04-28 08:12:45 -07:00
Sam Elliott
cfc5baf6e6
[RISCV] SiFive CLIC Support (#132481)
This Change adds support for two SiFive vendor attributes in clang:
- "SiFive-CLIC-preemptible"
- "SiFive-CLIC-stack-swap"

These can be given together, and can be combined with "machine", but
cannot be combined with any other interrupt attribute values.

These are handled primarily in RISCVFrameLowering:
- "SiFive-CLIC-stack-swap" entails swapping `sp` with `sf.mscratchcsw`
  at function entry and exit, which holds the trap stack pointer.
- "SiFive-CLIC-preemptible" entails saving `mcause` and `mepc` before
  re-enabling interrupts using `mstatus`. To save these, `s0` and `s1`
  are first spilled to the stack, and then the values are read into
  these registers. If these registers are used in the function, their
  values will be spilled a second time onto the stack with the generic
  callee-saved-register handling. At the end of the function interrupts
  are disabled again before `mepc` and `mcause` are restored.

This Change also adds support for the following two experimental
extensions, which only contain CSRs:
- XSfsclic - for SiFive's CLIC Supervisor-Mode CSRs
- XSfmclic - for SiFive's CLIC Machine-Mode CSRs

The latter is needed for interrupt support.

The CFI information for this implementation is not correct, but I'd
prefer to correct this in a follow-up. While it's unlikely anyone wants
to unwind through a handler, the CFI information is also used by
debuggers so it would be good to get it right.

Co-authored-by: Ana Pazos <apazos@quicinc.com>
2025-04-25 17:12:27 -07:00
Craig Topper
fc7fee8360
Revert "[RISCV] Allow spilling to unused Zcmp Stack (#125959)" (#137060)
This reverts commit 50cdf6cbc5035345507bb4d23fcb0292272754eb.

This patch causes miscompiles with vector and produces some odd code for
ilp32e.
2025-04-23 17:36:00 -07:00
Craig Topper
a1db2c6491 [RISCV] Remove duplicate call to MFI.getStackID(FI). NFC
Reuse existing local variable.
2025-04-21 16:53:22 -07:00
Paul Kirth
b3d2dc321c
[RISCV] Fix assertion failure when using -fstack-clash-protection (#135248)
We can't assume MBBI is still pointing at MBB if we've already expanded
a probe. We need to re-query the MBB from MBBI. Fixes #135206

Co-authored-by: Craig Topper <craig.topper@sifive.com>
2025-04-18 09:12:52 -07:00
Sergei Barannikov
ed9bcb5295
[CodeGen][RISCV] Add helper class for emitting CFI instructions into MIR (#135845)
PR: https://github.com/llvm/llvm-project/pull/135845
2025-04-16 20:05:13 +03:00
Craig Topper
9069ba183d [RISCV] Rename Spimm to StackAdj in most places. NFC
Spimm in the spec refers to the 2-bit encoded value. All of the code
uses the 0, 16, 32, or 48 adjustment value.

Also remove the decodeZcmpSpimm as its identical to the default
behavior for no custom DecoderMethod.
2025-04-04 12:49:09 -07:00
Craig Topper
70a1445e40 [RISCV] Prefer RegList over Rlist in assembler. NFC
This makes it more obvious what the R means. I've kept rlist in
place that refer to the encoding.
2025-04-04 09:37:52 -07:00
Sam Elliott
8a133882bb
[RISCV] Xqciint SystemRegs, Final Assembly Insts (#130867)
This adds the Xqciint system registers from the Xqci-0.7 spec, as well
as two leftover instructions: `qc.c.mret` and `qc.c.mnret`

Co-authored-by: Sudharsan Veeravalli <quic_svs@quicinc.com>
2025-03-23 12:04:06 -07:00
Philip Reames
8d78b7cc7d
[RISCV] Introduce RISCV::RVVBytesPerBlock to simplify code [nfc] (#132436) 2025-03-21 11:11:54 -07:00
Kito Cheng
7f8451c868
[RISCV] Use vsetvli instead of vlenb in Prologue/Epilogue (#113756)
Currently, we use `csrr` with `vlenb` to obtain the `VLEN`, but this is
not the only option. We can also use `vsetvli` with `e8`/`m1` to get
`VLENMAX`, which is equal to the VLEN. This method is preferable on some
microarchitectures and makes it easier to obtain values like `VLEN * 2`,
`VLEN * 4`, or `VLEN * 8`, reducing the number of instructions needed to
calculate VLEN multiples.

However, this approach is *NOT* always interchangeable, as it changes
the state of `VTYPE` and `VL`, which can alter the behavior of vector
instructions, potentially causing incorrect code generation if applied
after a vsetvli insertion. Therefore, we limit its use to the
prologue/epilogue for now, as there are no vector operations within the
prologue/epilogue sequence.

With further analysis, we may extend this approach beyond the
prologue/epilogue in the future, but starting here should be a good
first step.

This feature is gurded by the `+prefer-vsetvli-over-read-vlenb` feature,
which is disabled by default for now.
2025-03-21 17:22:32 +08:00
Sam Elliott
ae985267d0
[RISCV] Update to Xqciint v0.4 (#130219)
The Xqci 0.7.0 spec just came out, with some updates to Xqciint,
bringing it to v0.4. The main update of any relevance is that
`qc.c.mienter` and `qc.c.mienter.nest` now update both the stack pointer
and the frame pointer (before, they only updated the stack pointer).
They both remain compatible with the frame pointer convention.

This change bumps the Xqciint version, and ensures that we don't emit
the unneeded frame pointer adjustment instruction after
`qc.c.mienter(.nest)`.
2025-03-11 08:54:22 -07:00
Sam Elliott
3492245ac0
[RISCV] QCI Interrupt Support (#129957)
This change adds support for `qci-nest` and `qci-nonest` interrupt
attribute values. Both of these are machine-mode interrupts, which use
instructions in Xqciint to push and pop A- and T-registers (and a few
others) from the stack.

In particular:
- `qci-nonest` uses `qc.c.mienter` to save registers at the start of the
function, and uses `qc.c.mileaveret` to restore those registers and
return from the interrupt.
- `qci-nest` uses `qc.c.mienter.nest` to save registers at the start of
the function, and uses `qc.c.mileaveret` to restore those registers and
return from the interrupt.
- `qc.c.mienter` and `qc.c.mienter.nest` both push registers ra, s0
(fp), t0-t6, and a0-a10 onto the stack (as well as some CSRs for the
interrupt context). The difference between these is that
`qc.c.mienter.nest` re-enables M-mode interrupts.
- `qc.c.mileaveret` will restore the registers that were saved by
`qc.c.mienter(.nest)`, and return from the interrupt.

These work for both standard M-mode interrupts and the non-maskable
interrupt CSRs added by Xqciint.

The `qc.c.mienter`, `qc.c.mienter.nest` and `qc.c.mileaveret`
instructions are compatible with push and pop instructions, in as much
as they (mostly) only spill the A- and T-registers, so we can use the
`Zcmp` or `Xqccmp` instructions to spill the S-registers. This
combination (`qci-(no)nest` and `Xqccmp`/`Zcmp`) is not implemented in
this change.

The `qc.c.mienter(.nest)` instructions have a specific register storage
order so they preserve the frame pointer convention linked list past the
current interrupt handler and into the interrupted code and frames if
frame pointers are enabled.

Co-authored-by: Pankaj Gode <quic_pgode@quicinc.com>
2025-03-06 13:31:08 -08:00
Sam Elliott
e49180d84c
[RISCV] Xqccmp Code Generation (#128815)
This adds support for Xqccmp to the following passes:
- Prolog Epilog Insertion - reusing much of the existing push/pop logic,
but extending it to cope with frame pointers and reorder the CFI
information correctly.
- Move Merger - extending it to support the `qc.` variants of the
double-move instructions.
- Push/Pop Optimizer - extending it to support the `qc.` variants of the
pop instructions.

The testing is based on existing Zcmp tests, but I have put them in
separate files as some of the Zcmp tests were getting quite long.
2025-03-05 10:59:45 -08:00
Craig Topper
313b71fc1a
[RISCV] Simplify tracking of tracking and encoding of push/pop in RISCVFrameLowering. NFC (#129343)
Previously we calculated the max register id. Then converted it to the number
of registers and encoding. Then converted number of registers to stack
size. Then saved number of registers, encoding, and stack size to
MachineFunctionInfo.

This patch removes the calculation of max register id, and instead
calculates the number of registers. The encoding is removed from
MachineFunctionInfo in favor of converting the number of registers to
encoding at the time of use.
2025-03-03 14:38:41 -08:00
Craig Topper
810150bcb6
[RISCV] Remove the offset numbers from the FixedCSRFIMap. NFC (#129297)
Use the position within the table instead with a little bit of
arithmetic.
2025-02-28 20:06:10 -08:00
Craig Topper
743571b5f1 [RISCV] Remove unused argument. NFC 2025-02-28 15:14:51 -08:00
Craig Topper
af64f0a6c2
[FrameLowering] Use MCRegister instead of Register in CalleeSavedInfo. NFC (#128095)
Callee saved registers should always be phyiscal registers. They are
often passed directly to other functions that take MCRegister like
getMinimalPhysRegClass or TargetRegisterClass::contains.

Unfortunately, sometimes the MCRegister is compared to a Register which
gave an ambiguous comparison error when the MCRegister is on the LHS.
Adding a MCRegister==Register comparison operator created more ambiguous
comparison errors elsewhere. These cases were usually comparing against
a base or frame pointer register that is a physical register in a
Register. For those I added an explicit conversion of Register to
MCRegister to fix the error.
2025-02-20 23:44:05 -08:00
Sudharsan Veeravalli
83783e8bec
[RISCV] Fix typos discovered by codespell (NFC) (#126191)
Found using https://github.com/codespell-project/codespell

```
codespell RISCV --write-changes \
       --ignore-words-list=FPR,fpr,VAs,ORE,WorstCase,hart,sie,MIs,FLE,fle,CarryIn,vor,OLT,VILL,vill,bu,pass-thru 
```
2025-02-07 13:35:30 +05:30
Sam Elliott
50cdf6cbc5
[RISCV] Allow spilling to unused Zcmp Stack (#125959)
This is a tiny change that can save up to 16 bytes of stack allocation,
which is more beneficial on RV32 than RV64.

cm.push allocates multiples of 16 bytes, but only uses a subset of those
bytes for pushing callee-saved registers. Up to 12 (rv32) or 8 (rv64)
bytes are left unused, depending on how many registers are pushed.
Before this change, we told LLVM that the entire allocation was used, by
creating a fixed stack object which covered the whole allocation.

This change instead gives an accurate extent to the fixed stack object,
to only cover the registers that have been pushed. This allows the
PrologEpilogInserter to use any unused bytes for spills. Potentially
this saves an extra move of the stack pointer after the push, because
the push can allocate up to 48 more bytes than it needs for registers.

We cannot do the same change for save/restore, because the restore
routines restore in batches of `stackalign/(xlen/8)` registers, and we
don't want to clobber the saved values of registers that we didn't tell
the compiler we were saving/restoring - for instance `__riscv_restore_0`
is used by the compiler when it only wants to save `ra`, but will end up
restoring `ra` and `s0`.
2025-02-06 19:45:47 -08:00
Craig Topper
6e14d75f54 [RISCV] Fix some implicit conversions from Register to unsigned. NFC 2025-02-05 17:06:10 -08:00
Venkata Ramanaiah Nalamothu
a0b049055d
[RISC-V] Fix incorrect epilogue_begin setting in debug line table (#120623)
The DwarfDebug.cpp implementation expects the epilogue instructions to
have source location of last non-debug instruction after which the epilogue
instructions are inserted. The epilogue_begin is set on location of the first
FrameDestroy instruction with source line information that has been seen in
the epilogue basic block.

In the trunk, the risc-v backend sets the epilogue_begin after the epilogue has
actually begun i.e. after callee saved register reloads and the source line
information is not set on those reload instructions. This is leading to #120553
where, while debugging, breaking on or single stepping to the epilogue_begin
location will make accessing the variables from wrong place as the FP has been
restored to the parent frame's FP.

To fix that, this patch sets FrameSetup/FrameDestroy flags on the callee saved
register spill/reload instructions which is actually correct. Then the
RISCVInstrInfo::loadRegFromStackSlot uses FrameDestroy flag to identify a
reload of the callee saved register in the epilogue and copies the source
line information from insert position instruction to that reload instruction.

Requires PR #120622

Fixes #120553
2025-01-28 21:03:12 +05:30
Raphael Moreira Zinsly
01d7f434d2
[RISCV] Stack clash protection for dynamic alloca (#122508)
Create a probe loop for dynamic allocation and add the corresponding
SelectionDAG support in order to use it.
2025-01-16 11:58:42 -08:00
Guy David
1a935d7a17
[llvm] Mark scavenging spill-slots as *spilled* stack objects. (#122673)
This seems like an oversight when copying code from other backends.
2025-01-14 10:18:31 +02:00
Raphael Moreira Zinsly
6f53886a9a
[RISCV] Add stack clash vector support (#119458)
Use the probe loop structure to allocate vector code in the stack as
well. We add the pseudo instruction RISCV::PROBED_STACKALLOC_RVV to
differentiate from the normal loop.
2025-01-10 09:48:21 -08:00
Elizaveta Noskova
5fc8062f5d
[llvm][RISCV] Set ScalableVector stack id in proper place (#117862)
Without this patch ScalableVector frame index property is used before
assignment. More precisely, let's take a look at
RISCVFrameLowering::assignCalleeSavedSpillSlots. In this function we
divide callee saved registers on scalar and vector ones, based on
ScalableVector property of their frame indexes:
```
  ...
  const auto &UnmanagedCSI = getUnmanagedCSI(*MF, CSI);
  const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI);
  ...
```
But we assign ScalableVector property several lines below:
```
  ...
  auto storeRegToStackSlot = [&](decltype(UnmanagedCSI) CSInfo) {
    for (auto &CS : CSInfo) {
      // Insert the spill to the stack frame.
      Register Reg = CS.getReg();
      const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
      TII.storeRegToStackSlot(MBB, MI, Reg, !MBB.isLiveIn(Reg),
                              CS.getFrameIdx(), RC, TRI, Register());
    }
  };
  storeRegToStackSlot(UnmanagedCSI);
  ...
```
Due to it, list of RVV callee saved registers will always be empty.
Currently this problem doesn't appear, but if you slightly change the
code and, for example, put some instructions between scalar and vector
spills, the resulting code will be ill formed.
2024-12-18 12:27:40 +03:00
Craig Topper
42d598b591 [RISCV] Rename a lambda to have plural nouns to reflect that it contains a loop. NFC
storeRegToStackSlot contains a loop that stores multiple registers
to multiple slots.
2024-12-11 11:44:36 -08:00
Craig Topper
c835b48a4d [RISCV] Compute liveins for new basic blocks in emitStackProbeInline.
Fixes expensive check failures from #117612.
2024-12-10 12:37:45 -08:00
Raphael Moreira Zinsly
708a478d67
[RISCV] Add stack clash protection (#117612)
Enable `-fstack-clash-protection` for RISCV and stack probe for function
prologues.
We probe the stack by creating a loop that allocates and probe the stack
in ProbeSize chunks.
We emit an unrolled probe loop for small allocations and emit a variable
length probe loop for bigger ones.
2024-12-10 16:48:26 +00:00
Raphael Moreira Zinsly
57452bb3a9
[NFC][RISCV] Remove CFIIndex argument from allocateStack (#117871)
Calculates CFIIndex inside RISCVFrameLowering::allocateStack instead of
sending it by argument.
2024-12-02 10:37:02 -08:00