@@ -412,4 +412,72 @@ inline Register as_Register(FloatRegister reg) {
412412// High-level register class of an OptoReg or a VMReg register.
413413enum RC { rc_bad, rc_int, rc_float, rc_predicate, rc_stack };
414414
415+ // AArch64 Vector Register Sequence management support
416+ //
417+ // VSeq implements an indexable (by operator[]) vector register
418+ // sequence starting from a fixed base register and with a fixed delta
419+ // (defaulted to 1, but sometimes 0 or 2) e.g. VSeq<4>(16) will return
420+ // registers v16, ... v19 for indices 0, ... 3.
421+ //
422+ // Generator methods may iterate across sets of VSeq<4> to schedule an
423+ // operation 4 times using distinct input and output registers,
424+ // profiting from 4-way instruction parallelism.
425+ //
426+ // A VSeq<2> can be used to specify registers loaded with special
427+ // constants e.g. <v30, v31> --> <MONT_Q, MONT_Q_INV_MOD_R>.
428+ //
429+ // A VSeq with base n and delta 0 can be used to generate code that
430+ // combines values in another VSeq with the constant in register vn.
431+ //
432+ // A VSeq with base n and delta 2 can be used to select an odd or even
433+ // indexed set of registers.
434+ //
435+ // Methods which accept arguments of type VSeq<8>, may split their
436+ // inputs into front and back halves or odd and even halves (see
437+ // convenience methods below).
438+
439+ template <int N> class VSeq {
440+ static_assert (N >= 2 , " vector sequence length must be greater than 1" );
441+ static_assert (N <= 8 , " vector sequence length must not exceed 8" );
442+ static_assert ((N & (N - 1 )) == 0 , " vector sequence length must be power of two" );
443+ private:
444+ int _base; // index of first register in sequence
445+ int _delta; // increment to derive successive indices
446+ public:
447+ VSeq (FloatRegister base_reg, int delta = 1 ) : VSeq(base_reg->encoding (), delta) { }
448+ VSeq (int base, int delta = 1 ) : _base(base), _delta(delta) {
449+ assert (_base >= 0 , " invalid base register" );
450+ assert (_delta >= 0 , " invalid register delta" );
451+ assert ((_base + (N - 1 ) * _delta) < 32 , " range exceeded" );
452+ }
453+ // indexed access to sequence
454+ FloatRegister operator [](int i) const {
455+ assert (0 <= i && i < N, " index out of bounds" );
456+ return as_FloatRegister (_base + i * _delta);
457+ }
458+ int mask () const {
459+ int m = 0 ;
460+ int bit = 1 << _base;
461+ for (int i = 0 ; i < N; i++) {
462+ m |= bit << (i * _delta);
463+ }
464+ return m;
465+ }
466+ int base () const { return _base; }
467+ int delta () const { return _delta; }
468+ };
469+
470+ // declare convenience methods for splitting vector register sequences
471+
472+ VSeq<4 > vs_front (const VSeq<8 >& v);
473+ VSeq<4 > vs_back (const VSeq<8 >& v);
474+ VSeq<4 > vs_even (const VSeq<8 >& v);
475+ VSeq<4 > vs_odd (const VSeq<8 >& v);
476+
477+ // methods for use in asserts to check VSeq inputs and oupts are
478+ // either disjoint or equal
479+
480+ template <int N, int M> bool vs_disjoint (const VSeq<N>& n, const VSeq<M>& m) { return (n.mask () & m.mask ()) == 0 ; }
481+ template <int N> bool vs_same (const VSeq<N>& n, const VSeq<N>& m) { return n.mask () == m.mask (); }
482+
415483#endif // CPU_AARCH64_REGISTER_AARCH64_HPP
0 commit comments