@@ -152,7 +152,6 @@ void TemplateAssertionPredicate::rewire_loop_data_dependencies(IfTrueNode* targe
152
152
}
153
153
}
154
154
155
-
156
155
// Template Assertion Predicates always have the dedicated OpaqueTemplateAssertionPredicate to identify them.
157
156
bool TemplateAssertionPredicate::is_predicate (Node* node) {
158
157
if (!may_be_assertion_predicate_if (node)) {
@@ -179,6 +178,24 @@ IfTrueNode* TemplateAssertionPredicate::clone_and_replace_init(Node* new_control
179
178
return success_proj;
180
179
}
181
180
181
+ // Replace the input to OpaqueLoopStrideNode with 'new_stride' and leave the other nodes unchanged.
182
+ void TemplateAssertionPredicate::replace_opaque_stride_input (Node* new_stride, PhaseIterGVN& igvn) const {
183
+ TemplateAssertionExpression expression (opaque_node ());
184
+ expression.replace_opaque_stride_input (new_stride, igvn);
185
+ }
186
+
187
+ // Create a new Initialized Assertion Predicate from this template at 'new_control' and return the success projection
188
+ // of the newly created Initialized Assertion Predicate.
189
+ IfTrueNode* TemplateAssertionPredicate::initialize (PhaseIdealLoop* phase, Node* new_control) const {
190
+ assert (phase->assertion_predicate_has_loop_opaque_node (head ()),
191
+ " must find OpaqueLoop* nodes for Template Assertion Predicate" );
192
+ InitializedAssertionPredicateCreator initialized_assertion_predicate (phase);
193
+ IfTrueNode* success_proj = initialized_assertion_predicate.create_from_template (head (), new_control);
194
+ assert (!phase->assertion_predicate_has_loop_opaque_node (success_proj->in (0 )->as_If ()),
195
+ " Initialized Assertion Predicates do not have OpaqueLoop* nodes in the bool expression anymore" );
196
+ return success_proj;
197
+ }
198
+
182
199
// Initialized Assertion Predicates always have the dedicated OpaqueInitiailizedAssertionPredicate node to identify
183
200
// them.
184
201
bool InitializedAssertionPredicate::is_predicate (Node* node) {
@@ -189,6 +206,12 @@ bool InitializedAssertionPredicate::is_predicate(Node* node) {
189
206
return if_node->in (1 )->is_OpaqueInitializedAssertionPredicate ();
190
207
}
191
208
209
+ void InitializedAssertionPredicate::kill (PhaseIdealLoop* phase) const {
210
+ Node* true_con = phase->igvn ().intcon (1 );
211
+ phase->set_ctrl (true_con, phase->C ->root ());
212
+ phase->igvn ().replace_input_of (_if_node, 1 , true_con);
213
+ }
214
+
192
215
#ifdef ASSERT
193
216
// Check that the block has at most one Parse Predicate and that we only find Regular Predicate nodes (i.e. IfProj,
194
217
// If, or RangeCheck nodes).
@@ -388,6 +411,63 @@ TemplateAssertionExpression::clone(const TransformStrategyForOpaqueLoopNodes& tr
388
411
return opaque_node_clone->as_OpaqueTemplateAssertionPredicate ();
389
412
}
390
413
414
+ // This class is used to replace the input to OpaqueLoopStrideNode with a new node while leaving the other nodes
415
+ // unchanged.
416
+ class ReplaceOpaqueStrideInput : public StackObj {
417
+ PhaseIterGVN& _igvn;
418
+ Unique_Node_List _nodes_to_visit;
419
+
420
+ public:
421
+ ReplaceOpaqueStrideInput (OpaqueTemplateAssertionPredicateNode* start_node, PhaseIterGVN& igvn) : _igvn(igvn) {
422
+ _nodes_to_visit.push (start_node);
423
+ }
424
+ NONCOPYABLE (ReplaceOpaqueStrideInput);
425
+
426
+ void replace (Node* new_opaque_stride_input) {
427
+ for (uint i = 0 ; i < _nodes_to_visit.size (); i++) {
428
+ Node* next = _nodes_to_visit[i];
429
+ for (uint j = 1 ; j < next->req (); j++) {
430
+ Node* input = next->in (j);
431
+ if (input->is_OpaqueLoopStride ()) {
432
+ assert (TemplateAssertionExpressionNode::is_maybe_in_expression (input), " must also pass node filter" );
433
+ _igvn.replace_input_of (input, 1 , new_opaque_stride_input);
434
+ } else if (TemplateAssertionExpressionNode::is_maybe_in_expression (input)) {
435
+ _nodes_to_visit.push (input);
436
+ }
437
+ }
438
+ }
439
+ }
440
+ };
441
+
442
+ // Replace the input to OpaqueLoopStrideNode with 'new_stride' and leave the other nodes unchanged.
443
+ void TemplateAssertionExpression::replace_opaque_stride_input (Node* new_stride, PhaseIterGVN& igvn) {
444
+ ReplaceOpaqueStrideInput replace_opaque_stride_input (_opaque_node, igvn);
445
+ replace_opaque_stride_input.replace (new_stride);
446
+ }
447
+
448
+ // The transformations of this class fold the OpaqueLoop* nodes by returning their inputs.
449
+ class RemoveOpaqueLoopNodesStrategy : public TransformStrategyForOpaqueLoopNodes {
450
+ public:
451
+ Node* transform_opaque_init (OpaqueLoopInitNode* opaque_init) const override {
452
+ return opaque_init->in (1 );
453
+ }
454
+
455
+ Node* transform_opaque_stride (OpaqueLoopStrideNode* opaque_stride) const override {
456
+ return opaque_stride->in (1 );
457
+ }
458
+ };
459
+
460
+ OpaqueInitializedAssertionPredicateNode*
461
+ TemplateAssertionExpression::clone_and_fold_opaque_loop_nodes (Node* new_control, PhaseIdealLoop* phase) {
462
+ RemoveOpaqueLoopNodesStrategy remove_opaque_loop_nodes_strategy;
463
+ OpaqueTemplateAssertionPredicateNode* cloned_template_opaque = clone (remove_opaque_loop_nodes_strategy, new_control,
464
+ phase);
465
+ OpaqueInitializedAssertionPredicateNode* opaque_initialized_opaque =
466
+ new OpaqueInitializedAssertionPredicateNode (cloned_template_opaque->in (1 )->as_Bool (), phase->C );
467
+ phase->register_new_node (opaque_initialized_opaque, new_control);
468
+ return opaque_initialized_opaque;
469
+ }
470
+
391
471
// Check if this node belongs a Template Assertion Expression (including OpaqueLoop* nodes).
392
472
bool TemplateAssertionExpressionNode::is_in_expression (Node* node) {
393
473
if (is_maybe_in_expression (node)) {
@@ -664,6 +744,19 @@ IfTrueNode* InitializedAssertionPredicateCreator::create_from_template(IfNode* t
664
744
NOT_PRODUCT (COMMA template_assertion_predicate->assertion_predicate_type ()));
665
745
}
666
746
747
+ // Create a new Initialized Assertion Predicate from 'template_assertion_predicate' by cloning it but omitting the
748
+ // OpaqueLoop*Notes (i.e. taking their inputs instead).
749
+ IfTrueNode* InitializedAssertionPredicateCreator::create_from_template (IfNode* template_assertion_predicate,
750
+ Node* new_control) {
751
+ OpaqueTemplateAssertionPredicateNode* template_opaque =
752
+ template_assertion_predicate->in (1 )->as_OpaqueTemplateAssertionPredicate ();
753
+ TemplateAssertionExpression template_assertion_expression (template_opaque);
754
+ OpaqueInitializedAssertionPredicateNode* assertion_expression =
755
+ template_assertion_expression.clone_and_fold_opaque_loop_nodes (new_control, _phase);
756
+ return create_control_nodes (new_control, template_assertion_predicate->Opcode (), assertion_expression
757
+ NOT_PRODUCT (COMMA template_assertion_predicate->assertion_predicate_type ()));
758
+ }
759
+
667
760
// Create a new Initialized Assertion Predicate directly without a template.
668
761
IfTrueNode* InitializedAssertionPredicateCreator::create (Node* operand, Node* new_control, const jint stride,
669
762
const int scale, Node* offset, Node* range NOT_PRODUCT (COMMA
@@ -768,7 +861,7 @@ void CreateAssertionPredicatesVisitor::visit(const TemplateAssertionPredicate& t
768
861
769
862
// Create an Initialized Assertion Predicate from the provided Template Assertion Predicate.
770
863
IfTrueNode* CreateAssertionPredicatesVisitor::initialize_from_template (
771
- const TemplateAssertionPredicate& template_assertion_predicate) const {
864
+ const TemplateAssertionPredicate& template_assertion_predicate) const {
772
865
IfNode* template_head = template_assertion_predicate.head ();
773
866
IfTrueNode* initialized_predicate = _phase->create_initialized_assertion_predicate (template_head, _init, _stride,
774
867
_new_control);
@@ -783,3 +876,36 @@ IfTrueNode* CreateAssertionPredicatesVisitor::clone_template_and_replace_init_in
783
876
_phase->register_new_node (opaque_init, _new_control);
784
877
return template_assertion_predicate.clone_and_replace_init (_new_control, opaque_init, _phase);
785
878
}
879
+
880
+ // Clone the Template Assertion Predicate and set a new input for the OpaqueLoopStrideNode.
881
+ void UpdateStrideForAssertionPredicates::visit (const TemplateAssertionPredicate& template_assertion_predicate) {
882
+ replace_opaque_stride_input (template_assertion_predicate);
883
+ Node* template_tail_control_out = template_assertion_predicate.tail ()->unique_ctrl_out ();
884
+ IfTrueNode* initialized_success_proj = initialize_from_updated_template (template_assertion_predicate);
885
+ connect_initialized_assertion_predicate (template_tail_control_out, initialized_success_proj);
886
+ }
887
+
888
+ // Replace the input to OpaqueLoopStrideNode with 'new_stride' and leave the other nodes unchanged.
889
+ void UpdateStrideForAssertionPredicates::replace_opaque_stride_input (
890
+ const TemplateAssertionPredicate& template_assertion_predicate) const {
891
+ template_assertion_predicate.replace_opaque_stride_input (_new_stride, _phase->igvn ());
892
+ }
893
+
894
+ IfTrueNode* UpdateStrideForAssertionPredicates::initialize_from_updated_template (
895
+ const TemplateAssertionPredicate& template_assertion_predicate) const {
896
+ IfTrueNode* initialized_success_proj = template_assertion_predicate.initialize (_phase, template_assertion_predicate.tail ());
897
+ return initialized_success_proj;
898
+ }
899
+
900
+ // The newly created Initialized Assertion Predicate can safely be inserted because this visitor is already visiting
901
+ // the Template Assertion Predicate above this. So, we will not accidentally visit this again and kill it with the
902
+ // visit() method for Initialized Assertion Predicates.
903
+ void UpdateStrideForAssertionPredicates::connect_initialized_assertion_predicate (
904
+ Node* new_control_out, IfTrueNode* initialized_success_proj) const {
905
+ if (new_control_out->is_Loop ()) {
906
+ _phase->igvn ().replace_input_of (new_control_out, LoopNode::EntryControl, initialized_success_proj);
907
+ } else {
908
+ _phase->igvn ().replace_input_of (new_control_out, 0 , initialized_success_proj);
909
+ }
910
+ _phase->set_idom (new_control_out, initialized_success_proj, _phase->dom_depth (new_control_out));
911
+ }
0 commit comments