Skip to content

LLVM error "ran out of registers during register allocation" on 32-bit x86 with code-coverage #42200

@kimikage

Description

@kimikage

This comes from the discussion on Discourse.

I found a strange error "ran out of registers during register allocation" in the CI log of a package.
The error occurs on 32-bit x86, but I couldn't figure out the trigger for a long time. Later, @ChenNingCong found that the code for code coverage had something to do with it.

The following is an MWE. I think the easiest way to reproduce the error is to write it in runtests.jl and run it with pkg> test --coverage.

struct RGB8
    r::UInt8
    g::UInt8
    b::UInt8
end
Base.broadcastable(c::RGB8) = Ref(c)

_mapc(f, x::RGB8, y::RGB8) = RGB8(f(x.r, y.r), f(x.g, y.g), f(x.b, y.b))

function lighten(c1::RGB8, c2::RGB8, opacity::AbstractFloat)
    mixed = _mapc(max, c1, c2)
    w(v1, v2) = round(UInt8, v1 * (1 - opacity) + v2 * opacity)
    _mapc(w, c1, mixed)
end

c = RGB8(255, 0, 0)
cs = (RGB8(255, 0, 0), RGB8(0, 255, 0))
f(c1, c2, opacity) = lighten.(c1, c2, opacity)

using InteractiveUtils
versioninfo()

@code_llvm   f(c, cs, 0.8)
@code_native f(c, cs, 0.8) # error
Output of v1.6.2 on Windows (i686-w64-mingw32)
Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
  OS: Windows (i686-w64-mingw32)
  CPU: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
  WORD_SIZE: 32
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, tigerlake)
Environment:
  JULIA_LOAD_PATH = @;C:\Users\username\AppData\Local\Temp\jl_iMZPOq
;  @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:18 within `f'
; Function Attrs: alignstack(16)
define void @julia_f_224([2 x [3 x i8]]* noalias nocapture sret %0, [3 x i8]* nocapture nonnull readonly align 1 deref
erenceable(3) %1, [2 x [3 x i8]]* nocapture nonnull readonly align 1 dereferenceable(6) %2, double %3) #0 {
top:
  %4 = alloca [3 x i8], align 1
  %5 = alloca [3 x i8], align 1
  %6 = alloca [1 x double], align 8
  %7 = alloca [3 x i8], align 1
  %8 = alloca [3 x i8], align 1
  %9 = alloca [1 x double], align 8
  %lcnt = load volatile i64, i64* inttoptr (i32 390202632 to i64*), align 8
  %10 = add i64 %lcnt, 1
  store volatile i64 %10, i64* inttoptr (i32 390202632 to i64*), align 8
; ┌ @ broadcast.jl:1312 within `broadcasted'
; │┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:6 within `broadcastable'
    %lcnt1 = load volatile i64, i64* inttoptr (i32 390202536 to i64*), align 8
    %11 = add i64 %lcnt1, 1
    store volatile i64 %11, i64* inttoptr (i32 390202536 to i64*), align 8
; ││┌ @ refpointer.jl:134 within `Ref'
; │││┌ @ refvalue.jl:10 within `RefValue' @ refvalue.jl:8
      %.elt = getelementptr inbounds [3 x i8], [3 x i8]* %1, i32 0, i32 0
      %.unpack = load i8, i8* %.elt, align 1
      %.elt35 = getelementptr inbounds [3 x i8], [3 x i8]* %1, i32 0, i32 1
      %.unpack36 = load i8, i8* %.elt35, align 1
      %.elt37 = getelementptr inbounds [3 x i8], [3 x i8]* %1, i32 0, i32 2
      %.unpack38 = load i8, i8* %.elt37, align 1
; └└└└
; ┌ @ broadcast.jl:883 within `materialize'
; │┌ @ broadcast.jl:1098 within `copy'
; ││┌ @ ntuple.jl:49 within `ntuple'
; │││┌ @ broadcast.jl:1098 within `#19'
; ││││┌ @ broadcast.jl:620 within `_broadcast_getindex'
; │││││┌ @ broadcast.jl:644 within `_getindex'
; ││││││┌ @ broadcast.jl:595 within `_broadcast_getindex'
; │││││││┌ @ refvalue.jl:56 within `getindex'
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %.fca.0.gep30 = getelementptr inbounds [3 x i8], [3 x i8]* %4, i32 0, i32 0
           store i8 %.unpack, i8* %.fca.0.gep30, align 1
           %.fca.1.gep32 = getelementptr inbounds [3 x i8], [3 x i8]* %4, i32 0, i32 1
           store i8 %.unpack36, i8* %.fca.1.gep32, align 1
           %.fca.2.gep34 = getelementptr inbounds [3 x i8], [3 x i8]* %4, i32 0, i32 2
           store i8 %.unpack38, i8* %.fca.2.gep34, align 1
; ││││└└└└└
; ││││┌ @ broadcast.jl:621 within `_broadcast_getindex'
; │││││┌ @ broadcast.jl:648 within `_broadcast_getindex_evalf'
; ││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:11 within `lighten'
         %lcnt2 = load volatile i64, i64* inttoptr (i32 390202576 to i64*), align 16
         %12 = add i64 %lcnt2, 1
         store volatile i64 %12, i64* inttoptr (i32 390202576 to i64*), align 16
; │││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:8 within `_mapc'
          %lcnt3 = load volatile i64, i64* inttoptr (i32 390202552 to i64*), align 8
          %13 = add i64 %lcnt3, 1
          store volatile i64 %13, i64* inttoptr (i32 390202552 to i64*), align 8
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %14 = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %2, i32 0, i32 0, i32 0
; ││││││││└
; ││││││││┌ @ promotion.jl:421 within `max'
; │││││││││┌ @ int.jl:441 within `<'
            %15 = load i8, i8* %14, align 1
            %.not = icmp ult i8 %15, %.unpack
; │││││││││└
           %16 = select i1 %.not, i8 %.unpack, i8 %15
; ││││││││└
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %17 = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %2, i32 0, i32 0, i32 1
; ││││││││└
; ││││││││┌ @ promotion.jl:421 within `max'
; │││││││││┌ @ int.jl:441 within `<'
            %18 = load i8, i8* %17, align 1
            %.not50 = icmp ult i8 %18, %.unpack36
; │││││││││└
           %19 = select i1 %.not50, i8 %.unpack36, i8 %18
; ││││││││└
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %20 = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %2, i32 0, i32 0, i32 2
; ││││││││└
; ││││││││┌ @ promotion.jl:421 within `max'
; │││││││││┌ @ int.jl:441 within `<'
            %21 = load i8, i8* %20, align 1
            %.not51 = icmp ult i8 %21, %.unpack38
; │││││││││└
           %22 = select i1 %.not51, i8 %.unpack38, i8 %21
; ││││││││└
; ││││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:2 within `RGB8'
           %lcnt4 = load volatile i64, i64* inttoptr (i32 390202504 to i64*), align 8
           %23 = add i64 %lcnt4, 1
           store volatile i64 %23, i64* inttoptr (i32 390202504 to i64*), align 8
           %24 = getelementptr inbounds [3 x i8], [3 x i8]* %5, i32 0, i32 0
           store i8 %16, i8* %24, align 1
           %25 = getelementptr inbounds [3 x i8], [3 x i8]* %5, i32 0, i32 1
           store i8 %19, i8* %25, align 1
           %26 = getelementptr inbounds [3 x i8], [3 x i8]* %5, i32 0, i32 2
           store i8 %22, i8* %26, align 1
; ││││││└└└
; ││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:12 within `lighten'
         %lcnt5 = load volatile i64, i64* inttoptr (i32 390202584 to i64*), align 8
         %27 = add i64 %lcnt5, 1
         store volatile i64 %27, i64* inttoptr (i32 390202584 to i64*), align 8
         %28 = getelementptr inbounds [1 x double], [1 x double]* %6, i32 0, i32 0
         store double %3, double* %28, align 8
; ││││││└
; ││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:13 within `lighten'
         %lcnt6 = load volatile i64, i64* inttoptr (i32 390202592 to i64*), align 32
         %29 = add i64 %lcnt6, 1
         store volatile i64 %29, i64* inttoptr (i32 390202592 to i64*), align 32
         %30 = call [3 x i8] @j__mapc_226([1 x double]* nocapture readonly %6, [3 x i8]* nocapture readonly %4, [3 x i
8]* nocapture readonly %5) #0
         %.fca.0.extract20 = extractvalue [3 x i8] %30, 0
         %.fca.1.extract22 = extractvalue [3 x i8] %30, 1
         %.fca.2.extract24 = extractvalue [3 x i8] %30, 2
; ││││└└└
; ││││┌ @ broadcast.jl:620 within `_broadcast_getindex'
; │││││┌ @ broadcast.jl:644 within `_getindex'
; ││││││┌ @ broadcast.jl:595 within `_broadcast_getindex'
; │││││││┌ @ refvalue.jl:56 within `getindex'
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %.fca.0.gep = getelementptr inbounds [3 x i8], [3 x i8]* %7, i32 0, i32 0
           store i8 %.unpack, i8* %.fca.0.gep, align 1
           %.fca.1.gep = getelementptr inbounds [3 x i8], [3 x i8]* %7, i32 0, i32 1
           store i8 %.unpack36, i8* %.fca.1.gep, align 1
           %.fca.2.gep = getelementptr inbounds [3 x i8], [3 x i8]* %7, i32 0, i32 2
           store i8 %.unpack38, i8* %.fca.2.gep, align 1
; ││││└└└└└
; ││││┌ @ broadcast.jl:621 within `_broadcast_getindex'
; │││││┌ @ broadcast.jl:648 within `_broadcast_getindex_evalf'
; ││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:11 within `lighten'
         %lcnt7 = load volatile i64, i64* inttoptr (i32 390202576 to i64*), align 16
         %31 = add i64 %lcnt7, 1
         store volatile i64 %31, i64* inttoptr (i32 390202576 to i64*), align 16
; │││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:8 within `_mapc'
          %lcnt8 = load volatile i64, i64* inttoptr (i32 390202552 to i64*), align 8
          %32 = add i64 %lcnt8, 1
          store volatile i64 %32, i64* inttoptr (i32 390202552 to i64*), align 8
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %33 = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %2, i32 0, i32 1, i32 0
; ││││││││└
; ││││││││┌ @ promotion.jl:421 within `max'
; │││││││││┌ @ int.jl:441 within `<'
            %34 = load i8, i8* %33, align 1
            %.not58 = icmp ult i8 %34, %.unpack
; │││││││││└
           %35 = select i1 %.not58, i8 %.unpack, i8 %34
; ││││││││└
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %36 = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %2, i32 0, i32 1, i32 1
; ││││││││└
; ││││││││┌ @ promotion.jl:421 within `max'
; │││││││││┌ @ int.jl:441 within `<'
            %37 = load i8, i8* %36, align 1
            %.not59 = icmp ult i8 %37, %.unpack36
; │││││││││└
           %38 = select i1 %.not59, i8 %.unpack36, i8 %37
; ││││││││└
; ││││││││┌ @ Base.jl:33 within `getproperty'
           %39 = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %2, i32 0, i32 1, i32 2
; ││││││││└
; ││││││││┌ @ promotion.jl:421 within `max'
; │││││││││┌ @ int.jl:441 within `<'
            %40 = load i8, i8* %39, align 1
            %.not60 = icmp ult i8 %40, %.unpack38
; │││││││││└
           %41 = select i1 %.not60, i8 %.unpack38, i8 %40
; ││││││││└
; ││││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:2 within `RGB8'
           %lcnt9 = load volatile i64, i64* inttoptr (i32 390202504 to i64*), align 8
           %42 = add i64 %lcnt9, 1
           store volatile i64 %42, i64* inttoptr (i32 390202504 to i64*), align 8
           %43 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i32 0, i32 0
           store i8 %35, i8* %43, align 1
           %44 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i32 0, i32 1
           store i8 %38, i8* %44, align 1
           %45 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i32 0, i32 2
           store i8 %41, i8* %45, align 1
; ││││││└└└
; ││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:12 within `lighten'
         %lcnt10 = load volatile i64, i64* inttoptr (i32 390202584 to i64*), align 8
         %46 = add i64 %lcnt10, 1
         store volatile i64 %46, i64* inttoptr (i32 390202584 to i64*), align 8
         %47 = getelementptr inbounds [1 x double], [1 x double]* %9, i32 0, i32 0
         store double %3, double* %47, align 8
; ││││││└
; ││││││┌ @ C:\Users\username\.julia\dev\RanOutOfRegisters\test\runtests.jl:13 within `lighten'
         %lcnt11 = load volatile i64, i64* inttoptr (i32 390202592 to i64*), align 32
         %48 = add i64 %lcnt11, 1
         store volatile i64 %48, i64* inttoptr (i32 390202592 to i64*), align 32
         %49 = call [3 x i8] @j__mapc_227([1 x double]* nocapture readonly %9, [3 x i8]* nocapture readonly %7, [3 x i
8]* nocapture readonly %8) #0
         %.fca.0.extract = extractvalue [3 x i8] %49, 0
         %.fca.1.extract = extractvalue [3 x i8] %49, 1
         %.fca.2.extract = extractvalue [3 x i8] %49, 2
; └└└└└└└
  %.sroa.012.sroa.0.0..sroa.012.0..sroa_idx.sroa_idx = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %0, i32
0, i32 0, i32 0
  store i8 %.fca.0.extract20, i8* %.sroa.012.sroa.0.0..sroa.012.0..sroa_idx.sroa_idx, align 1
  %.sroa.012.sroa.2.0..sroa.012.0..sroa_idx.sroa_idx = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %0, i32
0, i32 0, i32 1
  store i8 %.fca.1.extract22, i8* %.sroa.012.sroa.2.0..sroa.012.0..sroa_idx.sroa_idx, align 1
  %.sroa.012.sroa.3.0..sroa.012.0..sroa_idx.sroa_idx = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %0, i32
0, i32 0, i32 2
  store i8 %.fca.2.extract24, i8* %.sroa.012.sroa.3.0..sroa.012.0..sroa_idx.sroa_idx, align 1
  %.sroa.215.0..sroa_idx = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %0, i32 0, i32 1, i32 0
  store i8 %.fca.0.extract, i8* %.sroa.215.0..sroa_idx, align 1
  %.sroa.316.0..sroa_idx = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %0, i32 0, i32 1, i32 1
  store i8 %.fca.1.extract, i8* %.sroa.316.0..sroa_idx, align 1
  %.sroa.4.0..sroa_idx = getelementptr inbounds [2 x [3 x i8]], [2 x [3 x i8]]* %0, i32 0, i32 1, i32 2
  store i8 %.fca.2.extract, i8* %.sroa.4.0..sroa_idx, align 1
  ret void
}
error: ran out of registers during register allocation
ERROR: Package RanOutOfRegisters errored during testing

This problem occurs in the following versions (on both Linux and Windows):

  • v1.5.4 (LLVM 9.0)
  • v1.6.2 (LLVM 11.0)
  • v1.7.0-beta4 (LLVM 12.0)
  • v1.8.0-DEV.498 (LLVM 12.0)

On the other hand, it does not seem to occur on x86-64 or 32-/64-bit ARM.

If you have difficulty preparing a 32-bit x86 environment, you can also use GitHub Actions to reproduce the error.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions