+/* ... Our peephole optimizer .............................................. */
+
+STATIC peep_t a_old_peep = 0; /* This is actually the rpeep past 5.13.5 */
+
+#if !A_HAS_RPEEP
+# define A_PEEP_REC_PROTO STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen)
+#else /* !A_HAS_RPEEP */
+# define A_PEEP_REC_PROTO STATIC void a_peep_rec(pTHX_ OP *o)
+#endif /* A_HAS_RPEEP */
+
+A_PEEP_REC_PROTO;
+A_PEEP_REC_PROTO {
+#if !A_HAS_RPEEP
+# define a_peep_rec(O) a_peep_rec(aTHX_ (O), seen)
+#else /* !A_HAS_RPEEP */
+# define a_peep_rec(O) a_peep_rec(aTHX_ (O))
+#endif /* A_HAS_RPEEP */
+ dA_MAP_THX;
+
+#if !A_HAS_RPEEP
+ if (ptable_fetch(seen, o))
+ return;
+#endif
+
+ for (; o; o = o->op_next) {
+ const a_op_info *oi = NULL;
+ UV flags = 0;
+
+#if !A_HAS_RPEEP
+ ptable_seen_store(seen, o, o);
+#endif
+ switch (o->op_type) {
+ case OP_PADSV:
+ if (o->op_ppaddr != a_pp_deref) {
+ oi = a_map_fetch(o);
+ if (oi && (oi->flags & A_HINT_DO)) {
+ a_map_store(o, o->op_ppaddr, oi->next, oi->flags);
+ o->op_ppaddr = a_pp_deref;
+ }
+ }
+ /* FALLTHROUGH */
+ case OP_AELEM:
+ case OP_AELEMFAST:
+ case OP_HELEM:
+ case OP_RV2SV:
+ if (o->op_ppaddr != a_pp_deref)
+ break;
+ oi = a_map_fetch(o);
+ if (!oi)
+ break;
+ flags = oi->flags;
+ if (!(flags & A_HINT_DEREF)
+ && (flags & A_HINT_DO)
+ && (o->op_private & OPpDEREF || flags & A_HINT_ROOT)) {
+ /* Decide if the expression must autovivify or not. */
+ flags = a_map_resolve(o, oi);
+ }
+ if (flags & A_HINT_DEREF)
+ o->op_private = ((o->op_private & ~OPpDEREF) | OPpLVAL_DEFER);
+ else
+ o->op_ppaddr = oi->old_pp;
+ break;
+ case OP_RV2AV:
+ case OP_RV2HV:
+ if ( o->op_ppaddr != a_pp_rv2av
+ && o->op_ppaddr != a_pp_rv2hv
+ && o->op_ppaddr != a_pp_rv2hv_simple)
+ break;
+ oi = a_map_fetch(o);
+ if (!oi)
+ break;
+ if (!(oi->flags & A_HINT_DEREF))
+ o->op_ppaddr = oi->old_pp;
+ break;
+#if !A_HAS_RPEEP
+ case OP_MAPWHILE:
+ case OP_GREPWHILE:
+ case OP_AND:
+ case OP_OR:
+ case OP_ANDASSIGN:
+ case OP_ORASSIGN:
+ case OP_COND_EXPR:
+ case OP_RANGE:
+# if A_HAS_PERL(5, 10, 0)
+ case OP_ONCE:
+ case OP_DOR:
+ case OP_DORASSIGN:
+# endif
+ a_peep_rec(cLOGOPo->op_other);
+ break;
+ case OP_ENTERLOOP:
+ case OP_ENTERITER:
+ a_peep_rec(cLOOPo->op_redoop);
+ a_peep_rec(cLOOPo->op_nextop);
+ a_peep_rec(cLOOPo->op_lastop);
+ break;
+# if A_HAS_PERL(5, 9, 5)
+ case OP_SUBST:
+ a_peep_rec(cPMOPo->op_pmstashstartu.op_pmreplstart);
+ break;
+# else
+ case OP_QR:
+ case OP_MATCH:
+ case OP_SUBST:
+ a_peep_rec(cPMOPo->op_pmreplstart);
+ break;
+# endif
+#endif /* !A_HAS_RPEEP */
+ default:
+ break;
+ }
+ }
+}
+
+STATIC void a_peep(pTHX_ OP *o) {
+#if !A_HAS_RPEEP
+ dMY_CXT;
+ ptable *seen = MY_CXT.seen;
+
+ ptable_seen_clear(seen);
+#endif /* !A_HAS_RPEEP */
+
+ a_old_peep(aTHX_ o);
+ a_peep_rec(o);
+}
+
+/* --- Interpreter setup/teardown ------------------------------------------ */
+