|
42 | 42 |
|
43 | 43 | #include <math.h> |
44 | 44 |
|
45 | | -ModFloatingNode::ModFloatingNode(Compile* C, const TypeFunc* tf, const char* name) : CallLeafNode(tf, nullptr, name, TypeRawPtr::BOTTOM) { |
| 45 | +ModFloatingNode::ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name) : CallLeafPureNode(tf, addr, name, TypeRawPtr::BOTTOM) { |
46 | 46 | add_flag(Flag_is_macro); |
47 | 47 | C->add_macro_node(this); |
48 | 48 | } |
49 | 49 |
|
50 | | -ModDNode::ModDNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::Math_DD_D_Type(), "drem") { |
| 50 | +ModDNode::ModDNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::drem), "drem") { |
51 | 51 | init_req(TypeFunc::Parms + 0, a); |
52 | 52 | init_req(TypeFunc::Parms + 1, C->top()); |
53 | 53 | init_req(TypeFunc::Parms + 2, b); |
54 | 54 | init_req(TypeFunc::Parms + 3, C->top()); |
55 | 55 | } |
56 | 56 |
|
57 | | -ModFNode::ModFNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::modf_Type(), "frem") { |
| 57 | +ModFNode::ModFNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::modf_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::frem), "frem") { |
58 | 58 | init_req(TypeFunc::Parms + 0, a); |
59 | 59 | init_req(TypeFunc::Parms + 1, b); |
60 | 60 | } |
@@ -1511,137 +1511,109 @@ const Type* UModLNode::Value(PhaseGVN* phase) const { |
1511 | 1511 | return unsigned_mod_value<TypeLong, julong, jlong>(phase, this); |
1512 | 1512 | } |
1513 | 1513 |
|
1514 | | -Node* ModFNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
1515 | | - if (!can_reshape) { |
1516 | | - return nullptr; |
1517 | | - } |
1518 | | - PhaseIterGVN* igvn = phase->is_IterGVN(); |
1519 | | - |
1520 | | - bool result_is_unused = proj_out_or_null(TypeFunc::Parms) == nullptr; |
1521 | | - bool not_dead = proj_out_or_null(TypeFunc::Control) != nullptr; |
1522 | | - if (result_is_unused && not_dead) { |
1523 | | - return replace_with_con(igvn, TypeF::make(0.)); |
1524 | | - } |
1525 | | - |
1526 | | - // Either input is TOP ==> the result is TOP |
1527 | | - const Type* t1 = phase->type(dividend()); |
1528 | | - const Type* t2 = phase->type(divisor()); |
1529 | | - if (t1 == Type::TOP || t2 == Type::TOP) { |
1530 | | - return phase->C->top(); |
1531 | | - } |
1532 | | - |
| 1514 | +const Type* ModFNode::get_result_if_constant(const Type* dividend, const Type* divisor) const { |
1533 | 1515 | // If either number is not a constant, we know nothing. |
1534 | | - if ((t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon)) { |
| 1516 | + if ((dividend->base() != Type::FloatCon) || (divisor->base() != Type::FloatCon)) { |
1535 | 1517 | return nullptr; // note: x%x can be either NaN or 0 |
1536 | 1518 | } |
1537 | 1519 |
|
1538 | | - float f1 = t1->getf(); |
1539 | | - float f2 = t2->getf(); |
1540 | | - jint x1 = jint_cast(f1); // note: *(int*)&f1, not just (int)f1 |
1541 | | - jint x2 = jint_cast(f2); |
| 1520 | + float dividend_f = dividend->getf(); |
| 1521 | + float divisor_f = divisor->getf(); |
| 1522 | + jint dividend_i = jint_cast(dividend_f); // note: *(int*)&f1, not just (int)f1 |
| 1523 | + jint divisor_i = jint_cast(divisor_f); |
1542 | 1524 |
|
1543 | 1525 | // If either is a NaN, return an input NaN |
1544 | | - if (g_isnan(f1)) { |
1545 | | - return replace_with_con(igvn, t1); |
| 1526 | + if (g_isnan(dividend_f)) { |
| 1527 | + return dividend; |
1546 | 1528 | } |
1547 | | - if (g_isnan(f2)) { |
1548 | | - return replace_with_con(igvn, t2); |
| 1529 | + if (g_isnan(divisor_f)) { |
| 1530 | + return divisor; |
1549 | 1531 | } |
1550 | 1532 |
|
1551 | 1533 | // If an operand is infinity or the divisor is +/- zero, punt. |
1552 | | - if (!g_isfinite(f1) || !g_isfinite(f2) || x2 == 0 || x2 == min_jint) { |
| 1534 | + if (!g_isfinite(dividend_f) || !g_isfinite(divisor_f) || divisor_i == 0 || divisor_i == min_jint) { |
1553 | 1535 | return nullptr; |
1554 | 1536 | } |
1555 | 1537 |
|
1556 | 1538 | // We must be modulo'ing 2 float constants. |
1557 | 1539 | // Make sure that the sign of the fmod is equal to the sign of the dividend |
1558 | | - jint xr = jint_cast(fmod(f1, f2)); |
1559 | | - if ((x1 ^ xr) < 0) { |
| 1540 | + jint xr = jint_cast(fmod(dividend_f, divisor_f)); |
| 1541 | + if ((dividend_i ^ xr) < 0) { |
1560 | 1542 | xr ^= min_jint; |
1561 | 1543 | } |
1562 | 1544 |
|
1563 | | - return replace_with_con(igvn, TypeF::make(jfloat_cast(xr))); |
| 1545 | + return TypeF::make(jfloat_cast(xr)); |
1564 | 1546 | } |
1565 | 1547 |
|
1566 | | -Node* ModDNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
1567 | | - if (!can_reshape) { |
1568 | | - return nullptr; |
1569 | | - } |
1570 | | - PhaseIterGVN* igvn = phase->is_IterGVN(); |
1571 | | - |
1572 | | - bool result_is_unused = proj_out_or_null(TypeFunc::Parms) == nullptr; |
1573 | | - bool not_dead = proj_out_or_null(TypeFunc::Control) != nullptr; |
1574 | | - if (result_is_unused && not_dead) { |
1575 | | - return replace_with_con(igvn, TypeD::make(0.)); |
1576 | | - } |
1577 | | - |
1578 | | - // Either input is TOP ==> the result is TOP |
1579 | | - const Type* t1 = phase->type(dividend()); |
1580 | | - const Type* t2 = phase->type(divisor()); |
1581 | | - if (t1 == Type::TOP || t2 == Type::TOP) { |
1582 | | - return nullptr; |
1583 | | - } |
1584 | | - |
| 1548 | +const Type* ModDNode::get_result_if_constant(const Type* dividend, const Type* divisor) const { |
1585 | 1549 | // If either number is not a constant, we know nothing. |
1586 | | - if ((t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon)) { |
| 1550 | + if ((dividend->base() != Type::DoubleCon) || (divisor->base() != Type::DoubleCon)) { |
1587 | 1551 | return nullptr; // note: x%x can be either NaN or 0 |
1588 | 1552 | } |
1589 | 1553 |
|
1590 | | - double f1 = t1->getd(); |
1591 | | - double f2 = t2->getd(); |
1592 | | - jlong x1 = jlong_cast(f1); // note: *(long*)&f1, not just (long)f1 |
1593 | | - jlong x2 = jlong_cast(f2); |
| 1554 | + double dividend_d = dividend->getd(); |
| 1555 | + double divisor_d = divisor->getd(); |
| 1556 | + jlong dividend_l = jlong_cast(dividend_d); // note: *(long*)&f1, not just (long)f1 |
| 1557 | + jlong divisor_l = jlong_cast(divisor_d); |
1594 | 1558 |
|
1595 | 1559 | // If either is a NaN, return an input NaN |
1596 | | - if (g_isnan(f1)) { |
1597 | | - return replace_with_con(igvn, t1); |
| 1560 | + if (g_isnan(dividend_d)) { |
| 1561 | + return dividend; |
1598 | 1562 | } |
1599 | | - if (g_isnan(f2)) { |
1600 | | - return replace_with_con(igvn, t2); |
| 1563 | + if (g_isnan(divisor_d)) { |
| 1564 | + return divisor; |
1601 | 1565 | } |
1602 | 1566 |
|
1603 | 1567 | // If an operand is infinity or the divisor is +/- zero, punt. |
1604 | | - if (!g_isfinite(f1) || !g_isfinite(f2) || x2 == 0 || x2 == min_jlong) { |
| 1568 | + if (!g_isfinite(dividend_d) || !g_isfinite(divisor_d) || divisor_l == 0 || divisor_l == min_jlong) { |
1605 | 1569 | return nullptr; |
1606 | 1570 | } |
1607 | 1571 |
|
1608 | 1572 | // We must be modulo'ing 2 double constants. |
1609 | 1573 | // Make sure that the sign of the fmod is equal to the sign of the dividend |
1610 | | - jlong xr = jlong_cast(fmod(f1, f2)); |
1611 | | - if ((x1 ^ xr) < 0) { |
| 1574 | + jlong xr = jlong_cast(fmod(dividend_d, divisor_d)); |
| 1575 | + if ((dividend_l ^ xr) < 0) { |
1612 | 1576 | xr ^= min_jlong; |
1613 | 1577 | } |
1614 | 1578 |
|
1615 | | - return replace_with_con(igvn, TypeD::make(jdouble_cast(xr))); |
| 1579 | + return TypeD::make(jdouble_cast(xr)); |
1616 | 1580 | } |
1617 | 1581 |
|
1618 | | -Node* ModFloatingNode::replace_with_con(PhaseIterGVN* phase, const Type* con) { |
1619 | | - Compile* C = phase->C; |
1620 | | - Node* con_node = phase->makecon(con); |
1621 | | - CallProjections projs; |
1622 | | - extract_projections(&projs, false, false); |
1623 | | - phase->replace_node(projs.fallthrough_proj, in(TypeFunc::Control)); |
1624 | | - if (projs.fallthrough_catchproj != nullptr) { |
1625 | | - phase->replace_node(projs.fallthrough_catchproj, in(TypeFunc::Control)); |
1626 | | - } |
1627 | | - if (projs.fallthrough_memproj != nullptr) { |
1628 | | - phase->replace_node(projs.fallthrough_memproj, in(TypeFunc::Memory)); |
1629 | | - } |
1630 | | - if (projs.catchall_memproj != nullptr) { |
1631 | | - phase->replace_node(projs.catchall_memproj, C->top()); |
1632 | | - } |
1633 | | - if (projs.fallthrough_ioproj != nullptr) { |
1634 | | - phase->replace_node(projs.fallthrough_ioproj, in(TypeFunc::I_O)); |
1635 | | - } |
1636 | | - assert(projs.catchall_ioproj == nullptr, "no exceptions from floating mod"); |
1637 | | - assert(projs.catchall_catchproj == nullptr, "no exceptions from floating mod"); |
1638 | | - if (projs.resproj != nullptr) { |
1639 | | - phase->replace_node(projs.resproj, con_node); |
| 1582 | +Node* ModFloatingNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
| 1583 | + if (can_reshape) { |
| 1584 | + PhaseIterGVN* igvn = phase->is_IterGVN(); |
| 1585 | + |
| 1586 | + // Either input is TOP ==> the result is TOP |
| 1587 | + const Type* dividend_type = phase->type(dividend()); |
| 1588 | + const Type* divisor_type = phase->type(divisor()); |
| 1589 | + if (dividend_type == Type::TOP || divisor_type == Type::TOP) { |
| 1590 | + return phase->C->top(); |
| 1591 | + } |
| 1592 | + const Type* constant_result = get_result_if_constant(dividend_type, divisor_type); |
| 1593 | + if (constant_result != nullptr) { |
| 1594 | + return make_tuple_of_input_state_and_constant_result(igvn, constant_result); |
| 1595 | + } |
1640 | 1596 | } |
1641 | | - phase->replace_node(this, C->top()); |
1642 | | - C->remove_macro_node(this); |
1643 | | - disconnect_inputs(C); |
1644 | | - return nullptr; |
| 1597 | + |
| 1598 | + return CallLeafPureNode::Ideal(phase, can_reshape); |
| 1599 | +} |
| 1600 | + |
| 1601 | +/* Give a tuple node for ::Ideal to return, made of the input state (control to return addr) |
| 1602 | + * and the given constant result. Idealization of projections will make sure to transparently |
| 1603 | + * propagate the input state and replace the result by the said constant. |
| 1604 | + */ |
| 1605 | +TupleNode* ModFloatingNode::make_tuple_of_input_state_and_constant_result(PhaseIterGVN* phase, const Type* con) const { |
| 1606 | + Node* con_node = phase->makecon(con); |
| 1607 | + TupleNode* tuple = TupleNode::make( |
| 1608 | + tf()->range(), |
| 1609 | + in(TypeFunc::Control), |
| 1610 | + in(TypeFunc::I_O), |
| 1611 | + in(TypeFunc::Memory), |
| 1612 | + in(TypeFunc::FramePtr), |
| 1613 | + in(TypeFunc::ReturnAdr), |
| 1614 | + con_node); |
| 1615 | + |
| 1616 | + return tuple; |
1645 | 1617 | } |
1646 | 1618 |
|
1647 | 1619 | //============================================================================= |
|
0 commit comments