@@ -3590,41 +3590,110 @@ Perl_rpeep(pTHX_ OP *o)
35903590 case OP_COND_EXPR :
35913591 if (o -> op_type == OP_COND_EXPR ) {
35923592 OP * stub = cLOGOP -> op_other ;
3593+ OP * trueop = OpSIBLING ( cLOGOP -> op_first );
3594+ OP * falseop = OpSIBLING (trueop );
3595+
35933596 /* Is there an empty "if" block or ternary true branch?
35943597 If so, optimise away the OP_STUB if safe to do so. */
35953598 if (stub -> op_type == OP_STUB &&
35963599 ((stub -> op_flags & OPf_WANT ) != OPf_WANT_SCALAR )
35973600 ) {
3598- OP * trueop = OpSIBLING ( cLOGOP -> op_first );
3599-
3600- assert ((stub == trueop ) || (OP_TYPE_IS (trueop , OP_SCOPE ) &&
3601- ((stub == cUNOPx (trueop )-> op_first )) && !OpSIBLING (stub ))
3602- );
3603- assert (!(stub -> op_flags & OPf_KIDS ));
3604-
3605- cLOGOP -> op_other = (stub -> op_next == trueop ) ?
3606- stub -> op_next -> op_next :
3607- stub -> op_next ;
3608-
3609- op_sibling_splice (o , cLOGOP -> op_first , 1 , NULL );
3610-
3611- if (stub != trueop ) op_free (stub );
3612- op_free (trueop );
3613- } else
3601+ if (stub == trueop ) {
3602+ /* This is very unlikely:
3603+ * cond_expr
3604+ * -condition-
3605+ * stub
3606+ * -else-
3607+ */
3608+ assert (!(stub -> op_flags & OPf_KIDS ));
3609+ cLOGOP -> op_other = stub -> op_next ;
3610+ op_sibling_splice (o , cLOGOP -> op_first , 1 , NULL );
3611+ op_free (stub );
3612+ break ;
3613+ } else if (OP_TYPE_IS (trueop , OP_SCOPE ) &&
3614+ (stub == cUNOPx (trueop )-> op_first ) ) {
3615+ assert (!(stub -> op_flags & OPf_KIDS ));
3616+
3617+ OP * stubsib = OpSIBLING (stub );
3618+ if (!stubsib ) {
3619+ /* cond_expr
3620+ * -condition-
3621+ * scope
3622+ * stub
3623+ * -else-
3624+ */
3625+ cLOGOP -> op_other = trueop -> op_next ;
3626+ op_sibling_splice (o , cLOGOP -> op_first , 1 , NULL );
3627+ op_free (stub );
3628+ op_free (trueop );
3629+ break ;
3630+ } else {
3631+ /* Could be something like this:
3632+ * -condition-
3633+ * scope
3634+ * stub
3635+ * null
3636+ * -else-
3637+ * But it may be more desirable (but is less
3638+ * straightforward) to transform this earlier
3639+ * in the compiler. Ignoring it for now,
3640+ * pending further exploration. */
3641+ }
3642+ }
3643+ }
36143644
36153645 /* Is there an empty "else" block or ternary false branch?
36163646 If so, optimise away the OP_STUB if safe to do so. */
36173647 stub = o -> op_next ;
3618- if (stub -> op_type == OP_STUB &&
3619- ((stub -> op_flags & OPf_WANT ) != OPf_WANT_SCALAR )
3620- ) {
3621- assert (stub == OpSIBLING (OpSIBLING ( cLOGOP -> op_first )));
3622- assert (!(stub -> op_flags & OPf_KIDS ));
3623- o -> op_flags |= OPf_SPECIAL ; /* For B::Deparse */
3624- o -> op_next = stub -> op_next ;
3625- op_sibling_splice (o , OpSIBLING (cLOGOP -> op_first ), 1 , NULL );
3626- op_free (stub );
3648+ if ((stub -> op_flags & OPf_WANT ) != OPf_WANT_SCALAR ) {
3649+ if (stub -> op_type == OP_STUB && !OpSIBLING (stub ) ){
3650+ OP * stubsib = OpSIBLING (stub );
3651+ if ((stub == falseop ) && !stubsib ) {
3652+ /* cond_expr
3653+ * -condition-
3654+ * - if -
3655+ * stub
3656+ */
3657+ assert (!(stub -> op_flags & OPf_KIDS ));
3658+ o -> op_flags |= OPf_SPECIAL ; /* For B::Deparse */
3659+ o -> op_next = stub -> op_next ;
3660+ op_sibling_splice (o , OpSIBLING (cLOGOP -> op_first ), 1 , NULL );
3661+ op_free (stub );
3662+ } 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
3685+ 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+ }
3693+ }
3694+ }
36273695 }
3696+
36283697 }
36293698 /* FALLTHROUGH */
36303699 case OP_MAPWHILE :
0 commit comments