265 Commits

Author SHA1 Message Date
Luke Lau
b02920f369
[RISCV] Don't increase vslide or splat vl if +vl-dependent-latency is present (#147089)
If the subtarget's latency is dependent on vl, then we shouldn't try to
fold away vsetvli toggles if it means increasing vl.
2025-07-09 16:25:22 +08:00
sc-clulzze
6c23e9e82c
[RISCV] Fix crash when trying to remove segment (#146524)
LiveInterval DefLI can be consisting of multiple segments, and SlotIndex
NewDefSI can be inside any of them. Currenty it is assumed that NewDefSI
belongs to the first segment, and when trying to call removeSegment,
clang crashes since there is no segment containing [DefLI.beginIndex(),
NewDefSI]

FIxes https://github.com/llvm/llvm-project/issues/146518
2025-07-03 16:15:40 +01:00
MingYan
faf9295f4e
[RISCV] Fix a bug where AVL is the last MI in MBB. (#144668)
When `AVL` is the last MI, `std::next(II)` equals `MBB.end()`, and
calling `II->getParent()` at that point will cause an error.

---------

Co-authored-by: yanming <ming.yan@terapines.com>
2025-06-19 10:15:31 +08:00
Luke Lau
2b8f82b830
[RISCV] Remove implicit $vl def on vleNff pseudos (#143935)
In #90049 we removed the side effect flag on the vleNff pseudos with the
reasoning that we modelled the effect of setting vl as an output
operand.

This extends this further by removing the implicit def on vl, inserting
it back in RISCVInsertVSETVLI when we also emit the PseudoReadVL.

The motiviation for this is to make it easier to handle vleff in more
places in RISCVVectorPeephole in a follow up patch, which in turn will
make migrating the last vmerge peephole over from RISCVISelDAGToDAG
easier.

Some of these tests claim that the vleff shouldn't be deleted when none
of its values are used, but these are from the initial commit in
3b5430eb0dad5. I'm not sure if these still hold today?

This also moves the fault-only-first predicate to
RISCVInstrPredicates.td since we can't rely on the implicit vl operand
anymore.
2025-06-12 23:40:57 +01:00
Luke Lau
a029ece7b0
[RISCV] Fix coalescing vsetvlis when AVL and vl registers are the same (#141941)
With EVL tail folding we can end up with vsetvlis where the output vl
and the input AVL are the same register. When we try to coalesce it we
crashed because we tried to move the def's live interval before the
kill's live interval, e.g. in this example:

    (vn0 def)
dead $x0 = PseudoVSETIVLI 1, 192, implicit-def $vl, implicit-def $vtype
    renamable $v9 = COPY killed renamable $v8
(vn1 def) %23:gprnox0 = PseudoVSETVLI killed (vn0) %23:gprnox0, 197,
implicit-def $vl, implicit-def $vtype

We would try to move the vn1 def VNInfo up to the previous VSETVLI, in
the middle of vn0's segment.

However separately, we were also assuming that the vl would only have
one definition and thus were just taking the VNInfo from beginIndex(),
so we ended up with a backwards segment and got the error "Cannot create
empty or backwards segment".

This fixes these two issues, the first one by moving the AVL operand +
live interval up first, and the second by taking the VNInfo from
NextMI's slot index.

Fixes #141907
2025-06-06 17:34:27 +02:00
Craig Topper
16994a6e76
[RISCV] Add a PseudoVSETVLIX0X0 pseudo for the x0,x0 vsetvli. NFC (#141875)
Strengthen the register class on PseudoVSETVLIX0 to disallow X0 as a
destination. This allows removal of an opcode check from
RISCVDeadRegisterDefinitions. Now the register class will prevent the
conversion to X0.

I'm considering removing the explicit X0 operands and adding them during
PseudoExpansion, but it complicates finding the vtype operand.
2025-05-29 10:21:38 -07:00
Min-Yih Hsu
ea88384466
[RISCV][InsertVSETVLI] Remove redundant vsetvli by coalescing blocks from bottom up (#141298)
I ran into a relatively rare case in RISCVInsertVSETVLIPass, where right
after the `emitVSETVLI` phase but before the `coalesceVSETVLIs` phase,
we have two blocks that look like this:
```
bb.first:
  %46:gprnox0 = PseudoVSETIVLI %30:gprnox0, 199 /* e8, mf2, ta, ma */, implicit-def $vl, implicit-def $vtype
  %76:gpr = PseudoVSETVLIX0 killed $x0, ..., implicit-def $vl, implicit-def $vtype
  $v10m2 = PseudoVMV_V_I_M2 undef renamable $v10m2, 0, -1, 5 /* e32 */, 0 /* tu, mu */, implicit $vl, implicit $vtype
...
bb.second:
  $x0 = PseudoVSETVLI %46, 209 /* e32, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
  $v10 = PseudoVMV_S_X undef $v10(tied-def 0), undef %53:gpr, $noreg, 5, implicit $vl, implicit $vtype
  $x0 = PseudoVSETVLI %30, 209 /* e32, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
  $v8 = PseudoVREDSUM_VS_M2_E32 undef $v8(tied-def 0), killed $v8m2, killed $v10, $noreg, 5, 0, implicit $vl, implicit $vtype
```

After the `coalesceVSETVLIs` phase, it turns into:
``` diff
bb.first:
-  %46:gprnox0 = PseudoVSETIVLI %30:gprnox0, 199 /* e8, mf2, ta, ma */, implicit-def $vl, implicit-def $vtype
+  dead %46:gprnox0 = PseudoVSETIVLI %30:gprnox0, 199 /* e8, mf2, ta, ma */, implicit-def $vl, implicit-def $vtype
  %76:gpr = PseudoVSETVLIX0 killed $x0, ..., implicit-def $vl, implicit-def $vtype
  $v10m2 = PseudoVMV_V_I_M2 undef renamable $v10m2, 0, -1, 5 /* e32 */, 0 /* tu, mu */, implicit $vl, implicit $vtype
...
bb.second:
-  $x0 = PseudoVSETVLI %46, 209 /* e32, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
+  $x0 = PseudoVSETVLI %30, 209 /* e32, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
  $v10 = PseudoVMV_S_X undef $v10(tied-def 0), undef %53:gpr, $noreg, 5, implicit $vl, implicit $vtype
- $x0 = PseudoVSETVLI %30, 209 /* e32, m2, ta, ma */, implicit-def $vl, implicit-def $vtype
  $v8 = PseudoVREDSUM_VS_M2_E32 undef $v8(tied-def 0), killed $v8m2, killed $v10, $noreg, 5, 0, implicit $vl, implicit $vtype
```
We forwarded `%30` to any use of `%46` and further reduced the number of
VSETVLI we need in `bb.second`. But the problem is, if `bb.first` is
processed before `bb.second` -- which is the majority of the cases --
then we're not able to remove the vsetvli which defines the now-dead
`%46` in `bb.first` after coalescing `bb.second`.

This will produce assembly code like this:
```
        vsetvli zero, s0, e8, mf2, ta, ma
        vsetvli a0, zero, e32, m2, ta, ma
        vmv.v.i v10, 0
```

This patch fixes this issue by coalescing the blocks from bottom up such
that we can account for dead VSETVLI in the earlier blocks after its
uses are eliminated in later blocks.

---------

Co-authored-by: Luke Lau <luke@igalia.com>
2025-05-27 12:15:37 -07:00
Philip Reames
e4b6cc314a [RISCV][InsertVSETVLI] Improve LMUL formatting in debug messages 2025-05-13 08:00:14 -07:00
Pengcheng Wang
8f75747935
[RISCV][NFC] Convert some predicates to TIIPredicate (#129658)
These predicates can also be used in macro fusion and scheduling
model.
2025-04-30 16:59:05 +08:00
Philip Reames
9062a38d5d
[RISCV] Add codegen support for ri.vinsert.v.x and ri.vextract.x.v (#136708)
These instructions are included in XRivosVisni. They perform a scalar
insert into a vector (with a potentially non-zero index) and a scalar
extract from a vector (with a potentially non-zero index) respectively.
They're very analogous to vmv.s.x and vmv.x.s respectively.

The instructions do have a couple restrictions:
1) Only constant indices are supported w/a uimm5 format.
2) There are no FP variants.

One important property of these instructions is that their throughput
and latency are expected to be LMUL independent.
2025-04-25 07:59:40 -07:00
Hank Chang
bd748b3395
[RISCV] Add implicit operand {VL, VTYPE} in RISCVInsertVSETVLI when u… (#130733)
…sing inline assembly.
Fixing [#128636](https://github.com/llvm/llvm-project/pull/128636).

This patch has RISCVInsertVSETVLI to add implicit use operand to inline
assembly, this approach is suggested by @preames and the implementation
I referenced is from @topperc . The purpose of adding vl, vtype implicit
operand is to prevent Post-RA scheduler moving vsetvl across inline
assembly.
2025-03-13 15:07:07 +08:00
Craig Topper
0cc532b79e
[RISCV] Move the RISCVII namespaced enums into RISCVVType namespace in RISCVTargetParser.h. NFC (#127585)
The VLMUL and policy enums originally lived in RISCVBaseInfo.h in the
backend which is where everything else in the RISCVII namespace is
defined.

RISCVTargetParser.h is used by much more of the compiler and it
doesn't really make sense to have 2 different namespaces exposed.
These enums are both associated with VTYPE so using the RISCVVType
namespace seems like a good home for them.
2025-02-18 08:27:25 -08:00
Craig Topper
9516f44f6b
[RISCV] Add policy operand to masked vector compare pseudos. Remove ForceTailAgnostic. NFC (#127575)
Add a policy operand to set the tail agnostic policy instead of using
ForceTailAgnostic. The masked to unmasked transforms had to be updated
to drop the policy operand when converting to unmasked.
2025-02-18 07:05: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
Luke Lau
c8d3ccfa16 [RISCV] Use llvm::reverse instead of make_range(rbegin, rend). NFC 2025-01-28 16:08:29 +08:00
Craig Topper
54246a39e4 [RISCV] Pass VSETVLIInfo by const reference. NFC 2025-01-03 16:51:08 -08:00
Craig Topper
d2b8acc104
[RISCV] Swap the order of SEWGreaterThanOrEqualAndLessThan64 and SEWGreaterThanOrEqual. (#120649)
SEWGreaterThanOrEqualAndLessThan64 is a stricter constraint so it should
have a higher value than SEWGreaterThanOrEqual.

Found by our random test generator.
2024-12-20 11:26:19 -08:00
Akshat Oke
2c7ece2e8c
[CodeGen][NewPM] Port LiveStacks analysis to NPM (#118778) 2024-12-06 15:16:07 +05:30
Luke Lau
b6c0f1bfa7
[RISCV] Clear vill for whole vector register moves in vsetvli insertion (#118283)
This is an alternative to #117866 that works by demanding a valid vtype
instead of using a separate pass.

The main advantage of this is that it allows coalesceVSETVLIs to just
reuse an existing vsetvli later in the block.

To do this we need to first transfer the vsetvli info to some arbitrary
valid state in transferBefore when we encounter a vector copy. Then we
add a new vill demanded field that will happily accept any other known
vtype, which allows us to coalesce these where possible.

Note we also need to check for vector copies in computeVLVTYPEChanges,
otherwise the pass will completely skip over functions that only have
vector copies and nothing else.

This is one part of a fix for #114518. We still need to check if there's
other cases where vector copies/whole register moves that are inserted
after vsetvli insertion.
2024-12-06 00:48:05 +08:00
Akshat Oke
d9b4bdbff5
[CodeGen][NewPM] Port LiveDebugVariables to NPM (#115468)
The existing analysis was already a pimpl wrapper.

I have extracted legacy pass logic to a LDVImpl wrapper named
`LiveDebugVariables` which is the analysis::Result now. This controls
whether to activate the LDV (depending on `-live-debug-variables` and
DIsubprogram) itself.

The legacy and new analysis only construct the LiveDebugVariables.

VirtRegRewriter will test this.
2024-12-04 14:31:34 +05:30
Luke Lau
c9fa3195f0
[RISCV] Use LiveIntervals to determine if AVL dominates when coalescing (#118285)
In order to coalesce a vsetvli with a register AVL into a previous
vsetvli, we need to make sure that the AVL register is reachable at the
previous vsetvli.

Back in pre-RA vsetvli insertion we just checked to see if the two
virtual registers were the same virtual register, and then this was
hacked around in the move to post-RA. We can instead use live intervals
to check that the reaching definition is the same at both instructions.

On its own this doesn't have much of an impact, but helps a lot in
#118283 and enables coalescing in about 60 of the test cases from that
PR.
2024-12-03 02:10:54 +08:00
Piotr Fusik
01b8dd1dba
[RISCV][NFC] Remove the unused RISCV_COALESCE_VSETVLI_NAME (#111536)
This pass was removed in 1cff74130f30aaf47a995c5f6b637a04eaab2617
2024-10-08 19:53:34 +02:00
Luke Lau
b1542afd0b
[RISCV] Rename merge operand -> passthru. NFC (#100330)
We sometimes call the first tied dest operand in vector pseudos the
merge operand, and other times the passthru.

Passthru seems to be more common, and it's what the C intrinsics call
it[^1], so this renames all usages of merge to passthru to be
consistent. It also helps prevent confusion with vmerge.vvm in some of
the peephole optimisations.

[^1]:
https://github.com/riscv-non-isa/rvv-intrinsic-doc/blob/main/doc/rvv-intrinsic-spec.adoc#the-passthrough-vd-argument-in-the-intrinsics
2024-07-30 17:47:00 +08:00
Luke Lau
e1065370aa
[RISCV] Remove vfmv.s.f and vfmv.f.s lmul pseudo variants (#100970)
In #71501 we removed the LMUL variants for vmv.s.x and vmv.x.s because
they ignore register groups, so this patch does the same for their
floating point equivalents.

We don't need to add any extra patterns for extractelt in
RISCVInstrInfoVSDPatterns.td because in lowerEXTRACT_VECTOR_ELT we make
sure that the node is narrowed down to LMUL 1.
2024-07-29 22:01:17 +08:00
Philip Reames
fd58e50880
[RISCV] Reverse iteration/deletion structure in vsetvli coalescing [NFC] (#98936)
The code previously deferred deleting the vsetvli to avoid invalidating
iterators, but eagerly deleted any ADDIs feeding the AVL register
operand. This was safe because the iterator was known to point to a
non-ADDI instruction (the vsetvli which was the previous user.) This
change switches to using an early_inc_range so that we can eagerly
delete the vsetvlis, but have to track ADDIs for later deletion.

This is purely stylistic, but IMO makes the code easier to follow. It
will also simplify a future change to support recursive deletion of
trivially dead instructions (i.e. LUI/ADDI pairs.)
2024-07-23 08:52:04 -07:00
Philip Reames
903f6fceb8
[RISCV] Prune dead LI in vsetvli coalescing with trivially dead vsetvli (#98647)
This is a follow up to ff8a03a7. On the review for that, I'd suggested a
stylistic rework, but after discussion we decided to move forward with
the fix as it was. This change is a small part of that suggested rework.
Once I sat down and wrote the code, I think I've convinced myself of an
entirely different approach (tbd), but for the moment, let's use a
lambda to share code so that we can pickup a missed optimization, and
reduce some duplication.

---------

Co-authored-by: Luke Lau <luke_lau@icloud.com>
2024-07-15 08:36:20 -07:00
Luke Lau
557ef043af
[RISCV] Copy AVLs whose LiveIntervals aren't extendable in insertVSETVLI (#98342)
Currently before forwarding an AVL we do a simple non-exhaustive check
to see if its LiveInterval is extendable. But we also need to check for
this when we're extending an AVL's LiveInterval via merging the
VSETVLIInfos in transferBefore with equally zero AVLs.

Rather than trying to conservatively prevent these cases, this inserts a
copy of the AVL instead if we don't know we'll be able to extend it.
This is likely to be more robust, and even if the extra copy is
undesirable these cases should be rare in practice.
2024-07-15 13:18:12 +08:00
Luke Lau
ff8a03a7ac
[RISCV] Fix coalesced vsetvli's AVL LiveInterval not always being shrunk (#98286)
Most of the time when we coalesce and delete a vsetvli, we shrink the
LiveInterval of its AVL register now that there is one less use. However
there's one edge case we were missing where if we have two vsetvlis with
no users of vl or vtype in between, we coalesced a vsetvli without
shrinking it's AVL.

This fixes it by shrinking the LiveInterval whenever we delete a
vsetvli, and also makes the LiveIntervals consistent in-situ by not
removing the use before shrinking.

This fixes a -verify-machineinstrs assertion in an MIR test case I found
while investigating
https://github.com/llvm/llvm-project/pull/97264#issuecomment-2218036877.
I couldn't recreate this at the LLVM IR level, seemingly because
RISCVInsertVSETVLI will just avoid inserting extra vsetvlis that don't
need coalesced.
2024-07-12 09:40:20 +08:00
Luke Lau
748a6ad68b [RISCV] Remove extra insertVSETVLI method. NFC
There's only one user of it, and to remove it we just need to pass
along the DebugLoc.
2024-07-10 19:57:18 +08:00
paperchalice
abde52aa66
[CodeGen][NewPM] Port LiveIntervals to new pass manager (#98118)
- Add `LiveIntervalsAnalysis`.
- Add `LiveIntervalsPrinterPass`.
- Use `LiveIntervalsWrapperPass` in legacy pass manager.
- Use `std::unique_ptr` instead of raw pointer for `LICalc`, so
destructor and default move constructor can handle it correctly.

This would be the last analysis required by `PHIElimination`.
2024-07-10 19:34:48 +08:00
Luke Lau
5ab755c972 [RISCV] Add LiveInterval assertions in insertVSETVLI. NFC
If we're inserting a vsetvli that uses a register AVL, then the AVL
register should either:

a) Be already live at the vsetvli with the expected value
b) Not be live at the vsetvli, but have exactly one value that can be
   extended safely: see #97264
2024-07-10 17:35:42 +08:00
Luke Lau
d0f3943a02
[RISCV] Remove -riscv-disable-insert-vsetvl-phi-opt flag (#97991)
This flag was added in https://reviews.llvm.org/D103277 out of
precaution, but it's been enabled by default for 3 years now and I
haven't seen any miscompiles upstream stemming from needVSETVLIPHI. This
would remove it just to simplify the number of configurations.
2024-07-09 12:11:08 +08:00
paperchalice
4010f894a1
[CodeGen][NewPM] Port SlotIndexes to new pass manager (#97941)
- Add `SlotIndexesAnalysis`.
- Add `SlotIndexesPrinterPass`.
- Use `SlotIndexesWrapperPass` in legacy pass.
2024-07-09 12:09:11 +08:00
Luke Lau
db782b44b3
[RISCV] Don't forward AVL in VSETVLIInfo if it would clobber other definitions (#97264)
This fixes a crash found when compiling OpenBLAS with -mllvm
-verify-machineinstrs.

When we "forward" the AVL from the output of a vsetvli, we might have to
extend the LiveInterval of the AVL to where insert the new vsetvli.

Most of the time we are able to extend the LiveInterval because there's
only one val num (definition) for the register. But PHI elimination can
assign multiple values to the same register, in which case we end up
clobbering a different val num when extending:

    %x = PseudoVSETVLI %avl, ...
    %avl = ADDI ...
    %v = PseudoVADD ..., avl=%x
    ; %avl is forwarded to PseudoVADD:
    %x = PseudoVSETVLI %avl, ...
    %avl = ADDI ...
    %v = PseudoVADD ..., avl=%avl

Here there's no way to extend the %avl from the vsetvli since %avl is
redefined, i.e. we have two val nums.

This fixes it by only forwarding it when we have exactly one val num,
where it should be safe to extend it.
2024-07-05 11:44:59 +08:00
Luke Lau
b3be148967
[RISCV] Use LiveIntervals::extendToIndices to extend AVL in insertVSETVLI (#97512)
In #96200 we handled extending AVL LiveIntervals across basic blocks,
which fixed a crash in a test case in
133ab9a8c82a31549f060da33fd7e14f1d7f39fd.

This was done by manually adding a single segment to the LiveInterval to
extend it from AVL def -> inserted vsetvli, but in hindsight this was
too simple and fails to handle cases where the vsetlvi is located before
the AVL def.

This patch fixes this by using LiveIntervals::extendToIndices instead
which can handle these cases.

(The crash that this fixes is separate from the crash in #97264)
2024-07-03 16:01:23 +08:00
Luke Lau
62a967d5dc
[RISCV] Return nullptr for PHI defs in VSETVLIInfo::getAVLDefMI (#97395)
When checking if a VSETVLIInfo is compatible, we call hasEquallyZeroAVL
if only the AVL-zeroness is demanded. This will try to lookup the
defining MachineInstr (to check if it's an ADDI immediate) via
getAVLDefMI, but in it we were asserting that the VSETVLIInfo's AVL
wouldn't come from a phi. It turns out this can happen in normal
circumstances.

This causes a crash when compiling highway, so this fixes it by relaxing
the assertion.
2024-07-02 20:41:11 +08:00
Luke Lau
f76ea31996 [RISCV] Deduplicate AVL forwarding in RISCVInsertVSETVLI. NFC
We do the AVL forwarding trick in both getInfoForVSETVLI and
computeInfoForInstr, but there's a bug with this that I plan on fixing
in an upcoming patch. This factors it out to so we only need to fix it
in one place.
2024-07-01 16:25:05 +08:00
Luke Lau
d03e812057 [RISCV] Update LiveIntervals before erasing instr in RISCVInsertVSETVLI
Hopefully fixes a use-after-poison reported from the asan buildbots. I
wasn't able to recreate the assertion locally though.
2024-07-01 14:02:48 +08:00
Luke Lau
95b0187165
[RISCV] Remove deleted AVL register defs from LiveInterval instr maps (#97011)
When coalescing vsetvlis we might remove a use of a register AVL, which
in turn might leave the AVL def dead. When it's dead (currently limited
to just ADDIs) we delete the def, but we were forgetting to remove it
from LiveInterval's instruction map. This fixes #95865
2024-07-01 10:15:58 +08:00
Luke Lau
a66900be75 [RISCV] Pretty print AVL register in VSETVLIInfo::dump. NFC
Currently the AVLReg is printed raw like {AVLReg=2147483668, ...}, this
changes it to {AVLReg=%20, ...} which should be easier to read.
2024-06-24 19:00:59 +08:00
Luke Lau
eb76bc38ff
[RISCV] Relax RISCVInsertVSETVLI output VL peeking to cover registers (#96200)
If the AVL in a VSETVLIInfo is the output VL of a vsetvli with the same
VLMAX, we treat it as the AVL of said vsetvli.

This allows us to remove a true dependency as well as treating
VSETVLIInfos as equal in more places and avoid toggles.

We do this in two places, needVSETVLI and computeInfoForInstr. However
we don't do this in computeInfoForInstr's vsetvli equivalent,
getInfoForVSETVLI.

We also have a restriction only in computeInfoForInstr that the AVL
can't be a register as we want to avoid extending live ranges.

This patch does two interlinked things:

1) It adds this AVL "peeking" to getInfoForVSETVLI

2) It relaxes the constraint that the AVL can't be a register in
computeInfoForInstr, since it removes a use of the output VL which can
actually reduce register pressure. E.g. see the diff in
@vector_init_vsetvli_N and @test6

Now that getInfoForVSETVLI and computeInfoForInstr are consistent, we
can remove the check in needVSETVLI.

We also need to update how we update LiveIntervals in insertVSETVLI, as
we can now end up needing to extend the LiveRange of the AVL across
blocks.
2024-06-23 20:20:59 +08:00
Luke Lau
d26808c4a6
[RISCV] Move RISCVInsertVSETVLI::coalesceVSETVLIs back to before insertReadVL (#96056) 2024-06-19 20:20:19 +08:00
Luke Lau
aabf6df644 [RISCV] Remove redundant dependency on SlotIndexes in RISCVInsertVSETVLI. NFC
SlotIndexes is already marked as a transitive requirement of
LiveIntervals, so we don't need to specify it again in
RISCVInsertVSETVLI.
2024-06-18 17:04:59 +08:00
Philip Reames
8756043467 [RISCV] Teach RISCVInsertVSETVLI to work without LiveIntervals
(Reapplying with corrected commit message)

We recently moved RISCVInsertVSETVLI from before vector register allocation
to after vector register allocation.  When doing so, we added an unconditional
dependency on LiveIntervals - even at O0 where LiveIntevals hadn't previously
run.  As reported in #93587, this was apparently not safe to do.

This change makes LiveIntervals optional, and adjusts all the update code to
only run wen live intervals is present.  The only real tricky part of this
change is the abstract state tracking in the dataflow.  We need to represent
a "register w/unknown definition" state - but only when we don't have
LiveIntervals.

This adjust the abstract state definition so that the AVLIsReg state can
represent either a register + valno, or a register + unknown definition.
With LiveIntervals, we have an exact definition for each AVL use.  Without
LiveIntervals, we  treat the definition of a register AVL as being unknown.

The key semantic change is that we now have a state in the lattice for which
something is known about the AVL value, but for which two identical lattice
elements do *not* neccessarily represent the same AVL value at runtime.
Previously, the only case which could result in such an unknown AVL was the
fully unknown state (where VTYPE is also fully unknown).  This requires a
small adjustment to hasSameAVL and lattice state equality to draw this
important distinction.

The net effect of this patch is that we remove the LiveIntervals dependency
at O0, and O0 code quality will regress for cases involving register AVL values.
In practice, this means we pessimize code written with intrinsics at O0.

This patch is an alternative to #93796 and #94340.  It is very directly
inspired by review conversation around them, and thus should be considered
coauthored by Luke.
2024-06-17 12:05:43 -07:00
Philip Reames
1d028151c9 Revert "[RISCV] Teach RISCVInsertVSETVLI to work without LiveIntervals (#94686)"
This reverts commit 111507ed4ce49bbb8cfbf36a3e143bb25f0f13c0.  Accidentally landed with stale commit message, will reply shortly.
2024-06-17 12:04:44 -07:00
Philip Reames
111507ed4c
[RISCV] Teach RISCVInsertVSETVLI to work without LiveIntervals (#94686)
Stacked on https://github.com/llvm/llvm-project/pull/94658.
    
We recently moved RISCVInsertVSETVLI from before vector register
allocation to after vector register allocation. When doing so, we added
an unconditional dependency on LiveIntervals - even at O0 where
LiveIntevals hadn't previously run. As reported in #93587, this was
apparently not safe to do.
    
This change makes LiveIntervals optional, and adjusts all the update
code to only run wen live intervals is present. The only real tricky
part of this change is the abstract state tracking in the dataflow. We
need to represent a "register w/unknown definition" state - but only
when we don't have LiveIntervals.
    
This adjust the abstract state definition so that the AVLIsReg state can
represent either a register + valno, or a register + unknown definition.
With LiveIntervals, we have an exact definition for each AVL use.
Without LiveIntervals, we treat the definition of a register AVL as
being unknown.
    
The key semantic change is that we now have a state in the lattice for
which something is known about the AVL value, but for which two
identical lattice elements do *not* necessarily represent the same AVL
value at runtime. Previously, the only case which could result in such
an unknown AVL was the fully unknown state (where VTYPE is also fully
unknown). This requires a small adjustment to hasSameAVL and lattice
state equality to draw this important distinction.
    
The net effect of this patch is that we remove the LiveIntervals
dependency at O0, and O0 code quality will regress for cases involving
register AVL values.
    
This patch is an alternative to
https://github.com/llvm/llvm-project/pull/93796 and
https://github.com/llvm/llvm-project/pull/94340. It is very directly
inspired by review conversation around them, and thus should be
considered coauthored by Luke.
2024-06-17 12:01:51 -07:00
Philip Reames
964c92d04f
[RISCV][InsertVSETVLI] Eliminate the AVLIsIgnored state (#94658)
As noted in one of the existing comments, the job AVLIsIgnored was
filing was really more of a demanded field role. Since we recently
realized we can use the values of VL on MI even in the backwards pass,
let's exploit that to improve demanded fields, and delete AVLIsIgnored.

Note that the test change is a real regression, but only incidental to
this patch. The backwards pass doesn't have the information that the VL
following a VL-preserving vtype is non-zero. This is an existing
problem, this patch just adds a few more cases where we prove
vl-preserving is legal.
2024-06-17 08:20:37 -07:00
Luke Lau
7d06bdcdfc
[RISCV] Use isCompatible when we need runtime VSETVLIInfo equality. NFC (#94340)
In VSETVLIInfo we define == as lattice equality, e.g. unknown == unknown
and invalid == invalid. We need this to check if the information at a
block's entry or exit has changed.

However I think we may have been conflating it with the notion that the
state of VL and VTYPE are the same, which isn't the case for two
unknowns, and potentially in an upcoming patch where we don't know the
value of an AVL register (see #93796)

This patch switches over the use in emitVSETVLIs to use isCompatible
with all fields demanded, since we need VL and VTYPE to be known equal
at runtime rather than just the VSETVLIInfos to be the same.

This should be NFC for now we shouldn't reach here with an unknown
state. But it's needed if we're to introduce the notion of an AVLReg
with a nullptr ValNo, which will need this non-reflexive equality.
Specifically, hasSameAVL should return false for this case, but ==
should return true.
2024-06-15 21:23:24 +08:00
Philip Reames
06f03b806a [RISCV][InsertVSETVLI] Check for undef register operand directly [nfc]
getVNInfoFromReg is expected to return a nullptr if-and-only-if the
operand is undef.  (This was asserted for.)  Reverse the order of the
checks to simplify an upcoming set of patches.
2024-06-06 13:21:04 -07:00
Luke Lau
83de21deb3 Revert "[RISCV] Store only VNInfo val no in VSETVLIInfo. NFC"
As noted in
https://github.com/llvm/llvm-project/pull/93796#issuecomment-2142752336,
a better way to teach RISCVInsertVSETVLI to work without LiveIntervals
is to set VNInfo to nullptr and teach the various methods to handle it.
We should try that approach first, so we no longer need this pre-commit
patch.

This reverts commit 4b4d36654d8056546b177b3d04c352ba0b16d7ea.
2024-06-03 15:54:36 +01:00