analyze.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /*
  2. * GTools C compiler
  3. * =================
  4. * source file :
  5. * analyzer
  6. *
  7. * Copyright 2001-2004 Paul Froissart.
  8. * Credits to Christoph van Wuellen and Matthew Brandt.
  9. * All commercial rights reserved.
  10. *
  11. * This compiler may be redistributed as long there is no
  12. * commercial interest. The compiler must not be redistributed
  13. * without its full sources. This notice must stay intact.
  14. */
  15. #include "define.h"
  16. _FILE(__FILE__)
  17. #include "c.h"
  18. #include "expr.h"
  19. #include "gen.h"
  20. #include "cglbdec.h"
  21. //#undef OPT_ROMCALLS
  22. /*
  23. * this module will step through the parse tree and find all optimizable
  24. * expressions. at present these expressions are limited to expressions that
  25. * are valid throughout the scope of the function. the list of optimizable
  26. * expressions is:
  27. *
  28. * constants
  29. * global and static addresses
  30. * auto addresses
  31. * contents of auto addresses.
  32. *
  33. * contents of auto addresses are valid only if the address is never referred to
  34. * without dereferencing.
  35. *
  36. * scan will build a list of optimizable expressions which opt1 will replace
  37. * during the second optimization pass.
  38. */
  39. void scan(struct snode *block);
  40. void repcse(struct snode *block);
  41. #define INIT_EXEC_COUNT 16
  42. FILE *list CGLOB;
  43. int regs_used CGLOB;
  44. struct enode *regexp[REGEXP_SIZE] CGLOBL;
  45. xstatic unsigned int exec_count CGLOB;
  46. xstatic struct cse *olist CGLOB; /* list of optimizable expressions */
  47. int equalnode(struct enode *node1, struct enode *node2) {
  48. /*
  49. * equalnode will return 1 if the expressions pointed to by node1 and node2
  50. * are equivalent.
  51. */
  52. if (node1 == 0 || node2 == 0)
  53. return 0;
  54. if (node1->nodetype != node2->nodetype)
  55. return 0;
  56. switch (node1->nodetype) {
  57. #ifndef AS
  58. case en_labcon:
  59. /* FALLTHROUGH - HACK : v.i==(long)v.ensp */
  60. case en_icon:
  61. #else
  62. case en_labcon:
  63. return (node1->v.enlab == node2->v.enlab);
  64. case en_icon:
  65. #endif
  66. case en_autocon:
  67. case en_tempref: // note: this one is not necessary when doing CSE, but can be useful in gen68k.c
  68. /*infunc("chk_curword")
  69. if (node2->v.i=(long)(char)0xCD)
  70. bkpt();*/
  71. return (node1->v.i == node2->v.i);
  72. case en_nacon:
  73. return (!strcmp(node1->v.ensp, node2->v.ensp));
  74. case en_ref:
  75. case en_fieldref:
  76. return equalnode(node1->v.p[0], node2->v.p[0]);
  77. default:
  78. return 0;
  79. }
  80. }
  81. static struct cse *searchnode(struct enode *node) {
  82. /*
  83. * searchnode will search the common expression table for an entry that
  84. * matches the node passed and return a pointer to it.
  85. * the top level of equalnode is code inline here for speed
  86. */
  87. register struct cse *csp;
  88. register struct enode *ep;
  89. if (node == 0)
  90. return 0;
  91. csp = olist;
  92. while (csp != 0) {
  93. ep = csp->exp;
  94. if (ep != 0 && node->nodetype == ep->nodetype) {
  95. switch (node->nodetype) {
  96. case en_icon:
  97. #ifndef AS
  98. case en_labcon:
  99. #endif
  100. case en_autocon:
  101. if (node->v.i == ep->v.i)
  102. return csp;
  103. break;
  104. #ifndef AS
  105. case en_nacon:
  106. if (!strcmp(node->v.ensp, ep->v.ensp))
  107. return csp;
  108. break;
  109. #endif
  110. #ifdef AS
  111. case en_labcon:
  112. case en_nacon:
  113. if (node->v.enlab == ep->v.enlab)
  114. return csp;
  115. break;
  116. #endif
  117. case en_ref:
  118. if (equalnode(node->v.p[0], ep->v.p[0])) {
  119. /* 05/09/03: added check for size ; struct or unions
  120. * won't work either since Gen68k needs their address
  121. */
  122. if (node->esize != ep->esize || bt_aggregate(node->etype))
  123. csp->voidf=1;
  124. return csp;
  125. }
  126. break;
  127. }
  128. }
  129. csp = csp->next;
  130. }
  131. return 0;
  132. }
  133. struct enode *copynode(struct enode *node) {
  134. /*
  135. * copy the node passed into a new enode so it wont get corrupted during
  136. * substitution.
  137. */
  138. struct enode *temp;
  139. if (node == 0)
  140. return 0;
  141. temp = (struct enode *) xalloc((int) sizeof(struct enode), ENODE+COPYNODE);
  142. *temp = *node;
  143. return temp;
  144. }
  145. static struct cse *enternode(struct enode *node, int duse) {
  146. /*
  147. * enternode will enter a reference to an expression node into the common
  148. * expression table. duse is a flag indicating whether or not this reference
  149. * will be dereferenced.
  150. */
  151. struct cse *csp;
  152. if ((csp = searchnode(node)) == 0) { /* add to tree */
  153. csp = (struct cse *) xalloc((int) sizeof(struct cse), CSE+ENTERNODE);
  154. csp->next = olist;
  155. #ifdef NO_CALLOC
  156. csp->uses = 0;
  157. csp->duses = 0;
  158. csp->voidf = 0;
  159. #endif
  160. csp->exp = copynode(node);
  161. olist = csp;
  162. if (bt_aggregate(node->etype))
  163. csp->voidf++;
  164. } else {
  165. /*
  166. * Integer constants may be in the table with different sizes -- keep
  167. * the maximum size
  168. */
  169. if (node->nodetype == en_icon && node->esize > csp->exp->esize)
  170. csp->exp->esize = node->esize;
  171. }
  172. /* infunc("chk_curword")
  173. if (node->nodetype != en_icon && node->esize==1)
  174. bkpt();*/
  175. #ifdef REGALLOC_FOR_SIZE
  176. #define exec_count INIT_EXEC_COUNT
  177. #endif
  178. csp->uses+=exec_count;
  179. if (duse)
  180. csp->duses+=exec_count;
  181. #ifdef REGALLOC_FOR_SIZE
  182. #undef exec_count
  183. #endif
  184. return csp;
  185. }
  186. static struct cse *voidauto(struct enode *node) {
  187. /*
  188. * voidauto will void an auto dereference node which points to the same auto
  189. * constant as node.
  190. */
  191. struct cse *csp;
  192. csp = olist;
  193. while (csp != 0) {
  194. if (csp->exp->nodetype==en_ref && equalnode(node, csp->exp->v.p[0])) {
  195. if (csp->voidf)
  196. return 0;
  197. csp->voidf = 1;
  198. return csp;
  199. }
  200. csp = csp->next;
  201. }
  202. return 0;
  203. }
  204. void scanexpr(struct enode *node, int duse) {
  205. /*
  206. * scanexpr will scan the expression pointed to by node for optimizable
  207. * subexpressions. when an optimizable expression is found it is entered into
  208. * the tree. if a reference to an autocon node is scanned the corresponding
  209. * auto dereferenced node will be voided. duse should be set if the
  210. * expression will be dereferenced.
  211. */
  212. struct cse *csp, *csp1;
  213. if (node == 0)
  214. return;
  215. switch (node->nodetype) {
  216. case en_nacon:
  217. #ifdef FLINE_RC
  218. if (fline_rc && node->v.ensp &&
  219. node->v.ensp[1]=='R' && node->v.ensp[0]=='_' &&
  220. !memcmp(node->v.ensp+2,"OM_CALL_",8))
  221. break;
  222. #endif
  223. /*@fallthrough@*/
  224. case en_labcon:
  225. #ifndef NO_ICONST_SCAN
  226. case en_icon:
  227. #endif
  228. (void) enternode(node, duse);
  229. break;
  230. case en_autocon:
  231. /*
  232. * look if the dereferenced use of the node is in the list, remove it
  233. * in this case
  234. */
  235. if ((csp = voidauto(node)) != 0) {
  236. csp1 = enternode(node, duse);
  237. csp1->duses += csp->uses;
  238. } else if (duse>=0) // don't enter it otherwise (we can already access it)
  239. (void) enternode(node, duse);
  240. break;
  241. case en_ref:
  242. case en_fieldref:
  243. if (node->v.p[0]->nodetype == en_autocon) {
  244. /*infunc("ChargerAdressesData")
  245. bkpt();*/
  246. {
  247. int first = (searchnode(node) == 0);
  248. /* infunc("chk_curword") if (node->v.p[0]->v.i==(long)(char)0xCD)
  249. bkpt();*/
  250. csp = enternode(node, duse);
  251. /*
  252. * take care: the non-derereferenced use of the autocon node may
  253. * already be in the list. In this case, set voidf to 1
  254. */
  255. if (searchnode(node->v.p[0]) != 0) {
  256. csp->voidf = 1;
  257. scanexpr(node->v.p[0], 1);
  258. } else if (first) {
  259. /* look for register nodes */
  260. int i = 0;
  261. XLST_TYPE j = (XLST_TYPE)node->v.p[0]->v.i, *p;
  262. p=reglst; while (i < regptr) {
  263. if (*p++ == j) {
  264. csp->voidf--; /* this is not in auto_lst */
  265. // if (regalloc[i]>=0) csp->reg=regalloc[i];
  266. csp->uses += 256 * INIT_EXEC_COUNT * (100 - i);
  267. //csp->duses += 30 * (100 - i); // so we know we don't always need an areg
  268. break;
  269. }
  270. ++i;
  271. }
  272. /* set voidf if the node is not in autolst */
  273. csp->voidf++;
  274. i = autoptr;
  275. p=autolst;
  276. while (i--)
  277. if (*p++ == j) {
  278. csp->voidf--;
  279. break;
  280. }
  281. /*
  282. * even if that item must not be put in a register,
  283. * it is legal to put its address therein
  284. */
  285. if (csp->voidf)
  286. scanexpr(node->v.p[0], 1);
  287. }
  288. }
  289. #ifdef OPT_ROMCALLS
  290. } else if (node->v.p[0]->nodetype == en_icon && node->v.p[0]->v.i == 0xC8) {
  291. enternode(node, 1);
  292. #endif
  293. } else {
  294. scanexpr(node->v.p[0], 1);
  295. }
  296. break;
  297. case en_uminus:
  298. case en_compl:
  299. case en_ainc:
  300. case en_adec:
  301. case en_not:
  302. case en_cast:
  303. case en_deref:
  304. scanexpr(node->v.p[0], duse);
  305. break;
  306. case en_alloca:
  307. scanexpr(node->v.p[0], 0);
  308. break;
  309. case en_asadd:
  310. case en_assub:
  311. case en_add:
  312. case en_sub:
  313. #ifndef NO_IMPROVED_CSE_SCAN
  314. if (duse) {
  315. if (node->v.p[0]->etype==bt_pointer
  316. || (node->v.p[1]->etype!=bt_pointer && node->v.p[0]->esize==4)
  317. || (node->v.p[1]->esize!=4)) {
  318. if (node->v.p[1]->nodetype!=en_icon)
  319. scanexpr(node->v.p[0], 1),
  320. scanexpr(node->v.p[1], 0);
  321. else
  322. scanexpr(node->v.p[0], -1);
  323. } else scanexpr(node->v.p[0], 0), scanexpr(node->v.p[1], 1);
  324. } else
  325. #endif
  326. scanexpr(node->v.p[0], 0), scanexpr(node->v.p[1], 0);
  327. /* scanexpr(node->v.p[0], duse); // why ??
  328. scanexpr(node->v.p[1], duse);*/
  329. break;
  330. case en_mul:
  331. case en_div:
  332. case en_lsh:
  333. case en_rsh:
  334. case en_mod:
  335. case en_and:
  336. case en_or:
  337. case en_xor:
  338. case en_lor:
  339. case en_land:
  340. case en_eq:
  341. case en_ne:
  342. case en_gt:
  343. case en_ge:
  344. case en_lt:
  345. case en_le:
  346. case en_asmul:
  347. case en_asdiv:
  348. case en_asmod:
  349. case en_aslsh:
  350. case en_asrsh:
  351. case en_asand:
  352. case en_asor:
  353. case en_asxor:
  354. case en_cond:
  355. case en_void:
  356. case en_assign:
  357. scanexpr(node->v.p[0], 0);
  358. scanexpr(node->v.p[1], 0);
  359. break;
  360. case en_fcall:
  361. scanexpr(node->v.p[0], 1);
  362. scanexpr(node->v.p[1], 0);
  363. break;
  364. case en_compound:
  365. scan(node->v.st);
  366. break;
  367. }
  368. }
  369. void scan(struct snode *block) {
  370. /*
  371. * scan will gather all optimizable expressions into the expression list for
  372. * a block of statements.
  373. */
  374. while (block != 0) {
  375. unsigned int old=exec_count;
  376. switch (block->stype) {
  377. case st_return:
  378. case st_expr:
  379. opt4(&block->exp);
  380. scanexpr(block->exp, 0);
  381. break;
  382. case st_loop:
  383. opt4(&block->exp);
  384. scanexpr(block->exp, 0);
  385. exec_count*=block->count;
  386. scanexpr(block->exp->v.p[0],0); // increase desirability of counter reg allocation
  387. scan(block->s1);
  388. if (block->v2.e) {
  389. opt4(&block->v2.e);
  390. scanexpr(block->v2.e, 0);
  391. }
  392. break;
  393. case st_while:
  394. case st_do:
  395. exec_count*=block->count;
  396. exec_count++;
  397. opt4(&block->exp);
  398. scanexpr(block->exp, 0);
  399. exec_count--;
  400. scan(block->s1);
  401. break;
  402. case st_for:
  403. opt4(&block->exp);
  404. scanexpr(block->exp, 0);
  405. exec_count*=block->count;
  406. opt4(&block->v1.e);
  407. scanexpr(block->v1.e, 0);
  408. scan(block->s1);
  409. opt4(&block->v2.e);
  410. scanexpr(block->v2.e, 0);
  411. break;
  412. case st_if:
  413. opt4(&block->exp);
  414. scanexpr(block->exp, 0);
  415. exec_count=(unsigned int)(((unsigned long)exec_count*(unsigned long)block->count+32768)>>16);
  416. scan(block->s1);
  417. exec_count=old-exec_count;
  418. scan(block->v1.s);
  419. break;
  420. case st_switch:
  421. opt4(&block->exp);
  422. scanexpr(block->exp, 0);
  423. exec_count>>=1;
  424. scan(block->v1.s);
  425. break;
  426. case st_case:
  427. case st_default:
  428. scan(block->v1.s);
  429. break;
  430. case st_compound:
  431. case st_label:
  432. scan(block->s1);
  433. break;
  434. }
  435. block = block->next;
  436. exec_count=old;
  437. }
  438. }
  439. unsigned long desire(struct cse *csp) {
  440. /*
  441. * returns the desirability of optimization for a subexpression.
  442. */
  443. #ifdef INFINITE_REGISTERS
  444. return 4294967295;
  445. #endif
  446. if (csp->voidf || (csp->exp->nodetype == en_icon &&
  447. // (unsigned int)csp->exp->v.i+8 <= 16))
  448. csp->exp->v.i < 16 && csp->exp->v.i >= 0))
  449. return 0;
  450. #ifdef REGPARM_OLD
  451. { struct enode *ep;
  452. if (csp->exp->nodetype == en_ref && (ep=csp->exp->v.p[0])->nodetype == en_autocon
  453. && ep->v.i>0 && (ep->v.i&REG_PARAMS))
  454. return 10000000; // if it's a register param, then it *must* be in a long-live reg
  455. }
  456. #endif
  457. if (g_lvalue(csp->exp))
  458. return 2 * csp->uses;
  459. return csp->uses;
  460. }
  461. void bsort(struct cse **list) {
  462. /*
  463. * bsort implements a bubble sort on the expression list.
  464. */
  465. struct cse *csp1, *csp2;
  466. csp1 = *list;
  467. if (csp1 == 0 || csp1->next == 0)
  468. return;
  469. bsort(&(csp1->next));
  470. while (csp1 != 0 && (csp2 = csp1->next) != 0 && desire(csp1) < desire(csp2)) {
  471. *list = csp2;
  472. csp1->next = csp2->next;
  473. csp2->next = csp1;
  474. list = &(csp2->next);
  475. }
  476. }
  477. #ifdef REGPARM_OLD
  478. extern struct typ *head;
  479. #define parm_val (_parm_val+1)
  480. XLST_TYPE _parm_val[1+MAX_DATA+1+MAX_ADDR+1];
  481. int parm_reg[MAX_DATA+1+MAX_ADDR+1];
  482. #endif
  483. void allocate(void) {
  484. /*
  485. * allocate will allocate registers for the expressions that have a high
  486. * enough desirability.
  487. */
  488. struct cse *csp;
  489. struct enode *exptr/*,*ep*/;
  490. reg_t datareg, addreg;
  491. #ifdef AREG_AS_DREG
  492. int areg_possible;
  493. #endif
  494. unsigned int mask, rmask;
  495. struct amode *ap, *ap2;
  496. //#define __DEBUG__
  497. /*#ifdef __DEBUG__
  498. int i=0;*
  499. #endif*/
  500. regs_used = 0;
  501. datareg = MAX_DATA+1;
  502. addreg = MAX_ADDR+1 + AREGBASE;
  503. mask = 0;
  504. rmask = 0;
  505. bsort(&olist); /* sort the expression list */
  506. csp = olist;
  507. /* infunc("play")
  508. bkpt();*/ //autoptr=0,regptr=0;
  509. while (csp != 0) {
  510. /*#ifdef __DEBUG__
  511. infunc("play")
  512. if (i++==2) {
  513. csp->voidf=1;
  514. regs_used++;
  515. rmask = rmask | (1 << (15 - datareg));
  516. mask = mask | (1 << datareg);
  517. datareg++;
  518. }
  519. #endif*/
  520. /*
  521. * If reg_option is not true, the 'desire' value must be at least
  522. * 5000, which I hope can only be achieved by the 'register' attribute
  523. */
  524. if (desire(csp) < 3*INIT_EXEC_COUNT || (!reg_option && desire(csp) < 5000))
  525. csp->reg = -1;
  526. #ifndef AREG_AS_DREG
  527. else if (csp->duses &&
  528. #else
  529. else if ((areg_possible=
  530. #endif
  531. /* && (csp->duses * 3) > csp->uses */
  532. addreg <
  533. #ifdef USE_LINK
  534. FRAMEPTR
  535. #else
  536. STACKPTR - uses_link
  537. #endif
  538. /*
  539. * integer constants may have different types
  540. */
  541. && (csp->exp->nodetype == en_icon
  542. /*
  543. * the types which are fine in address registers
  544. */
  545. || (csp->exp->etype == bt_short ||
  546. csp->exp->etype == bt_long ||
  547. csp->exp->etype == bt_ulong ||
  548. csp->exp->etype == bt_pointer))
  549. #ifndef AREG_AS_DREG
  550. )
  551. #else
  552. ) && csp->duses)
  553. #endif
  554. csp->reg = addreg++;
  555. else if (datareg < AREGBASE && csp->exp->nodetype!=en_autocon)
  556. csp->reg = datareg++;
  557. #ifdef AREG_AS_DREG
  558. else if (areg_possible)
  559. csp->reg = addreg++;
  560. #endif
  561. else
  562. csp->reg = -1;
  563. /* infunc("chk_curword")
  564. if (csp->reg==AREGBASE+2 || csp->reg==AREGBASE+3 || csp->reg==4)
  565. bkpt();*/
  566. if (csp->reg IS_VALID) {
  567. regexp[reg_t_to_regexp(csp->reg)] = csp->exp;
  568. regs_used++;
  569. rmask = rmask | (1 << (15 - csp->reg));
  570. mask = mask | (1 << csp->reg);
  571. }
  572. csp = csp->next;
  573. }
  574. #ifdef ADD_REDUNDANCY
  575. if (regs_used>=6) { /* >=6 : won't increase the push/pop time very much */
  576. mask = 0x7CF8, rmask = 0x1F3E;
  577. regs_used = 10;
  578. /* (note that we could use less than 6 as a threshold, but the benefit lies around
  579. +0.5% while the runtime cost is rather high for such functions)
  580. (note too that the benefit for the optimization with threshold 6 is around 0.5%
  581. only, but it is so inexpensive that we really can afford it :] ) */
  582. }
  583. #endif
  584. if (mask != 0) {
  585. g_code(op_movem, 4, mk_rmask(rmask), push_am);
  586. #ifdef ICODE
  587. if (icode_option)
  588. fprintf(icode, "\t$regpush %04x\n", rmask);
  589. #endif
  590. }
  591. save_mask = mask;
  592. csp = olist;
  593. while (csp != 0) {
  594. if (csp->reg IS_VALID) { /* see if preload needed */
  595. exptr = csp->exp;
  596. #ifdef REGPARM_OLD
  597. /* the following code works since REGPARM's are always
  598. * handled first -- their desire() is highest */
  599. if (exptr->nodetype==en_ref && (ep=exptr->v.p[0])->nodetype==en_autocon
  600. && ep->v.i>0 && (ep->v.i&REG_PARAMS)) {
  601. ap = mk_reg(ep->v.i>>REG_PARAMLOG);
  602. ap2 = mk_reg(csp->reg);
  603. g_code(op_move, (int) exptr->esize, ap, ap2);
  604. } else
  605. #endif
  606. if (exptr->nodetype!=en_ref
  607. #ifdef OPT_ROMCALLS
  608. || exptr->v.p[0]->nodetype!=en_autocon
  609. #endif
  610. #ifdef REGPARM
  611. || ((XLST_TYPE)exptr->v.p[0]->v.i >= -reg_size)) {
  612. #else
  613. || ((XLST_TYPE)exptr->v.p[0]->v.i > 0)) {
  614. #endif
  615. initstack();
  616. ap = g_expr(exptr, F_ALL | F_SRCOP);
  617. ap2 = mk_reg(csp->reg);
  618. g_code(op_move, (int) exptr->esize, ap, ap2);
  619. freeop(ap);
  620. #ifdef ICODE
  621. if (icode_option) {
  622. fprintf(icode, "$reg ");
  623. if (csp->reg < AREGBASE)
  624. fprintf(icode, "D%d\n", csp->reg);
  625. else
  626. fprintf(icode, "A%d\n", csp->reg - AREGBASE);
  627. g_icode(exptr);
  628. }
  629. #endif
  630. }
  631. }
  632. csp = csp->next;
  633. }
  634. }
  635. #ifdef NO_EXTENDED_AUTOS
  636. void repexpr(struct enode *node) {
  637. #else
  638. #define repexpr(node) _repexpr(&(node))
  639. void _repexpr(struct enode **ep) {
  640. struct enode *node=*ep;
  641. #endif
  642. /*
  643. * repexpr will replace all allocated references within an expression with
  644. * tempref nodes.
  645. */
  646. struct cse *csp;
  647. if (node == 0)
  648. return;
  649. switch (node->nodetype) {
  650. case en_icon:
  651. case en_nacon:
  652. case en_labcon:
  653. case en_autocon:
  654. if ((csp = searchnode(node)) != 0) {
  655. if (csp->reg > 0) {
  656. node->nodetype = en_tempref;
  657. node->v.i = csp->reg;
  658. }
  659. }
  660. break;
  661. case en_ref:
  662. case en_fieldref:
  663. if ((csp = searchnode(node)) != 0) {
  664. if (csp->reg > 0) {
  665. node->nodetype = en_tempref;
  666. node->v.i = csp->reg;
  667. } else
  668. repexpr(node->v.p[0]);
  669. } else
  670. repexpr(node->v.p[0]);
  671. break;
  672. case en_uminus:
  673. case en_not:
  674. case en_compl:
  675. case en_ainc:
  676. case en_adec:
  677. case en_cast:
  678. case en_deref:
  679. case en_alloca:
  680. repexpr(node->v.p[0]);
  681. break;
  682. case en_add:
  683. if (node->v.p[0]->nodetype==en_autocon && node->v.p[1]->nodetype==en_icon) {
  684. /**ep=mk_icon(node->v.p[0]->v.i+node->v.p[1]->v.i);
  685. (*ep)->nodetype=en_autocon;
  686. (*ep)->etype=bt_pointer;
  687. (*ep)->esize=4;*/
  688. node->v.p[0]->v.i+=node->v.p[1]->v.i;
  689. *ep=node->v.p[0];
  690. return;
  691. }
  692. /*@fallthrough@*/
  693. case en_sub:
  694. case en_mul:
  695. case en_div:
  696. case en_mod:
  697. case en_lsh:
  698. case en_rsh:
  699. case en_and:
  700. case en_or:
  701. case en_xor:
  702. case en_land:
  703. case en_lor:
  704. case en_eq:
  705. case en_ne:
  706. case en_lt:
  707. case en_le:
  708. case en_gt:
  709. case en_ge:
  710. case en_cond:
  711. case en_void:
  712. case en_asadd:
  713. case en_assub:
  714. case en_asmul:
  715. case en_asdiv:
  716. case en_asor:
  717. case en_asxor:
  718. case en_asand:
  719. case en_asmod:
  720. case en_aslsh:
  721. case en_asrsh:
  722. case en_fcall:
  723. case en_assign:
  724. repexpr(node->v.p[0]);
  725. repexpr(node->v.p[1]);
  726. break;
  727. case en_compound:
  728. repcse(node->v.st);
  729. break;
  730. }
  731. }
  732. void repcse(struct snode *block) {
  733. /*
  734. * repcse will scan through a block of statements replacing the optimized
  735. * expressions with their temporary references.
  736. */
  737. while (block != 0) {
  738. switch (block->stype) {
  739. case st_return:
  740. case st_expr:
  741. repexpr(block->exp);
  742. break;
  743. case st_loop:
  744. repexpr(block->exp);
  745. repcse(block->s1);
  746. repexpr(block->v2.e);
  747. break;
  748. case st_while:
  749. case st_do:
  750. repexpr(block->exp);
  751. repcse(block->s1);
  752. break;
  753. case st_for:
  754. repexpr(block->exp);
  755. repexpr(block->v1.e);
  756. repcse(block->s1);
  757. repexpr(block->v2.e);
  758. break;
  759. case st_if:
  760. repexpr(block->exp);
  761. repcse(block->s1);
  762. repcse(block->v1.s);
  763. break;
  764. case st_switch:
  765. repexpr(block->exp);
  766. repcse(block->v1.s);
  767. break;
  768. case st_case:
  769. case st_default:
  770. repcse(block->v1.s);
  771. break;
  772. case st_compound:
  773. case st_label:
  774. repcse(block->s1);
  775. break;
  776. }
  777. block = block->next;
  778. }
  779. }
  780. void opt1(struct snode *block) {
  781. /*
  782. * opt1 is the externally callable optimization routine. it will collect and
  783. * allocate common subexpressions and substitute the tempref for all
  784. * occurrances of the expression within the block.
  785. *
  786. */
  787. if (!opt_option)
  788. return;
  789. olist = 0;
  790. exec_count = INIT_EXEC_COUNT;
  791. scan(block); /* collect expressions */
  792. allocate(); /* allocate registers */
  793. repcse(block); /* replace allocated expressions */
  794. }
  795. // vim:ts=4:sw=4