reactorlabs/rir

partially defined values cause boxing

開放

#788 建立於 2020年1月22日

 (1 則留言) (0 個反應) (0 位負責人)C++ (19 個分叉)github user discovery
backendhelp wanted

倉庫指標

星標
 (61 顆星)
PR 合併指標
 (平均合併 1分鐘) (30 天內合併 1 個 PR)

描述

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

貢獻者指南