STATIC void touchlvalue(elem *e) { if (e->Eoper == OPind) /* if indirect store */ { /* NOTE: Some types of array assignments do not need * to touch all variables. (Like a[5], where a is an * array instead of a pointer.) */ touchfunc(0); return; } for (int i = hcsarray.top; --i >= 0;) { if (hcstab[i].Helem && hcstab[i].Helem->EV.sp.Vsym == e->EV.sp.Vsym) hcstab[i].Helem = NULL; } if (!(e->Eoper == OPvar || e->Eoper == OPrelconst)) elem_print(e); assert(e->Eoper == OPvar || e->Eoper == OPrelconst); switch (e->EV.sp.Vsym->Sclass) { case SCregpar: case SCregister: case SCpseudo: break; case SCauto: case SCparameter: case SCfastpar: case SCshadowreg: case SCbprel: if (e->EV.sp.Vsym->Sflags & SFLunambig) break; /* FALL-THROUGH */ case SCstatic: case SCextern: case SCglobal: case SClocstat: case SCcomdat: case SCinline: case SCsinline: case SCeinline: case SCcomdef: touchstar(); break; default: elem_print(e); symbol_print(e->EV.sp.Vsym); assert(0); } }
void list_print(FILE* fp, const List* list) { ListElem* le; for(le = list->anchor.next; le != &list->anchor; le = le->next) { switch(list->type) { case LIST_ELEM : elem_print(fp, le->data.elem, TRUE); break; case LIST_TUPLE : tuple_print(fp, le->data.tuple); break; case LIST_ENTRY : entry_print(fp, le->data.entry); break; case LIST_LIST : list_print(fp, le->data.list); break; default : abort(); } fprintf(fp, "\n"); } }
void dbg_optprint(char *title) { block *b; for (b = startblock; b; b = b->Bnext) if (b->Belem) { dbg_printf("%s\n",title); elem_print(b->Belem); } }
void dyntab_print(const dyntab* tab, void (*elem_print)(const void* elem)) { printf("[ ") ; for(size_t i = 0; i < tab->size; ++i) { elem_print(tab->data + i * tab->bytes) ; printf(" ") ; } printf("]\n") ; }
std::ostream& print(std::ostream& os, const ivl::array<T, S>& in) { array_details::print_init<T> init(os); os << "[ " ; for(typename ivl::array<T, S>::const_iterator it = in.begin(); it != in.end(); it++) { elem_print(os, *it); } os << "]"; return os; }
bool ofc_parse_list_print( ofc_colstr_t* cs, unsigned elem_count, const void** elem, bool (*elem_print)(ofc_colstr_t*, const void*)) { if (!elem || !elem_print) return false; unsigned i; for (i = 0; i < elem_count; i++) { if ((i > 0) && !ofc_colstr_atomic_writef(cs, ", ")) return false; if (!elem_print(cs, elem[i])) return false; } return true; }
void param_t::print() { dbg_printf("Pident=%p,Ptype=%p,Pelem=%p,Psym=%p,Pnext=%p\n",Pident,Ptype,Pelem,Psym,Pnext); if (Pident) dbg_printf("\tPident = '%s'\n", Pident); if (Ptype) { dbg_printf("\tPtype =\n"); type_print(Ptype); } if (Pelem) { dbg_printf("\tPelem =\n"); elem_print(Pelem); } if (Pdeftype) { dbg_printf("\tPdeftype =\n"); type_print(Pdeftype); } if (Psym) { dbg_printf("\tPsym = '%s'\n", Psym->Sident); } if (Pptpl) { dbg_printf("\tPptpl = %p\n", Pptpl); } }
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[] }
int main() { flint_rand_t state; long iter; printf("poly_divrem_basecase...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { ring_t ZZ, ZZp, ZZpx[3]; ring_struct * ring; elem_ptr p; long size[3]; elem_poly_t A, B, C, Q, Q2, R, R2; ring_init_limb(ZZ); ELEM_TMP_INIT(p, ZZ); elem_set_ui(p, n_randtest_prime(state, 0), ZZ); ring_init_mod(ZZp, ZZ, p); ring_init_poly(ZZpx[0], ZZp); ring_init_poly(ZZpx[1], ZZpx[0]); ring_init_poly(ZZpx[2], ZZpx[1]); ring = ZZpx[n_randint(state, 2)]; size[0] = 1 + n_randint(state, 30); size[1] = 1 + n_randint(state, 30); size[2] = 1 + n_randint(state, 30); elem_init(A, ring); elem_init(B, ring); elem_init(C, ring); elem_init(Q, ring); elem_init(Q2, ring); elem_init(R, ring); elem_init(R2, ring); elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(C, A, B, ring); elem_poly_divrem_basecase(Q, R, C, B, ring); if (!elem_equal(Q, A, ring) || !elem_is_zero(R, ring)) { printf("FAIL: (A * B) / B = A\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); elem_print(R, ring); printf("\n\n"); abort(); } elem_divrem(Q, R, A, B, ring); elem_mul(C, Q, B, ring); elem_add(C, C, R, ring); if (!elem_equal(C, A, ring)) { printf("FAIL: Q * B + R = A\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); elem_print(R, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_poly_divrem_basecase(Q, R, A, B, ring); elem_poly_divrem_basecase(A, R2, A, B, ring); if (!elem_equal(A, Q, ring) || !elem_equal(R, R2, ring)) { printf("FAIL: aliasing Q, A\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); elem_print(R, ring); printf("\n\n"); elem_print(R2, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_poly_divrem_basecase(Q, R, A, B, ring); elem_poly_divrem_basecase(Q2, A, A, B, ring); if (!elem_equal(A, R, ring) || !elem_equal(Q, Q2, ring)) { printf("FAIL: aliasing R, A\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); elem_print(Q2, ring); printf("\n\n"); elem_print(R, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_poly_divrem_basecase(Q, R, A, B, ring); elem_poly_divrem_basecase(Q2, B, A, B, ring); if (!elem_equal(B, R, ring) || !elem_equal(Q, Q2, ring)) { printf("FAIL: aliasing R, B\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); elem_print(Q2, ring); printf("\n\n"); elem_print(R, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_poly_divrem_basecase(Q, R, A, B, ring); elem_poly_divrem_basecase(B, R2, A, B, ring); if (!elem_equal(B, Q, ring) || !elem_equal(R, R2, ring)) { printf("FAIL: aliasing Q, B\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); elem_print(R, ring); printf("\n\n"); elem_print(R2, ring); printf("\n\n"); abort(); } elem_clear(A, ring); elem_clear(B, ring); elem_clear(C, ring); elem_clear(Q, ring); elem_clear(Q2, ring); elem_clear(R, ring); elem_clear(R2, ring); ring_clear(ZZpx[2]); ring_clear(ZZpx[1]); ring_clear(ZZpx[0]); ring_clear(ZZp); ELEM_TMP_CLEAR(p, ZZ); ring_clear(ZZ); } printf("PASS\n"); flint_randclear(state); return EXIT_SUCCESS; }
void optfunc() { #if !HTOD block *b; int iter; // iteration count clock_t starttime; cmes ("optfunc()\n"); dbg_optprint("optfunc\n"); #ifdef DEBUG if (debugb) { dbg_printf("................Before optimization.........\n"); WRfunc(); } #endif iter = 0; if (localgot) { // Initialize with: // localgot = OPgot; elem *e = el_long(TYnptr, 0); e->Eoper = OPgot; e = el_bin(OPeq, TYnptr, el_var(localgot), e); startblock->Belem = el_combine(e, startblock->Belem); } // Each pass through the loop can reduce only one level of comma expression. // The infinite loop check needs to take this into account. int iterationLimit = 0; for (b = startblock; b; b = b->Bnext) { if (!b->Belem) continue; int d = el_countCommas(b->Belem); if (d > iterationLimit) iterationLimit = d; } // Some functions can take enormous amounts of time to optimize. // We try to put a lid on it. starttime = clock(); do { //printf("iter = %d\n", iter); #if TX86 if (++iter > 200) { assert(iter < iterationLimit); // infinite loop check break; } #else L1: #endif #if MARS util_progress(); #else file_progress(); #endif //printf("optelem\n"); /* canonicalize the trees */ for (b = startblock; b; b = b->Bnext) if (b->Belem) { #if DEBUG if(debuge) { dbg_printf("before\n"); elem_print(b->Belem); //el_check(b->Belem); } #endif b->Belem = doptelem(b->Belem,bc_goal[b->BC] | GOALagain); #if DEBUG if(0 && debugf) { dbg_printf("after\n"); elem_print(b->Belem); } #endif } //printf("blockopt\n"); #if TX86 if (mfoptim & MFdc) blockopt(0); // do block optimization out_regcand(&globsym); // recompute register candidates changes = 0; /* no changes yet */ if (mfoptim & MFcnp) constprop(); /* make relationals unsigned */ if (mfoptim & (MFli | MFliv)) #else if (config.optimized && (mfoptim & MFdc)) blockopt(0); // do block optimization dbg_optprint("blockopt\n"); out_regcand(); // recompute register candidates changes = 0; /* no changes yet */ dbg_optprint("constprop\n"); if (config.optimized && (mfoptim & MFcnp)) constprop(); /* make relationals unsigned */ dbg_optprint("loopopt\n"); if (config.optimized && (mfoptim & (MFli | MFliv))) #endif loopopt(); /* remove loop invariants and */ /* induction vars */ /* do loop rotation */ else for (b = startblock; b; b = b->Bnext) b->Bweight = 1; dbg_optprint("boolopt\n"); #if TX86 if (mfoptim & MFcnp) boolopt(); // optimize boolean values if (changes && mfoptim & MFloop && (clock() - starttime) < 30 * CLOCKS_PER_SEC) continue; if (mfoptim & MFcnp) constprop(); /* constant propagation */ if (mfoptim & MFcp) copyprop(); /* do copy propagation */ /* Floating point constants and string literals need to be * replaced with loads from variables in read-only data. * This can result in localgot getting needed. */ symbol *localgotsave = localgot; for (b = startblock; b; b = b->Bnext) { if (b->Belem) { b->Belem = doptelem(b->Belem,bc_goal[b->BC] | GOALstruct); if (b->Belem) b->Belem = el_convert(b->Belem); } } if (localgot != localgotsave) { /* Looks like we did need localgot, initialize with: * localgot = OPgot; */ elem *e = el_long(TYnptr, 0); e->Eoper = OPgot; e = el_bin(OPeq, TYnptr, el_var(localgot), e); startblock->Belem = el_combine(e, startblock->Belem); } /* localize() is after localgot, otherwise we wind up with * more than one OPgot in a function, which mucks up OSX * code generation which assumes at most one (localgotoffset). */ if (mfoptim & MFlocal) localize(); // improve expression locality if (mfoptim & MFda) rmdeadass(); /* remove dead assignments */ cmes2 ("changes = %d\n", changes); if (!(changes && mfoptim & MFloop && (clock() - starttime) < 30 * CLOCKS_PER_SEC)) break; } while (1); cmes2("%d iterations\n",iter); if (mfoptim & MFdc) blockopt(1); // do block optimization #else if (config.optimized && (mfoptim & MFcnp)) boolopt(); // optimize boolean values util_progress(); if (changes) goto L1; dbg_optprint("constprop\n"); if (config.optimized && (mfoptim & MFcnp)) constprop(); /* constant propagation */ dbg_optprint("copyprop\n"); if (config.optimized && (mfoptim & MFcp)) copyprop(); /* do copy propagation */ dbg_optprint("localize\n"); if (config.optimized && (mfoptim & MFlocal)) localize(); // improve expression locality dbg_optprint("rmdeadass\n"); if (config.optimized && (mfoptim & MFda)) rmdeadass(); /* remove dead assignments */ cmes2 ("changes = %d\n", changes); iter++; assert (iter < 80); /* infinite loop check */ } while (changes && (config.optimized) && (mfoptim & MFloop));
STATIC void touchlvalue(elem *e) { register int i; if (e->Eoper == OPind) /* if indirect store */ { /* NOTE: Some types of array assignments do not need * to touch all variables. (Like a[5], where a is an * array instead of a pointer.) */ touchfunc(0); return; } for (i = hcstop; --i >= 0;) { if (hcstab[i].Helem && #if TARGET_MAC // Vsym should be valid before compare !EOP(hcstab[i].Helem) && hcstab[i].Helem->Eoper != OPconst && #endif hcstab[i].Helem->EV.sp.Vsym == e->EV.sp.Vsym) hcstab[i].Helem = NULL; } assert(e->Eoper == OPvar || e->Eoper == OPrelconst); switch (e->EV.sp.Vsym->Sclass) { case SCregpar: case SCregister: case SCtmp: case SCpseudo: break; case SCauto: case SCparameter: #if TX86 case SCfastpar: case SCbprel: #endif if (e->EV.sp.Vsym->Sflags & SFLunambig) break; /* FALL-THROUGH */ case SCstatic: case SCextern: case SCglobal: case SClocstat: case SCcomdat: case SCinline: case SCsinline: case SCeinline: #if TX86 case SCcomdef: #endif touchstar(); break; default: #ifdef DEBUG elem_print(e); symbol_print(e->EV.sp.Vsym); #endif assert(0); } }
char *template_mangle(symbol *s,param_t *arglist) { /* mangling ::= '$' template_name { type | expr } type ::= "T" mangled type expr ::= integer | string | address | float | double | long_double integer ::= "I" dimension string ::= "S" string address ::= "R" zname float ::= "F" hex_digits double ::= "D" hex_digits long_double ::= "L" hex_digits */ param_t *p; assert(s); symbol_debug(s); //assert(s->Sclass == SCtemplate); //printf("\ntemplate_mangle(s = '%s', arglist = %p)\n", s->Sident, arglist); //arglist->print_list(); MangleInuse m; mangle.znamei = 0; mangle.argi = 0; mangle.np = mangle.buf; mangle.buf[BUFIDMAX + 1] = 0x55; if (NEWTEMPMANGLE) STR("?$"); else CHAR('$'); // BUG: this is for templates nested inside class scopes. // Need to check if it creates names that are properly unmanglable. cpp_zname(s->Sident); if (s->Sscope) cpp_scope(s->Sscope); for (p = arglist; p; p = p->Pnext) { if (p->Ptype) { /* Argument is a type */ if (!NEWTEMPMANGLE) CHAR('T'); cpp_argument_list(p->Ptype, 1); } else if (p->Psym) { CHAR('V'); // this is a 'class' name, but it should be a 'template' name cpp_ecsu_name(p->Psym); } else { /* Argument is an expression */ elem *e = p->Pelem; tym_t ty = tybasic(e->ET->Tty); char *p; char a[2]; int ni; char c; L2: switch (e->Eoper) { case OPconst: switch (ty) { case TYfloat: ni = FLOATSIZE; c = 'F'; goto L1; case TYdouble_alias: case TYdouble: ni = DOUBLESIZE; c = 'D'; goto L1; case TYldouble: ni = LNGDBLSIZE; c = 'L'; goto L1; L1: if (NEWTEMPMANGLE) CHAR('$'); CHAR(c); p = (char *)&e->EV.Vdouble; while (ni--) { char c; #if __GNUC__ static char hex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; #else static char hex[16] = "0123456789ABCDEF"; #endif c = *p++; CHAR(hex[c & 15]); CHAR(hex[(c >> 4) & 15]); } break; default: #ifdef DEBUG if (!tyintegral(ty) && !tymptr(ty)) elem_print(e); #endif assert(tyintegral(ty) || tymptr(ty)); if (NEWTEMPMANGLE) STR("$0"); else CHAR('I'); cpp_dimension(el_tolongt(e)); break; } break; case OPstring: if (NEWTEMPMANGLE) STR("$S"); else CHAR('S'); if (e->EV.ss.Voffset) synerr(EM_const_init); // constant initializer expected cpp_string(e->EV.ss.Vstring,e->EV.ss.Vstrlen); break; case OPrelconst: if (e->EV.sp.Voffset) synerr(EM_const_init); // constant initializer expected s = e->EV.sp.Vsym; if (NEWTEMPMANGLE) { STR("$1"); cpp_decorated_name(s); } else { CHAR('R'); cpp_zname(s->Sident); } break; case OPvar: if (e->EV.sp.Vsym->Sflags & SFLvalue && tybasic(e->ET->Tty) != TYstruct) { e = e->EV.sp.Vsym->Svalue; goto L2; } else if (e->EV.sp.Vsym->Sclass == SCconst /*&& pstate.STintemplate*/) { CHAR('V'); // pretend to be a class name cpp_zname(e->EV.sp.Vsym->Sident); break; } default: #if SCPP #ifdef DEBUG if (!errcnt) elem_print(e); #endif synerr(EM_const_init); // constant initializer expected assert(errcnt); #endif break; } } } *mangle.np = 0; //printf("template_mangle() = '%s'\n", mangle.buf); assert(strlen(mangle.buf) <= BUFIDMAX); assert(mangle.buf[BUFIDMAX + 1] == 0x55); return mangle.buf; }
code *cdvector(elem *e, regm_t *pretregs) { /* e should look like one of: * vector * | * param * / \ * param op2 * / \ * op op1 */ if (!config.fpxmmregs) { printf("SIMD operations not supported on this platform\n"); exit(1); } unsigned n = el_nparams(e->E1); elem **params = (elem **)malloc(n * sizeof(elem *)); assert(params); elem **tmp = params; el_paramArray(&tmp, e->E1); #if 0 printf("cdvector()\n"); for (int i = 0; i < n; i++) { printf("[%d]: ", i); elem_print(params[i]); } #endif if (*pretregs == 0) { /* Evaluate for side effects only */ CodeBuilder cdb; for (int i = 0; i < n; i++) { cdb.append(codelem(params[i], pretregs, FALSE)); *pretregs = 0; // in case they got set } return cdb.finish(); } assert(n >= 2 && n <= 4); elem *eop = params[0]; elem *op1 = params[1]; elem *op2 = NULL; tym_t ty2 = 0; if (n >= 3) { op2 = params[2]; ty2 = tybasic(op2->Ety); } unsigned op = el_tolong(eop); #ifdef DEBUG assert(!isXMMstore(op)); #endif tym_t ty1 = tybasic(op1->Ety); unsigned sz1 = _tysize[ty1]; // assert(sz1 == 16); // float or double regm_t retregs; CodeBuilder cdb; if (n == 3 && ty2 == TYuchar && op2->Eoper == OPconst) { // Handle: op xmm,imm8 retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; cdb.append(codelem(op1,&retregs,FALSE)); // eval left leaf unsigned reg = findreg(retregs); int r; switch (op) { case PSLLD: r = 6; op = 0x660F72; break; case PSLLQ: r = 6; op = 0x660F73; break; case PSLLW: r = 6; op = 0x660F71; break; case PSRAD: r = 4; op = 0x660F72; break; case PSRAW: r = 4; op = 0x660F71; break; case PSRLD: r = 2; op = 0x660F72; break; case PSRLQ: r = 2; op = 0x660F73; break; case PSRLW: r = 2; op = 0x660F71; break; case PSRLDQ: r = 3; op = 0x660F73; break; case PSLLDQ: r = 7; op = 0x660F73; break; default: printf("op = x%x\n", op); assert(0); break; } cdb.append(getregs(retregs)); cdb.genc2(op,modregrmx(3,r,reg-XMM0), el_tolong(op2)); } else if (n == 2) { /* Handle: op xmm,mem * where xmm is written only, not read */ code cs; if ((op1->Eoper == OPind && !op1->Ecount) || op1->Eoper == OPvar) { cdb.append(getlvalue(&cs, op1, RMload)); // get addressing mode } else { regm_t rretregs = XMMREGS; cdb.append(codelem(op1, &rretregs, FALSE)); unsigned rreg = findreg(rretregs) - XMM0; cs.Irm = modregrm(3,0,rreg & 7); cs.Iflags = 0; cs.Irex = 0; if (rreg & 8) cs.Irex |= REX_B; } retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; unsigned reg; cdb.append(allocreg(&retregs, ®, e->Ety)); code_newreg(&cs, reg - XMM0); cs.Iop = op; cdb.gen(&cs); } else if (n == 3 || n == 4) { /* Handle: * op xmm,mem // n = 3 * op xmm,mem,imm8 // n = 4 * Both xmm and mem are operands, evaluate xmm first. */ code cs; retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; cdb.append(codelem(op1,&retregs,FALSE)); // eval left leaf unsigned reg = findreg(retregs); if ((op2->Eoper == OPind && !op2->Ecount) || op2->Eoper == OPvar) { cdb.append(getlvalue(&cs, op2, RMload | retregs)); // get addressing mode } else { unsigned rretregs = XMMREGS & ~retregs; cdb.append(scodelem(op2, &rretregs, retregs, TRUE)); unsigned rreg = findreg(rretregs) - XMM0; cs.Irm = modregrm(3,0,rreg & 7); cs.Iflags = 0; cs.Irex = 0; if (rreg & 8) cs.Irex |= REX_B; } cdb.append(getregs(retregs)); if (n == 4) { switch (op) { case CMPPD: case CMPSS: case CMPSD: case CMPPS: case PSHUFD: case PSHUFHW: case PSHUFLW: case BLENDPD: case BLENDPS: case DPPD: case DPPS: case MPSADBW: case PBLENDW: case ROUNDPD: case ROUNDPS: case ROUNDSD: case ROUNDSS: case SHUFPD: case SHUFPS: break; default: printf("op = x%x\n", op); assert(0); break; } elem *imm8 = params[3]; cs.IFL2 = FLconst; cs.IEV2.Vsize_t = el_tolong(imm8); } code_newreg(&cs, reg - XMM0); cs.Iop = op; cdb.gen(&cs); } else assert(0); cdb.append(fixresult(e,retregs,pretregs)); free(params); freenode(e); return cdb.finish(); }
/****************************************** * Return elem that evaluates to the static frame pointer for function fd. * If fd is a member function, the returned expression will compute the value * of fd's 'this' variable. * This routine is critical for implementing nested functions. */ elem *getEthis(Loc loc, IRState *irs, Dsymbol *fd) { elem *ethis; FuncDeclaration *thisfd = irs->getFunc(); Dsymbol *fdparent = fd->toParent2(); Dsymbol *fdp = fdparent; /* These two are compiler generated functions for the in and out contracts, * and are called from an overriding function, not just the one they're * nested inside, so this hack is so they'll pass */ if (fdparent != thisfd && (fd->ident == Id::require || fd->ident == Id::ensure)) { FuncDeclaration *fdthis = thisfd; for (size_t i = 0; ; ) { if (i == fdthis->foverrides.dim) { if (i == 0) break; fdthis = fdthis->foverrides[0]; i = 0; continue; } if (fdthis->foverrides[i] == fdp) { fdparent = thisfd; break; } i++; } } //printf("[%s] getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", loc.toChars(), thisfd->toPrettyChars(), fd->toPrettyChars(), fdparent->toPrettyChars()); if (fdparent == thisfd) { /* Going down one nesting level, i.e. we're calling * a nested function from its enclosing function. */ if (irs->sclosure && !(fd->ident == Id::require || fd->ident == Id::ensure)) { ethis = el_var(irs->sclosure); } else if (irs->sthis) { // We have a 'this' pointer for the current function /* If no variables in the current function's frame are * referenced by nested functions, then we can 'skip' * adding this frame into the linked list of stack * frames. */ if (thisfd->hasNestedFrameRefs()) { /* Local variables are referenced, can't skip. * Address of 'sthis' gives the 'this' for the nested * function */ ethis = el_ptr(irs->sthis); } else { ethis = el_var(irs->sthis); } } else { /* No 'this' pointer for current function, */ if (thisfd->hasNestedFrameRefs()) { /* OPframeptr is an operator that gets the frame pointer * for the current function, i.e. for the x86 it gets * the value of EBP */ ethis = el_long(TYnptr, 0); ethis->Eoper = OPframeptr; } else { /* Use NULL if no references to the current function's frame */ ethis = el_long(TYnptr, 0); } } } else { if (!irs->sthis) // if no frame pointer for this function { fd->error(loc, "is a nested function and cannot be accessed from %s", irs->getFunc()->toPrettyChars()); return el_long(TYnptr, 0); // error recovery } /* Go up a nesting level, i.e. we need to find the 'this' * of an enclosing function. * Our 'enclosing function' may also be an inner class. */ ethis = el_var(irs->sthis); Dsymbol *s = thisfd; while (fd != s) { FuncDeclaration *fdp = s->toParent2()->isFuncDeclaration(); //printf("\ts = '%s'\n", s->toChars()); thisfd = s->isFuncDeclaration(); if (thisfd) { /* Enclosing function is a function. */ // Error should have been caught by front end assert(thisfd->isNested() || thisfd->vthis); } else { /* Enclosed by an aggregate. That means the current * function must be a member function of that aggregate. */ AggregateDeclaration *ad = s->isAggregateDeclaration(); if (!ad) { Lnoframe: irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toPrettyChars()); return el_long(TYnptr, 0); // error recovery } ClassDeclaration *cd = ad->isClassDeclaration(); ClassDeclaration *cdx = fd->isClassDeclaration(); if (cd && cdx && cdx->isBaseOf(cd, NULL)) break; StructDeclaration *sd = ad->isStructDeclaration(); if (fd == sd) break; if (!ad->isNested() || !ad->vthis) goto Lnoframe; ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYsize_t, ad->vthis->offset)); ethis = el_una(OPind, TYnptr, ethis); } if (fdparent == s->toParent2()) break; /* Remember that frames for functions that have no * nested references are skipped in the linked list * of frames. */ if (fdp && fdp->hasNestedFrameRefs()) ethis = el_una(OPind, TYnptr, ethis); s = s->toParent2(); assert(s); } } #if 0 printf("ethis:\n"); elem_print(ethis); printf("\n"); #endif return ethis; }
void WRblock(block *b) { if (OPTIMIZER) { if (b && b->Bweight) dbg_printf("B%d: (%p), weight=%d",b->Bdfoidx,b,b->Bweight); else dbg_printf("block %p",b); if (!b) { ferr("\n"); return; } dbg_printf(" flags=x%x weight=%d",b->Bflags,b->Bweight); #if 0 dbg_printf("\tfile %p, line %d",b->Bfilptr,b->Blinnum); #endif dbg_printf(" "); WRBC(b->BC); dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex); #if SCPP if (b->BC == BCtry) dbg_printf(" catchvar = %p",b->catchvar); #endif dbg_printf("\n"); dbg_printf("\tBpred: "); WRblocklist(b->Bpred); dbg_printf("\tBsucc: "); WRblocklist(b->Bsucc); if (b->Belem) { if (debugf) /* if full output */ elem_print(b->Belem); else { ferr("\t"); WReqn(b->Belem); dbg_printf(";\n"); } } if (b->Bcode) b->Bcode->print(); ferr("\n"); } else { targ_llong *pu; int ncases; list_t bl; assert(b); dbg_printf("********* Basic Block %p ************\n",b); if (b->Belem) elem_print(b->Belem); dbg_printf("block: "); WRBC(b->BC); dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex); dbg_printf("\n"); dbg_printf("\tBpred:\n"); for (bl = b->Bpred; bl; bl = list_next(bl)) dbg_printf("\t%p\n",list_block(bl)); bl = b->Bsucc; switch (b->BC) { case BCswitch: pu = b->BS.Bswitch; assert(pu); ncases = *pu; dbg_printf("\tncases = %d\n",ncases); dbg_printf("\tdefault: %p\n",list_block(bl)); while (ncases--) { bl = list_next(bl); dbg_printf("\tcase %lld: %p\n",*++pu,list_block(bl)); } break; case BCiftrue: case BCgoto: case BCasm: #if SCPP case BCtry: case BCcatch: #endif case BCjcatch: case BC_try: case BC_filter: case BC_finally: case BC_ret: case BC_except: Lsucc: dbg_printf("\tBsucc:\n"); for ( ; bl; bl = list_next(bl)) dbg_printf("\t%p\n",list_block(bl)); break; case BCret: case BCretexp: case BCexit: break; default: assert(0); } } }
void test_divexact(flint_rand_t state, const ring_t ring, const long * size, long iters) { long iter; for (iter = 0; iter < iters; iter++) { elem_ptr A, B, C, Q; A = elem_new(ring); B = elem_new(ring); C = elem_new(ring); Q = elem_new(ring); elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(C, A, B, ring); elem_divexact(Q, C, B, ring); if (!elem_equal(Q, A, ring)) { printf("FAIL: (A * B) / B = A\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest_not_zero(A, state, size, ring); elem_set(B, A, ring); elem_divexact(C, A, A, ring); elem_divexact(Q, A, B, ring); if (!elem_equal(C, Q, ring) || !elem_is_one(Q, ring)) { printf("FAIL: aliasing A, B\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(A, A, B, ring); elem_divexact(Q, A, B, ring); elem_divexact(A, A, B, ring); if (!elem_equal(A, Q, ring)) { printf("FAIL: aliasing Q, A\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(A, A, B, ring); elem_divexact(Q, A, B, ring); elem_divexact(B, A, B, ring); if (!elem_equal(B, Q, ring)) { printf("FAIL: aliasing Q, A\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest_not_zero(B, state, size, ring); elem_divexact(Q, B, B, ring); elem_divexact(B, B, B, ring); if (!elem_equal(B, Q, ring)) { printf("FAIL: aliasing Q, A, B\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_del(A, ring); elem_del(B, ring); elem_del(C, ring); elem_del(Q, ring); } }
void type_print(type *t) { type_debug(t); dbg_printf("Tty="); WRTYxx(t->Tty); dbg_printf(" Tmangle=%d",t->Tmangle); dbg_printf(" Tflags=x%x",t->Tflags); dbg_printf(" Tcount=%d",t->Tcount); if (!(t->Tflags & TFsizeunknown) && tybasic(t->Tty) != TYvoid && tybasic(t->Tty) != TYident && tybasic(t->Tty) != TYmfunc && tybasic(t->Tty) != TYarray && tybasic(t->Tty) != TYtemplate) dbg_printf(" Tsize=%ld",type_size(t)); dbg_printf(" Tnext=%p",t->Tnext); switch (tybasic(t->Tty)) { case TYstruct: case TYmemptr: dbg_printf(" Ttag=%p,'%s'",t->Ttag,t->Ttag->Sident); //dbg_printf(" Sfldlst=%p",t->Ttag->Sstruct->Sfldlst); break; case TYarray: dbg_printf(" Tdim=%ld",t->Tdim); break; case TYident: dbg_printf(" Tident='%s'",t->Tident); break; case TYtemplate: dbg_printf(" Tsym='%s'",((typetemp_t *)t)->Tsym->Sident); { param_t *p; int i; i = 1; for (p = t->Tparamtypes; p; p = p->Pnext) { dbg_printf("\nTP%d (%p): ",i++,p); fflush(stdout); dbg_printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p->Pident,p->Ptype,p->Pelem,p->Pnext); param_debug(p); if (p->Pident) printf("'%s' ", p->Pident); if (p->Ptype) type_print(p->Ptype); if (p->Pelem) elem_print(p->Pelem); } } break; default: if (tyfunc(t->Tty)) { param_t *p; int i; i = 1; for (p = t->Tparamtypes; p; p = p->Pnext) { dbg_printf("\nP%d (%p): ",i++,p); fflush(stdout); dbg_printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p->Pident,p->Ptype,p->Pelem,p->Pnext); param_debug(p); if (p->Pident) printf("'%s' ", p->Pident); type_print(p->Ptype); } } break; } dbg_printf("\n"); if (t->Tnext) type_print(t->Tnext); }
int main(void) { flint_rand_t state; long i; printf("inv...."); fflush(stdout); flint_randinit(state); /* Test aliasing */ for (i = 0; i < 40 * flint_test_multiplier(); i++) { elem_mat_t A, Ainv; elem_poly_t den1, den2; ring_t ZZ, ZZx, MM; long n; long size[3] = {5, 5, 5}; int ns1, ns2; int result; n = n_randint(state, 8); ring_init_fmpz(ZZ); ring_init_poly(ZZx, ZZ); ring_init_mat(MM, ZZx); elem_mat_init(A, n, n, MM); elem_mat_init(Ainv, n, n, MM); elem_init(den1, ZZx); elem_init(den2, ZZx); elem_mat_randtest(A, state, size, MM); ns1 = elem_mat_inv(Ainv, den1, A, MM); ns2 = elem_mat_inv(A, den2, A, MM); result = ns1 == ns2; if (result && ns1 != 0) { result = elem_equal(den1, den2, ZZx) && elem_mat_equal(A, Ainv, MM); } if (!result) { printf("FAIL (aliasing)!\n"); elem_mat_print(A, MM); printf("\n"); elem_mat_print(Ainv, MM); printf("\n"); abort(); } elem_mat_clear(A, MM); elem_mat_clear(Ainv, MM); elem_clear(den1, ZZx); elem_clear(den2, ZZx); } /* Check A^(-1) = A = 1 */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { elem_mat_t A, Ainv, B, Iden; elem_poly_t den, det; ring_t ZZ, ZZx, MM; long n; long size[3] = {5, 5, 5}; int nonsingular; n = n_randint(state, 8); ring_init_fmpz(ZZ); ring_init_poly(ZZx, ZZ); ring_init_mat(MM, ZZx); elem_mat_init(A, n, n, MM); elem_mat_init(Ainv, n, n, MM); elem_mat_init(B, n, n, MM); elem_mat_init(Iden, n, n, MM); elem_init(den, ZZx); elem_init(det, ZZx); elem_mat_randtest(A, state, size, MM); nonsingular = elem_mat_inv(Ainv, den, A, MM); elem_mat_det(det, A, MM); if (n == 0) { if (nonsingular == 0 || !elem_is_one(den, ZZx)) { printf("FAIL: expected empty matrix to pass\n"); abort(); } } else { /* if (!elem_equal(den, det, ZZx)) { elem_neg(det, det, ZZx); printf("FAIL: den != det(A)\n"); abort(); } */ if (nonsingular) { elem_mat_mul(B, Ainv, A, MM); elem_mat_one(Iden, MM); elem_mat_scalar_mul(Iden, Iden, den, MM); if (!elem_mat_equal(B, Iden, MM)) { printf("FAIL:\n"); printf("A:\n"); elem_mat_print(A, MM); printf("Ainv:\n"); elem_mat_print(Ainv, MM); printf("B:\n"); elem_mat_print(B, MM); printf("den:\n"); elem_print(den, ZZx); abort(); } } else { if (!elem_is_zero(det, ZZx) || !elem_is_zero(den, ZZx)) { printf("FAIL (reported invertible):\n"); printf("A:\n"); elem_mat_print(A, MM); printf("Ainv:\n"); elem_mat_print(Ainv, MM); printf("den:\n"); elem_print(den, ZZx); abort(); } } } elem_clear(den, ZZx); elem_clear(det, ZZx); elem_mat_clear(A, MM); elem_mat_clear(Ainv, MM); elem_mat_clear(B, MM); elem_mat_clear(Iden, MM); } flint_randclear(state); _fmpz_cleanup(); printf("PASS\n"); return 0; }