Skip to content

Commit fe30ea7

Browse files
authored
Rir proms (#1064)
Speculatively inline promise code for builtins in RIR.
1 parent 41fd119 commit fe30ea7

File tree

12 files changed

+156
-21
lines changed

12 files changed

+156
-21
lines changed

.vscode/c_cpp_properties.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
"${workspaceFolder}/external/llvm-11/include/**",
99
"${workspaceFolder}/external/llvm-11.0.1.src/include/**"
1010
],
11-
"defines": ["ENABLE_SLOWASSERT"],
11+
"defines": [
12+
"ENABLE_SLOWASSERT"
13+
],
1214
"compilerPath": "/usr/bin/g++-8",
1315
"cStandard": "c11",
1416
"cppStandard": "c++14",
15-
"intelliSenseMode": "gcc-x64"
17+
"intelliSenseMode": "gcc-x64",
18+
"compileCommands": "${workspaceFolder}/build/debug/compile_commands.json"
1619
}
1720
],
1821
"version": 4
19-
}
22+
}

rir/src/compiler/native/lower_function_llvm.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ void LowerFunctionLLVM::insn_assert(llvm::Value* v, const char* msg,
188188

189189
builder.CreateUnreachable();
190190
builder.SetInsertPoint(ok);
191+
192+
191193
}
192194

193195
llvm::Value* LowerFunctionLLVM::constant(SEXP co, llvm::Type* needed) {
@@ -5355,6 +5357,7 @@ void LowerFunctionLLVM::compile() {
53555357
ensureNamed(val);
53565358
envStubSet(e, idx, val, environment->nLocals(),
53575359
!st->isStArg);
5360+
53585361
}
53595362

53605363
builder.CreateBr(done);

rir/src/compiler/native/pass_schedule_llvm.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "llvm/Transforms/Utils.h"
1818
#include "llvm/Transforms/Vectorize.h"
1919

20+
#include "llvm/Support/raw_os_ostream.h"
21+
#include <iostream>
22+
2023
namespace rir {
2124
namespace pir {
2225

@@ -43,6 +46,7 @@ operator()(llvm::orc::ThreadSafeModule TSM,
4346
verify();
4447

4548
#endif
49+
4650
});
4751
return std::move(TSM);
4852
}

rir/src/compiler/rir2pir/rir2pir.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,11 +384,21 @@ bool Rir2Pir::compileBC(const BC& bc, Opcode* pos, Opcode* nextPos,
384384
insert(new Visible());
385385
auto fs = inlining() ? (Value*)Tombstone::framestate()
386386
: insert.registerFrameState(srcCode, nextPos,
387+
387388
stack, inPromise());
388389
push(insert(new Force(v, env, fs)));
389390
break;
390391
}
391392

393+
case Opcode::ldvar_noforce_: {
394+
if (bc.immediateConst() == symbol::c)
395+
compiler.seenC = true;
396+
v = insert(new LdVar(bc.immediateConst(), env));
397+
398+
push(v);
399+
break;
400+
}
401+
392402
case Opcode::stvar_:
393403
case Opcode::stvar_cached_:
394404
if (bc.immediateConst() == symbol::c)

rir/src/interpreter/interp.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,34 @@ SEXP evalRirCode(Code* c, InterpreterInstance* ctx, SEXP env,
21862186
NEXT();
21872187
}
21882188

2189+
INSTRUCTION(ldvar_noforce_) {
2190+
SEXP sym = readConst(ctx, readImmediate());
2191+
advanceImmediate();
2192+
assert(!LazyEnvironment::check(env));
2193+
res = Rf_findVar(sym, env);
2194+
R_Visible = TRUE;
2195+
2196+
if (res == R_UnboundValue) {
2197+
Rf_error("object \"%s\" not found", CHAR(PRINTNAME(sym)));
2198+
} else if (res == R_MissingArg) {
2199+
Rf_error("argument \"%s\" is missing, with no default",
2200+
CHAR(PRINTNAME(sym)));
2201+
} else if (TYPEOF(res) == PROMSXP) {
2202+
// if already evaluated, return the value
2203+
if (PRVALUE(res) && PRVALUE(res) != R_UnboundValue) {
2204+
res = PRVALUE(res);
2205+
assert(TYPEOF(res) != PROMSXP);
2206+
2207+
if (res != R_NilValue)
2208+
ENSURE_NAMED(res);
2209+
}
2210+
}
2211+
2212+
ostack_push(ctx, res);
2213+
NEXT();
2214+
}
2215+
2216+
21892217
INSTRUCTION(ldvar_cached_) {
21902218
Immediate id = readImmediate();
21912219
advanceImmediate();

rir/src/ir/BC.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void BC::write(CodeStream& cs) const {
4646
case Opcode::ldfun_:
4747
case Opcode::ldddvar_:
4848
case Opcode::ldvar_:
49+
case Opcode::ldvar_noforce_:
4950
case Opcode::ldvar_for_update_:
5051
case Opcode::ldvar_super_:
5152
case Opcode::stvar_:
@@ -134,6 +135,7 @@ void BC::deserialize(SEXP refTable, R_inpstream_t inp, Opcode* code,
134135
case Opcode::ldfun_:
135136
case Opcode::ldddvar_:
136137
case Opcode::ldvar_:
138+
case Opcode::ldvar_noforce_:
137139
case Opcode::ldvar_for_update_:
138140
case Opcode::ldvar_super_:
139141
case Opcode::stvar_:
@@ -229,6 +231,7 @@ void BC::serialize(SEXP refTable, R_outpstream_t out, const Opcode* code,
229231
case Opcode::ldfun_:
230232
case Opcode::ldddvar_:
231233
case Opcode::ldvar_:
234+
case Opcode::ldvar_noforce_:
232235
case Opcode::ldvar_for_update_:
233236
case Opcode::ldvar_super_:
234237
case Opcode::stvar_:
@@ -373,6 +376,7 @@ void BC::print(std::ostream& out) const {
373376
break;
374377
case Opcode::ldfun_:
375378
case Opcode::ldvar_:
379+
case Opcode::ldvar_noforce_:
376380
case Opcode::ldvar_for_update_:
377381
case Opcode::ldvar_super_:
378382
case Opcode::ldddvar_:

rir/src/ir/BC.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ BC BC::ldvar(SEXP sym) {
7272
i.pool = Pool::insert(sym);
7373
return BC(Opcode::ldvar_, i);
7474
}
75+
76+
BC BC::ldvarNoForce(SEXP sym) {
77+
assert(TYPEOF(sym) == SYMSXP);
78+
assert(strlen(CHAR(PRINTNAME(sym))));
79+
ImmediateArguments i;
80+
i.pool = Pool::insert(sym);
81+
return BC(Opcode::ldvar_noforce_, i);
82+
}
83+
7584
BC BC::ldvarCached(SEXP sym, uint32_t cacheSlot) {
7685
assert(TYPEOF(sym) == SYMSXP);
7786
assert(strlen(CHAR(PRINTNAME(sym))));

rir/src/ir/BC_inc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ BC_NOARGS(V, _)
326326
inline static BC push_code(FunIdx i);
327327
inline static BC ldfun(SEXP sym);
328328
inline static BC ldvar(SEXP sym);
329+
inline static BC ldvarNoForce(SEXP sym);
329330
inline static BC ldvarCached(SEXP sym, uint32_t cacheSlot);
330331
inline static BC ldvarForUpdateCached(SEXP sym, uint32_t cacheSlot);
331332
inline static BC ldvarForUpdate(SEXP sym);
@@ -552,6 +553,7 @@ BC_NOARGS(V, _)
552553
case Opcode::push_:
553554
case Opcode::ldfun_:
554555
case Opcode::ldvar_:
556+
case Opcode::ldvar_noforce_:
555557
case Opcode::ldvar_super_:
556558
case Opcode::ldddvar_:
557559
case Opcode::stvar_:

rir/src/ir/CodeVerifier.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static Sources hasSources(Opcode bc) {
110110
case Opcode::ldfun_:
111111
case Opcode::ldddvar_:
112112
case Opcode::ldvar_:
113+
case Opcode::ldvar_noforce_:
113114
case Opcode::ldvar_cached_:
114115
case Opcode::ldvar_for_update_cache_:
115116
case Opcode::ldvar_for_update_:
@@ -290,7 +291,8 @@ void CodeVerifier::verifyFunctionLayout(SEXP sexp, InterpreterInstance* ctx) {
290291
Rf_error("RIR Verifier: Branch outside closure");
291292
}
292293
if (*cptr == Opcode::ldvar_ || *cptr == Opcode::ldvar_super_ ||
293-
*cptr == Opcode::ldvar_for_update_) {
294+
*cptr == Opcode::ldvar_for_update_ ||
295+
*cptr == Opcode::ldvar_noforce_) {
294296
unsigned* argsIndex = reinterpret_cast<Immediate*>(cptr + 1);
295297
if (*argsIndex >= cp_pool_length(ctx))
296298
Rf_error("RIR Verifier: Invalid arglist index");

rir/src/ir/Compiler.cpp

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ class CompilerContext {
110110
.first->second;
111111
}
112112
virtual bool loopIsLocal() { return !loops.empty(); }
113+
virtual bool isPromiseContext() { return false; }
113114
};
114115

115116
class PromiseContext : public CodeContext {
117+
116118
public:
117119
PromiseContext(SEXP ast, FunctionWriter& fun, CodeContext* p)
118120
: CodeContext(ast, fun, p) {}
@@ -123,6 +125,8 @@ class CompilerContext {
123125
}
124126
return true;
125127
}
128+
129+
bool isPromiseContext() override { return true; }
126130
};
127131

128132
std::stack<CodeContext*> code;
@@ -163,13 +167,19 @@ class CompilerContext {
163167
new CodeContext(ast, fun, code.empty() ? nullptr : code.top()));
164168
}
165169

170+
bool isInPromise() { return pushedPromiseContexts > 0; }
171+
166172
void pushPromiseContext(SEXP ast) {
173+
pushedPromiseContexts++;
174+
167175
code.push(
168176
new PromiseContext(ast, fun, code.empty() ? nullptr : code.top()));
169177
}
170178

171179
Code* pop() {
172180
Code* res = cs().finalize(0, code.top()->loadsSlotInCache.size());
181+
if (code.top()->isPromiseContext())
182+
pushedPromiseContexts--;
173183
delete code.top();
174184
code.pop();
175185
return res;
@@ -184,6 +194,9 @@ class CompilerContext {
184194
<< BC::push(R_FalseValue) << BC::push(Rf_mkString(msg))
185195
<< BC::callBuiltin(4, ast, getBuiltinFun("warning")) << BC::pop();
186196
}
197+
198+
private:
199+
unsigned int pushedPromiseContexts = 0;
187200
};
188201

189202
struct LoadArgsResult {
@@ -1751,19 +1764,55 @@ static LoadArgsResult compileLoadArgs(CompilerContext& ctx, SEXP ast, SEXP fun,
17511764
return res;
17521765
}
17531766

1767+
17541768
// function application
17551769
void compileCall(CompilerContext& ctx, SEXP ast, SEXP fun, SEXP args,
17561770
bool voidContext) {
1771+
17571772
CodeStream& cs = ctx.cs();
17581773

17591774
// application has the form:
17601775
// LHS ( ARGS )
17611776

17621777
// LHS can either be an identifier or an expression
1778+
bool speculateOnBuiltin = false;
1779+
BC::Label eager = 0;
1780+
BC::Label theEnd = 0;
1781+
17631782
if (TYPEOF(fun) == SYMSXP) {
17641783
if (compileSpecialCall(ctx, ast, fun, args, voidContext))
17651784
return;
17661785

1786+
if (!ctx.isInPromise()) {
1787+
1788+
auto callHasDots = false;
1789+
for (RListIter arg = RList(args).begin(); arg != RList::end();
1790+
++arg) {
1791+
1792+
if (*arg == R_DotsSymbol) {
1793+
callHasDots = true;
1794+
break;
1795+
}
1796+
}
1797+
1798+
if (!callHasDots) {
1799+
auto builtin = Rf_findVar(fun, R_BaseEnv);
1800+
auto likelyBuiltin = TYPEOF(builtin) == BUILTINSXP;
1801+
speculateOnBuiltin = likelyBuiltin;
1802+
1803+
if (speculateOnBuiltin) {
1804+
1805+
eager = cs.mkLabel();
1806+
theEnd = cs.mkLabel();
1807+
cs << BC::push(builtin) << BC::dup()
1808+
<< BC::ldvarNoForce(fun) << BC::identicalNoforce()
1809+
<< BC::recordTest() << BC::brtrue(eager);
1810+
1811+
cs << BC::pop();
1812+
}
1813+
}
1814+
}
1815+
17671816
cs << BC::ldfun(fun);
17681817
} else {
17691818
compileExpr(ctx, fun);
@@ -1773,22 +1822,37 @@ void compileCall(CompilerContext& ctx, SEXP ast, SEXP fun, SEXP args,
17731822
if (Compiler::profile)
17741823
cs << BC::recordCall();
17751824

1825+
auto compileCall = [&](LoadArgsResult& info) {
1826+
if (info.hasDots) {
1827+
cs << BC::callDots(info.numArgs, info.names, ast, info.assumptions);
1828+
} else if (info.hasNames) {
1829+
cs << BC::call(info.numArgs, info.names, ast, info.assumptions);
1830+
} else {
1831+
info.assumptions.add(Assumption::CorrectOrderOfArguments);
1832+
cs << BC::call(info.numArgs, ast, info.assumptions);
1833+
}
1834+
};
1835+
17761836
LoadArgsResult info;
17771837
if (fun == symbol::forceAndCall) {
17781838
// First arg certainly eager
17791839
info = compileLoadArgs(ctx, ast, fun, args, voidContext, 0, 2);
17801840
} else {
17811841
info = compileLoadArgs(ctx, ast, fun, args, voidContext);
17821842
}
1843+
compileCall(info);
17831844

1784-
if (info.hasDots) {
1785-
cs << BC::callDots(info.numArgs, info.names, ast, info.assumptions);
1786-
} else if (info.hasNames) {
1787-
cs << BC::call(info.numArgs, info.names, ast, info.assumptions);
1788-
} else {
1789-
info.assumptions.add(Assumption::CorrectOrderOfArguments);
1790-
cs << BC::call(info.numArgs, ast, info.assumptions);
1845+
if (speculateOnBuiltin) {
1846+
cs << BC::br(theEnd) << eager;
1847+
1848+
auto infoEager = compileLoadArgs(ctx, ast, fun, args, voidContext, 0,
1849+
RList(args).length());
1850+
1851+
compileCall(infoEager);
1852+
1853+
cs << theEnd;
17911854
}
1855+
17921856
if (voidContext)
17931857
cs << BC::pop();
17941858
else if (Compiler::profile)

0 commit comments

Comments
 (0)