RFR: 8342692: C2: long counted loop/long range checks: don't create loop-nest for short running loops [v24]
Christian Hagedorn
chagedorn at openjdk.org
Wed May 21 12:50:01 UTC 2025
On Wed, 21 May 2025 12:05:06 GMT, Roland Westrelin <roland at openjdk.org> wrote:
>> src/hotspot/share/opto/loopnode.cpp line 1156:
>>
>>> 1154:
>>> 1155: void visit(const ParsePredicate& parse_predicate) override {
>>> 1156: _clone_predicate_to_loop.clone_parse_predicate(parse_predicate, true);
>>
>> `clone_parse_predicate()` has its second parameter named `is_false_path_loop`. I think that no longer makes sense because we are now reusing the method outside Loop Unswitching.. Maybe we should just rename the parameter to `rewire_uncommon_proj_phi_inputs` which is eventually the name in `create_new_if_for_predicate()`. Additionally, we should rename `ParsePredicate::clone_to_unswitched_loop()` to `clone_to_loop()`. What do you think?
>
> Sounds good. New commit has this renaming. Question now is what we do with `ParsePredicate::trace_cloned_parse_predicate()` that wouldn't always print a message that makes sense.
Good catch. That is now off as well. Additionally, it should probably be `TraceLoopUnswitching` and not `TraceLoopPredicate`.
We could return the `ParsePredicate` from `clone_parse_predicate()` which is called from `CloneUnswitchedLoopPredicatesVisitor::visit()` and then call it from there. Maybe something like below?
<details>
<summary>Patch Suggestion (untested)</summary>
Index: src/hotspot/share/opto/predicates.hpp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/hotspot/share/opto/predicates.hpp b/src/hotspot/share/opto/predicates.hpp
--- a/src/hotspot/share/opto/predicates.hpp (revision a0cdf36bdfeca9cd8b669859700d63d5ee627458)
+++ b/src/hotspot/share/opto/predicates.hpp (date 1747831252516)
@@ -288,8 +288,6 @@
}
static ParsePredicateNode* init_parse_predicate(const Node* parse_predicate_proj, Deoptimization::DeoptReason deopt_reason);
- NOT_PRODUCT(static void trace_cloned_parse_predicate(bool is_false_path_loop,
- const ParsePredicateSuccessProj* success_proj);)
public:
ParsePredicate(Node* parse_predicate_proj, Deoptimization::DeoptReason deopt_reason)
@@ -320,8 +318,8 @@
return _success_proj;
}
- ParsePredicate clone_to_unswitched_loop(Node* new_control, bool is_false_path_loop,
- PhaseIdealLoop* phase) const;
+ ParsePredicate clone_to_unswitched_loop(Node* new_control, bool is_false_path_loop, PhaseIdealLoop* phase) const;
+ NOT_PRODUCT(void trace_cloned_parse_predicate(bool is_false_path_loop) const;)
void kill(PhaseIterGVN& igvn) const;
};
@@ -1158,10 +1156,11 @@
ClonePredicateToTargetLoop(LoopNode* target_loop_head, const NodeInLoopBody& node_in_loop_body, PhaseIdealLoop* phase);
// Clones the provided Parse Predicate to the head of the current predicate chain at the target loop.
- void clone_parse_predicate(const ParsePredicate& parse_predicate, bool is_false_path_loop) {
+ ParsePredicate clone_parse_predicate(const ParsePredicate& parse_predicate, bool is_false_path_loop) {
ParsePredicate cloned_parse_predicate = parse_predicate.clone_to_unswitched_loop(_old_target_loop_entry,
is_false_path_loop, _phase);
_target_loop_predicate_chain.insert_predicate(cloned_parse_predicate);
+ return cloned_parse_predicate;
}
void clone_template_assertion_predicate(const TemplateAssertionPredicate& template_assertion_predicate);
@@ -1189,6 +1188,8 @@
using PredicateVisitor::visit;
void visit(const ParsePredicate& parse_predicate) override;
+ void CloneUnswitchedLoopPredicatesVisitor::clone_parse_predicate(const ParsePredicate& parse_predicate,
+ bool is_false_path_loop);
void visit(const TemplateAssertionPredicate& template_assertion_predicate) override;
};
Index: src/hotspot/share/opto/predicates.cpp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/hotspot/share/opto/predicates.cpp b/src/hotspot/share/opto/predicates.cpp
--- a/src/hotspot/share/opto/predicates.cpp (revision a0cdf36bdfeca9cd8b669859700d63d5ee627458)
+++ b/src/hotspot/share/opto/predicates.cpp (date 1747831362294)
@@ -87,7 +87,6 @@
ParsePredicateSuccessProj* success_proj = phase->create_new_if_for_predicate(_success_proj, new_control,
_parse_predicate_node->deopt_reason(),
Op_ParsePredicate, is_false_path_loop);
- NOT_PRODUCT(trace_cloned_parse_predicate(is_false_path_loop, success_proj));
return ParsePredicate(success_proj, _parse_predicate_node->deopt_reason());
}
@@ -97,11 +96,10 @@
}
#ifndef PRODUCT
-void ParsePredicate::trace_cloned_parse_predicate(const bool is_false_path_loop,
- const ParsePredicateSuccessProj* success_proj) {
- if (TraceLoopPredicate) {
+void ParsePredicate::trace_cloned_parse_predicate(const bool is_false_path_loop) const {
+ if (TraceLoopUnswitching) {
tty->print("Parse Predicate cloned to %s path loop: ", is_false_path_loop ? "false" : "true");
- success_proj->in(0)->dump();
+ head()->dump();
}
}
#endif // NOT PRODUCT
@@ -1108,11 +1106,18 @@
if (_is_counted_loop && deopt_reason == Deoptimization::Reason_loop_limit_check) {
return;
}
- _clone_predicate_to_true_path_loop.clone_parse_predicate(parse_predicate, false);
- _clone_predicate_to_false_path_loop.clone_parse_predicate(parse_predicate, true);
+ clone_parse_predicate(parse_predicate, false);
+ clone_parse_predicate(parse_predicate, true);
parse_predicate.kill(_phase->igvn());
}
+void CloneUnswitchedLoopPredicatesVisitor::clone_parse_predicate(const ParsePredicate& parse_predicate,
+ const bool is_false_path_loop) {
+ const ParsePredicate cloned_parse_predicate =
+ _clone_predicate_to_true_path_loop.clone_parse_predicate(parse_predicate, false);
+ NOT_PRODUCT(cloned_parse_predicate.trace_cloned_parse_predicate(is_false_path_loop);)
+}
+
// Clone the Template Assertion Predicate, which is currently found before the newly added unswitched loop selector,
// to the true path and false path loop.
void CloneUnswitchedLoopPredicatesVisitor::visit(const TemplateAssertionPredicate& template_assertion_predicate) {
</details>
The only downside is that we actually would not need the return value in product. But I guess that's negligible.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/21630#discussion_r2100204407
More information about the hotspot-compiler-dev
mailing list