@@ -434,6 +434,16 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) {
434434 return false ;
435435}
436436
437+ bool VectorNode::is_maskall_type (const TypeLong* type, int vlen) {
438+ assert (type != nullptr , " type must not be null" );
439+ if (!type->is_con ()) {
440+ return false ;
441+ }
442+ long mask = (-1ULL >> (64 - vlen));
443+ long bit = type->get_con () & mask;
444+ return bit == 0 || bit == mask;
445+ }
446+
437447bool VectorNode::is_muladds2i (const Node* n) {
438448 return n->Opcode () == Op_MulAddS2I;
439449}
@@ -1503,6 +1513,45 @@ Node* ReductionNode::Ideal(PhaseGVN* phase, bool can_reshape) {
15031513 return nullptr ;
15041514}
15051515
1516+ // Convert fromLong to maskAll if the input sets or unsets all lanes.
1517+ Node* convertFromLongToMaskAll (PhaseGVN* phase, const TypeLong* bits_type, bool is_mask, const TypeVect* vt) {
1518+ uint vlen = vt->length ();
1519+ BasicType bt = vt->element_basic_type ();
1520+ // The "maskAll" API uses the corresponding integer types for floating-point data.
1521+ BasicType maskall_bt = (bt == T_FLOAT) ? T_INT : (bt == T_DOUBLE) ? T_LONG : bt;
1522+
1523+ if (VectorNode::is_maskall_type (bits_type, vlen) &&
1524+ Matcher::match_rule_supported_vector (Op_Replicate, vlen, maskall_bt)) {
1525+ Node* con = nullptr ;
1526+ jlong con_value = bits_type->get_con () == 0L ? 0L : -1L ;
1527+ if (maskall_bt == T_LONG) {
1528+ con = phase->longcon (con_value);
1529+ } else {
1530+ con = phase->intcon (con_value);
1531+ }
1532+ Node* res = VectorNode::scalar2vector (con, vlen, maskall_bt, is_mask);
1533+ // Convert back to the original floating-point data type.
1534+ if (is_floating_point_type (bt)) {
1535+ res = new VectorMaskCastNode (phase->transform (res), vt);
1536+ }
1537+ return res;
1538+ }
1539+ return nullptr ;
1540+ }
1541+
1542+ Node* VectorLoadMaskNode::Ideal (PhaseGVN* phase, bool can_reshape) {
1543+ // VectorLoadMask(VectorLongToMask(-1/0)) => Replicate(-1/0)
1544+ if (in (1 )->Opcode () == Op_VectorLongToMask) {
1545+ const TypeVect* vt = bottom_type ()->is_vect ();
1546+ Node* res = convertFromLongToMaskAll (phase, in (1 )->in (1 )->bottom_type ()->isa_long (), false , vt);
1547+ if (res != nullptr ) {
1548+ return res;
1549+ }
1550+ }
1551+
1552+ return VectorNode::Ideal (phase, can_reshape);
1553+ }
1554+
15061555Node* VectorLoadMaskNode::Identity (PhaseGVN* phase) {
15071556 BasicType out_bt = type ()->is_vect ()->element_basic_type ();
15081557 if (!Matcher::has_predicated_vectors () && out_bt == T_BOOLEAN) {
@@ -1918,6 +1967,45 @@ Node* VectorMaskOpNode::Ideal(PhaseGVN* phase, bool can_reshape) {
19181967 return nullptr ;
19191968}
19201969
1970+ Node* VectorMaskCastNode::Identity (PhaseGVN* phase) {
1971+ Node* in1 = in (1 );
1972+ // VectorMaskCast (VectorMaskCast x) => x
1973+ if (in1->Opcode () == Op_VectorMaskCast &&
1974+ vect_type ()->eq (in1->in (1 )->bottom_type ())) {
1975+ return in1->in (1 );
1976+ }
1977+ return this ;
1978+ }
1979+
1980+ // This function does the following optimization:
1981+ // VectorMaskToLong(MaskAll(l)) => (l & (-1ULL >> (64 - vlen)))
1982+ // VectorMaskToLong(VectorStoreMask(Replicate(l))) => (l & (-1ULL >> (64 - vlen)))
1983+ // l is -1 or 0.
1984+ Node* VectorMaskToLongNode::Ideal_MaskAll (PhaseGVN* phase) {
1985+ Node* in1 = in (1 );
1986+ // VectorMaskToLong follows a VectorStoreMask if predicate is not supported.
1987+ if (in1->Opcode () == Op_VectorStoreMask) {
1988+ assert (!in1->in (1 )->bottom_type ()->isa_vectmask (), " sanity" );
1989+ in1 = in1->in (1 );
1990+ }
1991+ if (VectorNode::is_all_ones_vector (in1)) {
1992+ int vlen = in1->bottom_type ()->is_vect ()->length ();
1993+ return new ConLNode (TypeLong::make (-1ULL >> (64 - vlen)));
1994+ }
1995+ if (VectorNode::is_all_zeros_vector (in1)) {
1996+ return new ConLNode (TypeLong::ZERO);
1997+ }
1998+ return nullptr ;
1999+ }
2000+
2001+ Node* VectorMaskToLongNode::Ideal (PhaseGVN* phase, bool can_reshape) {
2002+ Node* res = Ideal_MaskAll (phase);
2003+ if (res != nullptr ) {
2004+ return res;
2005+ }
2006+ return VectorMaskOpNode::Ideal (phase, can_reshape);
2007+ }
2008+
19212009Node* VectorMaskToLongNode::Identity (PhaseGVN* phase) {
19222010 if (in (1 )->Opcode () == Op_VectorLongToMask) {
19232011 return in (1 )->in (1 );
@@ -1927,28 +2015,41 @@ Node* VectorMaskToLongNode::Identity(PhaseGVN* phase) {
19272015
19282016Node* VectorLongToMaskNode::Ideal (PhaseGVN* phase, bool can_reshape) {
19292017 const TypeVect* dst_type = bottom_type ()->is_vect ();
2018+ uint vlen = dst_type->length ();
2019+ const TypeVectMask* is_mask = dst_type->isa_vectmask ();
2020+
19302021 if (in (1 )->Opcode () == Op_AndL &&
19312022 in (1 )->in (1 )->Opcode () == Op_VectorMaskToLong &&
19322023 in (1 )->in (2 )->bottom_type ()->isa_long () &&
19332024 in (1 )->in (2 )->bottom_type ()->is_long ()->is_con () &&
1934- in (1 )->in (2 )->bottom_type ()->is_long ()->get_con () == ((1L << dst_type-> length () ) - 1 )) {
2025+ in (1 )->in (2 )->bottom_type ()->is_long ()->get_con () == ((1L << vlen ) - 1 )) {
19352026 // Different src/dst mask length represents a re-interpretation operation,
19362027 // we can however generate a mask casting operation if length matches.
19372028 Node* src = in (1 )->in (1 )->in (1 );
1938- if (dst_type-> isa_vectmask () == nullptr ) {
2029+ if (is_mask == nullptr ) {
19392030 if (src->Opcode () != Op_VectorStoreMask) {
19402031 return nullptr ;
19412032 }
19422033 src = src->in (1 );
19432034 }
19442035 const TypeVect* src_type = src->bottom_type ()->is_vect ();
1945- if (src_type->length () == dst_type-> length () &&
1946- ((src_type->isa_vectmask () == nullptr && dst_type-> isa_vectmask () == nullptr ) ||
1947- (src_type->isa_vectmask () && dst_type-> isa_vectmask () ))) {
2036+ if (src_type->length () == vlen &&
2037+ ((src_type->isa_vectmask () == nullptr && is_mask == nullptr ) ||
2038+ (src_type->isa_vectmask () && is_mask ))) {
19482039 return new VectorMaskCastNode (src, dst_type);
19492040 }
19502041 }
1951- return nullptr ;
2042+
2043+ // VectorLongToMask(-1/0) => MaskAll(-1/0)
2044+ const TypeLong* bits_type = in (1 )->bottom_type ()->isa_long ();
2045+ if (bits_type && is_mask) {
2046+ Node* res = convertFromLongToMaskAll (phase, bits_type, true , dst_type);
2047+ if (res != nullptr ) {
2048+ return res;
2049+ }
2050+ }
2051+
2052+ return VectorNode::Ideal (phase, can_reshape);
19522053}
19532054
19542055Node* FmaVNode::Ideal (PhaseGVN* phase, bool can_reshape) {
0 commit comments