Skip to content

Commit

Permalink
Remove alloca from codegen (#49186)
Browse files Browse the repository at this point in the history
Replace with SmallVector for better readability.
  • Loading branch information
pchintalapudi authored Apr 10, 2023
1 parent d0f4327 commit ea72b94
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 65 deletions.
12 changes: 6 additions & 6 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar
* type. Otherwise we pass a pointer to a jl_value_t.
*/
std::vector<llvm::Type*> argtypes;
Value **argvals = (Value**)alloca(nargt * sizeof(Value*));
SmallVector<Value *, 8> argvals(nargt);
for (size_t i = 0; i < nargt; ++i) {
jl_value_t *tti = jl_svecref(tt,i);
bool toboxed;
Expand Down Expand Up @@ -986,7 +986,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar
Function *decl = Function::Create(decl_typ, def->getLinkage(), def->getAddressSpace(),
def->getName(), jl_Module);
decl->setAttributes(def->getAttributes());
CallInst *inst = ctx.builder.CreateCall(decl, ArrayRef<Value *>(&argvals[0], nargt));
CallInst *inst = ctx.builder.CreateCall(decl, argvals);

// save the module to be linked later.
// we cannot do this right now, because linking mutates the destination module,
Expand Down Expand Up @@ -1399,7 +1399,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
#define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), StringRef(XSTR(name)))

// emit arguments
jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nccallargs);
SmallVector<jl_cgval_t, 4> argv(nccallargs);
for (size_t i = 0; i < nccallargs; i++) {
// Julia (expression) value of current parameter
jl_value_t *argi = ccallarg(i);
Expand Down Expand Up @@ -1897,7 +1897,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
jl_cgval_t retval = sig.emit_a_ccall(
ctx,
symarg,
argv,
argv.data(),
gc_uses,
static_rt);
JL_GC_POP();
Expand All @@ -1919,7 +1919,7 @@ jl_cgval_t function_sig_t::emit_a_ccall(

FunctionType *functype = this->functype(ctx.builder.getContext());

Value **argvals = (Value**) alloca((nccallargs + sret) * sizeof(Value*));
SmallVector<Value *, 8> argvals(nccallargs + sret);
for (size_t ai = 0; ai < nccallargs; ai++) {
// Current C function parameter
jl_cgval_t &arg = argv[ai];
Expand Down Expand Up @@ -2099,7 +2099,7 @@ jl_cgval_t function_sig_t::emit_a_ccall(
OperandBundleDef OpBundle("jl_roots", gc_uses);
// the actual call
CallInst *ret = ctx.builder.CreateCall(functype, llvmf,
ArrayRef<Value*>(&argvals[0], nccallargs + sret),
argvals,
ArrayRef<OperandBundleDef>(&OpBundle, gc_uses.empty() ? 0 : 1));
((CallInst*)ret)->setAttributes(attributes);

Expand Down
2 changes: 1 addition & 1 deletion src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2859,7 +2859,7 @@ static Value *emit_array_nd_index(
endBB = BasicBlock::Create(ctx.builder.getContext(), "idxend");
}
#endif
Value **idxs = (Value**)alloca(sizeof(Value*) * nidxs);
SmallVector<Value *> idxs(nidxs);
for (size_t k = 0; k < nidxs; k++) {
idxs[k] = emit_unbox(ctx, ctx.types().T_size, argv[k], (jl_value_t*)jl_long_type); // type asserted by caller
}
Expand Down
59 changes: 30 additions & 29 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2491,7 +2491,7 @@ static void cg_bdw(jl_codectx_t &ctx, jl_sym_t *var, jl_binding_t *b)
static jl_value_t *static_apply_type(jl_codectx_t &ctx, const jl_cgval_t *args, size_t nargs)
{
assert(nargs > 1);
jl_value_t **v = (jl_value_t**)alloca(sizeof(jl_value_t*) * nargs);
SmallVector<jl_value_t *> v(nargs);
for (size_t i = 0; i < nargs; i++) {
if (!args[i].constant)
return NULL;
Expand All @@ -2503,7 +2503,7 @@ static jl_value_t *static_apply_type(jl_codectx_t &ctx, const jl_cgval_t *args,
jl_current_task->world_age = 1;
jl_value_t *result;
JL_TRY {
result = jl_apply(v, nargs);
result = jl_apply(v.data(), nargs);
}
JL_CATCH {
result = NULL;
Expand Down Expand Up @@ -4101,9 +4101,9 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_method_instance_
*return_roots = returninfo.return_roots;

size_t nfargs = cft->getNumParams();
Value **argvals = (Value**)alloca(nfargs * sizeof(Value*));
SmallVector<Value *> argvals(nfargs);
unsigned idx = 0;
AllocaInst *result;
AllocaInst *result = nullptr;
switch (returninfo.cc) {
case jl_returninfo_t::Boxed:
case jl_returninfo_t::Register:
Expand Down Expand Up @@ -4180,7 +4180,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_method_instance_
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const);
callee = ai.decorateInst(ctx.builder.CreateAlignedLoad(callee->getType(), GV, Align(sizeof(void*))));
}
CallInst *call = ctx.builder.CreateCall(cft, callee, ArrayRef<Value*>(&argvals[0], nfargs));
CallInst *call = ctx.builder.CreateCall(cft, callee, argvals);
call->setAttributes(returninfo.decl->getAttributes());

jl_cgval_t retval;
Expand All @@ -4192,6 +4192,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_method_instance_
retval = mark_julia_type(ctx, call, false, jlretty);
break;
case jl_returninfo_t::SRet:
assert(result);
retval = mark_julia_slot(result, jlretty, NULL, ctx.tbaa().tbaa_stack);
break;
case jl_returninfo_t::Union: {
Expand Down Expand Up @@ -4254,13 +4255,13 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
assert(arglen >= 2);

jl_cgval_t lival = emit_expr(ctx, args[0]);
jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
SmallVector<jl_cgval_t> argv(nargs);
for (size_t i = 0; i < nargs; ++i) {
argv[i] = emit_expr(ctx, args[i + 1]);
if (argv[i].typ == jl_bottom_type)
return jl_cgval_t();
}
return emit_invoke(ctx, lival, argv, nargs, rt);
return emit_invoke(ctx, lival, argv.data(), nargs, rt);
}

static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const jl_cgval_t *argv, size_t nargs, jl_value_t *rt)
Expand Down Expand Up @@ -4375,7 +4376,7 @@ static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_
size_t nargs = arglen - 1;
assert(arglen >= 2);
jl_cgval_t lival = emit_expr(ctx, args[0]);
jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
SmallVector<jl_cgval_t> argv(nargs);
for (size_t i = 0; i < nargs; ++i) {
argv[i] = emit_expr(ctx, args[i + 1]);
if (argv[i].typ == jl_bottom_type)
Expand All @@ -4384,7 +4385,7 @@ static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_
const jl_cgval_t &f = argv[0];
jl_cgval_t ret;
if (f.constant && f.constant == jl_builtin_modifyfield) {
if (emit_f_opfield(ctx, &ret, jl_builtin_modifyfield, argv, nargs - 1, &lival))
if (emit_f_opfield(ctx, &ret, jl_builtin_modifyfield, argv.data(), nargs - 1, &lival))
return ret;
auto it = builtin_func_map().find(jl_f_modifyfield_addr);
assert(it != builtin_func_map().end());
Expand All @@ -4394,11 +4395,11 @@ static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_
if (f.constant && jl_typeis(f.constant, jl_intrinsic_type)) {
JL_I::intrinsic fi = (intrinsic)*(uint32_t*)jl_data_ptr(f.constant);
if (fi == JL_I::atomic_pointermodify && jl_intrinsic_nargs((int)fi) == nargs - 1)
return emit_atomic_pointerop(ctx, fi, argv, nargs - 1, &lival);
return emit_atomic_pointerop(ctx, fi, argv.data(), nargs - 1, &lival);
}

// emit function and arguments
Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, nargs, julia_call);
Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv.data(), nargs, julia_call);
return mark_julia_type(ctx, callval, true, rt);
}

Expand All @@ -4418,8 +4419,8 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt, bo
jl_value_t *context = ctx.params->generic_context == jl_nothing ? nullptr : ctx.params->generic_context;
size_t n_generic_args = nargs + (context ? 1 : 0);

jl_cgval_t *generic_argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * n_generic_args);
jl_cgval_t *argv = generic_argv;
SmallVector<jl_cgval_t> generic_argv(n_generic_args);
jl_cgval_t *argv = generic_argv.data();
if (context) {
generic_argv[0] = mark_julia_const(ctx, context);
argv = &generic_argv[1];
Expand Down Expand Up @@ -4449,7 +4450,7 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt, bo
}

// emit function and arguments
Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, generic_argv, n_generic_args, julia_call);
Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, generic_argv.data(), n_generic_args, julia_call);
return mark_julia_type(ctx, callval, true, rt);
}

Expand Down Expand Up @@ -5420,7 +5421,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
is_promotable = ctx.ssavalue_usecount.at(ssaidx_0based) == 1;
}
assert(nargs > 0);
jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
SmallVector<jl_cgval_t> argv(nargs);
for (size_t i = 0; i < nargs; ++i) {
argv[i] = emit_expr(ctx, args[i]);
}
Expand All @@ -5429,12 +5430,12 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
jl_is_datatype(jl_tparam0(ty)) &&
jl_is_concrete_type(jl_tparam0(ty))) {
assert(nargs <= jl_datatype_nfields(jl_tparam0(ty)) + 1);
jl_cgval_t res = emit_new_struct(ctx, jl_tparam0(ty), nargs - 1, &argv[1], is_promotable);
jl_cgval_t res = emit_new_struct(ctx, jl_tparam0(ty), nargs - 1, argv.data() + 1, is_promotable);
if (is_promotable && res.promotion_point && res.promotion_ssa==-1)
res.promotion_ssa = ssaidx_0based;
return res;
}
Value *val = emit_jlcall(ctx, jlnew_func, nullptr, argv, nargs, julia_call);
Value *val = emit_jlcall(ctx, jlnew_func, nullptr, argv.data(), nargs, julia_call);
// temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
// it to the inferred type.
return mark_julia_type(ctx, val, true, (jl_value_t*)jl_any_type);
Expand Down Expand Up @@ -5478,12 +5479,12 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
jl_tupletype_t *env_t = NULL;
JL_GC_PUSH2(&closure_t, &env_t);

jl_value_t **env_component_ts = (jl_value_t**)alloca(sizeof(jl_value_t*) * (nargs-4));
SmallVector<jl_value_t *> env_component_ts(nargs-4);
for (size_t i = 0; i < nargs - 4; ++i) {
env_component_ts[i] = argv[4+i].typ;
}

env_t = jl_apply_tuple_type_v(env_component_ts, nargs-4);
env_t = jl_apply_tuple_type_v(env_component_ts.data(), nargs-4);
// we need to know the full env type to look up the right specialization
if (jl_is_concrete_type((jl_value_t*)env_t)) {
jl_tupletype_t *argt_typ = (jl_tupletype_t*)argt.constant;
Expand Down Expand Up @@ -5565,7 +5566,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
return mark_julia_const(ctx, bounds_check_enabled(ctx, jl_true) ? jl_true : jl_false);
}
else if (head == jl_gc_preserve_begin_sym) {
jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
SmallVector<jl_cgval_t> argv(nargs);
for (size_t i = 0; i < nargs; ++i) {
argv[i] = emit_expr(ctx, args[i]);
}
Expand Down Expand Up @@ -5716,7 +5717,7 @@ static void emit_cfunc_invalidate(
allocate_gc_frame(ctx, b0);

Function::arg_iterator AI = gf_thunk->arg_begin();
jl_cgval_t *myargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
SmallVector<jl_cgval_t> myargs(nargs);
if (cc == jl_returninfo_t::SRet || cc == jl_returninfo_t::Union)
++AI;
if (return_roots)
Expand Down Expand Up @@ -5747,7 +5748,7 @@ static void emit_cfunc_invalidate(
}
}
assert(AI == gf_thunk->arg_end());
Value *gf_ret = emit_jlcall(ctx, target, nullptr, myargs, nargs, julia_call);
Value *gf_ret = emit_jlcall(ctx, target, nullptr, myargs.data(), nargs, julia_call);
jl_cgval_t gf_retbox = mark_julia_type(ctx, gf_ret, true, jl_any_type);
if (cc != jl_returninfo_t::Boxed) {
emit_typecheck(ctx, gf_retbox, rettype, "cfunction");
Expand Down Expand Up @@ -5977,7 +5978,7 @@ static Function* gen_cfun_wrapper(
Function::arg_iterator AI = cw->arg_begin();
Value *sretPtr = sig.sret ? &*AI++ : NULL;
Value *nestPtr = nest ? &*AI++ : NULL;
jl_cgval_t *inputargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * (nargs + 1));
SmallVector<jl_cgval_t> inputargs(nargs + 1);
if (ff) {
// we need to pass the function object even if (even though) it is a singleton
inputargs[0] = mark_julia_const(ctx, ff);
Expand Down Expand Up @@ -6168,7 +6169,7 @@ static Function* gen_cfun_wrapper(
ctx.builder.CreateBr(b_after);
ctx.builder.SetInsertPoint(b_generic);
}
Value *ret = emit_jlcall(ctx, jlapplygeneric_func, NULL, inputargs, nargs + 1, julia_call);
Value *ret = emit_jlcall(ctx, jlapplygeneric_func, NULL, inputargs.data(), nargs + 1, julia_call);
if (age_ok) {
ctx.builder.CreateBr(b_after);
ctx.builder.SetInsertPoint(b_after);
Expand Down Expand Up @@ -6608,7 +6609,7 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret
// TODO: replace this with emit_call_specfun_other?
FunctionType *ftype = f.decl->getFunctionType();
size_t nfargs = ftype->getNumParams();
Value **args = (Value**) alloca(nfargs * sizeof(Value*));
SmallVector<Value *> args(nfargs);
unsigned idx = 0;
AllocaInst *result = NULL;
switch (f.cc) {
Expand Down Expand Up @@ -6665,7 +6666,7 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret
args[idx] = theArg;
idx++;
}
CallInst *call = ctx.builder.CreateCall(f.decl, ArrayRef<Value*>(&args[0], nfargs));
CallInst *call = ctx.builder.CreateCall(f.decl, args);
call->setAttributes(f.decl->getAttributes());

jl_cgval_t retval;
Expand Down Expand Up @@ -7594,20 +7595,20 @@ static jl_llvm_functions_t
}
else if (specsig) {
ctx.nvargs = jl_nparams(lam->specTypes) - nreq;
jl_cgval_t *vargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * ctx.nvargs);
SmallVector<jl_cgval_t> vargs(ctx.nvargs);
for (size_t i = nreq; i < jl_nparams(lam->specTypes); ++i) {
jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i);
bool isboxed = deserves_argbox(argType);
Type *llvmArgType = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, argType);
vargs[i - nreq] = get_specsig_arg(argType, llvmArgType, isboxed);
}
if (jl_is_concrete_type(vi.value.typ)) {
jl_cgval_t tuple = emit_new_struct(ctx, vi.value.typ, ctx.nvargs, vargs);
jl_cgval_t tuple = emit_new_struct(ctx, vi.value.typ, ctx.nvargs, vargs.data());
emit_varinfo_assign(ctx, vi, tuple);
}
else {
restTuple = emit_jlcall(ctx, jltuple_func, Constant::getNullValue(ctx.types().T_prjlvalue),
vargs, ctx.nvargs, julia_call);
vargs.data(), ctx.nvargs, julia_call);
jl_cgval_t tuple = mark_julia_type(ctx, restTuple, true, vi.value.typ);
emit_varinfo_assign(ctx, vi, tuple);
}
Expand Down
Loading

2 comments on commit ea72b94

@vtjnash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here.

Please sign in to comment.