Giter Site home page Giter Site logo

Comments (12)

jacquesguan avatar jacquesguan commented on July 19, 2024 1

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.

jacquesguan avatar jacquesguan commented on July 19, 2024 1

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.

chLFF avatar chLFF commented on July 19, 2024

But how to implement C operators with mask?

from rvv-intrinsic-doc.

nick-knight avatar nick-knight commented on July 19, 2024

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.

dzaima avatar dzaima commented on July 19, 2024

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) + bvint32m1_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.

kito-cheng avatar kito-cheng commented on July 19, 2024

@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:

  1. Brace initialization for tuple type (syntax sugar for vcreate)
vint32m1_t x, y;
vint32m1x2_t a = {x, y};
  1. subscript operators (syntax sugar for vget/vset)
vint32m1_t x, y;
vint32m1x2_t a;
a[1] = x;
y = a[1];

from rvv-intrinsic-doc.

artintel2017 avatar artintel2017 commented on July 19, 2024

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.

jan-wassenberg avatar jan-wassenberg commented on July 19, 2024

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.

jacquesguan avatar jacquesguan commented on July 19, 2024

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.

eopXD avatar eopXD commented on July 19, 2024

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.

jacquesguan avatar jacquesguan commented on July 19, 2024

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.

sh1boot avatar sh1boot commented on July 19, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.