1*e4b17023SJohn Marino /* Predicate aware uninitialized variable warning.
2*e4b17023SJohn Marino    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 Free Software
3*e4b17023SJohn Marino    Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Xinliang David Li <davidxl@google.com>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "tree.h"
27*e4b17023SJohn Marino #include "flags.h"
28*e4b17023SJohn Marino #include "tm_p.h"
29*e4b17023SJohn Marino #include "langhooks.h"
30*e4b17023SJohn Marino #include "basic-block.h"
31*e4b17023SJohn Marino #include "output.h"
32*e4b17023SJohn Marino #include "function.h"
33*e4b17023SJohn Marino #include "gimple-pretty-print.h"
34*e4b17023SJohn Marino #include "bitmap.h"
35*e4b17023SJohn Marino #include "pointer-set.h"
36*e4b17023SJohn Marino #include "tree-flow.h"
37*e4b17023SJohn Marino #include "gimple.h"
38*e4b17023SJohn Marino #include "tree-inline.h"
39*e4b17023SJohn Marino #include "timevar.h"
40*e4b17023SJohn Marino #include "hashtab.h"
41*e4b17023SJohn Marino #include "tree-dump.h"
42*e4b17023SJohn Marino #include "tree-pass.h"
43*e4b17023SJohn Marino #include "diagnostic-core.h"
44*e4b17023SJohn Marino #include "timevar.h"
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* This implements the pass that does predicate aware warning on uses of
47*e4b17023SJohn Marino    possibly uninitialized variables. The pass first collects the set of
48*e4b17023SJohn Marino    possibly uninitialized SSA names. For each such name, it walks through
49*e4b17023SJohn Marino    all its immediate uses. For each immediate use, it rebuilds the condition
50*e4b17023SJohn Marino    expression (the predicate) that guards the use. The predicate is then
51*e4b17023SJohn Marino    examined to see if the variable is always defined under that same condition.
52*e4b17023SJohn Marino    This is done either by pruning the unrealizable paths that lead to the
53*e4b17023SJohn Marino    default definitions or by checking if the predicate set that guards the
54*e4b17023SJohn Marino    defining paths is a superset of the use predicate.  */
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino /* Pointer set of potentially undefined ssa names, i.e.,
58*e4b17023SJohn Marino    ssa names that are defined by phi with operands that
59*e4b17023SJohn Marino    are not defined or potentially undefined.  */
60*e4b17023SJohn Marino static struct pointer_set_t *possibly_undefined_names = 0;
61*e4b17023SJohn Marino 
62*e4b17023SJohn Marino /* Bit mask handling macros.  */
63*e4b17023SJohn Marino #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
64*e4b17023SJohn Marino #define MASK_TEST_BIT(mask, pos) (mask & (1 << pos))
65*e4b17023SJohn Marino #define MASK_EMPTY(mask) (mask == 0)
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino /* Returns the first bit position (starting from LSB)
68*e4b17023SJohn Marino    in mask that is non zero. Returns -1 if the mask is empty.  */
69*e4b17023SJohn Marino static int
get_mask_first_set_bit(unsigned mask)70*e4b17023SJohn Marino get_mask_first_set_bit (unsigned mask)
71*e4b17023SJohn Marino {
72*e4b17023SJohn Marino   int pos = 0;
73*e4b17023SJohn Marino   if (mask == 0)
74*e4b17023SJohn Marino     return -1;
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino   while ((mask & (1 << pos)) == 0)
77*e4b17023SJohn Marino     pos++;
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino   return pos;
80*e4b17023SJohn Marino }
81*e4b17023SJohn Marino #define MASK_FIRST_SET_BIT(mask) get_mask_first_set_bit (mask)
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino /* Return true if T, an SSA_NAME, has an undefined value.  */
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino bool
ssa_undefined_value_p(tree t)87*e4b17023SJohn Marino ssa_undefined_value_p (tree t)
88*e4b17023SJohn Marino {
89*e4b17023SJohn Marino   tree var = SSA_NAME_VAR (t);
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino   /* Parameters get their initial value from the function entry.  */
92*e4b17023SJohn Marino   if (TREE_CODE (var) == PARM_DECL)
93*e4b17023SJohn Marino     return false;
94*e4b17023SJohn Marino 
95*e4b17023SJohn Marino   /* When returning by reference the return address is actually a hidden
96*e4b17023SJohn Marino      parameter.  */
97*e4b17023SJohn Marino   if (TREE_CODE (SSA_NAME_VAR (t)) == RESULT_DECL
98*e4b17023SJohn Marino       && DECL_BY_REFERENCE (SSA_NAME_VAR (t)))
99*e4b17023SJohn Marino     return false;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino   /* Hard register variables get their initial value from the ether.  */
102*e4b17023SJohn Marino   if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
103*e4b17023SJohn Marino     return false;
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   /* The value is undefined iff its definition statement is empty.  */
106*e4b17023SJohn Marino   return (gimple_nop_p (SSA_NAME_DEF_STMT (t))
107*e4b17023SJohn Marino           || (possibly_undefined_names
108*e4b17023SJohn Marino               && pointer_set_contains (possibly_undefined_names, t)));
109*e4b17023SJohn Marino }
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino /* Checks if the operand OPND of PHI is defined by
112*e4b17023SJohn Marino    another phi with one operand defined by this PHI,
113*e4b17023SJohn Marino    but the rest operands are all defined. If yes,
114*e4b17023SJohn Marino    returns true to skip this this operand as being
115*e4b17023SJohn Marino    redundant. Can be enhanced to be more general.  */
116*e4b17023SJohn Marino 
117*e4b17023SJohn Marino static bool
can_skip_redundant_opnd(tree opnd,gimple phi)118*e4b17023SJohn Marino can_skip_redundant_opnd (tree opnd, gimple phi)
119*e4b17023SJohn Marino {
120*e4b17023SJohn Marino   gimple op_def;
121*e4b17023SJohn Marino   tree phi_def;
122*e4b17023SJohn Marino   int i, n;
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino   phi_def = gimple_phi_result (phi);
125*e4b17023SJohn Marino   op_def = SSA_NAME_DEF_STMT (opnd);
126*e4b17023SJohn Marino   if (gimple_code (op_def) != GIMPLE_PHI)
127*e4b17023SJohn Marino     return false;
128*e4b17023SJohn Marino   n = gimple_phi_num_args (op_def);
129*e4b17023SJohn Marino   for (i = 0; i < n; ++i)
130*e4b17023SJohn Marino     {
131*e4b17023SJohn Marino       tree op = gimple_phi_arg_def (op_def, i);
132*e4b17023SJohn Marino       if (TREE_CODE (op) != SSA_NAME)
133*e4b17023SJohn Marino         continue;
134*e4b17023SJohn Marino       if (op != phi_def && ssa_undefined_value_p (op))
135*e4b17023SJohn Marino         return false;
136*e4b17023SJohn Marino     }
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino   return true;
139*e4b17023SJohn Marino }
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino /* Returns a bit mask holding the positions of arguments in PHI
142*e4b17023SJohn Marino    that have empty (or possibly empty) definitions.  */
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino static unsigned
compute_uninit_opnds_pos(gimple phi)145*e4b17023SJohn Marino compute_uninit_opnds_pos (gimple phi)
146*e4b17023SJohn Marino {
147*e4b17023SJohn Marino   size_t i, n;
148*e4b17023SJohn Marino   unsigned uninit_opnds = 0;
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino   n = gimple_phi_num_args (phi);
151*e4b17023SJohn Marino   /* Bail out for phi with too many args.  */
152*e4b17023SJohn Marino   if (n > 32)
153*e4b17023SJohn Marino     return 0;
154*e4b17023SJohn Marino 
155*e4b17023SJohn Marino   for (i = 0; i < n; ++i)
156*e4b17023SJohn Marino     {
157*e4b17023SJohn Marino       tree op = gimple_phi_arg_def (phi, i);
158*e4b17023SJohn Marino       if (TREE_CODE (op) == SSA_NAME
159*e4b17023SJohn Marino           && ssa_undefined_value_p (op)
160*e4b17023SJohn Marino           && !can_skip_redundant_opnd (op, phi))
161*e4b17023SJohn Marino         MASK_SET_BIT (uninit_opnds, i);
162*e4b17023SJohn Marino     }
163*e4b17023SJohn Marino   return uninit_opnds;
164*e4b17023SJohn Marino }
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino /* Find the immediate postdominator PDOM of the specified
167*e4b17023SJohn Marino    basic block BLOCK.  */
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino static inline basic_block
find_pdom(basic_block block)170*e4b17023SJohn Marino find_pdom (basic_block block)
171*e4b17023SJohn Marino {
172*e4b17023SJohn Marino    if (block == EXIT_BLOCK_PTR)
173*e4b17023SJohn Marino      return EXIT_BLOCK_PTR;
174*e4b17023SJohn Marino    else
175*e4b17023SJohn Marino      {
176*e4b17023SJohn Marino        basic_block bb
177*e4b17023SJohn Marino            = get_immediate_dominator (CDI_POST_DOMINATORS, block);
178*e4b17023SJohn Marino        if (! bb)
179*e4b17023SJohn Marino          return EXIT_BLOCK_PTR;
180*e4b17023SJohn Marino        return bb;
181*e4b17023SJohn Marino      }
182*e4b17023SJohn Marino }
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino /* Find the immediate DOM of the specified
185*e4b17023SJohn Marino    basic block BLOCK.  */
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino static inline basic_block
find_dom(basic_block block)188*e4b17023SJohn Marino find_dom (basic_block block)
189*e4b17023SJohn Marino {
190*e4b17023SJohn Marino    if (block == ENTRY_BLOCK_PTR)
191*e4b17023SJohn Marino      return ENTRY_BLOCK_PTR;
192*e4b17023SJohn Marino    else
193*e4b17023SJohn Marino      {
194*e4b17023SJohn Marino        basic_block bb = get_immediate_dominator (CDI_DOMINATORS, block);
195*e4b17023SJohn Marino        if (! bb)
196*e4b17023SJohn Marino          return ENTRY_BLOCK_PTR;
197*e4b17023SJohn Marino        return bb;
198*e4b17023SJohn Marino      }
199*e4b17023SJohn Marino }
200*e4b17023SJohn Marino 
201*e4b17023SJohn Marino /* Returns true if BB1 is postdominating BB2 and BB1 is
202*e4b17023SJohn Marino    not a loop exit bb. The loop exit bb check is simple and does
203*e4b17023SJohn Marino    not cover all cases.  */
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino static bool
is_non_loop_exit_postdominating(basic_block bb1,basic_block bb2)206*e4b17023SJohn Marino is_non_loop_exit_postdominating (basic_block bb1, basic_block bb2)
207*e4b17023SJohn Marino {
208*e4b17023SJohn Marino   if (!dominated_by_p (CDI_POST_DOMINATORS, bb2, bb1))
209*e4b17023SJohn Marino     return false;
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino   if (single_pred_p (bb1) && !single_succ_p (bb2))
212*e4b17023SJohn Marino     return false;
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino   return true;
215*e4b17023SJohn Marino }
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino /* Find the closest postdominator of a specified BB, which is control
218*e4b17023SJohn Marino    equivalent to BB.  */
219*e4b17023SJohn Marino 
220*e4b17023SJohn Marino static inline  basic_block
find_control_equiv_block(basic_block bb)221*e4b17023SJohn Marino find_control_equiv_block (basic_block bb)
222*e4b17023SJohn Marino {
223*e4b17023SJohn Marino   basic_block pdom;
224*e4b17023SJohn Marino 
225*e4b17023SJohn Marino   pdom = find_pdom (bb);
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino   /* Skip the postdominating bb that is also loop exit.  */
228*e4b17023SJohn Marino   if (!is_non_loop_exit_postdominating (pdom, bb))
229*e4b17023SJohn Marino     return NULL;
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino   if (dominated_by_p (CDI_DOMINATORS, pdom, bb))
232*e4b17023SJohn Marino     return pdom;
233*e4b17023SJohn Marino 
234*e4b17023SJohn Marino   return NULL;
235*e4b17023SJohn Marino }
236*e4b17023SJohn Marino 
237*e4b17023SJohn Marino #define MAX_NUM_CHAINS 8
238*e4b17023SJohn Marino #define MAX_CHAIN_LEN 5
239*e4b17023SJohn Marino 
240*e4b17023SJohn Marino /* Computes the control dependence chains (paths of edges)
241*e4b17023SJohn Marino    for DEP_BB up to the dominating basic block BB (the head node of a
242*e4b17023SJohn Marino    chain should be dominated by it).  CD_CHAINS is pointer to a
243*e4b17023SJohn Marino    dynamic array holding the result chains. CUR_CD_CHAIN is the current
244*e4b17023SJohn Marino    chain being computed.  *NUM_CHAINS is total number of chains.  The
245*e4b17023SJohn Marino    function returns true if the information is successfully computed,
246*e4b17023SJohn Marino    return false if there is no control dependence or not computed.  */
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino static bool
compute_control_dep_chain(basic_block bb,basic_block dep_bb,VEC (edge,heap)** cd_chains,size_t * num_chains,VEC (edge,heap)** cur_cd_chain)249*e4b17023SJohn Marino compute_control_dep_chain (basic_block bb, basic_block dep_bb,
250*e4b17023SJohn Marino                            VEC(edge, heap) **cd_chains,
251*e4b17023SJohn Marino                            size_t *num_chains,
252*e4b17023SJohn Marino                            VEC(edge, heap) **cur_cd_chain)
253*e4b17023SJohn Marino {
254*e4b17023SJohn Marino   edge_iterator ei;
255*e4b17023SJohn Marino   edge e;
256*e4b17023SJohn Marino   size_t i;
257*e4b17023SJohn Marino   bool found_cd_chain = false;
258*e4b17023SJohn Marino   size_t cur_chain_len = 0;
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino   if (EDGE_COUNT (bb->succs) < 2)
261*e4b17023SJohn Marino     return false;
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   /* Could  use a set instead.  */
264*e4b17023SJohn Marino   cur_chain_len = VEC_length (edge, *cur_cd_chain);
265*e4b17023SJohn Marino   if (cur_chain_len > MAX_CHAIN_LEN)
266*e4b17023SJohn Marino     return false;
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino   for (i = 0; i < cur_chain_len; i++)
269*e4b17023SJohn Marino     {
270*e4b17023SJohn Marino       edge e = VEC_index (edge, *cur_cd_chain, i);
271*e4b17023SJohn Marino       /* cycle detected. */
272*e4b17023SJohn Marino       if (e->src == bb)
273*e4b17023SJohn Marino         return false;
274*e4b17023SJohn Marino     }
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->succs)
277*e4b17023SJohn Marino     {
278*e4b17023SJohn Marino       basic_block cd_bb;
279*e4b17023SJohn Marino       if (e->flags & (EDGE_FAKE | EDGE_ABNORMAL))
280*e4b17023SJohn Marino         continue;
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino       cd_bb = e->dest;
283*e4b17023SJohn Marino       VEC_safe_push (edge, heap, *cur_cd_chain, e);
284*e4b17023SJohn Marino       while (!is_non_loop_exit_postdominating (cd_bb, bb))
285*e4b17023SJohn Marino         {
286*e4b17023SJohn Marino           if (cd_bb == dep_bb)
287*e4b17023SJohn Marino             {
288*e4b17023SJohn Marino               /* Found a direct control dependence.  */
289*e4b17023SJohn Marino               if (*num_chains < MAX_NUM_CHAINS)
290*e4b17023SJohn Marino                 {
291*e4b17023SJohn Marino                   cd_chains[*num_chains]
292*e4b17023SJohn Marino                       = VEC_copy (edge, heap, *cur_cd_chain);
293*e4b17023SJohn Marino                   (*num_chains)++;
294*e4b17023SJohn Marino                 }
295*e4b17023SJohn Marino               found_cd_chain = true;
296*e4b17023SJohn Marino               /* check path from next edge.  */
297*e4b17023SJohn Marino               break;
298*e4b17023SJohn Marino             }
299*e4b17023SJohn Marino 
300*e4b17023SJohn Marino           /* Now check if DEP_BB is indirectly control dependent on BB.  */
301*e4b17023SJohn Marino           if (compute_control_dep_chain (cd_bb, dep_bb, cd_chains,
302*e4b17023SJohn Marino                                          num_chains, cur_cd_chain))
303*e4b17023SJohn Marino             {
304*e4b17023SJohn Marino               found_cd_chain = true;
305*e4b17023SJohn Marino               break;
306*e4b17023SJohn Marino             }
307*e4b17023SJohn Marino 
308*e4b17023SJohn Marino           cd_bb = find_pdom (cd_bb);
309*e4b17023SJohn Marino           if (cd_bb == EXIT_BLOCK_PTR)
310*e4b17023SJohn Marino             break;
311*e4b17023SJohn Marino         }
312*e4b17023SJohn Marino       VEC_pop (edge, *cur_cd_chain);
313*e4b17023SJohn Marino       gcc_assert (VEC_length (edge, *cur_cd_chain) == cur_chain_len);
314*e4b17023SJohn Marino     }
315*e4b17023SJohn Marino   gcc_assert (VEC_length (edge, *cur_cd_chain) == cur_chain_len);
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino   return found_cd_chain;
318*e4b17023SJohn Marino }
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino typedef struct use_pred_info
321*e4b17023SJohn Marino {
322*e4b17023SJohn Marino   gimple cond;
323*e4b17023SJohn Marino   bool invert;
324*e4b17023SJohn Marino } *use_pred_info_t;
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino DEF_VEC_P(use_pred_info_t);
327*e4b17023SJohn Marino DEF_VEC_ALLOC_P(use_pred_info_t, heap);
328*e4b17023SJohn Marino 
329*e4b17023SJohn Marino 
330*e4b17023SJohn Marino /* Converts the chains of control dependence edges into a set of
331*e4b17023SJohn Marino    predicates. A control dependence chain is represented by a vector
332*e4b17023SJohn Marino    edges. DEP_CHAINS points to an array of dependence chains.
333*e4b17023SJohn Marino    NUM_CHAINS is the size of the chain array. One edge in a dependence
334*e4b17023SJohn Marino    chain is mapped to predicate expression represented by use_pred_info_t
335*e4b17023SJohn Marino    type. One dependence chain is converted to a composite predicate that
336*e4b17023SJohn Marino    is the result of AND operation of use_pred_info_t mapped to each edge.
337*e4b17023SJohn Marino    A composite predicate is presented by a vector of use_pred_info_t. On
338*e4b17023SJohn Marino    return, *PREDS points to the resulting array of composite predicates.
339*e4b17023SJohn Marino    *NUM_PREDS is the number of composite predictes.  */
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino static bool
convert_control_dep_chain_into_preds(VEC (edge,heap)** dep_chains,size_t num_chains,VEC (use_pred_info_t,heap)*** preds,size_t * num_preds)342*e4b17023SJohn Marino convert_control_dep_chain_into_preds (VEC(edge, heap) **dep_chains,
343*e4b17023SJohn Marino                                       size_t num_chains,
344*e4b17023SJohn Marino                                       VEC(use_pred_info_t, heap) ***preds,
345*e4b17023SJohn Marino                                       size_t *num_preds)
346*e4b17023SJohn Marino {
347*e4b17023SJohn Marino   bool has_valid_pred = false;
348*e4b17023SJohn Marino   size_t i, j;
349*e4b17023SJohn Marino   if (num_chains == 0 || num_chains >= MAX_NUM_CHAINS)
350*e4b17023SJohn Marino     return false;
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino   /* Now convert the control dep chain into a set
353*e4b17023SJohn Marino      of predicates.  */
354*e4b17023SJohn Marino   *preds = XCNEWVEC (VEC(use_pred_info_t, heap) *,
355*e4b17023SJohn Marino                      num_chains);
356*e4b17023SJohn Marino   *num_preds = num_chains;
357*e4b17023SJohn Marino 
358*e4b17023SJohn Marino   for (i = 0; i < num_chains; i++)
359*e4b17023SJohn Marino     {
360*e4b17023SJohn Marino       VEC(edge, heap) *one_cd_chain = dep_chains[i];
361*e4b17023SJohn Marino 
362*e4b17023SJohn Marino       has_valid_pred = false;
363*e4b17023SJohn Marino       for (j = 0; j < VEC_length (edge, one_cd_chain); j++)
364*e4b17023SJohn Marino         {
365*e4b17023SJohn Marino           gimple cond_stmt;
366*e4b17023SJohn Marino           gimple_stmt_iterator gsi;
367*e4b17023SJohn Marino           basic_block guard_bb;
368*e4b17023SJohn Marino           use_pred_info_t one_pred;
369*e4b17023SJohn Marino           edge e;
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino           e = VEC_index (edge, one_cd_chain, j);
372*e4b17023SJohn Marino           guard_bb = e->src;
373*e4b17023SJohn Marino           gsi = gsi_last_bb (guard_bb);
374*e4b17023SJohn Marino           if (gsi_end_p (gsi))
375*e4b17023SJohn Marino             {
376*e4b17023SJohn Marino               has_valid_pred = false;
377*e4b17023SJohn Marino               break;
378*e4b17023SJohn Marino             }
379*e4b17023SJohn Marino           cond_stmt = gsi_stmt (gsi);
380*e4b17023SJohn Marino           if (gimple_code (cond_stmt) == GIMPLE_CALL
381*e4b17023SJohn Marino               && EDGE_COUNT (e->src->succs) >= 2)
382*e4b17023SJohn Marino             {
383*e4b17023SJohn Marino               /* Ignore EH edge. Can add assertion
384*e4b17023SJohn Marino                  on the other edge's flag.  */
385*e4b17023SJohn Marino               continue;
386*e4b17023SJohn Marino             }
387*e4b17023SJohn Marino           /* Skip if there is essentially one succesor.  */
388*e4b17023SJohn Marino           if (EDGE_COUNT (e->src->succs) == 2)
389*e4b17023SJohn Marino             {
390*e4b17023SJohn Marino               edge e1;
391*e4b17023SJohn Marino               edge_iterator ei1;
392*e4b17023SJohn Marino               bool skip = false;
393*e4b17023SJohn Marino 
394*e4b17023SJohn Marino               FOR_EACH_EDGE (e1, ei1, e->src->succs)
395*e4b17023SJohn Marino                 {
396*e4b17023SJohn Marino                   if (EDGE_COUNT (e1->dest->succs) == 0)
397*e4b17023SJohn Marino                     {
398*e4b17023SJohn Marino                       skip = true;
399*e4b17023SJohn Marino                       break;
400*e4b17023SJohn Marino                     }
401*e4b17023SJohn Marino                 }
402*e4b17023SJohn Marino               if (skip)
403*e4b17023SJohn Marino                 continue;
404*e4b17023SJohn Marino             }
405*e4b17023SJohn Marino           if (gimple_code (cond_stmt) != GIMPLE_COND)
406*e4b17023SJohn Marino             {
407*e4b17023SJohn Marino               has_valid_pred = false;
408*e4b17023SJohn Marino               break;
409*e4b17023SJohn Marino             }
410*e4b17023SJohn Marino           one_pred = XNEW (struct use_pred_info);
411*e4b17023SJohn Marino           one_pred->cond = cond_stmt;
412*e4b17023SJohn Marino           one_pred->invert = !!(e->flags & EDGE_FALSE_VALUE);
413*e4b17023SJohn Marino           VEC_safe_push (use_pred_info_t, heap, (*preds)[i], one_pred);
414*e4b17023SJohn Marino 	  has_valid_pred = true;
415*e4b17023SJohn Marino         }
416*e4b17023SJohn Marino 
417*e4b17023SJohn Marino       if (!has_valid_pred)
418*e4b17023SJohn Marino         break;
419*e4b17023SJohn Marino     }
420*e4b17023SJohn Marino   return has_valid_pred;
421*e4b17023SJohn Marino }
422*e4b17023SJohn Marino 
423*e4b17023SJohn Marino /* Computes all control dependence chains for USE_BB. The control
424*e4b17023SJohn Marino    dependence chains are then converted to an array of composite
425*e4b17023SJohn Marino    predicates pointed to by PREDS.  PHI_BB is the basic block of
426*e4b17023SJohn Marino    the phi whose result is used in USE_BB.  */
427*e4b17023SJohn Marino 
428*e4b17023SJohn Marino static bool
find_predicates(VEC (use_pred_info_t,heap)*** preds,size_t * num_preds,basic_block phi_bb,basic_block use_bb)429*e4b17023SJohn Marino find_predicates (VEC(use_pred_info_t, heap) ***preds,
430*e4b17023SJohn Marino                  size_t *num_preds,
431*e4b17023SJohn Marino                  basic_block phi_bb,
432*e4b17023SJohn Marino                  basic_block use_bb)
433*e4b17023SJohn Marino {
434*e4b17023SJohn Marino   size_t num_chains = 0, i;
435*e4b17023SJohn Marino   VEC(edge, heap) **dep_chains = 0;
436*e4b17023SJohn Marino   VEC(edge, heap) *cur_chain = 0;
437*e4b17023SJohn Marino   bool has_valid_pred = false;
438*e4b17023SJohn Marino   basic_block cd_root = 0;
439*e4b17023SJohn Marino 
440*e4b17023SJohn Marino   dep_chains = XCNEWVEC (VEC(edge, heap) *, MAX_NUM_CHAINS);
441*e4b17023SJohn Marino 
442*e4b17023SJohn Marino   /* First find the closest bb that is control equivalent to PHI_BB
443*e4b17023SJohn Marino      that also dominates USE_BB.  */
444*e4b17023SJohn Marino   cd_root = phi_bb;
445*e4b17023SJohn Marino   while (dominated_by_p (CDI_DOMINATORS, use_bb, cd_root))
446*e4b17023SJohn Marino     {
447*e4b17023SJohn Marino       basic_block ctrl_eq_bb = find_control_equiv_block (cd_root);
448*e4b17023SJohn Marino       if (ctrl_eq_bb && dominated_by_p (CDI_DOMINATORS, use_bb, ctrl_eq_bb))
449*e4b17023SJohn Marino         cd_root = ctrl_eq_bb;
450*e4b17023SJohn Marino       else
451*e4b17023SJohn Marino         break;
452*e4b17023SJohn Marino     }
453*e4b17023SJohn Marino 
454*e4b17023SJohn Marino   compute_control_dep_chain (cd_root, use_bb,
455*e4b17023SJohn Marino                              dep_chains, &num_chains,
456*e4b17023SJohn Marino                              &cur_chain);
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino   has_valid_pred
459*e4b17023SJohn Marino       = convert_control_dep_chain_into_preds (dep_chains,
460*e4b17023SJohn Marino                                               num_chains,
461*e4b17023SJohn Marino                                               preds,
462*e4b17023SJohn Marino                                               num_preds);
463*e4b17023SJohn Marino   /* Free individual chain  */
464*e4b17023SJohn Marino   VEC_free (edge, heap, cur_chain);
465*e4b17023SJohn Marino   for (i = 0; i < num_chains; i++)
466*e4b17023SJohn Marino       VEC_free (edge, heap, dep_chains[i]);
467*e4b17023SJohn Marino   free (dep_chains);
468*e4b17023SJohn Marino   return has_valid_pred;
469*e4b17023SJohn Marino }
470*e4b17023SJohn Marino 
471*e4b17023SJohn Marino /* Computes the set of incoming edges of PHI that have non empty
472*e4b17023SJohn Marino    definitions of a phi chain.  The collection will be done
473*e4b17023SJohn Marino    recursively on operands that are defined by phis. CD_ROOT
474*e4b17023SJohn Marino    is the control dependence root. *EDGES holds the result, and
475*e4b17023SJohn Marino    VISITED_PHIS is a pointer set for detecting cycles.  */
476*e4b17023SJohn Marino 
477*e4b17023SJohn Marino static void
collect_phi_def_edges(gimple phi,basic_block cd_root,VEC (edge,heap)** edges,struct pointer_set_t * visited_phis)478*e4b17023SJohn Marino collect_phi_def_edges (gimple phi, basic_block cd_root,
479*e4b17023SJohn Marino                        VEC(edge, heap) **edges,
480*e4b17023SJohn Marino                        struct pointer_set_t *visited_phis)
481*e4b17023SJohn Marino {
482*e4b17023SJohn Marino   size_t i, n;
483*e4b17023SJohn Marino   edge opnd_edge;
484*e4b17023SJohn Marino   tree opnd;
485*e4b17023SJohn Marino 
486*e4b17023SJohn Marino   if (pointer_set_insert (visited_phis, phi))
487*e4b17023SJohn Marino     return;
488*e4b17023SJohn Marino 
489*e4b17023SJohn Marino   n = gimple_phi_num_args (phi);
490*e4b17023SJohn Marino   for (i = 0; i < n; i++)
491*e4b17023SJohn Marino     {
492*e4b17023SJohn Marino       opnd_edge = gimple_phi_arg_edge (phi, i);
493*e4b17023SJohn Marino       opnd = gimple_phi_arg_def (phi, i);
494*e4b17023SJohn Marino 
495*e4b17023SJohn Marino       if (TREE_CODE (opnd) != SSA_NAME)
496*e4b17023SJohn Marino         {
497*e4b17023SJohn Marino           if (dump_file && (dump_flags & TDF_DETAILS))
498*e4b17023SJohn Marino             {
499*e4b17023SJohn Marino               fprintf (dump_file, "\n[CHECK] Found def edge %d in ", (int)i);
500*e4b17023SJohn Marino               print_gimple_stmt (dump_file, phi, 0, 0);
501*e4b17023SJohn Marino             }
502*e4b17023SJohn Marino           VEC_safe_push (edge, heap, *edges, opnd_edge);
503*e4b17023SJohn Marino         }
504*e4b17023SJohn Marino       else
505*e4b17023SJohn Marino         {
506*e4b17023SJohn Marino           gimple def = SSA_NAME_DEF_STMT (opnd);
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino           if (gimple_code (def) == GIMPLE_PHI
509*e4b17023SJohn Marino               && dominated_by_p (CDI_DOMINATORS,
510*e4b17023SJohn Marino                                  gimple_bb (def), cd_root))
511*e4b17023SJohn Marino             collect_phi_def_edges (def, cd_root, edges,
512*e4b17023SJohn Marino                                    visited_phis);
513*e4b17023SJohn Marino           else if (!ssa_undefined_value_p (opnd))
514*e4b17023SJohn Marino             {
515*e4b17023SJohn Marino               if (dump_file && (dump_flags & TDF_DETAILS))
516*e4b17023SJohn Marino                 {
517*e4b17023SJohn Marino                   fprintf (dump_file, "\n[CHECK] Found def edge %d in ", (int)i);
518*e4b17023SJohn Marino                   print_gimple_stmt (dump_file, phi, 0, 0);
519*e4b17023SJohn Marino                 }
520*e4b17023SJohn Marino               VEC_safe_push (edge, heap, *edges, opnd_edge);
521*e4b17023SJohn Marino             }
522*e4b17023SJohn Marino         }
523*e4b17023SJohn Marino     }
524*e4b17023SJohn Marino }
525*e4b17023SJohn Marino 
526*e4b17023SJohn Marino /* For each use edge of PHI, computes all control dependence chains.
527*e4b17023SJohn Marino    The control dependence chains are then converted to an array of
528*e4b17023SJohn Marino    composite predicates pointed to by PREDS.  */
529*e4b17023SJohn Marino 
530*e4b17023SJohn Marino static bool
find_def_preds(VEC (use_pred_info_t,heap)*** preds,size_t * num_preds,gimple phi)531*e4b17023SJohn Marino find_def_preds (VEC(use_pred_info_t, heap) ***preds,
532*e4b17023SJohn Marino                 size_t *num_preds, gimple phi)
533*e4b17023SJohn Marino {
534*e4b17023SJohn Marino   size_t num_chains = 0, i, n;
535*e4b17023SJohn Marino   VEC(edge, heap) **dep_chains = 0;
536*e4b17023SJohn Marino   VEC(edge, heap) *cur_chain = 0;
537*e4b17023SJohn Marino   VEC(edge, heap) *def_edges = 0;
538*e4b17023SJohn Marino   bool has_valid_pred = false;
539*e4b17023SJohn Marino   basic_block phi_bb, cd_root = 0;
540*e4b17023SJohn Marino   struct pointer_set_t *visited_phis;
541*e4b17023SJohn Marino 
542*e4b17023SJohn Marino   dep_chains = XCNEWVEC (VEC(edge, heap) *, MAX_NUM_CHAINS);
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino   phi_bb = gimple_bb (phi);
545*e4b17023SJohn Marino   /* First find the closest dominating bb to be
546*e4b17023SJohn Marino      the control dependence root  */
547*e4b17023SJohn Marino   cd_root = find_dom (phi_bb);
548*e4b17023SJohn Marino   if (!cd_root)
549*e4b17023SJohn Marino     return false;
550*e4b17023SJohn Marino 
551*e4b17023SJohn Marino   visited_phis = pointer_set_create ();
552*e4b17023SJohn Marino   collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
553*e4b17023SJohn Marino   pointer_set_destroy (visited_phis);
554*e4b17023SJohn Marino 
555*e4b17023SJohn Marino   n = VEC_length (edge, def_edges);
556*e4b17023SJohn Marino   if (n == 0)
557*e4b17023SJohn Marino     return false;
558*e4b17023SJohn Marino 
559*e4b17023SJohn Marino   for (i = 0; i < n; i++)
560*e4b17023SJohn Marino     {
561*e4b17023SJohn Marino       size_t prev_nc, j;
562*e4b17023SJohn Marino       edge opnd_edge;
563*e4b17023SJohn Marino 
564*e4b17023SJohn Marino       opnd_edge = VEC_index (edge, def_edges, i);
565*e4b17023SJohn Marino       prev_nc = num_chains;
566*e4b17023SJohn Marino       compute_control_dep_chain (cd_root, opnd_edge->src,
567*e4b17023SJohn Marino                                  dep_chains, &num_chains,
568*e4b17023SJohn Marino                                  &cur_chain);
569*e4b17023SJohn Marino       /* Free individual chain  */
570*e4b17023SJohn Marino       VEC_free (edge, heap, cur_chain);
571*e4b17023SJohn Marino       cur_chain = 0;
572*e4b17023SJohn Marino 
573*e4b17023SJohn Marino       /* Now update the newly added chains with
574*e4b17023SJohn Marino          the phi operand edge:  */
575*e4b17023SJohn Marino       if (EDGE_COUNT (opnd_edge->src->succs) > 1)
576*e4b17023SJohn Marino         {
577*e4b17023SJohn Marino           if (prev_nc == num_chains
578*e4b17023SJohn Marino               && num_chains < MAX_NUM_CHAINS)
579*e4b17023SJohn Marino             num_chains++;
580*e4b17023SJohn Marino           for (j = prev_nc; j < num_chains; j++)
581*e4b17023SJohn Marino             {
582*e4b17023SJohn Marino               VEC_safe_push (edge, heap, dep_chains[j], opnd_edge);
583*e4b17023SJohn Marino             }
584*e4b17023SJohn Marino         }
585*e4b17023SJohn Marino     }
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino   has_valid_pred
588*e4b17023SJohn Marino       = convert_control_dep_chain_into_preds (dep_chains,
589*e4b17023SJohn Marino                                               num_chains,
590*e4b17023SJohn Marino                                               preds,
591*e4b17023SJohn Marino                                               num_preds);
592*e4b17023SJohn Marino   for (i = 0; i < num_chains; i++)
593*e4b17023SJohn Marino       VEC_free (edge, heap, dep_chains[i]);
594*e4b17023SJohn Marino   free (dep_chains);
595*e4b17023SJohn Marino   return has_valid_pred;
596*e4b17023SJohn Marino }
597*e4b17023SJohn Marino 
598*e4b17023SJohn Marino /* Dumps the predicates (PREDS) for USESTMT.  */
599*e4b17023SJohn Marino 
600*e4b17023SJohn Marino static void
dump_predicates(gimple usestmt,size_t num_preds,VEC (use_pred_info_t,heap)** preds,const char * msg)601*e4b17023SJohn Marino dump_predicates (gimple usestmt, size_t num_preds,
602*e4b17023SJohn Marino                  VEC(use_pred_info_t, heap) **preds,
603*e4b17023SJohn Marino                  const char* msg)
604*e4b17023SJohn Marino {
605*e4b17023SJohn Marino   size_t i, j;
606*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) *one_pred_chain;
607*e4b17023SJohn Marino   fprintf (dump_file, msg);
608*e4b17023SJohn Marino   print_gimple_stmt (dump_file, usestmt, 0, 0);
609*e4b17023SJohn Marino   fprintf (dump_file, "is guarded by :\n");
610*e4b17023SJohn Marino   /* do some dumping here:  */
611*e4b17023SJohn Marino   for (i = 0; i < num_preds; i++)
612*e4b17023SJohn Marino     {
613*e4b17023SJohn Marino       size_t np;
614*e4b17023SJohn Marino 
615*e4b17023SJohn Marino       one_pred_chain = preds[i];
616*e4b17023SJohn Marino       np = VEC_length (use_pred_info_t, one_pred_chain);
617*e4b17023SJohn Marino 
618*e4b17023SJohn Marino       for (j = 0; j < np; j++)
619*e4b17023SJohn Marino         {
620*e4b17023SJohn Marino           use_pred_info_t one_pred
621*e4b17023SJohn Marino               = VEC_index (use_pred_info_t, one_pred_chain, j);
622*e4b17023SJohn Marino           if (one_pred->invert)
623*e4b17023SJohn Marino             fprintf (dump_file, " (.NOT.) ");
624*e4b17023SJohn Marino           print_gimple_stmt (dump_file, one_pred->cond, 0, 0);
625*e4b17023SJohn Marino           if (j < np - 1)
626*e4b17023SJohn Marino             fprintf (dump_file, "(.AND.)\n");
627*e4b17023SJohn Marino         }
628*e4b17023SJohn Marino       if (i < num_preds - 1)
629*e4b17023SJohn Marino         fprintf (dump_file, "(.OR.)\n");
630*e4b17023SJohn Marino     }
631*e4b17023SJohn Marino }
632*e4b17023SJohn Marino 
633*e4b17023SJohn Marino /* Destroys the predicate set *PREDS.  */
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino static void
destroy_predicate_vecs(size_t n,VEC (use_pred_info_t,heap)** preds)636*e4b17023SJohn Marino destroy_predicate_vecs (size_t n,
637*e4b17023SJohn Marino                         VEC(use_pred_info_t, heap) ** preds)
638*e4b17023SJohn Marino {
639*e4b17023SJohn Marino   size_t i, j;
640*e4b17023SJohn Marino   for (i = 0; i < n; i++)
641*e4b17023SJohn Marino     {
642*e4b17023SJohn Marino       for (j = 0; j < VEC_length (use_pred_info_t, preds[i]); j++)
643*e4b17023SJohn Marino         free (VEC_index (use_pred_info_t, preds[i], j));
644*e4b17023SJohn Marino       VEC_free (use_pred_info_t, heap, preds[i]);
645*e4b17023SJohn Marino     }
646*e4b17023SJohn Marino   free (preds);
647*e4b17023SJohn Marino }
648*e4b17023SJohn Marino 
649*e4b17023SJohn Marino 
650*e4b17023SJohn Marino /* Computes the 'normalized' conditional code with operand
651*e4b17023SJohn Marino    swapping and condition inversion.  */
652*e4b17023SJohn Marino 
653*e4b17023SJohn Marino static enum tree_code
get_cmp_code(enum tree_code orig_cmp_code,bool swap_cond,bool invert)654*e4b17023SJohn Marino get_cmp_code (enum tree_code orig_cmp_code,
655*e4b17023SJohn Marino               bool swap_cond, bool invert)
656*e4b17023SJohn Marino {
657*e4b17023SJohn Marino   enum tree_code tc = orig_cmp_code;
658*e4b17023SJohn Marino 
659*e4b17023SJohn Marino   if (swap_cond)
660*e4b17023SJohn Marino     tc = swap_tree_comparison (orig_cmp_code);
661*e4b17023SJohn Marino   if (invert)
662*e4b17023SJohn Marino     tc = invert_tree_comparison (tc, false);
663*e4b17023SJohn Marino 
664*e4b17023SJohn Marino   switch (tc)
665*e4b17023SJohn Marino     {
666*e4b17023SJohn Marino     case LT_EXPR:
667*e4b17023SJohn Marino     case LE_EXPR:
668*e4b17023SJohn Marino     case GT_EXPR:
669*e4b17023SJohn Marino     case GE_EXPR:
670*e4b17023SJohn Marino     case EQ_EXPR:
671*e4b17023SJohn Marino     case NE_EXPR:
672*e4b17023SJohn Marino       break;
673*e4b17023SJohn Marino     default:
674*e4b17023SJohn Marino       return ERROR_MARK;
675*e4b17023SJohn Marino     }
676*e4b17023SJohn Marino   return tc;
677*e4b17023SJohn Marino }
678*e4b17023SJohn Marino 
679*e4b17023SJohn Marino /* Returns true if VAL falls in the range defined by BOUNDARY and CMPC, i.e.
680*e4b17023SJohn Marino    all values in the range satisfies (x CMPC BOUNDARY) == true.  */
681*e4b17023SJohn Marino 
682*e4b17023SJohn Marino static bool
is_value_included_in(tree val,tree boundary,enum tree_code cmpc)683*e4b17023SJohn Marino is_value_included_in (tree val, tree boundary, enum tree_code cmpc)
684*e4b17023SJohn Marino {
685*e4b17023SJohn Marino   bool inverted = false;
686*e4b17023SJohn Marino   bool is_unsigned;
687*e4b17023SJohn Marino   bool result;
688*e4b17023SJohn Marino 
689*e4b17023SJohn Marino   /* Only handle integer constant here.  */
690*e4b17023SJohn Marino   if (TREE_CODE (val) != INTEGER_CST
691*e4b17023SJohn Marino       || TREE_CODE (boundary) != INTEGER_CST)
692*e4b17023SJohn Marino     return true;
693*e4b17023SJohn Marino 
694*e4b17023SJohn Marino   is_unsigned = TYPE_UNSIGNED (TREE_TYPE (val));
695*e4b17023SJohn Marino 
696*e4b17023SJohn Marino   if (cmpc == GE_EXPR || cmpc == GT_EXPR
697*e4b17023SJohn Marino       || cmpc == NE_EXPR)
698*e4b17023SJohn Marino     {
699*e4b17023SJohn Marino       cmpc = invert_tree_comparison (cmpc, false);
700*e4b17023SJohn Marino       inverted = true;
701*e4b17023SJohn Marino     }
702*e4b17023SJohn Marino 
703*e4b17023SJohn Marino   if (is_unsigned)
704*e4b17023SJohn Marino     {
705*e4b17023SJohn Marino       if (cmpc == EQ_EXPR)
706*e4b17023SJohn Marino         result = tree_int_cst_equal (val, boundary);
707*e4b17023SJohn Marino       else if (cmpc == LT_EXPR)
708*e4b17023SJohn Marino         result = INT_CST_LT_UNSIGNED (val, boundary);
709*e4b17023SJohn Marino       else
710*e4b17023SJohn Marino         {
711*e4b17023SJohn Marino           gcc_assert (cmpc == LE_EXPR);
712*e4b17023SJohn Marino           result = (tree_int_cst_equal (val, boundary)
713*e4b17023SJohn Marino                     || INT_CST_LT_UNSIGNED (val, boundary));
714*e4b17023SJohn Marino         }
715*e4b17023SJohn Marino     }
716*e4b17023SJohn Marino   else
717*e4b17023SJohn Marino     {
718*e4b17023SJohn Marino       if (cmpc == EQ_EXPR)
719*e4b17023SJohn Marino         result = tree_int_cst_equal (val, boundary);
720*e4b17023SJohn Marino       else if (cmpc == LT_EXPR)
721*e4b17023SJohn Marino         result = INT_CST_LT (val, boundary);
722*e4b17023SJohn Marino       else
723*e4b17023SJohn Marino         {
724*e4b17023SJohn Marino           gcc_assert (cmpc == LE_EXPR);
725*e4b17023SJohn Marino           result = (tree_int_cst_equal (val, boundary)
726*e4b17023SJohn Marino                     || INT_CST_LT (val, boundary));
727*e4b17023SJohn Marino         }
728*e4b17023SJohn Marino     }
729*e4b17023SJohn Marino 
730*e4b17023SJohn Marino   if (inverted)
731*e4b17023SJohn Marino     result ^= 1;
732*e4b17023SJohn Marino 
733*e4b17023SJohn Marino   return result;
734*e4b17023SJohn Marino }
735*e4b17023SJohn Marino 
736*e4b17023SJohn Marino /* Returns true if PRED is common among all the predicate
737*e4b17023SJohn Marino    chains (PREDS) (and therefore can be factored out).
738*e4b17023SJohn Marino    NUM_PRED_CHAIN is the size of array PREDS.  */
739*e4b17023SJohn Marino 
740*e4b17023SJohn Marino static bool
find_matching_predicate_in_rest_chains(use_pred_info_t pred,VEC (use_pred_info_t,heap)** preds,size_t num_pred_chains)741*e4b17023SJohn Marino find_matching_predicate_in_rest_chains (use_pred_info_t pred,
742*e4b17023SJohn Marino                                         VEC(use_pred_info_t, heap) **preds,
743*e4b17023SJohn Marino                                         size_t num_pred_chains)
744*e4b17023SJohn Marino {
745*e4b17023SJohn Marino   size_t i, j, n;
746*e4b17023SJohn Marino 
747*e4b17023SJohn Marino   /* trival case  */
748*e4b17023SJohn Marino   if (num_pred_chains == 1)
749*e4b17023SJohn Marino     return true;
750*e4b17023SJohn Marino 
751*e4b17023SJohn Marino   for (i = 1; i < num_pred_chains; i++)
752*e4b17023SJohn Marino     {
753*e4b17023SJohn Marino       bool found = false;
754*e4b17023SJohn Marino       VEC(use_pred_info_t, heap) *one_chain = preds[i];
755*e4b17023SJohn Marino       n = VEC_length (use_pred_info_t, one_chain);
756*e4b17023SJohn Marino       for (j = 0; j < n; j++)
757*e4b17023SJohn Marino         {
758*e4b17023SJohn Marino           use_pred_info_t pred2
759*e4b17023SJohn Marino               = VEC_index (use_pred_info_t, one_chain, j);
760*e4b17023SJohn Marino           /* can relax the condition comparison to not
761*e4b17023SJohn Marino              use address comparison. However, the most common
762*e4b17023SJohn Marino              case is that multiple control dependent paths share
763*e4b17023SJohn Marino              a common path prefix, so address comparison should
764*e4b17023SJohn Marino              be ok.  */
765*e4b17023SJohn Marino 
766*e4b17023SJohn Marino           if (pred2->cond == pred->cond
767*e4b17023SJohn Marino               && pred2->invert == pred->invert)
768*e4b17023SJohn Marino             {
769*e4b17023SJohn Marino               found = true;
770*e4b17023SJohn Marino               break;
771*e4b17023SJohn Marino             }
772*e4b17023SJohn Marino         }
773*e4b17023SJohn Marino       if (!found)
774*e4b17023SJohn Marino         return false;
775*e4b17023SJohn Marino     }
776*e4b17023SJohn Marino   return true;
777*e4b17023SJohn Marino }
778*e4b17023SJohn Marino 
779*e4b17023SJohn Marino /* Forward declaration.  */
780*e4b17023SJohn Marino static bool
781*e4b17023SJohn Marino is_use_properly_guarded (gimple use_stmt,
782*e4b17023SJohn Marino                          basic_block use_bb,
783*e4b17023SJohn Marino                          gimple phi,
784*e4b17023SJohn Marino                          unsigned uninit_opnds,
785*e4b17023SJohn Marino                          struct pointer_set_t *visited_phis);
786*e4b17023SJohn Marino 
787*e4b17023SJohn Marino /* Returns true if all uninitialized opnds are pruned. Returns false
788*e4b17023SJohn Marino    otherwise. PHI is the phi node with uninitialized operands,
789*e4b17023SJohn Marino    UNINIT_OPNDS is the bitmap of the uninitialize operand positions,
790*e4b17023SJohn Marino    FLAG_DEF is the statement defining the flag guarding the use of the
791*e4b17023SJohn Marino    PHI output, BOUNDARY_CST is the const value used in the predicate
792*e4b17023SJohn Marino    associated with the flag, CMP_CODE is the comparison code used in
793*e4b17023SJohn Marino    the predicate, VISITED_PHIS is the pointer set of phis visited, and
794*e4b17023SJohn Marino    VISITED_FLAG_PHIS is the pointer to the pointer set of flag definitions
795*e4b17023SJohn Marino    that are also phis.
796*e4b17023SJohn Marino 
797*e4b17023SJohn Marino    Example scenario:
798*e4b17023SJohn Marino 
799*e4b17023SJohn Marino    BB1:
800*e4b17023SJohn Marino    flag_1 = phi <0, 1>                  // (1)
801*e4b17023SJohn Marino    var_1  = phi <undef, some_val>
802*e4b17023SJohn Marino 
803*e4b17023SJohn Marino 
804*e4b17023SJohn Marino    BB2:
805*e4b17023SJohn Marino    flag_2 = phi <0,   flag_1, flag_1>   // (2)
806*e4b17023SJohn Marino    var_2  = phi <undef, var_1, var_1>
807*e4b17023SJohn Marino    if (flag_2 == 1)
808*e4b17023SJohn Marino       goto BB3;
809*e4b17023SJohn Marino 
810*e4b17023SJohn Marino    BB3:
811*e4b17023SJohn Marino    use of var_2                         // (3)
812*e4b17023SJohn Marino 
813*e4b17023SJohn Marino    Because some flag arg in (1) is not constant, if we do not look into the
814*e4b17023SJohn Marino    flag phis recursively, it is conservatively treated as unknown and var_1
815*e4b17023SJohn Marino    is thought to be flowed into use at (3). Since var_1 is potentially uninitialized
816*e4b17023SJohn Marino    a false warning will be emitted. Checking recursively into (1), the compiler can
817*e4b17023SJohn Marino    find out that only some_val (which is defined) can flow into (3) which is OK.
818*e4b17023SJohn Marino 
819*e4b17023SJohn Marino */
820*e4b17023SJohn Marino 
821*e4b17023SJohn Marino static bool
prune_uninit_phi_opnds_in_unrealizable_paths(gimple phi,unsigned uninit_opnds,gimple flag_def,tree boundary_cst,enum tree_code cmp_code,struct pointer_set_t * visited_phis,bitmap * visited_flag_phis)822*e4b17023SJohn Marino prune_uninit_phi_opnds_in_unrealizable_paths (
823*e4b17023SJohn Marino     gimple phi, unsigned uninit_opnds,
824*e4b17023SJohn Marino     gimple flag_def, tree boundary_cst,
825*e4b17023SJohn Marino     enum tree_code cmp_code,
826*e4b17023SJohn Marino     struct pointer_set_t *visited_phis,
827*e4b17023SJohn Marino     bitmap *visited_flag_phis)
828*e4b17023SJohn Marino {
829*e4b17023SJohn Marino   unsigned i;
830*e4b17023SJohn Marino 
831*e4b17023SJohn Marino   for (i = 0; i < MIN (32, gimple_phi_num_args (flag_def)); i++)
832*e4b17023SJohn Marino     {
833*e4b17023SJohn Marino       tree flag_arg;
834*e4b17023SJohn Marino 
835*e4b17023SJohn Marino       if (!MASK_TEST_BIT (uninit_opnds, i))
836*e4b17023SJohn Marino         continue;
837*e4b17023SJohn Marino 
838*e4b17023SJohn Marino       flag_arg = gimple_phi_arg_def (flag_def, i);
839*e4b17023SJohn Marino       if (!is_gimple_constant (flag_arg))
840*e4b17023SJohn Marino         {
841*e4b17023SJohn Marino           gimple flag_arg_def, phi_arg_def;
842*e4b17023SJohn Marino           tree phi_arg;
843*e4b17023SJohn Marino           unsigned uninit_opnds_arg_phi;
844*e4b17023SJohn Marino 
845*e4b17023SJohn Marino           if (TREE_CODE (flag_arg) != SSA_NAME)
846*e4b17023SJohn Marino             return false;
847*e4b17023SJohn Marino           flag_arg_def = SSA_NAME_DEF_STMT (flag_arg);
848*e4b17023SJohn Marino           if (gimple_code (flag_arg_def) != GIMPLE_PHI)
849*e4b17023SJohn Marino             return false;
850*e4b17023SJohn Marino 
851*e4b17023SJohn Marino           phi_arg = gimple_phi_arg_def (phi, i);
852*e4b17023SJohn Marino           if (TREE_CODE (phi_arg) != SSA_NAME)
853*e4b17023SJohn Marino             return false;
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino           phi_arg_def = SSA_NAME_DEF_STMT (phi_arg);
856*e4b17023SJohn Marino           if (gimple_code (phi_arg_def) != GIMPLE_PHI)
857*e4b17023SJohn Marino             return false;
858*e4b17023SJohn Marino 
859*e4b17023SJohn Marino           if (gimple_bb (phi_arg_def) != gimple_bb (flag_arg_def))
860*e4b17023SJohn Marino             return false;
861*e4b17023SJohn Marino 
862*e4b17023SJohn Marino           if (!*visited_flag_phis)
863*e4b17023SJohn Marino             *visited_flag_phis = BITMAP_ALLOC (NULL);
864*e4b17023SJohn Marino 
865*e4b17023SJohn Marino           if (bitmap_bit_p (*visited_flag_phis,
866*e4b17023SJohn Marino                             SSA_NAME_VERSION (gimple_phi_result (flag_arg_def))))
867*e4b17023SJohn Marino             return false;
868*e4b17023SJohn Marino 
869*e4b17023SJohn Marino           bitmap_set_bit (*visited_flag_phis,
870*e4b17023SJohn Marino                           SSA_NAME_VERSION (gimple_phi_result (flag_arg_def)));
871*e4b17023SJohn Marino 
872*e4b17023SJohn Marino           /* Now recursively prune the uninitialized phi args.  */
873*e4b17023SJohn Marino           uninit_opnds_arg_phi = compute_uninit_opnds_pos (phi_arg_def);
874*e4b17023SJohn Marino           if (!prune_uninit_phi_opnds_in_unrealizable_paths (
875*e4b17023SJohn Marino                   phi_arg_def, uninit_opnds_arg_phi,
876*e4b17023SJohn Marino                   flag_arg_def, boundary_cst, cmp_code,
877*e4b17023SJohn Marino                   visited_phis, visited_flag_phis))
878*e4b17023SJohn Marino             return false;
879*e4b17023SJohn Marino 
880*e4b17023SJohn Marino           bitmap_clear_bit (*visited_flag_phis,
881*e4b17023SJohn Marino                             SSA_NAME_VERSION (gimple_phi_result (flag_arg_def)));
882*e4b17023SJohn Marino           continue;
883*e4b17023SJohn Marino         }
884*e4b17023SJohn Marino 
885*e4b17023SJohn Marino       /* Now check if the constant is in the guarded range.  */
886*e4b17023SJohn Marino       if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
887*e4b17023SJohn Marino         {
888*e4b17023SJohn Marino           tree opnd;
889*e4b17023SJohn Marino           gimple opnd_def;
890*e4b17023SJohn Marino 
891*e4b17023SJohn Marino           /* Now that we know that this undefined edge is not
892*e4b17023SJohn Marino              pruned. If the operand is defined by another phi,
893*e4b17023SJohn Marino              we can further prune the incoming edges of that
894*e4b17023SJohn Marino              phi by checking the predicates of this operands.  */
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino           opnd = gimple_phi_arg_def (phi, i);
897*e4b17023SJohn Marino           opnd_def = SSA_NAME_DEF_STMT (opnd);
898*e4b17023SJohn Marino           if (gimple_code (opnd_def) == GIMPLE_PHI)
899*e4b17023SJohn Marino             {
900*e4b17023SJohn Marino               edge opnd_edge;
901*e4b17023SJohn Marino               unsigned uninit_opnds2
902*e4b17023SJohn Marino                   = compute_uninit_opnds_pos (opnd_def);
903*e4b17023SJohn Marino               gcc_assert (!MASK_EMPTY (uninit_opnds2));
904*e4b17023SJohn Marino               opnd_edge = gimple_phi_arg_edge (phi, i);
905*e4b17023SJohn Marino               if (!is_use_properly_guarded (phi,
906*e4b17023SJohn Marino                                             opnd_edge->src,
907*e4b17023SJohn Marino                                             opnd_def,
908*e4b17023SJohn Marino                                             uninit_opnds2,
909*e4b17023SJohn Marino                                             visited_phis))
910*e4b17023SJohn Marino                   return false;
911*e4b17023SJohn Marino             }
912*e4b17023SJohn Marino           else
913*e4b17023SJohn Marino             return false;
914*e4b17023SJohn Marino         }
915*e4b17023SJohn Marino     }
916*e4b17023SJohn Marino 
917*e4b17023SJohn Marino   return true;
918*e4b17023SJohn Marino }
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino /* A helper function that determines if the predicate set
921*e4b17023SJohn Marino    of the use is not overlapping with that of the uninit paths.
922*e4b17023SJohn Marino    The most common senario of guarded use is in Example 1:
923*e4b17023SJohn Marino      Example 1:
924*e4b17023SJohn Marino            if (some_cond)
925*e4b17023SJohn Marino            {
926*e4b17023SJohn Marino               x = ...;
927*e4b17023SJohn Marino               flag = true;
928*e4b17023SJohn Marino            }
929*e4b17023SJohn Marino 
930*e4b17023SJohn Marino             ... some code ...
931*e4b17023SJohn Marino 
932*e4b17023SJohn Marino            if (flag)
933*e4b17023SJohn Marino               use (x);
934*e4b17023SJohn Marino 
935*e4b17023SJohn Marino      The real world examples are usually more complicated, but similar
936*e4b17023SJohn Marino      and usually result from inlining:
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino          bool init_func (int * x)
939*e4b17023SJohn Marino          {
940*e4b17023SJohn Marino              if (some_cond)
941*e4b17023SJohn Marino                 return false;
942*e4b17023SJohn Marino              *x  =  ..
943*e4b17023SJohn Marino              return true;
944*e4b17023SJohn Marino          }
945*e4b17023SJohn Marino 
946*e4b17023SJohn Marino          void foo(..)
947*e4b17023SJohn Marino          {
948*e4b17023SJohn Marino              int x;
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino              if (!init_func(&x))
951*e4b17023SJohn Marino                 return;
952*e4b17023SJohn Marino 
953*e4b17023SJohn Marino              .. some_code ...
954*e4b17023SJohn Marino              use (x);
955*e4b17023SJohn Marino          }
956*e4b17023SJohn Marino 
957*e4b17023SJohn Marino      Another possible use scenario is in the following trivial example:
958*e4b17023SJohn Marino 
959*e4b17023SJohn Marino      Example 2:
960*e4b17023SJohn Marino           if (n > 0)
961*e4b17023SJohn Marino              x = 1;
962*e4b17023SJohn Marino           ...
963*e4b17023SJohn Marino           if (n > 0)
964*e4b17023SJohn Marino             {
965*e4b17023SJohn Marino               if (m < 2)
966*e4b17023SJohn Marino                  .. = x;
967*e4b17023SJohn Marino             }
968*e4b17023SJohn Marino 
969*e4b17023SJohn Marino      Predicate analysis needs to compute the composite predicate:
970*e4b17023SJohn Marino 
971*e4b17023SJohn Marino        1) 'x' use predicate: (n > 0) .AND. (m < 2)
972*e4b17023SJohn Marino        2) 'x' default value  (non-def) predicate: .NOT. (n > 0)
973*e4b17023SJohn Marino        (the predicate chain for phi operand defs can be computed
974*e4b17023SJohn Marino        starting from a bb that is control equivalent to the phi's
975*e4b17023SJohn Marino        bb and is dominating the operand def.)
976*e4b17023SJohn Marino 
977*e4b17023SJohn Marino        and check overlapping:
978*e4b17023SJohn Marino           (n > 0) .AND. (m < 2) .AND. (.NOT. (n > 0))
979*e4b17023SJohn Marino         <==> false
980*e4b17023SJohn Marino 
981*e4b17023SJohn Marino      This implementation provides framework that can handle
982*e4b17023SJohn Marino      scenarios. (Note that many simple cases are handled properly
983*e4b17023SJohn Marino      without the predicate analysis -- this is due to jump threading
984*e4b17023SJohn Marino      transformation which eliminates the merge point thus makes
985*e4b17023SJohn Marino      path sensitive analysis unnecessary.)
986*e4b17023SJohn Marino 
987*e4b17023SJohn Marino      NUM_PREDS is the number is the number predicate chains, PREDS is
988*e4b17023SJohn Marino      the array of chains, PHI is the phi node whose incoming (undefined)
989*e4b17023SJohn Marino      paths need to be pruned, and UNINIT_OPNDS is the bitmap holding
990*e4b17023SJohn Marino      uninit operand positions. VISITED_PHIS is the pointer set of phi
991*e4b17023SJohn Marino      stmts being checked.  */
992*e4b17023SJohn Marino 
993*e4b17023SJohn Marino 
994*e4b17023SJohn Marino static bool
use_pred_not_overlap_with_undef_path_pred(size_t num_preds,VEC (use_pred_info_t,heap)** preds,gimple phi,unsigned uninit_opnds,struct pointer_set_t * visited_phis)995*e4b17023SJohn Marino use_pred_not_overlap_with_undef_path_pred (
996*e4b17023SJohn Marino     size_t num_preds,
997*e4b17023SJohn Marino     VEC(use_pred_info_t, heap) **preds,
998*e4b17023SJohn Marino     gimple phi, unsigned uninit_opnds,
999*e4b17023SJohn Marino     struct pointer_set_t *visited_phis)
1000*e4b17023SJohn Marino {
1001*e4b17023SJohn Marino   unsigned int i, n;
1002*e4b17023SJohn Marino   gimple flag_def = 0;
1003*e4b17023SJohn Marino   tree  boundary_cst = 0;
1004*e4b17023SJohn Marino   enum tree_code cmp_code;
1005*e4b17023SJohn Marino   bool swap_cond = false;
1006*e4b17023SJohn Marino   bool invert = false;
1007*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) *the_pred_chain;
1008*e4b17023SJohn Marino   bitmap visited_flag_phis = NULL;
1009*e4b17023SJohn Marino   bool all_pruned = false;
1010*e4b17023SJohn Marino 
1011*e4b17023SJohn Marino   gcc_assert (num_preds > 0);
1012*e4b17023SJohn Marino   /* Find within the common prefix of multiple predicate chains
1013*e4b17023SJohn Marino      a predicate that is a comparison of a flag variable against
1014*e4b17023SJohn Marino      a constant.  */
1015*e4b17023SJohn Marino   the_pred_chain = preds[0];
1016*e4b17023SJohn Marino   n = VEC_length (use_pred_info_t, the_pred_chain);
1017*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1018*e4b17023SJohn Marino     {
1019*e4b17023SJohn Marino       gimple cond;
1020*e4b17023SJohn Marino       tree cond_lhs, cond_rhs, flag = 0;
1021*e4b17023SJohn Marino 
1022*e4b17023SJohn Marino       use_pred_info_t the_pred
1023*e4b17023SJohn Marino           = VEC_index (use_pred_info_t, the_pred_chain, i);
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino       cond = the_pred->cond;
1026*e4b17023SJohn Marino       invert = the_pred->invert;
1027*e4b17023SJohn Marino       cond_lhs = gimple_cond_lhs (cond);
1028*e4b17023SJohn Marino       cond_rhs = gimple_cond_rhs (cond);
1029*e4b17023SJohn Marino       cmp_code = gimple_cond_code (cond);
1030*e4b17023SJohn Marino 
1031*e4b17023SJohn Marino       if (cond_lhs != NULL_TREE && TREE_CODE (cond_lhs) == SSA_NAME
1032*e4b17023SJohn Marino           && cond_rhs != NULL_TREE && is_gimple_constant (cond_rhs))
1033*e4b17023SJohn Marino         {
1034*e4b17023SJohn Marino           boundary_cst = cond_rhs;
1035*e4b17023SJohn Marino           flag = cond_lhs;
1036*e4b17023SJohn Marino         }
1037*e4b17023SJohn Marino       else if (cond_rhs != NULL_TREE && TREE_CODE (cond_rhs) == SSA_NAME
1038*e4b17023SJohn Marino                && cond_lhs != NULL_TREE && is_gimple_constant (cond_lhs))
1039*e4b17023SJohn Marino         {
1040*e4b17023SJohn Marino           boundary_cst = cond_lhs;
1041*e4b17023SJohn Marino           flag = cond_rhs;
1042*e4b17023SJohn Marino           swap_cond = true;
1043*e4b17023SJohn Marino         }
1044*e4b17023SJohn Marino 
1045*e4b17023SJohn Marino       if (!flag)
1046*e4b17023SJohn Marino         continue;
1047*e4b17023SJohn Marino 
1048*e4b17023SJohn Marino       flag_def = SSA_NAME_DEF_STMT (flag);
1049*e4b17023SJohn Marino 
1050*e4b17023SJohn Marino       if (!flag_def)
1051*e4b17023SJohn Marino         continue;
1052*e4b17023SJohn Marino 
1053*e4b17023SJohn Marino       if ((gimple_code (flag_def) == GIMPLE_PHI)
1054*e4b17023SJohn Marino           && (gimple_bb (flag_def) == gimple_bb (phi))
1055*e4b17023SJohn Marino           && find_matching_predicate_in_rest_chains (
1056*e4b17023SJohn Marino               the_pred, preds, num_preds))
1057*e4b17023SJohn Marino         break;
1058*e4b17023SJohn Marino 
1059*e4b17023SJohn Marino       flag_def = 0;
1060*e4b17023SJohn Marino     }
1061*e4b17023SJohn Marino 
1062*e4b17023SJohn Marino   if (!flag_def)
1063*e4b17023SJohn Marino     return false;
1064*e4b17023SJohn Marino 
1065*e4b17023SJohn Marino   /* Now check all the uninit incoming edge has a constant flag value
1066*e4b17023SJohn Marino      that is in conflict with the use guard/predicate.  */
1067*e4b17023SJohn Marino   cmp_code = get_cmp_code (cmp_code, swap_cond, invert);
1068*e4b17023SJohn Marino 
1069*e4b17023SJohn Marino   if (cmp_code == ERROR_MARK)
1070*e4b17023SJohn Marino     return false;
1071*e4b17023SJohn Marino 
1072*e4b17023SJohn Marino   all_pruned = prune_uninit_phi_opnds_in_unrealizable_paths (phi,
1073*e4b17023SJohn Marino                                                              uninit_opnds,
1074*e4b17023SJohn Marino                                                              flag_def,
1075*e4b17023SJohn Marino                                                              boundary_cst,
1076*e4b17023SJohn Marino                                                              cmp_code,
1077*e4b17023SJohn Marino                                                              visited_phis,
1078*e4b17023SJohn Marino                                                              &visited_flag_phis);
1079*e4b17023SJohn Marino 
1080*e4b17023SJohn Marino   if (visited_flag_phis)
1081*e4b17023SJohn Marino     BITMAP_FREE (visited_flag_phis);
1082*e4b17023SJohn Marino 
1083*e4b17023SJohn Marino   return all_pruned;
1084*e4b17023SJohn Marino }
1085*e4b17023SJohn Marino 
1086*e4b17023SJohn Marino /* Returns true if TC is AND or OR */
1087*e4b17023SJohn Marino 
1088*e4b17023SJohn Marino static inline bool
is_and_or_or(enum tree_code tc,tree typ)1089*e4b17023SJohn Marino is_and_or_or (enum tree_code tc, tree typ)
1090*e4b17023SJohn Marino {
1091*e4b17023SJohn Marino   return (tc == BIT_IOR_EXPR
1092*e4b17023SJohn Marino           || (tc == BIT_AND_EXPR
1093*e4b17023SJohn Marino               && (typ == 0 || TREE_CODE (typ) == BOOLEAN_TYPE)));
1094*e4b17023SJohn Marino }
1095*e4b17023SJohn Marino 
1096*e4b17023SJohn Marino typedef struct norm_cond
1097*e4b17023SJohn Marino {
1098*e4b17023SJohn Marino   VEC(gimple, heap) *conds;
1099*e4b17023SJohn Marino   enum tree_code cond_code;
1100*e4b17023SJohn Marino   bool invert;
1101*e4b17023SJohn Marino } *norm_cond_t;
1102*e4b17023SJohn Marino 
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino /* Normalizes gimple condition COND. The normalization follows
1105*e4b17023SJohn Marino    UD chains to form larger condition expression trees. NORM_COND
1106*e4b17023SJohn Marino    holds the normalized result. COND_CODE is the logical opcode
1107*e4b17023SJohn Marino    (AND or OR) of the normalized tree.  */
1108*e4b17023SJohn Marino 
1109*e4b17023SJohn Marino static void
normalize_cond_1(gimple cond,norm_cond_t norm_cond,enum tree_code cond_code)1110*e4b17023SJohn Marino normalize_cond_1 (gimple cond,
1111*e4b17023SJohn Marino                   norm_cond_t norm_cond,
1112*e4b17023SJohn Marino                   enum tree_code cond_code)
1113*e4b17023SJohn Marino {
1114*e4b17023SJohn Marino   enum gimple_code gc;
1115*e4b17023SJohn Marino   enum tree_code cur_cond_code;
1116*e4b17023SJohn Marino   tree rhs1, rhs2;
1117*e4b17023SJohn Marino 
1118*e4b17023SJohn Marino   gc = gimple_code (cond);
1119*e4b17023SJohn Marino   if (gc != GIMPLE_ASSIGN)
1120*e4b17023SJohn Marino     {
1121*e4b17023SJohn Marino       VEC_safe_push (gimple, heap, norm_cond->conds, cond);
1122*e4b17023SJohn Marino       return;
1123*e4b17023SJohn Marino     }
1124*e4b17023SJohn Marino 
1125*e4b17023SJohn Marino   cur_cond_code = gimple_assign_rhs_code (cond);
1126*e4b17023SJohn Marino   rhs1 = gimple_assign_rhs1 (cond);
1127*e4b17023SJohn Marino   rhs2 = gimple_assign_rhs2 (cond);
1128*e4b17023SJohn Marino   if (cur_cond_code == NE_EXPR)
1129*e4b17023SJohn Marino     {
1130*e4b17023SJohn Marino       if (integer_zerop (rhs2)
1131*e4b17023SJohn Marino           && (TREE_CODE (rhs1) == SSA_NAME))
1132*e4b17023SJohn Marino         normalize_cond_1 (
1133*e4b17023SJohn Marino             SSA_NAME_DEF_STMT (rhs1),
1134*e4b17023SJohn Marino             norm_cond, cond_code);
1135*e4b17023SJohn Marino       else if (integer_zerop (rhs1)
1136*e4b17023SJohn Marino                && (TREE_CODE (rhs2) == SSA_NAME))
1137*e4b17023SJohn Marino         normalize_cond_1 (
1138*e4b17023SJohn Marino             SSA_NAME_DEF_STMT (rhs2),
1139*e4b17023SJohn Marino             norm_cond, cond_code);
1140*e4b17023SJohn Marino       else
1141*e4b17023SJohn Marino         VEC_safe_push (gimple, heap, norm_cond->conds, cond);
1142*e4b17023SJohn Marino 
1143*e4b17023SJohn Marino       return;
1144*e4b17023SJohn Marino     }
1145*e4b17023SJohn Marino 
1146*e4b17023SJohn Marino   if (is_and_or_or (cur_cond_code, TREE_TYPE (rhs1))
1147*e4b17023SJohn Marino       && (cond_code == cur_cond_code || cond_code == ERROR_MARK)
1148*e4b17023SJohn Marino       && (TREE_CODE (rhs1) == SSA_NAME && TREE_CODE (rhs2) == SSA_NAME))
1149*e4b17023SJohn Marino     {
1150*e4b17023SJohn Marino       normalize_cond_1 (SSA_NAME_DEF_STMT (rhs1),
1151*e4b17023SJohn Marino                         norm_cond, cur_cond_code);
1152*e4b17023SJohn Marino       normalize_cond_1 (SSA_NAME_DEF_STMT (rhs2),
1153*e4b17023SJohn Marino                         norm_cond, cur_cond_code);
1154*e4b17023SJohn Marino       norm_cond->cond_code = cur_cond_code;
1155*e4b17023SJohn Marino     }
1156*e4b17023SJohn Marino   else
1157*e4b17023SJohn Marino     VEC_safe_push (gimple, heap, norm_cond->conds, cond);
1158*e4b17023SJohn Marino }
1159*e4b17023SJohn Marino 
1160*e4b17023SJohn Marino /* See normalize_cond_1 for details. INVERT is a flag to indicate
1161*e4b17023SJohn Marino    if COND needs to be inverted or not.  */
1162*e4b17023SJohn Marino 
1163*e4b17023SJohn Marino static void
normalize_cond(gimple cond,norm_cond_t norm_cond,bool invert)1164*e4b17023SJohn Marino normalize_cond (gimple cond, norm_cond_t norm_cond, bool invert)
1165*e4b17023SJohn Marino {
1166*e4b17023SJohn Marino   enum tree_code cond_code;
1167*e4b17023SJohn Marino 
1168*e4b17023SJohn Marino   norm_cond->cond_code = ERROR_MARK;
1169*e4b17023SJohn Marino   norm_cond->invert = false;
1170*e4b17023SJohn Marino   norm_cond->conds = NULL;
1171*e4b17023SJohn Marino   gcc_assert (gimple_code (cond) == GIMPLE_COND);
1172*e4b17023SJohn Marino   cond_code = gimple_cond_code (cond);
1173*e4b17023SJohn Marino   if (invert)
1174*e4b17023SJohn Marino     cond_code = invert_tree_comparison (cond_code, false);
1175*e4b17023SJohn Marino 
1176*e4b17023SJohn Marino   if (cond_code == NE_EXPR)
1177*e4b17023SJohn Marino     {
1178*e4b17023SJohn Marino       if (integer_zerop (gimple_cond_rhs (cond))
1179*e4b17023SJohn Marino           && (TREE_CODE (gimple_cond_lhs (cond)) == SSA_NAME))
1180*e4b17023SJohn Marino         normalize_cond_1 (
1181*e4b17023SJohn Marino             SSA_NAME_DEF_STMT (gimple_cond_lhs (cond)),
1182*e4b17023SJohn Marino             norm_cond, ERROR_MARK);
1183*e4b17023SJohn Marino       else if (integer_zerop (gimple_cond_lhs (cond))
1184*e4b17023SJohn Marino                && (TREE_CODE (gimple_cond_rhs (cond)) == SSA_NAME))
1185*e4b17023SJohn Marino         normalize_cond_1 (
1186*e4b17023SJohn Marino             SSA_NAME_DEF_STMT (gimple_cond_rhs (cond)),
1187*e4b17023SJohn Marino             norm_cond, ERROR_MARK);
1188*e4b17023SJohn Marino       else
1189*e4b17023SJohn Marino         {
1190*e4b17023SJohn Marino           VEC_safe_push (gimple, heap, norm_cond->conds, cond);
1191*e4b17023SJohn Marino           norm_cond->invert = invert;
1192*e4b17023SJohn Marino         }
1193*e4b17023SJohn Marino     }
1194*e4b17023SJohn Marino   else
1195*e4b17023SJohn Marino     {
1196*e4b17023SJohn Marino       VEC_safe_push (gimple, heap, norm_cond->conds, cond);
1197*e4b17023SJohn Marino       norm_cond->invert = invert;
1198*e4b17023SJohn Marino     }
1199*e4b17023SJohn Marino 
1200*e4b17023SJohn Marino   gcc_assert (VEC_length (gimple, norm_cond->conds) == 1
1201*e4b17023SJohn Marino               || is_and_or_or (norm_cond->cond_code, NULL));
1202*e4b17023SJohn Marino }
1203*e4b17023SJohn Marino 
1204*e4b17023SJohn Marino /* Returns true if the domain for condition COND1 is a subset of
1205*e4b17023SJohn Marino    COND2. REVERSE is a flag. when it is true the function checks
1206*e4b17023SJohn Marino    if COND1 is a superset of COND2. INVERT1 and INVERT2 are flags
1207*e4b17023SJohn Marino    to indicate if COND1 and COND2 need to be inverted or not.  */
1208*e4b17023SJohn Marino 
1209*e4b17023SJohn Marino static bool
is_gcond_subset_of(gimple cond1,bool invert1,gimple cond2,bool invert2,bool reverse)1210*e4b17023SJohn Marino is_gcond_subset_of (gimple cond1, bool invert1,
1211*e4b17023SJohn Marino                     gimple cond2, bool invert2,
1212*e4b17023SJohn Marino                     bool reverse)
1213*e4b17023SJohn Marino {
1214*e4b17023SJohn Marino   enum gimple_code gc1, gc2;
1215*e4b17023SJohn Marino   enum tree_code cond1_code, cond2_code;
1216*e4b17023SJohn Marino   gimple tmp;
1217*e4b17023SJohn Marino   tree cond1_lhs, cond1_rhs, cond2_lhs, cond2_rhs;
1218*e4b17023SJohn Marino 
1219*e4b17023SJohn Marino   /* Take the short cut.  */
1220*e4b17023SJohn Marino   if (cond1 == cond2)
1221*e4b17023SJohn Marino     return true;
1222*e4b17023SJohn Marino 
1223*e4b17023SJohn Marino   if (reverse)
1224*e4b17023SJohn Marino     {
1225*e4b17023SJohn Marino       tmp = cond1;
1226*e4b17023SJohn Marino       cond1 = cond2;
1227*e4b17023SJohn Marino       cond2 = tmp;
1228*e4b17023SJohn Marino     }
1229*e4b17023SJohn Marino 
1230*e4b17023SJohn Marino   gc1 = gimple_code (cond1);
1231*e4b17023SJohn Marino   gc2 = gimple_code (cond2);
1232*e4b17023SJohn Marino 
1233*e4b17023SJohn Marino   if ((gc1 != GIMPLE_ASSIGN && gc1 != GIMPLE_COND)
1234*e4b17023SJohn Marino       || (gc2 != GIMPLE_ASSIGN && gc2 != GIMPLE_COND))
1235*e4b17023SJohn Marino     return cond1 == cond2;
1236*e4b17023SJohn Marino 
1237*e4b17023SJohn Marino   cond1_code = ((gc1 == GIMPLE_ASSIGN)
1238*e4b17023SJohn Marino                 ? gimple_assign_rhs_code (cond1)
1239*e4b17023SJohn Marino                 : gimple_cond_code (cond1));
1240*e4b17023SJohn Marino 
1241*e4b17023SJohn Marino   cond2_code = ((gc2 == GIMPLE_ASSIGN)
1242*e4b17023SJohn Marino                 ? gimple_assign_rhs_code (cond2)
1243*e4b17023SJohn Marino                 : gimple_cond_code (cond2));
1244*e4b17023SJohn Marino 
1245*e4b17023SJohn Marino   if (TREE_CODE_CLASS (cond1_code) != tcc_comparison
1246*e4b17023SJohn Marino       || TREE_CODE_CLASS (cond2_code) != tcc_comparison)
1247*e4b17023SJohn Marino     return false;
1248*e4b17023SJohn Marino 
1249*e4b17023SJohn Marino   if (invert1)
1250*e4b17023SJohn Marino     cond1_code = invert_tree_comparison (cond1_code, false);
1251*e4b17023SJohn Marino   if (invert2)
1252*e4b17023SJohn Marino     cond2_code = invert_tree_comparison (cond2_code, false);
1253*e4b17023SJohn Marino 
1254*e4b17023SJohn Marino   cond1_lhs = ((gc1 == GIMPLE_ASSIGN)
1255*e4b17023SJohn Marino                ? gimple_assign_rhs1 (cond1)
1256*e4b17023SJohn Marino                : gimple_cond_lhs (cond1));
1257*e4b17023SJohn Marino   cond1_rhs = ((gc1 == GIMPLE_ASSIGN)
1258*e4b17023SJohn Marino                ? gimple_assign_rhs2 (cond1)
1259*e4b17023SJohn Marino                : gimple_cond_rhs (cond1));
1260*e4b17023SJohn Marino   cond2_lhs = ((gc2 == GIMPLE_ASSIGN)
1261*e4b17023SJohn Marino                ? gimple_assign_rhs1 (cond2)
1262*e4b17023SJohn Marino                : gimple_cond_lhs (cond2));
1263*e4b17023SJohn Marino   cond2_rhs = ((gc2 == GIMPLE_ASSIGN)
1264*e4b17023SJohn Marino                ? gimple_assign_rhs2 (cond2)
1265*e4b17023SJohn Marino                : gimple_cond_rhs (cond2));
1266*e4b17023SJohn Marino 
1267*e4b17023SJohn Marino   /* Assuming const operands have been swapped to the
1268*e4b17023SJohn Marino      rhs at this point of the analysis.  */
1269*e4b17023SJohn Marino 
1270*e4b17023SJohn Marino   if (cond1_lhs != cond2_lhs)
1271*e4b17023SJohn Marino     return false;
1272*e4b17023SJohn Marino 
1273*e4b17023SJohn Marino   if (!is_gimple_constant (cond1_rhs)
1274*e4b17023SJohn Marino       || TREE_CODE (cond1_rhs) != INTEGER_CST)
1275*e4b17023SJohn Marino     return (cond1_rhs == cond2_rhs);
1276*e4b17023SJohn Marino 
1277*e4b17023SJohn Marino   if (!is_gimple_constant (cond2_rhs)
1278*e4b17023SJohn Marino       || TREE_CODE (cond2_rhs) != INTEGER_CST)
1279*e4b17023SJohn Marino     return (cond1_rhs == cond2_rhs);
1280*e4b17023SJohn Marino 
1281*e4b17023SJohn Marino   if (cond1_code == EQ_EXPR)
1282*e4b17023SJohn Marino     return is_value_included_in (cond1_rhs,
1283*e4b17023SJohn Marino                                  cond2_rhs, cond2_code);
1284*e4b17023SJohn Marino   if (cond1_code == NE_EXPR || cond2_code == EQ_EXPR)
1285*e4b17023SJohn Marino     return ((cond2_code == cond1_code)
1286*e4b17023SJohn Marino             && tree_int_cst_equal (cond1_rhs, cond2_rhs));
1287*e4b17023SJohn Marino 
1288*e4b17023SJohn Marino   if (((cond1_code == GE_EXPR || cond1_code == GT_EXPR)
1289*e4b17023SJohn Marino        && (cond2_code == LE_EXPR || cond2_code == LT_EXPR))
1290*e4b17023SJohn Marino       || ((cond1_code == LE_EXPR || cond1_code == LT_EXPR)
1291*e4b17023SJohn Marino           && (cond2_code == GE_EXPR || cond2_code == GT_EXPR)))
1292*e4b17023SJohn Marino     return false;
1293*e4b17023SJohn Marino 
1294*e4b17023SJohn Marino   if (cond1_code != GE_EXPR && cond1_code != GT_EXPR
1295*e4b17023SJohn Marino       && cond1_code != LE_EXPR && cond1_code != LT_EXPR)
1296*e4b17023SJohn Marino     return false;
1297*e4b17023SJohn Marino 
1298*e4b17023SJohn Marino   if (cond1_code == GT_EXPR)
1299*e4b17023SJohn Marino     {
1300*e4b17023SJohn Marino       cond1_code = GE_EXPR;
1301*e4b17023SJohn Marino       cond1_rhs = fold_binary (PLUS_EXPR, TREE_TYPE (cond1_rhs),
1302*e4b17023SJohn Marino                                cond1_rhs,
1303*e4b17023SJohn Marino                                fold_convert (TREE_TYPE (cond1_rhs),
1304*e4b17023SJohn Marino                                              integer_one_node));
1305*e4b17023SJohn Marino     }
1306*e4b17023SJohn Marino   else if (cond1_code == LT_EXPR)
1307*e4b17023SJohn Marino     {
1308*e4b17023SJohn Marino       cond1_code = LE_EXPR;
1309*e4b17023SJohn Marino       cond1_rhs = fold_binary (MINUS_EXPR, TREE_TYPE (cond1_rhs),
1310*e4b17023SJohn Marino                                cond1_rhs,
1311*e4b17023SJohn Marino                                fold_convert (TREE_TYPE (cond1_rhs),
1312*e4b17023SJohn Marino                                              integer_one_node));
1313*e4b17023SJohn Marino     }
1314*e4b17023SJohn Marino 
1315*e4b17023SJohn Marino   if (!cond1_rhs)
1316*e4b17023SJohn Marino     return false;
1317*e4b17023SJohn Marino 
1318*e4b17023SJohn Marino   gcc_assert (cond1_code == GE_EXPR || cond1_code == LE_EXPR);
1319*e4b17023SJohn Marino 
1320*e4b17023SJohn Marino   if (cond2_code == GE_EXPR || cond2_code == GT_EXPR ||
1321*e4b17023SJohn Marino       cond2_code == LE_EXPR || cond2_code == LT_EXPR)
1322*e4b17023SJohn Marino     return is_value_included_in (cond1_rhs,
1323*e4b17023SJohn Marino                                  cond2_rhs, cond2_code);
1324*e4b17023SJohn Marino   else if (cond2_code == NE_EXPR)
1325*e4b17023SJohn Marino     return
1326*e4b17023SJohn Marino         (is_value_included_in (cond1_rhs,
1327*e4b17023SJohn Marino                                cond2_rhs, cond2_code)
1328*e4b17023SJohn Marino          && !is_value_included_in (cond2_rhs,
1329*e4b17023SJohn Marino                                    cond1_rhs, cond1_code));
1330*e4b17023SJohn Marino   return false;
1331*e4b17023SJohn Marino }
1332*e4b17023SJohn Marino 
1333*e4b17023SJohn Marino /* Returns true if the domain of the condition expression
1334*e4b17023SJohn Marino    in COND is a subset of any of the sub-conditions
1335*e4b17023SJohn Marino    of the normalized condtion NORM_COND.  INVERT is a flag
1336*e4b17023SJohn Marino    to indicate of the COND needs to be inverted.
1337*e4b17023SJohn Marino    REVERSE is a flag. When it is true, the check is reversed --
1338*e4b17023SJohn Marino    it returns true if COND is a superset of any of the subconditions
1339*e4b17023SJohn Marino    of NORM_COND.  */
1340*e4b17023SJohn Marino 
1341*e4b17023SJohn Marino static bool
is_subset_of_any(gimple cond,bool invert,norm_cond_t norm_cond,bool reverse)1342*e4b17023SJohn Marino is_subset_of_any (gimple cond, bool invert,
1343*e4b17023SJohn Marino                   norm_cond_t norm_cond, bool reverse)
1344*e4b17023SJohn Marino {
1345*e4b17023SJohn Marino   size_t i;
1346*e4b17023SJohn Marino   size_t len = VEC_length (gimple, norm_cond->conds);
1347*e4b17023SJohn Marino 
1348*e4b17023SJohn Marino   for (i = 0; i < len; i++)
1349*e4b17023SJohn Marino     {
1350*e4b17023SJohn Marino       if (is_gcond_subset_of (cond, invert,
1351*e4b17023SJohn Marino                               VEC_index (gimple, norm_cond->conds, i),
1352*e4b17023SJohn Marino                               false, reverse))
1353*e4b17023SJohn Marino         return true;
1354*e4b17023SJohn Marino     }
1355*e4b17023SJohn Marino   return false;
1356*e4b17023SJohn Marino }
1357*e4b17023SJohn Marino 
1358*e4b17023SJohn Marino /* NORM_COND1 and NORM_COND2 are normalized logical/BIT OR
1359*e4b17023SJohn Marino    expressions (formed by following UD chains not control
1360*e4b17023SJohn Marino    dependence chains). The function returns true of domain
1361*e4b17023SJohn Marino    of and expression NORM_COND1 is a subset of NORM_COND2's.
1362*e4b17023SJohn Marino    The implementation is conservative, and it returns false if
1363*e4b17023SJohn Marino    it the inclusion relationship may not hold.  */
1364*e4b17023SJohn Marino 
1365*e4b17023SJohn Marino static bool
is_or_set_subset_of(norm_cond_t norm_cond1,norm_cond_t norm_cond2)1366*e4b17023SJohn Marino is_or_set_subset_of (norm_cond_t norm_cond1,
1367*e4b17023SJohn Marino                      norm_cond_t norm_cond2)
1368*e4b17023SJohn Marino {
1369*e4b17023SJohn Marino   size_t i;
1370*e4b17023SJohn Marino   size_t len = VEC_length (gimple, norm_cond1->conds);
1371*e4b17023SJohn Marino 
1372*e4b17023SJohn Marino   for (i = 0; i < len; i++)
1373*e4b17023SJohn Marino     {
1374*e4b17023SJohn Marino       if (!is_subset_of_any (VEC_index (gimple, norm_cond1->conds, i),
1375*e4b17023SJohn Marino                              false, norm_cond2, false))
1376*e4b17023SJohn Marino         return false;
1377*e4b17023SJohn Marino     }
1378*e4b17023SJohn Marino   return true;
1379*e4b17023SJohn Marino }
1380*e4b17023SJohn Marino 
1381*e4b17023SJohn Marino /* NORM_COND1 and NORM_COND2 are normalized logical AND
1382*e4b17023SJohn Marino    expressions (formed by following UD chains not control
1383*e4b17023SJohn Marino    dependence chains). The function returns true of domain
1384*e4b17023SJohn Marino    of and expression NORM_COND1 is a subset of NORM_COND2's.  */
1385*e4b17023SJohn Marino 
1386*e4b17023SJohn Marino static bool
is_and_set_subset_of(norm_cond_t norm_cond1,norm_cond_t norm_cond2)1387*e4b17023SJohn Marino is_and_set_subset_of (norm_cond_t norm_cond1,
1388*e4b17023SJohn Marino                       norm_cond_t norm_cond2)
1389*e4b17023SJohn Marino {
1390*e4b17023SJohn Marino   size_t i;
1391*e4b17023SJohn Marino   size_t len = VEC_length (gimple, norm_cond2->conds);
1392*e4b17023SJohn Marino 
1393*e4b17023SJohn Marino   for (i = 0; i < len; i++)
1394*e4b17023SJohn Marino     {
1395*e4b17023SJohn Marino       if (!is_subset_of_any (VEC_index (gimple, norm_cond2->conds, i),
1396*e4b17023SJohn Marino                              false, norm_cond1, true))
1397*e4b17023SJohn Marino         return false;
1398*e4b17023SJohn Marino     }
1399*e4b17023SJohn Marino   return true;
1400*e4b17023SJohn Marino }
1401*e4b17023SJohn Marino 
1402*e4b17023SJohn Marino /* Returns true of the domain if NORM_COND1 is a subset
1403*e4b17023SJohn Marino    of that of NORM_COND2. Returns false if it can not be
1404*e4b17023SJohn Marino    proved to be so.  */
1405*e4b17023SJohn Marino 
1406*e4b17023SJohn Marino static bool
is_norm_cond_subset_of(norm_cond_t norm_cond1,norm_cond_t norm_cond2)1407*e4b17023SJohn Marino is_norm_cond_subset_of (norm_cond_t norm_cond1,
1408*e4b17023SJohn Marino                         norm_cond_t norm_cond2)
1409*e4b17023SJohn Marino {
1410*e4b17023SJohn Marino   size_t i;
1411*e4b17023SJohn Marino   enum tree_code code1, code2;
1412*e4b17023SJohn Marino 
1413*e4b17023SJohn Marino   code1 = norm_cond1->cond_code;
1414*e4b17023SJohn Marino   code2 = norm_cond2->cond_code;
1415*e4b17023SJohn Marino 
1416*e4b17023SJohn Marino   if (code1 == BIT_AND_EXPR)
1417*e4b17023SJohn Marino     {
1418*e4b17023SJohn Marino       /* Both conditions are AND expressions.  */
1419*e4b17023SJohn Marino       if (code2 == BIT_AND_EXPR)
1420*e4b17023SJohn Marino         return is_and_set_subset_of (norm_cond1, norm_cond2);
1421*e4b17023SJohn Marino       /* NORM_COND1 is an AND expression, and NORM_COND2 is an OR
1422*e4b17023SJohn Marino          expression. In this case, returns true if any subexpression
1423*e4b17023SJohn Marino          of NORM_COND1 is a subset of any subexpression of NORM_COND2.  */
1424*e4b17023SJohn Marino       else if (code2 == BIT_IOR_EXPR)
1425*e4b17023SJohn Marino         {
1426*e4b17023SJohn Marino           size_t len1;
1427*e4b17023SJohn Marino           len1 = VEC_length (gimple, norm_cond1->conds);
1428*e4b17023SJohn Marino           for (i = 0; i < len1; i++)
1429*e4b17023SJohn Marino             {
1430*e4b17023SJohn Marino               gimple cond1 = VEC_index (gimple, norm_cond1->conds, i);
1431*e4b17023SJohn Marino               if (is_subset_of_any (cond1, false, norm_cond2, false))
1432*e4b17023SJohn Marino                 return true;
1433*e4b17023SJohn Marino             }
1434*e4b17023SJohn Marino           return false;
1435*e4b17023SJohn Marino         }
1436*e4b17023SJohn Marino       else
1437*e4b17023SJohn Marino         {
1438*e4b17023SJohn Marino           gcc_assert (code2 == ERROR_MARK);
1439*e4b17023SJohn Marino           gcc_assert (VEC_length (gimple, norm_cond2->conds) == 1);
1440*e4b17023SJohn Marino           return is_subset_of_any (VEC_index (gimple, norm_cond2->conds, 0),
1441*e4b17023SJohn Marino                                    norm_cond2->invert, norm_cond1, true);
1442*e4b17023SJohn Marino         }
1443*e4b17023SJohn Marino     }
1444*e4b17023SJohn Marino   /* NORM_COND1 is an OR expression  */
1445*e4b17023SJohn Marino   else if (code1 == BIT_IOR_EXPR)
1446*e4b17023SJohn Marino     {
1447*e4b17023SJohn Marino       if (code2 != code1)
1448*e4b17023SJohn Marino         return false;
1449*e4b17023SJohn Marino 
1450*e4b17023SJohn Marino       return is_or_set_subset_of (norm_cond1, norm_cond2);
1451*e4b17023SJohn Marino     }
1452*e4b17023SJohn Marino   else
1453*e4b17023SJohn Marino     {
1454*e4b17023SJohn Marino       gcc_assert (code1 == ERROR_MARK);
1455*e4b17023SJohn Marino       gcc_assert (VEC_length (gimple, norm_cond1->conds) == 1);
1456*e4b17023SJohn Marino       /* Conservatively returns false if NORM_COND1 is non-decomposible
1457*e4b17023SJohn Marino          and NORM_COND2 is an AND expression.  */
1458*e4b17023SJohn Marino       if (code2 == BIT_AND_EXPR)
1459*e4b17023SJohn Marino         return false;
1460*e4b17023SJohn Marino 
1461*e4b17023SJohn Marino       if (code2 == BIT_IOR_EXPR)
1462*e4b17023SJohn Marino         return is_subset_of_any (VEC_index (gimple, norm_cond1->conds, 0),
1463*e4b17023SJohn Marino                                  norm_cond1->invert, norm_cond2, false);
1464*e4b17023SJohn Marino 
1465*e4b17023SJohn Marino       gcc_assert (code2 == ERROR_MARK);
1466*e4b17023SJohn Marino       gcc_assert (VEC_length (gimple, norm_cond2->conds) == 1);
1467*e4b17023SJohn Marino       return is_gcond_subset_of (VEC_index (gimple, norm_cond1->conds, 0),
1468*e4b17023SJohn Marino                                  norm_cond1->invert,
1469*e4b17023SJohn Marino                                  VEC_index (gimple, norm_cond2->conds, 0),
1470*e4b17023SJohn Marino                                  norm_cond2->invert, false);
1471*e4b17023SJohn Marino     }
1472*e4b17023SJohn Marino }
1473*e4b17023SJohn Marino 
1474*e4b17023SJohn Marino /* Returns true of the domain of single predicate expression
1475*e4b17023SJohn Marino    EXPR1 is a subset of that of EXPR2. Returns false if it
1476*e4b17023SJohn Marino    can not be proved.  */
1477*e4b17023SJohn Marino 
1478*e4b17023SJohn Marino static bool
is_pred_expr_subset_of(use_pred_info_t expr1,use_pred_info_t expr2)1479*e4b17023SJohn Marino is_pred_expr_subset_of (use_pred_info_t expr1,
1480*e4b17023SJohn Marino                         use_pred_info_t expr2)
1481*e4b17023SJohn Marino {
1482*e4b17023SJohn Marino   gimple cond1, cond2;
1483*e4b17023SJohn Marino   enum tree_code code1, code2;
1484*e4b17023SJohn Marino   struct norm_cond norm_cond1, norm_cond2;
1485*e4b17023SJohn Marino   bool is_subset = false;
1486*e4b17023SJohn Marino 
1487*e4b17023SJohn Marino   cond1 = expr1->cond;
1488*e4b17023SJohn Marino   cond2 = expr2->cond;
1489*e4b17023SJohn Marino   code1 = gimple_cond_code (cond1);
1490*e4b17023SJohn Marino   code2 = gimple_cond_code (cond2);
1491*e4b17023SJohn Marino 
1492*e4b17023SJohn Marino   if (expr1->invert)
1493*e4b17023SJohn Marino     code1 = invert_tree_comparison (code1, false);
1494*e4b17023SJohn Marino   if (expr2->invert)
1495*e4b17023SJohn Marino     code2 = invert_tree_comparison (code2, false);
1496*e4b17023SJohn Marino 
1497*e4b17023SJohn Marino   /* Fast path -- match exactly  */
1498*e4b17023SJohn Marino   if ((gimple_cond_lhs (cond1) == gimple_cond_lhs (cond2))
1499*e4b17023SJohn Marino       && (gimple_cond_rhs (cond1) == gimple_cond_rhs (cond2))
1500*e4b17023SJohn Marino       && (code1 == code2))
1501*e4b17023SJohn Marino     return true;
1502*e4b17023SJohn Marino 
1503*e4b17023SJohn Marino   /* Normalize conditions. To keep NE_EXPR, do not invert
1504*e4b17023SJohn Marino      with both need inversion.  */
1505*e4b17023SJohn Marino   normalize_cond (cond1, &norm_cond1, (expr1->invert));
1506*e4b17023SJohn Marino   normalize_cond (cond2, &norm_cond2, (expr2->invert));
1507*e4b17023SJohn Marino 
1508*e4b17023SJohn Marino   is_subset = is_norm_cond_subset_of (&norm_cond1, &norm_cond2);
1509*e4b17023SJohn Marino 
1510*e4b17023SJohn Marino   /* Free memory  */
1511*e4b17023SJohn Marino   VEC_free (gimple, heap, norm_cond1.conds);
1512*e4b17023SJohn Marino   VEC_free (gimple, heap, norm_cond2.conds);
1513*e4b17023SJohn Marino   return is_subset ;
1514*e4b17023SJohn Marino }
1515*e4b17023SJohn Marino 
1516*e4b17023SJohn Marino /* Returns true if the domain of PRED1 is a subset
1517*e4b17023SJohn Marino    of that of PRED2. Returns false if it can not be proved so.  */
1518*e4b17023SJohn Marino 
1519*e4b17023SJohn Marino static bool
is_pred_chain_subset_of(VEC (use_pred_info_t,heap)* pred1,VEC (use_pred_info_t,heap)* pred2)1520*e4b17023SJohn Marino is_pred_chain_subset_of (VEC(use_pred_info_t, heap) *pred1,
1521*e4b17023SJohn Marino                          VEC(use_pred_info_t, heap) *pred2)
1522*e4b17023SJohn Marino {
1523*e4b17023SJohn Marino   size_t np1, np2, i1, i2;
1524*e4b17023SJohn Marino 
1525*e4b17023SJohn Marino   np1 = VEC_length (use_pred_info_t, pred1);
1526*e4b17023SJohn Marino   np2 = VEC_length (use_pred_info_t, pred2);
1527*e4b17023SJohn Marino 
1528*e4b17023SJohn Marino   for (i2 = 0; i2 < np2; i2++)
1529*e4b17023SJohn Marino     {
1530*e4b17023SJohn Marino       bool found = false;
1531*e4b17023SJohn Marino       use_pred_info_t info2
1532*e4b17023SJohn Marino           = VEC_index (use_pred_info_t, pred2, i2);
1533*e4b17023SJohn Marino       for (i1 = 0; i1 < np1; i1++)
1534*e4b17023SJohn Marino         {
1535*e4b17023SJohn Marino           use_pred_info_t info1
1536*e4b17023SJohn Marino               = VEC_index (use_pred_info_t, pred1, i1);
1537*e4b17023SJohn Marino           if (is_pred_expr_subset_of (info1, info2))
1538*e4b17023SJohn Marino             {
1539*e4b17023SJohn Marino               found = true;
1540*e4b17023SJohn Marino               break;
1541*e4b17023SJohn Marino             }
1542*e4b17023SJohn Marino         }
1543*e4b17023SJohn Marino       if (!found)
1544*e4b17023SJohn Marino         return false;
1545*e4b17023SJohn Marino     }
1546*e4b17023SJohn Marino   return true;
1547*e4b17023SJohn Marino }
1548*e4b17023SJohn Marino 
1549*e4b17023SJohn Marino /* Returns true if the domain defined by
1550*e4b17023SJohn Marino    one pred chain ONE_PRED is a subset of the domain
1551*e4b17023SJohn Marino    of *PREDS. It returns false if ONE_PRED's domain is
1552*e4b17023SJohn Marino    not a subset of any of the sub-domains of PREDS (
1553*e4b17023SJohn Marino    corresponding to each individual chains in it), even
1554*e4b17023SJohn Marino    though it may be still be a subset of whole domain
1555*e4b17023SJohn Marino    of PREDS which is the union (ORed) of all its subdomains.
1556*e4b17023SJohn Marino    In other words, the result is conservative.  */
1557*e4b17023SJohn Marino 
1558*e4b17023SJohn Marino static bool
is_included_in(VEC (use_pred_info_t,heap)* one_pred,VEC (use_pred_info_t,heap)** preds,size_t n)1559*e4b17023SJohn Marino is_included_in (VEC(use_pred_info_t, heap) *one_pred,
1560*e4b17023SJohn Marino                 VEC(use_pred_info_t, heap) **preds,
1561*e4b17023SJohn Marino                 size_t n)
1562*e4b17023SJohn Marino {
1563*e4b17023SJohn Marino   size_t i;
1564*e4b17023SJohn Marino 
1565*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1566*e4b17023SJohn Marino     {
1567*e4b17023SJohn Marino       if (is_pred_chain_subset_of (one_pred, preds[i]))
1568*e4b17023SJohn Marino         return true;
1569*e4b17023SJohn Marino     }
1570*e4b17023SJohn Marino 
1571*e4b17023SJohn Marino   return false;
1572*e4b17023SJohn Marino }
1573*e4b17023SJohn Marino 
1574*e4b17023SJohn Marino /* compares two predicate sets PREDS1 and PREDS2 and returns
1575*e4b17023SJohn Marino    true if the domain defined by PREDS1 is a superset
1576*e4b17023SJohn Marino    of PREDS2's domain. N1 and N2 are array sizes of PREDS1 and
1577*e4b17023SJohn Marino    PREDS2 respectively. The implementation chooses not to build
1578*e4b17023SJohn Marino    generic trees (and relying on the folding capability of the
1579*e4b17023SJohn Marino    compiler), but instead performs brute force comparison of
1580*e4b17023SJohn Marino    individual predicate chains (won't be a compile time problem
1581*e4b17023SJohn Marino    as the chains are pretty short). When the function returns
1582*e4b17023SJohn Marino    false, it does not necessarily mean *PREDS1 is not a superset
1583*e4b17023SJohn Marino    of *PREDS2, but mean it may not be so since the analysis can
1584*e4b17023SJohn Marino    not prove it. In such cases, false warnings may still be
1585*e4b17023SJohn Marino    emitted.  */
1586*e4b17023SJohn Marino 
1587*e4b17023SJohn Marino static bool
is_superset_of(VEC (use_pred_info_t,heap)** preds1,size_t n1,VEC (use_pred_info_t,heap)** preds2,size_t n2)1588*e4b17023SJohn Marino is_superset_of (VEC(use_pred_info_t, heap) **preds1,
1589*e4b17023SJohn Marino                 size_t n1,
1590*e4b17023SJohn Marino                 VEC(use_pred_info_t, heap) **preds2,
1591*e4b17023SJohn Marino                 size_t n2)
1592*e4b17023SJohn Marino {
1593*e4b17023SJohn Marino   size_t i;
1594*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) *one_pred_chain;
1595*e4b17023SJohn Marino 
1596*e4b17023SJohn Marino   for (i = 0; i < n2; i++)
1597*e4b17023SJohn Marino     {
1598*e4b17023SJohn Marino       one_pred_chain = preds2[i];
1599*e4b17023SJohn Marino       if (!is_included_in (one_pred_chain, preds1, n1))
1600*e4b17023SJohn Marino         return false;
1601*e4b17023SJohn Marino     }
1602*e4b17023SJohn Marino 
1603*e4b17023SJohn Marino   return true;
1604*e4b17023SJohn Marino }
1605*e4b17023SJohn Marino 
1606*e4b17023SJohn Marino /* Comparison function used by qsort. It is used to
1607*e4b17023SJohn Marino    sort predicate chains to allow predicate
1608*e4b17023SJohn Marino    simplification.  */
1609*e4b17023SJohn Marino 
1610*e4b17023SJohn Marino static int
pred_chain_length_cmp(const void * p1,const void * p2)1611*e4b17023SJohn Marino pred_chain_length_cmp (const void *p1, const void *p2)
1612*e4b17023SJohn Marino {
1613*e4b17023SJohn Marino   use_pred_info_t i1, i2;
1614*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) * const *chain1
1615*e4b17023SJohn Marino       = (VEC(use_pred_info_t, heap) * const *)p1;
1616*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) * const *chain2
1617*e4b17023SJohn Marino       = (VEC(use_pred_info_t, heap) * const *)p2;
1618*e4b17023SJohn Marino 
1619*e4b17023SJohn Marino   if (VEC_length (use_pred_info_t, *chain1)
1620*e4b17023SJohn Marino       != VEC_length (use_pred_info_t, *chain2))
1621*e4b17023SJohn Marino     return (VEC_length (use_pred_info_t, *chain1)
1622*e4b17023SJohn Marino             - VEC_length (use_pred_info_t, *chain2));
1623*e4b17023SJohn Marino 
1624*e4b17023SJohn Marino   i1 = VEC_index (use_pred_info_t, *chain1, 0);
1625*e4b17023SJohn Marino   i2 = VEC_index (use_pred_info_t, *chain2, 0);
1626*e4b17023SJohn Marino 
1627*e4b17023SJohn Marino   /* Allow predicates with similar prefix come together.  */
1628*e4b17023SJohn Marino   if (!i1->invert && i2->invert)
1629*e4b17023SJohn Marino     return -1;
1630*e4b17023SJohn Marino   else if (i1->invert && !i2->invert)
1631*e4b17023SJohn Marino     return 1;
1632*e4b17023SJohn Marino 
1633*e4b17023SJohn Marino   return gimple_uid (i1->cond) - gimple_uid (i2->cond);
1634*e4b17023SJohn Marino }
1635*e4b17023SJohn Marino 
1636*e4b17023SJohn Marino /* x OR (!x AND y) is equivalent to x OR y.
1637*e4b17023SJohn Marino    This function normalizes x1 OR (!x1 AND x2) OR (!x1 AND !x2 AND x3)
1638*e4b17023SJohn Marino    into x1 OR x2 OR x3.  PREDS is the predicate chains, and N is
1639*e4b17023SJohn Marino    the number of chains. Returns true if normalization happens.  */
1640*e4b17023SJohn Marino 
1641*e4b17023SJohn Marino static bool
normalize_preds(VEC (use_pred_info_t,heap)** preds,size_t * n)1642*e4b17023SJohn Marino normalize_preds (VEC(use_pred_info_t, heap) **preds, size_t *n)
1643*e4b17023SJohn Marino {
1644*e4b17023SJohn Marino   size_t i, j, ll;
1645*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) *pred_chain;
1646*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) *x = 0;
1647*e4b17023SJohn Marino   use_pred_info_t xj = 0, nxj = 0;
1648*e4b17023SJohn Marino 
1649*e4b17023SJohn Marino   if (*n < 2)
1650*e4b17023SJohn Marino     return false;
1651*e4b17023SJohn Marino 
1652*e4b17023SJohn Marino   /* First sort the chains in ascending order of lengths.  */
1653*e4b17023SJohn Marino   qsort (preds, *n, sizeof (void *), pred_chain_length_cmp);
1654*e4b17023SJohn Marino   pred_chain = preds[0];
1655*e4b17023SJohn Marino   ll = VEC_length (use_pred_info_t, pred_chain);
1656*e4b17023SJohn Marino   if (ll != 1)
1657*e4b17023SJohn Marino    {
1658*e4b17023SJohn Marino      if (ll == 2)
1659*e4b17023SJohn Marino        {
1660*e4b17023SJohn Marino          use_pred_info_t xx, yy, xx2, nyy;
1661*e4b17023SJohn Marino          VEC(use_pred_info_t, heap) *pred_chain2 = preds[1];
1662*e4b17023SJohn Marino          if (VEC_length (use_pred_info_t, pred_chain2) != 2)
1663*e4b17023SJohn Marino            return false;
1664*e4b17023SJohn Marino 
1665*e4b17023SJohn Marino          /* See if simplification x AND y OR x AND !y is possible.  */
1666*e4b17023SJohn Marino          xx = VEC_index (use_pred_info_t, pred_chain, 0);
1667*e4b17023SJohn Marino          yy = VEC_index (use_pred_info_t, pred_chain, 1);
1668*e4b17023SJohn Marino          xx2 = VEC_index (use_pred_info_t, pred_chain2, 0);
1669*e4b17023SJohn Marino          nyy = VEC_index (use_pred_info_t, pred_chain2, 1);
1670*e4b17023SJohn Marino          if (gimple_cond_lhs (xx->cond) != gimple_cond_lhs (xx2->cond)
1671*e4b17023SJohn Marino              || gimple_cond_rhs (xx->cond) != gimple_cond_rhs (xx2->cond)
1672*e4b17023SJohn Marino              || gimple_cond_code (xx->cond) != gimple_cond_code (xx2->cond)
1673*e4b17023SJohn Marino              || (xx->invert != xx2->invert))
1674*e4b17023SJohn Marino            return false;
1675*e4b17023SJohn Marino          if (gimple_cond_lhs (yy->cond) != gimple_cond_lhs (nyy->cond)
1676*e4b17023SJohn Marino              || gimple_cond_rhs (yy->cond) != gimple_cond_rhs (nyy->cond)
1677*e4b17023SJohn Marino              || gimple_cond_code (yy->cond) != gimple_cond_code (nyy->cond)
1678*e4b17023SJohn Marino              || (yy->invert == nyy->invert))
1679*e4b17023SJohn Marino            return false;
1680*e4b17023SJohn Marino 
1681*e4b17023SJohn Marino          /* Now merge the first two chains.  */
1682*e4b17023SJohn Marino          free (yy);
1683*e4b17023SJohn Marino          free (nyy);
1684*e4b17023SJohn Marino          free (xx2);
1685*e4b17023SJohn Marino          VEC_free (use_pred_info_t, heap, pred_chain);
1686*e4b17023SJohn Marino          VEC_free (use_pred_info_t, heap, pred_chain2);
1687*e4b17023SJohn Marino          pred_chain = 0;
1688*e4b17023SJohn Marino          VEC_safe_push (use_pred_info_t, heap, pred_chain, xx);
1689*e4b17023SJohn Marino          preds[0] = pred_chain;
1690*e4b17023SJohn Marino          for (i = 1; i < *n - 1; i++)
1691*e4b17023SJohn Marino            preds[i] = preds[i + 1];
1692*e4b17023SJohn Marino 
1693*e4b17023SJohn Marino          preds[*n - 1] = 0;
1694*e4b17023SJohn Marino          *n = *n - 1;
1695*e4b17023SJohn Marino        }
1696*e4b17023SJohn Marino      else
1697*e4b17023SJohn Marino        return false;
1698*e4b17023SJohn Marino    }
1699*e4b17023SJohn Marino 
1700*e4b17023SJohn Marino   VEC_safe_push (use_pred_info_t, heap, x,
1701*e4b17023SJohn Marino                  VEC_index (use_pred_info_t, pred_chain, 0));
1702*e4b17023SJohn Marino 
1703*e4b17023SJohn Marino   /* The loop extracts x1, x2, x3, etc from chains
1704*e4b17023SJohn Marino      x1 OR (!x1 AND x2) OR (!x1 AND !x2 AND x3) OR ...  */
1705*e4b17023SJohn Marino   for (i = 1; i < *n; i++)
1706*e4b17023SJohn Marino     {
1707*e4b17023SJohn Marino       pred_chain = preds[i];
1708*e4b17023SJohn Marino       if (VEC_length (use_pred_info_t, pred_chain) != i + 1)
1709*e4b17023SJohn Marino         return false;
1710*e4b17023SJohn Marino 
1711*e4b17023SJohn Marino       for (j = 0; j < i; j++)
1712*e4b17023SJohn Marino         {
1713*e4b17023SJohn Marino           xj = VEC_index (use_pred_info_t, x, j);
1714*e4b17023SJohn Marino           nxj = VEC_index (use_pred_info_t, pred_chain, j);
1715*e4b17023SJohn Marino 
1716*e4b17023SJohn Marino           /* Check if nxj is !xj  */
1717*e4b17023SJohn Marino           if (gimple_cond_lhs (xj->cond) != gimple_cond_lhs (nxj->cond)
1718*e4b17023SJohn Marino               || gimple_cond_rhs (xj->cond) != gimple_cond_rhs (nxj->cond)
1719*e4b17023SJohn Marino               || gimple_cond_code (xj->cond) != gimple_cond_code (nxj->cond)
1720*e4b17023SJohn Marino               || (xj->invert == nxj->invert))
1721*e4b17023SJohn Marino             return false;
1722*e4b17023SJohn Marino         }
1723*e4b17023SJohn Marino 
1724*e4b17023SJohn Marino       VEC_safe_push (use_pred_info_t, heap, x,
1725*e4b17023SJohn Marino                      VEC_index (use_pred_info_t, pred_chain, i));
1726*e4b17023SJohn Marino     }
1727*e4b17023SJohn Marino 
1728*e4b17023SJohn Marino   /* Now normalize the pred chains using the extraced x1, x2, x3 etc.  */
1729*e4b17023SJohn Marino   for (j = 0; j < *n; j++)
1730*e4b17023SJohn Marino     {
1731*e4b17023SJohn Marino       use_pred_info_t t;
1732*e4b17023SJohn Marino       xj = VEC_index (use_pred_info_t, x, j);
1733*e4b17023SJohn Marino 
1734*e4b17023SJohn Marino       t = XNEW (struct use_pred_info);
1735*e4b17023SJohn Marino       *t = *xj;
1736*e4b17023SJohn Marino 
1737*e4b17023SJohn Marino       VEC_replace (use_pred_info_t, x, j, t);
1738*e4b17023SJohn Marino     }
1739*e4b17023SJohn Marino 
1740*e4b17023SJohn Marino   for (i = 0; i < *n; i++)
1741*e4b17023SJohn Marino     {
1742*e4b17023SJohn Marino       pred_chain = preds[i];
1743*e4b17023SJohn Marino       for (j = 0; j < VEC_length (use_pred_info_t, pred_chain); j++)
1744*e4b17023SJohn Marino         free (VEC_index (use_pred_info_t, pred_chain, j));
1745*e4b17023SJohn Marino       VEC_free (use_pred_info_t, heap, pred_chain);
1746*e4b17023SJohn Marino       pred_chain = 0;
1747*e4b17023SJohn Marino       /* A new chain.  */
1748*e4b17023SJohn Marino       VEC_safe_push (use_pred_info_t, heap, pred_chain,
1749*e4b17023SJohn Marino                      VEC_index (use_pred_info_t, x, i));
1750*e4b17023SJohn Marino       preds[i] = pred_chain;
1751*e4b17023SJohn Marino     }
1752*e4b17023SJohn Marino   return true;
1753*e4b17023SJohn Marino }
1754*e4b17023SJohn Marino 
1755*e4b17023SJohn Marino 
1756*e4b17023SJohn Marino 
1757*e4b17023SJohn Marino /* Computes the predicates that guard the use and checks
1758*e4b17023SJohn Marino    if the incoming paths that have empty (or possibly
1759*e4b17023SJohn Marino    empty) defintion can be pruned/filtered. The function returns
1760*e4b17023SJohn Marino    true if it can be determined that the use of PHI's def in
1761*e4b17023SJohn Marino    USE_STMT is guarded with a predicate set not overlapping with
1762*e4b17023SJohn Marino    predicate sets of all runtime paths that do not have a definition.
1763*e4b17023SJohn Marino    Returns false if it is not or it can not be determined. USE_BB is
1764*e4b17023SJohn Marino    the bb of the use (for phi operand use, the bb is not the bb of
1765*e4b17023SJohn Marino    the phi stmt, but the src bb of the operand edge). UNINIT_OPNDS
1766*e4b17023SJohn Marino    is a bit vector. If an operand of PHI is uninitialized, the
1767*e4b17023SJohn Marino    correponding bit in the vector is 1.  VISIED_PHIS is a pointer
1768*e4b17023SJohn Marino    set of phis being visted.  */
1769*e4b17023SJohn Marino 
1770*e4b17023SJohn Marino static bool
is_use_properly_guarded(gimple use_stmt,basic_block use_bb,gimple phi,unsigned uninit_opnds,struct pointer_set_t * visited_phis)1771*e4b17023SJohn Marino is_use_properly_guarded (gimple use_stmt,
1772*e4b17023SJohn Marino                          basic_block use_bb,
1773*e4b17023SJohn Marino                          gimple phi,
1774*e4b17023SJohn Marino                          unsigned uninit_opnds,
1775*e4b17023SJohn Marino                          struct pointer_set_t *visited_phis)
1776*e4b17023SJohn Marino {
1777*e4b17023SJohn Marino   basic_block phi_bb;
1778*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) **preds = 0;
1779*e4b17023SJohn Marino   VEC(use_pred_info_t, heap) **def_preds = 0;
1780*e4b17023SJohn Marino   size_t num_preds = 0, num_def_preds = 0;
1781*e4b17023SJohn Marino   bool has_valid_preds = false;
1782*e4b17023SJohn Marino   bool is_properly_guarded = false;
1783*e4b17023SJohn Marino 
1784*e4b17023SJohn Marino   if (pointer_set_insert (visited_phis, phi))
1785*e4b17023SJohn Marino     return false;
1786*e4b17023SJohn Marino 
1787*e4b17023SJohn Marino   phi_bb = gimple_bb (phi);
1788*e4b17023SJohn Marino 
1789*e4b17023SJohn Marino   if (is_non_loop_exit_postdominating (use_bb, phi_bb))
1790*e4b17023SJohn Marino     return false;
1791*e4b17023SJohn Marino 
1792*e4b17023SJohn Marino   has_valid_preds = find_predicates (&preds, &num_preds,
1793*e4b17023SJohn Marino                                      phi_bb, use_bb);
1794*e4b17023SJohn Marino 
1795*e4b17023SJohn Marino   if (!has_valid_preds)
1796*e4b17023SJohn Marino     {
1797*e4b17023SJohn Marino       destroy_predicate_vecs (num_preds, preds);
1798*e4b17023SJohn Marino       return false;
1799*e4b17023SJohn Marino     }
1800*e4b17023SJohn Marino 
1801*e4b17023SJohn Marino   if (dump_file)
1802*e4b17023SJohn Marino     dump_predicates (use_stmt, num_preds, preds,
1803*e4b17023SJohn Marino                      "\nUse in stmt ");
1804*e4b17023SJohn Marino 
1805*e4b17023SJohn Marino   has_valid_preds = find_def_preds (&def_preds,
1806*e4b17023SJohn Marino                                     &num_def_preds, phi);
1807*e4b17023SJohn Marino 
1808*e4b17023SJohn Marino   if (has_valid_preds)
1809*e4b17023SJohn Marino     {
1810*e4b17023SJohn Marino       bool normed;
1811*e4b17023SJohn Marino       if (dump_file)
1812*e4b17023SJohn Marino         dump_predicates (phi, num_def_preds, def_preds,
1813*e4b17023SJohn Marino                          "Operand defs of phi ");
1814*e4b17023SJohn Marino 
1815*e4b17023SJohn Marino       normed = normalize_preds (def_preds, &num_def_preds);
1816*e4b17023SJohn Marino       if (normed && dump_file)
1817*e4b17023SJohn Marino         {
1818*e4b17023SJohn Marino           fprintf (dump_file, "\nNormalized to\n");
1819*e4b17023SJohn Marino           dump_predicates (phi, num_def_preds, def_preds,
1820*e4b17023SJohn Marino                            "Operand defs of phi ");
1821*e4b17023SJohn Marino         }
1822*e4b17023SJohn Marino       is_properly_guarded =
1823*e4b17023SJohn Marino           is_superset_of (def_preds, num_def_preds,
1824*e4b17023SJohn Marino                           preds, num_preds);
1825*e4b17023SJohn Marino     }
1826*e4b17023SJohn Marino 
1827*e4b17023SJohn Marino   /* further prune the dead incoming phi edges. */
1828*e4b17023SJohn Marino   if (!is_properly_guarded)
1829*e4b17023SJohn Marino     is_properly_guarded
1830*e4b17023SJohn Marino         = use_pred_not_overlap_with_undef_path_pred (
1831*e4b17023SJohn Marino             num_preds, preds, phi, uninit_opnds, visited_phis);
1832*e4b17023SJohn Marino 
1833*e4b17023SJohn Marino   destroy_predicate_vecs (num_preds, preds);
1834*e4b17023SJohn Marino   destroy_predicate_vecs (num_def_preds, def_preds);
1835*e4b17023SJohn Marino   return is_properly_guarded;
1836*e4b17023SJohn Marino }
1837*e4b17023SJohn Marino 
1838*e4b17023SJohn Marino /* Searches through all uses of a potentially
1839*e4b17023SJohn Marino    uninitialized variable defined by PHI and returns a use
1840*e4b17023SJohn Marino    statement if the use is not properly guarded. It returns
1841*e4b17023SJohn Marino    NULL if all uses are guarded. UNINIT_OPNDS is a bitvector
1842*e4b17023SJohn Marino    holding the position(s) of uninit PHI operands. WORKLIST
1843*e4b17023SJohn Marino    is the vector of candidate phis that may be updated by this
1844*e4b17023SJohn Marino    function. ADDED_TO_WORKLIST is the pointer set tracking
1845*e4b17023SJohn Marino    if the new phi is already in the worklist.  */
1846*e4b17023SJohn Marino 
1847*e4b17023SJohn Marino static gimple
find_uninit_use(gimple phi,unsigned uninit_opnds,VEC (gimple,heap)** worklist,struct pointer_set_t * added_to_worklist)1848*e4b17023SJohn Marino find_uninit_use (gimple phi, unsigned uninit_opnds,
1849*e4b17023SJohn Marino                  VEC(gimple, heap) **worklist,
1850*e4b17023SJohn Marino 		 struct pointer_set_t *added_to_worklist)
1851*e4b17023SJohn Marino {
1852*e4b17023SJohn Marino   tree phi_result;
1853*e4b17023SJohn Marino   use_operand_p use_p;
1854*e4b17023SJohn Marino   gimple use_stmt;
1855*e4b17023SJohn Marino   imm_use_iterator iter;
1856*e4b17023SJohn Marino 
1857*e4b17023SJohn Marino   phi_result = gimple_phi_result (phi);
1858*e4b17023SJohn Marino 
1859*e4b17023SJohn Marino   FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
1860*e4b17023SJohn Marino     {
1861*e4b17023SJohn Marino       struct pointer_set_t *visited_phis;
1862*e4b17023SJohn Marino       basic_block use_bb;
1863*e4b17023SJohn Marino 
1864*e4b17023SJohn Marino       use_stmt = USE_STMT (use_p);
1865*e4b17023SJohn Marino       if (is_gimple_debug (use_stmt))
1866*e4b17023SJohn Marino 	continue;
1867*e4b17023SJohn Marino 
1868*e4b17023SJohn Marino       visited_phis = pointer_set_create ();
1869*e4b17023SJohn Marino 
1870*e4b17023SJohn Marino       if (gimple_code (use_stmt) == GIMPLE_PHI)
1871*e4b17023SJohn Marino 	use_bb = gimple_phi_arg_edge (use_stmt,
1872*e4b17023SJohn Marino 				      PHI_ARG_INDEX_FROM_USE (use_p))->src;
1873*e4b17023SJohn Marino       else
1874*e4b17023SJohn Marino 	use_bb = gimple_bb (use_stmt);
1875*e4b17023SJohn Marino 
1876*e4b17023SJohn Marino       if (is_use_properly_guarded (use_stmt,
1877*e4b17023SJohn Marino                                    use_bb,
1878*e4b17023SJohn Marino                                    phi,
1879*e4b17023SJohn Marino                                    uninit_opnds,
1880*e4b17023SJohn Marino                                    visited_phis))
1881*e4b17023SJohn Marino         {
1882*e4b17023SJohn Marino           pointer_set_destroy (visited_phis);
1883*e4b17023SJohn Marino           continue;
1884*e4b17023SJohn Marino         }
1885*e4b17023SJohn Marino       pointer_set_destroy (visited_phis);
1886*e4b17023SJohn Marino 
1887*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1888*e4b17023SJohn Marino         {
1889*e4b17023SJohn Marino           fprintf (dump_file, "[CHECK]: Found unguarded use: ");
1890*e4b17023SJohn Marino           print_gimple_stmt (dump_file, use_stmt, 0, 0);
1891*e4b17023SJohn Marino         }
1892*e4b17023SJohn Marino       /* Found one real use, return.  */
1893*e4b17023SJohn Marino       if (gimple_code (use_stmt) != GIMPLE_PHI)
1894*e4b17023SJohn Marino         return use_stmt;
1895*e4b17023SJohn Marino 
1896*e4b17023SJohn Marino       /* Found a phi use that is not guarded,
1897*e4b17023SJohn Marino          add the phi to the worklist.  */
1898*e4b17023SJohn Marino       if (!pointer_set_insert (added_to_worklist,
1899*e4b17023SJohn Marino                                use_stmt))
1900*e4b17023SJohn Marino         {
1901*e4b17023SJohn Marino           if (dump_file && (dump_flags & TDF_DETAILS))
1902*e4b17023SJohn Marino             {
1903*e4b17023SJohn Marino               fprintf (dump_file, "[WORKLIST]: Update worklist with phi: ");
1904*e4b17023SJohn Marino               print_gimple_stmt (dump_file, use_stmt, 0, 0);
1905*e4b17023SJohn Marino             }
1906*e4b17023SJohn Marino 
1907*e4b17023SJohn Marino           VEC_safe_push (gimple, heap, *worklist, use_stmt);
1908*e4b17023SJohn Marino           pointer_set_insert (possibly_undefined_names,
1909*e4b17023SJohn Marino 	                      phi_result);
1910*e4b17023SJohn Marino         }
1911*e4b17023SJohn Marino     }
1912*e4b17023SJohn Marino 
1913*e4b17023SJohn Marino   return NULL;
1914*e4b17023SJohn Marino }
1915*e4b17023SJohn Marino 
1916*e4b17023SJohn Marino /* Look for inputs to PHI that are SSA_NAMEs that have empty definitions
1917*e4b17023SJohn Marino    and gives warning if there exists a runtime path from the entry to a
1918*e4b17023SJohn Marino    use of the PHI def that does not contain a definition. In other words,
1919*e4b17023SJohn Marino    the warning is on the real use. The more dead paths that can be pruned
1920*e4b17023SJohn Marino    by the compiler, the fewer false positives the warning is. WORKLIST
1921*e4b17023SJohn Marino    is a vector of candidate phis to be examined. ADDED_TO_WORKLIST is
1922*e4b17023SJohn Marino    a pointer set tracking if the new phi is added to the worklist or not.  */
1923*e4b17023SJohn Marino 
1924*e4b17023SJohn Marino static void
warn_uninitialized_phi(gimple phi,VEC (gimple,heap)** worklist,struct pointer_set_t * added_to_worklist)1925*e4b17023SJohn Marino warn_uninitialized_phi (gimple phi, VEC(gimple, heap) **worklist,
1926*e4b17023SJohn Marino                         struct pointer_set_t *added_to_worklist)
1927*e4b17023SJohn Marino {
1928*e4b17023SJohn Marino   unsigned uninit_opnds;
1929*e4b17023SJohn Marino   gimple uninit_use_stmt = 0;
1930*e4b17023SJohn Marino   tree uninit_op;
1931*e4b17023SJohn Marino 
1932*e4b17023SJohn Marino   /* Don't look at memory tags.  */
1933*e4b17023SJohn Marino   if (!is_gimple_reg (gimple_phi_result (phi)))
1934*e4b17023SJohn Marino     return;
1935*e4b17023SJohn Marino 
1936*e4b17023SJohn Marino   uninit_opnds = compute_uninit_opnds_pos (phi);
1937*e4b17023SJohn Marino 
1938*e4b17023SJohn Marino   if  (MASK_EMPTY (uninit_opnds))
1939*e4b17023SJohn Marino     return;
1940*e4b17023SJohn Marino 
1941*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1942*e4b17023SJohn Marino     {
1943*e4b17023SJohn Marino       fprintf (dump_file, "[CHECK]: examining phi: ");
1944*e4b17023SJohn Marino       print_gimple_stmt (dump_file, phi, 0, 0);
1945*e4b17023SJohn Marino     }
1946*e4b17023SJohn Marino 
1947*e4b17023SJohn Marino   /* Now check if we have any use of the value without proper guard.  */
1948*e4b17023SJohn Marino   uninit_use_stmt = find_uninit_use (phi, uninit_opnds,
1949*e4b17023SJohn Marino                                      worklist, added_to_worklist);
1950*e4b17023SJohn Marino 
1951*e4b17023SJohn Marino   /* All uses are properly guarded.  */
1952*e4b17023SJohn Marino   if (!uninit_use_stmt)
1953*e4b17023SJohn Marino     return;
1954*e4b17023SJohn Marino 
1955*e4b17023SJohn Marino   uninit_op = gimple_phi_arg_def (phi, MASK_FIRST_SET_BIT (uninit_opnds));
1956*e4b17023SJohn Marino   warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, SSA_NAME_VAR (uninit_op),
1957*e4b17023SJohn Marino 	       SSA_NAME_VAR (uninit_op),
1958*e4b17023SJohn Marino                "%qD may be used uninitialized in this function",
1959*e4b17023SJohn Marino                uninit_use_stmt);
1960*e4b17023SJohn Marino 
1961*e4b17023SJohn Marino }
1962*e4b17023SJohn Marino 
1963*e4b17023SJohn Marino 
1964*e4b17023SJohn Marino /* Entry point to the late uninitialized warning pass.  */
1965*e4b17023SJohn Marino 
1966*e4b17023SJohn Marino static unsigned int
execute_late_warn_uninitialized(void)1967*e4b17023SJohn Marino execute_late_warn_uninitialized (void)
1968*e4b17023SJohn Marino {
1969*e4b17023SJohn Marino   basic_block bb;
1970*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1971*e4b17023SJohn Marino   VEC(gimple, heap) *worklist = 0;
1972*e4b17023SJohn Marino   struct pointer_set_t *added_to_worklist;
1973*e4b17023SJohn Marino 
1974*e4b17023SJohn Marino   calculate_dominance_info (CDI_DOMINATORS);
1975*e4b17023SJohn Marino   calculate_dominance_info (CDI_POST_DOMINATORS);
1976*e4b17023SJohn Marino   /* Re-do the plain uninitialized variable check, as optimization may have
1977*e4b17023SJohn Marino      straightened control flow.  Do this first so that we don't accidentally
1978*e4b17023SJohn Marino      get a "may be" warning when we'd have seen an "is" warning later.  */
1979*e4b17023SJohn Marino   warn_uninitialized_vars (/*warn_possibly_uninitialized=*/1);
1980*e4b17023SJohn Marino 
1981*e4b17023SJohn Marino   timevar_push (TV_TREE_UNINIT);
1982*e4b17023SJohn Marino 
1983*e4b17023SJohn Marino   possibly_undefined_names = pointer_set_create ();
1984*e4b17023SJohn Marino   added_to_worklist = pointer_set_create ();
1985*e4b17023SJohn Marino 
1986*e4b17023SJohn Marino   /* Initialize worklist  */
1987*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1988*e4b17023SJohn Marino     for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1989*e4b17023SJohn Marino       {
1990*e4b17023SJohn Marino         gimple phi = gsi_stmt (gsi);
1991*e4b17023SJohn Marino         size_t n, i;
1992*e4b17023SJohn Marino 
1993*e4b17023SJohn Marino         n = gimple_phi_num_args (phi);
1994*e4b17023SJohn Marino 
1995*e4b17023SJohn Marino         /* Don't look at memory tags.  */
1996*e4b17023SJohn Marino         if (!is_gimple_reg (gimple_phi_result (phi)))
1997*e4b17023SJohn Marino           continue;
1998*e4b17023SJohn Marino 
1999*e4b17023SJohn Marino         for (i = 0; i < n; ++i)
2000*e4b17023SJohn Marino           {
2001*e4b17023SJohn Marino             tree op = gimple_phi_arg_def (phi, i);
2002*e4b17023SJohn Marino             if (TREE_CODE (op) == SSA_NAME
2003*e4b17023SJohn Marino                 && ssa_undefined_value_p (op))
2004*e4b17023SJohn Marino               {
2005*e4b17023SJohn Marino                 VEC_safe_push (gimple, heap, worklist, phi);
2006*e4b17023SJohn Marino 		pointer_set_insert (added_to_worklist, phi);
2007*e4b17023SJohn Marino                 if (dump_file && (dump_flags & TDF_DETAILS))
2008*e4b17023SJohn Marino                   {
2009*e4b17023SJohn Marino                     fprintf (dump_file, "[WORKLIST]: add to initial list: ");
2010*e4b17023SJohn Marino                     print_gimple_stmt (dump_file, phi, 0, 0);
2011*e4b17023SJohn Marino                   }
2012*e4b17023SJohn Marino                 break;
2013*e4b17023SJohn Marino               }
2014*e4b17023SJohn Marino           }
2015*e4b17023SJohn Marino       }
2016*e4b17023SJohn Marino 
2017*e4b17023SJohn Marino   while (VEC_length (gimple, worklist) != 0)
2018*e4b17023SJohn Marino     {
2019*e4b17023SJohn Marino       gimple cur_phi = 0;
2020*e4b17023SJohn Marino       cur_phi = VEC_pop (gimple, worklist);
2021*e4b17023SJohn Marino       warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
2022*e4b17023SJohn Marino     }
2023*e4b17023SJohn Marino 
2024*e4b17023SJohn Marino   VEC_free (gimple, heap, worklist);
2025*e4b17023SJohn Marino   pointer_set_destroy (added_to_worklist);
2026*e4b17023SJohn Marino   pointer_set_destroy (possibly_undefined_names);
2027*e4b17023SJohn Marino   possibly_undefined_names = NULL;
2028*e4b17023SJohn Marino   free_dominance_info (CDI_POST_DOMINATORS);
2029*e4b17023SJohn Marino   timevar_pop (TV_TREE_UNINIT);
2030*e4b17023SJohn Marino   return 0;
2031*e4b17023SJohn Marino }
2032*e4b17023SJohn Marino 
2033*e4b17023SJohn Marino static bool
gate_warn_uninitialized(void)2034*e4b17023SJohn Marino gate_warn_uninitialized (void)
2035*e4b17023SJohn Marino {
2036*e4b17023SJohn Marino   return warn_uninitialized != 0;
2037*e4b17023SJohn Marino }
2038*e4b17023SJohn Marino 
2039*e4b17023SJohn Marino struct gimple_opt_pass pass_late_warn_uninitialized =
2040*e4b17023SJohn Marino {
2041*e4b17023SJohn Marino  {
2042*e4b17023SJohn Marino   GIMPLE_PASS,
2043*e4b17023SJohn Marino   "uninit",				/* name */
2044*e4b17023SJohn Marino   gate_warn_uninitialized,		/* gate */
2045*e4b17023SJohn Marino   execute_late_warn_uninitialized,	/* execute */
2046*e4b17023SJohn Marino   NULL,					/* sub */
2047*e4b17023SJohn Marino   NULL,					/* next */
2048*e4b17023SJohn Marino   0,					/* static_pass_number */
2049*e4b17023SJohn Marino   TV_NONE,     	        		/* tv_id */
2050*e4b17023SJohn Marino   PROP_ssa,				/* properties_required */
2051*e4b17023SJohn Marino   0,					/* properties_provided */
2052*e4b17023SJohn Marino   0,					/* properties_destroyed */
2053*e4b17023SJohn Marino   0,					/* todo_flags_start */
2054*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
2055*e4b17023SJohn Marino  }
2056*e4b17023SJohn Marino };
2057