8216050: Superword optimization fails with assert(0 <= i && i < _len) failed: illegal index
authorvdeshpande
Tue, 15 Jan 2019 11:19:14 -0800
changeset 53336 36ca868f266f
parent 53335 585902b2bfcb
child 53337 464f2e1b0383
8216050: Superword optimization fails with assert(0 <= i && i < _len) failed: illegal index Summary: Fix for the crash by matching the operands by swapping to right positions. Reviewed-by: thartmann, kvn
src/hotspot/cpu/x86/x86.ad
src/hotspot/share/opto/loopopts.cpp
src/hotspot/share/opto/mulnode.cpp
src/hotspot/share/opto/mulnode.hpp
src/hotspot/share/opto/superword.cpp
--- a/src/hotspot/cpu/x86/x86.ad	Tue Jan 15 10:55:26 2019 -0800
+++ b/src/hotspot/cpu/x86/x86.ad	Tue Jan 15 11:19:14 2019 -0800
@@ -9936,6 +9936,7 @@
     __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
   %}
   ins_pipe( pipe_slow );
+  ins_cost(10);
 %}
 
 instruct vmuladdadd8S4I_reg(vecX dst, vecX src1, vecX src2) %{
@@ -9947,6 +9948,7 @@
     __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
   %}
   ins_pipe( pipe_slow );
+  ins_cost(10);
 %}
 
 instruct vmuladdadd16S8I_reg(vecY dst, vecY src1, vecY src2) %{
@@ -9958,6 +9960,7 @@
     __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
   %}
   ins_pipe( pipe_slow );
+  ins_cost(10);
 %}
 
 instruct vmuladdadd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{
@@ -9969,6 +9972,7 @@
     __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
   %}
   ins_pipe( pipe_slow );
+  ins_cost(10);
 %}
 
 // --------------------------------- PopCount --------------------------------------
--- a/src/hotspot/share/opto/loopopts.cpp	Tue Jan 15 10:55:26 2019 -0800
+++ b/src/hotspot/share/opto/loopopts.cpp	Tue Jan 15 11:19:14 2019 -0800
@@ -532,6 +532,12 @@
               register_new_node(nn, get_ctrl(n));
               _igvn.replace_node(n, nn);
               return nn;
+            } else if ((adr1->in(AddPNode::Base) == adr4->in(AddPNode::Base)) &&
+                       (adr2->in(AddPNode::Base) == adr3->in(AddPNode::Base))) {
+              nn = new MulAddS2INode(mul_in1, mul_in2, mul_in4, mul_in3);
+              register_new_node(nn, get_ctrl(n));
+              _igvn.replace_node(n, nn);
+              return nn;
             }
           }
         }
--- a/src/hotspot/share/opto/mulnode.cpp	Tue Jan 15 10:55:26 2019 -0800
+++ b/src/hotspot/share/opto/mulnode.cpp	Tue Jan 15 11:19:14 2019 -0800
@@ -1401,3 +1401,12 @@
   return TypeF::make(fma(f1, f2, f3));
 #endif
 }
+
+//=============================================================================
+//------------------------------hash-------------------------------------------
+// Hash function for MulAddS2INode.  Operation is commutative with commutative pairs.
+// The hash function must return the same value when edge swapping is performed.
+uint MulAddS2INode::hash() const {
+  return (uintptr_t)in(1) + (uintptr_t)in(2) + (uintptr_t)in(3) + (uintptr_t)in(4) + Opcode();
+}
+
--- a/src/hotspot/share/opto/mulnode.hpp	Tue Jan 15 10:55:26 2019 -0800
+++ b/src/hotspot/share/opto/mulnode.hpp	Tue Jan 15 11:19:14 2019 -0800
@@ -289,6 +289,7 @@
 // Multiply shorts into integers and add them.
 // Semantics: I_OUT = S1 * S2 + S3 * S4
 class MulAddS2INode : public Node {
+  virtual uint hash() const;
 public:
   MulAddS2INode(Node* in1, Node *in2, Node *in3, Node* in4) : Node(0, in1, in2, in3, in4) {}
   virtual int Opcode() const;
--- a/src/hotspot/share/opto/superword.cpp	Tue Jan 15 10:55:26 2019 -0800
+++ b/src/hotspot/share/opto/superword.cpp	Tue Jan 15 11:19:14 2019 -0800
@@ -1445,7 +1445,7 @@
     Node* t1 = s1->fast_out(i);
 
     // Only allow operand swap on commuting operations
-    if (!t1->is_Add() && !t1->is_Mul()) {
+    if (!t1->is_Add() && !t1->is_Mul() && !VectorNode::is_muladds2i(t1)) {
       break;
     }
 
@@ -1500,9 +1500,23 @@
       if ((i1 == (3-i2)) && (u2->is_Add() || u2->is_Mul())) {
         // Further analysis relies on operands position matching.
         u2->swap_edges(i1, i2);
+      } else if (VectorNode::is_muladds2i(u2) && u1 != u2) {
+        if (i1 == 5 - i2) { // ((i1 == 3 && i2 == 2) || (i1 == 2 && i2 == 3) || (i1 == 1 && i2 == 4) || (i1 == 4 && i2 == 1))
+          u2->swap_edges(1, 2);
+          u2->swap_edges(3, 4);
+        }
+        if (i1 == 3 - i2 || i1 == 7 - i2) { // ((i1 == 1 && i2 == 2) || (i1 == 2 && i2 == 1) || (i1 == 3 && i2 == 4) || (i1 == 4 && i2 == 3))
+          u2->swap_edges(2, 3);
+          u2->swap_edges(1, 4);
+        }
+        return false; // Just swap the edges, the muladds2i nodes get packed in follow_use_defs
       } else {
         return false;
       }
+    } else if (i1 == i2 && VectorNode::is_muladds2i(u2) && u1 != u2) {
+      u2->swap_edges(1, 3);
+      u2->swap_edges(2, 4);
+      return false; // Just swap the edges, the muladds2i nodes get packed in follow_use_defs
     }
   } while (i1 < ct);
   return true;