oracle/graal · critical · OutOfRegistersException

There are no allocatable registers for kind %s, consider ass

Error message

There are no allocatable registers for kind %s, consider assigning fixed registers.

What it means

initVarsForAlloc asks the RegisterAllocationConfig for the allocatable registers of the interval's platform kind; if the backend never registered any allocatable register for that kind, allocatableRegisters is null and an OutOfRegistersException is thrown with the suggestion 'consider assigning fixed registers'. It means the target configuration is fundamentally unable to hold values of that kind, not merely that pressure is high.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java:1146

                if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) {
                    DebugContext debug = allocator.getDebug();
                    if (debug.isLogEnabled()) {
                        debug.log("free register cannot be available because all registers blocked by following call");
                    }

                    // safety check that there is really no register available
                    assert !allocFreeRegister(interval) : "found a register for this interval";
                    return true;
                }
            }
        }
        return false;
    }

    void initVarsForAlloc(Interval interval) {
        AllocatableRegisters allocatableRegisters = allocator.getRegisterAllocationConfig().getAllocatableRegisters(interval.kind().getPlatformKind());
        if (allocatableRegisters == null) {
            throw new OutOfRegistersException("There are no allocatable registers for kind " + interval.kind().getPlatformKind() + ", consider assigning fixed registers.");
        }
        availableRegs = allocatableRegisters.allocatableRegisters.toArray(Register[]::new);
        minReg = allocatableRegisters.minRegisterNumber;
        maxReg = allocatableRegisters.maxRegisterNumber;
    }

    static boolean isMove(LIRInstruction op, Interval from, Interval to) {
        if (StandardOp.ValueMoveOp.isValueMoveOp(op)) {
            StandardOp.ValueMoveOp move = StandardOp.ValueMoveOp.asValueMoveOp(op);
            if (LIRValueUtil.isVariable(move.getInput()) && LIRValueUtil.isVariable(move.getResult())) {
                return move.getInput() != null && move.getInput().equals(from.operand) && move.getResult() != null && move.getResult().equals(to.operand);
            }
        }
        return false;
    }

    // optimization (especially for phi functions of nested loops):
    // assign same spill slot to non-intersecting intervals

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. In the backend's RegisterConfig/CompilationSetup, define allocatable (or at minimum fixed) registers for the failing platform kind named in the message
  2. Verify the kind reaches LIR correctly: if the value should have been lowered to a supported kind before allocation, fix the lowering so unallocatable kinds never survive to LSRA
  3. If the kind is only used behind a feature flag/arch check, ensure the frontend does not emit it on architectures where it is unsupported
  4. Search the repo for existing backends handling the same kind (grep getAllocatableRegisters in compiler/src/jdk.graal.compiler/src/com.oracle.graal.lir) and mirror their configuration

Example fix

// before: new vector kind has no register class -> null allocatable registers
// in MyArchRegisterConfig:
//   (no entry for V512_MASK)

// after: assign registers for the kind
//   map Kind.V512_MASK -> allocatable set {k0..k7} in the RegisterAllocationConfig builder
Defensive patterns

Strategy: validation

Validate before calling

// Backend author: assert during setup that every kind you emit has registers
for (PlatformKind kind : arch.getPlatformKinds()) {
    AllocatableRegisters regs = registerConfig.getAllocatableRegisters(kind);
    if (regs == null && frontendEmits(kind)) {
        throw new IllegalStateException("No allocatable registers configured for " + kind);
    }
}

Try / catch

try { compile(m); } catch (OutOfRegistersException e) { /* config-level bug: fail fast in tests */ throw e; }

Prevention

When it happens

Trigger: An interval whose LIRKind carries a PlatformKind (often a vector kind like AVX512 mask registers, or a custom kind added to a new backend) for which RegisterConfig.getAllocatableRegisters returns null. Happens with custom/new architectures, misconfigured RegisterAllocationConfig, or when a generic phase emits a kind the current backend does not allocate registers for.

Common situations: Developing or backporting a Graal backend for a new architecture; using an experimental vector kind not yet wired into the register configuration; porting a patch where RegisterConfig.registerAllocationConfig was built without an entry for the new kind.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/593683d738dd1eed. Report an issue: GitHub.