[DTrace-devel] [PATCH 01/10] Reduce register pressure in substr()
Eugene Loh
eugene.loh at oracle.com
Sat Mar 19 22:25:24 UTC 2022
On 3/18/22 6:54 PM, Kris Van Hees wrote:
> On Fri, Mar 18, 2022 at 04:30:13PM -0400, Eugene Loh via DTrace-devel wrote:
>> On 3/18/22 3:04 PM, Kris Van Hees via DTrace-devel wrote:
>>> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
>>> + emit(dlp, BPF_MOV_REG(BPF_REG_2, str->dn_reg));
>>> dt_regset_free(drp, str->dn_reg);
>>> dt_cg_tstring_free(yypcb, str);
>>> - emit(dlp, BPF_MOV_REG(BPF_REG_3, idx->dn_reg));
>>> + emit(dlp, BPF_MOV_REG(BPF_REG_3, idx->dn_reg));
>>> dt_regset_free(drp, idx->dn_reg);
>>> if (cnt != NULL) {
>>> emit(dlp, BPF_MOV_REG(BPF_REG_4, cnt->dn_reg));
>>> @@ -4030,8 +4024,17 @@ dt_cg_subr_substr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>>> idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_substr");
>>> assert(idp != NULL);
>>> emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
>>> - dt_regset_free_args(drp);
>>> +
>>> + /*
>>> + * Allocate the result register, and assign the result to it..
>>> + */
>>> + dnp->dn_reg = dt_regset_alloc(drp);
>>> + if (dnp->dn_reg == -1)
>>> + longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
>>> +
>>> + emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
>>> dt_regset_free(drp, BPF_REG_0);
>>> + dt_regset_free_args(drp);
>> I think the dt_regset_free_args(drp) call should remain tight up against the
>> BPF_CALL_FUNC(). After all, as soon as that function call is made, the regs
>> are toast. Or, say dnp->dn_reg is assigned one of %r1-%r5 and therefore
>> spills that register. (Does that cause the BPF verifier to complain?) Then
>> we free_args() and fill the register, overwriting what was just there.
> We should be avoiding crossing lines with alloc/free of registers,
Why? This isn't a stack/LIFO situation.
Further, we do this all the time. E.g., we alloc regs for the func
call, then we alloc dnp->dn_reg, then we free the func-call regs, and
later we will free dnp->dn_reg. We do this sort of thing routinely.
Also, what about the scenario I raised? E.g., let's say dnp->dn_reg is
assigned %r5. After all, the situation is that we are facing register
pressure. So:
*) alloc %r1-%r5
*) alloc %r0
*) call func (%r0 is given a value while %r1-%r5 are clobbered)
*) alloc dnp->dn_reg, getting %r5, whose clobbered value is spilled to
stack
*) %r5 = %r0
*) free %r0
*) free %r1-%r5, filling %r5 (dnp->dn_reg) with the clobbered value
> so if we
> alloc the args first and then %r0, we should free %r0 first, and then the args.
More information about the DTrace-devel
mailing list