{"record":{"id":"d30e7ee5b8161d48","repo":"oracle/graal","slug":"normalizecomparenode-connected-to-s-s-s-s","errorCode":null,"errorMessage":"NormalizeCompareNode connected to %s (%s %s %s)","messagePattern":"NormalizeCompareNode connected to (.+?) \\((.+?) (.+?) (.+?)\\)","errorType":"exception","errorClass":"PermanentBailoutException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/calc/CompareNode.java","lineNumber":289,"sourceCode":"\n            return supported;\n        }\n\n        private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, CanonicalCondition condition, ConvertNode convert,\n                        Constant constant, NodeView view) {\n            if (convert.preservesOrder(condition, constant, constantReflection)) {\n                Constant reverseConverted = convert.reverse(constant, constantReflection);\n                if (reverseConverted != null && convert.convert(reverseConverted, constantReflection).equals(constant)) {\n                    return ConstantNode.forConstant(convert.getValue().stamp(view), reverseConverted, metaAccess);\n                }\n            }\n            return null;\n        }\n\n        @SuppressWarnings(\"unused\")\n        protected LogicNode optimizeNormalizeCompare(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,\n                        Constant constant, AbstractNormalizeCompareNode normalizeNode, boolean mirrored, NodeView view) {\n            throw new PermanentBailoutException(\"NormalizeCompareNode connected to %s (%s %s %s)\", this, constant, normalizeNode, mirrored);\n        }\n\n        private static LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond, boolean unorderedIsTrue) {\n            Constant trueConstant = conditionalNode.trueValue().asConstant();\n            Constant falseConstant = conditionalNode.falseValue().asConstant();\n\n            if (falseConstant != null && trueConstant != null && constantReflection != null) {\n                Stamp compareStamp = conditionalNode.trueValue().stamp(NodeView.DEFAULT);\n                TriState trueResult = cond.foldCondition(compareStamp, trueConstant, constant, constantReflection, unorderedIsTrue);\n                TriState falseResult = cond.foldCondition(compareStamp, falseConstant, constant, constantReflection, unorderedIsTrue);\n\n                if (trueResult.isKnown() && trueResult.equals(falseResult)) {\n                    return LogicConstantNode.forBoolean(trueResult.toBoolean());\n                } else {\n                    if (trueResult.isTrue() && falseResult.isFalse()) {\n                        return conditionalNode.condition();\n                    } else if (trueResult.isFalse() && falseResult.isTrue()) {\n                        return LogicNegationNode.create(conditionalNode.condition());","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/calc/CompareNode.java#L271-L307","documentation":"During CompareNode canonicalization, comparing an AbstractNormalizeCompareNode against a constant is only supported for the specific subclass overloads (e.g., Integer/Float CompareNode); the base-class fallback optimizeNormalizeCompare throws PermanentBailoutException listing the node, constant, normalize node, and mirrored flag. Hitting it means an unexpected comparison shape reached a compare node that cannot fold it — an internal invariant, not user configuration.","triggerScenarios":"A CompareNode subclass whose canonicalization delegates to the generic optimizeNormalizeCompare (i.e., no constant-folding support for the type combination) encounters normalize(x,y) OP constant during canonicalization. This requires a node/intrinsic producing an unusual normalize-compare usage pattern, typically from generated graphs or new node types.","commonSituations":"Custom Graal plugins or languages introducing new compare node types; rare shapes in auto-generated (bytecode-generated) code; effectively never in normal application compilation — essentially a bug-class error.","solutions":["File a GraalVM issue with -Dgraal.Dump=:2 output: the message already identifies the compare node, constant, and normalize node","Work around by restructuring the comparison at the source level (e.g., use explicit Integer.compare/compareTo instead of chained relational expressions with unary minus patterns that form NormalizeCompare nodes)","If developing custom nodes, override optimizeNormalizeCompare in your CompareNode subclass instead of relying on the throwing default"],"exampleFix":"// before: exotic pattern that folds to normalize-compare against a constant\nboolean b = (a < b ? -1 : a > b ? 1 : 0) == SOME_CONST;\n\n// after: plain comparison the canonicalizer handles\nboolean b = SOME_CONST == Integer.compare(a, b);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { compile(m); } catch (PermanentBailoutException e) { /* internal canonicalization invariant: report upstream with -Dgraal.Dump=:2 */ fallbackToBaseline(m, e); }","preventionTips":["Prefer direct Integer.compare/compareTo over normalize-compare-shaped relational chains","Custom CompareNode subclasses must override optimizeNormalizeCompare","Always attach Graal dumps when reporting this class of failure"],"tags":["graalvm","canonicalization","compare-nodes","internal-error","permanent-bailout"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}