Enum Class ExplodeLoop.LoopExplosionKind

java.lang.Object
java.lang.Enum<ExplodeLoop.LoopExplosionKind>
com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind
All Implemented Interfaces:
Serializable, Comparable<ExplodeLoop.LoopExplosionKind>, Constable
Enclosing class:
ExplodeLoop

public static enum ExplodeLoop.LoopExplosionKind extends Enum<ExplodeLoop.LoopExplosionKind>
Controls the behavior of the ExplodeLoop annotation.

Terminology

In the explanations below, the term loop end refers to control flow reaching the end of the loop body such as continue or a statement at the end of the loop body. The term loop exit refers to control flow exiting the loop, such as return or break. Example:
int loopEndExits() {
    int state = -1;
    for (int i = 0; i < 4; i++) {
        if (condition(i)) {
            continue; // loop end
        } else if (condition1(i)) {
            // loop exit (break)
            state = 2;
            break;
        } else if (condition2(i)) {
            // loop exit (return)
            state = 3;
            return state;
        } else {
            state = i;
            // loop end
        }
    }
    // loop exit (after last iteration)
    return state;
}
There are 4 loop explosion kinds (plus MERGE_EXPLODE, which is meant for bytecode interpreters), configurable by 2 parameters: UNROLL vs EXPLODE and UNTIL_RETURN vs not.

UNROLL vs EXPLODE

The first parameter specifies whether the partial evaluator should duplicate loop ends. UNROLL merges after each loop end and EXPLODE keeps exploding nested iterations like a tree.
@ExplodeLoop
void unrollVsExplodeLoop() {
    int state = 1;
    for (int i = 0; i < 2; i++) {
        if (c(i, state)) {
            state = 2;
        } else {
            state = 3;
        }
    }
}
gets unrolled with FULL_UNROLL to:
void unrollVsExplodeLoopUnrolled() {
    int state = 1;
    if (c(0, 1)) {
        state = 2;
    } else {
        state = 3;
    }

    if (c(1, state)) {
        state = 2;
    } else {
        state = 3;
    }
}
and exploded with FULL_EXPLODE to:
void unrollVsExplodeLoopExploded() {
    int state = 1;
    if (c(0, 1)) {
        if (c(1, 2)) {
            state = 2;
        } else {
            state = 3;
        }
    } else {
        if (c(1, 3)) {
            state = 2;
        } else {
            state = 3;
        }
    }
}

UNTIL_RETURN

The second parameter specifies whether the partial evaluator should duplicate loop exits. UNTIL_RETURN duplicates them, otherwise control flow is merged.
@ExplodeLoop
int untilReturnLoop() {
    for (int i = 0; i < 2; i++) {
        if (condition(i)) {
            // exit1
            return f(i);
        }
    }
    // exit2
    return fallback();
}
is expanded with FULL_UNROLL_UNTIL_RETURN to:
int untilReturn() {
    if (condition(0)) {
        return f(0);
    }

    if (condition(1)) {
        return f(1);
    }

    return fallback();
}
while FULL_UNROLL merges loop exits:
int notUntilReturn() {
    int i;
    for (;;) {
        if (condition(0)) {
            i = 0;
            break;
        }

        if (condition(1)) {
            i = 1;
            break;
        }

        return fallback();
    }

    return f(i);
}

break

Note that break statements inside the loop will duplicate code after the loop since they add new loop exits:
@ExplodeLoop
int breaksLoop() {
    int state = -1;

    for (int i = 0; i < 2; i++) {
        if (condition1(i)) {
            return f(i);
        } else if (condition2(i)) {
            state = i;
            break;
        }
    }

    return fallback(state);
}
is expanded with FULL_UNROLL_UNTIL_RETURN to:
int breaksLoopUnrollUntilReturn() {
    if (condition1(0)) {
        return f(0);
    } else if (condition2(0)) {
        return fallback(0);
    }

    if (condition1(1)) {
        return f(1);
    } else if (condition2(1)) {
        return fallback(1);
    }

    return fallback(-1);
}
Since:
0.15
  • Enum Constant Details

    • FULL_UNROLL

      public static final ExplodeLoop.LoopExplosionKind FULL_UNROLL
      Fully unroll all loops. The loops must have a known finite number of iterations. If a loop has multiple loop ends, they are merged so that the subsequent loop iteration is processed only once. For example, a loop with 4 iterations and 2 loop ends leads to 1+1+1+1 = 4 copies of the loop body.
      Since:
      0.15
    • FULL_UNROLL_UNTIL_RETURN

      public static final ExplodeLoop.LoopExplosionKind FULL_UNROLL_UNTIL_RETURN
      Like FULL_UNROLL, but in addition loop unrolling duplicates loop exits in every iteration instead of merging them. Code after a loop exit is duplicated for every loop exit and every loop iteration. For example, a loop with 4 iterations and 2 loop exits (exit1 and exit2, where exit1 is an early return inside a loop, such as untilReturnLoop()) leads to 4 copies of the loop body and 4 copies of exit1 and 1 copy of exit2. After each exit all code until a return is duplicated per iteration. Beware of break statements inside loops since they cause additional loop exits leading to code duplication along exit2.
      Since:
      20.0
    • FULL_EXPLODE

      public static final ExplodeLoop.LoopExplosionKind FULL_EXPLODE
      Fully explode all loops. The loops must have a known finite number of iterations. If a loop has multiple loop ends, they are not merged so that subsequent loop iterations are processed multiple times. For example, a loop with 4 iterations and 2 loop ends leads to 1+2+4+8 = 15 copies of the loop body.
      Since:
      0.15
    • FULL_EXPLODE_UNTIL_RETURN

      public static final ExplodeLoop.LoopExplosionKind FULL_EXPLODE_UNTIL_RETURN
      Like FULL_EXPLODE, but in addition explosion does not stop at loop exits. Code after the loop is duplicated for every loop exit of every loop iteration. For example, a loop with 4 iterations and 2 loop exits leads to 4 * 2 = 8 copies of the code after the loop.
      Since:
      0.15
    • MERGE_EXPLODE

      public static final ExplodeLoop.LoopExplosionKind MERGE_EXPLODE
      like FULL_EXPLODE, but copies of the loop body that have the exact same state (all local variables have the same value) are merged. This reduces the number of copies necessary, but can introduce loops again. This kind is useful for bytecode interpreter loops.
      Since:
      0.15
  • Method Details

    • values

      public static ExplodeLoop.LoopExplosionKind[] values()
      Returns an array containing the constants of this enum class, in the order they are declared.
      Returns:
      an array containing the constants of this enum class, in the order they are declared
    • valueOf

      public static ExplodeLoop.LoopExplosionKind valueOf(String name)
      Returns the enum constant of this class with the specified name. The string must match exactly an identifier used to declare an enum constant in this class. (Extraneous whitespace characters are not permitted.)
      Parameters:
      name - the name of the enum constant to be returned.
      Returns:
      the enum constant with the specified name
      Throws:
      IllegalArgumentException - if this enum class has no constant with the specified name
      NullPointerException - if the argument is null