@@ -3464,6 +3464,10 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
34643464 }
34653465 break ;
34663466 }
3467+ case Op_CastII: {
3468+ remove_range_check_cast (n->as_CastII ());
3469+ }
3470+ break ;
34673471#ifdef _LP64
34683472 case Op_CmpP:
34693473 // Do this transformation here to preserve CmpPNode::sub() and
@@ -3615,16 +3619,6 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
36153619
36163620#endif
36173621
3618- #ifdef ASSERT
3619- case Op_CastII:
3620- // Verify that all range check dependent CastII nodes were removed.
3621- if (n->isa_CastII ()->has_range_check ()) {
3622- n->dump (3 );
3623- assert (false , " Range check dependent CastII node was not removed" );
3624- }
3625- break ;
3626- #endif
3627-
36283622 case Op_ModI:
36293623 if (UseDivMod) {
36303624 // Check if a%b and a/b both exist
@@ -3633,6 +3627,8 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
36333627 // Replace them with a fused divmod if supported
36343628 if (Matcher::has_match_rule (Op_DivModI)) {
36353629 DivModINode* divmod = DivModINode::make (n);
3630+ divmod->add_prec_from (n);
3631+ divmod->add_prec_from (d);
36363632 d->subsume_by (divmod->div_proj (), this );
36373633 n->subsume_by (divmod->mod_proj (), this );
36383634 } else {
@@ -3653,6 +3649,8 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
36533649 // Replace them with a fused divmod if supported
36543650 if (Matcher::has_match_rule (Op_DivModL)) {
36553651 DivModLNode* divmod = DivModLNode::make (n);
3652+ divmod->add_prec_from (n);
3653+ divmod->add_prec_from (d);
36563654 d->subsume_by (divmod->div_proj (), this );
36573655 n->subsume_by (divmod->mod_proj (), this );
36583656 } else {
@@ -3673,6 +3671,8 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
36733671 // Replace them with a fused unsigned divmod if supported
36743672 if (Matcher::has_match_rule (Op_UDivModI)) {
36753673 UDivModINode* divmod = UDivModINode::make (n);
3674+ divmod->add_prec_from (n);
3675+ divmod->add_prec_from (d);
36763676 d->subsume_by (divmod->div_proj (), this );
36773677 n->subsume_by (divmod->mod_proj (), this );
36783678 } else {
@@ -3693,6 +3693,8 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
36933693 // Replace them with a fused unsigned divmod if supported
36943694 if (Matcher::has_match_rule (Op_UDivModL)) {
36953695 UDivModLNode* divmod = UDivModLNode::make (n);
3696+ divmod->add_prec_from (n);
3697+ divmod->add_prec_from (d);
36963698 d->subsume_by (divmod->div_proj (), this );
36973699 n->subsume_by (divmod->mod_proj (), this );
36983700 } else {
@@ -3894,6 +3896,34 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
38943896 }
38953897}
38963898
3899+ void Compile::remove_range_check_cast (CastIINode* cast) {
3900+ if (cast->has_range_check ()) {
3901+ // Range check CastII nodes feed into an address computation subgraph. Remove them to let that subgraph float freely.
3902+ // For memory access or integer divisions nodes that depend on the cast, record the dependency on the cast's control
3903+ // as a precedence edge, so they can't float above the cast in case that cast's narrowed type helped eliminate a
3904+ // range check or a null divisor check.
3905+ assert (cast->in (0 ) != nullptr , " All RangeCheck CastII must have a control dependency" );
3906+ ResourceMark rm;
3907+ Unique_Node_List wq;
3908+ wq.push (cast);
3909+ for (uint next = 0 ; next < wq.size (); ++next) {
3910+ Node* m = wq.at (next);
3911+ for (DUIterator_Fast imax, i = m->fast_outs (imax); i < imax; i++) {
3912+ Node* use = m->fast_out (i);
3913+ if (use->is_Mem () || use->is_div_or_mod (T_INT) || use->is_div_or_mod (T_LONG)) {
3914+ use->ensure_control_or_add_prec (cast->in (0 ));
3915+ } else if (!use->is_CFG () && !use->is_Phi ()) {
3916+ wq.push (use);
3917+ }
3918+ }
3919+ }
3920+ cast->subsume_by (cast->in (1 ), this );
3921+ if (cast->outcnt () == 0 ) {
3922+ cast->disconnect_inputs (this );
3923+ }
3924+ }
3925+ }
3926+
38973927// ------------------------------final_graph_reshaping_walk---------------------
38983928// Replacing Opaque nodes with their input in final_graph_reshaping_impl(),
38993929// requires that the walk visits a node's inputs before visiting the node.
0 commit comments