reactorlabs/rir

partially defined values cause boxing

Ouverte

#788 ouverte le 22 janv. 2020

 (1 commentaire) (0 réaction) (0 personne assignée)C++ (19 forks)github user discovery
backendhelp wanted

Métriques du dépôt

Stars
 (61 étoiles)
Métriques de merge PR
 (Merge moyen 1m) (1 PR mergée en 30 j)

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

Guide contributeur