void WReqn(elem *e) { static int nest; if (!e) return; if (OTunary(e->Eoper)) { WROP(e->Eoper); if (OTbinary(e->E1->Eoper)) { nest++; ferr("("); WReqn(e->E1); ferr(")"); nest--; } else WReqn(e->E1); } else if (e->Eoper == OPcomma && !nest) { WReqn(e->E1); dbg_printf(";\n\t"); WReqn(e->E2); } else if (OTbinary(e->Eoper)) { if (OTbinary(e->E1->Eoper)) { nest++; ferr("("); WReqn(e->E1); ferr(")"); nest--; } else WReqn(e->E1); ferr(" "); WROP(e->Eoper); if (e->Eoper == OPstreq) dbg_printf("%ld",(long)type_size(e->ET)); ferr(" "); if (OTbinary(e->E2->Eoper)) { nest++; ferr("("); WReqn(e->E2); ferr(")"); nest--; } else WReqn(e->E2); } else { switch (e->Eoper) { case OPconst: switch (tybasic(e->Ety)) { case TYfloat: dbg_printf("%g <float> ",e->EV.Vfloat); break; case TYdouble: dbg_printf("%g ",e->EV.Vdouble); break; case TYldouble: dbg_printf("%Lg ",e->EV.Vldouble); break; case TYcent: case TYucent: dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw); break; default: dbg_printf("%lld ",el_tolong(e)); break; } break; case OPrelconst: ferr("#"); /* FALL-THROUGH */ case OPvar: dbg_printf("%s",e->EV.sp.Vsym->Sident); if (e->EV.sp.Vsym->Ssymnum != -1) dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum); if (e->Eoffset != 0) { if (sizeof(e->Eoffset) == 8) dbg_printf(".x%llx", e->Eoffset); else dbg_printf(".%ld",(long)e->Eoffset); } break; case OPasm: case OPstring: dbg_printf("\"%s\"",e->EV.ss.Vstring); if (e->EV.ss.Voffset) dbg_printf("+%ld",(long)e->EV.ss.Voffset); break; case OPmark: case OPgot: case OPframeptr: case OPhalt: WROP(e->Eoper); break; case OPstrthis: break; default: WROP(e->Eoper); assert(0); } } }
STATIC void ecom(elem **pe) { int i,op,hcstopsave; unsigned hash; elem *e,*ehash; tym_t tym; e = *pe; assert(e); elem_debug(e); #ifdef DEBUG assert(e->Ecount == 0); //assert(e->Ecomsub == 0); #endif tym = tybasic(e->Ety); op = e->Eoper; switch (op) { case OPconst: case OPvar: case OPrelconst: break; case OPstreq: case OPpostinc: case OPpostdec: case OPeq: case OPaddass: case OPminass: case OPmulass: case OPdivass: case OPmodass: case OPshrass: case OPashrass: case OPshlass: case OPandass: case OPxorass: case OPorass: #if TX86 /* Reverse order of evaluation for double op=. This is so that */ /* the pushing of the address of the second operand is easier. */ /* However, with the 8087 we don't need the kludge. */ if (op != OPeq && tym == TYdouble && !config.inline8087) { if (EOP(e->E1)) ecom(&e->E1->E1); ecom(&e->E2); } else #endif { /* Don't mark the increment of an i++ or i-- as a CSE, if it */ /* can be done with an INC or DEC instruction. */ if (!(OTpost(op) && elemisone(e->E2))) ecom(&e->E2); /* evaluate 2nd operand first */ case OPnegass: if (EOP(e->E1)) /* if lvalue is an operator */ { #ifdef DEBUG if (e->E1->Eoper != OPind) elem_print(e); #endif assert(e->E1->Eoper == OPind); ecom(&(e->E1->E1)); } } touchlvalue(e->E1); if (!OTpost(op)) /* lvalue of i++ or i-- is not a cse*/ { hash = cs_comphash(e->E1); vec_setbit(hash % CSVECDIM,csvec); addhcstab(e->E1,hash); // add lvalue to hcstab[] } return; case OPbtc: case OPbts: case OPbtr: ecom(&e->E1); ecom(&e->E2); touchfunc(0); // indirect assignment return; case OPandand: case OPoror: ecom(&e->E1); hcstopsave = hcstop; ecom(&e->E2); hcstop = hcstopsave; /* no common subs by E2 */ return; /* if comsub then logexp() will */ /* break */ case OPcond: ecom(&e->E1); hcstopsave = hcstop; ecom(&e->E2->E1); /* left condition */ hcstop = hcstopsave; /* no common subs by E2 */ ecom(&e->E2->E2); /* right condition */ hcstop = hcstopsave; /* no common subs by E2 */ return; /* can't be a common sub */ case OPcall: case OPcallns: ecom(&e->E2); /* eval right first */ /* FALL-THROUGH */ case OPucall: case OPucallns: ecom(&e->E1); touchfunc(1); return; case OPstrpar: /* so we don't break logexp() */ #if TX86 case OPinp: /* never CSE the I/O instruction itself */ #endif case OPdctor: ecom(&e->E1); /* FALL-THROUGH */ case OPasm: case OPstrthis: // don't CSE these case OPframeptr: case OPgot: case OPctor: case OPdtor: case OPmark: return; case OPddtor: return; case OPparam: #if TX86 case OPoutp: #endif ecom(&e->E1); case OPinfo: ecom(&e->E2); return; case OPcomma: case OPremquo: ecom(&e->E1); ecom(&e->E2); break; #if TARGET_SEGMENTED case OPvp_fp: case OPcvp_fp: ecom(&e->E1); touchaccess(e); break; #endif case OPind: ecom(&e->E1); /* Generally, CSEing a *(double *) results in worse code */ if (tyfloating(tym)) return; break; #if TX86 case OPstrcpy: case OPstrcat: case OPmemcpy: case OPmemset: ecom(&e->E2); case OPsetjmp: ecom(&e->E1); touchfunc(0); return; #endif default: /* other operators */ #if TX86 #ifdef DEBUG if (!EBIN(e)) WROP(e->Eoper); #endif assert(EBIN(e)); case OPadd: case OPmin: case OPmul: case OPdiv: case OPor: case OPxor: case OPand: case OPeqeq: case OPne: case OPscale: case OPyl2x: case OPyl2xp1: ecom(&e->E1); ecom(&e->E2); break; #else #ifdef DEBUG if (!EOP(e)) WROP(e->Eoper); #endif assert(EOP(e)); ecom(&e->E1); if (EBIN(e)) ecom(&e->E2); /* eval left first */ break; #endif case OPstring: case OPaddr: case OPbit: #ifdef DEBUG WROP(e->Eoper); elem_print(e); #endif assert(0); /* optelem() should have removed these */ /* NOTREACHED */ // Explicitly list all the unary ops for speed case OPnot: case OPcom: case OPneg: case OPuadd: case OPabs: case OPsqrt: case OPrndtol: case OPsin: case OPcos: case OPrint: case OPpreinc: case OPpredec: case OPbool: case OPstrlen: case OPs16_32: case OPu16_32: case OPd_s32: case OPd_u32: case OPs32_d: case OPu32_d: case OPd_s16: case OPs16_d: case OP32_16: case OPd_f: case OPf_d: case OPd_ld: case OPld_d: case OPc_r: case OPc_i: case OPu8_16: case OPs8_16: case OP16_8: case OPu32_64: case OPs32_64: case OP64_32: case OPmsw: case OPu64_128: case OPs64_128: case OP128_64: case OPd_s64: case OPs64_d: case OPd_u64: case OPu64_d: case OPstrctor: case OPu16_d: case OPd_u16: case OParrow: case OPvoid: case OPnullcheck: case OPbsf: case OPbsr: case OPbswap: case OPld_u64: #if TARGET_SEGMENTED case OPoffset: case OPnp_fp: case OPnp_f16p: case OPf16p_np: #endif ecom(&e->E1); break; case OPhalt: return; } /* don't CSE structures or unions or volatile stuff */ if (tym == TYstruct || tym == TYvoid || e->Ety & mTYvolatile #if TX86 // don't CSE doubles if inline 8087 code (code generator can't handle it) || (tyfloating(tym) && config.inline8087) #endif ) return; hash = cs_comphash(e); /* must be AFTER leaves are done */ /* Search for a match in hcstab[]. * Search backwards, as most likely matches will be towards the end * of the list. */ #ifdef DEBUG if (debugx) dbg_printf("elem: %p hash: %6d\n",e,hash); #endif int csveci = hash % CSVECDIM; if (vec_testbit(csveci,csvec)) { for (i = hcstop; i--;) { #ifdef DEBUG if (debugx) dbg_printf("i: %2d Hhash: %6d Helem: %p\n", i,hcstab[i].Hhash,hcstab[i].Helem); #endif if (hash == hcstab[i].Hhash && (ehash = hcstab[i].Helem) != NULL) { /* if elems are the same and we still have room for more */ if (el_match(e,ehash) && ehash->Ecount < 0xFF) { /* Make sure leaves are also common subexpressions * to avoid false matches. */ if (!OTleaf(op)) { if (!e->E1->Ecount) continue; if (OTbinary(op) && !e->E2->Ecount) continue; } ehash->Ecount++; *pe = ehash; #ifdef DEBUG if (debugx) dbg_printf("**MATCH** %p with %p\n",e,*pe); #endif el_free(e); return; } } } } else vec_setbit(csveci,csvec); addhcstab(e,hash); // add this elem to hcstab[] }
void WReqn(elem *e) { static int nest; if (!e) return; if (OTunary(e->Eoper)) { WROP(e->Eoper); if (OTbinary(e->E1->Eoper)) { nest++; ferr("("); WReqn(e->E1); ferr(")"); nest--; } else WReqn(e->E1); } else if (e->Eoper == OPcomma && !nest) { WReqn(e->E1); dbg_printf(";\n\t"); WReqn(e->E2); } else if (OTbinary(e->Eoper)) { if (OTbinary(e->E1->Eoper)) { nest++; ferr("("); WReqn(e->E1); ferr(")"); nest--; } else WReqn(e->E1); ferr(" "); WROP(e->Eoper); if (e->Eoper == OPstreq) dbg_printf("%ld",e->Enumbytes); ferr(" "); if (OTbinary(e->E2->Eoper)) { nest++; ferr("("); WReqn(e->E2); ferr(")"); nest--; } else WReqn(e->E2); } else { switch (e->Eoper) { case OPconst: switch (tybasic(e->Ety)) { case TYfloat: dbg_printf("%g <float> ",e->EV.Vfloat); break; case TYdouble: dbg_printf("%g ",e->EV.Vdouble); break; default: dbg_printf("%lld ",el_tolong(e)); break; } break; case OPrelconst: ferr("#"); /* FALL-THROUGH */ case OPvar: dbg_printf("%s",e->EV.sp.Vsym->Sident); if (e->EV.sp.Vsym->Ssymnum != -1) dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum); if (e->Eoffset != 0) dbg_printf(".%ld",e->Eoffset); break; case OPasm: #if TARGET_MAC if (e->Eflags & EFsmasm) { if (e->EV.mac.Vasmdat[1]) dbg_printf("\"%c%c\"",e->EV.mac.Vasmdat[0],e->EV.mac.Vasmdat[1]); else dbg_printf("\"%c\"",e->EV.mac.Vasmdat[0]); break; }; #endif case OPstring: dbg_printf("\"%s\"",e->EV.ss.Vstring); if (e->EV.ss.Voffset) dbg_printf("+%ld",e->EV.ss.Voffset); break; case OPmark: case OPgot: case OPframeptr: WROP(e->Eoper); break; case OPstrthis: break; default: WROP(e->Eoper); assert(0); } } }