IGVN worklist ordering

Vladimir Kozlov vladimir.kozlov at oracle.com
Thu Dec 24 03:13:25 UTC 2015


 > Then is the record_for_igvn(ccast) call necessary here? If so, how does it really work?

Consider next code:

class A {}
class A1 extends A {}
class A2 extends A {}

  void test(class A a) {
     if (b1) {
         a = new A1();
     } else if (b2) {
         a = new A2();
     }
     if (a.getClass() == A.class)
         // Here cast (A)a could be incorrectly replaced by
         // (A1)a cast if second path was not processed yet

Vladimir

On 12/23/15 6:42 PM, Krystal Mok wrote:
> Hi Vladimir,
>
> Thanks a lot for your reply! I really appreciate it.
>
> On Wed, Dec 23, 2015 at 6:16 PM, Vladimir Kozlov <vladimir.kozlov at oracle.com <mailto:vladimir.kozlov at oracle.com>> wrote:
>
>     One of the problems is that IGVN worklist is not "true" queue. There is no guarantee that nodes will be processed in
>     the order they were placed on worklist. Long ago I played with "real" queue worklist but it bring only increase in
>     memory consumption.
>
>     1. We only delay transformation when there are merge paths to wait when all paths are complete.
>
>
> Yes, this is a good rule of thumb.
>
> Let's take Parse::sharpen_type_after_if() for example.
>
>    // Look for opportunities to sharpen the type of a node
>    // whose klass is compared with a constant klass.
>    if (btest == BoolTest::eq && tcon->isa_klassptr()) {
>      Node* obj = extract_obj_from_klass_load(&_gvn, val);
>      const TypeOopPtr* con_type = tcon->isa_klassptr()->as_instance_type();
>      if (obj != NULL && (con_type->isa_instptr() || con_type->isa_aryptr())) {
>         // Found:
>         //   Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq])
>         // or the narrowOop equivalent.
>         const Type* obj_type = _gvn.type(obj);
>         const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr();
>         if (tboth != NULL && tboth->klass_is_exact() && tboth != obj_type &&
>             tboth->higher_equal(obj_type)) {
>            // obj has to be of the exact type Foo if the CmpP succeeds.
>            int obj_in_map = map()->find_edge(obj);
>            JVMState* jvms = this->jvms();
>            if (obj_in_map >= 0 &&
>                (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) {
>              TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth);
>              const Type* tcc = ccast->as_Type()->type();
>              assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve");
>              // Delay transform() call to allow recovery of pre-cast value
>              // at the control merge.
>              _gvn.set_type_bottom(ccast);
>              record_for_igvn(ccast);
>              // Here's the payoff.
>              replace_in_map(obj, ccast);
>            }
>         }
>      }
>    }
>
> The CheckCastPP node replaces the original value on a certain path after a control split. It's not a node whose control
> is a merge point (Region, Loop, etc); the merge point after this split should see the original (pre-case) value.
> Then is the record_for_igvn(ccast) call necessary here? If so, how does it really work?
>
> (I wrote the code above, but thinking of it now, I don't seem to fully understand why I wrote it that way...)
>
>
>     2. In reality you can't say that some path is dead until some data nodes and depending on them condition code are
>     processed. We do try to eliminate dead nodes recursively when we find one - see remove_globally_dead_node() and
>     kill_dead_code(). But it not always work.
>
> Thanks a lot for the pointer. I'm looking at kill_dead_code() right now. I might have additional questions with regards
> to them later.
>
> Happy holidays!
>
> Best regards,
> Kris
>
>     Vladimir
>
>
>     On 12/23/15 3:07 PM, Krystal Mok wrote:
>
>         Hi compiler team,
>
>         I’d like to ask about the IGVN worklist ordering:
>
>         1. Is there a rule of thumb of which nodes should call record_for_igvn()? If so, in what order (e.g. data nodes vs.
>         their control dependence)?
>
>         Apparently, nodes that get a record_for_igvn() call right after their creation usually wants to delay the call to
>         transform(), perhaps due to potential optimizations to their control input, or because they're created after
>         parsing and
>         might affect other nodes.
>
>         But what would be a good list of guidelines about exactly what kind of nodes, or what kind of patterns in the
>         IR, that
>         should be considered as candidates to put onto the IGVN worklist, and vice versa?
>
>         2. Since it’s problematic for IGVN to process a node whose control path is already dead (but not yet collapsed
>         to TOP),
>         why isn’t there a mechanism built-in to IGVN’s worklist or PhaseIterGVN::transform_old() so that dead control paths
>         always collapses before IGVN decides to process a node?
>
>
>         I’ve had a doubt on this topic for quite a while now, so I’m seeking advice from all of you who have had to deal
>         with
>         bugs in this area.
>         There have been a lot of bugs related to the IGVN worklist ordering in the past, the most of the fixes does either:
>         a) add missing record_for_igvn() calls for problematic nodes
>         b) switch the order of adjacent record_for_igvn() calls on related nodes
>         Is it possible or a good idea to fix it down at the core of IGVN?
>
>         Happy holidays, guys!
>
>         Best regards,
>         Kris
>
>


More information about the hotspot-compiler-dev mailing list