To perform some loop optimizations, the C2 compiler requires well-defined graph shapes at certain places. To preserve these graphs during the loop optimization process, C2 hides some nodes behind "opaque" nodes (e.g., Opaque[1-3]). Also, C2 assumes that opaque nodes are removed only after all loop optimizations have finished.
C2's assumption regarding the removal of opaque nodes is wrong. Loop nodes are removed after major_progress is set to false, because major_progress is assumed to indicate that no more loop optimizations will be performed.
Unfortunately, major_progress can reset to true after some opaque nodes have been removed (see, e.g., Node::remove_useless_bool()). That results in inappropriate graph shapes showing up and C2 crashing as a result (see, e.g., JDK-8148754).
The issue related to the inconsistent usage of major_progress has been described and partially addressed by JDK-8144487. However, as JDK-8148754 shows, the usage of major_progress is inconsistent and more work remains to be done.