From fc2d9fedc2cc21f25608034518d75a8337301e9a Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Thu, 25 Aug 2022 15:01:27 -0700 Subject: [PATCH] Use getblockparamproxy with branch A common pattern when the block is an explicit parameter is to branch based on the block parameter instead of using `block_given?`, for example `block.call if block`. This commit checks in the peephole optimizer for that case and uses the getblockparamproxy optimization, which avoids allocating a proc for simple cases, whenever a getblockparam instruction is followed immediately by branchif or branchunless. ./miniruby --dump=insns -e 'def foo(&block); 123 if block; end' == disasm: # (catch: FALSE) local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1]) [ 1] block@0 0000 getblockparamproxy block@0, 0 ( 1)[LiCa] 0003 branchunless 8 0005 putobject 123 0007 leave [Re] 0008 putnil 0009 leave [Re] --- compile.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compile.c b/compile.c index 95318ffa84..4db1440bfa 100644 --- a/compile.c +++ b/compile.c @@ -3614,6 +3614,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } + if (IS_INSN_ID(iobj, getblockparam)) { + if (IS_NEXT_INSN_ID(&iobj->link, branchif) || IS_NEXT_INSN_ID(&iobj->link, branchunless)) { + iobj->insn_id = BIN(getblockparamproxy); + } + } + return COMPILE_OK; }