optimize.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. /*
  2. * GTools C compiler
  3. * =================
  4. * source file :
  5. * optimization
  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. static void fold_const();
  22. void dooper(struct enode **node) {
  23. /*
  24. * dooper will execute a constant operation in a node and modify the node to
  25. * be the result of the operation.
  26. */
  27. struct enode *ep = *node;
  28. enum(e_node) type = ep->nodetype;
  29. #define ep0 ep->v.p[0]
  30. #define ep1 ep->v.p[1]
  31. #define epi ep->v.i
  32. #define epf ep->v.f
  33. #define ulong unsigned long
  34. ep->nodetype = ep0->nodetype;
  35. if (ep0->nodetype == en_fcon) {
  36. #ifndef NOFLOAT
  37. switch (type) {
  38. case en_uminus:
  39. #ifdef PC
  40. epf = - ep0->v.f;
  41. #else
  42. epf = ep0->v.f;
  43. if (epf) epf^=0x80;
  44. #endif
  45. break;
  46. case en_not:
  47. ep->nodetype = en_icon;
  48. epi = (ep0->v.f) ? 0 : 1;
  49. break;
  50. case en_add:
  51. #ifdef PC
  52. epf = ep0->v.f + ep1->v.f;
  53. #else
  54. epf = ffpadd(ep0->v.f, ep1->v.f);
  55. #endif
  56. break;
  57. case en_sub:
  58. #ifdef PC
  59. epf = ep0->v.f - ep1->v.f;
  60. #else
  61. epf = ffpsub(ep0->v.f, ep1->v.f);
  62. #endif
  63. break;
  64. case en_mul:
  65. #ifdef PC
  66. epf = ep0->v.f * ep1->v.f;
  67. #else
  68. epf = ffpmul(ep0->v.f, ep1->v.f);
  69. #endif
  70. break;
  71. case en_div:
  72. if (ep1->v.f == 0) {
  73. uwarn("division by zero");
  74. ep->nodetype = en_div;
  75. } else {
  76. #ifdef PC
  77. epf = ep0->v.f / ep1->v.f;
  78. #else
  79. epf = ffpdiv(ep0->v.f, ep1->v.f);
  80. #endif
  81. }
  82. break;
  83. case en_eq:
  84. ep->nodetype = en_icon;
  85. epi = (ep0->v.f == ep1->v.f) ? 1 : 0;
  86. break;
  87. case en_ne:
  88. ep->nodetype = en_icon;
  89. epi = (ep0->v.f != ep1->v.f) ? 1 : 0;
  90. break;
  91. case en_land:
  92. ep->nodetype = en_icon;
  93. epi = (ep0->v.f && ep1->v.f) ? 1 : 0;
  94. break;
  95. case en_lor:
  96. ep->nodetype = en_icon;
  97. epi = (ep0->v.f || ep1->v.f) ? 1 : 0;
  98. break;
  99. case en_lt:
  100. ep->nodetype = en_icon;
  101. #ifdef PC
  102. epi = (ep0->v.f < ep1->v.f) ? 1 : 0;
  103. #else
  104. epi = (ffpcmp_c(ep0->v.f, ep1->v.f) < 0) ? 1 : 0;
  105. #endif
  106. break;
  107. case en_le:
  108. ep->nodetype = en_icon;
  109. #ifdef PC
  110. epi = (ep0->v.f <= ep1->v.f) ? 1 : 0;
  111. #else
  112. epi = (ffpcmp_c(ep0->v.f, ep1->v.f) <= 0) ? 1 : 0;
  113. #endif
  114. break;
  115. case en_gt:
  116. ep->nodetype = en_icon;
  117. #ifdef PC
  118. epi = (ep0->v.f > ep1->v.f) ? 1 : 0;
  119. #else
  120. epi = (ffpcmp_c(ep0->v.f, ep1->v.f) > 0) ? 1 : 0;
  121. #endif
  122. break;
  123. case en_ge:
  124. ep->nodetype = en_icon;
  125. #ifdef PC
  126. epi = (ep0->v.f >= ep1->v.f) ? 1 : 0;
  127. #else
  128. epi = (ffpcmp_c(ep0->v.f, ep1->v.f) >= 0) ? 1 : 0;
  129. #endif
  130. break;
  131. default:
  132. ep->nodetype = type;
  133. iwarn(DOOPER,1);
  134. break;
  135. }
  136. #endif /* NOFLOAT */
  137. return;
  138. }
  139. /*
  140. * Thus, ep0->nodetype is en_icon
  141. * We have to distinguish unsigned long from the other cases
  142. *
  143. * Since we always store in ep->v.i, it is
  144. * ASSUMED THAT (long) (ulong) ep->v.i == ep->v.i always
  145. */
  146. if (ep0->etype == bt_ulong || ep0->etype == bt_pointer) {
  147. switch (type) {
  148. case en_uminus:
  149. epi = - ep0->v.i;
  150. break;
  151. case en_not:
  152. epi = ((ulong) ep0->v.i) ? 0 : 1;
  153. break;
  154. case en_compl:
  155. epi = ~ (ulong) ep0->v.i;
  156. epi = strip_icon(epi, ep->etype);
  157. break;
  158. case en_add:
  159. epi = (ulong) ep0->v.i + (ulong) ep1->v.i;
  160. break;
  161. case en_sub:
  162. epi = (ulong) ep0->v.i - (ulong) ep1->v.i;
  163. break;
  164. case en_mul:
  165. epi = (ulong) ep0->v.i * (ulong) ep1->v.i;
  166. break;
  167. case en_div:
  168. if ((ulong) ep1->v.i == 0) {
  169. uwarn("division by zero");
  170. ep->nodetype = en_div;
  171. } else {
  172. epi = (ulong) ep0->v.i / (ulong) ep1->v.i;
  173. }
  174. break;
  175. case en_mod:
  176. if ((ulong) ep1->v.i == 0) {
  177. uwarn("division by zero");
  178. ep->nodetype = en_mod;
  179. } else {
  180. epi = (ulong) ep0->v.i % (ulong) ep1->v.i;
  181. }
  182. break;
  183. case en_and:
  184. epi = (ulong) ep0->v.i & (ulong) ep1->v.i;
  185. break;
  186. case en_or:
  187. epi = (ulong) ep0->v.i | (ulong) ep1->v.i;
  188. break;
  189. case en_xor:
  190. epi = (ulong) ep0->v.i ^ (ulong) ep1->v.i;
  191. break;
  192. case en_eq:
  193. epi = ((ulong) ep0->v.i == (ulong) ep1->v.i) ? 1 : 0;
  194. break;
  195. case en_ne:
  196. epi = ((ulong) ep0->v.i != (ulong) ep1->v.i) ? 1 : 0;
  197. break;
  198. case en_land:
  199. epi = ((ulong) ep0->v.i && (ulong) ep1->v.i) ? 1 : 0;
  200. break;
  201. case en_lor:
  202. epi = ((ulong) ep0->v.i || (ulong) ep1->v.i) ? 1 : 0;
  203. break;
  204. case en_lt:
  205. epi = ((ulong) ep0->v.i < (ulong) ep1->v.i) ? 1 : 0;
  206. break;
  207. case en_le:
  208. epi = ((ulong) ep0->v.i <= (ulong) ep1->v.i) ? 1 : 0;
  209. break;
  210. case en_gt:
  211. epi = ((ulong) ep0->v.i > (ulong) ep1->v.i) ? 1 : 0;
  212. break;
  213. case en_ge:
  214. epi = ((ulong) ep0->v.i >= (ulong) ep1->v.i) ? 1 : 0;
  215. break;
  216. case en_lsh:
  217. #ifdef MINIMAL_SIZES
  218. epi = (ulong) ep0->v.i << (char) ep1->v.i;
  219. #else
  220. epi = (ulong) ep0->v.i << (ulong) ep1->v.i;
  221. #endif
  222. break;
  223. case en_rsh:
  224. #ifdef MINIMAL_SIZES
  225. epi = (ulong) ep0->v.i >> (char) ep1->v.i;
  226. #else
  227. epi = (ulong) ep0->v.i >> (ulong) ep1->v.i;
  228. #endif
  229. break;
  230. default:
  231. ep->nodetype = type;
  232. iwarn(DOOPER,2);
  233. break;
  234. }
  235. } else {
  236. switch (type) {
  237. case en_uminus:
  238. epi = - ep0->v.i;
  239. break;
  240. case en_not:
  241. epi = (ep0->v.i) ? 0 : 1;
  242. break;
  243. case en_compl:
  244. epi = ~ ep0->v.i;
  245. epi = strip_icon(epi, type);
  246. break;
  247. case en_add:
  248. epi = ep0->v.i + ep1->v.i;
  249. break;
  250. case en_sub:
  251. epi = ep0->v.i - ep1->v.i;
  252. break;
  253. case en_mul:
  254. epi = ep0->v.i * ep1->v.i;
  255. break;
  256. case en_div:
  257. if (ep1->v.i == 0) {
  258. uwarn("division by zero");
  259. ep->nodetype = en_div;
  260. } else {
  261. epi = ep0->v.i / ep1->v.i;
  262. }
  263. break;
  264. case en_mod:
  265. if (ep1->v.i == 0) {
  266. uwarn("division by zero");
  267. ep->nodetype = en_mod;
  268. } else {
  269. epi = ep0->v.i % ep1->v.i;
  270. }
  271. break;
  272. case en_and:
  273. epi = ep0->v.i & ep1->v.i;
  274. break;
  275. case en_or:
  276. epi = ep0->v.i | ep1->v.i;
  277. break;
  278. case en_xor:
  279. epi = ep0->v.i ^ ep1->v.i;
  280. break;
  281. case en_eq:
  282. epi = (ep0->v.i == ep1->v.i) ? 1 : 0;
  283. break;
  284. case en_ne:
  285. epi = (ep0->v.i != ep1->v.i) ? 1 : 0;
  286. break;
  287. case en_land:
  288. epi = (ep0->v.i && ep1->v.i) ? 1 : 0;
  289. break;
  290. case en_lor:
  291. epi = (ep0->v.i || ep1->v.i) ? 1 : 0;
  292. break;
  293. case en_lt:
  294. epi = (ep0->v.i < ep1->v.i) ? 1 : 0;
  295. break;
  296. case en_le:
  297. epi = (ep0->v.i <= ep1->v.i) ? 1 : 0;
  298. break;
  299. case en_gt:
  300. epi = (ep0->v.i > ep1->v.i) ? 1 : 0;
  301. break;
  302. case en_ge:
  303. epi = (ep0->v.i >= ep1->v.i) ? 1 : 0;
  304. break;
  305. case en_lsh:
  306. #ifdef MINIMAL_SIZES
  307. epi = ep0->v.i << (char)ep1->v.i;
  308. #else
  309. epi = ep0->v.i << ep1->v.i;
  310. #endif
  311. break;
  312. case en_rsh:
  313. #ifdef MINIMAL_SIZES
  314. epi = ep0->v.i >> (char)ep1->v.i;
  315. #else
  316. epi = ep0->v.i >> ep1->v.i;
  317. #endif
  318. break;
  319. default:
  320. ep->nodetype = type;
  321. iwarn(DOOPER,3);
  322. break;
  323. }
  324. }
  325. #undef ep0
  326. #undef ep1
  327. #undef epi
  328. #undef epf
  329. #undef ulong
  330. }
  331. int pwrof2(long i) {
  332. /*
  333. * return which power of two i is or -1.
  334. */
  335. int p;
  336. long q;
  337. q = 2;
  338. p = 1;
  339. while (q > 0) {
  340. if (q == i)
  341. return p;
  342. q <<= 1;
  343. ++p;
  344. }
  345. return -1;
  346. }
  347. long mod_mask(long i) {
  348. /*
  349. * make a mod mask for a power of two.
  350. */
  351. long m;
  352. m = 0;
  353. while (i--)
  354. m = (m << 1) | 1;
  355. return m;
  356. }
  357. void opt0(struct enode **node) {
  358. /*
  359. * opt0 - delete useless expressions and combine constants.
  360. *
  361. * opt0 will delete expressions such as x + 0,
  362. * x - 0,
  363. * x * 0,
  364. * x * 1,
  365. * 0 / x,
  366. * x / 1,
  367. * x % (1<<3),
  368. * etc from the tree pointed to by node and combine obvious
  369. * constant operations. It cannot combine name and label constants but will
  370. * combine icon type nodes.
  371. */
  372. struct enode *ep;
  373. #define ep0 ep->v.p[0]
  374. #define ep1 ep->v.p[1]
  375. long val, sc;
  376. enum(e_node) typ;
  377. ep = *node;
  378. if (ep == 0)
  379. return;
  380. typ = ep->nodetype;
  381. switch (typ) {
  382. case en_ref:
  383. case en_fieldref:
  384. case en_ainc:
  385. case en_adec:
  386. case en_deref:
  387. opt0(&ep0);
  388. break;
  389. case en_uminus:
  390. case en_compl:
  391. opt0(&ep0);
  392. /*
  393. * This operation applied twice is a no-op
  394. */
  395. if (ep0->nodetype == typ) {
  396. *node = ep0->v.p[0];
  397. break;
  398. }
  399. if (ep0->nodetype == en_icon || ep0->nodetype == en_fcon)
  400. dooper(node);
  401. break;
  402. case en_not:
  403. opt0(&ep0);
  404. if (ep0->nodetype == en_icon || ep0->nodetype == en_fcon)
  405. dooper(node);
  406. break;
  407. case en_add:
  408. case en_sub:
  409. opt0(&ep0);
  410. opt0(&ep1);
  411. /*
  412. * a + (-b) = a - b
  413. * a - (-b) = a + b
  414. * (-a) + b = b - a
  415. */
  416. if (ep1->nodetype == en_uminus) {
  417. ep1 = ep1->v.p[0];
  418. ep->nodetype = typ = (typ == en_add) ? en_sub : en_add;
  419. }
  420. if (ep0->nodetype == en_uminus && typ == en_add) {
  421. ep0 = ep0->v.p[0];
  422. swap_nodes(ep);
  423. ep->nodetype = typ = en_sub;
  424. }
  425. /*
  426. * constant expressions
  427. */
  428. if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
  429. (ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
  430. dooper(node);
  431. break;
  432. }
  433. /*infunc("DrawNumberOfClock")
  434. bkpt();*/
  435. /* the following would bug, as :
  436. short my_array[2]={12,570};
  437. int i=2;
  438. while (i--) printf("%d",my_array[i]);
  439. wouldn't print 570 correctly... */
  440. #ifdef BUGGY_AND_ANYWAY_NOT_COMPAT_WITH_NO_OFFSET_AUTOCON
  441. if (typ == en_add) {
  442. if (ep1->nodetype == en_autocon)
  443. swap_nodes(ep);
  444. }
  445. #endif
  446. if (ep0->nodetype == en_icon) {
  447. if (ep0->v.i == 0) {
  448. if (typ == en_sub) {
  449. ep0 = ep1;
  450. ep->nodetype = typ = en_uminus;
  451. } else
  452. *node = ep1;
  453. break;
  454. #ifdef PREFER_POS_VALUES
  455. } else if (ep0->nodetype==en_add && ep0->v.i<0) {
  456. ep0->v.i=-ep0->v.i;
  457. swap_nodes(ep);
  458. ep->nodetype=en_sub;
  459. #endif
  460. }
  461. } else if (ep1->nodetype == en_icon) {
  462. #ifdef BUGGY_AND_ANYWAY_NOT_COMPAT_WITH_NO_OFFSET_AUTOCON
  463. if (ep0->nodetype == en_autocon && typ == en_add) {
  464. ep0->v.i += ep1->v.i;
  465. *node = ep0;
  466. break;
  467. }
  468. #endif
  469. if (ep1->v.i == 0) {
  470. *node = ep0;
  471. break;
  472. #ifdef PREFER_POS_VALUES
  473. } else if (ep1->v.i<0) {
  474. ep->nodetype^=1;
  475. ep1->v.i=-ep1->v.i;
  476. #endif
  477. }
  478. }
  479. break;
  480. case en_mul:
  481. opt0(&ep0);
  482. opt0(&ep1);
  483. /*
  484. * constant expressions
  485. */
  486. if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
  487. (ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
  488. dooper(node);
  489. break;
  490. }
  491. if (ep0->nodetype == en_icon) {
  492. val = ep0->v.i;
  493. if (val == 0) {
  494. *node = ep0;
  495. break;
  496. }
  497. if (val == 1) {
  498. *node = ep1;
  499. break;
  500. }
  501. sc = pwrof2(val);
  502. if (sc IS_VALID) {
  503. swap_nodes(ep);
  504. ep1->v.i = sc;
  505. ep->nodetype = en_lsh;
  506. }
  507. } else if (ep1->nodetype == en_icon) {
  508. val = ep1->v.i;
  509. if (val == 0) {
  510. *node = ep1;
  511. break;
  512. }
  513. if (val == 1) {
  514. *node = ep0;
  515. break;
  516. }
  517. sc = pwrof2(val);
  518. if (sc IS_VALID) {
  519. ep1->v.i = sc;
  520. ep->nodetype = en_lsh;
  521. }
  522. }
  523. break;
  524. case en_div:
  525. opt0(&ep0);
  526. opt0(&ep1);
  527. /*
  528. * constant expressions
  529. */
  530. if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
  531. (ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
  532. dooper(node);
  533. break;
  534. }
  535. if (ep0->nodetype == en_icon) {
  536. if (ep0->v.i == 0) { /* 0/x */
  537. *node = ep0;
  538. break;
  539. }
  540. } else if (ep1->nodetype == en_icon) {
  541. val = ep1->v.i;
  542. if (val == 1) { /* x/1 */
  543. *node = ep0;
  544. break;
  545. }
  546. sc = pwrof2(val);
  547. if (sc IS_VALID) {
  548. ep1->v.i = sc;
  549. ep->nodetype = en_rsh;
  550. }
  551. }
  552. break;
  553. case en_mod:
  554. opt0(&ep0);
  555. opt0(&ep1);
  556. /*
  557. * constant expressions
  558. */
  559. if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
  560. (ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
  561. dooper(node);
  562. break;
  563. }
  564. if (ep1->nodetype == en_icon) {
  565. sc = pwrof2(ep1->v.i);
  566. if (sc IS_VALID) {
  567. ep1->v.i = mod_mask(sc);
  568. ep->nodetype = en_and;
  569. }
  570. }
  571. break;
  572. case en_land:
  573. case en_lor:
  574. #if 0 /* perhaps this isn't *that* useful... and ep0/ep1 are long to access */
  575. opt0(&ep0);
  576. opt0(&ep1);
  577. if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
  578. (ep0->nodetype == en_fcon && ep1->nodetype == en_fcon))
  579. dooper(node);
  580. else {
  581. typ = (typ==en_lor);
  582. if (ep0->nodetype == en_icon) {
  583. if ((!ep0->v.i)!=typ) /* absorbing element */
  584. ep = ep0;
  585. else /* "neutral" element */
  586. //ep = ep1; -> not quite, should be !!x
  587. (void)0;
  588. } else if (ep1->nodetype == en_icon) {
  589. if ((!ep1->v.i)!=typ) /* absorbing element */
  590. ep->nodetype = en_void, ep1->v.i=typ;
  591. else /* "neutral" element */
  592. //ep = ep0; -> not quite, should be !!x
  593. (void)0;
  594. }
  595. }
  596. break;
  597. #else
  598. /* FALL THROUGH */
  599. #endif
  600. case en_and:
  601. case en_or:
  602. case en_xor:
  603. case en_eq:
  604. case en_ne:
  605. case en_lt:
  606. case en_le:
  607. case en_gt:
  608. case en_ge:
  609. opt0(&ep0);
  610. opt0(&ep1);
  611. /*
  612. * constant expressions
  613. */
  614. if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
  615. (ep0->nodetype == en_fcon && ep1->nodetype == en_fcon))
  616. dooper(node);
  617. break;
  618. case en_lsh:
  619. case en_rsh:
  620. opt0(&ep0);
  621. opt0(&ep1);
  622. if (ep0->nodetype == en_icon && ep1->nodetype == en_icon) {
  623. dooper(node);
  624. break;
  625. }
  626. /*
  627. * optimize a << 0 and a >> 0
  628. */
  629. if (ep1->nodetype == en_icon && ep1->v.i == 0)
  630. *node = ep0;
  631. break;
  632. case en_cond:
  633. opt0(&ep0);
  634. opt0(&ep1);
  635. if (ep0->nodetype == en_icon) {
  636. if (ep0->v.i) {
  637. if (ep1->v.p[0]) *node=ep1->v.p[0];
  638. else *node=ep0;
  639. } else
  640. *node=ep1->v.p[1];
  641. }
  642. break;
  643. case en_asand:
  644. case en_asor:
  645. case en_asxor:
  646. case en_asadd:
  647. case en_assub:
  648. case en_asmul:
  649. case en_asdiv:
  650. case en_asmod:
  651. case en_asrsh:
  652. case en_aslsh:
  653. case en_fcall:
  654. case en_void:
  655. case en_assign:
  656. opt0(&ep0);
  657. opt0(&ep1);
  658. break;
  659. /* now handled in expr.c */
  660. case en_cast:
  661. opt0(&ep0);
  662. if (ep0->nodetype == en_icon) {
  663. #ifndef NOFLOAT
  664. if (ep->etype != bt_float
  665. #ifdef DOUBLE
  666. && ep->etype != bt_double
  667. #endif
  668. ) {
  669. #endif
  670. ierr(OPT0,1);
  671. /* ep->nodetype = en_icon;
  672. ep->v.i = ep0->v.i;*/
  673. #ifndef NOFLOAT
  674. } else {
  675. #ifdef XCON_DOESNT_SUPPORT_FLOATS
  676. #error Fix me now :)
  677. #endif
  678. ep->nodetype = en_fcon;
  679. #ifdef PC
  680. ep->v.f = (double)ep0->v.i;
  681. #else
  682. #ifndef BCDFLT
  683. ep->v.f = ffpltof(ep0->v.i);
  684. #else
  685. ep->v.f = (double)ep0->v.i;
  686. #endif
  687. #endif
  688. }
  689. #endif
  690. }
  691. /* perhaps BUGGY */
  692. else if ((ep0->nodetype == en_labcon || ep0->nodetype == en_nacon)
  693. && ep->esize<=ep0->esize) {
  694. ep0->etype = ep->etype;
  695. ep0->esize = ep->esize;
  696. ep=ep0;
  697. *node=ep;
  698. }
  699. #ifndef NOFLOAT
  700. else if (ep0->nodetype == en_fcon && bt_integral(ep->etype)) {
  701. ep->nodetype = en_icon;
  702. #ifdef PC
  703. ep->v.i = (long)ep0->v.f;
  704. #else
  705. ep->v.i = ffpftol(ep0->v.f);
  706. #endif
  707. }
  708. #endif
  709. break;
  710. /*case en_icon:
  711. case en_fcon:
  712. case en_labcon:
  713. case en_nacon:
  714. case en_autocon:
  715. case en_tempref:
  716. break;
  717. default:
  718. uwarn("Didn't optimize nodetype %d. Please send me your source code.",typ);*/
  719. }
  720. #undef ep0
  721. #undef ep1
  722. }
  723. static long xfold(struct enode *node) {
  724. /*
  725. * xfold will remove constant nodes and return the values to the calling
  726. * routines.
  727. */
  728. long i;
  729. if (node == 0)
  730. return 0;
  731. switch (node->nodetype) {
  732. case en_icon:
  733. i = node->v.i;
  734. node->v.i = 0;
  735. return i;
  736. case en_add:
  737. return xfold(node->v.p[0]) + xfold(node->v.p[1]);
  738. case en_sub:
  739. return xfold(node->v.p[0]) - xfold(node->v.p[1]);
  740. case en_mul:
  741. if (node->v.p[0]->nodetype == en_icon)
  742. return xfold(node->v.p[1]) * node->v.p[0]->v.i;
  743. else if (node->v.p[1]->nodetype == en_icon)
  744. return xfold(node->v.p[0]) * node->v.p[1]->v.i;
  745. else {
  746. fold_const(&node->v.p[0]);
  747. fold_const(&node->v.p[1]);
  748. return 0;
  749. }
  750. /*
  751. * CVW: This seems wrong to me... case en_lsh: if(
  752. * node->v.p[0]->nodetype == en_icon ) return xfold(node->v.p[1]) <<
  753. * node->v.p[0]->v.i; else if( node->v.p[1]->nodetype == en_icon )
  754. * return xfold(node->v.p[0]) << node->v.p[1]->v.i; else return 0;
  755. */
  756. case en_uminus:
  757. return -xfold(node->v.p[0]);
  758. case en_lsh:
  759. case en_rsh:
  760. case en_div:
  761. case en_mod:
  762. case en_asadd:
  763. case en_assub:
  764. case en_asmul:
  765. case en_asdiv:
  766. case en_asmod:
  767. case en_and:
  768. case en_land:
  769. case en_or:
  770. case en_lor:
  771. case en_xor:
  772. case en_asand:
  773. case en_asor:
  774. case en_asxor:
  775. case en_void:
  776. case en_fcall:
  777. case en_assign:
  778. case en_eq:
  779. case en_ne:
  780. case en_lt:
  781. case en_le:
  782. case en_gt:
  783. case en_ge:
  784. fold_const(&node->v.p[0]);
  785. fold_const(&node->v.p[1]);
  786. return 0;
  787. case en_ref:
  788. case en_fieldref:
  789. case en_compl:
  790. case en_not:
  791. case en_deref:
  792. fold_const(&node->v.p[0]);
  793. return 0;
  794. /*
  795. * This is not stricly legal: (long)(x+10) * 4l might not be the same
  796. * as (long)(x) * 4l + 40l but it is the same as long as no overflows
  797. * occur
  798. */
  799. case en_cast:
  800. #ifdef DONTDEF
  801. return xfold(node->v.p[0]);
  802. #endif
  803. /*
  804. * Well, sometimes I prefer purity to efficiency
  805. * It is a matter of taste how you decide here....
  806. */
  807. fold_const(&node->v.p[0]);
  808. return 0;
  809. }
  810. return 0;
  811. }
  812. static void fold_const(struct enode **node) {
  813. /*
  814. * reorganize an expression for optimal constant grouping.
  815. */
  816. struct enode *ep;
  817. long i;
  818. ep = *node;
  819. if (ep == 0)
  820. return;
  821. if (ep->nodetype == en_add) {
  822. if (ep->v.p[0]->nodetype == en_icon) {
  823. ep->v.p[0]->v.i += xfold(ep->v.p[1]);
  824. return;
  825. } else if (ep->v.p[1]->nodetype == en_icon) {
  826. ep->v.p[1]->v.i += xfold(ep->v.p[0]);
  827. return;
  828. }
  829. } else if (ep->nodetype == en_sub) {
  830. if (ep->v.p[0]->nodetype == en_icon) {
  831. ep->v.p[0]->v.i -= xfold(ep->v.p[1]);
  832. return;
  833. } else if (ep->v.p[1]->nodetype == en_icon) {
  834. ep->v.p[1]->v.i -= xfold(ep->v.p[0]);
  835. return;
  836. }
  837. }
  838. i = xfold(ep);
  839. if (i != 0) {
  840. /*
  841. * strip_icon is in fact harmless here since this value is
  842. * just added to *node
  843. * consider in 16-bit mode:
  844. *
  845. * int day, year;
  846. * day = 365 * (year - 1970);
  847. *
  848. * and look at the code, which is transformed to
  849. *
  850. * day = 365*year + 1846;
  851. *
  852. * which works if the multiplication returns the lower 16 bits of
  853. * the result correctly.
  854. */
  855. i = strip_icon(i, (*node)->etype);
  856. ep = mk_icon(i);
  857. ep->etype = (*node)->etype;
  858. ep->esize = (*node)->esize;
  859. ep = mk_node(en_add, *node, ep);
  860. ep->etype = (*node)->etype;
  861. ep->esize = (*node)->esize;
  862. *node = ep;
  863. }
  864. }
  865. void opt4(struct enode **node) {
  866. /*
  867. * apply all constant optimizations.
  868. */
  869. /* opt0(node); */
  870. fold_const(node);
  871. opt0(node);
  872. }
  873. // vim:ts=4:sw=4