< prev index next >
src/hotspot/share/opto/addnode.cpp
Print this page
@@ -234,10 +234,44 @@
return NULL;
}
//=============================================================================
+
+static Node* convert_add_to_muladd(PhaseGVN *phase, Node* in1, Node* in2) {
+ // Only convert to this type of node if backend supports and if vectorizer supports it as well.
+ // The reason vectorizer is also checked is because this transformation is explicitly done
+ // to make vectorizer analysis easier for forms where type transition happens during operation.
+ if (Matcher::match_rule_supported(Op_MulAddS2I) &&
+ Matcher::match_rule_supported(Op_MulAddVS2VI)) {
+ if (in1->Opcode() == Op_MulI && in2->Opcode() == Op_MulI) {
+ 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))) {
+ return new MulAddS2INode(mul_in1, mul_in2, mul_in3, mul_in4);
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
//------------------------------Idealize---------------------------------------
Node *AddINode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* in1 = in(1);
Node* in2 = in(2);
int op1 = in1->Opcode();
@@ -318,10 +352,15 @@
return new URShiftINode( a, in1->in(2) );
}
}
}
+ Node* muladd = convert_add_to_muladd(phase, in1, in2);
+ if (muladd != NULL) {
+ return muladd;
+ }
+
return AddNode::Ideal(phase, can_reshape);
}
//------------------------------Identity---------------------------------------
< prev index next >