Given a node N with its control input A and B being the immediate dominator of A. If A post-dominates B (i.e. a control flow visits A iff it visits B), then N can be rewired to B. This allows N to be more freely schedulable, even hoist it above the loop because the loop entry dominates the loop head and the loop head post-dominates the loop entry.
For example:
public static void test(Blackhole bh, NativeMemorySegment a, int inc) {
for (int i = 0; i < 100; i += inc) {
// Not a counted loop
bh.consume(a.get(ValueLayout.JAVA_INT_UNALIGNED, 0));
}
}
Since the native load is an unsafe load, when the range check is predicated out, it is wired to the loop head. We can hoist it to the loop entry. Note that we may not be able to do this with stores because of some assertions that I don't fully understand.
The same happens with an UTF-16 string, because StringUTF16::getChar produces a pinned load:
public static void test(Blackhole bh, String s, int inc) {
for (int i = 0; i < 100; i += inc) {
// Not a counted loop
bh.consume(s.charAt(0));
}
}
For example:
public static void test(Blackhole bh, NativeMemorySegment a, int inc) {
for (int i = 0; i < 100; i += inc) {
// Not a counted loop
bh.consume(a.get(ValueLayout.JAVA_INT_UNALIGNED, 0));
}
}
Since the native load is an unsafe load, when the range check is predicated out, it is wired to the loop head. We can hoist it to the loop entry. Note that we may not be able to do this with stores because of some assertions that I don't fully understand.
The same happens with an UTF-16 string, because StringUTF16::getChar produces a pinned load:
public static void test(Blackhole bh, String s, int inc) {
for (int i = 0; i < 100; i += inc) {
// Not a counted loop
bh.consume(s.charAt(0));
}
}