|
1 | 1 | //
|
2 |
| -// Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. |
| 2 | +// Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | // Copyright (c) 2020, 2024, Arm Limited. All rights reserved.
|
4 | 4 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
5 | 5 | //
|
@@ -254,6 +254,13 @@ source %{
|
254 | 254 | case Op_CompressBitsV:
|
255 | 255 | case Op_ExpandBitsV:
|
256 | 256 | return false;
|
| 257 | + case Op_SaturatingAddV: |
| 258 | + case Op_SaturatingSubV: |
| 259 | + // Only SVE2 supports the predicated saturating instructions. |
| 260 | + if (UseSVE < 2) { |
| 261 | + return false; |
| 262 | + } |
| 263 | + break; |
257 | 264 | // We use Op_LoadVectorMasked to implement the predicated Op_LoadVector.
|
258 | 265 | // Hence we turn to check whether Op_LoadVectorMasked is supported. The
|
259 | 266 | // same as vector store/gather/scatter.
|
@@ -1539,6 +1546,142 @@ instruct vand_notL_masked(vReg dst_src1, vReg src2, immL_M1 m1, pRegGov pg) %{
|
1539 | 1546 | ins_pipe(pipe_slow);
|
1540 | 1547 | %}
|
1541 | 1548 |
|
| 1549 | +// ------------------------- Vector saturating add ----------------------------- |
| 1550 | + |
| 1551 | +// Signed saturating add |
| 1552 | + |
| 1553 | +instruct vsqadd(vReg dst, vReg src1, vReg src2) %{ |
| 1554 | + predicate(!n->as_SaturatingVector()->is_unsigned()); |
| 1555 | + match(Set dst (SaturatingAddV src1 src2)); |
| 1556 | + format %{ "vsqadd $dst, $src1, $src2" %} |
| 1557 | + ins_encode %{ |
| 1558 | + uint length_in_bytes = Matcher::vector_length_in_bytes(this); |
| 1559 | + if (VM_Version::use_neon_for_vector(length_in_bytes)) { |
| 1560 | + __ sqaddv($dst$$FloatRegister, get_arrangement(this), |
| 1561 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1562 | + } else { |
| 1563 | + assert(UseSVE > 0, "must be sve"); |
| 1564 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1565 | + __ sve_sqadd($dst$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1566 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1567 | + } |
| 1568 | + %} |
| 1569 | + ins_pipe(pipe_slow); |
| 1570 | +%} |
| 1571 | + |
| 1572 | +instruct vsqadd_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ |
| 1573 | + predicate(UseSVE == 2 && !n->as_SaturatingVector()->is_unsigned()); |
| 1574 | + match(Set dst_src1 (SaturatingAddV (Binary dst_src1 src2) pg)); |
| 1575 | + format %{ "vsqadd_masked $dst_src1, $pg, $dst_src1, $src2" %} |
| 1576 | + ins_encode %{ |
| 1577 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1578 | + __ sve_sqadd($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1579 | + $pg$$PRegister, $src2$$FloatRegister); |
| 1580 | + %} |
| 1581 | + ins_pipe(pipe_slow); |
| 1582 | +%} |
| 1583 | + |
| 1584 | +// Unsigned saturating add |
| 1585 | + |
| 1586 | +instruct vuqadd(vReg dst, vReg src1, vReg src2) %{ |
| 1587 | + predicate(n->as_SaturatingVector()->is_unsigned()); |
| 1588 | + match(Set dst (SaturatingAddV src1 src2)); |
| 1589 | + format %{ "vuqadd $dst, $src1, $src2" %} |
| 1590 | + ins_encode %{ |
| 1591 | + uint length_in_bytes = Matcher::vector_length_in_bytes(this); |
| 1592 | + if (VM_Version::use_neon_for_vector(length_in_bytes)) { |
| 1593 | + __ uqaddv($dst$$FloatRegister, get_arrangement(this), |
| 1594 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1595 | + } else { |
| 1596 | + assert(UseSVE > 0, "must be sve"); |
| 1597 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1598 | + __ sve_uqadd($dst$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1599 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1600 | + } |
| 1601 | + %} |
| 1602 | + ins_pipe(pipe_slow); |
| 1603 | +%} |
| 1604 | + |
| 1605 | +instruct vuqadd_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ |
| 1606 | + predicate(UseSVE == 2 && n->as_SaturatingVector()->is_unsigned()); |
| 1607 | + match(Set dst_src1 (SaturatingAddV (Binary dst_src1 src2) pg)); |
| 1608 | + format %{ "vuqadd_masked $dst_src1, $pg, $dst_src1, $src2" %} |
| 1609 | + ins_encode %{ |
| 1610 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1611 | + __ sve_uqadd($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1612 | + $pg$$PRegister, $src2$$FloatRegister); |
| 1613 | + %} |
| 1614 | + ins_pipe(pipe_slow); |
| 1615 | +%} |
| 1616 | + |
| 1617 | +// ------------------------- Vector saturating sub ----------------------------- |
| 1618 | + |
| 1619 | +// Signed saturating sub |
| 1620 | + |
| 1621 | +instruct vsqsub(vReg dst, vReg src1, vReg src2) %{ |
| 1622 | + predicate(!n->as_SaturatingVector()->is_unsigned()); |
| 1623 | + match(Set dst (SaturatingSubV src1 src2)); |
| 1624 | + format %{ "vsqsub $dst, $src1, $src2" %} |
| 1625 | + ins_encode %{ |
| 1626 | + uint length_in_bytes = Matcher::vector_length_in_bytes(this); |
| 1627 | + if (VM_Version::use_neon_for_vector(length_in_bytes)) { |
| 1628 | + __ sqsubv($dst$$FloatRegister, get_arrangement(this), |
| 1629 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1630 | + } else { |
| 1631 | + assert(UseSVE > 0, "must be sve"); |
| 1632 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1633 | + __ sve_sqsub($dst$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1634 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1635 | + } |
| 1636 | + %} |
| 1637 | + ins_pipe(pipe_slow); |
| 1638 | +%} |
| 1639 | + |
| 1640 | +instruct vsqsub_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ |
| 1641 | + predicate(UseSVE == 2 && !n->as_SaturatingVector()->is_unsigned()); |
| 1642 | + match(Set dst_src1 (SaturatingSubV (Binary dst_src1 src2) pg)); |
| 1643 | + format %{ "vsqsub_masked $dst_src1, $pg, $dst_src1, $src2" %} |
| 1644 | + ins_encode %{ |
| 1645 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1646 | + __ sve_sqsub($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1647 | + $pg$$PRegister, $src2$$FloatRegister); |
| 1648 | + %} |
| 1649 | + ins_pipe(pipe_slow); |
| 1650 | +%} |
| 1651 | + |
| 1652 | +// Unsigned saturating sub |
| 1653 | + |
| 1654 | +instruct vuqsub(vReg dst, vReg src1, vReg src2) %{ |
| 1655 | + predicate(n->as_SaturatingVector()->is_unsigned()); |
| 1656 | + match(Set dst (SaturatingSubV src1 src2)); |
| 1657 | + format %{ "vuqsub $dst, $src1, $src2" %} |
| 1658 | + ins_encode %{ |
| 1659 | + uint length_in_bytes = Matcher::vector_length_in_bytes(this); |
| 1660 | + if (VM_Version::use_neon_for_vector(length_in_bytes)) { |
| 1661 | + __ uqsubv($dst$$FloatRegister, get_arrangement(this), |
| 1662 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1663 | + } else { |
| 1664 | + assert(UseSVE > 0, "must be sve"); |
| 1665 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1666 | + __ sve_uqsub($dst$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1667 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 1668 | + } |
| 1669 | + %} |
| 1670 | + ins_pipe(pipe_slow); |
| 1671 | +%} |
| 1672 | + |
| 1673 | +instruct vuqsub_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ |
| 1674 | + predicate(UseSVE == 2 && n->as_SaturatingVector()->is_unsigned()); |
| 1675 | + match(Set dst_src1 (SaturatingSubV (Binary dst_src1 src2) pg)); |
| 1676 | + format %{ "vuqsub_masked $dst_src1, $pg, $dst_src1, $src2" %} |
| 1677 | + ins_encode %{ |
| 1678 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 1679 | + __ sve_uqsub($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 1680 | + $pg$$PRegister, $src2$$FloatRegister); |
| 1681 | + %} |
| 1682 | + ins_pipe(pipe_slow); |
| 1683 | +%} |
| 1684 | + |
1542 | 1685 | // ------------------------------ Vector abs -----------------------------------
|
1543 | 1686 |
|
1544 | 1687 | // vector abs
|
@@ -1993,6 +2136,76 @@ instruct vmin_masked(vReg dst_src1, vReg src2, pRegGov pg) %{
|
1993 | 2136 | ins_pipe(pipe_slow);
|
1994 | 2137 | %}
|
1995 | 2138 |
|
| 2139 | +// vector unsigned min - LONG |
| 2140 | + |
| 2141 | +instruct vuminL_neon(vReg dst, vReg src1, vReg src2) %{ |
| 2142 | + predicate(UseSVE == 0 && Matcher::vector_element_basic_type(n) == T_LONG); |
| 2143 | + match(Set dst (UMinV src1 src2)); |
| 2144 | + effect(TEMP_DEF dst); |
| 2145 | + format %{ "vuminL_neon $dst, $src1, $src2\t# 2L" %} |
| 2146 | + ins_encode %{ |
| 2147 | + __ cm(Assembler::HI, $dst$$FloatRegister, __ T2D, $src1$$FloatRegister, $src2$$FloatRegister); |
| 2148 | + __ bsl($dst$$FloatRegister, __ T16B, $src2$$FloatRegister, $src1$$FloatRegister); |
| 2149 | + %} |
| 2150 | + ins_pipe(pipe_slow); |
| 2151 | +%} |
| 2152 | + |
| 2153 | +instruct vuminL_sve(vReg dst_src1, vReg src2) %{ |
| 2154 | + predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_LONG); |
| 2155 | + match(Set dst_src1 (UMinV dst_src1 src2)); |
| 2156 | + format %{ "vuminL_sve $dst_src1, $dst_src1, $src2" %} |
| 2157 | + ins_encode %{ |
| 2158 | + __ sve_umin($dst_src1$$FloatRegister, __ D, ptrue, $src2$$FloatRegister); |
| 2159 | + %} |
| 2160 | + ins_pipe(pipe_slow); |
| 2161 | +%} |
| 2162 | + |
| 2163 | +// vector unsigned min - B/S/I |
| 2164 | + |
| 2165 | +instruct vumin_neon(vReg dst, vReg src1, vReg src2) %{ |
| 2166 | + predicate(Matcher::vector_element_basic_type(n) != T_LONG && |
| 2167 | + VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n))); |
| 2168 | + match(Set dst (UMinV src1 src2)); |
| 2169 | + format %{ "vumin_neon $dst, $src1, $src2\t# B/S/I" %} |
| 2170 | + ins_encode %{ |
| 2171 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 2172 | + assert(is_integral_type(bt) && bt != T_LONG, "unsupported type"); |
| 2173 | + __ uminv($dst$$FloatRegister, get_arrangement(this), |
| 2174 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 2175 | + %} |
| 2176 | + ins_pipe(pipe_slow); |
| 2177 | +%} |
| 2178 | + |
| 2179 | +instruct vumin_sve(vReg dst_src1, vReg src2) %{ |
| 2180 | + predicate(Matcher::vector_element_basic_type(n) != T_LONG && |
| 2181 | + !VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n))); |
| 2182 | + match(Set dst_src1 (UMinV dst_src1 src2)); |
| 2183 | + format %{ "vumin_sve $dst_src1, $dst_src1, $src2\t# B/S/I" %} |
| 2184 | + ins_encode %{ |
| 2185 | + assert(UseSVE > 0, "must be sve"); |
| 2186 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 2187 | + assert(is_integral_type(bt) && bt != T_LONG, "unsupported type"); |
| 2188 | + __ sve_umin($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 2189 | + ptrue, $src2$$FloatRegister); |
| 2190 | + %} |
| 2191 | + ins_pipe(pipe_slow); |
| 2192 | +%} |
| 2193 | + |
| 2194 | +// vector unsigned min - predicated |
| 2195 | + |
| 2196 | +instruct vumin_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ |
| 2197 | + predicate(UseSVE > 0); |
| 2198 | + match(Set dst_src1 (UMinV (Binary dst_src1 src2) pg)); |
| 2199 | + format %{ "vumin_masked $dst_src1, $pg, $dst_src1, $src2" %} |
| 2200 | + ins_encode %{ |
| 2201 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 2202 | + assert(is_integral_type(bt), "unsupported type"); |
| 2203 | + __ sve_umin($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 2204 | + $pg$$PRegister, $src2$$FloatRegister); |
| 2205 | + %} |
| 2206 | + ins_pipe(pipe_slow); |
| 2207 | +%} |
| 2208 | + |
1996 | 2209 | // ------------------------------ Vector max -----------------------------------
|
1997 | 2210 |
|
1998 | 2211 | // vector max - LONG
|
@@ -2080,6 +2293,76 @@ instruct vmax_masked(vReg dst_src1, vReg src2, pRegGov pg) %{
|
2080 | 2293 | ins_pipe(pipe_slow);
|
2081 | 2294 | %}
|
2082 | 2295 |
|
| 2296 | +// vector unsigned max - LONG |
| 2297 | + |
| 2298 | +instruct vumaxL_neon(vReg dst, vReg src1, vReg src2) %{ |
| 2299 | + predicate(UseSVE == 0 && Matcher::vector_element_basic_type(n) == T_LONG); |
| 2300 | + match(Set dst (UMaxV src1 src2)); |
| 2301 | + effect(TEMP_DEF dst); |
| 2302 | + format %{ "vumaxL_neon $dst, $src1, $src2\t# 2L" %} |
| 2303 | + ins_encode %{ |
| 2304 | + __ cm(Assembler::HI, $dst$$FloatRegister, __ T2D, $src1$$FloatRegister, $src2$$FloatRegister); |
| 2305 | + __ bsl($dst$$FloatRegister, __ T16B, $src1$$FloatRegister, $src2$$FloatRegister); |
| 2306 | + %} |
| 2307 | + ins_pipe(pipe_slow); |
| 2308 | +%} |
| 2309 | + |
| 2310 | +instruct vumaxL_sve(vReg dst_src1, vReg src2) %{ |
| 2311 | + predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_LONG); |
| 2312 | + match(Set dst_src1 (UMaxV dst_src1 src2)); |
| 2313 | + format %{ "vumaxL_sve $dst_src1, $dst_src1, $src2" %} |
| 2314 | + ins_encode %{ |
| 2315 | + __ sve_umax($dst_src1$$FloatRegister, __ D, ptrue, $src2$$FloatRegister); |
| 2316 | + %} |
| 2317 | + ins_pipe(pipe_slow); |
| 2318 | +%} |
| 2319 | + |
| 2320 | +// vector unsigned max - B/S/I |
| 2321 | + |
| 2322 | +instruct vumax_neon(vReg dst, vReg src1, vReg src2) %{ |
| 2323 | + predicate(Matcher::vector_element_basic_type(n) != T_LONG && |
| 2324 | + VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n))); |
| 2325 | + match(Set dst (UMaxV src1 src2)); |
| 2326 | + format %{ "vumax_neon $dst, $src1, $src2\t# B/S/I" %} |
| 2327 | + ins_encode %{ |
| 2328 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 2329 | + assert(is_integral_type(bt) && bt != T_LONG, "unsupported type"); |
| 2330 | + __ umaxv($dst$$FloatRegister, get_arrangement(this), |
| 2331 | + $src1$$FloatRegister, $src2$$FloatRegister); |
| 2332 | + %} |
| 2333 | + ins_pipe(pipe_slow); |
| 2334 | +%} |
| 2335 | + |
| 2336 | +instruct vumax_sve(vReg dst_src1, vReg src2) %{ |
| 2337 | + predicate(Matcher::vector_element_basic_type(n) != T_LONG && |
| 2338 | + !VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n))); |
| 2339 | + match(Set dst_src1 (UMaxV dst_src1 src2)); |
| 2340 | + format %{ "vumax_sve $dst_src1, $dst_src1, $src2\t# B/S/I" %} |
| 2341 | + ins_encode %{ |
| 2342 | + assert(UseSVE > 0, "must be sve"); |
| 2343 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 2344 | + assert(is_integral_type(bt) && bt != T_LONG, "unsupported type"); |
| 2345 | + __ sve_umax($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 2346 | + ptrue, $src2$$FloatRegister); |
| 2347 | + %} |
| 2348 | + ins_pipe(pipe_slow); |
| 2349 | +%} |
| 2350 | + |
| 2351 | +// vector unsigned max - predicated |
| 2352 | + |
| 2353 | +instruct vumax_masked(vReg dst_src1, vReg src2, pRegGov pg) %{ |
| 2354 | + predicate(UseSVE > 0); |
| 2355 | + match(Set dst_src1 (UMaxV (Binary dst_src1 src2) pg)); |
| 2356 | + format %{ "vumax_masked $dst_src1, $pg, $dst_src1, $src2" %} |
| 2357 | + ins_encode %{ |
| 2358 | + BasicType bt = Matcher::vector_element_basic_type(this); |
| 2359 | + assert(is_integral_type(bt), "unsupported type"); |
| 2360 | + __ sve_umax($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt), |
| 2361 | + $pg$$PRegister, $src2$$FloatRegister); |
| 2362 | + %} |
| 2363 | + ins_pipe(pipe_slow); |
| 2364 | +%} |
| 2365 | + |
2083 | 2366 | // ------------------------------ MLA RELATED ----------------------------------
|
2084 | 2367 |
|
2085 | 2368 | // vector mla
|
|
0 commit comments