aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authorkvn <none@none>2012-08-22 11:55:40 -0700
committerkvn <none@none>2012-08-22 11:55:40 -0700
commit06527d43dd2244c1d1edd440eb37c54e9819c2f2 (patch)
tree75060c4ffd655651a377d5e91c0230611891d228 /src/share/vm/opto
parent579738a34629f40328bca19d539c924a560cd970 (diff)
7192963: assert(_in[req-1] == this) failed: Must pass arg count to 'new'
Summary: Fixed Pack node generation. Not vectorize shift instructions if count is not the same for all shifts and if count is vector. Reviewed-by: twisti
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r--src/share/vm/opto/compile.cpp2
-rw-r--r--src/share/vm/opto/superword.cpp85
-rw-r--r--src/share/vm/opto/vectornode.cpp73
-rw-r--r--src/share/vm/opto/vectornode.hpp10
4 files changed, 96 insertions, 74 deletions
diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp
index 0836fc205..01e4b3462 100644
--- a/src/share/vm/opto/compile.cpp
+++ b/src/share/vm/opto/compile.cpp
@@ -2604,7 +2604,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
if (n->req()-1 > 2) {
// Replace many operand PackNodes with a binary tree for matching
PackNode* p = (PackNode*) n;
- Node* btp = p->binaryTreePack(Compile::current(), 1, n->req());
+ Node* btp = p->binary_tree_pack(Compile::current(), 1, n->req());
n->subsume_by(btp);
}
break;
diff --git a/src/share/vm/opto/superword.cpp b/src/share/vm/opto/superword.cpp
index 2efb15fbd..8d640c1e6 100644
--- a/src/share/vm/opto/superword.cpp
+++ b/src/share/vm/opto/superword.cpp
@@ -1055,18 +1055,30 @@ void SuperWord::filter_packs() {
// Can code be generated for pack p?
bool SuperWord::implemented(Node_List* p) {
Node* p0 = p->at(0);
- if (VectorNode::is_shift(p0) && in_bb(p0->in(2))) {
- return false; // vector shift count should be loop's invariant.
- }
return VectorNode::implemented(p0->Opcode(), p->size(), velt_basic_type(p0));
}
+//------------------------------same_inputs--------------------------
+// For pack p, are all idx operands the same?
+static bool same_inputs(Node_List* p, int idx) {
+ Node* p0 = p->at(0);
+ uint vlen = p->size();
+ Node* p0_def = p0->in(idx);
+ for (uint i = 1; i < vlen; i++) {
+ Node* pi = p->at(i);
+ Node* pi_def = pi->in(idx);
+ if (p0_def != pi_def)
+ return false;
+ }
+ return true;
+}
+
//------------------------------profitable---------------------------
// For pack p, are all operands and all uses (with in the block) vector?
bool SuperWord::profitable(Node_List* p) {
Node* p0 = p->at(0);
uint start, end;
- vector_opd_range(p0, &start, &end);
+ VectorNode::vector_operands(p0, &start, &end);
// Return false if some input is not vector and inside block
for (uint i = start; i < end; i++) {
@@ -1074,15 +1086,20 @@ bool SuperWord::profitable(Node_List* p) {
// For now, return false if not scalar promotion case (inputs are the same.)
// Later, implement PackNode and allow differing, non-vector inputs
// (maybe just the ones from outside the block.)
- Node* p0_def = p0->in(i);
- for (uint j = 1; j < p->size(); j++) {
- Node* use = p->at(j);
- Node* def = use->in(i);
- if (p0_def != def)
- return false;
+ if (!same_inputs(p, i)) {
+ return false;
}
}
}
+ if (VectorNode::is_shift(p0)) {
+ // For now, return false if shift count is vector because
+ // hw does not support it.
+ if (is_vector_use(p0, 2))
+ return false;
+ // For the same reason return false if different shift counts.
+ if (!same_inputs(p, 2))
+ return false;
+ }
if (!p0->is_Store()) {
// For now, return false if not all uses are vector.
// Later, implement ExtractNode and allow non-vector uses (maybe
@@ -1395,17 +1412,7 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
uint vlen = p->size();
Node* opd = p0->in(opd_idx);
- bool same_opd = true;
- for (uint i = 1; i < vlen; i++) {
- Node* pi = p->at(i);
- Node* in = pi->in(opd_idx);
- if (opd != in) {
- same_opd = false;
- break;
- }
- }
-
- if (same_opd) {
+ if (same_inputs(p, opd_idx)) {
if (opd->is_Vector() || opd->is_LoadVector()) {
assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector");
return opd; // input is matching vector
@@ -1468,7 +1475,7 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
Node* in = pi->in(opd_idx);
assert(my_pack(in) == NULL, "Should already have been unpacked");
assert(opd_bt == in->bottom_type()->basic_type(), "all same type");
- pk->add_opd(i, in);
+ pk->add_opd(in);
}
_phase->_igvn.register_new_node_with_optimizer(pk);
_phase->set_ctrl(pk, _phase->get_ctrl(opd));
@@ -1761,7 +1768,7 @@ void SuperWord::compute_vector_element_type() {
const Type* vt = velt_type(n);
if (vt->basic_type() == T_INT) {
uint start, end;
- vector_opd_range(n, &start, &end);
+ VectorNode::vector_operands(n, &start, &end);
const Type* vt = velt_type(n);
for (uint j = start; j < end; j++) {
@@ -1839,38 +1846,6 @@ bool SuperWord::same_velt_type(Node* n1, Node* n2) {
return vt1 == vt2;
}
-//-------------------------vector_opd_range-----------------------
-// (Start, end] half-open range defining which operands are vector
-void SuperWord::vector_opd_range(Node* n, uint* start, uint* end) {
- switch (n->Opcode()) {
- case Op_LoadB: case Op_LoadUB:
- case Op_LoadS: case Op_LoadUS:
- case Op_LoadI: case Op_LoadL:
- case Op_LoadF: case Op_LoadD:
- case Op_LoadP:
- *start = 0;
- *end = 0;
- return;
- case Op_StoreB: case Op_StoreC:
- case Op_StoreI: case Op_StoreL:
- case Op_StoreF: case Op_StoreD:
- case Op_StoreP:
- *start = MemNode::ValueIn;
- *end = *start + 1;
- return;
- case Op_LShiftI: case Op_LShiftL:
- *start = 1;
- *end = 2;
- return;
- case Op_CMoveI: case Op_CMoveL: case Op_CMoveF: case Op_CMoveD:
- *start = 2;
- *end = n->req();
- return;
- }
- *start = 1;
- *end = n->req(); // default is all operands
-}
-
//------------------------------in_packset---------------------------
// Are s1 and s2 in a pack pair and ordered as s1,s2?
bool SuperWord::in_packset(Node* s1, Node* s2) {
diff --git a/src/share/vm/opto/vectornode.cpp b/src/share/vm/opto/vectornode.cpp
index 8e5e03b9f..7c8e52199 100644
--- a/src/share/vm/opto/vectornode.cpp
+++ b/src/share/vm/opto/vectornode.cpp
@@ -31,7 +31,7 @@
// Return the vector operator for the specified scalar operation
// and vector length. Also used to check if the code generator
// supports the vector operation.
-int VectorNode::opcode(int sopc, uint vlen, BasicType bt) {
+int VectorNode::opcode(int sopc, BasicType bt) {
switch (sopc) {
case Op_AddI:
switch (bt) {
@@ -161,7 +161,7 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) {
if (is_java_primitive(bt) &&
(vlen > 1) && is_power_of_2(vlen) &&
Matcher::vector_size_supported(bt, vlen)) {
- int vopc = VectorNode::opcode(opc, vlen, bt);
+ int vopc = VectorNode::opcode(opc, bt);
return vopc > 0 && Matcher::has_match_rule(vopc);
}
return false;
@@ -195,10 +195,54 @@ bool VectorNode::is_invariant_vector(Node* n) {
return false;
}
+// [Start, end) half-open range defining which operands are vectors
+void VectorNode::vector_operands(Node* n, uint* start, uint* end) {
+ switch (n->Opcode()) {
+ case Op_LoadB: case Op_LoadUB:
+ case Op_LoadS: case Op_LoadUS:
+ case Op_LoadI: case Op_LoadL:
+ case Op_LoadF: case Op_LoadD:
+ case Op_LoadP: case Op_LoadN:
+ *start = 0;
+ *end = 0; // no vector operands
+ break;
+ case Op_StoreB: case Op_StoreC:
+ case Op_StoreI: case Op_StoreL:
+ case Op_StoreF: case Op_StoreD:
+ case Op_StoreP: case Op_StoreN:
+ *start = MemNode::ValueIn;
+ *end = MemNode::ValueIn + 1; // 1 vector operand
+ break;
+ case Op_LShiftI: case Op_LShiftL:
+ case Op_RShiftI: case Op_RShiftL:
+ case Op_URShiftI: case Op_URShiftL:
+ *start = 1;
+ *end = 2; // 1 vector operand
+ break;
+ case Op_AddI: case Op_AddL: case Op_AddF: case Op_AddD:
+ case Op_SubI: case Op_SubL: case Op_SubF: case Op_SubD:
+ case Op_MulI: case Op_MulL: case Op_MulF: case Op_MulD:
+ case Op_DivF: case Op_DivD:
+ case Op_AndI: case Op_AndL:
+ case Op_OrI: case Op_OrL:
+ case Op_XorI: case Op_XorL:
+ *start = 1;
+ *end = 3; // 2 vector operands
+ break;
+ case Op_CMoveI: case Op_CMoveL: case Op_CMoveF: case Op_CMoveD:
+ *start = 2;
+ *end = n->req();
+ break;
+ default:
+ *start = 1;
+ *end = n->req(); // default is all operands
+ }
+}
+
// Return the vector version of a scalar operation node.
VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) {
const TypeVect* vt = TypeVect::make(bt, vlen);
- int vopc = VectorNode::opcode(opc, vlen, bt);
+ int vopc = VectorNode::opcode(opc, bt);
switch (vopc) {
case Op_AddVB: return new (C, 3) AddVBNode(n1, n2, vt);
@@ -278,38 +322,39 @@ PackNode* PackNode::make(Compile* C, Node* s, uint vlen, BasicType bt) {
switch (bt) {
case T_BOOLEAN:
case T_BYTE:
- return new (C, vlen+1) PackBNode(s, vt);
+ return new (C, 2) PackBNode(s, vt);
case T_CHAR:
case T_SHORT:
- return new (C, vlen+1) PackSNode(s, vt);
+ return new (C, 2) PackSNode(s, vt);
case T_INT:
- return new (C, vlen+1) PackINode(s, vt);
+ return new (C, 2) PackINode(s, vt);
case T_LONG:
- return new (C, vlen+1) PackLNode(s, vt);
+ return new (C, 2) PackLNode(s, vt);
case T_FLOAT:
- return new (C, vlen+1) PackFNode(s, vt);
+ return new (C, 2) PackFNode(s, vt);
case T_DOUBLE:
- return new (C, vlen+1) PackDNode(s, vt);
+ return new (C, 2) PackDNode(s, vt);
}
ShouldNotReachHere();
return NULL;
}
// Create a binary tree form for Packs. [lo, hi) (half-open) range
-Node* PackNode::binaryTreePack(Compile* C, int lo, int hi) {
+PackNode* PackNode::binary_tree_pack(Compile* C, int lo, int hi) {
int ct = hi - lo;
assert(is_power_of_2(ct), "power of 2");
if (ct == 2) {
PackNode* pk = PackNode::make(C, in(lo), 2, vect_type()->element_basic_type());
- pk->add_opd(1, in(lo+1));
+ pk->add_opd(in(lo+1));
return pk;
} else {
int mid = lo + ct/2;
- Node* n1 = binaryTreePack(C, lo, mid);
- Node* n2 = binaryTreePack(C, mid, hi );
+ PackNode* n1 = binary_tree_pack(C, lo, mid);
+ PackNode* n2 = binary_tree_pack(C, mid, hi );
- BasicType bt = vect_type()->element_basic_type();
+ BasicType bt = n1->vect_type()->element_basic_type();
+ assert(bt == n2->vect_type()->element_basic_type(), "should be the same");
switch (bt) {
case T_BOOLEAN:
case T_BYTE:
diff --git a/src/share/vm/opto/vectornode.hpp b/src/share/vm/opto/vectornode.hpp
index 9b01e638c..02521bbe1 100644
--- a/src/share/vm/opto/vectornode.hpp
+++ b/src/share/vm/opto/vectornode.hpp
@@ -56,10 +56,12 @@ class VectorNode : public TypeNode {
static VectorNode* make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt);
- static int opcode(int opc, uint vlen, BasicType bt);
+ static int opcode(int opc, BasicType bt);
static bool implemented(int opc, uint vlen, BasicType bt);
static bool is_shift(Node* n);
static bool is_invariant_vector(Node* n);
+ // [Start, end) half-open range defining which operands are vectors
+ static void vector_operands(Node* n, uint* start, uint* end);
};
//===========================Vector=ALU=Operations====================================
@@ -440,12 +442,12 @@ class PackNode : public VectorNode {
PackNode(Node* in1, Node* n2, const TypeVect* vt) : VectorNode(in1, n2, vt) {}
virtual int Opcode() const;
- void add_opd(uint i, Node* n) {
- init_req(i+1, n);
+ void add_opd(Node* n) {
+ add_req(n);
}
// Create a binary tree form for Packs. [lo, hi) (half-open) range
- Node* binaryTreePack(Compile* C, int lo, int hi);
+ PackNode* binary_tree_pack(Compile* C, int lo, int hi);
static PackNode* make(Compile* C, Node* s, uint vlen, BasicType bt);
};