Skip to content
Closed
66 changes: 66 additions & 0 deletions src/hotspot/share/opto/vectornode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2237,6 +2237,72 @@ bool MulVLNode::has_uint_inputs() const {
has_vector_elements_fit_uint(in(2));
}

static Node* UMinMaxV_Ideal(Node* n, PhaseGVN* phase, bool can_reshape) {
int vopc = n->Opcode();
assert(vopc == Op_UMinV || vopc == Op_UMaxV, "Unexpected opcode");

Node* umin = nullptr;
Node* umax = nullptr;
int lopc = n->in(1)->Opcode();
int ropc = n->in(2)->Opcode();

if (lopc == Op_UMinV && ropc == Op_UMaxV) {
umin = n->in(1);
umax = n->in(2);
} else if (lopc == Op_UMaxV && ropc == Op_UMinV) {
umin = n->in(2);
umax = n->in(1);
} else {
return nullptr;
}

// UMin (UMin(a, b), UMax(a, b)) => UMin(a, b)
// UMin (UMax(a, b), UMin(b, a)) => UMin(a, b)
// UMax (UMin(a, b), UMax(a, b)) => UMax(a, b)
// UMax (UMax(a, b), UMin(b, a)) => UMax(a, b)
if (umin != nullptr && umax != nullptr) {
if ((umin->in(1) == umax->in(1) && umin->in(2) == umax->in(2)) ||
(umin->in(2) == umax->in(1) && umin->in(1) == umax->in(2))) {
if (vopc == Op_UMinV) {
return new UMinVNode(umax->in(1), umax->in(2), n->bottom_type()->is_vect());
} else {
return new UMaxVNode(umax->in(1), umax->in(2), n->bottom_type()->is_vect());
}
}
}

return nullptr;
}

Node* UMinVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
Node* progress = UMinMaxV_Ideal(this, phase, can_reshape);
if (progress != nullptr) return progress;

return VectorNode::Ideal(phase, can_reshape);
}

Node* UMinVNode::Identity(PhaseGVN* phase) {
// UMin (a, a) => a
if (in(1) == in(2)) {
return in(1);
}
return this;
}

Node* UMaxVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
Node* progress = UMinMaxV_Ideal(this, phase, can_reshape);
if (progress != nullptr) return progress;

return VectorNode::Ideal(phase, can_reshape);
}

Node* UMaxVNode::Identity(PhaseGVN* phase) {
// UMax (a, a) => a
if (in(1) == in(2)) {
return in(1);
}
return this;
}
#ifndef PRODUCT
void VectorBoxAllocateNode::dump_spec(outputStream *st) const {
CallStaticJavaNode::dump_spec(st);
Expand Down
5 changes: 5 additions & 0 deletions src/hotspot/share/opto/vectornode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,12 @@ class UMinVNode : public VectorNode {
UMinVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2 ,vt) {
assert(is_integral_type(vt->element_basic_type()), "");
}
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
virtual Node* Identity(PhaseGVN* phase);
virtual int Opcode() const;
};


//------------------------------MaxVNode--------------------------------------
// Vector Max
class MaxVNode : public VectorNode {
Expand All @@ -691,6 +694,8 @@ class UMaxVNode : public VectorNode {
UMaxVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {
assert(is_integral_type(vt->element_basic_type()), "");
}
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
virtual Node* Identity(PhaseGVN* phase);
virtual int Opcode() const;
};

Expand Down
40 changes: 40 additions & 0 deletions test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,46 @@ public class IRNode {
vectorNode(MUL_ADD_VS2VI, "MulAddVS2VI", TYPE_INT);
}

public static final String UMIN_VB = VECTOR_PREFIX + "UMIN_VB" + POSTFIX;
static {
vectorNode(UMIN_VB, "UMinV", TYPE_BYTE);
}

public static final String UMIN_VS = VECTOR_PREFIX + "UMIN_VS" + POSTFIX;
static {
vectorNode(UMIN_VS, "UMinV", TYPE_SHORT);
}

public static final String UMIN_VI = VECTOR_PREFIX + "UMIN_VI" + POSTFIX;
static {
vectorNode(UMIN_VI, "UMinV", TYPE_INT);
}

public static final String UMIN_VL = VECTOR_PREFIX + "UMIN_VL" + POSTFIX;
static {
vectorNode(UMIN_VL, "UMinV", TYPE_LONG);
}

public static final String UMAX_VB = VECTOR_PREFIX + "UMAX_VB" + POSTFIX;
static {
vectorNode(UMAX_VB, "UMaxV", TYPE_BYTE);
}

public static final String UMAX_VS = VECTOR_PREFIX + "UMAX_VS" + POSTFIX;
static {
vectorNode(UMAX_VS, "UMaxV", TYPE_SHORT);
}

public static final String UMAX_VI = VECTOR_PREFIX + "UMAX_VI" + POSTFIX;
static {
vectorNode(UMAX_VI, "UMaxV", TYPE_INT);
}

public static final String UMAX_VL = VECTOR_PREFIX + "UMAX_VL" + POSTFIX;
static {
vectorNode(UMAX_VL, "UMaxV", TYPE_LONG);
}

// Can only be used if avx512_vnni is available.
public static final String MUL_ADD_VS2VI_VNNI = PREFIX + "MUL_ADD_VS2VI_VNNI" + POSTFIX;
static {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,4 +573,54 @@ public void checkVectorIRSharing19() {
Verify.checkEQ(ir1[i], (mask ? ia[i] + ib[i] : ia[i]) + (mask ? ib[i] + ia[i] : ib[i]));
}
}

@Test
@IR(counts = {IRNode.UMAX_VI, IRNode.VECTOR_SIZE_ANY, " 1 "}, applyIfCPUFeatureOr = {"avx", "true"})
public void testVectorIRSharing20(int index) {
IntVector vec1 = IntVector.fromArray(I_SPECIES, ia, index);
IntVector vec2 = IntVector.fromArray(I_SPECIES, ib, index);
// UMax ((UMax vec1, vec2), (UMax vec2, vec1))
vec1.lanewise(VectorOperators.UMAX, vec2)
.lanewise(VectorOperators.UMAX, vec2.lanewise(VectorOperators.UMAX, vec1))
.intoArray(ir1, index);
}

@Run(test = "testVectorIRSharing20")
public void testVectorIRSharingDriver20() {
for (int i = 0; i < I_SPECIES.loopBound(LENGTH); i += I_SPECIES.length()) {
testVectorIRSharing20(i);
}
checkVectorIRSharing20();
}

public void checkVectorIRSharing20() {
for (int i = 0; i < I_SPECIES.loopBound(LENGTH); i++) {
Verify.checkEQ(ir1[i], VectorMath.maxUnsigned(ia[i], ib[i]));
}
}

@Test
@IR(counts = {IRNode.UMIN_VI, IRNode.VECTOR_SIZE_ANY, " 1 "}, applyIfCPUFeatureOr = {"avx", "true"})
public void testVectorIRSharing21(int index) {
IntVector vec1 = IntVector.fromArray(I_SPECIES, ia, index);
IntVector vec2 = IntVector.fromArray(I_SPECIES, ib, index);
// UMin ((UMin vec1, vec2), (UMin vec2, vec1))
vec1.lanewise(VectorOperators.UMIN, vec2)
.lanewise(VectorOperators.UMIN, vec2.lanewise(VectorOperators.UMIN, vec1))
.intoArray(ir1, index);
}

@Run(test = "testVectorIRSharing21")
public void testVectorIRSharingDriver21() {
for (int i = 0; i < I_SPECIES.loopBound(LENGTH); i += I_SPECIES.length()) {
testVectorIRSharing21(i);
}
checkVectorIRSharing21();
}

public void checkVectorIRSharing21() {
for (int i = 0; i < I_SPECIES.loopBound(LENGTH); i++) {
Verify.checkEQ(ir1[i], VectorMath.minUnsigned(ia[i], ib[i]));
}
}
}
Loading