reactorlabs/rir

partially defined values cause boxing

Open

#788 opened on Jan 22, 2020

 (1 comment) (0 reactions) (0 assignees)C++ (19 forks)github user discovery
backendhelp wanted

Repository metrics

Stars
 (61 stars)
PR merge metrics
 (Avg merge 1m) (1 merged PR in 30d)

Description

Reproduce

First disable loop peeling (rir/src/ir/Compiler.cpp Compiler::loopPeelingEnabled) Then run the following code:

f = function(u) {
  for (i in 1:10) {
    1+u  # this causes speculation (and a deopt)
    a=1  # this declares a
  }
}

# call with non-reflective, but not trivial promise
a=1
f(a)
f(a)
f(a)

with PIR_DEBUG=PrintPirAfterOpt bin/R

Issue

The variable a is captured by the deopt point. But in the first iteration it is uninitialized. This causes us to have the variable as:

(real|_)"       %1.0  = Phi                      unboundValue:BB0, %0.1:BB3

First of all, the type inference seems to drop the scalar flag $, but even worse, the type of unboundValue (ie. _) is represented as a boxed value in the native backend (rir/src/compiler/native/lower_llvm.cpp). Therefore the real will also be boxed.

Solutions

I see two solutions:

1. At the PIR level

Have a PIR pass that does sth like:

real$       %1.0  = Phi                      undefined:BB0, %0.1:BB3
t           %1.1  = Phi                      TRUE:BB0,      FALSE:BB3

and then (using pseudo PIR code)

  • when a it is used as a variable:
if (!%1.1) error("missing object a")
  • when a is used to create an env:
MKEnv                    a= (%1.1 ? %1.0 : unboundValue)

2. In the native backend

  1. Compile any T|_ to a T instead, initialize it with undef.
  2. Keep a bitset that remembers which of those are initialized
  3. Automatically insert the above checks when such a variable is accessed

Contributor guide