Skip to content

Commit ef13941

Browse files
committed
Perl_rpeep: Fix empty else {} optimization in OP_COND_EXPR case
Until `else` blocks were subject to the same block scoping rules as `if` and `elsif`, an empty `else` block or ternary condition would arrive at the peephole optimizer as a bare stub OP: +--null (ex-stub) OP(0x562e555a7310) FLAGS = (...,PARENS,SLABBED) Now, it could arrive in that form OR as a SCOPE + NULL: scope LISTOP(0x5603b282b190) PARENT ===> 3 [cond_expr 0x5603b282b770] FLAGS = (VOID,KIDS,SLABBED) | +--null (ex-stub) OP(0x5603b282b350) ===> 1 [scope 0x5603b282b190] FLAGS = (VOID,SLABBED) This commit updates the "empty else" optimization on `OP_COND_EXPR`s so that the OPs associated with empty "else" conditions are removed (when not in scalar context) regardless of which form they arrive in.
1 parent 2f42d3c commit ef13941

File tree

2 files changed

+23
-32
lines changed

2 files changed

+23
-32
lines changed

op.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4552,6 +4552,13 @@ Perl_op_scope(pTHX_ OP *o)
45524552
kid = OpSIBLING(kid);
45534553
if (kid && OP_TYPE_IS_COP_NN(kid))
45544554
op_null(kid);
4555+
} else if (OP_TYPE_IS(kid, OP_STUB)) {
4556+
OP *sib = OpSIBLING(kid);
4557+
if (OP_TYPE_IS(sib, OP_NULL) && !OpSIBLING(sib) &&
4558+
!(sib->op_flags & OPf_KIDS)) {
4559+
op_sibling_splice(o,kid,1,NULL);
4560+
op_free(sib);
4561+
}
45554562
}
45564563
}
45574564
else

peep.c

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,10 +3645,10 @@ Perl_rpeep(pTHX_ OP *o)
36453645
/* Is there an empty "else" block or ternary false branch?
36463646
If so, optimise away the OP_STUB if safe to do so. */
36473647
stub = o->op_next;
3648-
if ((stub->op_flags & OPf_WANT) != OPf_WANT_SCALAR) {
3648+
if ((stub == falseop) && (stub->op_flags & OPf_WANT) != OPf_WANT_SCALAR) {
36493649
if (stub->op_type == OP_STUB && !OpSIBLING(stub) ){
36503650
OP *stubsib = OpSIBLING(stub);
3651-
if ((stub == falseop) && !stubsib) {
3651+
if (!stubsib) {
36523652
/* cond_expr
36533653
* -condition-
36543654
* - if -
@@ -3659,41 +3659,25 @@ Perl_rpeep(pTHX_ OP *o)
36593659
o->op_next = stub->op_next;
36603660
op_sibling_splice(o, OpSIBLING(cLOGOP->op_first), 1, NULL);
36613661
op_free(stub);
3662+
}
36623663
} else { /* Unexpected */ }
3663-
} else if (OP_TYPE_IS(stub,OP_ENTER) &&
3664-
OP_TYPE_IS(falseop, OP_LEAVE)) {
3665-
OP *enter = stub;
3666-
OP *stub = OpSIBLING(enter);
3667-
if (stub && OP_TYPE_IS(stub, OP_STUB) ){
3668-
assert(!(stub->op_flags & OPf_KIDS));
3669-
OP *stubsib = OpSIBLING(stub);
3670-
assert(stubsib);
3671-
if (OP_TYPE_IS(stubsib, OP_NULL) &&
3672-
!OpSIBLING(stubsib) &&
3673-
!(stubsib->op_flags & OPf_KIDS) ) {
3674-
/* cond_expr
3675-
* -condition-
3676-
* - if -
3677-
* leave
3678-
* enter
3679-
* stub
3680-
* null
3681-
*/
3682-
/* Ignoring it for now, pending further exploration.*/
3683-
/*
3684-
o->op_flags |= OPf_SPECIAL; // For B::Deparse
3664+
} else if (OP_TYPE_IS(falseop,OP_SCOPE) &&
3665+
(falseop->op_flags & OPf_KIDS)) {
3666+
OP* stub = cLISTOPx(falseop)->op_first;
3667+
if (OP_TYPE_IS_OR_WAS(stub, OP_STUB) && !OpSIBLING(stub)) {
3668+
assert(o->op_next != falseop);
3669+
assert(!(stub->op_flags & OPf_KIDS));
3670+
o->op_flags |= OPf_SPECIAL; /* For B::Deparse */
3671+
op_sibling_splice(o, OpSIBLING(cLOGOP->op_first), 1, NULL);
3672+
if (o->op_next == stub) {
3673+
if (stub->op_next == falseop)
36853674
o->op_next = falseop->op_next;
3686-
op_sibling_splice(o, OpSIBLING(cLOGOP->op_first), 1, NULL);
3687-
op_free(enter);
3688-
op_free(stub);
3689-
op_free(stubsib);
3690-
op_free(falseop);
3691-
*/
3692-
}
3675+
else
3676+
o->op_next = stub->op_next;
36933677
}
3678+
op_free(falseop);
36943679
}
36953680
}
3696-
36973681
}
36983682
/* FALLTHROUGH */
36993683
case OP_MAPWHILE:

0 commit comments

Comments
 (0)