tree-chkp-opt.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. /* Pointer Bounds Checker optimization pass.
  2. Copyright (C) 2014-2015 Free Software Foundation, Inc.
  3. Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 3, or (at your option) any later
  8. version.
  9. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GCC; see the file COPYING3. If not see
  15. <http://www.gnu.org/licenses/>. */
  16. #include "config.h"
  17. #include "system.h"
  18. #include "coretypes.h"
  19. #include "hash-set.h"
  20. #include "machmode.h"
  21. #include "vec.h"
  22. #include "double-int.h"
  23. #include "input.h"
  24. #include "alias.h"
  25. #include "symtab.h"
  26. #include "options.h"
  27. #include "wide-int.h"
  28. #include "inchash.h"
  29. #include "tree.h"
  30. #include "fold-const.h"
  31. #include "target.h"
  32. #include "tree-cfg.h"
  33. #include "tree-pass.h"
  34. #include "is-a.h"
  35. #include "cfgloop.h"
  36. #include "stringpool.h"
  37. #include "tree-ssa-alias.h"
  38. #include "tree-ssanames.h"
  39. #include "tree-ssa-operands.h"
  40. #include "tree-ssa-address.h"
  41. #include "tree-ssa.h"
  42. #include "predict.h"
  43. #include "dominance.h"
  44. #include "cfg.h"
  45. #include "basic-block.h"
  46. #include "tree-ssa-loop-niter.h"
  47. #include "gimple-expr.h"
  48. #include "gimple.h"
  49. #include "tree-phinodes.h"
  50. #include "gimple-ssa.h"
  51. #include "ssa-iterators.h"
  52. #include "gimple-pretty-print.h"
  53. #include "gimple-iterator.h"
  54. #include "gimplify.h"
  55. #include "gimplify-me.h"
  56. #include "hashtab.h"
  57. #include "tm.h"
  58. #include "hard-reg-set.h"
  59. #include "function.h"
  60. #include "rtl.h"
  61. #include "flags.h"
  62. #include "statistics.h"
  63. #include "real.h"
  64. #include "fixed-value.h"
  65. #include "insn-config.h"
  66. #include "expmed.h"
  67. #include "dojump.h"
  68. #include "explow.h"
  69. #include "calls.h"
  70. #include "emit-rtl.h"
  71. #include "varasm.h"
  72. #include "stmt.h"
  73. #include "expr.h"
  74. #include "tree-chkp.h"
  75. #include "ipa-chkp.h"
  76. #include "diagnostic.h"
  77. enum check_type
  78. {
  79. CHECK_LOWER_BOUND,
  80. CHECK_UPPER_BOUND
  81. };
  82. struct pol_item
  83. {
  84. tree cst;
  85. tree var;
  86. };
  87. struct address_t
  88. {
  89. vec<struct pol_item> pol;
  90. };
  91. /* Structure to hold check informtation. */
  92. struct check_info
  93. {
  94. /* Type of the check. */
  95. check_type type;
  96. /* Address used for the check. */
  97. address_t addr;
  98. /* Bounds used for the check. */
  99. tree bounds;
  100. /* Check statement. Can be NULL for removed checks. */
  101. gimple stmt;
  102. };
  103. /* Structure to hold checks information for BB. */
  104. struct bb_checks
  105. {
  106. vec<struct check_info, va_heap, vl_ptr> checks;
  107. };
  108. static void chkp_collect_value (tree ssa_name, address_t &res);
  109. #define chkp_bndmk_fndecl \
  110. (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDMK))
  111. #define chkp_intersect_fndecl \
  112. (targetm.builtin_chkp_function (BUILT_IN_CHKP_INTERSECT))
  113. #define chkp_checkl_fndecl \
  114. (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDCL))
  115. #define chkp_checku_fndecl \
  116. (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDCU))
  117. static vec<struct bb_checks, va_heap, vl_ptr> check_infos = vNULL;
  118. /* Comparator for pol_item structures I1 and I2 to be used
  119. to find items with equal var. Also used for polynomial
  120. sorting. */
  121. static int
  122. chkp_pol_item_compare (const void *i1, const void *i2)
  123. {
  124. const struct pol_item *p1 = (const struct pol_item *)i1;
  125. const struct pol_item *p2 = (const struct pol_item *)i2;
  126. if (p1->var == p2->var)
  127. return 0;
  128. else if (p1->var > p2->var)
  129. return 1;
  130. else
  131. return -1;
  132. }
  133. /* Find polynomial item in ADDR with var equal to VAR
  134. and return its index. Return -1 if item was not
  135. found. */
  136. static int
  137. chkp_pol_find (address_t &addr, tree var)
  138. {
  139. int left = 0;
  140. int right = addr.pol.length () - 1;
  141. int n;
  142. while (right >= left)
  143. {
  144. n = (left + right) / 2;
  145. if (addr.pol[n].var == var
  146. || (var && addr.pol[n].var
  147. && TREE_CODE (var) == ADDR_EXPR
  148. && TREE_CODE (addr.pol[n].var) == ADDR_EXPR
  149. && TREE_OPERAND (var, 0) == TREE_OPERAND (addr.pol[n].var, 0)))
  150. return n;
  151. else if (addr.pol[n].var > var)
  152. right = n - 1;
  153. else
  154. left = n + 1;
  155. }
  156. return -1;
  157. }
  158. /* Return constant CST extended to size type. */
  159. static tree
  160. chkp_extend_const (tree cst)
  161. {
  162. if (TYPE_PRECISION (TREE_TYPE (cst)) < TYPE_PRECISION (size_type_node))
  163. return build_int_cst_type (size_type_node, tree_to_shwi (cst));
  164. return cst;
  165. }
  166. /* Add polynomial item CST * VAR to ADDR. */
  167. static void
  168. chkp_add_addr_item (address_t &addr, tree cst, tree var)
  169. {
  170. int n = chkp_pol_find (addr, var);
  171. cst = chkp_extend_const (cst);
  172. if (n < 0)
  173. {
  174. struct pol_item item;
  175. item.cst = cst;
  176. item.var = var;
  177. addr.pol.safe_push (item);
  178. addr.pol.qsort (&chkp_pol_item_compare);
  179. }
  180. else
  181. {
  182. addr.pol[n].cst = fold_build2 (PLUS_EXPR, TREE_TYPE (addr.pol[n].cst),
  183. addr.pol[n].cst, cst);
  184. if (TREE_CODE (addr.pol[n].cst) == INTEGER_CST
  185. && integer_zerop (addr.pol[n].cst))
  186. addr.pol.ordered_remove (n);
  187. }
  188. }
  189. /* Subtract polynomial item CST * VAR from ADDR. */
  190. static void
  191. chkp_sub_addr_item (address_t &addr, tree cst, tree var)
  192. {
  193. int n = chkp_pol_find (addr, var);
  194. cst = chkp_extend_const (cst);
  195. if (n < 0)
  196. {
  197. struct pol_item item;
  198. item.cst = fold_build2 (MINUS_EXPR, TREE_TYPE (cst),
  199. integer_zero_node, cst);
  200. item.var = var;
  201. addr.pol.safe_push (item);
  202. addr.pol.qsort (&chkp_pol_item_compare);
  203. }
  204. else
  205. {
  206. addr.pol[n].cst = fold_build2 (MINUS_EXPR, TREE_TYPE (addr.pol[n].cst),
  207. addr.pol[n].cst, cst);
  208. if (TREE_CODE (addr.pol[n].cst) == INTEGER_CST
  209. && integer_zerop (addr.pol[n].cst))
  210. addr.pol.ordered_remove (n);
  211. }
  212. }
  213. /* Add address DELTA to ADDR. */
  214. static void
  215. chkp_add_addr_addr (address_t &addr, address_t &delta)
  216. {
  217. unsigned int i;
  218. for (i = 0; i < delta.pol.length (); i++)
  219. chkp_add_addr_item (addr, delta.pol[i].cst, delta.pol[i].var);
  220. }
  221. /* Subtract address DELTA from ADDR. */
  222. static void
  223. chkp_sub_addr_addr (address_t &addr, address_t &delta)
  224. {
  225. unsigned int i;
  226. for (i = 0; i < delta.pol.length (); i++)
  227. chkp_sub_addr_item (addr, delta.pol[i].cst, delta.pol[i].var);
  228. }
  229. /* Mutiply address ADDR by integer constant MULT. */
  230. static void
  231. chkp_mult_addr (address_t &addr, tree mult)
  232. {
  233. unsigned int i;
  234. for (i = 0; i < addr.pol.length (); i++)
  235. addr.pol[i].cst = fold_build2 (MULT_EXPR, TREE_TYPE (addr.pol[i].cst),
  236. addr.pol[i].cst, mult);
  237. }
  238. /* Return 1 if we may prove ADDR has a constant value with
  239. determined sign, which is put into *SIGN. Otherwise
  240. return 0. */
  241. static bool
  242. chkp_is_constant_addr (const address_t &addr, int *sign)
  243. {
  244. *sign = 0;
  245. if (addr.pol.length () == 0)
  246. return true;
  247. else if (addr.pol.length () > 1)
  248. return false;
  249. else if (addr.pol[0].var)
  250. return false;
  251. else if (integer_zerop (addr.pol[0].cst))
  252. *sign = 0;
  253. else if (tree_int_cst_sign_bit (addr.pol[0].cst))
  254. *sign = -1;
  255. else
  256. *sign = 1;
  257. return true;
  258. }
  259. /* Dump ADDR into dump_file. */
  260. static void
  261. chkp_print_addr (const address_t &addr)
  262. {
  263. unsigned int n = 0;
  264. for (n = 0; n < addr.pol.length (); n++)
  265. {
  266. if (n > 0)
  267. fprintf (dump_file, " + ");
  268. if (addr.pol[n].var == NULL_TREE)
  269. print_generic_expr (dump_file, addr.pol[n].cst, 0);
  270. else
  271. {
  272. if (TREE_CODE (addr.pol[n].cst) != INTEGER_CST
  273. || !integer_onep (addr.pol[n].cst))
  274. {
  275. print_generic_expr (dump_file, addr.pol[n].cst, 0);
  276. fprintf (dump_file, " * ");
  277. }
  278. print_generic_expr (dump_file, addr.pol[n].var, 0);
  279. }
  280. }
  281. }
  282. /* Compute value of PTR and put it into address RES.
  283. PTR has to be ADDR_EXPR. */
  284. static void
  285. chkp_collect_addr_value (tree ptr, address_t &res)
  286. {
  287. tree obj = TREE_OPERAND (ptr, 0);
  288. address_t addr;
  289. switch (TREE_CODE (obj))
  290. {
  291. case INDIRECT_REF:
  292. chkp_collect_value (TREE_OPERAND (obj, 0), res);
  293. break;
  294. case MEM_REF:
  295. chkp_collect_value (TREE_OPERAND (obj, 0), res);
  296. addr.pol.create (0);
  297. chkp_collect_value (TREE_OPERAND (obj, 1), addr);
  298. chkp_add_addr_addr (res, addr);
  299. addr.pol.release ();
  300. break;
  301. case ARRAY_REF:
  302. chkp_collect_value (build_fold_addr_expr (TREE_OPERAND (obj, 0)), res);
  303. addr.pol.create (0);
  304. chkp_collect_value (TREE_OPERAND (obj, 1), addr);
  305. chkp_mult_addr (addr, array_ref_element_size (obj));
  306. chkp_add_addr_addr (res, addr);
  307. addr.pol.release ();
  308. break;
  309. case COMPONENT_REF:
  310. {
  311. tree str = TREE_OPERAND (obj, 0);
  312. tree field = TREE_OPERAND (obj, 1);
  313. chkp_collect_value (build_fold_addr_expr (str), res);
  314. addr.pol.create (0);
  315. chkp_collect_value (component_ref_field_offset (obj), addr);
  316. chkp_add_addr_addr (res, addr);
  317. addr.pol.release ();
  318. if (DECL_FIELD_BIT_OFFSET (field))
  319. {
  320. addr.pol.create (0);
  321. chkp_collect_value (fold_build2 (TRUNC_DIV_EXPR, size_type_node,
  322. DECL_FIELD_BIT_OFFSET (field),
  323. size_int (BITS_PER_UNIT)),
  324. addr);
  325. chkp_add_addr_addr (res, addr);
  326. addr.pol.release ();
  327. }
  328. }
  329. break;
  330. default:
  331. chkp_add_addr_item (res, integer_one_node, ptr);
  332. break;
  333. }
  334. }
  335. /* Compute value of PTR and put it into address RES. */
  336. static void
  337. chkp_collect_value (tree ptr, address_t &res)
  338. {
  339. gimple def_stmt;
  340. enum gimple_code code;
  341. enum tree_code rhs_code;
  342. address_t addr;
  343. tree rhs1;
  344. if (TREE_CODE (ptr) == INTEGER_CST)
  345. {
  346. chkp_add_addr_item (res, ptr, NULL);
  347. return;
  348. }
  349. else if (TREE_CODE (ptr) == ADDR_EXPR)
  350. {
  351. chkp_collect_addr_value (ptr, res);
  352. return;
  353. }
  354. else if (TREE_CODE (ptr) != SSA_NAME)
  355. {
  356. chkp_add_addr_item (res, integer_one_node, ptr);
  357. return;
  358. }
  359. /* Now we handle the case when polynomial is computed
  360. for SSA NAME. */
  361. def_stmt = SSA_NAME_DEF_STMT (ptr);
  362. code = gimple_code (def_stmt);
  363. /* Currently we do not walk through statements other
  364. than assignment. */
  365. if (code != GIMPLE_ASSIGN)
  366. {
  367. chkp_add_addr_item (res, integer_one_node, ptr);
  368. return;
  369. }
  370. rhs_code = gimple_assign_rhs_code (def_stmt);
  371. rhs1 = gimple_assign_rhs1 (def_stmt);
  372. switch (rhs_code)
  373. {
  374. case SSA_NAME:
  375. case INTEGER_CST:
  376. case ADDR_EXPR:
  377. chkp_collect_value (rhs1, res);
  378. break;
  379. case PLUS_EXPR:
  380. case POINTER_PLUS_EXPR:
  381. chkp_collect_value (rhs1, res);
  382. addr.pol.create (0);
  383. chkp_collect_value (gimple_assign_rhs2 (def_stmt), addr);
  384. chkp_add_addr_addr (res, addr);
  385. addr.pol.release ();
  386. break;
  387. case MINUS_EXPR:
  388. chkp_collect_value (rhs1, res);
  389. addr.pol.create (0);
  390. chkp_collect_value (gimple_assign_rhs2 (def_stmt), addr);
  391. chkp_sub_addr_addr (res, addr);
  392. addr.pol.release ();
  393. break;
  394. case MULT_EXPR:
  395. if (TREE_CODE (rhs1) == SSA_NAME
  396. && TREE_CODE (gimple_assign_rhs2 (def_stmt)) == INTEGER_CST)
  397. {
  398. chkp_collect_value (rhs1, res);
  399. chkp_mult_addr (res, gimple_assign_rhs2 (def_stmt));
  400. }
  401. else if (TREE_CODE (gimple_assign_rhs2 (def_stmt)) == SSA_NAME
  402. && TREE_CODE (rhs1) == INTEGER_CST)
  403. {
  404. chkp_collect_value (gimple_assign_rhs2 (def_stmt), res);
  405. chkp_mult_addr (res, rhs1);
  406. }
  407. else
  408. chkp_add_addr_item (res, integer_one_node, ptr);
  409. break;
  410. default:
  411. chkp_add_addr_item (res, integer_one_node, ptr);
  412. break;
  413. }
  414. }
  415. /* Fill check_info structure *CI with information about
  416. check STMT. */
  417. static void
  418. chkp_fill_check_info (gimple stmt, struct check_info *ci)
  419. {
  420. ci->addr.pol.create (0);
  421. ci->bounds = gimple_call_arg (stmt, 1);
  422. chkp_collect_value (gimple_call_arg (stmt, 0), ci->addr);
  423. ci->type = (gimple_call_fndecl (stmt) == chkp_checkl_fndecl
  424. ? CHECK_LOWER_BOUND
  425. : CHECK_UPPER_BOUND);
  426. ci->stmt = stmt;
  427. }
  428. /* Release structures holding check information
  429. for current function. */
  430. static void
  431. chkp_release_check_info (void)
  432. {
  433. unsigned int n, m;
  434. if (check_infos.exists ())
  435. {
  436. for (n = 0; n < check_infos.length (); n++)
  437. {
  438. for (m = 0; m < check_infos[n].checks.length (); m++)
  439. if (check_infos[n].checks[m].addr.pol.exists ())
  440. check_infos[n].checks[m].addr.pol.release ();
  441. check_infos[n].checks.release ();
  442. }
  443. check_infos.release ();
  444. }
  445. }
  446. /* Create structures to hold check information
  447. for current function. */
  448. static void
  449. chkp_init_check_info (void)
  450. {
  451. struct bb_checks empty_bbc;
  452. int n;
  453. empty_bbc.checks = vNULL;
  454. chkp_release_check_info ();
  455. check_infos.create (last_basic_block_for_fn (cfun));
  456. for (n = 0; n < last_basic_block_for_fn (cfun); n++)
  457. {
  458. check_infos.safe_push (empty_bbc);
  459. check_infos.last ().checks.create (0);
  460. }
  461. }
  462. /* Find all checks in current function and store info about them
  463. in check_infos. */
  464. static void
  465. chkp_gather_checks_info (void)
  466. {
  467. basic_block bb;
  468. gimple_stmt_iterator i;
  469. if (dump_file && (dump_flags & TDF_DETAILS))
  470. fprintf (dump_file, "Gathering information about checks...\n");
  471. chkp_init_check_info ();
  472. FOR_EACH_BB_FN (bb, cfun)
  473. {
  474. struct bb_checks *bbc = &check_infos[bb->index];
  475. if (dump_file && (dump_flags & TDF_DETAILS))
  476. fprintf (dump_file, "Searching checks in BB%d...\n", bb->index);
  477. for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
  478. {
  479. gimple stmt = gsi_stmt (i);
  480. if (gimple_code (stmt) != GIMPLE_CALL)
  481. continue;
  482. if (gimple_call_fndecl (stmt) == chkp_checkl_fndecl
  483. || gimple_call_fndecl (stmt) == chkp_checku_fndecl)
  484. {
  485. struct check_info ci;
  486. chkp_fill_check_info (stmt, &ci);
  487. bbc->checks.safe_push (ci);
  488. if (dump_file && (dump_flags & TDF_DETAILS))
  489. {
  490. fprintf (dump_file, "Adding check information:\n");
  491. fprintf (dump_file, " bounds: ");
  492. print_generic_expr (dump_file, ci.bounds, 0);
  493. fprintf (dump_file, "\n address: ");
  494. chkp_print_addr (ci.addr);
  495. fprintf (dump_file, "\n check: ");
  496. print_gimple_stmt (dump_file, stmt, 0, 0);
  497. }
  498. }
  499. }
  500. }
  501. }
  502. /* Return 1 if check CI against BOUNDS always pass,
  503. -1 if check CI against BOUNDS always fails and
  504. 0 if we cannot compute check result. */
  505. static int
  506. chkp_get_check_result (struct check_info *ci, tree bounds)
  507. {
  508. gimple bnd_def;
  509. address_t bound_val;
  510. int sign, res = 0;
  511. if (dump_file && (dump_flags & TDF_DETAILS))
  512. {
  513. fprintf (dump_file, "Trying to compute result of the check\n");
  514. fprintf (dump_file, " check: ");
  515. print_gimple_stmt (dump_file, ci->stmt, 0, 0);
  516. fprintf (dump_file, " address: ");
  517. chkp_print_addr (ci->addr);
  518. fprintf (dump_file, "\n bounds: ");
  519. print_generic_expr (dump_file, bounds, 0);
  520. fprintf (dump_file, "\n");
  521. }
  522. if (TREE_CODE (bounds) != SSA_NAME)
  523. {
  524. if (dump_file && (dump_flags & TDF_DETAILS))
  525. fprintf (dump_file, " result: bounds tree code is not ssa_name\n");
  526. return 0;
  527. }
  528. bnd_def = SSA_NAME_DEF_STMT (bounds);
  529. /* Currently we handle cases when bounds are result of bndmk
  530. or loaded static bounds var. */
  531. if (gimple_code (bnd_def) == GIMPLE_CALL
  532. && gimple_call_fndecl (bnd_def) == chkp_bndmk_fndecl)
  533. {
  534. bound_val.pol.create (0);
  535. chkp_collect_value (gimple_call_arg (bnd_def, 0), bound_val);
  536. if (ci->type == CHECK_UPPER_BOUND)
  537. {
  538. address_t size_val;
  539. size_val.pol.create (0);
  540. chkp_collect_value (gimple_call_arg (bnd_def, 1), size_val);
  541. chkp_add_addr_addr (bound_val, size_val);
  542. size_val.pol.release ();
  543. chkp_add_addr_item (bound_val, integer_minus_one_node, NULL);
  544. }
  545. }
  546. else if (gimple_code (bnd_def) == GIMPLE_ASSIGN
  547. && gimple_assign_rhs1 (bnd_def) == chkp_get_zero_bounds_var ())
  548. {
  549. if (dump_file && (dump_flags & TDF_DETAILS))
  550. fprintf (dump_file, " result: always pass with zero bounds\n");
  551. return 1;
  552. }
  553. else if (gimple_code (bnd_def) == GIMPLE_ASSIGN
  554. && gimple_assign_rhs1 (bnd_def) == chkp_get_none_bounds_var ())
  555. {
  556. if (dump_file && (dump_flags & TDF_DETAILS))
  557. fprintf (dump_file, " result: always fails with none bounds\n");
  558. return -1;
  559. }
  560. else if (gimple_code (bnd_def) == GIMPLE_ASSIGN
  561. && TREE_CODE (gimple_assign_rhs1 (bnd_def)) == VAR_DECL)
  562. {
  563. tree bnd_var = gimple_assign_rhs1 (bnd_def);
  564. tree var;
  565. tree size;
  566. if (!DECL_INITIAL (bnd_var)
  567. || DECL_INITIAL (bnd_var) == error_mark_node)
  568. {
  569. if (dump_file && (dump_flags & TDF_DETAILS))
  570. fprintf (dump_file, " result: cannot compute bounds\n");
  571. return 0;
  572. }
  573. gcc_assert (TREE_CODE (DECL_INITIAL (bnd_var)) == ADDR_EXPR);
  574. var = TREE_OPERAND (DECL_INITIAL (bnd_var), 0);
  575. bound_val.pol.create (0);
  576. chkp_collect_value (DECL_INITIAL (bnd_var), bound_val);
  577. if (ci->type == CHECK_UPPER_BOUND)
  578. {
  579. if (TREE_CODE (var) == VAR_DECL)
  580. {
  581. if (DECL_SIZE (var)
  582. && !chkp_variable_size_type (TREE_TYPE (var)))
  583. size = DECL_SIZE_UNIT (var);
  584. else
  585. {
  586. if (dump_file && (dump_flags & TDF_DETAILS))
  587. fprintf (dump_file, " result: cannot compute bounds\n");
  588. return 0;
  589. }
  590. }
  591. else
  592. {
  593. gcc_assert (TREE_CODE (var) == STRING_CST);
  594. size = build_int_cst (size_type_node,
  595. TREE_STRING_LENGTH (var));
  596. }
  597. address_t size_val;
  598. size_val.pol.create (0);
  599. chkp_collect_value (size, size_val);
  600. chkp_add_addr_addr (bound_val, size_val);
  601. size_val.pol.release ();
  602. chkp_add_addr_item (bound_val, integer_minus_one_node, NULL);
  603. }
  604. }
  605. else
  606. {
  607. if (dump_file && (dump_flags & TDF_DETAILS))
  608. fprintf (dump_file, " result: cannot compute bounds\n");
  609. return 0;
  610. }
  611. if (dump_file && (dump_flags & TDF_DETAILS))
  612. {
  613. fprintf (dump_file, " bound value: ");
  614. chkp_print_addr (bound_val);
  615. fprintf (dump_file, "\n");
  616. }
  617. chkp_sub_addr_addr (bound_val, ci->addr);
  618. if (!chkp_is_constant_addr (bound_val, &sign))
  619. {
  620. if (dump_file && (dump_flags & TDF_DETAILS))
  621. fprintf (dump_file, " result: cannot compute result\n");
  622. res = 0;
  623. }
  624. else if (sign == 0
  625. || (ci->type == CHECK_UPPER_BOUND && sign > 0)
  626. || (ci->type == CHECK_LOWER_BOUND && sign < 0))
  627. {
  628. if (dump_file && (dump_flags & TDF_DETAILS))
  629. fprintf (dump_file, " result: always pass\n");
  630. res = 1;
  631. }
  632. else
  633. {
  634. if (dump_file && (dump_flags & TDF_DETAILS))
  635. fprintf (dump_file, " result: always fail\n");
  636. res = -1;
  637. }
  638. bound_val.pol.release ();
  639. return res;
  640. }
  641. /* Try to compare bounds value and address value
  642. used in the check CI. If we can prove that check
  643. always pass then remove it. */
  644. static void
  645. chkp_remove_check_if_pass (struct check_info *ci)
  646. {
  647. int result = 0;
  648. if (dump_file && (dump_flags & TDF_DETAILS))
  649. {
  650. fprintf (dump_file, "Trying to remove check: ");
  651. print_gimple_stmt (dump_file, ci->stmt, 0, 0);
  652. }
  653. result = chkp_get_check_result (ci, ci->bounds);
  654. if (result == 1)
  655. {
  656. gimple_stmt_iterator i = gsi_for_stmt (ci->stmt);
  657. if (dump_file && (dump_flags & TDF_DETAILS))
  658. fprintf (dump_file, " action: delete check (always pass)\n");
  659. gsi_remove (&i, true);
  660. unlink_stmt_vdef (ci->stmt);
  661. release_defs (ci->stmt);
  662. ci->stmt = NULL;
  663. }
  664. else if (result == -1)
  665. {
  666. if (dump_file && (dump_flags & TDF_DETAILS))
  667. fprintf (dump_file, " action: keep check (always fail)\n");
  668. warning_at (gimple_location (ci->stmt), OPT_Wchkp,
  669. "memory access check always fail");
  670. }
  671. else if (result == 0)
  672. {
  673. if (dump_file && (dump_flags & TDF_DETAILS))
  674. fprintf (dump_file, " action: keep check (cannot compute result)\n");
  675. }
  676. }
  677. /* For bounds used in CI check if bounds are produced by
  678. intersection and we may use outer bounds instead. If
  679. transformation is possible then fix check statement and
  680. recompute its info. */
  681. static void
  682. chkp_use_outer_bounds_if_possible (struct check_info *ci)
  683. {
  684. gimple bnd_def;
  685. tree bnd1, bnd2, bnd_res = NULL;
  686. int check_res1, check_res2;
  687. if (TREE_CODE (ci->bounds) != SSA_NAME)
  688. return;
  689. bnd_def = SSA_NAME_DEF_STMT (ci->bounds);
  690. if (gimple_code (bnd_def) != GIMPLE_CALL
  691. || gimple_call_fndecl (bnd_def) != chkp_intersect_fndecl)
  692. return;
  693. if (dump_file && (dump_flags & TDF_DETAILS))
  694. {
  695. fprintf (dump_file, "Check if bounds intersection is redundant: \n");
  696. fprintf (dump_file, " check: ");
  697. print_gimple_stmt (dump_file, ci->stmt, 0, 0);
  698. fprintf (dump_file, " intersection: ");
  699. print_gimple_stmt (dump_file, bnd_def, 0, 0);
  700. fprintf (dump_file, "\n");
  701. }
  702. bnd1 = gimple_call_arg (bnd_def, 0);
  703. bnd2 = gimple_call_arg (bnd_def, 1);
  704. check_res1 = chkp_get_check_result (ci, bnd1);
  705. check_res2 = chkp_get_check_result (ci, bnd2);
  706. if (check_res1 == 1)
  707. bnd_res = bnd2;
  708. else if (check_res1 == -1)
  709. bnd_res = bnd1;
  710. else if (check_res2 == 1)
  711. bnd_res = bnd1;
  712. else if (check_res2 == -1)
  713. bnd_res = bnd2;
  714. if (bnd_res)
  715. {
  716. if (dump_file && (dump_flags & TDF_DETAILS))
  717. {
  718. fprintf (dump_file, " action: use ");
  719. print_generic_expr (dump_file, bnd2, 0);
  720. fprintf (dump_file, " instead of ");
  721. print_generic_expr (dump_file, ci->bounds, 0);
  722. fprintf (dump_file, "\n");
  723. }
  724. ci->bounds = bnd_res;
  725. gimple_call_set_arg (ci->stmt, 1, bnd_res);
  726. update_stmt (ci->stmt);
  727. chkp_fill_check_info (ci->stmt, ci);
  728. }
  729. }
  730. /* Try to find checks whose bounds were produced by intersection
  731. which does not affect check result. In such check outer bounds
  732. are used instead. It allows to remove excess intersections
  733. and helps to compare checks. */
  734. static void
  735. chkp_remove_excess_intersections (void)
  736. {
  737. basic_block bb;
  738. if (dump_file && (dump_flags & TDF_DETAILS))
  739. fprintf (dump_file, "Searching for redundant bounds intersections...\n");
  740. FOR_EACH_BB_FN (bb, cfun)
  741. {
  742. struct bb_checks *bbc = &check_infos[bb->index];
  743. unsigned int no;
  744. /* Iterate through all found checks in BB. */
  745. for (no = 0; no < bbc->checks.length (); no++)
  746. if (bbc->checks[no].stmt)
  747. chkp_use_outer_bounds_if_possible (&bbc->checks[no]);
  748. }
  749. }
  750. /* Try to remove all checks which are known to alwyas pass. */
  751. static void
  752. chkp_remove_constant_checks (void)
  753. {
  754. basic_block bb;
  755. if (dump_file && (dump_flags & TDF_DETAILS))
  756. fprintf (dump_file, "Searching for redundant checks...\n");
  757. FOR_EACH_BB_FN (bb, cfun)
  758. {
  759. struct bb_checks *bbc = &check_infos[bb->index];
  760. unsigned int no;
  761. /* Iterate through all found checks in BB. */
  762. for (no = 0; no < bbc->checks.length (); no++)
  763. if (bbc->checks[no].stmt)
  764. chkp_remove_check_if_pass (&bbc->checks[no]);
  765. }
  766. }
  767. /* Return fast version of string function FNCODE. */
  768. static tree
  769. chkp_get_nobnd_fndecl (enum built_in_function fncode)
  770. {
  771. /* Check if we are allowed to use fast string functions. */
  772. if (!flag_chkp_use_fast_string_functions)
  773. return NULL_TREE;
  774. tree fndecl = NULL_TREE;
  775. switch (fncode)
  776. {
  777. case BUILT_IN_MEMCPY_CHKP:
  778. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND);
  779. break;
  780. case BUILT_IN_MEMPCPY_CHKP:
  781. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND);
  782. break;
  783. case BUILT_IN_MEMMOVE_CHKP:
  784. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND);
  785. break;
  786. case BUILT_IN_MEMSET_CHKP:
  787. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND);
  788. break;
  789. case BUILT_IN_CHKP_MEMCPY_NOCHK_CHKP:
  790. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK);
  791. break;
  792. case BUILT_IN_CHKP_MEMPCPY_NOCHK_CHKP:
  793. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK);
  794. break;
  795. case BUILT_IN_CHKP_MEMMOVE_NOCHK_CHKP:
  796. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK);
  797. break;
  798. case BUILT_IN_CHKP_MEMSET_NOCHK_CHKP:
  799. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK);
  800. break;
  801. default:
  802. break;
  803. }
  804. if (fndecl)
  805. fndecl = chkp_maybe_clone_builtin_fndecl (fndecl);
  806. return fndecl;
  807. }
  808. /* Return no-check version of string function FNCODE. */
  809. static tree
  810. chkp_get_nochk_fndecl (enum built_in_function fncode)
  811. {
  812. /* Check if we are allowed to use fast string functions. */
  813. if (!flag_chkp_use_nochk_string_functions)
  814. return NULL_TREE;
  815. tree fndecl = NULL_TREE;
  816. switch (fncode)
  817. {
  818. case BUILT_IN_MEMCPY_CHKP:
  819. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOCHK);
  820. break;
  821. case BUILT_IN_MEMPCPY_CHKP:
  822. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOCHK);
  823. break;
  824. case BUILT_IN_MEMMOVE_CHKP:
  825. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOCHK);
  826. break;
  827. case BUILT_IN_MEMSET_CHKP:
  828. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOCHK);
  829. break;
  830. case BUILT_IN_CHKP_MEMCPY_NOBND_CHKP:
  831. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK);
  832. break;
  833. case BUILT_IN_CHKP_MEMPCPY_NOBND_CHKP:
  834. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK);
  835. break;
  836. case BUILT_IN_CHKP_MEMMOVE_NOBND_CHKP:
  837. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK);
  838. break;
  839. case BUILT_IN_CHKP_MEMSET_NOBND_CHKP:
  840. fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK);
  841. break;
  842. default:
  843. break;
  844. }
  845. if (fndecl)
  846. fndecl = chkp_maybe_clone_builtin_fndecl (fndecl);
  847. return fndecl;
  848. }
  849. /* Find memcpy, mempcpy, memmove and memset calls, perform
  850. checks before call and then call no_chk version of
  851. functions. We do it on O2 to enable inlining of these
  852. functions during expand.
  853. Also try to find memcpy, mempcpy, memmove and memset calls
  854. which are known to not write pointers to memory and use
  855. faster function versions for them. */
  856. static void
  857. chkp_optimize_string_function_calls (void)
  858. {
  859. basic_block bb;
  860. if (dump_file && (dump_flags & TDF_DETAILS))
  861. fprintf (dump_file, "Searching for replaceable string function calls...\n");
  862. FOR_EACH_BB_FN (bb, cfun)
  863. {
  864. gimple_stmt_iterator i;
  865. for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
  866. {
  867. gimple stmt = gsi_stmt (i);
  868. tree fndecl;
  869. if (gimple_code (stmt) != GIMPLE_CALL
  870. || !gimple_call_with_bounds_p (stmt))
  871. continue;
  872. fndecl = gimple_call_fndecl (stmt);
  873. if (!fndecl || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
  874. continue;
  875. if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMCPY_CHKP
  876. || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY_CHKP
  877. || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMMOVE_CHKP
  878. || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHKP)
  879. {
  880. tree dst = gimple_call_arg (stmt, 0);
  881. tree dst_bnd = gimple_call_arg (stmt, 1);
  882. bool is_memset = DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHKP;
  883. tree size = gimple_call_arg (stmt, is_memset ? 3 : 4);
  884. tree fndecl_nochk;
  885. gimple_stmt_iterator j;
  886. basic_block check_bb;
  887. address_t size_val;
  888. int sign;
  889. bool known;
  890. /* We may replace call with corresponding __chkp_*_nobnd
  891. call in case destination pointer base type is not
  892. void or pointer. */
  893. if (POINTER_TYPE_P (TREE_TYPE (dst))
  894. && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (dst)))
  895. && !chkp_type_has_pointer (TREE_TYPE (TREE_TYPE (dst))))
  896. {
  897. tree fndecl_nobnd
  898. = chkp_get_nobnd_fndecl (DECL_FUNCTION_CODE (fndecl));
  899. if (fndecl_nobnd)
  900. fndecl = fndecl_nobnd;
  901. }
  902. fndecl_nochk = chkp_get_nochk_fndecl (DECL_FUNCTION_CODE (fndecl));
  903. if (fndecl_nochk)
  904. fndecl = fndecl_nochk;
  905. if (fndecl != gimple_call_fndecl (stmt))
  906. {
  907. if (dump_file && (dump_flags & TDF_DETAILS))
  908. {
  909. fprintf (dump_file, "Replacing call: ");
  910. print_gimple_stmt (dump_file, stmt, 0,
  911. TDF_VOPS|TDF_MEMSYMS);
  912. }
  913. gimple_call_set_fndecl (stmt, fndecl);
  914. if (dump_file && (dump_flags & TDF_DETAILS))
  915. {
  916. fprintf (dump_file, "With a new call: ");
  917. print_gimple_stmt (dump_file, stmt, 0,
  918. TDF_VOPS|TDF_MEMSYMS);
  919. }
  920. }
  921. /* If there is no nochk version of function then
  922. do nothing. Otherwise insert checks before
  923. the call. */
  924. if (!fndecl_nochk)
  925. continue;
  926. /* If size passed to call is known and > 0
  927. then we may insert checks unconditionally. */
  928. size_val.pol.create (0);
  929. chkp_collect_value (size, size_val);
  930. known = chkp_is_constant_addr (size_val, &sign);
  931. size_val.pol.release ();
  932. /* If we are not sure size is not zero then we have
  933. to perform runtime check for size and perform
  934. checks only when size is not zero. */
  935. if (!known)
  936. {
  937. gimple check = gimple_build_cond (NE_EXPR,
  938. size,
  939. size_zero_node,
  940. NULL_TREE,
  941. NULL_TREE);
  942. /* Split block before string function call. */
  943. gsi_prev (&i);
  944. check_bb = insert_cond_bb (bb, gsi_stmt (i), check);
  945. /* Set position for checks. */
  946. j = gsi_last_bb (check_bb);
  947. /* The block was splitted and therefore we
  948. need to set iterator to its end. */
  949. i = gsi_last_bb (bb);
  950. }
  951. /* If size is known to be zero then no checks
  952. should be performed. */
  953. else if (!sign)
  954. continue;
  955. else
  956. j = i;
  957. size = size_binop (MINUS_EXPR, size, size_one_node);
  958. if (!is_memset)
  959. {
  960. tree src = gimple_call_arg (stmt, 2);
  961. tree src_bnd = gimple_call_arg (stmt, 3);
  962. chkp_check_mem_access (src, fold_build_pointer_plus (src, size),
  963. src_bnd, j, gimple_location (stmt),
  964. integer_zero_node);
  965. }
  966. chkp_check_mem_access (dst, fold_build_pointer_plus (dst, size),
  967. dst_bnd, j, gimple_location (stmt),
  968. integer_one_node);
  969. }
  970. }
  971. }
  972. }
  973. /* Intrumentation pass inserts most of bounds creation code
  974. in the header of the function. We want to move bounds
  975. creation closer to bounds usage to reduce bounds lifetime.
  976. We also try to avoid bounds creation code on paths where
  977. bounds are not used. */
  978. static void
  979. chkp_reduce_bounds_lifetime (void)
  980. {
  981. basic_block bb = FALLTHRU_EDGE (ENTRY_BLOCK_PTR_FOR_FN (cfun))->dest;
  982. gimple_stmt_iterator i;
  983. for (i = gsi_start_bb (bb); !gsi_end_p (i); )
  984. {
  985. gimple dom_use, use_stmt, stmt = gsi_stmt (i);
  986. basic_block dom_bb;
  987. ssa_op_iter iter;
  988. imm_use_iterator use_iter;
  989. use_operand_p use_p;
  990. tree op;
  991. bool want_move = false;
  992. bool deps = false;
  993. if (gimple_code (stmt) == GIMPLE_CALL
  994. && gimple_call_fndecl (stmt) == chkp_bndmk_fndecl)
  995. want_move = true;
  996. if (gimple_code (stmt) == GIMPLE_ASSIGN
  997. && POINTER_BOUNDS_P (gimple_assign_lhs (stmt))
  998. && gimple_assign_rhs_code (stmt) == VAR_DECL)
  999. want_move = true;
  1000. if (!want_move)
  1001. {
  1002. gsi_next (&i);
  1003. continue;
  1004. }
  1005. /* Check we do not increase other values lifetime. */
  1006. FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
  1007. {
  1008. op = USE_FROM_PTR (use_p);
  1009. if (TREE_CODE (op) == SSA_NAME
  1010. && gimple_code (SSA_NAME_DEF_STMT (op)) != GIMPLE_NOP)
  1011. {
  1012. deps = true;
  1013. break;
  1014. }
  1015. }
  1016. if (deps)
  1017. {
  1018. gsi_next (&i);
  1019. continue;
  1020. }
  1021. /* Check all usages of bounds. */
  1022. if (gimple_code (stmt) == GIMPLE_CALL)
  1023. op = gimple_call_lhs (stmt);
  1024. else
  1025. {
  1026. gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
  1027. op = gimple_assign_lhs (stmt);
  1028. }
  1029. dom_use = NULL;
  1030. dom_bb = NULL;
  1031. FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, op)
  1032. {
  1033. if (is_gimple_debug (use_stmt))
  1034. continue;
  1035. if (dom_bb &&
  1036. dominated_by_p (CDI_DOMINATORS,
  1037. dom_bb, gimple_bb (use_stmt)))
  1038. {
  1039. dom_use = use_stmt;
  1040. dom_bb = NULL;
  1041. }
  1042. else if (dom_bb)
  1043. dom_bb = nearest_common_dominator (CDI_DOMINATORS, dom_bb,
  1044. gimple_bb (use_stmt));
  1045. else if (!dom_use)
  1046. dom_use = use_stmt;
  1047. else if (stmt_dominates_stmt_p (use_stmt, dom_use))
  1048. dom_use = use_stmt;
  1049. else if (!stmt_dominates_stmt_p (dom_use, use_stmt)
  1050. /* If dom_use and use_stmt are PHI nodes in one BB
  1051. then it is OK to keep any of them as dom_use.
  1052. stmt_dominates_stmt_p returns 0 for such
  1053. combination, so check it here manually. */
  1054. && (gimple_code (dom_use) != GIMPLE_PHI
  1055. || gimple_code (use_stmt) != GIMPLE_PHI
  1056. || gimple_bb (use_stmt) != gimple_bb (dom_use))
  1057. )
  1058. {
  1059. dom_bb = nearest_common_dominator (CDI_DOMINATORS,
  1060. gimple_bb (use_stmt),
  1061. gimple_bb (dom_use));
  1062. dom_use = NULL;
  1063. }
  1064. }
  1065. /* In case there is a single use, just move bounds
  1066. creation to the use. */
  1067. if (dom_use || dom_bb)
  1068. {
  1069. if (dump_file && (dump_flags & TDF_DETAILS))
  1070. {
  1071. fprintf (dump_file, "Moving creation of ");
  1072. print_generic_expr (dump_file, op, 0);
  1073. fprintf (dump_file, " down to its use.\n");
  1074. }
  1075. if (dom_use && gimple_code (dom_use) == GIMPLE_PHI)
  1076. {
  1077. dom_bb = get_immediate_dominator (CDI_DOMINATORS,
  1078. gimple_bb (dom_use));
  1079. dom_use = NULL;
  1080. }
  1081. if (dom_bb == bb
  1082. || (dom_use && gimple_bb (dom_use) == bb))
  1083. {
  1084. if (dump_file && (dump_flags & TDF_DETAILS))
  1085. fprintf (dump_file, "Cannot move statement bacause there is no "
  1086. "suitable dominator block other than entry block.\n");
  1087. gsi_next (&i);
  1088. }
  1089. else
  1090. {
  1091. if (dom_bb)
  1092. {
  1093. gimple_stmt_iterator last = gsi_last_bb (dom_bb);
  1094. if (!gsi_end_p (last) && stmt_ends_bb_p (gsi_stmt (last)))
  1095. gsi_move_before (&i, &last);
  1096. else
  1097. gsi_move_after (&i, &last);
  1098. }
  1099. else
  1100. {
  1101. gimple_stmt_iterator gsi = gsi_for_stmt (dom_use);
  1102. gsi_move_before (&i, &gsi);
  1103. }
  1104. update_stmt (stmt);
  1105. }
  1106. }
  1107. else
  1108. gsi_next (&i);
  1109. }
  1110. }
  1111. /* Initilize checker optimization pass. */
  1112. static void
  1113. chkp_opt_init (void)
  1114. {
  1115. check_infos.create (0);
  1116. calculate_dominance_info (CDI_DOMINATORS);
  1117. calculate_dominance_info (CDI_POST_DOMINATORS);
  1118. /* With LTO constant bounds vars may be not initialized by now.
  1119. Get constant bounds vars to handle their assignments during
  1120. optimizations. */
  1121. chkp_get_zero_bounds_var ();
  1122. chkp_get_none_bounds_var ();
  1123. }
  1124. /* Finalise checker optimization pass. */
  1125. static void
  1126. chkp_opt_fini (void)
  1127. {
  1128. chkp_fix_cfg ();
  1129. }
  1130. /* Checker optimization pass function. */
  1131. static unsigned int
  1132. chkp_opt_execute (void)
  1133. {
  1134. chkp_opt_init();
  1135. /* This optimization may introduce new checks
  1136. and thus we put it before checks search. */
  1137. chkp_optimize_string_function_calls ();
  1138. chkp_gather_checks_info ();
  1139. chkp_remove_excess_intersections ();
  1140. chkp_remove_constant_checks ();
  1141. chkp_reduce_bounds_lifetime ();
  1142. chkp_release_check_info ();
  1143. chkp_opt_fini ();
  1144. return 0;
  1145. }
  1146. /* Pass gate. */
  1147. static bool
  1148. chkp_opt_gate (void)
  1149. {
  1150. return chkp_function_instrumented_p (cfun->decl)
  1151. && (flag_chkp_optimize > 0
  1152. || (flag_chkp_optimize == -1 && optimize > 0));
  1153. }
  1154. namespace {
  1155. const pass_data pass_data_chkp_opt =
  1156. {
  1157. GIMPLE_PASS, /* type */
  1158. "chkpopt", /* name */
  1159. OPTGROUP_NONE, /* optinfo_flags */
  1160. TV_NONE, /* tv_id */
  1161. PROP_ssa | PROP_cfg, /* properties_required */
  1162. 0, /* properties_provided */
  1163. 0, /* properties_destroyed */
  1164. 0, /* todo_flags_start */
  1165. TODO_verify_il
  1166. | TODO_update_ssa /* todo_flags_finish */
  1167. };
  1168. class pass_chkp_opt : public gimple_opt_pass
  1169. {
  1170. public:
  1171. pass_chkp_opt (gcc::context *ctxt)
  1172. : gimple_opt_pass (pass_data_chkp_opt, ctxt)
  1173. {}
  1174. /* opt_pass methods: */
  1175. virtual opt_pass * clone ()
  1176. {
  1177. return new pass_chkp_opt (m_ctxt);
  1178. }
  1179. virtual bool gate (function *)
  1180. {
  1181. return chkp_opt_gate ();
  1182. }
  1183. virtual unsigned int execute (function *)
  1184. {
  1185. return chkp_opt_execute ();
  1186. }
  1187. }; // class pass_chkp_opt
  1188. } // anon namespace
  1189. gimple_opt_pass *
  1190. make_pass_chkp_opt (gcc::context *ctxt)
  1191. {
  1192. return new pass_chkp_opt (ctxt);
  1193. }