@@ -62,7 +62,7 @@ void VTransformGraph::optimize(VTransform& vtransform) {
6262 // 1. Memory phi uses are not modeled, so they appear to have no use here, but must be kept alive.
6363 // 2. Similarly, some stores may not have their memory uses modeled, but need to be kept alive.
6464 // 3. Outer node with strong inputs: is a use after the loop that we must keep alive.
65- !(vtn->isa_LoopPhi () != nullptr ||
65+ !(vtn->isa_PhiScalar () != nullptr ||
6666 vtn->is_load_or_store_in_loop () ||
6767 (vtn->isa_Outer () != nullptr && vtn->has_strong_in_edge ()))) {
6868 vtn->mark_dead ();
@@ -123,8 +123,10 @@ bool VTransformGraph::schedule() {
123123 // Skip dead nodes
124124 if (!use->is_alive ()) { continue ; }
125125
126- // Skip LoopPhi backedge.
127- if ((use->isa_LoopPhi () != nullptr || use->isa_CountedLoop () != nullptr ) && use->in_req (2 ) == vtn) { continue ; }
126+ // Skip backedges.
127+ if ((use->is_loop_head_phi () || use->isa_CountedLoop () != nullptr ) && use->in_req (2 ) == vtn) {
128+ continue ;
129+ }
128130
129131 if (post_visited.test (use->_idx )) { continue ; }
130132 if (pre_visited.test (use->_idx )) {
@@ -205,7 +207,7 @@ void VTransformGraph::mark_vtnodes_in_loop(VectorSet& in_loop) const {
205207 for (int i = 0 ; i < _schedule.length (); i++) {
206208 VTransformNode* vtn = _schedule.at (i);
207209 // Is vtn a loop-phi?
208- if (vtn->isa_LoopPhi () != nullptr ||
210+ if (vtn->is_loop_head_phi () ||
209211 vtn->is_load_or_store_in_loop ()) {
210212 is_not_before_loop.set (vtn->_idx );
211213 continue ;
@@ -232,8 +234,7 @@ void VTransformGraph::mark_vtnodes_in_loop(VectorSet& in_loop) const {
232234 for (uint i = 0 ; i < vtn->out_strong_edges (); i++) {
233235 VTransformNode* use = vtn->out_strong_edge (i);
234236 // Or is vtn a backedge or one of its transitive defs?
235- if (in_loop.test (use->_idx ) ||
236- use->isa_LoopPhi () != nullptr ) {
237+ if (in_loop.test (use->_idx ) || use->is_loop_head_phi ()) {
237238 in_loop.set (vtn->_idx );
238239 break ;
239240 }
@@ -957,27 +958,22 @@ VTransformApplyResult VTransformDataScalarNode::apply(VTransformApplyState& appl
957958 return VTransformApplyResult::make_scalar (_node);
958959}
959960
960- VTransformApplyResult VTransformLoopPhiNode ::apply (VTransformApplyState& apply_state) const {
961+ VTransformApplyResult VTransformPhiScalarNode ::apply (VTransformApplyState& apply_state) const {
961962 PhaseIdealLoop* phase = apply_state.phase ();
962963 Node* in0 = apply_state.transformed_node (in_req (0 ));
963964 Node* in1 = apply_state.transformed_node (in_req (1 ));
964965 phase->igvn ().replace_input_of (_node, 0 , in0);
965966 phase->igvn ().replace_input_of (_node, 1 , in1);
966967 // Note: the backedge is hooked up later.
967968
968- // The Phi's inputs may have been modified, and the types changes,
969- // e.g. from scalar to vector.
970- const Type* t = in1->bottom_type ();
971- _node->as_Type ()->set_type (t);
972- phase->igvn ().set_type (_node, t);
973-
974969 return VTransformApplyResult::make_scalar (_node);
975970}
976971
977972// Cleanup backedges. In the schedule, the backedges come after their phis. Hence,
978973// we only have the transformed backedges after the phis are already transformed.
979974// We hook the backedges into the phis now, during cleanup.
980- void VTransformLoopPhiNode::apply_backedge (VTransformApplyState& apply_state) const {
975+ void VTransformPhiScalarNode::apply_backedge (VTransformApplyState& apply_state) const {
976+ assert (_node == apply_state.transformed_node (this ), " sanity" );
981977 PhaseIdealLoop* phase = apply_state.phase ();
982978 if (_node->is_memory_phi ()) {
983979 // Memory phi/backedge
@@ -1219,7 +1215,7 @@ bool VTransformReductionVectorNode::requires_strict_order() const {
12191215// are performed inside the loop.
12201216bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_out_of_loop_preconditions (VTransform& vtransform) {
12211217 // We have a phi with a single use.
1222- VTransformLoopPhiNode * phi = in_req (1 )->isa_LoopPhi ();
1218+ VTransformPhiScalarNode * phi = in_req (1 )->isa_PhiScalar ();
12231219 if (phi == nullptr ) {
12241220 return false ;
12251221 }
@@ -1284,7 +1280,7 @@ bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_ou
12841280 // All uses must be outside loop body, except for the phi.
12851281 for (uint i = 0 ; i < current_red->out_strong_edges (); i++) {
12861282 VTransformNode* use = current_red->out_strong_edge (i);
1287- if (use->isa_LoopPhi () == nullptr &&
1283+ if (use->isa_PhiScalar () == nullptr &&
12881284 use->isa_Outer () == nullptr ) {
12891285 // Should not be allowed by SuperWord::mark_reductions
12901286 assert (false , " reduction has use inside loop" );
@@ -1339,16 +1335,28 @@ bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_ou
13391335 VTransformNode* vtn_identity_vector = new (vtransform.arena ()) VTransformReplicateNode (vtransform, vlen, bt);
13401336 vtn_identity_vector->init_req (1 , vtn_identity);
13411337
1342- // Turn the scalar phi into a vector phi.
1343- VTransformLoopPhiNode* phi = in_req (1 )->isa_LoopPhi ();
1344- VTransformNode* init = phi->in_req (1 );
1345- phi->set_req (1 , vtn_identity_vector);
1338+ // Look at old scalar phi.
1339+ VTransformPhiScalarNode* phi_scalar = in_req (1 )->isa_PhiScalar ();
1340+ PhiNode* old_phi = phi_scalar->node ();
1341+ VTransformNode* init = phi_scalar->in_req (1 );
1342+
1343+ TRACE_OPTIMIZE (
1344+ tty->print (" phi_scalar " );
1345+ phi_scalar->print ();
1346+ )
1347+
1348+ // Create new vector phi
1349+ const VTransformVectorNodeProperties properties = VTransformVectorNodeProperties::make_for_phi_vector (old_phi, vlen, bt);
1350+ VTransformPhiVectorNode* phi_vector = new (vtransform.arena ()) VTransformPhiVectorNode (vtransform, 3 , properties);
1351+ phi_vector->init_req (0 , phi_scalar->in_req (0 ));
1352+ phi_vector->init_req (1 , vtn_identity_vector);
1353+ // Note: backedge comes later
13461354
13471355 // Traverse down the chain of reductions, and replace them with vector_accumulators.
13481356 VTransformReductionVectorNode* first_red = this ;
1349- VTransformReductionVectorNode* last_red = phi ->in_req (2 )->isa_ReductionVector ();
1357+ VTransformReductionVectorNode* last_red = phi_scalar ->in_req (2 )->isa_ReductionVector ();
13501358 VTransformReductionVectorNode* current_red = first_red;
1351- VTransformNode* current_vector_accumulator = phi ;
1359+ VTransformNode* current_vector_accumulator = phi_vector ;
13521360 while (true ) {
13531361 VTransformNode* vector_input = current_red->in_req (2 );
13541362 VTransformVectorNode* vector_accumulator = new (vtransform.arena ()) VTransformElementWiseVectorNode (vtransform, 3 , current_red->properties (), vopc);
@@ -1366,15 +1374,15 @@ bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_ou
13661374 }
13671375
13681376 // Feed vector accumulator into the backedge.
1369- phi ->set_req (2 , current_vector_accumulator);
1377+ phi_vector ->set_req (2 , current_vector_accumulator);
13701378
13711379 // Create post-loop reduction. last_red keeps all uses outside the loop.
13721380 last_red->set_req (1 , init);
13731381 last_red->set_req (2 , current_vector_accumulator);
13741382
13751383 TRACE_OPTIMIZE (
1376- tty->print (" phi " );
1377- phi ->print ();
1384+ tty->print (" phi_scalar " );
1385+ phi_scalar ->print ();
13781386 tty->print (" after loop " );
13791387 last_red->print ();
13801388 )
@@ -1398,6 +1406,37 @@ VTransformApplyResult VTransformReductionVectorNode::apply(VTransformApplyState&
13981406 return VTransformApplyResult::make_vector (vn, vn->vect_type ());
13991407}
14001408
1409+ VTransformApplyResult VTransformPhiVectorNode::apply (VTransformApplyState& apply_state) const {
1410+ PhaseIdealLoop* phase = apply_state.phase ();
1411+ Node* in0 = apply_state.transformed_node (in_req (0 ));
1412+ Node* in1 = apply_state.transformed_node (in_req (1 ));
1413+
1414+ // We create a new phi node, because the type is different to the scalar phi.
1415+ PhiNode* old_phi = approximate_origin ()->as_Phi ();
1416+ PhiNode* new_phi = old_phi->clone ()->as_Phi ();
1417+
1418+ phase->igvn ().replace_input_of (new_phi, 0 , in0);
1419+ phase->igvn ().replace_input_of (new_phi, 1 , in1);
1420+ // Note: the backedge is hooked up later.
1421+
1422+ // Give the new phi node the correct vector type.
1423+ const TypeVect* vt = TypeVect::make (element_basic_type (), vector_length ());
1424+ new_phi->as_Type ()->set_type (vt);
1425+ phase->igvn ().set_type (new_phi, vt);
1426+
1427+ return VTransformApplyResult::make_vector (new_phi, vt);
1428+ }
1429+
1430+ // Cleanup backedges. In the schedule, the backedges come after their phis. Hence,
1431+ // we only have the transformed backedges after the phis are already transformed.
1432+ // We hook the backedges into the phis now, during cleanup.
1433+ void VTransformPhiVectorNode::apply_backedge (VTransformApplyState& apply_state) const {
1434+ PhaseIdealLoop* phase = apply_state.phase ();
1435+ PhiNode* new_phi = apply_state.transformed_node (this )->as_Phi ();
1436+ Node* in2 = apply_state.transformed_node (in_req (2 ));
1437+ phase->igvn ().replace_input_of (new_phi, 2 , in2);
1438+ }
1439+
14011440float VTransformLoadVectorNode::cost (const VLoopAnalyzer& vloop_analyzer) const {
14021441 uint vlen = vector_length ();
14031442 BasicType bt = element_basic_type ();
@@ -1535,7 +1574,7 @@ void VTransformDataScalarNode::print_spec() const {
15351574 tty->print (" node[%d %s]" , _node->_idx , _node->Name ());
15361575}
15371576
1538- void VTransformLoopPhiNode ::print_spec () const {
1577+ void VTransformPhiScalarNode ::print_spec () const {
15391578 tty->print (" node[%d %s]" , _node->_idx , _node->Name ());
15401579}
15411580
0 commit comments