mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-03 22:55:40 +00:00
8379555: Test compiler/igvn/ExpressionFuzzer.java crashed with -Xcomp: Not monotonic
Reviewed-by: shade, kvn Backport-of: bab561b0c5079979cf1c364bc46dcadb3b28b4b5
This commit is contained in:
parent
f42ad10d17
commit
5912cccbf2
@ -22,14 +22,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opto/addnode.hpp"
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#include "opto/memnode.hpp"
|
||||
#include "opto/mulnode.hpp"
|
||||
#include "opto/opcodes.hpp"
|
||||
#include "opto/phaseX.hpp"
|
||||
#include "utilities/count_leading_zeros.hpp"
|
||||
#include "opto/rangeinference.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/population_count.hpp"
|
||||
|
||||
//=============================================================================
|
||||
// Do not match memory edge.
|
||||
@ -231,171 +230,68 @@ Node* ExpandBitsNode::Identity(PhaseGVN* phase) {
|
||||
return compress_expand_identity(phase, this);
|
||||
}
|
||||
|
||||
static const Type* bitshuffle_value(const TypeInteger* src_type, const TypeInteger* mask_type, int opc, BasicType bt) {
|
||||
|
||||
// Bit expansion is a reverse process of bit compression. It sequentially reads source bits
|
||||
// starting from LSB and places them at bit positions in result value where corresponding mask bits
|
||||
// are 1. Thus, bit expansion for non-negative mask value will always generate a +ve value, this is
|
||||
// because sign bit of result will never be set to 1 as corresponding mask bit is always 0.
|
||||
static const Type* expand_bits_value(const TypeInteger* mask_type, BasicType bt) {
|
||||
assert(bt == T_INT || bt == T_LONG, "unexpected BasicType %s", type2name(bt));
|
||||
jlong hi = bt == T_INT ? max_jint : max_jlong;
|
||||
jlong lo = bt == T_INT ? min_jint : min_jlong;
|
||||
assert(bt == T_INT || bt == T_LONG, "");
|
||||
|
||||
// Rule 1: Bit compression selects the source bits corresponding to true mask bits,
|
||||
// packs them and places them contiguously at destination bit positions
|
||||
// starting from least significant bit, remaining higher order bits are set
|
||||
// to zero.
|
||||
|
||||
// Rule 2: Bit expansion is a reverse process, which sequentially reads source bits
|
||||
// starting from LSB and places them at bit positions in result value where
|
||||
// corresponding mask bits are 1. Thus, bit expansion for non-negative mask
|
||||
// value will always generate a +ve value, this is because sign bit of result
|
||||
// will never be set to 1 as corresponding mask bit is always 0.
|
||||
|
||||
// Case A) Constant mask
|
||||
if (mask_type->is_con()) {
|
||||
// Case A) Constant mask
|
||||
jlong maskcon = mask_type->get_con_as_long(bt);
|
||||
if (opc == Op_CompressBits) {
|
||||
// Case A.1 bit compression:-
|
||||
// For an outlier mask value of -1 upper bound of the result equals
|
||||
// maximum integral value, for any other mask value its computed using
|
||||
// following formula
|
||||
// Result.Hi = 1 << popcount(mask_bits) - 1
|
||||
if (maskcon >= 0L) {
|
||||
// Case A.2.1 constant mask >= 0
|
||||
// Result.Hi = mask, optimistically assuming all source bits
|
||||
// read starting from least significant bit positions are 1.
|
||||
// Result.Lo = 0, because at least one bit in mask is zero.
|
||||
// e.g.
|
||||
// src = 0xXXXXXXXX (non-constant source)
|
||||
// mask = 0x7FFFFFFF (constant mask >= 0)
|
||||
// result.hi = 0x7FFFFFFF
|
||||
// result.lo = 0
|
||||
hi = maskcon;
|
||||
lo = 0L;
|
||||
} else {
|
||||
// Case A.2.2) mask < 0
|
||||
// For constant mask strictly less than zero, the maximum result value will be
|
||||
// the same as the mask value with its sign bit flipped, assuming all source bits
|
||||
// except the MSB bit are set(one).
|
||||
//
|
||||
// For mask values other than -1, lower bound of the result is estimated
|
||||
// as zero, by assuming at least one mask bit is zero and corresponding source
|
||||
// bit will be masked, hence result of bit compression will always be
|
||||
// non-negative value. For outlier mask value of -1, assume all source bits
|
||||
// apart from most significant bit were set to 0, thereby resulting in
|
||||
// a minimum integral value.
|
||||
// e.g.
|
||||
// src = 0xXXXXXXXX (non-constant source)
|
||||
// mask = 0xEFFFFFFF (constant mask)
|
||||
// result.hi = 0x7FFFFFFF
|
||||
// result.lo = 0
|
||||
if (maskcon != -1L) {
|
||||
int bitcount = population_count(static_cast<julong>(bt == T_INT ? maskcon & 0xFFFFFFFFL : maskcon));
|
||||
hi = right_n_bits<jlong>(bitcount);
|
||||
lo = 0L;
|
||||
} else {
|
||||
// preserve originally assigned hi (MAX_INT/LONG) and lo (MIN_INT/LONG) values
|
||||
// for unknown source bits.
|
||||
assert(hi == (bt == T_INT ? max_jint : max_jlong), "");
|
||||
assert(lo == (bt == T_INT ? min_jint : min_jlong), "");
|
||||
}
|
||||
} else {
|
||||
// Case A.2 bit expansion:-
|
||||
assert(opc == Op_ExpandBits, "");
|
||||
if (maskcon >= 0L) {
|
||||
// Case A.2.1 constant mask >= 0
|
||||
// Result.Hi = mask, optimistically assuming all source bits
|
||||
// read starting from least significant bit positions are 1.
|
||||
// Result.Lo = 0, because at least one bit in mask is zero.
|
||||
// e.g.
|
||||
// src = 0xXXXXXXXX (non-constant source)
|
||||
// mask = 0x7FFFFFFF (constant mask >= 0)
|
||||
// result.hi = 0x7FFFFFFF
|
||||
// result.lo = 0
|
||||
hi = maskcon;
|
||||
lo = 0L;
|
||||
} else {
|
||||
// Case A.2.2) mask < 0
|
||||
// For constant mask strictly less than zero, the maximum result value will be
|
||||
// the same as the mask value with its sign bit flipped, assuming all source bits
|
||||
// except the MSB bit are set(one).
|
||||
//
|
||||
// To compute minimum result value we assume all but last read source bit as zero,
|
||||
// this is because sign bit of result will always be set to 1 while other bit
|
||||
// corresponding to set mask bit should be zero.
|
||||
// e.g.
|
||||
// src = 0xXXXXXXXX (non-constant source)
|
||||
// mask = 0xEFFFFFFF (constant mask)
|
||||
// result.hi = 0xEFFFFFFF ^ 0x80000000 = 0x6FFFFFFF
|
||||
// result.lo = 0x80000000
|
||||
//
|
||||
hi = maskcon ^ lo;
|
||||
// lo still retains MIN_INT/LONG.
|
||||
assert(lo == (bt == T_INT ? min_jint : min_jlong), "");
|
||||
}
|
||||
// To compute minimum result value we assume all but last read source bit as zero,
|
||||
// this is because sign bit of result will always be set to 1 while other bit
|
||||
// corresponding to set mask bit should be zero.
|
||||
// e.g.
|
||||
// src = 0xXXXXXXXX (non-constant source)
|
||||
// mask = 0xEFFFFFFF (constant mask)
|
||||
// result.hi = 0xEFFFFFFF ^ 0x80000000 = 0x6FFFFFFF
|
||||
// result.lo = 0x80000000
|
||||
//
|
||||
hi = maskcon ^ lo;
|
||||
// lo still retains MIN_INT/LONG.
|
||||
assert(lo == (bt == T_INT ? min_jint : min_jlong), "");
|
||||
}
|
||||
}
|
||||
|
||||
// Case B) Non-constant mask.
|
||||
if (!mask_type->is_con()) {
|
||||
if ( opc == Op_CompressBits) {
|
||||
int result_bit_width;
|
||||
int mask_bit_width = bt == T_INT ? 32 : 64;
|
||||
if ((mask_type->lo_as_long() < 0L && mask_type->hi_as_long() >= -1L)) {
|
||||
// Case B.1 The mask value range includes -1, hence we may use all bits,
|
||||
// the result has the whole value range.
|
||||
result_bit_width = mask_bit_width;
|
||||
} else if (mask_type->hi_as_long() < -1L) {
|
||||
// Case B.2 Mask value range is strictly less than -1, this indicates presence of at least
|
||||
// one unset(zero) bit in mask value, thus as per Rule 1, bit compression will always
|
||||
// result in a non-negative value. This guarantees that MSB bit of result value will
|
||||
// always be set to zero.
|
||||
result_bit_width = mask_bit_width - 1;
|
||||
} else {
|
||||
assert(mask_type->lo_as_long() >= 0, "");
|
||||
// Case B.3 Mask value range only includes non-negative values. Since all integral
|
||||
// types honours an invariant that TypeInteger._lo <= TypeInteger._hi, thus computing
|
||||
// leading zero bits of upper bound of mask value will allow us to ascertain
|
||||
// optimistic upper bound of result i.e. all the bits other than leading zero bits
|
||||
// can be assumed holding 1 value.
|
||||
jlong clz = count_leading_zeros(mask_type->hi_as_long());
|
||||
// Here, result of clz is w.r.t to long argument, hence for integer argument
|
||||
// we explicitly subtract 32 from the result.
|
||||
clz = bt == T_INT ? clz - 32 : clz;
|
||||
result_bit_width = mask_bit_width - clz;
|
||||
}
|
||||
// If the number of bits required to for the mask value range is less than the
|
||||
// full bit width of the integral type, then the MSB bit is guaranteed to be zero,
|
||||
// thus the compression result will never be a -ve value and we can safely set the
|
||||
// lower bound of the bit compression to zero.
|
||||
lo = result_bit_width == mask_bit_width ? lo : 0L;
|
||||
|
||||
assert(hi == (bt == T_INT ? max_jint : max_jlong), "");
|
||||
assert(lo == (bt == T_INT ? min_jint : min_jlong) || lo == 0, "");
|
||||
|
||||
if (src_type->lo_as_long() >= 0) {
|
||||
// Lemma 1: For strictly non-negative src, the result of the compression will never be
|
||||
// greater than src.
|
||||
// Proof: Since src is a non-negative value, its most significant bit is always 0.
|
||||
// Thus even if the corresponding MSB of the mask is one, the result will be a +ve
|
||||
// value. There are three possible cases
|
||||
// a. All the mask bits corresponding to set source bits are unset(zero).
|
||||
// b. All the mask bits corresponding to set source bits are set(one)
|
||||
// c. Some mask bits corresponding to set source bits are set(one) while others are unset(zero)
|
||||
//
|
||||
// Case a. results into an allzero result, while Case b. gives us the upper bound which is equals source
|
||||
// value, while for Case c. the result will lie within [0, src]
|
||||
//
|
||||
hi = src_type->hi_as_long();
|
||||
lo = 0L;
|
||||
}
|
||||
|
||||
if (result_bit_width < mask_bit_width) {
|
||||
// Rule 3:
|
||||
// We can further constrain the upper bound of bit compression if the number of bits
|
||||
// which can be set(one) is less than the maximum number of bits of integral type.
|
||||
hi = MIN2(right_n_bits<jlong>(result_bit_width), hi);
|
||||
}
|
||||
} else {
|
||||
// Case B) Non-constant mask.
|
||||
jlong max_mask = mask_type->hi_as_long();
|
||||
jlong min_mask = mask_type->lo_as_long();
|
||||
// Since mask here a range and not a constant value, hence being
|
||||
// conservative in determining the value range of result.
|
||||
if (min_mask >= 0L) {
|
||||
// Lemma 2: Based on the integral type invariant ie. TypeInteger.lo <= TypeInteger.hi,
|
||||
// if the lower bound of non-constant mask is a non-negative value then result can never
|
||||
// be greater than the mask.
|
||||
// Proof: Since lower bound of the mask is a non-negative value, hence most significant
|
||||
// bit of its entire value must be unset(zero). If all the lower order 'n' source bits
|
||||
// where n corresponds to popcount of mask are set(ones) then upper bound of the result equals
|
||||
// mask. In order to compute the lower bound, we pssimistically assume all the lower order 'n'
|
||||
// source bits are unset(zero) there by resuling into a zero value.
|
||||
hi = max_mask;
|
||||
lo = 0;
|
||||
} else {
|
||||
assert(opc == Op_ExpandBits, "");
|
||||
jlong max_mask = mask_type->hi_as_long();
|
||||
jlong min_mask = mask_type->lo_as_long();
|
||||
// Since mask here a range and not a constant value, hence being
|
||||
// conservative in determining the value range of result.
|
||||
if (min_mask >= 0L) {
|
||||
// Lemma 2: Based on the integral type invariant ie. TypeInteger.lo <= TypeInteger.hi,
|
||||
// if the lower bound of non-constant mask is a non-negative value then result can never
|
||||
// be greater than the mask.
|
||||
// Proof: Since lower bound of the mask is a non-negative value, hence most significant
|
||||
// bit of its entire value must be unset(zero). If all the lower order 'n' source bits
|
||||
// where n corresponds to popcount of mask are set(ones) then upper bound of the result equals
|
||||
// mask. In order to compute the lower bound, we pssimistically assume all the lower order 'n'
|
||||
// source bits are unset(zero) there by resuling into a zero value.
|
||||
hi = max_mask;
|
||||
lo = 0;
|
||||
} else {
|
||||
// preserve the lo and hi bounds estimated till now.
|
||||
}
|
||||
// preserve the lo and hi bounds estimated till now.
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,25 +319,12 @@ const Type* CompressBitsNode::Value(PhaseGVN* phase) const {
|
||||
}
|
||||
|
||||
BasicType bt = bottom_type()->basic_type();
|
||||
const TypeInteger* src_type = t1->is_integer(bt);
|
||||
const TypeInteger* mask_type = t2->is_integer(bt);
|
||||
int w = bt == T_INT ? 32 : 64;
|
||||
|
||||
// Constant fold if both src and mask are constants.
|
||||
if (src_type->is_con() && mask_type->is_con()) {
|
||||
jlong src = src_type->get_con_as_long(bt);
|
||||
jlong mask = mask_type->get_con_as_long(bt);
|
||||
jlong res = compress_bits(src, mask, w);
|
||||
return bt == T_INT ? static_cast<const Type*>(TypeInt::make(res)) :
|
||||
static_cast<const Type*>(TypeLong::make(res));
|
||||
if (bt == T_INT) {
|
||||
return RangeInference::infer_compress_bits(t1->is_int(), t2->is_int());
|
||||
} else {
|
||||
assert(bt == T_LONG, "unexpected BasicType %s", type2name(bt));
|
||||
return RangeInference::infer_compress_bits(t1->is_long(), t2->is_long());
|
||||
}
|
||||
|
||||
// Result is zero if src is zero irrespective of mask value.
|
||||
if (src_type == TypeInteger::zero(bt)) {
|
||||
return TypeInteger::zero(bt);
|
||||
}
|
||||
|
||||
return bitshuffle_value(src_type, mask_type, Op_CompressBits, bt);
|
||||
}
|
||||
|
||||
jlong ExpandBitsNode::expand_bits(jlong src, jlong mask, int bit_count) {
|
||||
@ -482,5 +365,5 @@ const Type* ExpandBitsNode::Value(PhaseGVN* phase) const {
|
||||
return TypeInteger::zero(bt);
|
||||
}
|
||||
|
||||
return bitshuffle_value(src_type, mask_type, Op_ExpandBits, bt);
|
||||
return expand_bits_value(mask_type, bt);
|
||||
}
|
||||
|
||||
@ -222,12 +222,16 @@ public:
|
||||
return TypeIntHelper::int_type_union(this, &o);
|
||||
}
|
||||
|
||||
bool contains(U u) const {
|
||||
S s = S(u);
|
||||
return s >= _lo && s <= _hi && u >= _ulo && u <= _uhi && _bits.is_satisfied_by(u);
|
||||
}
|
||||
|
||||
// These allow TypeIntMirror to mimick the behaviors of TypeInt* and TypeLong*, so they can be
|
||||
// passed into RangeInference methods. These are only used in testing, so they are implemented in
|
||||
// the test file.
|
||||
static TypeIntMirror make(const TypeIntMirror& t, int widen);
|
||||
const TypeIntMirror* operator->() const;
|
||||
bool contains(U u) const;
|
||||
bool contains(const TypeIntMirror& o) const;
|
||||
bool operator==(const TypeIntMirror& o) const;
|
||||
|
||||
@ -365,20 +369,23 @@ private:
|
||||
return CT<CTP>::make(res, MAX2(t1->_widen, t2->_widen));
|
||||
}
|
||||
|
||||
template <class CTP>
|
||||
static TypeIntMirror<S<CTP>, U<CTP>> infer_and_impl(const TypeIntMirror<S<CTP>, U<CTP>>& st1, const TypeIntMirror<S<CTP>, U<CTP>>& st2) {
|
||||
S<CTP> lo = std::numeric_limits<S<CTP>>::min();
|
||||
S<CTP> hi = std::numeric_limits<S<CTP>>::max();
|
||||
U<CTP> ulo = std::numeric_limits<U<CTP>>::min();
|
||||
// The unsigned value of the result of 'and' is always not greater than both of its inputs
|
||||
// since there is no position at which the bit is 1 in the result and 0 in either input
|
||||
U<CTP> uhi = MIN2(st1._uhi, st2._uhi);
|
||||
U<CTP> zeros = st1._bits._zeros | st2._bits._zeros;
|
||||
U<CTP> ones = st1._bits._ones & st2._bits._ones;
|
||||
return TypeIntMirror<S<CTP>, U<CTP>>::make(TypeIntPrototype<S<CTP>, U<CTP>>{{lo, hi}, {ulo, uhi}, {zeros, ones}});
|
||||
}
|
||||
|
||||
public:
|
||||
template <class CTP>
|
||||
static CTP infer_and(CTP t1, CTP t2) {
|
||||
return infer_binary(t1, t2, [&](const TypeIntMirror<S<CTP>, U<CTP>>& st1, const TypeIntMirror<S<CTP>, U<CTP>>& st2) {
|
||||
S<CTP> lo = std::numeric_limits<S<CTP>>::min();
|
||||
S<CTP> hi = std::numeric_limits<S<CTP>>::max();
|
||||
U<CTP> ulo = std::numeric_limits<U<CTP>>::min();
|
||||
// The unsigned value of the result of 'and' is always not greater than both of its inputs
|
||||
// since there is no position at which the bit is 1 in the result and 0 in either input
|
||||
U<CTP> uhi = MIN2(st1._uhi, st2._uhi);
|
||||
U<CTP> zeros = st1._bits._zeros | st2._bits._zeros;
|
||||
U<CTP> ones = st1._bits._ones & st2._bits._ones;
|
||||
return TypeIntMirror<S<CTP>, U<CTP>>::make(TypeIntPrototype<S<CTP>, U<CTP>>{{lo, hi}, {ulo, uhi}, {zeros, ones}});
|
||||
});
|
||||
return infer_binary(t1, t2, infer_and_impl<CTP>);
|
||||
}
|
||||
|
||||
template <class CTP>
|
||||
@ -442,6 +449,104 @@ public:
|
||||
TypeIntPrototype<S<CTP>, U<CTP>> proto{{slo, shi}, {ulo, uhi}, known_bits};
|
||||
return CT<CTP>::make(proto, t1->_widen);
|
||||
}
|
||||
|
||||
// Bit compression selects the source bits corresponding to true mask bits, packs them and places
|
||||
// them contiguously at destination bit positions starting from least significant bit, remaining
|
||||
// higher order bits are set to zero.
|
||||
template <class CTP>
|
||||
static CTP infer_compress_bits(CTP t1, CTP t2) {
|
||||
return infer_binary(t1, t2, [](const TypeIntMirror<S<CTP>, U<CTP>>& st1, const TypeIntMirror<S<CTP>, U<CTP>>& st2) {
|
||||
S<CTP> lo = std::numeric_limits<S<CTP>>::min();
|
||||
const S<CTP> hi = std::numeric_limits<S<CTP>>::max();
|
||||
const U<CTP> ulo = U<CTP>(0);
|
||||
// Integer.compress(v, mask) == Integer.compress(v & mask, mask)
|
||||
// Integer.compress(v, mask) u<= v
|
||||
// So, Integer.compress(v, mask) u<= (v & mask)
|
||||
const U<CTP> uhi = infer_and_impl<CTP>(st1, st2)._uhi;
|
||||
// If the mask has at least 1 unset bit, then the result must have its highest bit unset, and
|
||||
// since the only value with no unset bit is the maximum unsigned value, if st2 does not
|
||||
// contain that value, the result must be non-negative
|
||||
if (!st2.contains(std::numeric_limits<U<CTP>>::max())) {
|
||||
lo = S<CTP>(0);
|
||||
}
|
||||
|
||||
U<CTP> zeros = U<CTP>(0);
|
||||
U<CTP> ones = U<CTP>(0);
|
||||
// Firstly, try to collect known bits by traversing from the lowest to the highest bits, we
|
||||
// can collect bits up to the first position at which the corresponding bit in the second
|
||||
// operand is unknown.
|
||||
// For example, consider Integer.compress(v, mask), with:
|
||||
// v = 0bxyztuv
|
||||
// mask = 0b*1*110
|
||||
// we can walk the lowest 3 bits of the operands, and determine that the result must be
|
||||
// 0b****tu
|
||||
{
|
||||
// The bit index in result that will be taken from the current bit in the first operand,
|
||||
// can only be known if we have not encountered any unknown bit in the second operand
|
||||
int res_bit_idx = 0;
|
||||
for (int op_bit_idx = 0; op_bit_idx < HotSpotNumerics::type_width<U<CTP>>(); op_bit_idx++) {
|
||||
// If the bit is 0 in the second operand, the corresponding bit value in the first
|
||||
// operand is irrelevant
|
||||
U<CTP> op_bit_mask = U<CTP>(1) << op_bit_idx;
|
||||
if ((st2._bits._zeros & op_bit_mask) != U<CTP>(0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// No further analysis is possible
|
||||
if ((st2._bits._ones & op_bit_mask) == U<CTP>(0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// The bit of the second operand at op_bit_idx must be 1
|
||||
U<CTP> res_bit_mask = U<CTP>(1) << res_bit_idx;
|
||||
if ((st1._bits._zeros & op_bit_mask) != U<CTP>(0)) {
|
||||
zeros |= res_bit_mask;
|
||||
} else if ((st1._bits._ones & op_bit_mask) != U<CTP>(0)) {
|
||||
ones |= res_bit_mask;
|
||||
}
|
||||
res_bit_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// Secondly, try to infer the number of leading zeros by traversing from the highest to the
|
||||
// lowest bits. Integer.compress(v, mask) == Integer.compress(v & mask, mask), so the number
|
||||
// of leading zeros in the result is not less than the number of leading zeros in (v & mask).
|
||||
// Furthermore, in the remaining bits, for each bit in the second operand that must be 0, an
|
||||
// addition leading zero in result is guaranteed.
|
||||
// For example, consider Integer.compress(v, mask), with:
|
||||
// v = 0b*01***
|
||||
// mask = 0b0x1*0*
|
||||
// v & mask = 0b001*0*
|
||||
// So the result must have at least 2 leading zeros. Furthermore, we can see that it is
|
||||
// irrelevant whether the bit x in mask is 0 or 1, because the bit in result corresponding to
|
||||
// x must be 0, and the result must have no higher set bit in either case. As a result, we
|
||||
// can assume mask = 0b001*0*. And since mask has at least 3 unset bits, the result must have
|
||||
// at least 3 leading zeros.
|
||||
{
|
||||
// The bit index in result that is determined to be 0
|
||||
int res_bit_idx = HotSpotNumerics::type_width<U<CTP>>() - 1;
|
||||
// Whether we have encountered a bit that is not known 0 in either the first or the second
|
||||
// operand
|
||||
bool leading_zeros = true;
|
||||
for (int op_bit_idx = HotSpotNumerics::type_width<U<CTP>>() - 1; op_bit_idx >= 0; op_bit_idx--) {
|
||||
U<CTP> op_bit_mask = U<CTP>(1) << op_bit_idx;
|
||||
if ((st2._bits._zeros & op_bit_mask) != U<CTP>(0)) {
|
||||
zeros |= (U<CTP>(1) << res_bit_idx);
|
||||
res_bit_idx--;
|
||||
} else if (leading_zeros) {
|
||||
if ((st1._bits._zeros & op_bit_mask) != U<CTP>(0)) {
|
||||
zeros |= (U<CTP>(1) << res_bit_idx);
|
||||
res_bit_idx--;
|
||||
} else {
|
||||
leading_zeros = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TypeIntMirror<S<CTP>, U<CTP>>::make(TypeIntPrototype<S<CTP>, U<CTP>>{{lo, hi}, {ulo, uhi}, {zeros, ones}});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_OPTO_RANGEINFERENCE_HPP
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#include "opto/rangeinference.hpp"
|
||||
#include "opto/type.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
@ -225,12 +226,6 @@ const TypeIntMirror<S, U>* TypeIntMirror<S, U>::operator->() const {
|
||||
return this;
|
||||
}
|
||||
|
||||
template <class S, class U>
|
||||
bool TypeIntMirror<S, U>::contains(U u) const {
|
||||
S s = S(u);
|
||||
return s >= _lo && s <= _hi && u >= _ulo && u <= _uhi && _bits.is_satisfied_by(u);
|
||||
}
|
||||
|
||||
template <class S, class U>
|
||||
bool TypeIntMirror<S, U>::contains(const TypeIntMirror& o) const {
|
||||
return TypeIntHelper::int_type_is_subset(*this, o);
|
||||
@ -745,9 +740,31 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class U>
|
||||
class OpCompressBits {
|
||||
public:
|
||||
U operator()(U v1, U v2) const {
|
||||
constexpr int W = HotSpotNumerics::type_width<U>();
|
||||
if constexpr (W == 64) {
|
||||
return CompressBitsNode::compress_bits(v1, v2, W);
|
||||
} else {
|
||||
return U(uint(CompressBitsNode::compress_bits(uint(v1), uint(v2), W)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class CTP>
|
||||
class InferCompressBits {
|
||||
public:
|
||||
CTP operator()(CTP t1, CTP t2) const {
|
||||
return RangeInference::infer_compress_bits(t1, t2);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(opto, range_inference) {
|
||||
test_binary<OpAnd, InferAnd>();
|
||||
test_binary<OpOr, InferOr>();
|
||||
test_binary<OpXor, InferXor>();
|
||||
test_binary<OpCompressBits, InferCompressBits>();
|
||||
test_lshift();
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package compiler.ccp;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8379555
|
||||
* @summary Test that CompressBitsNode::Value does not violate monotonicity
|
||||
* @run main/othervm -Xbatch -XX:CompileOnly=${test.main.class}::test* ${test.main.class}
|
||||
*/
|
||||
public class TestCompressBitsMonotonicity {
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
testInt(0);
|
||||
testLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
private static int testInt(int v) {
|
||||
v &= 0b1101;
|
||||
int mask = 0b1111;
|
||||
int sum = 0;
|
||||
for (int i = 1; i < 10; i *= 2) {
|
||||
mask = Integer.compress(v, mask);
|
||||
sum += mask;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static long testLong(long v) {
|
||||
v &= 0b1101;
|
||||
long mask = 0b1111;
|
||||
long sum = 0;
|
||||
for (int i = 1; i < 10; i *= 2) {
|
||||
mask = Long.compress(v, mask);
|
||||
sum += mask;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user