RFC: support scalable vector model / riscv vector
Jojo R <rjiejie-KPsoFbNs7GizrGE5bRqYAgC/[email protected]> Fri, 21 Apr 2023 17:25:40 +0800
| Newsgroups | gmane.comp.debugging.valgrind.devel,gmane.comp.debugging.valgrind |
|---|---|
| Message-ID | <[email protected]> |
Hi,
We consider to add RVV/Vector [1] feature in valgrind, there are some
challenges.
RVV like ARM's SVE [2] programming model, it's scalable/VLA, that means
the vector length is agnostic.
ARM's SVE is not supported in valgrind :(
There are three major issues in implementing RVV instruction set in
Valgrind as following:
1. Scalable vector register width VLENB
2. Runtime changing property of LMUL and SEW
3. Lack of proper VEX IR to represent all vector operations
We propose applicable methods to solve 1 and 2. As for 3, we explore
several possible but maybe imperfect approaches to handle different cases.
We start from 1. As each guest register should be described in
VEXGuestState struct, the vector registers with scalable width of VLENB
can be added into VEXGuestState as arrays using an allowable maximum
length like 2048/4096.
The actual available access range can be determined at Valgrind startup
time by querying the CPU for its vector capability or some suitable
setup steps.
To solve problem 2, we are inspired by already-proven techniques in
QEMU, where translation blocks are broken up when certain critical CSRs
are set. Because the guest code to IR translation relies on the precise
value of LMUL/SEW and they may change within a basic block, we can break
up the basic block each time encountering a vsetvl{i} instruction and
return to the scheduler to execute the translated code and update
LMUL/SEW. Accordingly, translation cache management should be refactored
to detect the changing of LMUL/SEW to invalidate outdated code cache.
Without losing the generality, the LMUL/SEW should be encoded into an
ULong flag such that other architectures can leverage this flag to store
their arch-dependent information. The TTentry struct should also take
the flag into account no matter insertion or deletion. By doing this,
the flag carries the newest LMUL/SEW throughout the simulation and can
be passed to disassemble functions using the VEXArchInfo struct such
that we can get the real and newest value of LMUL and SEW to facilitate
our translation.
Also, some architecture-related code should be taken care of. Like
m_dispatch part, disp_cp_xindir function looks up code cache using
hardcoded assembly by checking the requested guest state IP and
translation cache entry address with no more constraints. Many other
modules should be checked to ensure the in-time update of LMUL/SEW is
instantly visible to essential parts in Valgrind.
The last remaining big issue is 3, which we introduce some ad-hoc
approaches to deal with. We summarize these approaches into three types
as following:
1. Break down a vector instruction to scalar VEX IR ops.
2. Break down a vector instruction to fixed-length VEX IR ops.
3. Use dirty helpers to realize vector instructions.
The very first method theoretically exists but is probably not
applicable as the number of IR ops explodes when a large VLENB is
adopted. Imaging a configuration of VLENB=512, SEW=8, LMUL=8, the VL is
512 * 8 / 8 = 512, meaning that a single vector instruction turns into
512 scalar instructions and each scalar instruction would be expanded to
multiple IRs. To make things worse, the tool instrumentation will insert
more IRs between adjacent scalar IR ops. As a result, the performance is
likely to be slowed down thousand times during running a real-world
application with lots of vector instructions. Therefore, the other two
methods are more promising and we will discuss them below.
2 and 3 are not mutually exclusive as we may choose a suitable method
from them to implement a vector instruction regarding its concrete
behavior. To explain these methods in detail, we present some instances
to illustrate their pros and cons.
In terms of method 2, we have real values of VLENB/LMUL/SEW. The simple
case is VLENB <= 256 and LMUL=1, where many SIMD IR ops are available
and can be directly applied to represent vector operations. However,
even when VLENB is restricted to 128, it still exceeds the maximum SIMD
width of 256 supported by VEX IR if LMUL>2. Hence, here are two variants
of method 2 to deal with long vectors:
*2.1*Add more SIMD IR ops such as 1024/2048/4096, and translate vector
instructions in the granularity of VLENB. Accordingly, VLENB=4096 with
LMUL=2 is fulfilled by two 4096 SIMD VEX IR ops.
* *pros*: it encourages VEX backend to generate more compact and
efficient SIMD code (maybe). Particularly,it accommodatesmask and
gather/scatter (indexed) instructions by delivering more information
in IR itself.
* *cons*: too many new IR ops need to be introduced in VEX as each op
of different length should implement its add/sub/mul variants. New
data types to denote long vectors are necessary too, causing
difficulties in both VEX backend register allocation and tool
instrumentation.
*2.2*Break down long vectors to multiple repeated SIMD ops. For
instance, a vadd.vv vector instruction with VLENB=256/LMUL=2/SEW=8 is
composed of four operators of Iop_Add8x16 type.
* *pros:*less efforts are required in register allocation and tool
instrumentation. The VEX frontend is able to notify the backend to
generate efficient vector instructions by existing Iops. It better
trades off the complexity of adding many long vector IR ops and the
benefit of generating high-efficiency host code.
* *cons:*it is hard to describe a mask operation given that the mask
is pretty flexible (the least significant bit of each segment of
v0). Additionally, gather/scatter instructions may have similar
problems in appropriately dividing index registers. There are
various corner cases left here such as widening arithmetic
operations (widening SIMD IR ops are currently not compatible) and
vstart CSR register. When using fixed-length IR ops to comprise a
vector instruction, we will inevitably tell each IR op which
position encoded in vstart you can start to process the data. We can
use vstart as a normal guest state virtual register to calculate
each op's start position as a guard IRExpr or obtain the value of
vstart like what we do in LMUL/SEW. Nevertheless, it is non-trivial
to decompose a vector instruction concisely.
In short, both 2.1 and 2.2 confront a dilemma in reducing engineering
efforts of refactoring Valgrind elegantly as well as implementing the
vector instruction set efficiently. Same obstacles exist in ARM SVE as
they are scalable vector instructions and flexible in many ways.
The final solution is the dirty helper. It is undoubtedly practical and
requires possibly the least engineering efforts in dealing with so many
details in Valgrind. In this design, each instruction is completed using
an inline assembly running the same instruction on the host. Moreover,
tool instrumentation already handles IRDirty except that new fields
should be added in _IRDirty struct to indicate strided/indexed/masked
memory accesses and arithmetic operations.
* *pros:*it supports all instructions without bothering to build
complicated IR expressions and statements. It executes vector
instructions using host CPU to get acceleration to some extent.
Besides, we do not need to add VEX backend to translate new IRs to
vector instructions.
* *cons:*the dirty helper always keeps its operations in a black box
such that tools can never see what happens in a dirty helper. Like
memcheck, the bit precision merit is missing once it meets a dirty
helper as the V-bit propagation chain adopts a pretty coarse
determination strategy. On the other hand, it is also not an elegant
way to implement the entire ISA extension in dirty helpers.
In summary, it is far to reach a truly applicable solution in adding
vector extensions in Valgrind. We need to do detailed and comprehensive
estimations on different vector instruction categories.
Any feedback is welcome in github [3] also.
[1] https://github.com/riscv/riscv-v-spec
[2]
https://community.arm.com/arm-research/b/articles/posts/the-arm-scalable-vector-extension-sve
[3] https://github.com/petrpavlu/valgrind-riscv64/issues/17
Thanks.
Jojo
_______________________________________________
Valgrind-developers mailing list
Valgrind-developers-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/valgrind-developers