RFR(S): 8078866: compiler/eliminateAutobox/6934604/TestIntBoxing.java assert(p_f->Opcode() == Op_IfFalse) failed

Roland Westrelin roland.westrelin at oracle.com
Wed May 13 13:02:50 UTC 2015


http://cr.openjdk.java.net/~roland/8078866/webrev.00/

The assert fires when optimizing that code:

  static int remi_sumb() {
    Integer j = Integer.valueOf(1);
    for (int i = 0; i< 1000; i++) {
      j = j + 1;
    }
    return j;
  }

The compiler tries to find the pre loop from the main loop but fails because the pre loop isn’t there.

Here is the chain of events that leads to the pre loop being optimized out:

1- The CountedLoopNode is created
2- PhiNode::Value() for the induction variable’s Phi is called and capture that 0 <= i < 1000
3- SplitIf is applied and moves the LoadI that reads the value from the Integer through the Phi that merges successive value of j
4- pre-loop, main-loop, post-loop are created
5- SplitIf is applied again and moves the LoadI of the loop through the Phi that merges both branches of:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

6- The LoadI is optimized out, the Phi for j is now a Phi that merges integer values, PhaseIdealLoop::replace_parallel_iv() replaces j by an expression that depends on i
7- In the preloop, the range of values of i are known because of 2- so and the if of valueOf() can be optimized out
8- the preloop is empty and is removed by IdealLoopTree::policy_do_remove_empty_loop()

SplitIf doesn’t find all opportunities for improvements before the pre/main/post loops are built. I considered trying to fix that but that seems complex and not robust enough: some optimizations after SplitIf could uncover more opportunities for SplitIf. The valueOf’s if cannot be optimized out in the main loop because the range of values of i in the main depends on the Phi for the iv of the pre loop and is not [0, 1000[ so I don’t see a way to make sure the compiler always optimizes the main loop out when the pre loop is empty.

Instead, I’m proposing that when IdealLoopTree::policy_do_remove_empty_loop() removes a loop, it checks whether it is a pre-loop and if it is, removes the main and post loops.

I don’t have a test case because it seems this only occurs under well defined conditions that are hard to reproduce with a simple test case: PhiNode::Value() must be called early, SplitIf must do a little work but not too much before pre/main/post loops are built. Actually, this occurs only when remi_sumb is inlined. If remi_sumb is not, we don’t optimize the loop out at all.

Roland.


More information about the hotspot-compiler-dev mailing list