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