backendhelp wanted
Repository metrics
- Stars
- (61 個のスター)
- PR merge metrics
- (平均マージ 1m) (30d で 1 merged 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
ait is used as a variable:
if (!%1.1) error("missing object a")
- when
ais used to create an env:
MKEnv a= (%1.1 ? %1.0 : unboundValue)
2. In the native backend
- Compile any
T|_to aTinstead, initialize it with undef. - Keep a bitset that remembers which of those are initialized
- Automatically insert the above checks when such a variable is accessed