-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8338023: Support two vector selectFrom API #20508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
45bfe6c
82c0b0a
055fb22
e24632c
d7ad688
6cb1a46
408a869
8d71f17
d3ee310
1c00f41
7c80bfc
d72c82e
2953004
31a5864
42ca80c
7327736
130fa3e
6215ab9
1cca8e2
79ee29c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2087,106 +2087,66 @@ Node* VectorBlendNode::Identity(PhaseGVN* phase) { | |
| Node* SelectFromTwoVectorNode::Ideal(PhaseGVN* phase, bool can_reshape) { | ||
| int num_elem = vect_type()->length(); | ||
| BasicType elem_bt = vect_type()->element_basic_type(); | ||
|
|
||
| // Keep the node if it is supported, else lower it to other nodes. | ||
| if (Matcher::match_rule_supported_vector(Op_SelectFromTwoVector, num_elem, elem_bt)) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| Node* index_vec = in(1); | ||
| Node* src1 = in(2); | ||
| Node* src2 = in(3); | ||
|
|
||
| // Lower the IR to constituents operations. | ||
| // SelectFromTwoVectorNode = | ||
| // (VectorBlend | ||
| // (VectorRearrange SRC1 INDEX) | ||
| // (VectorRearrange SRC2 NORM_INDEX) | ||
| // (VectorRearrange SRC1 (WRAPED_INDEX AND (VLEN-1)) | ||
| // (VectorRearrange SRC2 (WRAPED_INDEX AND (VLEN-1)) | ||
| // MASK) | ||
| // Where | ||
| // incoming WRAPED_INDEX is within two vector index range [0, VLEN*2) and | ||
| // MASK = WRAPED_INDEX < VLEN | ||
| // | ||
| // MASK = INDEX < num_elem | ||
| // | ||
| // This shall prevent an intrinsification failure and associated argument | ||
| // IR lowering prevents intrinsification failure and associated argument | ||
| // boxing penalties. | ||
|
||
| // Here, MASK lanes corresponding to INDEX values greater than or equal to | ||
| // vector length (VELEN) are set and are used to select the elements from | ||
| // second source (SRC2) vector. | ||
| // | ||
|
|
||
| const Type* lane_count_type = nullptr; | ||
| switch(elem_bt) { | ||
| case T_BYTE: | ||
| case T_SHORT: | ||
| case T_INT: | ||
| case T_FLOAT: | ||
| lane_count_type = TypeInt::make(num_elem); | ||
| break; | ||
| case T_DOUBLE: | ||
| case T_LONG: | ||
| lane_count_type = TypeLong::make(num_elem); | ||
| break; | ||
| default: | ||
| fatal("Unsupported vectortype (%s)", type2name(elem_bt)); | ||
| break; | ||
| } | ||
| const TypeVect* index_vect_type = index_vec->bottom_type()->is_vect(); | ||
| BasicType index_elem_bt = index_vect_type->element_basic_type(); | ||
| assert(!is_floating_point_type(index_elem_bt), ""); | ||
jatin-bhateja marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| BasicType integral_elem_bt = elem_bt; | ||
| Node* integral_index_vec = index_vec; | ||
| if (elem_bt == T_FLOAT) { | ||
| integral_elem_bt = T_INT; | ||
| integral_index_vec = phase->transform(new VectorCastF2XNode(index_vec, TypeVect::make(integral_elem_bt, num_elem))); | ||
| } else if (elem_bt == T_DOUBLE) { | ||
| integral_elem_bt = T_LONG; | ||
| integral_index_vec = phase->transform(new VectorCastD2XNode(index_vec, TypeVect::make(integral_elem_bt, num_elem))); | ||
| } | ||
| // Downcast index vector to a type agnostic shuffle representation, shuffle indices | ||
| // are held in a byte vector which are later massaged to target specific permutation | ||
| // index format by subsequent VectorLoadShuffle. | ||
| int cast_vopc = VectorCastNode::opcode(0, index_elem_bt, true); | ||
jatin-bhateja marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Node* index_byte_vec = phase->transform(VectorCastNode::make(cast_vopc, index_vec, T_BYTE, num_elem)); | ||
|
||
|
|
||
| int opc = VectorSupport::vop2ideal(VectorSupport::VECTOR_OP_SUB, integral_elem_bt); | ||
| int sopc = VectorNode::opcode(opc, integral_elem_bt); | ||
| Node* lane_cnt_m1 = phase->makecon(TypeInt::make(num_elem - 1)); | ||
| Node* bcast_lane_cnt_m1_vec = phase->transform(VectorNode::scalar2vector(lane_cnt_m1, num_elem, Type::get_const_basic_type(T_BYTE), false)); | ||
|
|
||
| BoolTest::mask pred = BoolTest::lt; | ||
| // Compute the blend mask for merging two indipendently permututed vectors | ||
jatin-bhateja marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // using shuff index in two vector index range [0, VLEN * 2). | ||
| BoolTest::mask pred = BoolTest::le; | ||
| ConINode* pred_node = (ConINode*)phase->makecon(TypeInt::make(pred)); | ||
|
||
| Node* lane_cnt = phase->makecon(lane_count_type); | ||
| Node* bcast_lane_cnt_vec = phase->transform(VectorNode::scalar2vector(lane_cnt, num_elem, Type::get_const_basic_type(integral_elem_bt), false)); | ||
| const TypeVect* vmask_type = TypeVect::makemask(T_BYTE, num_elem); | ||
| Node* mask = phase->transform(new VectorMaskCmpNode(pred, index_byte_vec, bcast_lane_cnt_m1_vec, pred_node, vmask_type)); | ||
|
|
||
| // Rearrange expects the indexes to lie within single vector index range [0, VLEN). | ||
| index_byte_vec = phase->transform(VectorNode::make(Op_AndV, index_byte_vec, bcast_lane_cnt_m1_vec, index_byte_vec->bottom_type()->is_vect())); | ||
|
|
||
| // Comparison over integral vectors weeds out emitting additional | ||
| // instructions for checking special floating point values. | ||
| const TypeVect* vmask_type = TypeVect::makemask(integral_elem_bt, num_elem); | ||
| Node* mask = phase->transform(new VectorMaskCmpNode(pred, integral_index_vec, bcast_lane_cnt_vec, pred_node, vmask_type)); | ||
| // Load indexes from byte vector and appropriatly massage them to target specific | ||
| // permutation index format. | ||
jatin-bhateja marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| index_vec = phase->transform(new VectorLoadShuffleNode(index_byte_vec, index_vect_type)); | ||
|
|
||
| vmask_type = TypeVect::makemask(elem_bt, num_elem); | ||
| mask = phase->transform(new VectorMaskCastNode(mask, vmask_type)); | ||
|
|
||
| Node* p1 = phase->transform(new VectorRearrangeNode(src1, integral_index_vec)); | ||
| Node* normalized_index_vec = phase->transform(VectorNode::make(sopc, integral_index_vec, bcast_lane_cnt_vec, vect_type())); | ||
| Node* p2 = phase->transform(new VectorRearrangeNode(src2, normalized_index_vec)); | ||
| Node* p1 = phase->transform(new VectorRearrangeNode(src1, index_vec)); | ||
| Node* p2 = phase->transform(new VectorRearrangeNode(src2, index_vec)); | ||
|
|
||
| return new VectorBlendNode(p2, p1, mask); | ||
| } | ||
|
|
||
| Node* VectorRearrangeNode::Ideal(PhaseGVN* phase, bool can_reshape) { | ||
| BasicType elem_bt = vect_type()->element_basic_type(); | ||
| int num_elem = vect_type()->length(); | ||
| if (in(2)->Opcode() != Op_VectorUnbox && | ||
| in(2)->Opcode() != Op_VectorLoadShuffle && | ||
| Matcher::match_rule_supported_vector(Op_VectorRearrange, num_elem, elem_bt) && | ||
| Matcher::vector_indexes_needs_pruning(elem_bt, num_elem)) { | ||
|
|
||
| BasicType integral_elem_bt = elem_bt; | ||
| if (elem_bt == T_FLOAT) { | ||
| integral_elem_bt = T_INT; | ||
| } else if (elem_bt == T_DOUBLE) { | ||
| integral_elem_bt = T_LONG; | ||
| } | ||
|
|
||
| // Targets emulating unsupported permutation for certain vector types | ||
| // may need to massage the indexes to match the users intent. | ||
| // 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(integral_elem_bt, num_elem); | ||
| Node* unpack_shuf = phase->transform(new VectorLoadShuffleNode(pack_shuf, newvt)); | ||
| return new VectorRearrangeNode(in(1), unpack_shuf); | ||
| } | ||
| return nullptr; | ||
| } | ||
|
|
||
| #ifndef PRODUCT | ||
| void VectorBoxAllocateNode::dump_spec(outputStream *st) const { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.