{"record":{"id":"58f500004fa679c3","repo":"oracle/graal","slug":"irreducible","errorCode":null,"errorMessage":"Irreducible","messagePattern":"Irreducible","errorType":"exception","errorClass":"PermanentBailoutException","httpStatus":null,"severity":"warning","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BciBlockMapping.java","lineNumber":1840,"sourceCode":"                            makeLoopHeader(successor);\n                        }\n                        loopBits = (BitSet) successor.loops.clone();\n                    } else {\n                        // re-reaching control-flow through new path.\n                        // Find loop bits\n                        loopBits = (BitSet) successor.loops.clone();\n                        if (successor.isLoopHeader) {\n                            // this is a forward edge\n                            loopBits.clear(successor.loopId);\n                        }\n                        // Check if we are re-entering a loop in an irreducible way\n                        BitSet checkBits = loopBits;\n                        int outermostInactiveLoopId = -1;\n                        for (int pos = -1; (pos = checkBits.nextSetBit(pos + 1)) >= 0;) {\n                            int id = pos;\n                            if (!loopHeaders[id].active) {\n                                if (Options.MaxDuplicationFactor.getValue(debug.getOptions()) <= 1.0D) {\n                                    throw new PermanentBailoutException(\"Irreducible\");\n                                } else if (outermostInactiveLoopId == -1 || !loopHeaders[id].loops.get(outermostInactiveLoopId)) {\n                                    outermostInactiveLoopId = id;\n                                }\n                            }\n                        }\n                        if (outermostInactiveLoopId != -1) {\n                            assert !(step instanceof DuplicationTraversalStep) : step;\n                            // we need to duplicate until we can merge with this loop's header\n                            successor.predecessorCount--;\n                            BciBlock duplicate = successor.duplicate();\n                            duplicate.predecessorCount++;\n                            block.successors.set(step.currentSuccessorIndex, duplicate);\n                            DuplicationTraversalStep duplicationStep = new DuplicationTraversalStep(step, duplicate, loopHeaders[outermostInactiveLoopId]);\n                            workStack.push(duplicationStep);\n                            debug.log(\"Starting duplication @ %s\", duplicate);\n                            debug.dump(DebugContext.DETAILED_LEVEL, this, \"Starting duplication @ %s\", duplicate);\n                            duplicationStep.duplicationMap.put(successor, duplicate);\n                            newDuplicateBlocks++;","sourceCodeStart":1822,"sourceCodeEnd":1858,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BciBlockMapping.java#L1822-L1858","documentation":"Thrown during BciBlockMapping when control flow re-enters a loop that is not currently active — irreducible control flow — and -Dgraal.MaxDuplicationFactor is <= 1.0, so block duplication (the mechanism that would make the loop reducible) is disabled. Graal's frontend only handles reducible loops; with duplication off, irreducible re-entry is a permanent bailout.","triggerScenarios":"Parsing a method whose BCI graph re-enters an inactive loop (a jump into the middle of a loop from outside it) while Options.MaxDuplicationFactor <= 1.0D (the check in the loop over loopBits finding !loopHeaders[id].active).","commonSituations":"Methods with irreducible control flow from bytecode obfuscators, goto-heavy generated code, or languages compiling to class files with unstructured jumps; users who explicitly set -Dgraal.MaxDuplicationFactor=1 to shrink compilation time/memory and then compile such a method.","solutions":["Raise -Dgraal.MaxDuplicationFactor above 1.0 so the duplication pass can restructure the irreducible loop (subject to the cap that guards against duplication explosion).","Recompile the offending class with structured loops (normal Java break/continue) to eliminate irreducible flow.","If the bytecode is produced by a tool (obfuscator/DSL compiler), configure it to emit reducible control flow."],"exampleFix":"# before\njava -Dgraal.MaxDuplicationFactor=1 MyApp\n\n# after\njava -Dgraal.MaxDuplicationFactor=2 MyApp","handlingStrategy":"validation","validationCode":"// if you must compile irreducible-flow bytecode, check the flag first\ndouble factor = jdk.graal.compiler.options.OptionValues\n                .thenApply(v -> MaxDuplicationFactor.getValue(v));\nif (factor <= 1.0D) {\n    // raise the flag or restructure the bytecode; parsing will bail out otherwise\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep -Dgraal.MaxDuplicationFactor > 1.0 (default) if you run obfuscated or goto-heavy bytecode.","Prefer structured, reducible loops in generated code."],"tags":["graalvm","bytecode-parsing","irreducible-loops","bailout","flags"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}