|
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