Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/hotspot/share/opto/vectornode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2100,7 +2100,9 @@ Node* SelectFromTwoVectorNode::Ideal(PhaseGVN* phase, bool can_reshape) {
// (VectorRearrange SRC1, INDEX)
// (VectorRearrange SRC2, NORM_INDEX)
// MASK)
//
// This shall prevent an intrinsification failure and associated argument
// boxing penalties.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick comment about how the mask is computed could be nice.
MASK = INDEX < num_elem

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jatin-bhateja very nice, thanks!


auto lane_count_type = [&]() {
switch(elem_bt) {
case T_BYTE:
Expand Down Expand Up @@ -2177,6 +2179,10 @@ Node* VectorRearrangeNode::Ideal(PhaseGVN* phase, bool can_reshape) {
default: return elem_bt;
}
};
// Targets emulating unsupported permutation for certain vector types
// may need to message the indexes to match the users intent.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// may need to message the indexes to match the users intent.
// may need to massage the indexes to match the users intent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This optimization for now seems quite specific to your SelectFromTwoVectorNode::Ideal lowering code. Can this conversion not be done there already?

What is the semantics of VectorRearrangeNode? Should its shuffle vector always be bytes, and we now violated that "for a quick second"? Or is it going to be generally the idea to create all sorts of shuffle types and then fix that up? But then why do we need the vector_indexes_needs_massaging?

Can you help me understand the concept/strategy behind this?

Copy link
Member Author

@jatin-bhateja jatin-bhateja Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, variable index permutation instruction on every target expects shape conformance b/w data vector and permute index vector. Rearrange expects indices to be passed through shuffle, idealization routines automatically injects a VectorLoadShuffle after loading indexes held in shuffle's backing storage i.e. a byte array.

In all the cases apart from byte vector permute , VectorLoadShuffle expands the index byte lanes to match the data vector lane. So we always end up emitting a lane expansion instruction before permute instruction (scenario 1). Apart from usual expansions VectorLoadShuffle may also do additional magic for some targets where it may need to prune / massage the index vector if target does not support destination vector type (scenario 2).

For our case, new selectFrom accepts the indices though vectors which save redundant expansions, but to leverage existing backend support for scenario 2 we do target specific pruning

// Lowering index vector to a bytevector followed by an explicit loadshuffle
// will bring the indexes in the consumable format.
int cast_opc = VectorCastNode::opcode(-1, elem_bt, true);
Node* pack_shuf = phase->transform(VectorCastNode::make(cast_opc, in(2), T_BYTE, num_elem));
const TypeVect* newvt = TypeVect::make(get_integal_type(elem_bt), num_elem);
Expand Down