Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 9 additions & 82 deletions src/hotspot/share/opto/addnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
#include "opto/movenode.hpp"
#include "opto/mulnode.hpp"
#include "opto/phaseX.hpp"
#include "opto/rangeinference.hpp"
#include "opto/subnode.hpp"
#include "opto/utilities/xor.hpp"
#include "runtime/stubRoutines.hpp"

// Portions of code courtesy of Clifford Click
Expand Down Expand Up @@ -838,35 +838,8 @@ Node* OrINode::Ideal(PhaseGVN* phase, bool can_reshape) {
// the logical operations the ring's ADD is really a logical OR function.
// This also type-checks the inputs for sanity. Guaranteed never to
// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
const Type *OrINode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeInt *r0 = t0->is_int(); // Handy access
const TypeInt *r1 = t1->is_int();

// If both args are bool, can figure out better types
if ( r0 == TypeInt::BOOL ) {
if ( r1 == TypeInt::ONE) {
return TypeInt::ONE;
} else if ( r1 == TypeInt::BOOL ) {
return TypeInt::BOOL;
}
} else if ( r0 == TypeInt::ONE ) {
if ( r1 == TypeInt::BOOL ) {
return TypeInt::ONE;
}
}

// If either input is all ones, the output is all ones.
// x | ~0 == ~0 <==> x | -1 == -1
if (r0 == TypeInt::MINUS_1 || r1 == TypeInt::MINUS_1) {
return TypeInt::MINUS_1;
}

// If either input is not a constant, just return all integers.
if( !r0->is_con() || !r1->is_con() )
return TypeInt::INT; // Any integer, but still no symbols.

// Otherwise just OR them bits.
return TypeInt::make( r0->get_con() | r1->get_con() );
const Type* OrINode::add_ring(const Type* t1, const Type* t2) const {
return RangeInference::infer_or(t1->is_int(), t2->is_int());
}

//=============================================================================
Expand Down Expand Up @@ -914,22 +887,8 @@ Node* OrLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
}

//------------------------------add_ring---------------------------------------
const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeLong *r0 = t0->is_long(); // Handy access
const TypeLong *r1 = t1->is_long();

// If either input is all ones, the output is all ones.
// x | ~0 == ~0 <==> x | -1 == -1
if (r0 == TypeLong::MINUS_1 || r1 == TypeLong::MINUS_1) {
return TypeLong::MINUS_1;
}

// If either input is not a constant, just return all integers.
if( !r0->is_con() || !r1->is_con() )
return TypeLong::LONG; // Any integer, but still no symbols.

// Otherwise just OR them bits.
return TypeLong::make( r0->get_con() | r1->get_con() );
const Type* OrLNode::add_ring(const Type* t1, const Type* t2) const {
return RangeInference::infer_or(t1->is_long(), t2->is_long());
}

//---------------------------Helper -------------------------------------------
Expand Down Expand Up @@ -1016,46 +975,14 @@ const Type* XorINode::Value(PhaseGVN* phase) const {
// the logical operations the ring's ADD is really a logical OR function.
// This also type-checks the inputs for sanity. Guaranteed never to
// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
const Type *XorINode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeInt *r0 = t0->is_int(); // Handy access
const TypeInt *r1 = t1->is_int();

if (r0->is_con() && r1->is_con()) {
// compute constant result
return TypeInt::make(r0->get_con() ^ r1->get_con());
}

// At least one of the arguments is not constant

if (r0->_lo >= 0 && r1->_lo >= 0) {
// Combine [r0->_lo, r0->_hi] ^ [r0->_lo, r1->_hi] -> [0, upper_bound]
jint upper_bound = xor_upper_bound_for_ranges<jint, juint>(r0->_hi, r1->_hi);
return TypeInt::make(0, upper_bound, MAX2(r0->_widen, r1->_widen));
}

return TypeInt::INT;
const Type* XorINode::add_ring(const Type* t1, const Type* t2) const {
return RangeInference::infer_xor(t1->is_int(), t2->is_int());
}

//=============================================================================
//------------------------------add_ring---------------------------------------
const Type *XorLNode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeLong *r0 = t0->is_long(); // Handy access
const TypeLong *r1 = t1->is_long();

if (r0->is_con() && r1->is_con()) {
// compute constant result
return TypeLong::make(r0->get_con() ^ r1->get_con());
}

// At least one of the arguments is not constant

if (r0->_lo >= 0 && r1->_lo >= 0) {
// Combine [r0->_lo, r0->_hi] ^ [r0->_lo, r1->_hi] -> [0, upper_bound]
julong upper_bound = xor_upper_bound_for_ranges<jlong, julong>(r0->_hi, r1->_hi);
return TypeLong::make(0, upper_bound, MAX2(r0->_widen, r1->_widen));
}

return TypeLong::LONG;
const Type* XorLNode::add_ring(const Type* t1, const Type* t2) const {
return RangeInference::infer_xor(t1->is_long(), t2->is_long());
}

Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
Expand Down
78 changes: 5 additions & 73 deletions src/hotspot/share/opto/mulnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "opto/memnode.hpp"
#include "opto/mulnode.hpp"
#include "opto/phaseX.hpp"
#include "opto/rangeinference.hpp"
#include "opto/subnode.hpp"
#include "utilities/powerOfTwo.hpp"

Expand Down Expand Up @@ -628,80 +629,14 @@ const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot) {
return TypeLong::LONG;
}

template<typename IntegerType>
static const IntegerType* and_value(const IntegerType* r0, const IntegerType* r1) {
typedef typename IntegerType::NativeType NativeType;
static_assert(std::is_signed<NativeType>::value, "Native type of IntegerType must be signed!");

int widen = MAX2(r0->_widen, r1->_widen);

// If both types are constants, we can calculate a constant result.
if (r0->is_con() && r1->is_con()) {
return IntegerType::make(r0->get_con() & r1->get_con());
}

// If both ranges are positive, the result will range from 0 up to the hi value of the smaller range. The minimum
// of the two constrains the upper bound because any higher value in the other range will see all zeroes, so it will be masked out.
if (r0->_lo >= 0 && r1->_lo >= 0) {
return IntegerType::make(0, MIN2(r0->_hi, r1->_hi), widen);
}

// If only one range is positive, the result will range from 0 up to that range's maximum value.
// For the operation 'x & C' where C is a positive constant, the result will be in the range [0..C]. With that observation,
// we can say that for any integer c such that 0 <= c <= C will also be in the range [0..C]. Therefore, 'x & [c..C]'
// where c >= 0 will be in the range [0..C].
if (r0->_lo >= 0) {
return IntegerType::make(0, r0->_hi, widen);
}

if (r1->_lo >= 0) {
return IntegerType::make(0, r1->_hi, widen);
}

// At this point, all positive ranges will have already been handled, so the only remaining cases will be negative ranges
// and constants.

assert(r0->_lo < 0 && r1->_lo < 0, "positive ranges should already be handled!");

// As two's complement means that both numbers will start with leading 1s, the lower bound of both ranges will contain
// the common leading 1s of both minimum values. In order to count them with count_leading_zeros, the bits are inverted.
NativeType sel_val = ~MIN2(r0->_lo, r1->_lo);

NativeType min;
if (sel_val == 0) {
// Since count_leading_zeros is undefined at 0, we short-circuit the condition where both ranges have a minimum of -1.
min = -1;
} else {
// To get the number of bits to shift, we count the leading 0-bits and then subtract one, as the sign bit is already set.
int shift_bits = count_leading_zeros(sel_val) - 1;
min = std::numeric_limits<NativeType>::min() >> shift_bits;
}

NativeType max;
if (r0->_hi < 0 && r1->_hi < 0) {
// If both ranges are negative, then the same optimization as both positive ranges will apply, and the smaller hi
// value will mask off any bits set by higher values.
max = MIN2(r0->_hi, r1->_hi);
} else {
// In the case of ranges that cross zero, negative values can cause the higher order bits to be set, so the maximum
// positive value can be as high as the larger hi value.
max = MAX2(r0->_hi, r1->_hi);
}

return IntegerType::make(min, max, widen);
}

//=============================================================================
//------------------------------mul_ring---------------------------------------
// Supplied function returns the product of the inputs IN THE CURRENT RING.
// For the logical operations the ring's MUL is really a logical AND function.
// This also type-checks the inputs for sanity. Guaranteed never to
// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
const Type *AndINode::mul_ring( const Type *t0, const Type *t1 ) const {
const TypeInt* r0 = t0->is_int();
const TypeInt* r1 = t1->is_int();

return and_value<TypeInt>(r0, r1);
const Type* AndINode::mul_ring(const Type* t1, const Type* t2) const {
return RangeInference::infer_and(t1->is_int(), t2->is_int());
}

static bool AndIL_is_zero_element_under_mask(const PhaseGVN* phase, const Node* expr, const Node* mask, BasicType bt);
Expand Down Expand Up @@ -830,11 +765,8 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
// For the logical operations the ring's MUL is really a logical AND function.
// This also type-checks the inputs for sanity. Guaranteed never to
// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
const Type *AndLNode::mul_ring( const Type *t0, const Type *t1 ) const {
const TypeLong* r0 = t0->is_long();
const TypeLong* r1 = t1->is_long();

return and_value<TypeLong>(r0, r1);
const Type* AndLNode::mul_ring(const Type* t1, const Type* t2) const {
return RangeInference::infer_and(t1->is_long(), t2->is_long());
}

const Type* AndLNode::Value(PhaseGVN* phase) const {
Expand Down
1 change: 0 additions & 1 deletion src/hotspot/share/opto/rangeinference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "opto/rangeinference.hpp"
#include "opto/type.hpp"
#include "utilities/intn_t.hpp"
#include "utilities/tuple.hpp"

// If the cardinality of a TypeInt is below this threshold, use min widen, see
// TypeIntPrototype<S, U>::normalize_widen
Expand Down
Loading