On 04/03/2016 09:12 PM, Woon yung Liu wrote:
I can't figure out how to implement comparison operations (specifically,
equals and the greater than operators). The GCC documentation mentions that
the pattern for comparison (==) should be vec_cmp, but I don't understand
why it has 4 operands and what they are used for.
The second operand is the comparison operator. So given
(set (reg:V4SI x) (eq:V4SI (reg:V4SI y) (reg:V4SI z))
operand 0 is x,
operand 1 is the entire (eq ...) expression,
operand 2 is y,
operand 3 is z.
This is exactly the same as the normal integer cbranch<mode> patterns.
I've implemented it
anyway, but GCC does not use it. I've taken a look at the rs6000 and
Loongson ports, and they seem to be implementing their comparison operators
with some non-standard pattern name and the pattern operations are different
too (i.e. Loongson uses unspec, while rs6000 uses gt and eq).
rs6000 doesn't implement bare comparisons, but only implements the "vcond"
conditional move upon which uses the comparison. Many of the other targets do
the same thing.
What happens what multiplication or division is performed a vector? For
example: c = a * b; Whereby a and b are both V4SI vectors. What vector type
would C be? Would it become another V4SI (meaning that the multiplication
result is truncated) or V4DI?
It would be the truncated V4SI mode.
There are other named patterns that implement widening multiply. Which you
choose depends on how the hardware selects which operands to include in the
multiply. Let { A, B, C, D } and { W, X, Y, Z} be V4SI inputs, then
Optab Result
vec_widen_{s,u}mult_hi_<mode> { A * W, B * X }
vec_widen_{s,u}mult_lo_<mode> { C * Y, D * Z }
vec_widen_{s,u}mult_even_<mode> { A * W, C * Y }
vec_widen_{s,u}mult_odd_<mode> { B * X, D * Z }
I also would like to ask about implementing bitwise-shifting. The R5900's
vector-shifting instructions are like the MIPS sll, srl and sra instructions,
whereby they use an immediate to shift all elements within the vector. Based on
the GCC documentation, a scalar can be used, but it will be first converted
into a similarly-sized vector
There are three different types of shifting: by a scalar (all elements shifted
by the same amount), by a vector (every element receives its own shift amount),
and full vector (shifting is not restricted to the element boundaries).
Scalar shifts: ashr<mode>3, ashl<mode>3, lshr<mode>3.
Vector shifts: vashr<mode>3, vashl<mode>3, vlshr<mode>3.
Full shifts: vec_shl_<mode>, vec_shr_<mode>.
Finally, what should I be modifying, if I want to implement extraction and
packing of the upper 64-bits of the 128-bit vector? Right now, GCC will just
generate multiple shifts (i.e. dsll32) to access the upper 64-bits, which is
not legal. This means that using any operation that requires unimplemented
patterns will not work correctly.
You want to implement vec_init<mode>, vec_extract<mode>, and vec_set<mode>.
You also want to implement as many vec_perm_const<mode> patterns as you can.
The existing mips_expand_vec_perm_const_1 code for loongson should be a good
starting point. The most important patterns that you'll want to be sure that
you can handle are interleave, even/odd, and broadcast. These are generated by
the vectorizer. You may wish to examine the aarch64 code for additional ideas;
it all depends on what sort of instructions you have available.
r~