-
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,68 +2087,63 @@ 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)) { | ||
jatin-bhateja marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return nullptr; | ||
| } | ||
| Node* index_vec = in(1); | ||
| Node* src1 = in(2); | ||
| Node* src2 = in(3); | ||
| 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 INDEX) | ||
| // (VectorRearrange SRC2 NORM_INDEX) | ||
| // MASK) | ||
| // | ||
| // MASK = INDEX < num_elem | ||
| // | ||
| // This shall prevent an 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. | ||
|
|
||
| auto lane_count_type = [&]() { | ||
| switch(elem_bt) { | ||
| case T_BYTE: | ||
| case T_SHORT: | ||
| case T_INT: | ||
| case T_FLOAT: | ||
| return static_cast<const Type*>(TypeInt::make(num_elem)); | ||
| case T_DOUBLE: | ||
| case T_LONG: | ||
| return static_cast<const Type*>(TypeLong::make(num_elem)); | ||
| default: | ||
| fatal("Unsupported vectortype (%s)", type2name(elem_bt)); | ||
| return static_cast<const Type*>(nullptr); | ||
| } | ||
| }; | ||
|
|
||
| auto make_integral_index_vec = [&](Node* index_vec) { | ||
| switch(elem_bt) { | ||
| case T_FLOAT: | ||
| return phase->transform(new VectorCastF2XNode(index_vec, TypeVect::make(T_INT, num_elem))); | ||
| 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; | ||
jatin-bhateja marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| case T_DOUBLE: | ||
| return phase->transform(new VectorCastD2XNode(index_vec, TypeVect::make(T_LONG, num_elem))); | ||
| default: | ||
| fatal("Unsupported vectortype (%s)", type2name(elem_bt)); | ||
| break; | ||
| default: | ||
| return index_vec; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| auto get_integal_type = [&](BasicType elem_bt) { | ||
| switch(elem_bt) { | ||
| case T_FLOAT: return T_INT; | ||
| case T_DOUBLE: return T_LONG; | ||
| default: return elem_bt; | ||
| } | ||
| }; | ||
| 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))); | ||
| } | ||
|
|
||
| BasicType integral_elem_bt = get_integal_type(elem_bt); | ||
| int opc = VectorSupport::vop2ideal(VectorSupport::VECTOR_OP_SUB, integral_elem_bt); | ||
| int sopc = VectorNode::opcode(opc, integral_elem_bt); | ||
|
|
||
| BoolTest::mask pred = BoolTest::lt; | ||
| ConINode* pred_node = (ConINode*)phase->makecon(TypeInt::make(pred)); | ||
|
||
| Node* lane_cnt = phase->makecon(lane_count_type()); | ||
| 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)); | ||
| Node* integral_index_vec = make_integral_index_vec(index_vec); | ||
|
|
||
| // Comparison over integral vectors weeds out emitting additional | ||
| // instructions for checking special floating point values. | ||
|
|
@@ -2171,21 +2166,22 @@ Node* VectorRearrangeNode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
| 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_massaging(elem_bt, num_elem)) { | ||
| auto get_integal_type = [&](BasicType elem_bt) { | ||
| switch(elem_bt) { | ||
| case T_FLOAT: return T_INT; | ||
| case T_DOUBLE: return T_LONG; | ||
| default: return 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 message the indexes to match the users intent. | ||
| // 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(get_integal_type(elem_bt), 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); | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.