Skip to content

Commit

Permalink
Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@Iv)
Browse files Browse the repository at this point in the history
Due to how the compiler works, while f(*a, &lvar) and f(*a, &@Iv)
do not allocate an array, but f(1, *a, &lvar) and f(1, *a, &@Iv)
do.  It's probably possible to fix this in the compiler, but
seems easiest to fix this in the peephole optimizer.

Eliminating this array allocation is as safe as the current
elimination of the array allocation for f(*a, &lvar) and
f(*a, &@Iv).
  • Loading branch information
jeremyevans committed Dec 7, 2023
1 parent 40a2afd commit c70c1d2
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions compile.c
Expand Up @@ -3854,6 +3854,30 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
if ((flag & VM_CALL_ARGS_SPLAT) && !(flag & (VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG))) {
OPERAND_AT(iobj, 0) = Qfalse;
}
} else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) {
niobj = niobj->next;

if (IS_NEXT_INSN_ID(niobj, send)) {
niobj = niobj->next;
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));

if ((flag & VM_CALL_ARGS_SPLAT)) {
/*
* Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv)
*
* splatarray true
* getlocal / getinstancevariable
* send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
* =>
* splatarray false
* getlocal / getinstancevariable
* send
*/
if ((flag & VM_CALL_ARGS_BLOCKARG) && !(flag & VM_CALL_KW_SPLAT)) {
OPERAND_AT(iobj, 0) = Qfalse;
}
}
}
}
}

Expand Down

0 comments on commit c70c1d2

Please sign in to comment.