< prev index next >

src/hotspot/share/opto/loopopts.cpp

Print this page

        

@@ -491,10 +491,46 @@
   }
 
   return NULL;
 }
 
+Node *PhaseIdealLoop::convert_add_to_muladd(Node* n) {
+  Node * nn = NULL;
+  Node * in1 = n->in(1);
+  Node * in2 = n->in(2);
+  if (in1->Opcode() == Op_MulI && in2->Opcode() == Op_MulI) {
+    if (Matcher::match_rule_supported(Op_MulAddS2I) &&
+      Matcher::match_rule_supported(Op_MulAddVS2VI)) {
+      Node* mul_in1 = in1->in(1);
+      Node* mul_in2 = in1->in(2);
+      Node* mul_in3 = in2->in(1);
+      Node* mul_in4 = in2->in(2);
+
+      if (mul_in1->Opcode() == Op_LoadS &&
+        mul_in2->Opcode() == Op_LoadS &&
+        mul_in3->Opcode() == Op_LoadS &&
+        mul_in4->Opcode() == Op_LoadS) {
+        Node* adr1 = mul_in1->in(MemNode::Address);
+        Node* adr2 = mul_in2->in(MemNode::Address);
+        Node* adr3 = mul_in3->in(MemNode::Address);
+        Node* adr4 = mul_in4->in(MemNode::Address);
+
+        if (adr1->is_AddP() && adr2->is_AddP() && adr3->is_AddP() && adr4->is_AddP()) {
+          if ((adr1->in(AddPNode::Base) == adr3->in(AddPNode::Base)) &&
+            (adr2->in(AddPNode::Base) == adr4->in(AddPNode::Base))) {
+            nn = new MulAddS2INode(mul_in1, mul_in2, mul_in3, mul_in4);
+            register_new_node(nn, get_ctrl(n));
+            _igvn.replace_node(n, nn);
+            return nn;
+          }
+        }
+      }
+    }
+  }
+  return nn;
+}
+
 //------------------------------conditional_move-------------------------------
 // Attempt to replace a Phi with a conditional move.  We have some pretty
 // strict profitability requirements.  All Phis at the merge point must
 // be converted, so we can remove the control flow.  We need to limit the
 // number of c-moves to a small handful.  All code that was in the side-arms

@@ -920,10 +956,15 @@
 
   // Attempt to remix address expressions for loop invariants
   Node *m = remix_address_expressions( n );
   if( m ) return m;
 
+  if (n_op == Op_AddI) {
+    Node *nn = convert_add_to_muladd( n );
+    if ( nn ) return nn;
+  }
+
   if (n->is_ConstraintCast()) {
     Node* dom_cast = n->as_ConstraintCast()->dominating_cast(&_igvn, this);
     // ConstraintCastNode::dominating_cast() uses node control input to determine domination.
     // Node control inputs don't necessarily agree with loop control info (due to
     // transformations happened in between), thus additional dominance check is needed
< prev index next >