Comments (12)
Now clang already supports some C operators for SVE sizeless types. I have a patch to support C operators for RVV sizeless types, https://reviews.llvm.org/D158259.
from rvv-intrinsic-doc.
The backend of compiler (not sure about gcc) has ability to transform mask ? op1+op2 : vd
into masked instruction. So with implemention of the conditional expression, I think we could handle the masked cases.
For vl, I also agree with @dzaima. One of motivation of this proposal is simplifying the syntax of vector calculation when vl=vlmax. For the cases that still demand vl, I think we could keep using intrinsics.
from rvv-intrinsic-doc.
But how to implement C operators with mask?
from rvv-intrinsic-doc.
But how to implement C operators with mask?
... And how to control mask policy?
Or how to use flexible VL? And how to control tail policy?
The proposed semantics are unmasked, with VL = VLMAX, which resolves these questions, but requires users who need those features to use intrinsics.
from rvv-intrinsic-doc.
If a ? b : c
was supported (as gcc and clang do for fixed-length vectors, ...though only in C++), or some similar thing for a blend/merge, __riscv_vadd_vv_i32m1_mu(mask, vd, op1, op2, -1)
could be mask ? op1+op2 : vd
. (and fwiw, clang already can convert a __riscv_vmerge
to masking a source operand)
For arithmetic operations (i.e. all things proposed here), tail-agnostic and mask-agnostic aren't really strictly necessary; the compiler could infer a smaller VL from uses/argument sources. e.g. these are valid transformations:
__riscv_vse32(ptr, __riscv_vadd(a, b, VLMAX), 2); // == proposed __riscv_vse32(ptr, a+b, 2);
↓
__riscv_vse32(ptr, __riscv_vadd(a, b, 2), 2);
vint32m1_t vec = __riscv_vadd(__riscv_vle32_v_i32m1(ptr, 2), b, VLMAX); // == proposed __riscv_vle32_v_i32m1(ptr, 2) + b
↓
vint32m1_t vec = __riscv_vadd(__riscv_vle32_v_i32m1(ptr, 2), b, 2);
and mask-agnostic afaik isn't really useful for arithmetic at all other than a hint (ignoring FP exceptions/vxsat, which should be rarely needed and isn't even supported by existing intrinsics yet anyway), and thus are replaceable with like mask ? op1+op2 : __riscv_vundefined_i32m1()
if really desired for whatever reason.
There'll still be some cases where VL control is required (tail-undisturbed is a thing that's not easily replaced; I guess there's like __riscv_vmv_v(vd, a+b, vl)
?), but it could still be worth having the C operators for when that's not the case.
from rvv-intrinsic-doc.
@jacquesguan thanks for raising this, this topic has raise long time ago, however it has stop for a while since we've discuss around explicitly VL or implicitly VL at that moment, but now we are settle down with the explicitly VL for a while so it's kind of obviously to define those operator as VLMAX semantics for now.
Anyway I want to express I am support this in general, and here is few comments around different things:
- Unary operators like
-
,!
and~
.++
and--
may just ignore. - How about
vbool*_t
? I guess we could support bitwise operators, also!
and/or~
.
If a ? b : c was supported (as gcc and clang do for fixed-length vectors, ...though only in C++),
I support this, it's customized type, so I think we are not necessary has same limitation, I mean we could support that for both C and C++.
Also I would like to add few more syntax sugar around tuple type:
- Brace initialization for tuple type (syntax sugar for vcreate)
vint32m1_t x, y;
vint32m1x2_t a = {x, y};
- subscript operators (syntax sugar for vget/vset)
vint32m1_t x, y;
vint32m1x2_t a;
a[1] = x;
y = a[1];
from rvv-intrinsic-doc.
I've tried a similar approach using C++ template classes and operators, here is some example I achieved:
All that required is to enable rvv intrinsic types to be contained in regular C++ class/struct (which is not true for now, but I tried all the code below with modified riscv g++ from gcc 12) , then rest of the work is all done by C++ grammar features, no further compiler frontend support needed.
basic types
rvv_vector<uint32_t, m1> v0;
rvv_vector<uint64_t, m4> v1;
rvv_vector<uint16_t, mf2> v2;
rvv_vector<uint8_t, mf8> v3;
rvv_mask<8> vm1;
rvv_mask<64> vm2;
vlen setting:
size_t vl = rvv_vector<uint16_t, m2>::vsetvlmax(); // set max vl according to vtype and lmul
set_global_vl(13); // set global vl, all operators below will use it, until set vl again or specified vl in specific op
v3.store(data, vl); // certain functions can have specified vl
//most operators can only use global vl, since there is not enough slot
load store
uint16_t data[512] = {...}; //
rvv_vector<uint16_t, m2> v1, v2, v3;
v1.load(data);
vl = 15;
v1.load(data, vl);
v1.load_index_od(data, index, vl); // variations of load instrinsics
v1 = 12;
v3.store(data, vl);
arithmetic
rvv_vector<uint32_t, m1> vindex, v0, v1, v2, v3, v4, v5;
vindex.index(); // index operator, v[i] = i
v1 = 1; // v1[i] = C for all i = {0, 1, 2, ...}
v2 = vindex % 2; // v2[i] = vindex[i] % 2
v3 = vindex + v2;
v3 += 3;
v4 = v2*v3;
v5 *= v4<<1;
v6 = v2 & v5; // v6[i] = v2[i] & v5[i] for i = {0, 1, 2, 3, ...}
v6 = v1+v2-v3*v4; // conbinations
logical and mask operations, commonly used syntax in math libs like numpy
rvv_vector<uint32_t, m1> v0, v1, v2, v3;
vindex.index(); // vindex = {0,1,2,3, ... }
rvv_mask<8> vm1 = vindex==1; // vm1[i] = 1 if i==1, else 0
auto vm2 = vindex%1!=0; // vm2[i] = 1 if i = 1,3,5,...
auto vm3 = vindex>5; // vm3[i]=1 if i>5
auto vm4 = v1&&v2 || vm3; // logic operations
v2 = v1[vm1]; // masked assignment
v2[vm1] = v1; // same effect as above
v2 = v1[vm4] + v0; // v2[i] = v1[i]+v2[i] if vm4[i]==1, else v2[i]
v3 = v1[vindex>1 && vindex<5 || vindex>8] * v2; // combinations
widen/narrow op:
rvv_vector<uint8_t, m1> v0, v1, v2;
auto v1 = v0.widen_op() + 1 // rvv_vector<uint16_t, m2>
auto v2 = v1.narrow_op(); // rvv_vector<uint8_t, m1>
rvv_vector<uint64_t, m8> v4;
auto v5 = v4.narrow_op() + 1; // error, uint8 can't be narrowed
auto v6 = v5.widen_op() * 1; // error, m8 can't be widdend
from rvv-intrinsic-doc.
Just a quick +1 from Highway, we'd love to have operators. Currently we're requiring user code to write Div() or MaskedDivOr(), it would be nice to avoid that.
I agree with dzaima, _mu is the only thing we'd use (why use masks otherwise?). And VLMAX is also fine, one can also use masks for tail/remainder handling.
from rvv-intrinsic-doc.
With @kito-cheng 's comment, let me conclude the operators we would support for RVV:
For RVV sizeless vector type:
unary operators:
-
, +
!
, ~
++
, --
binary operators:
arithmetic operators: +
, -
, *
, /
, %
;
bitwise operators: &
, |
, ^
;
compare operators: ==
, !=
, >
, >=
, <
, <=
;
shift operators: <<
, >>
;
subscript operators: []
.
ternary operatros : ?
For RVV sizeless mask vector type:
Only support:
!
, ~
, &
, |
, ^
;
For RVV sizeless vector tuple type:
brace initialization {}
subscript operators []
from rvv-intrinsic-doc.
I see subscript operators for non-tuple types too, do you intend to propose declaration for an array of RVV non-tuple type?
from rvv-intrinsic-doc.
I see subscript operators for non-tuple types too, do you intend to propose declaration for an array of RVV non-tuple type?
Similar to fixed length vectors, subscript operator for sizeless vectors means getting the i th element from the vector. By example, v[i]
will lower to extractelement <vscale x n x ty> v, i64 i
in LLVM.
from rvv-intrinsic-doc.
As I mentioned in #13, if you use the architecture-independent vector extension in Clang then you can use C operators for the bulk of your code and dip into intrinsics when you need to do something esoteric.
I'll just repeat that here, because I don't want existing functionality to be overlooked and duplicated.
Trouble is, that extension forces you to specify the size of the vector at compile time, and it picks RVV types which it thinks can do the job; setting VL appropriately for portable code. That's where I think an extension would be needed -- the ability to make that vector type sizeless.
And also it doesn't work in GCC.
from rvv-intrinsic-doc.
Related Issues (20)
- [Requirement]: The RISC-V RVV vector intrinsic must include support for vector groups in the __riscv_vfredosum function HOT 4
- Type-relative overloads for vreinterpret, vlmul_ext, vlmul_trunc, etc. HOT 1
- How to use a class to wrap or derive from a sizeless vector type HOT 1
- Encode all the effects of vsetvl in the return type, for use in subsequent type deductions HOT 1
- Does `__riscv_v_intrinsic >= 1000000` imply overloaded intrinsics are supported?
- Create bibliography from reference section HOT 3
- Simple questions about inline assembly in vmv.x.s instruction HOT 2
- Asterisks are not subscripts
- the wrong result of "vmerge_vvm_i32m1" HOT 5
- ta,ma reduction destination with vl=0 HOT 1
- Clarify the consequences of vxsat not being handled by the intrinsics HOT 3
- Add a section with examples HOT 3
- Rename uses of {implicit,explicit}-frm into {Implicit, Explicit} FP rounding mode HOT 1
- Clarify the mapping of pseudo-intrinsics
- Clarify what float and double means HOT 1
- Fix authors in the document
- How to use LMUL in rvv-intrinsic? HOT 6
- Mismatched bfloat16 autogenerated files HOT 3
- Freeze the specification HOT 1
- `vfirst` and `vcpop` return types unexpectedly changed HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rvv-intrinsic-doc.