@@ -2687,11 +2687,12 @@ bool LibraryCallKit::inline_vector_insert() {
2687
2687
}
2688
2688
2689
2689
// public static
2690
- // <V extends Vector<E> ,
2690
+ // <VM extends VectorPayload ,
2691
2691
// E>
2692
- // long extract(Class<? extends V> vectorClass, Class<E> elementType, int vlen,
2693
- // V vec, int ix,
2694
- // VecExtractOp<V> defaultImpl)
2692
+ // long extract(Class<? extends VM> vClass, Class<E> eClass,
2693
+ // int length,
2694
+ // VM vm, int i,
2695
+ // VecExtractOp<VM> defaultImpl)
2695
2696
bool LibraryCallKit::inline_vector_extract () {
2696
2697
const TypeInstPtr* vector_klass = gvn ().type (argument (0 ))->isa_instptr ();
2697
2698
const TypeInstPtr* elem_klass = gvn ().type (argument (1 ))->isa_instptr ();
@@ -2701,13 +2702,12 @@ bool LibraryCallKit::inline_vector_extract() {
2701
2702
if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || idx == nullptr ) {
2702
2703
return false ; // dead code
2703
2704
}
2704
- if (vector_klass->const_oop () == nullptr || elem_klass->const_oop () == nullptr || !vlen->is_con () || !idx-> is_con () ) {
2705
+ if (vector_klass->const_oop () == nullptr || elem_klass->const_oop () == nullptr || !vlen->is_con ()) {
2705
2706
if (C->print_intrinsics ()) {
2706
- tty->print_cr (" ** missing constant: vclass=%s etype=%s vlen=%s idx=%s " ,
2707
+ tty->print_cr (" ** missing constant: vclass=%s etype=%s vlen=%s" ,
2707
2708
NodeClassNames[argument (0 )->Opcode ()],
2708
2709
NodeClassNames[argument (1 )->Opcode ()],
2709
- NodeClassNames[argument (2 )->Opcode ()],
2710
- NodeClassNames[argument (4 )->Opcode ()]);
2710
+ NodeClassNames[argument (2 )->Opcode ()]);
2711
2711
}
2712
2712
return false ; // not enough info for intrinsification
2713
2713
}
@@ -2726,51 +2726,93 @@ bool LibraryCallKit::inline_vector_extract() {
2726
2726
}
2727
2727
BasicType elem_bt = elem_type->basic_type ();
2728
2728
int num_elem = vlen->get_con ();
2729
- int vopc = ExtractNode::opcode (elem_bt);
2730
- if (!arch_supports_vector (vopc, num_elem, elem_bt, VecMaskNotUsed)) {
2731
- if (C->print_intrinsics ()) {
2732
- tty->print_cr (" ** not supported: arity=1 op=extract vlen=%d etype=%s ismask=no" ,
2733
- num_elem, type2name (elem_bt));
2734
- }
2735
- return false ; // not supported
2736
- }
2737
2729
2738
2730
ciKlass* vbox_klass = vector_klass->const_oop ()->as_instance ()->java_lang_Class_klass ();
2739
2731
const TypeInstPtr* vbox_type = TypeInstPtr::make_exact (TypePtr::NotNull, vbox_klass);
2740
2732
2741
- Node* opd = unbox_vector (argument (3 ), vbox_type, elem_bt, num_elem);
2742
- if (opd == nullptr ) {
2743
- return false ;
2744
- }
2733
+ Node* opd = nullptr ;
2745
2734
2746
- ConINode* idx_con = gvn (). intcon (idx-> get_con ())-> as_ConI ();
2747
- Node* operation = gvn (). transform ( ExtractNode::make (opd, idx_con, elem_bt));
2735
+ if ( is_vector_mask (vbox_klass)) {
2736
+ // vbox_klass is mask. This is used for VectorMask.laneIsSet(int).
2748
2737
2749
- Node* bits = nullptr ;
2750
- switch (elem_bt) {
2751
- case T_BYTE:
2752
- case T_SHORT:
2753
- case T_INT: {
2754
- bits = gvn ().transform (new ConvI2LNode (operation));
2755
- break ;
2738
+ Node* pos = argument (4 ); // can be variable
2739
+ if (arch_supports_vector (Op_ExtractUB, num_elem, elem_bt, VecMaskUseAll)) {
2740
+ // Transform mask to vector with type of boolean and utilize ExtractUB node.
2741
+ opd = unbox_vector (argument (3 ), vbox_type, elem_bt, num_elem);
2742
+ if (opd == nullptr ) {
2743
+ return false ;
2744
+ }
2745
+ opd = gvn ().transform (VectorStoreMaskNode::make (gvn (), opd, elem_bt, num_elem));
2746
+ opd = gvn ().transform (new ExtractUBNode (opd, pos));
2747
+ opd = gvn ().transform (new ConvI2LNode (opd));
2748
+ } else if (arch_supports_vector (Op_VectorMaskToLong, num_elem, elem_bt, VecMaskUseLoad)) {
2749
+ opd = unbox_vector (argument (3 ), vbox_type, elem_bt, num_elem);
2750
+ if (opd == nullptr ) {
2751
+ return false ;
2752
+ }
2753
+ // VectorMaskToLongNode requires the input is either a mask or a vector with BOOLEAN type.
2754
+ if (opd->bottom_type ()->isa_vectmask () == nullptr ) {
2755
+ opd = gvn ().transform (VectorStoreMaskNode::make (gvn (), opd, elem_bt, num_elem));
2756
+ }
2757
+ // ((toLong() >>> pos) & 1L
2758
+ opd = gvn ().transform (new VectorMaskToLongNode (opd, TypeLong::LONG));
2759
+ opd = gvn ().transform (new URShiftLNode (opd, pos));
2760
+ opd = gvn ().transform (new AndLNode (opd, gvn ().makecon (TypeLong::ONE)));
2761
+ } else {
2762
+ if (C->print_intrinsics ()) {
2763
+ tty->print_cr (" ** Rejected mask extraction because architecture does not support it" );
2764
+ }
2765
+ return false ; // not supported
2756
2766
}
2757
- case T_FLOAT: {
2758
- bits = gvn ().transform (new MoveF2INode (operation));
2759
- bits = gvn ().transform (new ConvI2LNode (bits));
2760
- break ;
2767
+ } else {
2768
+ // vbox_klass is vector. This is used for Vector.lane(int).
2769
+ if (!idx->is_con ()) {
2770
+ if (C->print_intrinsics ()) {
2771
+ tty->print_cr (" ** missing constant: idx=%s" , NodeClassNames[argument (4 )->Opcode ()]);
2772
+ }
2773
+ return false ; // not enough info for intrinsification
2761
2774
}
2762
- case T_DOUBLE: {
2763
- bits = gvn ().transform (new MoveD2LNode (operation));
2764
- break ;
2775
+
2776
+ int vopc = ExtractNode::opcode (elem_bt);
2777
+ if (!arch_supports_vector (vopc, num_elem, elem_bt, VecMaskNotUsed)) {
2778
+ if (C->print_intrinsics ()) {
2779
+ tty->print_cr (" ** not supported: arity=1 op=extract vlen=%d etype=%s ismask=no" ,
2780
+ num_elem, type2name (elem_bt));
2781
+ }
2782
+ return false ; // not supported
2765
2783
}
2766
- case T_LONG: {
2767
- bits = operation; // no conversion needed
2768
- break ;
2784
+
2785
+ opd = unbox_vector (argument (3 ), vbox_type, elem_bt, num_elem);
2786
+ if (opd == nullptr ) {
2787
+ return false ;
2769
2788
}
2770
- default : fatal (" %s" , type2name (elem_bt));
2771
- }
2789
+ ConINode* idx_con = gvn ().intcon (idx->get_con ())->as_ConI ();
2772
2790
2773
- set_result (bits);
2791
+ opd = gvn ().transform (ExtractNode::make (opd, idx_con, elem_bt));
2792
+ switch (elem_bt) {
2793
+ case T_BYTE:
2794
+ case T_SHORT:
2795
+ case T_INT: {
2796
+ opd = gvn ().transform (new ConvI2LNode (opd));
2797
+ break ;
2798
+ }
2799
+ case T_FLOAT: {
2800
+ opd = gvn ().transform (new MoveF2INode (opd));
2801
+ opd = gvn ().transform (new ConvI2LNode (opd));
2802
+ break ;
2803
+ }
2804
+ case T_DOUBLE: {
2805
+ opd = gvn ().transform (new MoveD2LNode (opd));
2806
+ break ;
2807
+ }
2808
+ case T_LONG: {
2809
+ // no conversion needed
2810
+ break ;
2811
+ }
2812
+ default : fatal (" %s" , type2name (elem_bt));
2813
+ }
2814
+ }
2815
+ set_result (opd);
2774
2816
return true ;
2775
2817
}
2776
2818
0 commit comments