Skip to content

Implement RVV widening floating-point conversions - #771

Open
alanhc wants to merge 1 commit into
sysprog21:masterfrom
alanhc:rvv-vfwcvt
Open

alanhc wants to merge 1 commit into
sysprog21:masterfrom
alanhc:rvv-vfwcvt

Conversation

@alanhc

@alanhc alanhc commented Sep 10, 2026

Copy link
Copy Markdown

Implements the widening conversions from #734. Second of three PRs sharing
the VFUNARY0 decode site; best taken after #770.

Adds the seven vfwcvt forms (V 1.0 §13.17), producing a 64-bit destination
element from a 32-bit source.

As with vzext/vsext, the destination EEW exceeds the source EEW, so §5.2
requires the source EMUL to be at least 1 and the overlap to sit in the
highest-numbered part of the destination group. rvv_cross_eew_overlap_illegal()
implements the shared-base-register rule instead, which matches the narrowing
direction, so this path uses a dedicated predicate
(rvv_widen_overlap_illegal()) with a comment explaining the distinction.
The predicate was checked against the spec's LMUL=8 example and against
fractional-LMUL cases where the source EMUL falls below 1.

Reserved vs1 values and the single-width / narrowing ranges are rejected;
the decode tests assert that.

Smoke coverage uses 1.5 to separate RNE from RTZ (2.5 gives the same result
under both, so it would not catch a .rtz variant that ignored its suffix)
and -3 to separate the signed and unsigned integer-to-float forms.

make check passes; the build was checked in the default, EXT_V,
JIT+EXT_V and EXT_V-without-EXT_F configurations. clang-format 20.1.7
clean.


Summary by cubic

Implements the seven vfwcvt widening floating-point conversions from #734, producing 64-bit destination elements from 32-bit sources. Previously these encodings returned illegal; now they decode and execute.

New Features

  • Supports all seven forms: float-to-int, int-to-float, and float-to-float, with rtz variants pinning round-towards-zero.
  • Enforces the spec's §5.2 overlap rule via a dedicated predicate, which requires the source EMUL to be at least 1 and the overlap in the highest-numbered destination part.
  • Adds smoke tests using 1.5 and -3 to distinguish rounding modes and signed/unsigned conversions.

Written for commit 3c5b27a. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/rv32_v_template.c">

<violation number="1" location="src/rv32_v_template.c:7552">
P2: When a masked `vfwcvt` uses `vd` overlapping `v0`, this validation allows it and the execution loop reads and overwrites the same mask register. Later elements then use result bits as mask bits; reject destination groups overlapping `v0` whenever `ir->vm` is clear, as the masked load paths do.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/rv32_v_template.c
if ((rvv_sew_bits(rv->csr_vtype) != 32) || \
!rvv_wide_group_span(rv, &wide_span) || \
!rvv_validate_wide_reg(rv, ir->vd) || \
!rvv_validate_data_reg(rv->csr_vtype, ir->vs2) || \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a masked vfwcvt uses vd overlapping v0, this validation allows it and the execution loop reads and overwrites the same mask register. Later elements then use result bits as mask bits; reject destination groups overlapping v0 whenever ir->vm is clear, as the masked load paths do.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/rv32_v_template.c, line 7552:

<comment>When a masked `vfwcvt` uses `vd` overlapping `v0`, this validation allows it and the execution loop reads and overwrites the same mask register. Later elements then use result bits as mask bits; reject destination groups overlapping `v0` whenever `ir->vm` is clear, as the masked load paths do.</comment>

<file context>
@@ -7448,6 +7540,35 @@ static inline void rvv_exec_vfmv_v_f(riscv_t *rv,
+        if ((rvv_sew_bits(rv->csr_vtype) != 32) ||                    \
+            !rvv_wide_group_span(rv, &wide_span) ||                   \
+            !rvv_validate_wide_reg(rv, ir->vd) ||                     \
+            !rvv_validate_data_reg(rv->csr_vtype, ir->vs2) ||         \
+            rvv_widen_overlap_illegal(rv, ir->vd, wide_span, ir->vs2, \
+                                      narrow_span))                   \
</file context>

Add the seven vfwcvt forms (V 1.0 section 13.17), producing a 64-bit
destination element from a 32-bit source.

The destination EEW exceeds the source EEW, so section 5.2 requires the
overlap to sit in the highest-numbered part of the destination group with
a source EMUL of at least 1. That is not the rule implemented by
rvv_cross_eew_overlap_illegal(), which matches the narrowing direction, so
this path uses a dedicated predicate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant