C2: cyclic IR for JVMS
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Thu Dec 18 19:11:15 UTC 2014
Roland,
The code is reachable by the time inlining occurs, but the call node is
broken.
The transformation which breaks the code is performed in
RegionNode::Ideal()
Phi (Region) (Proj #5 (CallStaticJava ... Phi(backref)...))
==>
(Proj #5 (CallStaticJava ... Proj(backref)...))
The RegionNode and Phi are removed, but CallStaticJava is broken.
It seems that if RegionNode::is_unreachable_region() detected that
RegionNode is dead, it would break the vicious circle (PhiNode is
replaced by top()).
Not sure why the call node is live, though the loop was dead.
Best regards,
Vladimir Ivanov
On 12/18/14, 8:25 PM, Roland Westrelin wrote:
>> As my investigations show, it's a leftover from a loop.
>> CallStaticJava represents loop counter increment.
>>
>> The graph is as follows:
>> Phi (Region) (Proj #5 (CallStaticJava ... Phi(backref)...))
>>
>> The Region is dead, but RegionNode::is_unreachable_region doesn't detect that. Node::simple_data_loop_check(Phi, Proj) doesn't find the cycle, because most of Proj nodes have Flag_is_dead_loop_safe set [1].
>> And I don't understand why it is so. Is the check in Node::is_dead_loop_safe() too weak or Flag_is_dead_loop_safe too "optimistic"? :-)
>
> Isn’t the problem that you try to late inline a call that is dead and that the checks in LateInlineCallGenerator::do_late_inline():
>
> if (call == NULL || call->outcnt() == 0 ||
> call->in(0) == NULL || call->in(0)->is_top()) {
> return;
> }
>
> const TypeTuple *r = call->tf()->domain();
> for (int i1 = 0; i1 < method()->arg_size(); i1++) {
> if (call->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) {
> assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
> return;
> }
> }
>
> if (call->in(TypeFunc::Memory)->is_top()) {
> assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
> return;
> }
>
> don’t detect it?
> FWIW, I know there are rare cases where those tests are not sufficient. Ideally, you would need Compile::inline_incrementally() to do:
> PhaseIdealLoop ideal_loop( igvn, false, true );
> after every inline but that’s very expensive.
>
> Roland.
>
More information about the hotspot-compiler-dev
mailing list