Skip to content

Commit

Permalink
8335713: Enhance vectorization analysis
Browse files Browse the repository at this point in the history
Reviewed-by: roland
Backport-of: 3c05ad2290936ec9abc3f271cb6bf89e18c3eea7
  • Loading branch information
martinuy authored and RealCLanger committed Oct 3, 2024
1 parent fdf897f commit cdd9e7e
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 10 deletions.
83 changes: 73 additions & 10 deletions src/hotspot/share/opto/superword.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4228,11 +4228,42 @@ bool SWPointer::scaled_iv_plus_offset(Node* n) {
}
} else if (opc == Op_SubI) {
if (offset_plus_k(n->in(2), true) && scaled_iv_plus_offset(n->in(1))) {
// (offset1 + invar1 + scale * iv) - (offset2) or
// (offset1 + scale * iv) - (offset2 + invar1)
// Subtraction handled via "negate" flag of "offset_plus_k".
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_6(n);)
return true;
}
if (offset_plus_k(n->in(1)) && scaled_iv_plus_offset(n->in(2))) {
_scale *= -1;
SWPointer tmp(this);
if (offset_plus_k(n->in(1)) && tmp.scaled_iv_plus_offset(n->in(2))) {
// (offset1 + invar1) - (offset2 + scale * iv) or
// (offset1) - (offset2 + invar1 + scale * iv)
// Subtraction handled explicitly below.
assert(_scale == 0, "shouldn't be set yet");
// _scale = -tmp._scale
if (!try_MulI_no_overflow(-1, tmp._scale, _scale)) {
return false; // mul overflow.
}
// _offset -= tmp._offset
if (!try_SubI_no_overflow(_offset, tmp._offset, _offset)) {
return false; // sub overflow.
}
// _invar -= tmp._invar
if (tmp._invar != nullptr) {
if (_invar != nullptr) {
return false;
}
_invar = tmp._invar;
_invar_scale = tmp._invar_scale;
_negate_invar = !tmp._negate_invar;
}

// SWPointer tmp does not have an integer part to be forwarded
// (tmp._has_int_index_after_convI2L is false) because n is a SubI, all
// nodes above must also be of integer type (ConvL2I is not handled
// to allow a long) and ConvI2L (the only node that can add an integer
// part) won't be present.

NOT_PRODUCT(_tracer.scaled_iv_plus_offset_7(n);)
return true;
}
Expand Down Expand Up @@ -4275,7 +4306,9 @@ bool SWPointer::scaled_iv(Node* n) {
}
} else if (opc == Op_LShiftI) {
if (n->in(1) == iv() && n->in(2)->is_Con()) {
_scale = 1 << n->in(2)->get_int();
if (!try_LShiftI_no_overflow(1, n->in(2)->get_int(), _scale)) {
return false; // shift overflow.
}
NOT_PRODUCT(_tracer.scaled_iv_6(n, _scale);)
return true;
}
Expand All @@ -4298,15 +4331,29 @@ bool SWPointer::scaled_iv(Node* n) {
if (tmp.scaled_iv_plus_offset(n->in(1)) && tmp.has_iv()) {
// We successfully matched an integer index, of the form:
// int_index = int_offset + int_invar + int_scale * iv
// Forward scale.
assert(_scale == 0 && tmp._scale != 0, "iv only found just now");
_scale = tmp._scale;
// Accumulate offset.
if (!try_AddI_no_overflow(_offset, tmp._offset, _offset)) {
return false; // add overflow.
}
// Forward invariant if not already found.
if (tmp._invar != nullptr) {
if (_invar != nullptr) {
return false;
}
_invar = tmp._invar;
_invar_scale = tmp._invar_scale;
_negate_invar = tmp._negate_invar;
}
// Set info about the int_index:
assert(!_has_int_index_after_convI2L, "no previous int_index discovered");
_has_int_index_after_convI2L = true;
_int_index_after_convI2L_offset = tmp._offset;
_int_index_after_convI2L_invar = tmp._invar;
_int_index_after_convI2L_scale = tmp._scale;
}

// Now parse it again for the real SWPointer. This makes sure that the int_offset, int_invar,
// and int_scale are properly added to the final SWPointer's offset, invar, and scale.
if (scaled_iv_plus_offset(n->in(1))) {
NOT_PRODUCT(_tracer.scaled_iv_7(n);)
return true;
}
Expand All @@ -4325,12 +4372,14 @@ bool SWPointer::scaled_iv(Node* n) {
NOT_PRODUCT(_tracer.scaled_iv_8(n, &tmp);)

if (tmp.scaled_iv_plus_offset(n->in(1))) {
int scale = n->in(2)->get_int();
int shift = n->in(2)->get_int();
// Accumulate scale.
_scale = tmp._scale << scale;
if (!try_LShiftI_no_overflow(tmp._scale, shift, _scale)) {
return false; // shift overflow.
}
// Accumulate offset.
int shifted_offset = 0;
if (!try_LShiftI_no_overflow(tmp._offset, scale, shifted_offset)) {
if (!try_LShiftI_no_overflow(tmp._offset, shift, shifted_offset)) {
return false; // shift overflow.
}
if (!try_AddI_no_overflow(_offset, shifted_offset, _offset)) {
Expand All @@ -4344,6 +4393,7 @@ bool SWPointer::scaled_iv(Node* n) {
}

// Forward info about the int_index:
assert(!_has_int_index_after_convI2L, "no previous int_index discovered");
_has_int_index_after_convI2L = tmp._has_int_index_after_convI2L;
_int_index_after_convI2L_offset = tmp._int_index_after_convI2L_offset;
_int_index_after_convI2L_invar = tmp._int_index_after_convI2L_invar;
Expand Down Expand Up @@ -4486,6 +4536,9 @@ bool SWPointer::try_AddSubI_no_overflow(int offset1, int offset2, bool is_sub, i
}

bool SWPointer::try_LShiftI_no_overflow(int offset, int shift, int& result) {
if (shift < 0 || shift > 31) {
return false;
}
jlong long_offset = java_shift_left((jlong)(offset), (julong)((jlong)(shift)));
jint int_offset = java_shift_left((jint)(offset), (juint)((jint)(shift)));
if (long_offset != int_offset) {
Expand All @@ -4495,6 +4548,16 @@ bool SWPointer::try_LShiftI_no_overflow(int offset, int shift, int& result) {
return true;
}

bool SWPointer::try_MulI_no_overflow(int offset1, int offset2, int& result) {
jlong long_offset = java_multiply((jlong)(offset1), (jlong)(offset2));
jint int_offset = java_multiply((jint)(offset1), (jint)(offset2));
if (long_offset != int_offset) {
return false;
}
result = int_offset;
return true;
}

//----------------------------print------------------------
void SWPointer::print() {
#ifndef PRODUCT
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/superword.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ class SWPointer {
static bool try_SubI_no_overflow(int offset1, int offset2, int& result);
static bool try_AddSubI_no_overflow(int offset1, int offset2, bool is_sub, int& result);
static bool try_LShiftI_no_overflow(int offset1, int offset2, int& result);
static bool try_MulI_no_overflow(int offset1, int offset2, int& result);

};

Expand Down

0 comments on commit cdd9e7e

Please sign in to comment.