xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-ssa-reassoc.c (revision e4b17023d31ea40e02fa06b141db27753ecc6934)
1*e4b17023SJohn Marino /* Reassociation for trees.
2*e4b17023SJohn Marino    Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Daniel Berlin <dan@dberlin.org>
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 "basic-block.h"
28*e4b17023SJohn Marino #include "tree-pretty-print.h"
29*e4b17023SJohn Marino #include "gimple-pretty-print.h"
30*e4b17023SJohn Marino #include "tree-inline.h"
31*e4b17023SJohn Marino #include "tree-flow.h"
32*e4b17023SJohn Marino #include "gimple.h"
33*e4b17023SJohn Marino #include "tree-dump.h"
34*e4b17023SJohn Marino #include "timevar.h"
35*e4b17023SJohn Marino #include "tree-iterator.h"
36*e4b17023SJohn Marino #include "tree-pass.h"
37*e4b17023SJohn Marino #include "alloc-pool.h"
38*e4b17023SJohn Marino #include "vec.h"
39*e4b17023SJohn Marino #include "langhooks.h"
40*e4b17023SJohn Marino #include "pointer-set.h"
41*e4b17023SJohn Marino #include "cfgloop.h"
42*e4b17023SJohn Marino #include "flags.h"
43*e4b17023SJohn Marino #include "target.h"
44*e4b17023SJohn Marino #include "params.h"
45*e4b17023SJohn Marino #include "diagnostic-core.h"
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino /*  This is a simple global reassociation pass.  It is, in part, based
48*e4b17023SJohn Marino     on the LLVM pass of the same name (They do some things more/less
49*e4b17023SJohn Marino     than we do, in different orders, etc).
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino     It consists of five steps:
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino     1. Breaking up subtract operations into addition + negate, where
54*e4b17023SJohn Marino     it would promote the reassociation of adds.
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino     2. Left linearization of the expression trees, so that (A+B)+(C+D)
57*e4b17023SJohn Marino     becomes (((A+B)+C)+D), which is easier for us to rewrite later.
58*e4b17023SJohn Marino     During linearization, we place the operands of the binary
59*e4b17023SJohn Marino     expressions into a vector of operand_entry_t
60*e4b17023SJohn Marino 
61*e4b17023SJohn Marino     3. Optimization of the operand lists, eliminating things like a +
62*e4b17023SJohn Marino     -a, a & a, etc.
63*e4b17023SJohn Marino 
64*e4b17023SJohn Marino     4. Rewrite the expression trees we linearized and optimized so
65*e4b17023SJohn Marino     they are in proper rank order.
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino     5. Repropagate negates, as nothing else will clean it up ATM.
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino     A bit of theory on #4, since nobody seems to write anything down
70*e4b17023SJohn Marino     about why it makes sense to do it the way they do it:
71*e4b17023SJohn Marino 
72*e4b17023SJohn Marino     We could do this much nicer theoretically, but don't (for reasons
73*e4b17023SJohn Marino     explained after how to do it theoretically nice :P).
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino     In order to promote the most redundancy elimination, you want
76*e4b17023SJohn Marino     binary expressions whose operands are the same rank (or
77*e4b17023SJohn Marino     preferably, the same value) exposed to the redundancy eliminator,
78*e4b17023SJohn Marino     for possible elimination.
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino     So the way to do this if we really cared, is to build the new op
81*e4b17023SJohn Marino     tree from the leaves to the roots, merging as you go, and putting the
82*e4b17023SJohn Marino     new op on the end of the worklist, until you are left with one
83*e4b17023SJohn Marino     thing on the worklist.
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino     IE if you have to rewrite the following set of operands (listed with
86*e4b17023SJohn Marino     rank in parentheses), with opcode PLUS_EXPR:
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino     a (1),  b (1),  c (1),  d (2), e (2)
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino     We start with our merge worklist empty, and the ops list with all of
92*e4b17023SJohn Marino     those on it.
93*e4b17023SJohn Marino 
94*e4b17023SJohn Marino     You want to first merge all leaves of the same rank, as much as
95*e4b17023SJohn Marino     possible.
96*e4b17023SJohn Marino 
97*e4b17023SJohn Marino     So first build a binary op of
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino     mergetmp = a + b, and put "mergetmp" on the merge worklist.
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino     Because there is no three operand form of PLUS_EXPR, c is not going to
102*e4b17023SJohn Marino     be exposed to redundancy elimination as a rank 1 operand.
103*e4b17023SJohn Marino 
104*e4b17023SJohn Marino     So you might as well throw it on the merge worklist (you could also
105*e4b17023SJohn Marino     consider it to now be a rank two operand, and merge it with d and e,
106*e4b17023SJohn Marino     but in this case, you then have evicted e from a binary op. So at
107*e4b17023SJohn Marino     least in this situation, you can't win.)
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino     Then build a binary op of d + e
110*e4b17023SJohn Marino     mergetmp2 = d + e
111*e4b17023SJohn Marino 
112*e4b17023SJohn Marino     and put mergetmp2 on the merge worklist.
113*e4b17023SJohn Marino 
114*e4b17023SJohn Marino     so merge worklist = {mergetmp, c, mergetmp2}
115*e4b17023SJohn Marino 
116*e4b17023SJohn Marino     Continue building binary ops of these operations until you have only
117*e4b17023SJohn Marino     one operation left on the worklist.
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino     So we have
120*e4b17023SJohn Marino 
121*e4b17023SJohn Marino     build binary op
122*e4b17023SJohn Marino     mergetmp3 = mergetmp + c
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino     worklist = {mergetmp2, mergetmp3}
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino     mergetmp4 = mergetmp2 + mergetmp3
127*e4b17023SJohn Marino 
128*e4b17023SJohn Marino     worklist = {mergetmp4}
129*e4b17023SJohn Marino 
130*e4b17023SJohn Marino     because we have one operation left, we can now just set the original
131*e4b17023SJohn Marino     statement equal to the result of that operation.
132*e4b17023SJohn Marino 
133*e4b17023SJohn Marino     This will at least expose a + b  and d + e to redundancy elimination
134*e4b17023SJohn Marino     as binary operations.
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino     For extra points, you can reuse the old statements to build the
137*e4b17023SJohn Marino     mergetmps, since you shouldn't run out.
138*e4b17023SJohn Marino 
139*e4b17023SJohn Marino     So why don't we do this?
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino     Because it's expensive, and rarely will help.  Most trees we are
142*e4b17023SJohn Marino     reassociating have 3 or less ops.  If they have 2 ops, they already
143*e4b17023SJohn Marino     will be written into a nice single binary op.  If you have 3 ops, a
144*e4b17023SJohn Marino     single simple check suffices to tell you whether the first two are of the
145*e4b17023SJohn Marino     same rank.  If so, you know to order it
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino     mergetmp = op1 + op2
148*e4b17023SJohn Marino     newstmt = mergetmp + op3
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino     instead of
151*e4b17023SJohn Marino     mergetmp = op2 + op3
152*e4b17023SJohn Marino     newstmt = mergetmp + op1
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino     If all three are of the same rank, you can't expose them all in a
155*e4b17023SJohn Marino     single binary operator anyway, so the above is *still* the best you
156*e4b17023SJohn Marino     can do.
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino     Thus, this is what we do.  When we have three ops left, we check to see
159*e4b17023SJohn Marino     what order to put them in, and call it a day.  As a nod to vector sum
160*e4b17023SJohn Marino     reduction, we check if any of the ops are really a phi node that is a
161*e4b17023SJohn Marino     destructive update for the associating op, and keep the destructive
162*e4b17023SJohn Marino     update together for vector sum reduction recognition.  */
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino /* Statistics */
166*e4b17023SJohn Marino static struct
167*e4b17023SJohn Marino {
168*e4b17023SJohn Marino   int linearized;
169*e4b17023SJohn Marino   int constants_eliminated;
170*e4b17023SJohn Marino   int ops_eliminated;
171*e4b17023SJohn Marino   int rewritten;
172*e4b17023SJohn Marino } reassociate_stats;
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino /* Operator, rank pair.  */
175*e4b17023SJohn Marino typedef struct operand_entry
176*e4b17023SJohn Marino {
177*e4b17023SJohn Marino   unsigned int rank;
178*e4b17023SJohn Marino   int id;
179*e4b17023SJohn Marino   tree op;
180*e4b17023SJohn Marino } *operand_entry_t;
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino static alloc_pool operand_entry_pool;
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino /* This is used to assign a unique ID to each struct operand_entry
185*e4b17023SJohn Marino    so that qsort results are identical on different hosts.  */
186*e4b17023SJohn Marino static int next_operand_entry_id;
187*e4b17023SJohn Marino 
188*e4b17023SJohn Marino /* Starting rank number for a given basic block, so that we can rank
189*e4b17023SJohn Marino    operations using unmovable instructions in that BB based on the bb
190*e4b17023SJohn Marino    depth.  */
191*e4b17023SJohn Marino static long *bb_rank;
192*e4b17023SJohn Marino 
193*e4b17023SJohn Marino /* Operand->rank hashtable.  */
194*e4b17023SJohn Marino static struct pointer_map_t *operand_rank;
195*e4b17023SJohn Marino 
196*e4b17023SJohn Marino /* Forward decls.  */
197*e4b17023SJohn Marino static long get_rank (tree);
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino 
200*e4b17023SJohn Marino /* Bias amount for loop-carried phis.  We want this to be larger than
201*e4b17023SJohn Marino    the depth of any reassociation tree we can see, but not larger than
202*e4b17023SJohn Marino    the rank difference between two blocks.  */
203*e4b17023SJohn Marino #define PHI_LOOP_BIAS (1 << 15)
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino /* Rank assigned to a phi statement.  If STMT is a loop-carried phi of
206*e4b17023SJohn Marino    an innermost loop, and the phi has only a single use which is inside
207*e4b17023SJohn Marino    the loop, then the rank is the block rank of the loop latch plus an
208*e4b17023SJohn Marino    extra bias for the loop-carried dependence.  This causes expressions
209*e4b17023SJohn Marino    calculated into an accumulator variable to be independent for each
210*e4b17023SJohn Marino    iteration of the loop.  If STMT is some other phi, the rank is the
211*e4b17023SJohn Marino    block rank of its containing block.  */
212*e4b17023SJohn Marino static long
213*e4b17023SJohn Marino phi_rank (gimple stmt)
214*e4b17023SJohn Marino {
215*e4b17023SJohn Marino   basic_block bb = gimple_bb (stmt);
216*e4b17023SJohn Marino   struct loop *father = bb->loop_father;
217*e4b17023SJohn Marino   tree res;
218*e4b17023SJohn Marino   unsigned i;
219*e4b17023SJohn Marino   use_operand_p use;
220*e4b17023SJohn Marino   gimple use_stmt;
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino   /* We only care about real loops (those with a latch).  */
223*e4b17023SJohn Marino   if (!father->latch)
224*e4b17023SJohn Marino     return bb_rank[bb->index];
225*e4b17023SJohn Marino 
226*e4b17023SJohn Marino   /* Interesting phis must be in headers of innermost loops.  */
227*e4b17023SJohn Marino   if (bb != father->header
228*e4b17023SJohn Marino       || father->inner)
229*e4b17023SJohn Marino     return bb_rank[bb->index];
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino   /* Ignore virtual SSA_NAMEs.  */
232*e4b17023SJohn Marino   res = gimple_phi_result (stmt);
233*e4b17023SJohn Marino   if (!is_gimple_reg (SSA_NAME_VAR (res)))
234*e4b17023SJohn Marino     return bb_rank[bb->index];
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino   /* The phi definition must have a single use, and that use must be
237*e4b17023SJohn Marino      within the loop.  Otherwise this isn't an accumulator pattern.  */
238*e4b17023SJohn Marino   if (!single_imm_use (res, &use, &use_stmt)
239*e4b17023SJohn Marino       || gimple_bb (use_stmt)->loop_father != father)
240*e4b17023SJohn Marino     return bb_rank[bb->index];
241*e4b17023SJohn Marino 
242*e4b17023SJohn Marino   /* Look for phi arguments from within the loop.  If found, bias this phi.  */
243*e4b17023SJohn Marino   for (i = 0; i < gimple_phi_num_args (stmt); i++)
244*e4b17023SJohn Marino     {
245*e4b17023SJohn Marino       tree arg = gimple_phi_arg_def (stmt, i);
246*e4b17023SJohn Marino       if (TREE_CODE (arg) == SSA_NAME
247*e4b17023SJohn Marino 	  && !SSA_NAME_IS_DEFAULT_DEF (arg))
248*e4b17023SJohn Marino 	{
249*e4b17023SJohn Marino 	  gimple def_stmt = SSA_NAME_DEF_STMT (arg);
250*e4b17023SJohn Marino 	  if (gimple_bb (def_stmt)->loop_father == father)
251*e4b17023SJohn Marino 	    return bb_rank[father->latch->index] + PHI_LOOP_BIAS;
252*e4b17023SJohn Marino 	}
253*e4b17023SJohn Marino     }
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   /* Must be an uninteresting phi.  */
256*e4b17023SJohn Marino   return bb_rank[bb->index];
257*e4b17023SJohn Marino }
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino /* If EXP is an SSA_NAME defined by a PHI statement that represents a
260*e4b17023SJohn Marino    loop-carried dependence of an innermost loop, return TRUE; else
261*e4b17023SJohn Marino    return FALSE.  */
262*e4b17023SJohn Marino static bool
263*e4b17023SJohn Marino loop_carried_phi (tree exp)
264*e4b17023SJohn Marino {
265*e4b17023SJohn Marino   gimple phi_stmt;
266*e4b17023SJohn Marino   long block_rank;
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino   if (TREE_CODE (exp) != SSA_NAME
269*e4b17023SJohn Marino       || SSA_NAME_IS_DEFAULT_DEF (exp))
270*e4b17023SJohn Marino     return false;
271*e4b17023SJohn Marino 
272*e4b17023SJohn Marino   phi_stmt = SSA_NAME_DEF_STMT (exp);
273*e4b17023SJohn Marino 
274*e4b17023SJohn Marino   if (gimple_code (SSA_NAME_DEF_STMT (exp)) != GIMPLE_PHI)
275*e4b17023SJohn Marino     return false;
276*e4b17023SJohn Marino 
277*e4b17023SJohn Marino   /* Non-loop-carried phis have block rank.  Loop-carried phis have
278*e4b17023SJohn Marino      an additional bias added in.  If this phi doesn't have block rank,
279*e4b17023SJohn Marino      it's biased and should not be propagated.  */
280*e4b17023SJohn Marino   block_rank = bb_rank[gimple_bb (phi_stmt)->index];
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino   if (phi_rank (phi_stmt) != block_rank)
283*e4b17023SJohn Marino     return true;
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino   return false;
286*e4b17023SJohn Marino }
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino /* Return the maximum of RANK and the rank that should be propagated
289*e4b17023SJohn Marino    from expression OP.  For most operands, this is just the rank of OP.
290*e4b17023SJohn Marino    For loop-carried phis, the value is zero to avoid undoing the bias
291*e4b17023SJohn Marino    in favor of the phi.  */
292*e4b17023SJohn Marino static long
293*e4b17023SJohn Marino propagate_rank (long rank, tree op)
294*e4b17023SJohn Marino {
295*e4b17023SJohn Marino   long op_rank;
296*e4b17023SJohn Marino 
297*e4b17023SJohn Marino   if (loop_carried_phi (op))
298*e4b17023SJohn Marino     return rank;
299*e4b17023SJohn Marino 
300*e4b17023SJohn Marino   op_rank = get_rank (op);
301*e4b17023SJohn Marino 
302*e4b17023SJohn Marino   return MAX (rank, op_rank);
303*e4b17023SJohn Marino }
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino /* Look up the operand rank structure for expression E.  */
306*e4b17023SJohn Marino 
307*e4b17023SJohn Marino static inline long
308*e4b17023SJohn Marino find_operand_rank (tree e)
309*e4b17023SJohn Marino {
310*e4b17023SJohn Marino   void **slot = pointer_map_contains (operand_rank, e);
311*e4b17023SJohn Marino   return slot ? (long) (intptr_t) *slot : -1;
312*e4b17023SJohn Marino }
313*e4b17023SJohn Marino 
314*e4b17023SJohn Marino /* Insert {E,RANK} into the operand rank hashtable.  */
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino static inline void
317*e4b17023SJohn Marino insert_operand_rank (tree e, long rank)
318*e4b17023SJohn Marino {
319*e4b17023SJohn Marino   void **slot;
320*e4b17023SJohn Marino   gcc_assert (rank > 0);
321*e4b17023SJohn Marino   slot = pointer_map_insert (operand_rank, e);
322*e4b17023SJohn Marino   gcc_assert (!*slot);
323*e4b17023SJohn Marino   *slot = (void *) (intptr_t) rank;
324*e4b17023SJohn Marino }
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino /* Given an expression E, return the rank of the expression.  */
327*e4b17023SJohn Marino 
328*e4b17023SJohn Marino static long
329*e4b17023SJohn Marino get_rank (tree e)
330*e4b17023SJohn Marino {
331*e4b17023SJohn Marino   /* Constants have rank 0.  */
332*e4b17023SJohn Marino   if (is_gimple_min_invariant (e))
333*e4b17023SJohn Marino     return 0;
334*e4b17023SJohn Marino 
335*e4b17023SJohn Marino   /* SSA_NAME's have the rank of the expression they are the result
336*e4b17023SJohn Marino      of.
337*e4b17023SJohn Marino      For globals and uninitialized values, the rank is 0.
338*e4b17023SJohn Marino      For function arguments, use the pre-setup rank.
339*e4b17023SJohn Marino      For PHI nodes, stores, asm statements, etc, we use the rank of
340*e4b17023SJohn Marino      the BB.
341*e4b17023SJohn Marino      For simple operations, the rank is the maximum rank of any of
342*e4b17023SJohn Marino      its operands, or the bb_rank, whichever is less.
343*e4b17023SJohn Marino      I make no claims that this is optimal, however, it gives good
344*e4b17023SJohn Marino      results.  */
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino   /* We make an exception to the normal ranking system to break
347*e4b17023SJohn Marino      dependences of accumulator variables in loops.  Suppose we
348*e4b17023SJohn Marino      have a simple one-block loop containing:
349*e4b17023SJohn Marino 
350*e4b17023SJohn Marino        x_1 = phi(x_0, x_2)
351*e4b17023SJohn Marino        b = a + x_1
352*e4b17023SJohn Marino        c = b + d
353*e4b17023SJohn Marino        x_2 = c + e
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino      As shown, each iteration of the calculation into x is fully
356*e4b17023SJohn Marino      dependent upon the iteration before it.  We would prefer to
357*e4b17023SJohn Marino      see this in the form:
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino        x_1 = phi(x_0, x_2)
360*e4b17023SJohn Marino        b = a + d
361*e4b17023SJohn Marino        c = b + e
362*e4b17023SJohn Marino        x_2 = c + x_1
363*e4b17023SJohn Marino 
364*e4b17023SJohn Marino      If the loop is unrolled, the calculations of b and c from
365*e4b17023SJohn Marino      different iterations can be interleaved.
366*e4b17023SJohn Marino 
367*e4b17023SJohn Marino      To obtain this result during reassociation, we bias the rank
368*e4b17023SJohn Marino      of the phi definition x_1 upward, when it is recognized as an
369*e4b17023SJohn Marino      accumulator pattern.  The artificial rank causes it to be
370*e4b17023SJohn Marino      added last, providing the desired independence.  */
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino   if (TREE_CODE (e) == SSA_NAME)
373*e4b17023SJohn Marino     {
374*e4b17023SJohn Marino       gimple stmt;
375*e4b17023SJohn Marino       long rank;
376*e4b17023SJohn Marino       int i, n;
377*e4b17023SJohn Marino       tree op;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino       if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
380*e4b17023SJohn Marino 	  && SSA_NAME_IS_DEFAULT_DEF (e))
381*e4b17023SJohn Marino 	return find_operand_rank (e);
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino       stmt = SSA_NAME_DEF_STMT (e);
384*e4b17023SJohn Marino       if (gimple_bb (stmt) == NULL)
385*e4b17023SJohn Marino 	return 0;
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_PHI)
388*e4b17023SJohn Marino 	return phi_rank (stmt);
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino       if (!is_gimple_assign (stmt)
391*e4b17023SJohn Marino 	  || gimple_vdef (stmt))
392*e4b17023SJohn Marino 	return bb_rank[gimple_bb (stmt)->index];
393*e4b17023SJohn Marino 
394*e4b17023SJohn Marino       /* If we already have a rank for this expression, use that.  */
395*e4b17023SJohn Marino       rank = find_operand_rank (e);
396*e4b17023SJohn Marino       if (rank != -1)
397*e4b17023SJohn Marino 	return rank;
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino       /* Otherwise, find the maximum rank for the operands.  As an
400*e4b17023SJohn Marino 	 exception, remove the bias from loop-carried phis when propagating
401*e4b17023SJohn Marino 	 the rank so that dependent operations are not also biased.  */
402*e4b17023SJohn Marino       rank = 0;
403*e4b17023SJohn Marino       if (gimple_assign_single_p (stmt))
404*e4b17023SJohn Marino 	{
405*e4b17023SJohn Marino 	  tree rhs = gimple_assign_rhs1 (stmt);
406*e4b17023SJohn Marino 	  n = TREE_OPERAND_LENGTH (rhs);
407*e4b17023SJohn Marino 	  if (n == 0)
408*e4b17023SJohn Marino 	    rank = propagate_rank (rank, rhs);
409*e4b17023SJohn Marino 	  else
410*e4b17023SJohn Marino 	    {
411*e4b17023SJohn Marino 	      for (i = 0; i < n; i++)
412*e4b17023SJohn Marino 		{
413*e4b17023SJohn Marino 		  op = TREE_OPERAND (rhs, i);
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino 		  if (op != NULL_TREE)
416*e4b17023SJohn Marino 		    rank = propagate_rank (rank, op);
417*e4b17023SJohn Marino 		}
418*e4b17023SJohn Marino 	    }
419*e4b17023SJohn Marino 	}
420*e4b17023SJohn Marino       else
421*e4b17023SJohn Marino 	{
422*e4b17023SJohn Marino 	  n = gimple_num_ops (stmt);
423*e4b17023SJohn Marino 	  for (i = 1; i < n; i++)
424*e4b17023SJohn Marino 	    {
425*e4b17023SJohn Marino 	      op = gimple_op (stmt, i);
426*e4b17023SJohn Marino 	      gcc_assert (op);
427*e4b17023SJohn Marino 	      rank = propagate_rank (rank, op);
428*e4b17023SJohn Marino 	    }
429*e4b17023SJohn Marino 	}
430*e4b17023SJohn Marino 
431*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
432*e4b17023SJohn Marino 	{
433*e4b17023SJohn Marino 	  fprintf (dump_file, "Rank for ");
434*e4b17023SJohn Marino 	  print_generic_expr (dump_file, e, 0);
435*e4b17023SJohn Marino 	  fprintf (dump_file, " is %ld\n", (rank + 1));
436*e4b17023SJohn Marino 	}
437*e4b17023SJohn Marino 
438*e4b17023SJohn Marino       /* Note the rank in the hashtable so we don't recompute it.  */
439*e4b17023SJohn Marino       insert_operand_rank (e, (rank + 1));
440*e4b17023SJohn Marino       return (rank + 1);
441*e4b17023SJohn Marino     }
442*e4b17023SJohn Marino 
443*e4b17023SJohn Marino   /* Globals, etc,  are rank 0 */
444*e4b17023SJohn Marino   return 0;
445*e4b17023SJohn Marino }
446*e4b17023SJohn Marino 
447*e4b17023SJohn Marino DEF_VEC_P(operand_entry_t);
448*e4b17023SJohn Marino DEF_VEC_ALLOC_P(operand_entry_t, heap);
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino /* We want integer ones to end up last no matter what, since they are
451*e4b17023SJohn Marino    the ones we can do the most with.  */
452*e4b17023SJohn Marino #define INTEGER_CONST_TYPE 1 << 3
453*e4b17023SJohn Marino #define FLOAT_CONST_TYPE 1 << 2
454*e4b17023SJohn Marino #define OTHER_CONST_TYPE 1 << 1
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino /* Classify an invariant tree into integer, float, or other, so that
457*e4b17023SJohn Marino    we can sort them to be near other constants of the same type.  */
458*e4b17023SJohn Marino static inline int
459*e4b17023SJohn Marino constant_type (tree t)
460*e4b17023SJohn Marino {
461*e4b17023SJohn Marino   if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
462*e4b17023SJohn Marino     return INTEGER_CONST_TYPE;
463*e4b17023SJohn Marino   else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (t)))
464*e4b17023SJohn Marino     return FLOAT_CONST_TYPE;
465*e4b17023SJohn Marino   else
466*e4b17023SJohn Marino     return OTHER_CONST_TYPE;
467*e4b17023SJohn Marino }
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino /* qsort comparison function to sort operand entries PA and PB by rank
470*e4b17023SJohn Marino    so that the sorted array is ordered by rank in decreasing order.  */
471*e4b17023SJohn Marino static int
472*e4b17023SJohn Marino sort_by_operand_rank (const void *pa, const void *pb)
473*e4b17023SJohn Marino {
474*e4b17023SJohn Marino   const operand_entry_t oea = *(const operand_entry_t *)pa;
475*e4b17023SJohn Marino   const operand_entry_t oeb = *(const operand_entry_t *)pb;
476*e4b17023SJohn Marino 
477*e4b17023SJohn Marino   /* It's nicer for optimize_expression if constants that are likely
478*e4b17023SJohn Marino      to fold when added/multiplied//whatever are put next to each
479*e4b17023SJohn Marino      other.  Since all constants have rank 0, order them by type.  */
480*e4b17023SJohn Marino   if (oeb->rank == 0 &&  oea->rank == 0)
481*e4b17023SJohn Marino     {
482*e4b17023SJohn Marino       if (constant_type (oeb->op) != constant_type (oea->op))
483*e4b17023SJohn Marino 	return constant_type (oeb->op) - constant_type (oea->op);
484*e4b17023SJohn Marino       else
485*e4b17023SJohn Marino 	/* To make sorting result stable, we use unique IDs to determine
486*e4b17023SJohn Marino 	   order.  */
487*e4b17023SJohn Marino         return oeb->id - oea->id;
488*e4b17023SJohn Marino     }
489*e4b17023SJohn Marino 
490*e4b17023SJohn Marino   /* Lastly, make sure the versions that are the same go next to each
491*e4b17023SJohn Marino      other.  We use SSA_NAME_VERSION because it's stable.  */
492*e4b17023SJohn Marino   if ((oeb->rank - oea->rank == 0)
493*e4b17023SJohn Marino       && TREE_CODE (oea->op) == SSA_NAME
494*e4b17023SJohn Marino       && TREE_CODE (oeb->op) == SSA_NAME)
495*e4b17023SJohn Marino     {
496*e4b17023SJohn Marino       if (SSA_NAME_VERSION (oeb->op) != SSA_NAME_VERSION (oea->op))
497*e4b17023SJohn Marino 	return SSA_NAME_VERSION (oeb->op) - SSA_NAME_VERSION (oea->op);
498*e4b17023SJohn Marino       else
499*e4b17023SJohn Marino 	return oeb->id - oea->id;
500*e4b17023SJohn Marino     }
501*e4b17023SJohn Marino 
502*e4b17023SJohn Marino   if (oeb->rank != oea->rank)
503*e4b17023SJohn Marino     return oeb->rank - oea->rank;
504*e4b17023SJohn Marino   else
505*e4b17023SJohn Marino     return oeb->id - oea->id;
506*e4b17023SJohn Marino }
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino /* Add an operand entry to *OPS for the tree operand OP.  */
509*e4b17023SJohn Marino 
510*e4b17023SJohn Marino static void
511*e4b17023SJohn Marino add_to_ops_vec (VEC(operand_entry_t, heap) **ops, tree op)
512*e4b17023SJohn Marino {
513*e4b17023SJohn Marino   operand_entry_t oe = (operand_entry_t) pool_alloc (operand_entry_pool);
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino   oe->op = op;
516*e4b17023SJohn Marino   oe->rank = get_rank (op);
517*e4b17023SJohn Marino   oe->id = next_operand_entry_id++;
518*e4b17023SJohn Marino   VEC_safe_push (operand_entry_t, heap, *ops, oe);
519*e4b17023SJohn Marino }
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino /* Return true if STMT is reassociable operation containing a binary
522*e4b17023SJohn Marino    operation with tree code CODE, and is inside LOOP.  */
523*e4b17023SJohn Marino 
524*e4b17023SJohn Marino static bool
525*e4b17023SJohn Marino is_reassociable_op (gimple stmt, enum tree_code code, struct loop *loop)
526*e4b17023SJohn Marino {
527*e4b17023SJohn Marino   basic_block bb = gimple_bb (stmt);
528*e4b17023SJohn Marino 
529*e4b17023SJohn Marino   if (gimple_bb (stmt) == NULL)
530*e4b17023SJohn Marino     return false;
531*e4b17023SJohn Marino 
532*e4b17023SJohn Marino   if (!flow_bb_inside_loop_p (loop, bb))
533*e4b17023SJohn Marino     return false;
534*e4b17023SJohn Marino 
535*e4b17023SJohn Marino   if (is_gimple_assign (stmt)
536*e4b17023SJohn Marino       && gimple_assign_rhs_code (stmt) == code
537*e4b17023SJohn Marino       && has_single_use (gimple_assign_lhs (stmt)))
538*e4b17023SJohn Marino     return true;
539*e4b17023SJohn Marino 
540*e4b17023SJohn Marino   return false;
541*e4b17023SJohn Marino }
542*e4b17023SJohn Marino 
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino /* Given NAME, if NAME is defined by a unary operation OPCODE, return the
545*e4b17023SJohn Marino    operand of the negate operation.  Otherwise, return NULL.  */
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino static tree
548*e4b17023SJohn Marino get_unary_op (tree name, enum tree_code opcode)
549*e4b17023SJohn Marino {
550*e4b17023SJohn Marino   gimple stmt = SSA_NAME_DEF_STMT (name);
551*e4b17023SJohn Marino 
552*e4b17023SJohn Marino   if (!is_gimple_assign (stmt))
553*e4b17023SJohn Marino     return NULL_TREE;
554*e4b17023SJohn Marino 
555*e4b17023SJohn Marino   if (gimple_assign_rhs_code (stmt) == opcode)
556*e4b17023SJohn Marino     return gimple_assign_rhs1 (stmt);
557*e4b17023SJohn Marino   return NULL_TREE;
558*e4b17023SJohn Marino }
559*e4b17023SJohn Marino 
560*e4b17023SJohn Marino /* If CURR and LAST are a pair of ops that OPCODE allows us to
561*e4b17023SJohn Marino    eliminate through equivalences, do so, remove them from OPS, and
562*e4b17023SJohn Marino    return true.  Otherwise, return false.  */
563*e4b17023SJohn Marino 
564*e4b17023SJohn Marino static bool
565*e4b17023SJohn Marino eliminate_duplicate_pair (enum tree_code opcode,
566*e4b17023SJohn Marino 			  VEC (operand_entry_t, heap) **ops,
567*e4b17023SJohn Marino 			  bool *all_done,
568*e4b17023SJohn Marino 			  unsigned int i,
569*e4b17023SJohn Marino 			  operand_entry_t curr,
570*e4b17023SJohn Marino 			  operand_entry_t last)
571*e4b17023SJohn Marino {
572*e4b17023SJohn Marino 
573*e4b17023SJohn Marino   /* If we have two of the same op, and the opcode is & |, min, or max,
574*e4b17023SJohn Marino      we can eliminate one of them.
575*e4b17023SJohn Marino      If we have two of the same op, and the opcode is ^, we can
576*e4b17023SJohn Marino      eliminate both of them.  */
577*e4b17023SJohn Marino 
578*e4b17023SJohn Marino   if (last && last->op == curr->op)
579*e4b17023SJohn Marino     {
580*e4b17023SJohn Marino       switch (opcode)
581*e4b17023SJohn Marino 	{
582*e4b17023SJohn Marino 	case MAX_EXPR:
583*e4b17023SJohn Marino 	case MIN_EXPR:
584*e4b17023SJohn Marino 	case BIT_IOR_EXPR:
585*e4b17023SJohn Marino 	case BIT_AND_EXPR:
586*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
587*e4b17023SJohn Marino 	    {
588*e4b17023SJohn Marino 	      fprintf (dump_file, "Equivalence: ");
589*e4b17023SJohn Marino 	      print_generic_expr (dump_file, curr->op, 0);
590*e4b17023SJohn Marino 	      fprintf (dump_file, " [&|minmax] ");
591*e4b17023SJohn Marino 	      print_generic_expr (dump_file, last->op, 0);
592*e4b17023SJohn Marino 	      fprintf (dump_file, " -> ");
593*e4b17023SJohn Marino 	      print_generic_stmt (dump_file, last->op, 0);
594*e4b17023SJohn Marino 	    }
595*e4b17023SJohn Marino 
596*e4b17023SJohn Marino 	  VEC_ordered_remove (operand_entry_t, *ops, i);
597*e4b17023SJohn Marino 	  reassociate_stats.ops_eliminated ++;
598*e4b17023SJohn Marino 
599*e4b17023SJohn Marino 	  return true;
600*e4b17023SJohn Marino 
601*e4b17023SJohn Marino 	case BIT_XOR_EXPR:
602*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
603*e4b17023SJohn Marino 	    {
604*e4b17023SJohn Marino 	      fprintf (dump_file, "Equivalence: ");
605*e4b17023SJohn Marino 	      print_generic_expr (dump_file, curr->op, 0);
606*e4b17023SJohn Marino 	      fprintf (dump_file, " ^ ");
607*e4b17023SJohn Marino 	      print_generic_expr (dump_file, last->op, 0);
608*e4b17023SJohn Marino 	      fprintf (dump_file, " -> nothing\n");
609*e4b17023SJohn Marino 	    }
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino 	  reassociate_stats.ops_eliminated += 2;
612*e4b17023SJohn Marino 
613*e4b17023SJohn Marino 	  if (VEC_length (operand_entry_t, *ops) == 2)
614*e4b17023SJohn Marino 	    {
615*e4b17023SJohn Marino 	      VEC_free (operand_entry_t, heap, *ops);
616*e4b17023SJohn Marino 	      *ops = NULL;
617*e4b17023SJohn Marino 	      add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (last->op)));
618*e4b17023SJohn Marino 	      *all_done = true;
619*e4b17023SJohn Marino 	    }
620*e4b17023SJohn Marino 	  else
621*e4b17023SJohn Marino 	    {
622*e4b17023SJohn Marino 	      VEC_ordered_remove (operand_entry_t, *ops, i-1);
623*e4b17023SJohn Marino 	      VEC_ordered_remove (operand_entry_t, *ops, i-1);
624*e4b17023SJohn Marino 	    }
625*e4b17023SJohn Marino 
626*e4b17023SJohn Marino 	  return true;
627*e4b17023SJohn Marino 
628*e4b17023SJohn Marino 	default:
629*e4b17023SJohn Marino 	  break;
630*e4b17023SJohn Marino 	}
631*e4b17023SJohn Marino     }
632*e4b17023SJohn Marino   return false;
633*e4b17023SJohn Marino }
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino static VEC(tree, heap) *plus_negates;
636*e4b17023SJohn Marino 
637*e4b17023SJohn Marino /* If OPCODE is PLUS_EXPR, CURR->OP is a negate expression or a bitwise not
638*e4b17023SJohn Marino    expression, look in OPS for a corresponding positive operation to cancel
639*e4b17023SJohn Marino    it out.  If we find one, remove the other from OPS, replace
640*e4b17023SJohn Marino    OPS[CURRINDEX] with 0 or -1, respectively, and return true.  Otherwise,
641*e4b17023SJohn Marino    return false. */
642*e4b17023SJohn Marino 
643*e4b17023SJohn Marino static bool
644*e4b17023SJohn Marino eliminate_plus_minus_pair (enum tree_code opcode,
645*e4b17023SJohn Marino 			   VEC (operand_entry_t, heap) **ops,
646*e4b17023SJohn Marino 			   unsigned int currindex,
647*e4b17023SJohn Marino 			   operand_entry_t curr)
648*e4b17023SJohn Marino {
649*e4b17023SJohn Marino   tree negateop;
650*e4b17023SJohn Marino   tree notop;
651*e4b17023SJohn Marino   unsigned int i;
652*e4b17023SJohn Marino   operand_entry_t oe;
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino   if (opcode != PLUS_EXPR || TREE_CODE (curr->op) != SSA_NAME)
655*e4b17023SJohn Marino     return false;
656*e4b17023SJohn Marino 
657*e4b17023SJohn Marino   negateop = get_unary_op (curr->op, NEGATE_EXPR);
658*e4b17023SJohn Marino   notop = get_unary_op (curr->op, BIT_NOT_EXPR);
659*e4b17023SJohn Marino   if (negateop == NULL_TREE && notop == NULL_TREE)
660*e4b17023SJohn Marino     return false;
661*e4b17023SJohn Marino 
662*e4b17023SJohn Marino   /* Any non-negated version will have a rank that is one less than
663*e4b17023SJohn Marino      the current rank.  So once we hit those ranks, if we don't find
664*e4b17023SJohn Marino      one, we can stop.  */
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino   for (i = currindex + 1;
667*e4b17023SJohn Marino        VEC_iterate (operand_entry_t, *ops, i, oe)
668*e4b17023SJohn Marino        && oe->rank >= curr->rank - 1 ;
669*e4b17023SJohn Marino        i++)
670*e4b17023SJohn Marino     {
671*e4b17023SJohn Marino       if (oe->op == negateop)
672*e4b17023SJohn Marino 	{
673*e4b17023SJohn Marino 
674*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
675*e4b17023SJohn Marino 	    {
676*e4b17023SJohn Marino 	      fprintf (dump_file, "Equivalence: ");
677*e4b17023SJohn Marino 	      print_generic_expr (dump_file, negateop, 0);
678*e4b17023SJohn Marino 	      fprintf (dump_file, " + -");
679*e4b17023SJohn Marino 	      print_generic_expr (dump_file, oe->op, 0);
680*e4b17023SJohn Marino 	      fprintf (dump_file, " -> 0\n");
681*e4b17023SJohn Marino 	    }
682*e4b17023SJohn Marino 
683*e4b17023SJohn Marino 	  VEC_ordered_remove (operand_entry_t, *ops, i);
684*e4b17023SJohn Marino 	  add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (oe->op)));
685*e4b17023SJohn Marino 	  VEC_ordered_remove (operand_entry_t, *ops, currindex);
686*e4b17023SJohn Marino 	  reassociate_stats.ops_eliminated ++;
687*e4b17023SJohn Marino 
688*e4b17023SJohn Marino 	  return true;
689*e4b17023SJohn Marino 	}
690*e4b17023SJohn Marino       else if (oe->op == notop)
691*e4b17023SJohn Marino 	{
692*e4b17023SJohn Marino 	  tree op_type = TREE_TYPE (oe->op);
693*e4b17023SJohn Marino 
694*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
695*e4b17023SJohn Marino 	    {
696*e4b17023SJohn Marino 	      fprintf (dump_file, "Equivalence: ");
697*e4b17023SJohn Marino 	      print_generic_expr (dump_file, notop, 0);
698*e4b17023SJohn Marino 	      fprintf (dump_file, " + ~");
699*e4b17023SJohn Marino 	      print_generic_expr (dump_file, oe->op, 0);
700*e4b17023SJohn Marino 	      fprintf (dump_file, " -> -1\n");
701*e4b17023SJohn Marino 	    }
702*e4b17023SJohn Marino 
703*e4b17023SJohn Marino 	  VEC_ordered_remove (operand_entry_t, *ops, i);
704*e4b17023SJohn Marino 	  add_to_ops_vec (ops, build_int_cst_type (op_type, -1));
705*e4b17023SJohn Marino 	  VEC_ordered_remove (operand_entry_t, *ops, currindex);
706*e4b17023SJohn Marino 	  reassociate_stats.ops_eliminated ++;
707*e4b17023SJohn Marino 
708*e4b17023SJohn Marino 	  return true;
709*e4b17023SJohn Marino 	}
710*e4b17023SJohn Marino     }
711*e4b17023SJohn Marino 
712*e4b17023SJohn Marino   /* CURR->OP is a negate expr in a plus expr: save it for later
713*e4b17023SJohn Marino      inspection in repropagate_negates().  */
714*e4b17023SJohn Marino   if (negateop != NULL_TREE)
715*e4b17023SJohn Marino     VEC_safe_push (tree, heap, plus_negates, curr->op);
716*e4b17023SJohn Marino 
717*e4b17023SJohn Marino   return false;
718*e4b17023SJohn Marino }
719*e4b17023SJohn Marino 
720*e4b17023SJohn Marino /* If OPCODE is BIT_IOR_EXPR, BIT_AND_EXPR, and, CURR->OP is really a
721*e4b17023SJohn Marino    bitwise not expression, look in OPS for a corresponding operand to
722*e4b17023SJohn Marino    cancel it out.  If we find one, remove the other from OPS, replace
723*e4b17023SJohn Marino    OPS[CURRINDEX] with 0, and return true.  Otherwise, return
724*e4b17023SJohn Marino    false. */
725*e4b17023SJohn Marino 
726*e4b17023SJohn Marino static bool
727*e4b17023SJohn Marino eliminate_not_pairs (enum tree_code opcode,
728*e4b17023SJohn Marino 		     VEC (operand_entry_t, heap) **ops,
729*e4b17023SJohn Marino 		     unsigned int currindex,
730*e4b17023SJohn Marino 		     operand_entry_t curr)
731*e4b17023SJohn Marino {
732*e4b17023SJohn Marino   tree notop;
733*e4b17023SJohn Marino   unsigned int i;
734*e4b17023SJohn Marino   operand_entry_t oe;
735*e4b17023SJohn Marino 
736*e4b17023SJohn Marino   if ((opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
737*e4b17023SJohn Marino       || TREE_CODE (curr->op) != SSA_NAME)
738*e4b17023SJohn Marino     return false;
739*e4b17023SJohn Marino 
740*e4b17023SJohn Marino   notop = get_unary_op (curr->op, BIT_NOT_EXPR);
741*e4b17023SJohn Marino   if (notop == NULL_TREE)
742*e4b17023SJohn Marino     return false;
743*e4b17023SJohn Marino 
744*e4b17023SJohn Marino   /* Any non-not version will have a rank that is one less than
745*e4b17023SJohn Marino      the current rank.  So once we hit those ranks, if we don't find
746*e4b17023SJohn Marino      one, we can stop.  */
747*e4b17023SJohn Marino 
748*e4b17023SJohn Marino   for (i = currindex + 1;
749*e4b17023SJohn Marino        VEC_iterate (operand_entry_t, *ops, i, oe)
750*e4b17023SJohn Marino        && oe->rank >= curr->rank - 1;
751*e4b17023SJohn Marino        i++)
752*e4b17023SJohn Marino     {
753*e4b17023SJohn Marino       if (oe->op == notop)
754*e4b17023SJohn Marino 	{
755*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
756*e4b17023SJohn Marino 	    {
757*e4b17023SJohn Marino 	      fprintf (dump_file, "Equivalence: ");
758*e4b17023SJohn Marino 	      print_generic_expr (dump_file, notop, 0);
759*e4b17023SJohn Marino 	      if (opcode == BIT_AND_EXPR)
760*e4b17023SJohn Marino 		fprintf (dump_file, " & ~");
761*e4b17023SJohn Marino 	      else if (opcode == BIT_IOR_EXPR)
762*e4b17023SJohn Marino 		fprintf (dump_file, " | ~");
763*e4b17023SJohn Marino 	      print_generic_expr (dump_file, oe->op, 0);
764*e4b17023SJohn Marino 	      if (opcode == BIT_AND_EXPR)
765*e4b17023SJohn Marino 		fprintf (dump_file, " -> 0\n");
766*e4b17023SJohn Marino 	      else if (opcode == BIT_IOR_EXPR)
767*e4b17023SJohn Marino 		fprintf (dump_file, " -> -1\n");
768*e4b17023SJohn Marino 	    }
769*e4b17023SJohn Marino 
770*e4b17023SJohn Marino 	  if (opcode == BIT_AND_EXPR)
771*e4b17023SJohn Marino 	    oe->op = build_zero_cst (TREE_TYPE (oe->op));
772*e4b17023SJohn Marino 	  else if (opcode == BIT_IOR_EXPR)
773*e4b17023SJohn Marino 	    oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
774*e4b17023SJohn Marino 					  TYPE_PRECISION (TREE_TYPE (oe->op)));
775*e4b17023SJohn Marino 
776*e4b17023SJohn Marino 	  reassociate_stats.ops_eliminated
777*e4b17023SJohn Marino 	    += VEC_length (operand_entry_t, *ops) - 1;
778*e4b17023SJohn Marino 	  VEC_free (operand_entry_t, heap, *ops);
779*e4b17023SJohn Marino 	  *ops = NULL;
780*e4b17023SJohn Marino 	  VEC_safe_push (operand_entry_t, heap, *ops, oe);
781*e4b17023SJohn Marino 	  return true;
782*e4b17023SJohn Marino 	}
783*e4b17023SJohn Marino     }
784*e4b17023SJohn Marino 
785*e4b17023SJohn Marino   return false;
786*e4b17023SJohn Marino }
787*e4b17023SJohn Marino 
788*e4b17023SJohn Marino /* Use constant value that may be present in OPS to try to eliminate
789*e4b17023SJohn Marino    operands.  Note that this function is only really used when we've
790*e4b17023SJohn Marino    eliminated ops for other reasons, or merged constants.  Across
791*e4b17023SJohn Marino    single statements, fold already does all of this, plus more.  There
792*e4b17023SJohn Marino    is little point in duplicating logic, so I've only included the
793*e4b17023SJohn Marino    identities that I could ever construct testcases to trigger.  */
794*e4b17023SJohn Marino 
795*e4b17023SJohn Marino static void
796*e4b17023SJohn Marino eliminate_using_constants (enum tree_code opcode,
797*e4b17023SJohn Marino 			   VEC(operand_entry_t, heap) **ops)
798*e4b17023SJohn Marino {
799*e4b17023SJohn Marino   operand_entry_t oelast = VEC_last (operand_entry_t, *ops);
800*e4b17023SJohn Marino   tree type = TREE_TYPE (oelast->op);
801*e4b17023SJohn Marino 
802*e4b17023SJohn Marino   if (oelast->rank == 0
803*e4b17023SJohn Marino       && (INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type)))
804*e4b17023SJohn Marino     {
805*e4b17023SJohn Marino       switch (opcode)
806*e4b17023SJohn Marino 	{
807*e4b17023SJohn Marino 	case BIT_AND_EXPR:
808*e4b17023SJohn Marino 	  if (integer_zerop (oelast->op))
809*e4b17023SJohn Marino 	    {
810*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
811*e4b17023SJohn Marino 		{
812*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
813*e4b17023SJohn Marino 		    fprintf (dump_file, "Found & 0, removing all other ops\n");
814*e4b17023SJohn Marino 
815*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated
816*e4b17023SJohn Marino 		    += VEC_length (operand_entry_t, *ops) - 1;
817*e4b17023SJohn Marino 
818*e4b17023SJohn Marino 		  VEC_free (operand_entry_t, heap, *ops);
819*e4b17023SJohn Marino 		  *ops = NULL;
820*e4b17023SJohn Marino 		  VEC_safe_push (operand_entry_t, heap, *ops, oelast);
821*e4b17023SJohn Marino 		  return;
822*e4b17023SJohn Marino 		}
823*e4b17023SJohn Marino 	    }
824*e4b17023SJohn Marino 	  else if (integer_all_onesp (oelast->op))
825*e4b17023SJohn Marino 	    {
826*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
827*e4b17023SJohn Marino 		{
828*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
829*e4b17023SJohn Marino 		    fprintf (dump_file, "Found & -1, removing\n");
830*e4b17023SJohn Marino 		  VEC_pop (operand_entry_t, *ops);
831*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated++;
832*e4b17023SJohn Marino 		}
833*e4b17023SJohn Marino 	    }
834*e4b17023SJohn Marino 	  break;
835*e4b17023SJohn Marino 	case BIT_IOR_EXPR:
836*e4b17023SJohn Marino 	  if (integer_all_onesp (oelast->op))
837*e4b17023SJohn Marino 	    {
838*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
839*e4b17023SJohn Marino 		{
840*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
841*e4b17023SJohn Marino 		    fprintf (dump_file, "Found | -1, removing all other ops\n");
842*e4b17023SJohn Marino 
843*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated
844*e4b17023SJohn Marino 		    += VEC_length (operand_entry_t, *ops) - 1;
845*e4b17023SJohn Marino 
846*e4b17023SJohn Marino 		  VEC_free (operand_entry_t, heap, *ops);
847*e4b17023SJohn Marino 		  *ops = NULL;
848*e4b17023SJohn Marino 		  VEC_safe_push (operand_entry_t, heap, *ops, oelast);
849*e4b17023SJohn Marino 		  return;
850*e4b17023SJohn Marino 		}
851*e4b17023SJohn Marino 	    }
852*e4b17023SJohn Marino 	  else if (integer_zerop (oelast->op))
853*e4b17023SJohn Marino 	    {
854*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
855*e4b17023SJohn Marino 		{
856*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
857*e4b17023SJohn Marino 		    fprintf (dump_file, "Found | 0, removing\n");
858*e4b17023SJohn Marino 		  VEC_pop (operand_entry_t, *ops);
859*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated++;
860*e4b17023SJohn Marino 		}
861*e4b17023SJohn Marino 	    }
862*e4b17023SJohn Marino 	  break;
863*e4b17023SJohn Marino 	case MULT_EXPR:
864*e4b17023SJohn Marino 	  if (integer_zerop (oelast->op)
865*e4b17023SJohn Marino 	      || (FLOAT_TYPE_P (type)
866*e4b17023SJohn Marino 		  && !HONOR_NANS (TYPE_MODE (type))
867*e4b17023SJohn Marino 		  && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
868*e4b17023SJohn Marino 		  && real_zerop (oelast->op)))
869*e4b17023SJohn Marino 	    {
870*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
871*e4b17023SJohn Marino 		{
872*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
873*e4b17023SJohn Marino 		    fprintf (dump_file, "Found * 0, removing all other ops\n");
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated
876*e4b17023SJohn Marino 		    += VEC_length (operand_entry_t, *ops) - 1;
877*e4b17023SJohn Marino 		  VEC_free (operand_entry_t, heap, *ops);
878*e4b17023SJohn Marino 		  *ops = NULL;
879*e4b17023SJohn Marino 		  VEC_safe_push (operand_entry_t, heap, *ops, oelast);
880*e4b17023SJohn Marino 		  return;
881*e4b17023SJohn Marino 		}
882*e4b17023SJohn Marino 	    }
883*e4b17023SJohn Marino 	  else if (integer_onep (oelast->op)
884*e4b17023SJohn Marino 		   || (FLOAT_TYPE_P (type)
885*e4b17023SJohn Marino 		       && !HONOR_SNANS (TYPE_MODE (type))
886*e4b17023SJohn Marino 		       && real_onep (oelast->op)))
887*e4b17023SJohn Marino 	    {
888*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
889*e4b17023SJohn Marino 		{
890*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
891*e4b17023SJohn Marino 		    fprintf (dump_file, "Found * 1, removing\n");
892*e4b17023SJohn Marino 		  VEC_pop (operand_entry_t, *ops);
893*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated++;
894*e4b17023SJohn Marino 		  return;
895*e4b17023SJohn Marino 		}
896*e4b17023SJohn Marino 	    }
897*e4b17023SJohn Marino 	  break;
898*e4b17023SJohn Marino 	case BIT_XOR_EXPR:
899*e4b17023SJohn Marino 	case PLUS_EXPR:
900*e4b17023SJohn Marino 	case MINUS_EXPR:
901*e4b17023SJohn Marino 	  if (integer_zerop (oelast->op)
902*e4b17023SJohn Marino 	      || (FLOAT_TYPE_P (type)
903*e4b17023SJohn Marino 		  && (opcode == PLUS_EXPR || opcode == MINUS_EXPR)
904*e4b17023SJohn Marino 		  && fold_real_zero_addition_p (type, oelast->op,
905*e4b17023SJohn Marino 						opcode == MINUS_EXPR)))
906*e4b17023SJohn Marino 	    {
907*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, *ops) != 1)
908*e4b17023SJohn Marino 		{
909*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
910*e4b17023SJohn Marino 		    fprintf (dump_file, "Found [|^+] 0, removing\n");
911*e4b17023SJohn Marino 		  VEC_pop (operand_entry_t, *ops);
912*e4b17023SJohn Marino 		  reassociate_stats.ops_eliminated++;
913*e4b17023SJohn Marino 		  return;
914*e4b17023SJohn Marino 		}
915*e4b17023SJohn Marino 	    }
916*e4b17023SJohn Marino 	  break;
917*e4b17023SJohn Marino 	default:
918*e4b17023SJohn Marino 	  break;
919*e4b17023SJohn Marino 	}
920*e4b17023SJohn Marino     }
921*e4b17023SJohn Marino }
922*e4b17023SJohn Marino 
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino static void linearize_expr_tree (VEC(operand_entry_t, heap) **, gimple,
925*e4b17023SJohn Marino 				 bool, bool);
926*e4b17023SJohn Marino 
927*e4b17023SJohn Marino /* Structure for tracking and counting operands.  */
928*e4b17023SJohn Marino typedef struct oecount_s {
929*e4b17023SJohn Marino   int cnt;
930*e4b17023SJohn Marino   int id;
931*e4b17023SJohn Marino   enum tree_code oecode;
932*e4b17023SJohn Marino   tree op;
933*e4b17023SJohn Marino } oecount;
934*e4b17023SJohn Marino 
935*e4b17023SJohn Marino DEF_VEC_O(oecount);
936*e4b17023SJohn Marino DEF_VEC_ALLOC_O(oecount,heap);
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino /* The heap for the oecount hashtable and the sorted list of operands.  */
939*e4b17023SJohn Marino static VEC (oecount, heap) *cvec;
940*e4b17023SJohn Marino 
941*e4b17023SJohn Marino /* Hash function for oecount.  */
942*e4b17023SJohn Marino 
943*e4b17023SJohn Marino static hashval_t
944*e4b17023SJohn Marino oecount_hash (const void *p)
945*e4b17023SJohn Marino {
946*e4b17023SJohn Marino   const oecount *c = VEC_index (oecount, cvec, (size_t)p - 42);
947*e4b17023SJohn Marino   return htab_hash_pointer (c->op) ^ (hashval_t)c->oecode;
948*e4b17023SJohn Marino }
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino /* Comparison function for oecount.  */
951*e4b17023SJohn Marino 
952*e4b17023SJohn Marino static int
953*e4b17023SJohn Marino oecount_eq (const void *p1, const void *p2)
954*e4b17023SJohn Marino {
955*e4b17023SJohn Marino   const oecount *c1 = VEC_index (oecount, cvec, (size_t)p1 - 42);
956*e4b17023SJohn Marino   const oecount *c2 = VEC_index (oecount, cvec, (size_t)p2 - 42);
957*e4b17023SJohn Marino   return (c1->oecode == c2->oecode
958*e4b17023SJohn Marino 	  && c1->op == c2->op);
959*e4b17023SJohn Marino }
960*e4b17023SJohn Marino 
961*e4b17023SJohn Marino /* Comparison function for qsort sorting oecount elements by count.  */
962*e4b17023SJohn Marino 
963*e4b17023SJohn Marino static int
964*e4b17023SJohn Marino oecount_cmp (const void *p1, const void *p2)
965*e4b17023SJohn Marino {
966*e4b17023SJohn Marino   const oecount *c1 = (const oecount *)p1;
967*e4b17023SJohn Marino   const oecount *c2 = (const oecount *)p2;
968*e4b17023SJohn Marino   if (c1->cnt != c2->cnt)
969*e4b17023SJohn Marino     return c1->cnt - c2->cnt;
970*e4b17023SJohn Marino   else
971*e4b17023SJohn Marino     /* If counts are identical, use unique IDs to stabilize qsort.  */
972*e4b17023SJohn Marino     return c1->id - c2->id;
973*e4b17023SJohn Marino }
974*e4b17023SJohn Marino 
975*e4b17023SJohn Marino /* Walks the linear chain with result *DEF searching for an operation
976*e4b17023SJohn Marino    with operand OP and code OPCODE removing that from the chain.  *DEF
977*e4b17023SJohn Marino    is updated if there is only one operand but no operation left.  */
978*e4b17023SJohn Marino 
979*e4b17023SJohn Marino static void
980*e4b17023SJohn Marino zero_one_operation (tree *def, enum tree_code opcode, tree op)
981*e4b17023SJohn Marino {
982*e4b17023SJohn Marino   gimple stmt = SSA_NAME_DEF_STMT (*def);
983*e4b17023SJohn Marino 
984*e4b17023SJohn Marino   do
985*e4b17023SJohn Marino     {
986*e4b17023SJohn Marino       tree name = gimple_assign_rhs1 (stmt);
987*e4b17023SJohn Marino 
988*e4b17023SJohn Marino       /* If this is the operation we look for and one of the operands
989*e4b17023SJohn Marino          is ours simply propagate the other operand into the stmts
990*e4b17023SJohn Marino 	 single use.  */
991*e4b17023SJohn Marino       if (gimple_assign_rhs_code (stmt) == opcode
992*e4b17023SJohn Marino 	  && (name == op
993*e4b17023SJohn Marino 	      || gimple_assign_rhs2 (stmt) == op))
994*e4b17023SJohn Marino 	{
995*e4b17023SJohn Marino 	  gimple use_stmt;
996*e4b17023SJohn Marino 	  use_operand_p use;
997*e4b17023SJohn Marino 	  gimple_stmt_iterator gsi;
998*e4b17023SJohn Marino 	  if (name == op)
999*e4b17023SJohn Marino 	    name = gimple_assign_rhs2 (stmt);
1000*e4b17023SJohn Marino 	  gcc_assert (has_single_use (gimple_assign_lhs (stmt)));
1001*e4b17023SJohn Marino 	  single_imm_use (gimple_assign_lhs (stmt), &use, &use_stmt);
1002*e4b17023SJohn Marino 	  if (gimple_assign_lhs (stmt) == *def)
1003*e4b17023SJohn Marino 	    *def = name;
1004*e4b17023SJohn Marino 	  SET_USE (use, name);
1005*e4b17023SJohn Marino 	  if (TREE_CODE (name) != SSA_NAME)
1006*e4b17023SJohn Marino 	    update_stmt (use_stmt);
1007*e4b17023SJohn Marino 	  gsi = gsi_for_stmt (stmt);
1008*e4b17023SJohn Marino 	  gsi_remove (&gsi, true);
1009*e4b17023SJohn Marino 	  release_defs (stmt);
1010*e4b17023SJohn Marino 	  return;
1011*e4b17023SJohn Marino 	}
1012*e4b17023SJohn Marino 
1013*e4b17023SJohn Marino       /* Continue walking the chain.  */
1014*e4b17023SJohn Marino       gcc_assert (name != op
1015*e4b17023SJohn Marino 		  && TREE_CODE (name) == SSA_NAME);
1016*e4b17023SJohn Marino       stmt = SSA_NAME_DEF_STMT (name);
1017*e4b17023SJohn Marino     }
1018*e4b17023SJohn Marino   while (1);
1019*e4b17023SJohn Marino }
1020*e4b17023SJohn Marino 
1021*e4b17023SJohn Marino /* Builds one statement performing OP1 OPCODE OP2 using TMPVAR for
1022*e4b17023SJohn Marino    the result.  Places the statement after the definition of either
1023*e4b17023SJohn Marino    OP1 or OP2.  Returns the new statement.  */
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino static gimple
1026*e4b17023SJohn Marino build_and_add_sum (tree tmpvar, tree op1, tree op2, enum tree_code opcode)
1027*e4b17023SJohn Marino {
1028*e4b17023SJohn Marino   gimple op1def = NULL, op2def = NULL;
1029*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1030*e4b17023SJohn Marino   tree op;
1031*e4b17023SJohn Marino   gimple sum;
1032*e4b17023SJohn Marino 
1033*e4b17023SJohn Marino   /* Create the addition statement.  */
1034*e4b17023SJohn Marino   sum = gimple_build_assign_with_ops (opcode, tmpvar, op1, op2);
1035*e4b17023SJohn Marino   op = make_ssa_name (tmpvar, sum);
1036*e4b17023SJohn Marino   gimple_assign_set_lhs (sum, op);
1037*e4b17023SJohn Marino 
1038*e4b17023SJohn Marino   /* Find an insertion place and insert.  */
1039*e4b17023SJohn Marino   if (TREE_CODE (op1) == SSA_NAME)
1040*e4b17023SJohn Marino     op1def = SSA_NAME_DEF_STMT (op1);
1041*e4b17023SJohn Marino   if (TREE_CODE (op2) == SSA_NAME)
1042*e4b17023SJohn Marino     op2def = SSA_NAME_DEF_STMT (op2);
1043*e4b17023SJohn Marino   if ((!op1def || gimple_nop_p (op1def))
1044*e4b17023SJohn Marino       && (!op2def || gimple_nop_p (op2def)))
1045*e4b17023SJohn Marino     {
1046*e4b17023SJohn Marino       gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
1047*e4b17023SJohn Marino       gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
1048*e4b17023SJohn Marino     }
1049*e4b17023SJohn Marino   else if ((!op1def || gimple_nop_p (op1def))
1050*e4b17023SJohn Marino 	   || (op2def && !gimple_nop_p (op2def)
1051*e4b17023SJohn Marino 	       && stmt_dominates_stmt_p (op1def, op2def)))
1052*e4b17023SJohn Marino     {
1053*e4b17023SJohn Marino       if (gimple_code (op2def) == GIMPLE_PHI)
1054*e4b17023SJohn Marino 	{
1055*e4b17023SJohn Marino 	  gsi = gsi_after_labels (gimple_bb (op2def));
1056*e4b17023SJohn Marino 	  gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
1057*e4b17023SJohn Marino 	}
1058*e4b17023SJohn Marino       else
1059*e4b17023SJohn Marino 	{
1060*e4b17023SJohn Marino 	  if (!stmt_ends_bb_p (op2def))
1061*e4b17023SJohn Marino 	    {
1062*e4b17023SJohn Marino 	      gsi = gsi_for_stmt (op2def);
1063*e4b17023SJohn Marino 	      gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
1064*e4b17023SJohn Marino 	    }
1065*e4b17023SJohn Marino 	  else
1066*e4b17023SJohn Marino 	    {
1067*e4b17023SJohn Marino 	      edge e;
1068*e4b17023SJohn Marino 	      edge_iterator ei;
1069*e4b17023SJohn Marino 
1070*e4b17023SJohn Marino 	      FOR_EACH_EDGE (e, ei, gimple_bb (op2def)->succs)
1071*e4b17023SJohn Marino 		if (e->flags & EDGE_FALLTHRU)
1072*e4b17023SJohn Marino 		  gsi_insert_on_edge_immediate (e, sum);
1073*e4b17023SJohn Marino 	    }
1074*e4b17023SJohn Marino 	}
1075*e4b17023SJohn Marino     }
1076*e4b17023SJohn Marino   else
1077*e4b17023SJohn Marino     {
1078*e4b17023SJohn Marino       if (gimple_code (op1def) == GIMPLE_PHI)
1079*e4b17023SJohn Marino 	{
1080*e4b17023SJohn Marino 	  gsi = gsi_after_labels (gimple_bb (op1def));
1081*e4b17023SJohn Marino 	  gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
1082*e4b17023SJohn Marino 	}
1083*e4b17023SJohn Marino       else
1084*e4b17023SJohn Marino 	{
1085*e4b17023SJohn Marino 	  if (!stmt_ends_bb_p (op1def))
1086*e4b17023SJohn Marino 	    {
1087*e4b17023SJohn Marino 	      gsi = gsi_for_stmt (op1def);
1088*e4b17023SJohn Marino 	      gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
1089*e4b17023SJohn Marino 	    }
1090*e4b17023SJohn Marino 	  else
1091*e4b17023SJohn Marino 	    {
1092*e4b17023SJohn Marino 	      edge e;
1093*e4b17023SJohn Marino 	      edge_iterator ei;
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino 	      FOR_EACH_EDGE (e, ei, gimple_bb (op1def)->succs)
1096*e4b17023SJohn Marino 		if (e->flags & EDGE_FALLTHRU)
1097*e4b17023SJohn Marino 		  gsi_insert_on_edge_immediate (e, sum);
1098*e4b17023SJohn Marino 	    }
1099*e4b17023SJohn Marino 	}
1100*e4b17023SJohn Marino     }
1101*e4b17023SJohn Marino   update_stmt (sum);
1102*e4b17023SJohn Marino 
1103*e4b17023SJohn Marino   return sum;
1104*e4b17023SJohn Marino }
1105*e4b17023SJohn Marino 
1106*e4b17023SJohn Marino /* Perform un-distribution of divisions and multiplications.
1107*e4b17023SJohn Marino    A * X + B * X is transformed into (A + B) * X and A / X + B / X
1108*e4b17023SJohn Marino    to (A + B) / X for real X.
1109*e4b17023SJohn Marino 
1110*e4b17023SJohn Marino    The algorithm is organized as follows.
1111*e4b17023SJohn Marino 
1112*e4b17023SJohn Marino     - First we walk the addition chain *OPS looking for summands that
1113*e4b17023SJohn Marino       are defined by a multiplication or a real division.  This results
1114*e4b17023SJohn Marino       in the candidates bitmap with relevant indices into *OPS.
1115*e4b17023SJohn Marino 
1116*e4b17023SJohn Marino     - Second we build the chains of multiplications or divisions for
1117*e4b17023SJohn Marino       these candidates, counting the number of occurences of (operand, code)
1118*e4b17023SJohn Marino       pairs in all of the candidates chains.
1119*e4b17023SJohn Marino 
1120*e4b17023SJohn Marino     - Third we sort the (operand, code) pairs by number of occurence and
1121*e4b17023SJohn Marino       process them starting with the pair with the most uses.
1122*e4b17023SJohn Marino 
1123*e4b17023SJohn Marino       * For each such pair we walk the candidates again to build a
1124*e4b17023SJohn Marino         second candidate bitmap noting all multiplication/division chains
1125*e4b17023SJohn Marino 	that have at least one occurence of (operand, code).
1126*e4b17023SJohn Marino 
1127*e4b17023SJohn Marino       * We build an alternate addition chain only covering these
1128*e4b17023SJohn Marino         candidates with one (operand, code) operation removed from their
1129*e4b17023SJohn Marino 	multiplication/division chain.
1130*e4b17023SJohn Marino 
1131*e4b17023SJohn Marino       * The first candidate gets replaced by the alternate addition chain
1132*e4b17023SJohn Marino         multiplied/divided by the operand.
1133*e4b17023SJohn Marino 
1134*e4b17023SJohn Marino       * All candidate chains get disabled for further processing and
1135*e4b17023SJohn Marino         processing of (operand, code) pairs continues.
1136*e4b17023SJohn Marino 
1137*e4b17023SJohn Marino   The alternate addition chains built are re-processed by the main
1138*e4b17023SJohn Marino   reassociation algorithm which allows optimizing a * x * y + b * y * x
1139*e4b17023SJohn Marino   to (a + b ) * x * y in one invocation of the reassociation pass.  */
1140*e4b17023SJohn Marino 
1141*e4b17023SJohn Marino static bool
1142*e4b17023SJohn Marino undistribute_ops_list (enum tree_code opcode,
1143*e4b17023SJohn Marino 		       VEC (operand_entry_t, heap) **ops, struct loop *loop)
1144*e4b17023SJohn Marino {
1145*e4b17023SJohn Marino   unsigned int length = VEC_length (operand_entry_t, *ops);
1146*e4b17023SJohn Marino   operand_entry_t oe1;
1147*e4b17023SJohn Marino   unsigned i, j;
1148*e4b17023SJohn Marino   sbitmap candidates, candidates2;
1149*e4b17023SJohn Marino   unsigned nr_candidates, nr_candidates2;
1150*e4b17023SJohn Marino   sbitmap_iterator sbi0;
1151*e4b17023SJohn Marino   VEC (operand_entry_t, heap) **subops;
1152*e4b17023SJohn Marino   htab_t ctable;
1153*e4b17023SJohn Marino   bool changed = false;
1154*e4b17023SJohn Marino   int next_oecount_id = 0;
1155*e4b17023SJohn Marino 
1156*e4b17023SJohn Marino   if (length <= 1
1157*e4b17023SJohn Marino       || opcode != PLUS_EXPR)
1158*e4b17023SJohn Marino     return false;
1159*e4b17023SJohn Marino 
1160*e4b17023SJohn Marino   /* Build a list of candidates to process.  */
1161*e4b17023SJohn Marino   candidates = sbitmap_alloc (length);
1162*e4b17023SJohn Marino   sbitmap_zero (candidates);
1163*e4b17023SJohn Marino   nr_candidates = 0;
1164*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (operand_entry_t, *ops, i, oe1)
1165*e4b17023SJohn Marino     {
1166*e4b17023SJohn Marino       enum tree_code dcode;
1167*e4b17023SJohn Marino       gimple oe1def;
1168*e4b17023SJohn Marino 
1169*e4b17023SJohn Marino       if (TREE_CODE (oe1->op) != SSA_NAME)
1170*e4b17023SJohn Marino 	continue;
1171*e4b17023SJohn Marino       oe1def = SSA_NAME_DEF_STMT (oe1->op);
1172*e4b17023SJohn Marino       if (!is_gimple_assign (oe1def))
1173*e4b17023SJohn Marino 	continue;
1174*e4b17023SJohn Marino       dcode = gimple_assign_rhs_code (oe1def);
1175*e4b17023SJohn Marino       if ((dcode != MULT_EXPR
1176*e4b17023SJohn Marino 	   && dcode != RDIV_EXPR)
1177*e4b17023SJohn Marino 	  || !is_reassociable_op (oe1def, dcode, loop))
1178*e4b17023SJohn Marino 	continue;
1179*e4b17023SJohn Marino 
1180*e4b17023SJohn Marino       SET_BIT (candidates, i);
1181*e4b17023SJohn Marino       nr_candidates++;
1182*e4b17023SJohn Marino     }
1183*e4b17023SJohn Marino 
1184*e4b17023SJohn Marino   if (nr_candidates < 2)
1185*e4b17023SJohn Marino     {
1186*e4b17023SJohn Marino       sbitmap_free (candidates);
1187*e4b17023SJohn Marino       return false;
1188*e4b17023SJohn Marino     }
1189*e4b17023SJohn Marino 
1190*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1191*e4b17023SJohn Marino     {
1192*e4b17023SJohn Marino       fprintf (dump_file, "searching for un-distribute opportunities ");
1193*e4b17023SJohn Marino       print_generic_expr (dump_file,
1194*e4b17023SJohn Marino 	VEC_index (operand_entry_t, *ops,
1195*e4b17023SJohn Marino 		   sbitmap_first_set_bit (candidates))->op, 0);
1196*e4b17023SJohn Marino       fprintf (dump_file, " %d\n", nr_candidates);
1197*e4b17023SJohn Marino     }
1198*e4b17023SJohn Marino 
1199*e4b17023SJohn Marino   /* Build linearized sub-operand lists and the counting table.  */
1200*e4b17023SJohn Marino   cvec = NULL;
1201*e4b17023SJohn Marino   ctable = htab_create (15, oecount_hash, oecount_eq, NULL);
1202*e4b17023SJohn Marino   subops = XCNEWVEC (VEC (operand_entry_t, heap) *,
1203*e4b17023SJohn Marino 		     VEC_length (operand_entry_t, *ops));
1204*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_SBITMAP (candidates, 0, i, sbi0)
1205*e4b17023SJohn Marino     {
1206*e4b17023SJohn Marino       gimple oedef;
1207*e4b17023SJohn Marino       enum tree_code oecode;
1208*e4b17023SJohn Marino       unsigned j;
1209*e4b17023SJohn Marino 
1210*e4b17023SJohn Marino       oedef = SSA_NAME_DEF_STMT (VEC_index (operand_entry_t, *ops, i)->op);
1211*e4b17023SJohn Marino       oecode = gimple_assign_rhs_code (oedef);
1212*e4b17023SJohn Marino       linearize_expr_tree (&subops[i], oedef,
1213*e4b17023SJohn Marino 			   associative_tree_code (oecode), false);
1214*e4b17023SJohn Marino 
1215*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
1216*e4b17023SJohn Marino 	{
1217*e4b17023SJohn Marino 	  oecount c;
1218*e4b17023SJohn Marino 	  void **slot;
1219*e4b17023SJohn Marino 	  size_t idx;
1220*e4b17023SJohn Marino 	  c.oecode = oecode;
1221*e4b17023SJohn Marino 	  c.cnt = 1;
1222*e4b17023SJohn Marino 	  c.id = next_oecount_id++;
1223*e4b17023SJohn Marino 	  c.op = oe1->op;
1224*e4b17023SJohn Marino 	  VEC_safe_push (oecount, heap, cvec, &c);
1225*e4b17023SJohn Marino 	  idx = VEC_length (oecount, cvec) + 41;
1226*e4b17023SJohn Marino 	  slot = htab_find_slot (ctable, (void *)idx, INSERT);
1227*e4b17023SJohn Marino 	  if (!*slot)
1228*e4b17023SJohn Marino 	    {
1229*e4b17023SJohn Marino 	      *slot = (void *)idx;
1230*e4b17023SJohn Marino 	    }
1231*e4b17023SJohn Marino 	  else
1232*e4b17023SJohn Marino 	    {
1233*e4b17023SJohn Marino 	      VEC_pop (oecount, cvec);
1234*e4b17023SJohn Marino 	      VEC_index (oecount, cvec, (size_t)*slot - 42)->cnt++;
1235*e4b17023SJohn Marino 	    }
1236*e4b17023SJohn Marino 	}
1237*e4b17023SJohn Marino     }
1238*e4b17023SJohn Marino   htab_delete (ctable);
1239*e4b17023SJohn Marino 
1240*e4b17023SJohn Marino   /* Sort the counting table.  */
1241*e4b17023SJohn Marino   VEC_qsort (oecount, cvec, oecount_cmp);
1242*e4b17023SJohn Marino 
1243*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1244*e4b17023SJohn Marino     {
1245*e4b17023SJohn Marino       oecount *c;
1246*e4b17023SJohn Marino       fprintf (dump_file, "Candidates:\n");
1247*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (oecount, cvec, j, c)
1248*e4b17023SJohn Marino 	{
1249*e4b17023SJohn Marino 	  fprintf (dump_file, "  %u %s: ", c->cnt,
1250*e4b17023SJohn Marino 		   c->oecode == MULT_EXPR
1251*e4b17023SJohn Marino 		   ? "*" : c->oecode == RDIV_EXPR ? "/" : "?");
1252*e4b17023SJohn Marino 	  print_generic_expr (dump_file, c->op, 0);
1253*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
1254*e4b17023SJohn Marino 	}
1255*e4b17023SJohn Marino     }
1256*e4b17023SJohn Marino 
1257*e4b17023SJohn Marino   /* Process the (operand, code) pairs in order of most occurence.  */
1258*e4b17023SJohn Marino   candidates2 = sbitmap_alloc (length);
1259*e4b17023SJohn Marino   while (!VEC_empty (oecount, cvec))
1260*e4b17023SJohn Marino     {
1261*e4b17023SJohn Marino       oecount *c = VEC_last (oecount, cvec);
1262*e4b17023SJohn Marino       if (c->cnt < 2)
1263*e4b17023SJohn Marino 	break;
1264*e4b17023SJohn Marino 
1265*e4b17023SJohn Marino       /* Now collect the operands in the outer chain that contain
1266*e4b17023SJohn Marino          the common operand in their inner chain.  */
1267*e4b17023SJohn Marino       sbitmap_zero (candidates2);
1268*e4b17023SJohn Marino       nr_candidates2 = 0;
1269*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_SBITMAP (candidates, 0, i, sbi0)
1270*e4b17023SJohn Marino 	{
1271*e4b17023SJohn Marino 	  gimple oedef;
1272*e4b17023SJohn Marino 	  enum tree_code oecode;
1273*e4b17023SJohn Marino 	  unsigned j;
1274*e4b17023SJohn Marino 	  tree op = VEC_index (operand_entry_t, *ops, i)->op;
1275*e4b17023SJohn Marino 
1276*e4b17023SJohn Marino 	  /* If we undistributed in this chain already this may be
1277*e4b17023SJohn Marino 	     a constant.  */
1278*e4b17023SJohn Marino 	  if (TREE_CODE (op) != SSA_NAME)
1279*e4b17023SJohn Marino 	    continue;
1280*e4b17023SJohn Marino 
1281*e4b17023SJohn Marino 	  oedef = SSA_NAME_DEF_STMT (op);
1282*e4b17023SJohn Marino 	  oecode = gimple_assign_rhs_code (oedef);
1283*e4b17023SJohn Marino 	  if (oecode != c->oecode)
1284*e4b17023SJohn Marino 	    continue;
1285*e4b17023SJohn Marino 
1286*e4b17023SJohn Marino 	  FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
1287*e4b17023SJohn Marino 	    {
1288*e4b17023SJohn Marino 	      if (oe1->op == c->op)
1289*e4b17023SJohn Marino 		{
1290*e4b17023SJohn Marino 		  SET_BIT (candidates2, i);
1291*e4b17023SJohn Marino 		  ++nr_candidates2;
1292*e4b17023SJohn Marino 		  break;
1293*e4b17023SJohn Marino 		}
1294*e4b17023SJohn Marino 	    }
1295*e4b17023SJohn Marino 	}
1296*e4b17023SJohn Marino 
1297*e4b17023SJohn Marino       if (nr_candidates2 >= 2)
1298*e4b17023SJohn Marino 	{
1299*e4b17023SJohn Marino 	  operand_entry_t oe1, oe2;
1300*e4b17023SJohn Marino 	  tree tmpvar;
1301*e4b17023SJohn Marino 	  gimple prod;
1302*e4b17023SJohn Marino 	  int first = sbitmap_first_set_bit (candidates2);
1303*e4b17023SJohn Marino 
1304*e4b17023SJohn Marino 	  /* Build the new addition chain.  */
1305*e4b17023SJohn Marino 	  oe1 = VEC_index (operand_entry_t, *ops, first);
1306*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
1307*e4b17023SJohn Marino 	    {
1308*e4b17023SJohn Marino 	      fprintf (dump_file, "Building (");
1309*e4b17023SJohn Marino 	      print_generic_expr (dump_file, oe1->op, 0);
1310*e4b17023SJohn Marino 	    }
1311*e4b17023SJohn Marino 	  tmpvar = create_tmp_reg (TREE_TYPE (oe1->op), NULL);
1312*e4b17023SJohn Marino 	  add_referenced_var (tmpvar);
1313*e4b17023SJohn Marino 	  zero_one_operation (&oe1->op, c->oecode, c->op);
1314*e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_SBITMAP (candidates2, first+1, i, sbi0)
1315*e4b17023SJohn Marino 	    {
1316*e4b17023SJohn Marino 	      gimple sum;
1317*e4b17023SJohn Marino 	      oe2 = VEC_index (operand_entry_t, *ops, i);
1318*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1319*e4b17023SJohn Marino 		{
1320*e4b17023SJohn Marino 		  fprintf (dump_file, " + ");
1321*e4b17023SJohn Marino 		  print_generic_expr (dump_file, oe2->op, 0);
1322*e4b17023SJohn Marino 		}
1323*e4b17023SJohn Marino 	      zero_one_operation (&oe2->op, c->oecode, c->op);
1324*e4b17023SJohn Marino 	      sum = build_and_add_sum (tmpvar, oe1->op, oe2->op, opcode);
1325*e4b17023SJohn Marino 	      oe2->op = build_zero_cst (TREE_TYPE (oe2->op));
1326*e4b17023SJohn Marino 	      oe2->rank = 0;
1327*e4b17023SJohn Marino 	      oe1->op = gimple_get_lhs (sum);
1328*e4b17023SJohn Marino 	    }
1329*e4b17023SJohn Marino 
1330*e4b17023SJohn Marino 	  /* Apply the multiplication/division.  */
1331*e4b17023SJohn Marino 	  prod = build_and_add_sum (tmpvar, oe1->op, c->op, c->oecode);
1332*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
1333*e4b17023SJohn Marino 	    {
1334*e4b17023SJohn Marino 	      fprintf (dump_file, ") %s ", c->oecode == MULT_EXPR ? "*" : "/");
1335*e4b17023SJohn Marino 	      print_generic_expr (dump_file, c->op, 0);
1336*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1337*e4b17023SJohn Marino 	    }
1338*e4b17023SJohn Marino 
1339*e4b17023SJohn Marino 	  /* Record it in the addition chain and disable further
1340*e4b17023SJohn Marino 	     undistribution with this op.  */
1341*e4b17023SJohn Marino 	  oe1->op = gimple_assign_lhs (prod);
1342*e4b17023SJohn Marino 	  oe1->rank = get_rank (oe1->op);
1343*e4b17023SJohn Marino 	  VEC_free (operand_entry_t, heap, subops[first]);
1344*e4b17023SJohn Marino 
1345*e4b17023SJohn Marino 	  changed = true;
1346*e4b17023SJohn Marino 	}
1347*e4b17023SJohn Marino 
1348*e4b17023SJohn Marino       VEC_pop (oecount, cvec);
1349*e4b17023SJohn Marino     }
1350*e4b17023SJohn Marino 
1351*e4b17023SJohn Marino   for (i = 0; i < VEC_length (operand_entry_t, *ops); ++i)
1352*e4b17023SJohn Marino     VEC_free (operand_entry_t, heap, subops[i]);
1353*e4b17023SJohn Marino   free (subops);
1354*e4b17023SJohn Marino   VEC_free (oecount, heap, cvec);
1355*e4b17023SJohn Marino   sbitmap_free (candidates);
1356*e4b17023SJohn Marino   sbitmap_free (candidates2);
1357*e4b17023SJohn Marino 
1358*e4b17023SJohn Marino   return changed;
1359*e4b17023SJohn Marino }
1360*e4b17023SJohn Marino 
1361*e4b17023SJohn Marino /* If OPCODE is BIT_IOR_EXPR or BIT_AND_EXPR and CURR is a comparison
1362*e4b17023SJohn Marino    expression, examine the other OPS to see if any of them are comparisons
1363*e4b17023SJohn Marino    of the same values, which we may be able to combine or eliminate.
1364*e4b17023SJohn Marino    For example, we can rewrite (a < b) | (a == b) as (a <= b).  */
1365*e4b17023SJohn Marino 
1366*e4b17023SJohn Marino static bool
1367*e4b17023SJohn Marino eliminate_redundant_comparison (enum tree_code opcode,
1368*e4b17023SJohn Marino 				VEC (operand_entry_t, heap) **ops,
1369*e4b17023SJohn Marino 				unsigned int currindex,
1370*e4b17023SJohn Marino 				operand_entry_t curr)
1371*e4b17023SJohn Marino {
1372*e4b17023SJohn Marino   tree op1, op2;
1373*e4b17023SJohn Marino   enum tree_code lcode, rcode;
1374*e4b17023SJohn Marino   gimple def1, def2;
1375*e4b17023SJohn Marino   int i;
1376*e4b17023SJohn Marino   operand_entry_t oe;
1377*e4b17023SJohn Marino 
1378*e4b17023SJohn Marino   if (opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
1379*e4b17023SJohn Marino     return false;
1380*e4b17023SJohn Marino 
1381*e4b17023SJohn Marino   /* Check that CURR is a comparison.  */
1382*e4b17023SJohn Marino   if (TREE_CODE (curr->op) != SSA_NAME)
1383*e4b17023SJohn Marino     return false;
1384*e4b17023SJohn Marino   def1 = SSA_NAME_DEF_STMT (curr->op);
1385*e4b17023SJohn Marino   if (!is_gimple_assign (def1))
1386*e4b17023SJohn Marino     return false;
1387*e4b17023SJohn Marino   lcode = gimple_assign_rhs_code (def1);
1388*e4b17023SJohn Marino   if (TREE_CODE_CLASS (lcode) != tcc_comparison)
1389*e4b17023SJohn Marino     return false;
1390*e4b17023SJohn Marino   op1 = gimple_assign_rhs1 (def1);
1391*e4b17023SJohn Marino   op2 = gimple_assign_rhs2 (def1);
1392*e4b17023SJohn Marino 
1393*e4b17023SJohn Marino   /* Now look for a similar comparison in the remaining OPS.  */
1394*e4b17023SJohn Marino   for (i = currindex + 1;
1395*e4b17023SJohn Marino        VEC_iterate (operand_entry_t, *ops, i, oe);
1396*e4b17023SJohn Marino        i++)
1397*e4b17023SJohn Marino     {
1398*e4b17023SJohn Marino       tree t;
1399*e4b17023SJohn Marino 
1400*e4b17023SJohn Marino       if (TREE_CODE (oe->op) != SSA_NAME)
1401*e4b17023SJohn Marino 	continue;
1402*e4b17023SJohn Marino       def2 = SSA_NAME_DEF_STMT (oe->op);
1403*e4b17023SJohn Marino       if (!is_gimple_assign (def2))
1404*e4b17023SJohn Marino 	continue;
1405*e4b17023SJohn Marino       rcode = gimple_assign_rhs_code (def2);
1406*e4b17023SJohn Marino       if (TREE_CODE_CLASS (rcode) != tcc_comparison)
1407*e4b17023SJohn Marino 	continue;
1408*e4b17023SJohn Marino 
1409*e4b17023SJohn Marino       /* If we got here, we have a match.  See if we can combine the
1410*e4b17023SJohn Marino 	 two comparisons.  */
1411*e4b17023SJohn Marino       if (opcode == BIT_IOR_EXPR)
1412*e4b17023SJohn Marino 	t = maybe_fold_or_comparisons (lcode, op1, op2,
1413*e4b17023SJohn Marino 				       rcode, gimple_assign_rhs1 (def2),
1414*e4b17023SJohn Marino 				       gimple_assign_rhs2 (def2));
1415*e4b17023SJohn Marino       else
1416*e4b17023SJohn Marino 	t = maybe_fold_and_comparisons (lcode, op1, op2,
1417*e4b17023SJohn Marino 					rcode, gimple_assign_rhs1 (def2),
1418*e4b17023SJohn Marino 					gimple_assign_rhs2 (def2));
1419*e4b17023SJohn Marino       if (!t)
1420*e4b17023SJohn Marino 	continue;
1421*e4b17023SJohn Marino 
1422*e4b17023SJohn Marino       /* maybe_fold_and_comparisons and maybe_fold_or_comparisons
1423*e4b17023SJohn Marino 	 always give us a boolean_type_node value back.  If the original
1424*e4b17023SJohn Marino 	 BIT_AND_EXPR or BIT_IOR_EXPR was of a wider integer type,
1425*e4b17023SJohn Marino 	 we need to convert.  */
1426*e4b17023SJohn Marino       if (!useless_type_conversion_p (TREE_TYPE (curr->op), TREE_TYPE (t)))
1427*e4b17023SJohn Marino 	t = fold_convert (TREE_TYPE (curr->op), t);
1428*e4b17023SJohn Marino 
1429*e4b17023SJohn Marino       if (TREE_CODE (t) != INTEGER_CST
1430*e4b17023SJohn Marino 	  && !operand_equal_p (t, curr->op, 0))
1431*e4b17023SJohn Marino 	{
1432*e4b17023SJohn Marino 	  enum tree_code subcode;
1433*e4b17023SJohn Marino 	  tree newop1, newop2;
1434*e4b17023SJohn Marino 	  if (!COMPARISON_CLASS_P (t))
1435*e4b17023SJohn Marino 	    continue;
1436*e4b17023SJohn Marino 	  extract_ops_from_tree (t, &subcode, &newop1, &newop2);
1437*e4b17023SJohn Marino 	  STRIP_USELESS_TYPE_CONVERSION (newop1);
1438*e4b17023SJohn Marino 	  STRIP_USELESS_TYPE_CONVERSION (newop2);
1439*e4b17023SJohn Marino 	  if (!is_gimple_val (newop1) || !is_gimple_val (newop2))
1440*e4b17023SJohn Marino 	    continue;
1441*e4b17023SJohn Marino 	}
1442*e4b17023SJohn Marino 
1443*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1444*e4b17023SJohn Marino 	{
1445*e4b17023SJohn Marino 	  fprintf (dump_file, "Equivalence: ");
1446*e4b17023SJohn Marino 	  print_generic_expr (dump_file, curr->op, 0);
1447*e4b17023SJohn Marino 	  fprintf (dump_file, " %s ", op_symbol_code (opcode));
1448*e4b17023SJohn Marino 	  print_generic_expr (dump_file, oe->op, 0);
1449*e4b17023SJohn Marino 	  fprintf (dump_file, " -> ");
1450*e4b17023SJohn Marino 	  print_generic_expr (dump_file, t, 0);
1451*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
1452*e4b17023SJohn Marino 	}
1453*e4b17023SJohn Marino 
1454*e4b17023SJohn Marino       /* Now we can delete oe, as it has been subsumed by the new combined
1455*e4b17023SJohn Marino          expression t.  */
1456*e4b17023SJohn Marino       VEC_ordered_remove (operand_entry_t, *ops, i);
1457*e4b17023SJohn Marino       reassociate_stats.ops_eliminated ++;
1458*e4b17023SJohn Marino 
1459*e4b17023SJohn Marino       /* If t is the same as curr->op, we're done.  Otherwise we must
1460*e4b17023SJohn Marino 	 replace curr->op with t.  Special case is if we got a constant
1461*e4b17023SJohn Marino 	 back, in which case we add it to the end instead of in place of
1462*e4b17023SJohn Marino 	 the current entry.  */
1463*e4b17023SJohn Marino       if (TREE_CODE (t) == INTEGER_CST)
1464*e4b17023SJohn Marino 	{
1465*e4b17023SJohn Marino 	  VEC_ordered_remove (operand_entry_t, *ops, currindex);
1466*e4b17023SJohn Marino 	  add_to_ops_vec (ops, t);
1467*e4b17023SJohn Marino 	}
1468*e4b17023SJohn Marino       else if (!operand_equal_p (t, curr->op, 0))
1469*e4b17023SJohn Marino 	{
1470*e4b17023SJohn Marino 	  tree tmpvar;
1471*e4b17023SJohn Marino 	  gimple sum;
1472*e4b17023SJohn Marino 	  enum tree_code subcode;
1473*e4b17023SJohn Marino 	  tree newop1;
1474*e4b17023SJohn Marino 	  tree newop2;
1475*e4b17023SJohn Marino 	  gcc_assert (COMPARISON_CLASS_P (t));
1476*e4b17023SJohn Marino 	  tmpvar = create_tmp_var (TREE_TYPE (t), NULL);
1477*e4b17023SJohn Marino 	  add_referenced_var (tmpvar);
1478*e4b17023SJohn Marino 	  extract_ops_from_tree (t, &subcode, &newop1, &newop2);
1479*e4b17023SJohn Marino 	  STRIP_USELESS_TYPE_CONVERSION (newop1);
1480*e4b17023SJohn Marino 	  STRIP_USELESS_TYPE_CONVERSION (newop2);
1481*e4b17023SJohn Marino 	  gcc_checking_assert (is_gimple_val (newop1)
1482*e4b17023SJohn Marino 			       && is_gimple_val (newop2));
1483*e4b17023SJohn Marino 	  sum = build_and_add_sum (tmpvar, newop1, newop2, subcode);
1484*e4b17023SJohn Marino 	  curr->op = gimple_get_lhs (sum);
1485*e4b17023SJohn Marino 	}
1486*e4b17023SJohn Marino       return true;
1487*e4b17023SJohn Marino     }
1488*e4b17023SJohn Marino 
1489*e4b17023SJohn Marino   return false;
1490*e4b17023SJohn Marino }
1491*e4b17023SJohn Marino 
1492*e4b17023SJohn Marino /* Perform various identities and other optimizations on the list of
1493*e4b17023SJohn Marino    operand entries, stored in OPS.  The tree code for the binary
1494*e4b17023SJohn Marino    operation between all the operands is OPCODE.  */
1495*e4b17023SJohn Marino 
1496*e4b17023SJohn Marino static void
1497*e4b17023SJohn Marino optimize_ops_list (enum tree_code opcode,
1498*e4b17023SJohn Marino 		   VEC (operand_entry_t, heap) **ops)
1499*e4b17023SJohn Marino {
1500*e4b17023SJohn Marino   unsigned int length = VEC_length (operand_entry_t, *ops);
1501*e4b17023SJohn Marino   unsigned int i;
1502*e4b17023SJohn Marino   operand_entry_t oe;
1503*e4b17023SJohn Marino   operand_entry_t oelast = NULL;
1504*e4b17023SJohn Marino   bool iterate = false;
1505*e4b17023SJohn Marino 
1506*e4b17023SJohn Marino   if (length == 1)
1507*e4b17023SJohn Marino     return;
1508*e4b17023SJohn Marino 
1509*e4b17023SJohn Marino   oelast = VEC_last (operand_entry_t, *ops);
1510*e4b17023SJohn Marino 
1511*e4b17023SJohn Marino   /* If the last two are constants, pop the constants off, merge them
1512*e4b17023SJohn Marino      and try the next two.  */
1513*e4b17023SJohn Marino   if (oelast->rank == 0 && is_gimple_min_invariant (oelast->op))
1514*e4b17023SJohn Marino     {
1515*e4b17023SJohn Marino       operand_entry_t oelm1 = VEC_index (operand_entry_t, *ops, length - 2);
1516*e4b17023SJohn Marino 
1517*e4b17023SJohn Marino       if (oelm1->rank == 0
1518*e4b17023SJohn Marino 	  && is_gimple_min_invariant (oelm1->op)
1519*e4b17023SJohn Marino 	  && useless_type_conversion_p (TREE_TYPE (oelm1->op),
1520*e4b17023SJohn Marino 				       TREE_TYPE (oelast->op)))
1521*e4b17023SJohn Marino 	{
1522*e4b17023SJohn Marino 	  tree folded = fold_binary (opcode, TREE_TYPE (oelm1->op),
1523*e4b17023SJohn Marino 				     oelm1->op, oelast->op);
1524*e4b17023SJohn Marino 
1525*e4b17023SJohn Marino 	  if (folded && is_gimple_min_invariant (folded))
1526*e4b17023SJohn Marino 	    {
1527*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1528*e4b17023SJohn Marino 		fprintf (dump_file, "Merging constants\n");
1529*e4b17023SJohn Marino 
1530*e4b17023SJohn Marino 	      VEC_pop (operand_entry_t, *ops);
1531*e4b17023SJohn Marino 	      VEC_pop (operand_entry_t, *ops);
1532*e4b17023SJohn Marino 
1533*e4b17023SJohn Marino 	      add_to_ops_vec (ops, folded);
1534*e4b17023SJohn Marino 	      reassociate_stats.constants_eliminated++;
1535*e4b17023SJohn Marino 
1536*e4b17023SJohn Marino 	      optimize_ops_list (opcode, ops);
1537*e4b17023SJohn Marino 	      return;
1538*e4b17023SJohn Marino 	    }
1539*e4b17023SJohn Marino 	}
1540*e4b17023SJohn Marino     }
1541*e4b17023SJohn Marino 
1542*e4b17023SJohn Marino   eliminate_using_constants (opcode, ops);
1543*e4b17023SJohn Marino   oelast = NULL;
1544*e4b17023SJohn Marino 
1545*e4b17023SJohn Marino   for (i = 0; VEC_iterate (operand_entry_t, *ops, i, oe);)
1546*e4b17023SJohn Marino     {
1547*e4b17023SJohn Marino       bool done = false;
1548*e4b17023SJohn Marino 
1549*e4b17023SJohn Marino       if (eliminate_not_pairs (opcode, ops, i, oe))
1550*e4b17023SJohn Marino 	return;
1551*e4b17023SJohn Marino       if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast)
1552*e4b17023SJohn Marino 	  || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe))
1553*e4b17023SJohn Marino 	  || (!done && eliminate_redundant_comparison (opcode, ops, i, oe)))
1554*e4b17023SJohn Marino 	{
1555*e4b17023SJohn Marino 	  if (done)
1556*e4b17023SJohn Marino 	    return;
1557*e4b17023SJohn Marino 	  iterate = true;
1558*e4b17023SJohn Marino 	  oelast = NULL;
1559*e4b17023SJohn Marino 	  continue;
1560*e4b17023SJohn Marino 	}
1561*e4b17023SJohn Marino       oelast = oe;
1562*e4b17023SJohn Marino       i++;
1563*e4b17023SJohn Marino     }
1564*e4b17023SJohn Marino 
1565*e4b17023SJohn Marino   length  = VEC_length (operand_entry_t, *ops);
1566*e4b17023SJohn Marino   oelast = VEC_last (operand_entry_t, *ops);
1567*e4b17023SJohn Marino 
1568*e4b17023SJohn Marino   if (iterate)
1569*e4b17023SJohn Marino     optimize_ops_list (opcode, ops);
1570*e4b17023SJohn Marino }
1571*e4b17023SJohn Marino 
1572*e4b17023SJohn Marino /* The following functions are subroutines to optimize_range_tests and allow
1573*e4b17023SJohn Marino    it to try to change a logical combination of comparisons into a range
1574*e4b17023SJohn Marino    test.
1575*e4b17023SJohn Marino 
1576*e4b17023SJohn Marino    For example, both
1577*e4b17023SJohn Marino 	X == 2 || X == 5 || X == 3 || X == 4
1578*e4b17023SJohn Marino    and
1579*e4b17023SJohn Marino 	X >= 2 && X <= 5
1580*e4b17023SJohn Marino    are converted to
1581*e4b17023SJohn Marino 	(unsigned) (X - 2) <= 3
1582*e4b17023SJohn Marino 
1583*e4b17023SJohn Marino    For more information see comments above fold_test_range in fold-const.c,
1584*e4b17023SJohn Marino    this implementation is for GIMPLE.  */
1585*e4b17023SJohn Marino 
1586*e4b17023SJohn Marino struct range_entry
1587*e4b17023SJohn Marino {
1588*e4b17023SJohn Marino   tree exp;
1589*e4b17023SJohn Marino   tree low;
1590*e4b17023SJohn Marino   tree high;
1591*e4b17023SJohn Marino   bool in_p;
1592*e4b17023SJohn Marino   bool strict_overflow_p;
1593*e4b17023SJohn Marino   unsigned int idx, next;
1594*e4b17023SJohn Marino };
1595*e4b17023SJohn Marino 
1596*e4b17023SJohn Marino /* This is similar to make_range in fold-const.c, but on top of
1597*e4b17023SJohn Marino    GIMPLE instead of trees.  */
1598*e4b17023SJohn Marino 
1599*e4b17023SJohn Marino static void
1600*e4b17023SJohn Marino init_range_entry (struct range_entry *r, tree exp)
1601*e4b17023SJohn Marino {
1602*e4b17023SJohn Marino   int in_p;
1603*e4b17023SJohn Marino   tree low, high;
1604*e4b17023SJohn Marino   bool is_bool, strict_overflow_p;
1605*e4b17023SJohn Marino 
1606*e4b17023SJohn Marino   r->exp = NULL_TREE;
1607*e4b17023SJohn Marino   r->in_p = false;
1608*e4b17023SJohn Marino   r->strict_overflow_p = false;
1609*e4b17023SJohn Marino   r->low = NULL_TREE;
1610*e4b17023SJohn Marino   r->high = NULL_TREE;
1611*e4b17023SJohn Marino   if (TREE_CODE (exp) != SSA_NAME || !INTEGRAL_TYPE_P (TREE_TYPE (exp)))
1612*e4b17023SJohn Marino     return;
1613*e4b17023SJohn Marino 
1614*e4b17023SJohn Marino   /* Start with simply saying "EXP != 0" and then look at the code of EXP
1615*e4b17023SJohn Marino      and see if we can refine the range.  Some of the cases below may not
1616*e4b17023SJohn Marino      happen, but it doesn't seem worth worrying about this.  We "continue"
1617*e4b17023SJohn Marino      the outer loop when we've changed something; otherwise we "break"
1618*e4b17023SJohn Marino      the switch, which will "break" the while.  */
1619*e4b17023SJohn Marino   low = build_int_cst (TREE_TYPE (exp), 0);
1620*e4b17023SJohn Marino   high = low;
1621*e4b17023SJohn Marino   in_p = 0;
1622*e4b17023SJohn Marino   strict_overflow_p = false;
1623*e4b17023SJohn Marino   is_bool = false;
1624*e4b17023SJohn Marino   if (TYPE_PRECISION (TREE_TYPE (exp)) == 1)
1625*e4b17023SJohn Marino     {
1626*e4b17023SJohn Marino       if (TYPE_UNSIGNED (TREE_TYPE (exp)))
1627*e4b17023SJohn Marino 	is_bool = true;
1628*e4b17023SJohn Marino       else
1629*e4b17023SJohn Marino 	return;
1630*e4b17023SJohn Marino     }
1631*e4b17023SJohn Marino   else if (TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE)
1632*e4b17023SJohn Marino     is_bool = true;
1633*e4b17023SJohn Marino 
1634*e4b17023SJohn Marino   while (1)
1635*e4b17023SJohn Marino     {
1636*e4b17023SJohn Marino       gimple stmt;
1637*e4b17023SJohn Marino       enum tree_code code;
1638*e4b17023SJohn Marino       tree arg0, arg1, exp_type;
1639*e4b17023SJohn Marino       tree nexp;
1640*e4b17023SJohn Marino       location_t loc;
1641*e4b17023SJohn Marino 
1642*e4b17023SJohn Marino       if (TREE_CODE (exp) != SSA_NAME)
1643*e4b17023SJohn Marino 	break;
1644*e4b17023SJohn Marino 
1645*e4b17023SJohn Marino       stmt = SSA_NAME_DEF_STMT (exp);
1646*e4b17023SJohn Marino       if (!is_gimple_assign (stmt))
1647*e4b17023SJohn Marino 	break;
1648*e4b17023SJohn Marino 
1649*e4b17023SJohn Marino       code = gimple_assign_rhs_code (stmt);
1650*e4b17023SJohn Marino       arg0 = gimple_assign_rhs1 (stmt);
1651*e4b17023SJohn Marino       if (TREE_CODE (arg0) != SSA_NAME)
1652*e4b17023SJohn Marino 	break;
1653*e4b17023SJohn Marino       arg1 = gimple_assign_rhs2 (stmt);
1654*e4b17023SJohn Marino       exp_type = TREE_TYPE (exp);
1655*e4b17023SJohn Marino       loc = gimple_location (stmt);
1656*e4b17023SJohn Marino       switch (code)
1657*e4b17023SJohn Marino 	{
1658*e4b17023SJohn Marino 	case BIT_NOT_EXPR:
1659*e4b17023SJohn Marino 	  if (TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE)
1660*e4b17023SJohn Marino 	    {
1661*e4b17023SJohn Marino 	      in_p = !in_p;
1662*e4b17023SJohn Marino 	      exp = arg0;
1663*e4b17023SJohn Marino 	      continue;
1664*e4b17023SJohn Marino 	    }
1665*e4b17023SJohn Marino 	  break;
1666*e4b17023SJohn Marino 	case SSA_NAME:
1667*e4b17023SJohn Marino 	  exp = arg0;
1668*e4b17023SJohn Marino 	  continue;
1669*e4b17023SJohn Marino 	CASE_CONVERT:
1670*e4b17023SJohn Marino 	  if (is_bool)
1671*e4b17023SJohn Marino 	    goto do_default;
1672*e4b17023SJohn Marino 	  if (TYPE_PRECISION (TREE_TYPE (arg0)) == 1)
1673*e4b17023SJohn Marino 	    {
1674*e4b17023SJohn Marino 	      if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
1675*e4b17023SJohn Marino 		is_bool = true;
1676*e4b17023SJohn Marino 	      else
1677*e4b17023SJohn Marino 		return;
1678*e4b17023SJohn Marino 	    }
1679*e4b17023SJohn Marino 	  else if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE)
1680*e4b17023SJohn Marino 	    is_bool = true;
1681*e4b17023SJohn Marino 	  goto do_default;
1682*e4b17023SJohn Marino 	case EQ_EXPR:
1683*e4b17023SJohn Marino 	case NE_EXPR:
1684*e4b17023SJohn Marino 	case LT_EXPR:
1685*e4b17023SJohn Marino 	case LE_EXPR:
1686*e4b17023SJohn Marino 	case GE_EXPR:
1687*e4b17023SJohn Marino 	case GT_EXPR:
1688*e4b17023SJohn Marino 	  is_bool = true;
1689*e4b17023SJohn Marino 	  /* FALLTHRU */
1690*e4b17023SJohn Marino 	default:
1691*e4b17023SJohn Marino 	  if (!is_bool)
1692*e4b17023SJohn Marino 	    return;
1693*e4b17023SJohn Marino 	do_default:
1694*e4b17023SJohn Marino 	  nexp = make_range_step (loc, code, arg0, arg1, exp_type,
1695*e4b17023SJohn Marino 				  &low, &high, &in_p,
1696*e4b17023SJohn Marino 				  &strict_overflow_p);
1697*e4b17023SJohn Marino 	  if (nexp != NULL_TREE)
1698*e4b17023SJohn Marino 	    {
1699*e4b17023SJohn Marino 	      exp = nexp;
1700*e4b17023SJohn Marino 	      gcc_assert (TREE_CODE (exp) == SSA_NAME);
1701*e4b17023SJohn Marino 	      continue;
1702*e4b17023SJohn Marino 	    }
1703*e4b17023SJohn Marino 	  break;
1704*e4b17023SJohn Marino 	}
1705*e4b17023SJohn Marino       break;
1706*e4b17023SJohn Marino     }
1707*e4b17023SJohn Marino   if (is_bool)
1708*e4b17023SJohn Marino     {
1709*e4b17023SJohn Marino       r->exp = exp;
1710*e4b17023SJohn Marino       r->in_p = in_p;
1711*e4b17023SJohn Marino       r->low = low;
1712*e4b17023SJohn Marino       r->high = high;
1713*e4b17023SJohn Marino       r->strict_overflow_p = strict_overflow_p;
1714*e4b17023SJohn Marino     }
1715*e4b17023SJohn Marino }
1716*e4b17023SJohn Marino 
1717*e4b17023SJohn Marino /* Comparison function for qsort.  Sort entries
1718*e4b17023SJohn Marino    without SSA_NAME exp first, then with SSA_NAMEs sorted
1719*e4b17023SJohn Marino    by increasing SSA_NAME_VERSION, and for the same SSA_NAMEs
1720*e4b17023SJohn Marino    by increasing ->low and if ->low is the same, by increasing
1721*e4b17023SJohn Marino    ->high.  ->low == NULL_TREE means minimum, ->high == NULL_TREE
1722*e4b17023SJohn Marino    maximum.  */
1723*e4b17023SJohn Marino 
1724*e4b17023SJohn Marino static int
1725*e4b17023SJohn Marino range_entry_cmp (const void *a, const void *b)
1726*e4b17023SJohn Marino {
1727*e4b17023SJohn Marino   const struct range_entry *p = (const struct range_entry *) a;
1728*e4b17023SJohn Marino   const struct range_entry *q = (const struct range_entry *) b;
1729*e4b17023SJohn Marino 
1730*e4b17023SJohn Marino   if (p->exp != NULL_TREE && TREE_CODE (p->exp) == SSA_NAME)
1731*e4b17023SJohn Marino     {
1732*e4b17023SJohn Marino       if (q->exp != NULL_TREE && TREE_CODE (q->exp) == SSA_NAME)
1733*e4b17023SJohn Marino 	{
1734*e4b17023SJohn Marino 	  /* Group range_entries for the same SSA_NAME together.  */
1735*e4b17023SJohn Marino 	  if (SSA_NAME_VERSION (p->exp) < SSA_NAME_VERSION (q->exp))
1736*e4b17023SJohn Marino 	    return -1;
1737*e4b17023SJohn Marino 	  else if (SSA_NAME_VERSION (p->exp) > SSA_NAME_VERSION (q->exp))
1738*e4b17023SJohn Marino 	    return 1;
1739*e4b17023SJohn Marino 	  /* If ->low is different, NULL low goes first, then by
1740*e4b17023SJohn Marino 	     ascending low.  */
1741*e4b17023SJohn Marino 	  if (p->low != NULL_TREE)
1742*e4b17023SJohn Marino 	    {
1743*e4b17023SJohn Marino 	      if (q->low != NULL_TREE)
1744*e4b17023SJohn Marino 		{
1745*e4b17023SJohn Marino 		  tree tem = fold_binary (LT_EXPR, boolean_type_node,
1746*e4b17023SJohn Marino 					  p->low, q->low);
1747*e4b17023SJohn Marino 		  if (tem && integer_onep (tem))
1748*e4b17023SJohn Marino 		    return -1;
1749*e4b17023SJohn Marino 		  tem = fold_binary (GT_EXPR, boolean_type_node,
1750*e4b17023SJohn Marino 				     p->low, q->low);
1751*e4b17023SJohn Marino 		  if (tem && integer_onep (tem))
1752*e4b17023SJohn Marino 		    return 1;
1753*e4b17023SJohn Marino 		}
1754*e4b17023SJohn Marino 	      else
1755*e4b17023SJohn Marino 		return 1;
1756*e4b17023SJohn Marino 	    }
1757*e4b17023SJohn Marino 	  else if (q->low != NULL_TREE)
1758*e4b17023SJohn Marino 	    return -1;
1759*e4b17023SJohn Marino 	  /* If ->high is different, NULL high goes last, before that by
1760*e4b17023SJohn Marino 	     ascending high.  */
1761*e4b17023SJohn Marino 	  if (p->high != NULL_TREE)
1762*e4b17023SJohn Marino 	    {
1763*e4b17023SJohn Marino 	      if (q->high != NULL_TREE)
1764*e4b17023SJohn Marino 		{
1765*e4b17023SJohn Marino 		  tree tem = fold_binary (LT_EXPR, boolean_type_node,
1766*e4b17023SJohn Marino 					  p->high, q->high);
1767*e4b17023SJohn Marino 		  if (tem && integer_onep (tem))
1768*e4b17023SJohn Marino 		    return -1;
1769*e4b17023SJohn Marino 		  tem = fold_binary (GT_EXPR, boolean_type_node,
1770*e4b17023SJohn Marino 				     p->high, q->high);
1771*e4b17023SJohn Marino 		  if (tem && integer_onep (tem))
1772*e4b17023SJohn Marino 		    return 1;
1773*e4b17023SJohn Marino 		}
1774*e4b17023SJohn Marino 	      else
1775*e4b17023SJohn Marino 		return -1;
1776*e4b17023SJohn Marino 	    }
1777*e4b17023SJohn Marino 	  else if (p->high != NULL_TREE)
1778*e4b17023SJohn Marino 	    return 1;
1779*e4b17023SJohn Marino 	  /* If both ranges are the same, sort below by ascending idx.  */
1780*e4b17023SJohn Marino 	}
1781*e4b17023SJohn Marino       else
1782*e4b17023SJohn Marino 	return 1;
1783*e4b17023SJohn Marino     }
1784*e4b17023SJohn Marino   else if (q->exp != NULL_TREE && TREE_CODE (q->exp) == SSA_NAME)
1785*e4b17023SJohn Marino     return -1;
1786*e4b17023SJohn Marino 
1787*e4b17023SJohn Marino   if (p->idx < q->idx)
1788*e4b17023SJohn Marino     return -1;
1789*e4b17023SJohn Marino   else
1790*e4b17023SJohn Marino     {
1791*e4b17023SJohn Marino       gcc_checking_assert (p->idx > q->idx);
1792*e4b17023SJohn Marino       return 1;
1793*e4b17023SJohn Marino     }
1794*e4b17023SJohn Marino }
1795*e4b17023SJohn Marino 
1796*e4b17023SJohn Marino /* Helper routine of optimize_range_test.
1797*e4b17023SJohn Marino    [EXP, IN_P, LOW, HIGH, STRICT_OVERFLOW_P] is a merged range for
1798*e4b17023SJohn Marino    RANGE and OTHERRANGE through OTHERRANGE + COUNT - 1 ranges,
1799*e4b17023SJohn Marino    OPCODE and OPS are arguments of optimize_range_tests.  Return
1800*e4b17023SJohn Marino    true if the range merge has been successful.  */
1801*e4b17023SJohn Marino 
1802*e4b17023SJohn Marino static bool
1803*e4b17023SJohn Marino update_range_test (struct range_entry *range, struct range_entry *otherrange,
1804*e4b17023SJohn Marino 		   unsigned int count, enum tree_code opcode,
1805*e4b17023SJohn Marino 		   VEC (operand_entry_t, heap) **ops, tree exp, bool in_p,
1806*e4b17023SJohn Marino 		   tree low, tree high, bool strict_overflow_p)
1807*e4b17023SJohn Marino {
1808*e4b17023SJohn Marino   tree op = VEC_index (operand_entry_t, *ops, range->idx)->op;
1809*e4b17023SJohn Marino   location_t loc = gimple_location (SSA_NAME_DEF_STMT (op));
1810*e4b17023SJohn Marino   tree tem = build_range_check (loc, TREE_TYPE (op), exp, in_p, low, high);
1811*e4b17023SJohn Marino   enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON;
1812*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1813*e4b17023SJohn Marino 
1814*e4b17023SJohn Marino   if (tem == NULL_TREE)
1815*e4b17023SJohn Marino     return false;
1816*e4b17023SJohn Marino 
1817*e4b17023SJohn Marino   if (strict_overflow_p && issue_strict_overflow_warning (wc))
1818*e4b17023SJohn Marino     warning_at (loc, OPT_Wstrict_overflow,
1819*e4b17023SJohn Marino 		"assuming signed overflow does not occur "
1820*e4b17023SJohn Marino 		"when simplifying range test");
1821*e4b17023SJohn Marino 
1822*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1823*e4b17023SJohn Marino     {
1824*e4b17023SJohn Marino       struct range_entry *r;
1825*e4b17023SJohn Marino       fprintf (dump_file, "Optimizing range tests ");
1826*e4b17023SJohn Marino       print_generic_expr (dump_file, range->exp, 0);
1827*e4b17023SJohn Marino       fprintf (dump_file, " %c[", range->in_p ? '+' : '-');
1828*e4b17023SJohn Marino       print_generic_expr (dump_file, range->low, 0);
1829*e4b17023SJohn Marino       fprintf (dump_file, ", ");
1830*e4b17023SJohn Marino       print_generic_expr (dump_file, range->high, 0);
1831*e4b17023SJohn Marino       fprintf (dump_file, "]");
1832*e4b17023SJohn Marino       for (r = otherrange; r < otherrange + count; r++)
1833*e4b17023SJohn Marino 	{
1834*e4b17023SJohn Marino 	  fprintf (dump_file, " and %c[", r->in_p ? '+' : '-');
1835*e4b17023SJohn Marino 	  print_generic_expr (dump_file, r->low, 0);
1836*e4b17023SJohn Marino 	  fprintf (dump_file, ", ");
1837*e4b17023SJohn Marino 	  print_generic_expr (dump_file, r->high, 0);
1838*e4b17023SJohn Marino 	  fprintf (dump_file, "]");
1839*e4b17023SJohn Marino 	}
1840*e4b17023SJohn Marino       fprintf (dump_file, "\n into ");
1841*e4b17023SJohn Marino       print_generic_expr (dump_file, tem, 0);
1842*e4b17023SJohn Marino       fprintf (dump_file, "\n");
1843*e4b17023SJohn Marino     }
1844*e4b17023SJohn Marino 
1845*e4b17023SJohn Marino   if (opcode == BIT_IOR_EXPR)
1846*e4b17023SJohn Marino     tem = invert_truthvalue_loc (loc, tem);
1847*e4b17023SJohn Marino 
1848*e4b17023SJohn Marino   tem = fold_convert_loc (loc, TREE_TYPE (op), tem);
1849*e4b17023SJohn Marino   gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (op));
1850*e4b17023SJohn Marino   tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
1851*e4b17023SJohn Marino 				  GSI_SAME_STMT);
1852*e4b17023SJohn Marino 
1853*e4b17023SJohn Marino   VEC_index (operand_entry_t, *ops, range->idx)->op = tem;
1854*e4b17023SJohn Marino   range->exp = exp;
1855*e4b17023SJohn Marino   range->low = low;
1856*e4b17023SJohn Marino   range->high = high;
1857*e4b17023SJohn Marino   range->in_p = in_p;
1858*e4b17023SJohn Marino   range->strict_overflow_p = false;
1859*e4b17023SJohn Marino 
1860*e4b17023SJohn Marino   for (range = otherrange; range < otherrange + count; range++)
1861*e4b17023SJohn Marino     {
1862*e4b17023SJohn Marino       VEC_index (operand_entry_t, *ops, range->idx)->op = error_mark_node;
1863*e4b17023SJohn Marino       range->exp = NULL_TREE;
1864*e4b17023SJohn Marino     }
1865*e4b17023SJohn Marino   return true;
1866*e4b17023SJohn Marino }
1867*e4b17023SJohn Marino 
1868*e4b17023SJohn Marino /* Optimize range tests, similarly how fold_range_test optimizes
1869*e4b17023SJohn Marino    it on trees.  The tree code for the binary
1870*e4b17023SJohn Marino    operation between all the operands is OPCODE.  */
1871*e4b17023SJohn Marino 
1872*e4b17023SJohn Marino static void
1873*e4b17023SJohn Marino optimize_range_tests (enum tree_code opcode,
1874*e4b17023SJohn Marino 		      VEC (operand_entry_t, heap) **ops)
1875*e4b17023SJohn Marino {
1876*e4b17023SJohn Marino   unsigned int length = VEC_length (operand_entry_t, *ops), i, j, first;
1877*e4b17023SJohn Marino   operand_entry_t oe;
1878*e4b17023SJohn Marino   struct range_entry *ranges;
1879*e4b17023SJohn Marino   bool any_changes = false;
1880*e4b17023SJohn Marino 
1881*e4b17023SJohn Marino   if (length == 1)
1882*e4b17023SJohn Marino     return;
1883*e4b17023SJohn Marino 
1884*e4b17023SJohn Marino   ranges = XNEWVEC (struct range_entry, length);
1885*e4b17023SJohn Marino   for (i = 0; i < length; i++)
1886*e4b17023SJohn Marino     {
1887*e4b17023SJohn Marino       ranges[i].idx = i;
1888*e4b17023SJohn Marino       init_range_entry (ranges + i, VEC_index (operand_entry_t, *ops, i)->op);
1889*e4b17023SJohn Marino       /* For | invert it now, we will invert it again before emitting
1890*e4b17023SJohn Marino 	 the optimized expression.  */
1891*e4b17023SJohn Marino       if (opcode == BIT_IOR_EXPR)
1892*e4b17023SJohn Marino 	ranges[i].in_p = !ranges[i].in_p;
1893*e4b17023SJohn Marino     }
1894*e4b17023SJohn Marino 
1895*e4b17023SJohn Marino   qsort (ranges, length, sizeof (*ranges), range_entry_cmp);
1896*e4b17023SJohn Marino   for (i = 0; i < length; i++)
1897*e4b17023SJohn Marino     if (ranges[i].exp != NULL_TREE && TREE_CODE (ranges[i].exp) == SSA_NAME)
1898*e4b17023SJohn Marino       break;
1899*e4b17023SJohn Marino 
1900*e4b17023SJohn Marino   /* Try to merge ranges.  */
1901*e4b17023SJohn Marino   for (first = i; i < length; i++)
1902*e4b17023SJohn Marino     {
1903*e4b17023SJohn Marino       tree low = ranges[i].low;
1904*e4b17023SJohn Marino       tree high = ranges[i].high;
1905*e4b17023SJohn Marino       int in_p = ranges[i].in_p;
1906*e4b17023SJohn Marino       bool strict_overflow_p = ranges[i].strict_overflow_p;
1907*e4b17023SJohn Marino       int update_fail_count = 0;
1908*e4b17023SJohn Marino 
1909*e4b17023SJohn Marino       for (j = i + 1; j < length; j++)
1910*e4b17023SJohn Marino 	{
1911*e4b17023SJohn Marino 	  if (ranges[i].exp != ranges[j].exp)
1912*e4b17023SJohn Marino 	    break;
1913*e4b17023SJohn Marino 	  if (!merge_ranges (&in_p, &low, &high, in_p, low, high,
1914*e4b17023SJohn Marino 			     ranges[j].in_p, ranges[j].low, ranges[j].high))
1915*e4b17023SJohn Marino 	    break;
1916*e4b17023SJohn Marino 	  strict_overflow_p |= ranges[j].strict_overflow_p;
1917*e4b17023SJohn Marino 	}
1918*e4b17023SJohn Marino 
1919*e4b17023SJohn Marino       if (j == i + 1)
1920*e4b17023SJohn Marino 	continue;
1921*e4b17023SJohn Marino 
1922*e4b17023SJohn Marino       if (update_range_test (ranges + i, ranges + i + 1, j - i - 1, opcode,
1923*e4b17023SJohn Marino 			     ops, ranges[i].exp, in_p, low, high,
1924*e4b17023SJohn Marino 			     strict_overflow_p))
1925*e4b17023SJohn Marino 	{
1926*e4b17023SJohn Marino 	  i = j - 1;
1927*e4b17023SJohn Marino 	  any_changes = true;
1928*e4b17023SJohn Marino 	}
1929*e4b17023SJohn Marino       /* Avoid quadratic complexity if all merge_ranges calls would succeed,
1930*e4b17023SJohn Marino 	 while update_range_test would fail.  */
1931*e4b17023SJohn Marino       else if (update_fail_count == 64)
1932*e4b17023SJohn Marino 	i = j - 1;
1933*e4b17023SJohn Marino       else
1934*e4b17023SJohn Marino 	++update_fail_count;
1935*e4b17023SJohn Marino     }
1936*e4b17023SJohn Marino 
1937*e4b17023SJohn Marino   /* Optimize X == CST1 || X == CST2
1938*e4b17023SJohn Marino      if popcount (CST1 ^ CST2) == 1 into
1939*e4b17023SJohn Marino      (X & ~(CST1 ^ CST2)) == (CST1 & ~(CST1 ^ CST2)).
1940*e4b17023SJohn Marino      Similarly for ranges.  E.g.
1941*e4b17023SJohn Marino      X != 2 && X != 3 && X != 10 && X != 11
1942*e4b17023SJohn Marino      will be transformed by the above loop into
1943*e4b17023SJohn Marino      (X - 2U) <= 1U && (X - 10U) <= 1U
1944*e4b17023SJohn Marino      and this loop can transform that into
1945*e4b17023SJohn Marino      ((X & ~8) - 2U) <= 1U.  */
1946*e4b17023SJohn Marino   for (i = first; i < length; i++)
1947*e4b17023SJohn Marino     {
1948*e4b17023SJohn Marino       tree lowi, highi, lowj, highj, type, lowxor, highxor, tem, exp;
1949*e4b17023SJohn Marino 
1950*e4b17023SJohn Marino       if (ranges[i].exp == NULL_TREE || ranges[i].in_p)
1951*e4b17023SJohn Marino 	continue;
1952*e4b17023SJohn Marino       type = TREE_TYPE (ranges[i].exp);
1953*e4b17023SJohn Marino       if (!INTEGRAL_TYPE_P (type))
1954*e4b17023SJohn Marino 	continue;
1955*e4b17023SJohn Marino       lowi = ranges[i].low;
1956*e4b17023SJohn Marino       if (lowi == NULL_TREE)
1957*e4b17023SJohn Marino 	lowi = TYPE_MIN_VALUE (type);
1958*e4b17023SJohn Marino       highi = ranges[i].high;
1959*e4b17023SJohn Marino       if (highi == NULL_TREE)
1960*e4b17023SJohn Marino 	continue;
1961*e4b17023SJohn Marino       for (j = i + 1; j < length && j < i + 64; j++)
1962*e4b17023SJohn Marino 	{
1963*e4b17023SJohn Marino 	  if (ranges[j].exp == NULL_TREE)
1964*e4b17023SJohn Marino 	    continue;
1965*e4b17023SJohn Marino 	  if (ranges[i].exp != ranges[j].exp)
1966*e4b17023SJohn Marino 	    break;
1967*e4b17023SJohn Marino 	  if (ranges[j].in_p)
1968*e4b17023SJohn Marino 	    continue;
1969*e4b17023SJohn Marino 	  lowj = ranges[j].low;
1970*e4b17023SJohn Marino 	  if (lowj == NULL_TREE)
1971*e4b17023SJohn Marino 	    continue;
1972*e4b17023SJohn Marino 	  highj = ranges[j].high;
1973*e4b17023SJohn Marino 	  if (highj == NULL_TREE)
1974*e4b17023SJohn Marino 	    highj = TYPE_MAX_VALUE (type);
1975*e4b17023SJohn Marino 	  tem = fold_binary (GT_EXPR, boolean_type_node,
1976*e4b17023SJohn Marino 			     lowj, highi);
1977*e4b17023SJohn Marino 	  if (tem == NULL_TREE || !integer_onep (tem))
1978*e4b17023SJohn Marino 	    continue;
1979*e4b17023SJohn Marino 	  lowxor = fold_binary (BIT_XOR_EXPR, type, lowi, lowj);
1980*e4b17023SJohn Marino 	  if (lowxor == NULL_TREE || TREE_CODE (lowxor) != INTEGER_CST)
1981*e4b17023SJohn Marino 	    continue;
1982*e4b17023SJohn Marino 	  gcc_checking_assert (!integer_zerop (lowxor));
1983*e4b17023SJohn Marino 	  tem = fold_binary (MINUS_EXPR, type, lowxor,
1984*e4b17023SJohn Marino 			     build_int_cst (type, 1));
1985*e4b17023SJohn Marino 	  if (tem == NULL_TREE)
1986*e4b17023SJohn Marino 	    continue;
1987*e4b17023SJohn Marino 	  tem = fold_binary (BIT_AND_EXPR, type, lowxor, tem);
1988*e4b17023SJohn Marino 	  if (tem == NULL_TREE || !integer_zerop (tem))
1989*e4b17023SJohn Marino 	    continue;
1990*e4b17023SJohn Marino 	  highxor = fold_binary (BIT_XOR_EXPR, type, highi, highj);
1991*e4b17023SJohn Marino 	  if (!tree_int_cst_equal (lowxor, highxor))
1992*e4b17023SJohn Marino 	    continue;
1993*e4b17023SJohn Marino 	  tem = fold_build1 (BIT_NOT_EXPR, type, lowxor);
1994*e4b17023SJohn Marino 	  exp = fold_build2 (BIT_AND_EXPR, type, ranges[i].exp, tem);
1995*e4b17023SJohn Marino 	  lowj = fold_build2 (BIT_AND_EXPR, type, lowi, tem);
1996*e4b17023SJohn Marino 	  highj = fold_build2 (BIT_AND_EXPR, type, highi, tem);
1997*e4b17023SJohn Marino 	  if (update_range_test (ranges + i, ranges + j, 1, opcode, ops, exp,
1998*e4b17023SJohn Marino 				 ranges[i].in_p, lowj, highj,
1999*e4b17023SJohn Marino 				 ranges[i].strict_overflow_p
2000*e4b17023SJohn Marino 				 || ranges[j].strict_overflow_p))
2001*e4b17023SJohn Marino 	    {
2002*e4b17023SJohn Marino 	      any_changes = true;
2003*e4b17023SJohn Marino 	      break;
2004*e4b17023SJohn Marino 	    }
2005*e4b17023SJohn Marino 	}
2006*e4b17023SJohn Marino     }
2007*e4b17023SJohn Marino 
2008*e4b17023SJohn Marino   if (any_changes)
2009*e4b17023SJohn Marino     {
2010*e4b17023SJohn Marino       j = 0;
2011*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (operand_entry_t, *ops, i, oe)
2012*e4b17023SJohn Marino 	{
2013*e4b17023SJohn Marino 	  if (oe->op == error_mark_node)
2014*e4b17023SJohn Marino 	    continue;
2015*e4b17023SJohn Marino 	  else if (i != j)
2016*e4b17023SJohn Marino 	    VEC_replace (operand_entry_t, *ops, j, oe);
2017*e4b17023SJohn Marino 	  j++;
2018*e4b17023SJohn Marino 	}
2019*e4b17023SJohn Marino       VEC_truncate (operand_entry_t, *ops, j);
2020*e4b17023SJohn Marino     }
2021*e4b17023SJohn Marino 
2022*e4b17023SJohn Marino   XDELETEVEC (ranges);
2023*e4b17023SJohn Marino }
2024*e4b17023SJohn Marino 
2025*e4b17023SJohn Marino /* Return true if OPERAND is defined by a PHI node which uses the LHS
2026*e4b17023SJohn Marino    of STMT in it's operands.  This is also known as a "destructive
2027*e4b17023SJohn Marino    update" operation.  */
2028*e4b17023SJohn Marino 
2029*e4b17023SJohn Marino static bool
2030*e4b17023SJohn Marino is_phi_for_stmt (gimple stmt, tree operand)
2031*e4b17023SJohn Marino {
2032*e4b17023SJohn Marino   gimple def_stmt;
2033*e4b17023SJohn Marino   tree lhs;
2034*e4b17023SJohn Marino   use_operand_p arg_p;
2035*e4b17023SJohn Marino   ssa_op_iter i;
2036*e4b17023SJohn Marino 
2037*e4b17023SJohn Marino   if (TREE_CODE (operand) != SSA_NAME)
2038*e4b17023SJohn Marino     return false;
2039*e4b17023SJohn Marino 
2040*e4b17023SJohn Marino   lhs = gimple_assign_lhs (stmt);
2041*e4b17023SJohn Marino 
2042*e4b17023SJohn Marino   def_stmt = SSA_NAME_DEF_STMT (operand);
2043*e4b17023SJohn Marino   if (gimple_code (def_stmt) != GIMPLE_PHI)
2044*e4b17023SJohn Marino     return false;
2045*e4b17023SJohn Marino 
2046*e4b17023SJohn Marino   FOR_EACH_PHI_ARG (arg_p, def_stmt, i, SSA_OP_USE)
2047*e4b17023SJohn Marino     if (lhs == USE_FROM_PTR (arg_p))
2048*e4b17023SJohn Marino       return true;
2049*e4b17023SJohn Marino   return false;
2050*e4b17023SJohn Marino }
2051*e4b17023SJohn Marino 
2052*e4b17023SJohn Marino /* Remove def stmt of VAR if VAR has zero uses and recurse
2053*e4b17023SJohn Marino    on rhs1 operand if so.  */
2054*e4b17023SJohn Marino 
2055*e4b17023SJohn Marino static void
2056*e4b17023SJohn Marino remove_visited_stmt_chain (tree var)
2057*e4b17023SJohn Marino {
2058*e4b17023SJohn Marino   gimple stmt;
2059*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
2060*e4b17023SJohn Marino 
2061*e4b17023SJohn Marino   while (1)
2062*e4b17023SJohn Marino     {
2063*e4b17023SJohn Marino       if (TREE_CODE (var) != SSA_NAME || !has_zero_uses (var))
2064*e4b17023SJohn Marino 	return;
2065*e4b17023SJohn Marino       stmt = SSA_NAME_DEF_STMT (var);
2066*e4b17023SJohn Marino       if (!is_gimple_assign (stmt)
2067*e4b17023SJohn Marino 	  || !gimple_visited_p (stmt))
2068*e4b17023SJohn Marino 	return;
2069*e4b17023SJohn Marino       var = gimple_assign_rhs1 (stmt);
2070*e4b17023SJohn Marino       gsi = gsi_for_stmt (stmt);
2071*e4b17023SJohn Marino       gsi_remove (&gsi, true);
2072*e4b17023SJohn Marino       release_defs (stmt);
2073*e4b17023SJohn Marino     }
2074*e4b17023SJohn Marino }
2075*e4b17023SJohn Marino 
2076*e4b17023SJohn Marino /* This function checks three consequtive operands in
2077*e4b17023SJohn Marino    passed operands vector OPS starting from OPINDEX and
2078*e4b17023SJohn Marino    swaps two operands if it is profitable for binary operation
2079*e4b17023SJohn Marino    consuming OPINDEX + 1 abnd OPINDEX + 2 operands.
2080*e4b17023SJohn Marino 
2081*e4b17023SJohn Marino    We pair ops with the same rank if possible.
2082*e4b17023SJohn Marino 
2083*e4b17023SJohn Marino    The alternative we try is to see if STMT is a destructive
2084*e4b17023SJohn Marino    update style statement, which is like:
2085*e4b17023SJohn Marino    b = phi (a, ...)
2086*e4b17023SJohn Marino    a = c + b;
2087*e4b17023SJohn Marino    In that case, we want to use the destructive update form to
2088*e4b17023SJohn Marino    expose the possible vectorizer sum reduction opportunity.
2089*e4b17023SJohn Marino    In that case, the third operand will be the phi node. This
2090*e4b17023SJohn Marino    check is not performed if STMT is null.
2091*e4b17023SJohn Marino 
2092*e4b17023SJohn Marino    We could, of course, try to be better as noted above, and do a
2093*e4b17023SJohn Marino    lot of work to try to find these opportunities in >3 operand
2094*e4b17023SJohn Marino    cases, but it is unlikely to be worth it.  */
2095*e4b17023SJohn Marino 
2096*e4b17023SJohn Marino static void
2097*e4b17023SJohn Marino swap_ops_for_binary_stmt (VEC(operand_entry_t, heap) * ops,
2098*e4b17023SJohn Marino 			  unsigned int opindex, gimple stmt)
2099*e4b17023SJohn Marino {
2100*e4b17023SJohn Marino   operand_entry_t oe1, oe2, oe3;
2101*e4b17023SJohn Marino 
2102*e4b17023SJohn Marino   oe1 = VEC_index (operand_entry_t, ops, opindex);
2103*e4b17023SJohn Marino   oe2 = VEC_index (operand_entry_t, ops, opindex + 1);
2104*e4b17023SJohn Marino   oe3 = VEC_index (operand_entry_t, ops, opindex + 2);
2105*e4b17023SJohn Marino 
2106*e4b17023SJohn Marino   if ((oe1->rank == oe2->rank
2107*e4b17023SJohn Marino        && oe2->rank != oe3->rank)
2108*e4b17023SJohn Marino       || (stmt && is_phi_for_stmt (stmt, oe3->op)
2109*e4b17023SJohn Marino 	  && !is_phi_for_stmt (stmt, oe1->op)
2110*e4b17023SJohn Marino 	  && !is_phi_for_stmt (stmt, oe2->op)))
2111*e4b17023SJohn Marino     {
2112*e4b17023SJohn Marino       struct operand_entry temp = *oe3;
2113*e4b17023SJohn Marino       oe3->op = oe1->op;
2114*e4b17023SJohn Marino       oe3->rank = oe1->rank;
2115*e4b17023SJohn Marino       oe1->op = temp.op;
2116*e4b17023SJohn Marino       oe1->rank= temp.rank;
2117*e4b17023SJohn Marino     }
2118*e4b17023SJohn Marino   else if ((oe1->rank == oe3->rank
2119*e4b17023SJohn Marino 	    && oe2->rank != oe3->rank)
2120*e4b17023SJohn Marino 	   || (stmt && is_phi_for_stmt (stmt, oe2->op)
2121*e4b17023SJohn Marino 	       && !is_phi_for_stmt (stmt, oe1->op)
2122*e4b17023SJohn Marino 	       && !is_phi_for_stmt (stmt, oe3->op)))
2123*e4b17023SJohn Marino     {
2124*e4b17023SJohn Marino       struct operand_entry temp = *oe2;
2125*e4b17023SJohn Marino       oe2->op = oe1->op;
2126*e4b17023SJohn Marino       oe2->rank = oe1->rank;
2127*e4b17023SJohn Marino       oe1->op = temp.op;
2128*e4b17023SJohn Marino       oe1->rank= temp.rank;
2129*e4b17023SJohn Marino     }
2130*e4b17023SJohn Marino }
2131*e4b17023SJohn Marino 
2132*e4b17023SJohn Marino /* Recursively rewrite our linearized statements so that the operators
2133*e4b17023SJohn Marino    match those in OPS[OPINDEX], putting the computation in rank
2134*e4b17023SJohn Marino    order.  */
2135*e4b17023SJohn Marino 
2136*e4b17023SJohn Marino static void
2137*e4b17023SJohn Marino rewrite_expr_tree (gimple stmt, unsigned int opindex,
2138*e4b17023SJohn Marino 		   VEC(operand_entry_t, heap) * ops, bool moved)
2139*e4b17023SJohn Marino {
2140*e4b17023SJohn Marino   tree rhs1 = gimple_assign_rhs1 (stmt);
2141*e4b17023SJohn Marino   tree rhs2 = gimple_assign_rhs2 (stmt);
2142*e4b17023SJohn Marino   operand_entry_t oe;
2143*e4b17023SJohn Marino 
2144*e4b17023SJohn Marino   /* If we have three operands left, then we want to make sure the ones
2145*e4b17023SJohn Marino      that get the double binary op are chosen wisely.  */
2146*e4b17023SJohn Marino   if (opindex + 3 == VEC_length (operand_entry_t, ops))
2147*e4b17023SJohn Marino     swap_ops_for_binary_stmt (ops, opindex, stmt);
2148*e4b17023SJohn Marino 
2149*e4b17023SJohn Marino   /* The final recursion case for this function is that you have
2150*e4b17023SJohn Marino      exactly two operations left.
2151*e4b17023SJohn Marino      If we had one exactly one op in the entire list to start with, we
2152*e4b17023SJohn Marino      would have never called this function, and the tail recursion
2153*e4b17023SJohn Marino      rewrites them one at a time.  */
2154*e4b17023SJohn Marino   if (opindex + 2 == VEC_length (operand_entry_t, ops))
2155*e4b17023SJohn Marino     {
2156*e4b17023SJohn Marino       operand_entry_t oe1, oe2;
2157*e4b17023SJohn Marino 
2158*e4b17023SJohn Marino       oe1 = VEC_index (operand_entry_t, ops, opindex);
2159*e4b17023SJohn Marino       oe2 = VEC_index (operand_entry_t, ops, opindex + 1);
2160*e4b17023SJohn Marino 
2161*e4b17023SJohn Marino       if (rhs1 != oe1->op || rhs2 != oe2->op)
2162*e4b17023SJohn Marino 	{
2163*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2164*e4b17023SJohn Marino 	    {
2165*e4b17023SJohn Marino 	      fprintf (dump_file, "Transforming ");
2166*e4b17023SJohn Marino 	      print_gimple_stmt (dump_file, stmt, 0, 0);
2167*e4b17023SJohn Marino 	    }
2168*e4b17023SJohn Marino 
2169*e4b17023SJohn Marino 	  gimple_assign_set_rhs1 (stmt, oe1->op);
2170*e4b17023SJohn Marino 	  gimple_assign_set_rhs2 (stmt, oe2->op);
2171*e4b17023SJohn Marino 	  update_stmt (stmt);
2172*e4b17023SJohn Marino 	  if (rhs1 != oe1->op && rhs1 != oe2->op)
2173*e4b17023SJohn Marino 	    remove_visited_stmt_chain (rhs1);
2174*e4b17023SJohn Marino 
2175*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2176*e4b17023SJohn Marino 	    {
2177*e4b17023SJohn Marino 	      fprintf (dump_file, " into ");
2178*e4b17023SJohn Marino 	      print_gimple_stmt (dump_file, stmt, 0, 0);
2179*e4b17023SJohn Marino 	    }
2180*e4b17023SJohn Marino 
2181*e4b17023SJohn Marino 	}
2182*e4b17023SJohn Marino       return;
2183*e4b17023SJohn Marino     }
2184*e4b17023SJohn Marino 
2185*e4b17023SJohn Marino   /* If we hit here, we should have 3 or more ops left.  */
2186*e4b17023SJohn Marino   gcc_assert (opindex + 2 < VEC_length (operand_entry_t, ops));
2187*e4b17023SJohn Marino 
2188*e4b17023SJohn Marino   /* Rewrite the next operator.  */
2189*e4b17023SJohn Marino   oe = VEC_index (operand_entry_t, ops, opindex);
2190*e4b17023SJohn Marino 
2191*e4b17023SJohn Marino   if (oe->op != rhs2)
2192*e4b17023SJohn Marino     {
2193*e4b17023SJohn Marino       if (!moved)
2194*e4b17023SJohn Marino 	{
2195*e4b17023SJohn Marino 	  gimple_stmt_iterator gsinow, gsirhs1;
2196*e4b17023SJohn Marino 	  gimple stmt1 = stmt, stmt2;
2197*e4b17023SJohn Marino 	  unsigned int count;
2198*e4b17023SJohn Marino 
2199*e4b17023SJohn Marino 	  gsinow = gsi_for_stmt (stmt);
2200*e4b17023SJohn Marino 	  count = VEC_length (operand_entry_t, ops) - opindex - 2;
2201*e4b17023SJohn Marino 	  while (count-- != 0)
2202*e4b17023SJohn Marino 	    {
2203*e4b17023SJohn Marino 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
2204*e4b17023SJohn Marino 	      gsirhs1 = gsi_for_stmt (stmt2);
2205*e4b17023SJohn Marino 	      gsi_move_before (&gsirhs1, &gsinow);
2206*e4b17023SJohn Marino 	      gsi_prev (&gsinow);
2207*e4b17023SJohn Marino 	      stmt1 = stmt2;
2208*e4b17023SJohn Marino 	    }
2209*e4b17023SJohn Marino 	  moved = true;
2210*e4b17023SJohn Marino 	}
2211*e4b17023SJohn Marino 
2212*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2213*e4b17023SJohn Marino 	{
2214*e4b17023SJohn Marino 	  fprintf (dump_file, "Transforming ");
2215*e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, stmt, 0, 0);
2216*e4b17023SJohn Marino 	}
2217*e4b17023SJohn Marino 
2218*e4b17023SJohn Marino       gimple_assign_set_rhs2 (stmt, oe->op);
2219*e4b17023SJohn Marino       update_stmt (stmt);
2220*e4b17023SJohn Marino 
2221*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2222*e4b17023SJohn Marino 	{
2223*e4b17023SJohn Marino 	  fprintf (dump_file, " into ");
2224*e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, stmt, 0, 0);
2225*e4b17023SJohn Marino 	}
2226*e4b17023SJohn Marino     }
2227*e4b17023SJohn Marino   /* Recurse on the LHS of the binary operator, which is guaranteed to
2228*e4b17023SJohn Marino      be the non-leaf side.  */
2229*e4b17023SJohn Marino   rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops, moved);
2230*e4b17023SJohn Marino }
2231*e4b17023SJohn Marino 
2232*e4b17023SJohn Marino /* Find out how many cycles we need to compute statements chain.
2233*e4b17023SJohn Marino    OPS_NUM holds number os statements in a chain.  CPU_WIDTH is a
2234*e4b17023SJohn Marino    maximum number of independent statements we may execute per cycle.  */
2235*e4b17023SJohn Marino 
2236*e4b17023SJohn Marino static int
2237*e4b17023SJohn Marino get_required_cycles (int ops_num, int cpu_width)
2238*e4b17023SJohn Marino {
2239*e4b17023SJohn Marino   int res;
2240*e4b17023SJohn Marino   int elog;
2241*e4b17023SJohn Marino   unsigned int rest;
2242*e4b17023SJohn Marino 
2243*e4b17023SJohn Marino   /* While we have more than 2 * cpu_width operands
2244*e4b17023SJohn Marino      we may reduce number of operands by cpu_width
2245*e4b17023SJohn Marino      per cycle.  */
2246*e4b17023SJohn Marino   res = ops_num / (2 * cpu_width);
2247*e4b17023SJohn Marino 
2248*e4b17023SJohn Marino   /* Remained operands count may be reduced twice per cycle
2249*e4b17023SJohn Marino      until we have only one operand.  */
2250*e4b17023SJohn Marino   rest = (unsigned)(ops_num - res * cpu_width);
2251*e4b17023SJohn Marino   elog = exact_log2 (rest);
2252*e4b17023SJohn Marino   if (elog >= 0)
2253*e4b17023SJohn Marino     res += elog;
2254*e4b17023SJohn Marino   else
2255*e4b17023SJohn Marino     res += floor_log2 (rest) + 1;
2256*e4b17023SJohn Marino 
2257*e4b17023SJohn Marino   return res;
2258*e4b17023SJohn Marino }
2259*e4b17023SJohn Marino 
2260*e4b17023SJohn Marino /* Returns an optimal number of registers to use for computation of
2261*e4b17023SJohn Marino    given statements.  */
2262*e4b17023SJohn Marino 
2263*e4b17023SJohn Marino static int
2264*e4b17023SJohn Marino get_reassociation_width (int ops_num, enum tree_code opc,
2265*e4b17023SJohn Marino 			 enum machine_mode mode)
2266*e4b17023SJohn Marino {
2267*e4b17023SJohn Marino   int param_width = PARAM_VALUE (PARAM_TREE_REASSOC_WIDTH);
2268*e4b17023SJohn Marino   int width;
2269*e4b17023SJohn Marino   int width_min;
2270*e4b17023SJohn Marino   int cycles_best;
2271*e4b17023SJohn Marino 
2272*e4b17023SJohn Marino   if (param_width > 0)
2273*e4b17023SJohn Marino     width = param_width;
2274*e4b17023SJohn Marino   else
2275*e4b17023SJohn Marino     width = targetm.sched.reassociation_width (opc, mode);
2276*e4b17023SJohn Marino 
2277*e4b17023SJohn Marino   if (width == 1)
2278*e4b17023SJohn Marino     return width;
2279*e4b17023SJohn Marino 
2280*e4b17023SJohn Marino   /* Get the minimal time required for sequence computation.  */
2281*e4b17023SJohn Marino   cycles_best = get_required_cycles (ops_num, width);
2282*e4b17023SJohn Marino 
2283*e4b17023SJohn Marino   /* Check if we may use less width and still compute sequence for
2284*e4b17023SJohn Marino      the same time.  It will allow us to reduce registers usage.
2285*e4b17023SJohn Marino      get_required_cycles is monotonically increasing with lower width
2286*e4b17023SJohn Marino      so we can perform a binary search for the minimal width that still
2287*e4b17023SJohn Marino      results in the optimal cycle count.  */
2288*e4b17023SJohn Marino   width_min = 1;
2289*e4b17023SJohn Marino   while (width > width_min)
2290*e4b17023SJohn Marino     {
2291*e4b17023SJohn Marino       int width_mid = (width + width_min) / 2;
2292*e4b17023SJohn Marino 
2293*e4b17023SJohn Marino       if (get_required_cycles (ops_num, width_mid) == cycles_best)
2294*e4b17023SJohn Marino 	width = width_mid;
2295*e4b17023SJohn Marino       else if (width_min < width_mid)
2296*e4b17023SJohn Marino 	width_min = width_mid;
2297*e4b17023SJohn Marino       else
2298*e4b17023SJohn Marino 	break;
2299*e4b17023SJohn Marino     }
2300*e4b17023SJohn Marino 
2301*e4b17023SJohn Marino   return width;
2302*e4b17023SJohn Marino }
2303*e4b17023SJohn Marino 
2304*e4b17023SJohn Marino /* Recursively rewrite our linearized statements so that the operators
2305*e4b17023SJohn Marino    match those in OPS[OPINDEX], putting the computation in rank
2306*e4b17023SJohn Marino    order and trying to allow operations to be executed in
2307*e4b17023SJohn Marino    parallel.  */
2308*e4b17023SJohn Marino 
2309*e4b17023SJohn Marino static void
2310*e4b17023SJohn Marino rewrite_expr_tree_parallel (gimple stmt, int width,
2311*e4b17023SJohn Marino 			    VEC(operand_entry_t, heap) * ops)
2312*e4b17023SJohn Marino {
2313*e4b17023SJohn Marino   enum tree_code opcode = gimple_assign_rhs_code (stmt);
2314*e4b17023SJohn Marino   int op_num = VEC_length (operand_entry_t, ops);
2315*e4b17023SJohn Marino   int stmt_num = op_num - 1;
2316*e4b17023SJohn Marino   gimple *stmts = XALLOCAVEC (gimple, stmt_num);
2317*e4b17023SJohn Marino   int op_index = op_num - 1;
2318*e4b17023SJohn Marino   int stmt_index = 0;
2319*e4b17023SJohn Marino   int ready_stmts_end = 0;
2320*e4b17023SJohn Marino   int i = 0;
2321*e4b17023SJohn Marino   tree last_rhs1 = gimple_assign_rhs1 (stmt);
2322*e4b17023SJohn Marino   tree lhs_var;
2323*e4b17023SJohn Marino 
2324*e4b17023SJohn Marino   /* We start expression rewriting from the top statements.
2325*e4b17023SJohn Marino      So, in this loop we create a full list of statements
2326*e4b17023SJohn Marino      we will work with.  */
2327*e4b17023SJohn Marino   stmts[stmt_num - 1] = stmt;
2328*e4b17023SJohn Marino   for (i = stmt_num - 2; i >= 0; i--)
2329*e4b17023SJohn Marino     stmts[i] = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmts[i+1]));
2330*e4b17023SJohn Marino 
2331*e4b17023SJohn Marino   lhs_var = create_tmp_reg (TREE_TYPE (last_rhs1), NULL);
2332*e4b17023SJohn Marino   add_referenced_var (lhs_var);
2333*e4b17023SJohn Marino 
2334*e4b17023SJohn Marino   for (i = 0; i < stmt_num; i++)
2335*e4b17023SJohn Marino     {
2336*e4b17023SJohn Marino       tree op1, op2;
2337*e4b17023SJohn Marino 
2338*e4b17023SJohn Marino       /* Determine whether we should use results of
2339*e4b17023SJohn Marino 	 already handled statements or not.  */
2340*e4b17023SJohn Marino       if (ready_stmts_end == 0
2341*e4b17023SJohn Marino 	  && (i - stmt_index >= width || op_index < 1))
2342*e4b17023SJohn Marino 	ready_stmts_end = i;
2343*e4b17023SJohn Marino 
2344*e4b17023SJohn Marino       /* Now we choose operands for the next statement.  Non zero
2345*e4b17023SJohn Marino 	 value in ready_stmts_end means here that we should use
2346*e4b17023SJohn Marino 	 the result of already generated statements as new operand.  */
2347*e4b17023SJohn Marino       if (ready_stmts_end > 0)
2348*e4b17023SJohn Marino 	{
2349*e4b17023SJohn Marino 	  op1 = gimple_assign_lhs (stmts[stmt_index++]);
2350*e4b17023SJohn Marino 	  if (ready_stmts_end > stmt_index)
2351*e4b17023SJohn Marino 	    op2 = gimple_assign_lhs (stmts[stmt_index++]);
2352*e4b17023SJohn Marino 	  else if (op_index >= 0)
2353*e4b17023SJohn Marino 	    op2 = VEC_index (operand_entry_t, ops, op_index--)->op;
2354*e4b17023SJohn Marino 	  else
2355*e4b17023SJohn Marino 	    {
2356*e4b17023SJohn Marino 	      gcc_assert (stmt_index < i);
2357*e4b17023SJohn Marino 	      op2 = gimple_assign_lhs (stmts[stmt_index++]);
2358*e4b17023SJohn Marino 	    }
2359*e4b17023SJohn Marino 
2360*e4b17023SJohn Marino 	  if (stmt_index >= ready_stmts_end)
2361*e4b17023SJohn Marino 	    ready_stmts_end = 0;
2362*e4b17023SJohn Marino 	}
2363*e4b17023SJohn Marino       else
2364*e4b17023SJohn Marino 	{
2365*e4b17023SJohn Marino 	  if (op_index > 1)
2366*e4b17023SJohn Marino 	    swap_ops_for_binary_stmt (ops, op_index - 2, NULL);
2367*e4b17023SJohn Marino 	  op2 = VEC_index (operand_entry_t, ops, op_index--)->op;
2368*e4b17023SJohn Marino 	  op1 = VEC_index (operand_entry_t, ops, op_index--)->op;
2369*e4b17023SJohn Marino 	}
2370*e4b17023SJohn Marino 
2371*e4b17023SJohn Marino       /* If we emit the last statement then we should put
2372*e4b17023SJohn Marino 	 operands into the last statement.  It will also
2373*e4b17023SJohn Marino 	 break the loop.  */
2374*e4b17023SJohn Marino       if (op_index < 0 && stmt_index == i)
2375*e4b17023SJohn Marino 	i = stmt_num - 1;
2376*e4b17023SJohn Marino 
2377*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2378*e4b17023SJohn Marino 	{
2379*e4b17023SJohn Marino 	  fprintf (dump_file, "Transforming ");
2380*e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, stmts[i], 0, 0);
2381*e4b17023SJohn Marino 	}
2382*e4b17023SJohn Marino 
2383*e4b17023SJohn Marino       /* We keep original statement only for the last one.  All
2384*e4b17023SJohn Marino 	 others are recreated.  */
2385*e4b17023SJohn Marino       if (i == stmt_num - 1)
2386*e4b17023SJohn Marino 	{
2387*e4b17023SJohn Marino 	  gimple_assign_set_rhs1 (stmts[i], op1);
2388*e4b17023SJohn Marino 	  gimple_assign_set_rhs2 (stmts[i], op2);
2389*e4b17023SJohn Marino 	  update_stmt (stmts[i]);
2390*e4b17023SJohn Marino 	}
2391*e4b17023SJohn Marino       else
2392*e4b17023SJohn Marino 	stmts[i] = build_and_add_sum (lhs_var, op1, op2, opcode);
2393*e4b17023SJohn Marino 
2394*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2395*e4b17023SJohn Marino 	{
2396*e4b17023SJohn Marino 	  fprintf (dump_file, " into ");
2397*e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, stmts[i], 0, 0);
2398*e4b17023SJohn Marino 	}
2399*e4b17023SJohn Marino     }
2400*e4b17023SJohn Marino 
2401*e4b17023SJohn Marino   remove_visited_stmt_chain (last_rhs1);
2402*e4b17023SJohn Marino }
2403*e4b17023SJohn Marino 
2404*e4b17023SJohn Marino /* Transform STMT, which is really (A +B) + (C + D) into the left
2405*e4b17023SJohn Marino    linear form, ((A+B)+C)+D.
2406*e4b17023SJohn Marino    Recurse on D if necessary.  */
2407*e4b17023SJohn Marino 
2408*e4b17023SJohn Marino static void
2409*e4b17023SJohn Marino linearize_expr (gimple stmt)
2410*e4b17023SJohn Marino {
2411*e4b17023SJohn Marino   gimple_stmt_iterator gsinow, gsirhs;
2412*e4b17023SJohn Marino   gimple binlhs = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
2413*e4b17023SJohn Marino   gimple binrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
2414*e4b17023SJohn Marino   enum tree_code rhscode = gimple_assign_rhs_code (stmt);
2415*e4b17023SJohn Marino   gimple newbinrhs = NULL;
2416*e4b17023SJohn Marino   struct loop *loop = loop_containing_stmt (stmt);
2417*e4b17023SJohn Marino 
2418*e4b17023SJohn Marino   gcc_assert (is_reassociable_op (binlhs, rhscode, loop)
2419*e4b17023SJohn Marino 	      && is_reassociable_op (binrhs, rhscode, loop));
2420*e4b17023SJohn Marino 
2421*e4b17023SJohn Marino   gsinow = gsi_for_stmt (stmt);
2422*e4b17023SJohn Marino   gsirhs = gsi_for_stmt (binrhs);
2423*e4b17023SJohn Marino   gsi_move_before (&gsirhs, &gsinow);
2424*e4b17023SJohn Marino 
2425*e4b17023SJohn Marino   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
2426*e4b17023SJohn Marino   gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs));
2427*e4b17023SJohn Marino   gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (binrhs));
2428*e4b17023SJohn Marino 
2429*e4b17023SJohn Marino   if (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
2430*e4b17023SJohn Marino     newbinrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
2431*e4b17023SJohn Marino 
2432*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2433*e4b17023SJohn Marino     {
2434*e4b17023SJohn Marino       fprintf (dump_file, "Linearized: ");
2435*e4b17023SJohn Marino       print_gimple_stmt (dump_file, stmt, 0, 0);
2436*e4b17023SJohn Marino     }
2437*e4b17023SJohn Marino 
2438*e4b17023SJohn Marino   reassociate_stats.linearized++;
2439*e4b17023SJohn Marino   update_stmt (binrhs);
2440*e4b17023SJohn Marino   update_stmt (binlhs);
2441*e4b17023SJohn Marino   update_stmt (stmt);
2442*e4b17023SJohn Marino 
2443*e4b17023SJohn Marino   gimple_set_visited (stmt, true);
2444*e4b17023SJohn Marino   gimple_set_visited (binlhs, true);
2445*e4b17023SJohn Marino   gimple_set_visited (binrhs, true);
2446*e4b17023SJohn Marino 
2447*e4b17023SJohn Marino   /* Tail recurse on the new rhs if it still needs reassociation.  */
2448*e4b17023SJohn Marino   if (newbinrhs && is_reassociable_op (newbinrhs, rhscode, loop))
2449*e4b17023SJohn Marino     /* ??? This should probably be linearize_expr (newbinrhs) but I don't
2450*e4b17023SJohn Marino 	   want to change the algorithm while converting to tuples.  */
2451*e4b17023SJohn Marino     linearize_expr (stmt);
2452*e4b17023SJohn Marino }
2453*e4b17023SJohn Marino 
2454*e4b17023SJohn Marino /* If LHS has a single immediate use that is a GIMPLE_ASSIGN statement, return
2455*e4b17023SJohn Marino    it.  Otherwise, return NULL.  */
2456*e4b17023SJohn Marino 
2457*e4b17023SJohn Marino static gimple
2458*e4b17023SJohn Marino get_single_immediate_use (tree lhs)
2459*e4b17023SJohn Marino {
2460*e4b17023SJohn Marino   use_operand_p immuse;
2461*e4b17023SJohn Marino   gimple immusestmt;
2462*e4b17023SJohn Marino 
2463*e4b17023SJohn Marino   if (TREE_CODE (lhs) == SSA_NAME
2464*e4b17023SJohn Marino       && single_imm_use (lhs, &immuse, &immusestmt)
2465*e4b17023SJohn Marino       && is_gimple_assign (immusestmt))
2466*e4b17023SJohn Marino     return immusestmt;
2467*e4b17023SJohn Marino 
2468*e4b17023SJohn Marino   return NULL;
2469*e4b17023SJohn Marino }
2470*e4b17023SJohn Marino 
2471*e4b17023SJohn Marino /* Recursively negate the value of TONEGATE, and return the SSA_NAME
2472*e4b17023SJohn Marino    representing the negated value.  Insertions of any necessary
2473*e4b17023SJohn Marino    instructions go before GSI.
2474*e4b17023SJohn Marino    This function is recursive in that, if you hand it "a_5" as the
2475*e4b17023SJohn Marino    value to negate, and a_5 is defined by "a_5 = b_3 + b_4", it will
2476*e4b17023SJohn Marino    transform b_3 + b_4 into a_5 = -b_3 + -b_4.  */
2477*e4b17023SJohn Marino 
2478*e4b17023SJohn Marino static tree
2479*e4b17023SJohn Marino negate_value (tree tonegate, gimple_stmt_iterator *gsi)
2480*e4b17023SJohn Marino {
2481*e4b17023SJohn Marino   gimple negatedefstmt= NULL;
2482*e4b17023SJohn Marino   tree resultofnegate;
2483*e4b17023SJohn Marino 
2484*e4b17023SJohn Marino   /* If we are trying to negate a name, defined by an add, negate the
2485*e4b17023SJohn Marino      add operands instead.  */
2486*e4b17023SJohn Marino   if (TREE_CODE (tonegate) == SSA_NAME)
2487*e4b17023SJohn Marino     negatedefstmt = SSA_NAME_DEF_STMT (tonegate);
2488*e4b17023SJohn Marino   if (TREE_CODE (tonegate) == SSA_NAME
2489*e4b17023SJohn Marino       && is_gimple_assign (negatedefstmt)
2490*e4b17023SJohn Marino       && TREE_CODE (gimple_assign_lhs (negatedefstmt)) == SSA_NAME
2491*e4b17023SJohn Marino       && has_single_use (gimple_assign_lhs (negatedefstmt))
2492*e4b17023SJohn Marino       && gimple_assign_rhs_code (negatedefstmt) == PLUS_EXPR)
2493*e4b17023SJohn Marino     {
2494*e4b17023SJohn Marino       gimple_stmt_iterator gsi;
2495*e4b17023SJohn Marino       tree rhs1 = gimple_assign_rhs1 (negatedefstmt);
2496*e4b17023SJohn Marino       tree rhs2 = gimple_assign_rhs2 (negatedefstmt);
2497*e4b17023SJohn Marino 
2498*e4b17023SJohn Marino       gsi = gsi_for_stmt (negatedefstmt);
2499*e4b17023SJohn Marino       rhs1 = negate_value (rhs1, &gsi);
2500*e4b17023SJohn Marino       gimple_assign_set_rhs1 (negatedefstmt, rhs1);
2501*e4b17023SJohn Marino 
2502*e4b17023SJohn Marino       gsi = gsi_for_stmt (negatedefstmt);
2503*e4b17023SJohn Marino       rhs2 = negate_value (rhs2, &gsi);
2504*e4b17023SJohn Marino       gimple_assign_set_rhs2 (negatedefstmt, rhs2);
2505*e4b17023SJohn Marino 
2506*e4b17023SJohn Marino       update_stmt (negatedefstmt);
2507*e4b17023SJohn Marino       return gimple_assign_lhs (negatedefstmt);
2508*e4b17023SJohn Marino     }
2509*e4b17023SJohn Marino 
2510*e4b17023SJohn Marino   tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
2511*e4b17023SJohn Marino   resultofnegate = force_gimple_operand_gsi (gsi, tonegate, true,
2512*e4b17023SJohn Marino 					     NULL_TREE, true, GSI_SAME_STMT);
2513*e4b17023SJohn Marino   return resultofnegate;
2514*e4b17023SJohn Marino }
2515*e4b17023SJohn Marino 
2516*e4b17023SJohn Marino /* Return true if we should break up the subtract in STMT into an add
2517*e4b17023SJohn Marino    with negate.  This is true when we the subtract operands are really
2518*e4b17023SJohn Marino    adds, or the subtract itself is used in an add expression.  In
2519*e4b17023SJohn Marino    either case, breaking up the subtract into an add with negate
2520*e4b17023SJohn Marino    exposes the adds to reassociation.  */
2521*e4b17023SJohn Marino 
2522*e4b17023SJohn Marino static bool
2523*e4b17023SJohn Marino should_break_up_subtract (gimple stmt)
2524*e4b17023SJohn Marino {
2525*e4b17023SJohn Marino   tree lhs = gimple_assign_lhs (stmt);
2526*e4b17023SJohn Marino   tree binlhs = gimple_assign_rhs1 (stmt);
2527*e4b17023SJohn Marino   tree binrhs = gimple_assign_rhs2 (stmt);
2528*e4b17023SJohn Marino   gimple immusestmt;
2529*e4b17023SJohn Marino   struct loop *loop = loop_containing_stmt (stmt);
2530*e4b17023SJohn Marino 
2531*e4b17023SJohn Marino   if (TREE_CODE (binlhs) == SSA_NAME
2532*e4b17023SJohn Marino       && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR, loop))
2533*e4b17023SJohn Marino     return true;
2534*e4b17023SJohn Marino 
2535*e4b17023SJohn Marino   if (TREE_CODE (binrhs) == SSA_NAME
2536*e4b17023SJohn Marino       && is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), PLUS_EXPR, loop))
2537*e4b17023SJohn Marino     return true;
2538*e4b17023SJohn Marino 
2539*e4b17023SJohn Marino   if (TREE_CODE (lhs) == SSA_NAME
2540*e4b17023SJohn Marino       && (immusestmt = get_single_immediate_use (lhs))
2541*e4b17023SJohn Marino       && is_gimple_assign (immusestmt)
2542*e4b17023SJohn Marino       && (gimple_assign_rhs_code (immusestmt) == PLUS_EXPR
2543*e4b17023SJohn Marino 	  ||  gimple_assign_rhs_code (immusestmt) == MULT_EXPR))
2544*e4b17023SJohn Marino     return true;
2545*e4b17023SJohn Marino   return false;
2546*e4b17023SJohn Marino }
2547*e4b17023SJohn Marino 
2548*e4b17023SJohn Marino /* Transform STMT from A - B into A + -B.  */
2549*e4b17023SJohn Marino 
2550*e4b17023SJohn Marino static void
2551*e4b17023SJohn Marino break_up_subtract (gimple stmt, gimple_stmt_iterator *gsip)
2552*e4b17023SJohn Marino {
2553*e4b17023SJohn Marino   tree rhs1 = gimple_assign_rhs1 (stmt);
2554*e4b17023SJohn Marino   tree rhs2 = gimple_assign_rhs2 (stmt);
2555*e4b17023SJohn Marino 
2556*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2557*e4b17023SJohn Marino     {
2558*e4b17023SJohn Marino       fprintf (dump_file, "Breaking up subtract ");
2559*e4b17023SJohn Marino       print_gimple_stmt (dump_file, stmt, 0, 0);
2560*e4b17023SJohn Marino     }
2561*e4b17023SJohn Marino 
2562*e4b17023SJohn Marino   rhs2 = negate_value (rhs2, gsip);
2563*e4b17023SJohn Marino   gimple_assign_set_rhs_with_ops (gsip, PLUS_EXPR, rhs1, rhs2);
2564*e4b17023SJohn Marino   update_stmt (stmt);
2565*e4b17023SJohn Marino }
2566*e4b17023SJohn Marino 
2567*e4b17023SJohn Marino /* Recursively linearize a binary expression that is the RHS of STMT.
2568*e4b17023SJohn Marino    Place the operands of the expression tree in the vector named OPS.  */
2569*e4b17023SJohn Marino 
2570*e4b17023SJohn Marino static void
2571*e4b17023SJohn Marino linearize_expr_tree (VEC(operand_entry_t, heap) **ops, gimple stmt,
2572*e4b17023SJohn Marino 		     bool is_associative, bool set_visited)
2573*e4b17023SJohn Marino {
2574*e4b17023SJohn Marino   tree binlhs = gimple_assign_rhs1 (stmt);
2575*e4b17023SJohn Marino   tree binrhs = gimple_assign_rhs2 (stmt);
2576*e4b17023SJohn Marino   gimple binlhsdef, binrhsdef;
2577*e4b17023SJohn Marino   bool binlhsisreassoc = false;
2578*e4b17023SJohn Marino   bool binrhsisreassoc = false;
2579*e4b17023SJohn Marino   enum tree_code rhscode = gimple_assign_rhs_code (stmt);
2580*e4b17023SJohn Marino   struct loop *loop = loop_containing_stmt (stmt);
2581*e4b17023SJohn Marino 
2582*e4b17023SJohn Marino   if (set_visited)
2583*e4b17023SJohn Marino     gimple_set_visited (stmt, true);
2584*e4b17023SJohn Marino 
2585*e4b17023SJohn Marino   if (TREE_CODE (binlhs) == SSA_NAME)
2586*e4b17023SJohn Marino     {
2587*e4b17023SJohn Marino       binlhsdef = SSA_NAME_DEF_STMT (binlhs);
2588*e4b17023SJohn Marino       binlhsisreassoc = (is_reassociable_op (binlhsdef, rhscode, loop)
2589*e4b17023SJohn Marino 			 && !stmt_could_throw_p (binlhsdef));
2590*e4b17023SJohn Marino     }
2591*e4b17023SJohn Marino 
2592*e4b17023SJohn Marino   if (TREE_CODE (binrhs) == SSA_NAME)
2593*e4b17023SJohn Marino     {
2594*e4b17023SJohn Marino       binrhsdef = SSA_NAME_DEF_STMT (binrhs);
2595*e4b17023SJohn Marino       binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
2596*e4b17023SJohn Marino 			 && !stmt_could_throw_p (binrhsdef));
2597*e4b17023SJohn Marino     }
2598*e4b17023SJohn Marino 
2599*e4b17023SJohn Marino   /* If the LHS is not reassociable, but the RHS is, we need to swap
2600*e4b17023SJohn Marino      them.  If neither is reassociable, there is nothing we can do, so
2601*e4b17023SJohn Marino      just put them in the ops vector.  If the LHS is reassociable,
2602*e4b17023SJohn Marino      linearize it.  If both are reassociable, then linearize the RHS
2603*e4b17023SJohn Marino      and the LHS.  */
2604*e4b17023SJohn Marino 
2605*e4b17023SJohn Marino   if (!binlhsisreassoc)
2606*e4b17023SJohn Marino     {
2607*e4b17023SJohn Marino       tree temp;
2608*e4b17023SJohn Marino 
2609*e4b17023SJohn Marino       /* If this is not a associative operation like division, give up.  */
2610*e4b17023SJohn Marino       if (!is_associative)
2611*e4b17023SJohn Marino 	{
2612*e4b17023SJohn Marino 	  add_to_ops_vec (ops, binrhs);
2613*e4b17023SJohn Marino 	  return;
2614*e4b17023SJohn Marino 	}
2615*e4b17023SJohn Marino 
2616*e4b17023SJohn Marino       if (!binrhsisreassoc)
2617*e4b17023SJohn Marino 	{
2618*e4b17023SJohn Marino 	  add_to_ops_vec (ops, binrhs);
2619*e4b17023SJohn Marino 	  add_to_ops_vec (ops, binlhs);
2620*e4b17023SJohn Marino 	  return;
2621*e4b17023SJohn Marino 	}
2622*e4b17023SJohn Marino 
2623*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2624*e4b17023SJohn Marino 	{
2625*e4b17023SJohn Marino 	  fprintf (dump_file, "swapping operands of ");
2626*e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, stmt, 0, 0);
2627*e4b17023SJohn Marino 	}
2628*e4b17023SJohn Marino 
2629*e4b17023SJohn Marino       swap_tree_operands (stmt,
2630*e4b17023SJohn Marino 			  gimple_assign_rhs1_ptr (stmt),
2631*e4b17023SJohn Marino 			  gimple_assign_rhs2_ptr (stmt));
2632*e4b17023SJohn Marino       update_stmt (stmt);
2633*e4b17023SJohn Marino 
2634*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2635*e4b17023SJohn Marino 	{
2636*e4b17023SJohn Marino 	  fprintf (dump_file, " is now ");
2637*e4b17023SJohn Marino 	  print_gimple_stmt (dump_file, stmt, 0, 0);
2638*e4b17023SJohn Marino 	}
2639*e4b17023SJohn Marino 
2640*e4b17023SJohn Marino       /* We want to make it so the lhs is always the reassociative op,
2641*e4b17023SJohn Marino 	 so swap.  */
2642*e4b17023SJohn Marino       temp = binlhs;
2643*e4b17023SJohn Marino       binlhs = binrhs;
2644*e4b17023SJohn Marino       binrhs = temp;
2645*e4b17023SJohn Marino     }
2646*e4b17023SJohn Marino   else if (binrhsisreassoc)
2647*e4b17023SJohn Marino     {
2648*e4b17023SJohn Marino       linearize_expr (stmt);
2649*e4b17023SJohn Marino       binlhs = gimple_assign_rhs1 (stmt);
2650*e4b17023SJohn Marino       binrhs = gimple_assign_rhs2 (stmt);
2651*e4b17023SJohn Marino     }
2652*e4b17023SJohn Marino 
2653*e4b17023SJohn Marino   gcc_assert (TREE_CODE (binrhs) != SSA_NAME
2654*e4b17023SJohn Marino 	      || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
2655*e4b17023SJohn Marino 				      rhscode, loop));
2656*e4b17023SJohn Marino   linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs),
2657*e4b17023SJohn Marino 		       is_associative, set_visited);
2658*e4b17023SJohn Marino   add_to_ops_vec (ops, binrhs);
2659*e4b17023SJohn Marino }
2660*e4b17023SJohn Marino 
2661*e4b17023SJohn Marino /* Repropagate the negates back into subtracts, since no other pass
2662*e4b17023SJohn Marino    currently does it.  */
2663*e4b17023SJohn Marino 
2664*e4b17023SJohn Marino static void
2665*e4b17023SJohn Marino repropagate_negates (void)
2666*e4b17023SJohn Marino {
2667*e4b17023SJohn Marino   unsigned int i = 0;
2668*e4b17023SJohn Marino   tree negate;
2669*e4b17023SJohn Marino 
2670*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, plus_negates, i, negate)
2671*e4b17023SJohn Marino     {
2672*e4b17023SJohn Marino       gimple user = get_single_immediate_use (negate);
2673*e4b17023SJohn Marino 
2674*e4b17023SJohn Marino       if (!user || !is_gimple_assign (user))
2675*e4b17023SJohn Marino 	continue;
2676*e4b17023SJohn Marino 
2677*e4b17023SJohn Marino       /* The negate operand can be either operand of a PLUS_EXPR
2678*e4b17023SJohn Marino 	 (it can be the LHS if the RHS is a constant for example).
2679*e4b17023SJohn Marino 
2680*e4b17023SJohn Marino 	 Force the negate operand to the RHS of the PLUS_EXPR, then
2681*e4b17023SJohn Marino 	 transform the PLUS_EXPR into a MINUS_EXPR.  */
2682*e4b17023SJohn Marino       if (gimple_assign_rhs_code (user) == PLUS_EXPR)
2683*e4b17023SJohn Marino 	{
2684*e4b17023SJohn Marino 	  /* If the negated operand appears on the LHS of the
2685*e4b17023SJohn Marino 	     PLUS_EXPR, exchange the operands of the PLUS_EXPR
2686*e4b17023SJohn Marino 	     to force the negated operand to the RHS of the PLUS_EXPR.  */
2687*e4b17023SJohn Marino 	  if (gimple_assign_rhs1 (user) == negate)
2688*e4b17023SJohn Marino 	    {
2689*e4b17023SJohn Marino 	      swap_tree_operands (user,
2690*e4b17023SJohn Marino 				  gimple_assign_rhs1_ptr (user),
2691*e4b17023SJohn Marino 				  gimple_assign_rhs2_ptr (user));
2692*e4b17023SJohn Marino 	    }
2693*e4b17023SJohn Marino 
2694*e4b17023SJohn Marino 	  /* Now transform the PLUS_EXPR into a MINUS_EXPR and replace
2695*e4b17023SJohn Marino 	     the RHS of the PLUS_EXPR with the operand of the NEGATE_EXPR.  */
2696*e4b17023SJohn Marino 	  if (gimple_assign_rhs2 (user) == negate)
2697*e4b17023SJohn Marino 	    {
2698*e4b17023SJohn Marino 	      tree rhs1 = gimple_assign_rhs1 (user);
2699*e4b17023SJohn Marino 	      tree rhs2 = get_unary_op (negate, NEGATE_EXPR);
2700*e4b17023SJohn Marino 	      gimple_stmt_iterator gsi = gsi_for_stmt (user);
2701*e4b17023SJohn Marino 	      gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, rhs1, rhs2);
2702*e4b17023SJohn Marino 	      update_stmt (user);
2703*e4b17023SJohn Marino 	    }
2704*e4b17023SJohn Marino 	}
2705*e4b17023SJohn Marino       else if (gimple_assign_rhs_code (user) == MINUS_EXPR)
2706*e4b17023SJohn Marino 	{
2707*e4b17023SJohn Marino 	  if (gimple_assign_rhs1 (user) == negate)
2708*e4b17023SJohn Marino 	    {
2709*e4b17023SJohn Marino 	      /* We have
2710*e4b17023SJohn Marino 	           x = -a
2711*e4b17023SJohn Marino 		   y = x - b
2712*e4b17023SJohn Marino 		 which we transform into
2713*e4b17023SJohn Marino 		   x = a + b
2714*e4b17023SJohn Marino 		   y = -x .
2715*e4b17023SJohn Marino 		 This pushes down the negate which we possibly can merge
2716*e4b17023SJohn Marino 		 into some other operation, hence insert it into the
2717*e4b17023SJohn Marino 		 plus_negates vector.  */
2718*e4b17023SJohn Marino 	      gimple feed = SSA_NAME_DEF_STMT (negate);
2719*e4b17023SJohn Marino 	      tree a = gimple_assign_rhs1 (feed);
2720*e4b17023SJohn Marino 	      tree rhs2 = gimple_assign_rhs2 (user);
2721*e4b17023SJohn Marino 	      gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2;
2722*e4b17023SJohn Marino 	      gimple_replace_lhs (feed, negate);
2723*e4b17023SJohn Marino 	      gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2);
2724*e4b17023SJohn Marino 	      update_stmt (gsi_stmt (gsi));
2725*e4b17023SJohn Marino 	      gsi2 = gsi_for_stmt (user);
2726*e4b17023SJohn Marino 	      gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, negate, NULL);
2727*e4b17023SJohn Marino 	      update_stmt (gsi_stmt (gsi2));
2728*e4b17023SJohn Marino 	      gsi_move_before (&gsi, &gsi2);
2729*e4b17023SJohn Marino 	      VEC_safe_push (tree, heap, plus_negates,
2730*e4b17023SJohn Marino 			     gimple_assign_lhs (gsi_stmt (gsi2)));
2731*e4b17023SJohn Marino 	    }
2732*e4b17023SJohn Marino 	  else
2733*e4b17023SJohn Marino 	    {
2734*e4b17023SJohn Marino 	      /* Transform "x = -a; y = b - x" into "y = b + a", getting
2735*e4b17023SJohn Marino 	         rid of one operation.  */
2736*e4b17023SJohn Marino 	      gimple feed = SSA_NAME_DEF_STMT (negate);
2737*e4b17023SJohn Marino 	      tree a = gimple_assign_rhs1 (feed);
2738*e4b17023SJohn Marino 	      tree rhs1 = gimple_assign_rhs1 (user);
2739*e4b17023SJohn Marino 	      gimple_stmt_iterator gsi = gsi_for_stmt (user);
2740*e4b17023SJohn Marino 	      gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, rhs1, a);
2741*e4b17023SJohn Marino 	      update_stmt (gsi_stmt (gsi));
2742*e4b17023SJohn Marino 	    }
2743*e4b17023SJohn Marino 	}
2744*e4b17023SJohn Marino     }
2745*e4b17023SJohn Marino }
2746*e4b17023SJohn Marino 
2747*e4b17023SJohn Marino /* Returns true if OP is of a type for which we can do reassociation.
2748*e4b17023SJohn Marino    That is for integral or non-saturating fixed-point types, and for
2749*e4b17023SJohn Marino    floating point type when associative-math is enabled.  */
2750*e4b17023SJohn Marino 
2751*e4b17023SJohn Marino static bool
2752*e4b17023SJohn Marino can_reassociate_p (tree op)
2753*e4b17023SJohn Marino {
2754*e4b17023SJohn Marino   tree type = TREE_TYPE (op);
2755*e4b17023SJohn Marino   if ((INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
2756*e4b17023SJohn Marino       || NON_SAT_FIXED_POINT_TYPE_P (type)
2757*e4b17023SJohn Marino       || (flag_associative_math && FLOAT_TYPE_P (type)))
2758*e4b17023SJohn Marino     return true;
2759*e4b17023SJohn Marino   return false;
2760*e4b17023SJohn Marino }
2761*e4b17023SJohn Marino 
2762*e4b17023SJohn Marino /* Break up subtract operations in block BB.
2763*e4b17023SJohn Marino 
2764*e4b17023SJohn Marino    We do this top down because we don't know whether the subtract is
2765*e4b17023SJohn Marino    part of a possible chain of reassociation except at the top.
2766*e4b17023SJohn Marino 
2767*e4b17023SJohn Marino    IE given
2768*e4b17023SJohn Marino    d = f + g
2769*e4b17023SJohn Marino    c = a + e
2770*e4b17023SJohn Marino    b = c - d
2771*e4b17023SJohn Marino    q = b - r
2772*e4b17023SJohn Marino    k = t - q
2773*e4b17023SJohn Marino 
2774*e4b17023SJohn Marino    we want to break up k = t - q, but we won't until we've transformed q
2775*e4b17023SJohn Marino    = b - r, which won't be broken up until we transform b = c - d.
2776*e4b17023SJohn Marino 
2777*e4b17023SJohn Marino    En passant, clear the GIMPLE visited flag on every statement.  */
2778*e4b17023SJohn Marino 
2779*e4b17023SJohn Marino static void
2780*e4b17023SJohn Marino break_up_subtract_bb (basic_block bb)
2781*e4b17023SJohn Marino {
2782*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
2783*e4b17023SJohn Marino   basic_block son;
2784*e4b17023SJohn Marino 
2785*e4b17023SJohn Marino   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2786*e4b17023SJohn Marino     {
2787*e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
2788*e4b17023SJohn Marino       gimple_set_visited (stmt, false);
2789*e4b17023SJohn Marino 
2790*e4b17023SJohn Marino       if (!is_gimple_assign (stmt)
2791*e4b17023SJohn Marino 	  || !can_reassociate_p (gimple_assign_lhs (stmt)))
2792*e4b17023SJohn Marino 	continue;
2793*e4b17023SJohn Marino 
2794*e4b17023SJohn Marino       /* Look for simple gimple subtract operations.  */
2795*e4b17023SJohn Marino       if (gimple_assign_rhs_code (stmt) == MINUS_EXPR)
2796*e4b17023SJohn Marino 	{
2797*e4b17023SJohn Marino 	  if (!can_reassociate_p (gimple_assign_rhs1 (stmt))
2798*e4b17023SJohn Marino 	      || !can_reassociate_p (gimple_assign_rhs2 (stmt)))
2799*e4b17023SJohn Marino 	    continue;
2800*e4b17023SJohn Marino 
2801*e4b17023SJohn Marino 	  /* Check for a subtract used only in an addition.  If this
2802*e4b17023SJohn Marino 	     is the case, transform it into add of a negate for better
2803*e4b17023SJohn Marino 	     reassociation.  IE transform C = A-B into C = A + -B if C
2804*e4b17023SJohn Marino 	     is only used in an addition.  */
2805*e4b17023SJohn Marino 	  if (should_break_up_subtract (stmt))
2806*e4b17023SJohn Marino 	    break_up_subtract (stmt, &gsi);
2807*e4b17023SJohn Marino 	}
2808*e4b17023SJohn Marino       else if (gimple_assign_rhs_code (stmt) == NEGATE_EXPR
2809*e4b17023SJohn Marino 	       && can_reassociate_p (gimple_assign_rhs1 (stmt)))
2810*e4b17023SJohn Marino 	VEC_safe_push (tree, heap, plus_negates, gimple_assign_lhs (stmt));
2811*e4b17023SJohn Marino     }
2812*e4b17023SJohn Marino   for (son = first_dom_son (CDI_DOMINATORS, bb);
2813*e4b17023SJohn Marino        son;
2814*e4b17023SJohn Marino        son = next_dom_son (CDI_DOMINATORS, son))
2815*e4b17023SJohn Marino     break_up_subtract_bb (son);
2816*e4b17023SJohn Marino }
2817*e4b17023SJohn Marino 
2818*e4b17023SJohn Marino /* Reassociate expressions in basic block BB and its post-dominator as
2819*e4b17023SJohn Marino    children.  */
2820*e4b17023SJohn Marino 
2821*e4b17023SJohn Marino static void
2822*e4b17023SJohn Marino reassociate_bb (basic_block bb)
2823*e4b17023SJohn Marino {
2824*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
2825*e4b17023SJohn Marino   basic_block son;
2826*e4b17023SJohn Marino 
2827*e4b17023SJohn Marino   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
2828*e4b17023SJohn Marino     {
2829*e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
2830*e4b17023SJohn Marino 
2831*e4b17023SJohn Marino       if (is_gimple_assign (stmt)
2832*e4b17023SJohn Marino 	  && !stmt_could_throw_p (stmt))
2833*e4b17023SJohn Marino 	{
2834*e4b17023SJohn Marino 	  tree lhs, rhs1, rhs2;
2835*e4b17023SJohn Marino 	  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
2836*e4b17023SJohn Marino 
2837*e4b17023SJohn Marino 	  /* If this is not a gimple binary expression, there is
2838*e4b17023SJohn Marino 	     nothing for us to do with it.  */
2839*e4b17023SJohn Marino 	  if (get_gimple_rhs_class (rhs_code) != GIMPLE_BINARY_RHS)
2840*e4b17023SJohn Marino 	    continue;
2841*e4b17023SJohn Marino 
2842*e4b17023SJohn Marino 	  /* If this was part of an already processed statement,
2843*e4b17023SJohn Marino 	     we don't need to touch it again. */
2844*e4b17023SJohn Marino 	  if (gimple_visited_p (stmt))
2845*e4b17023SJohn Marino 	    {
2846*e4b17023SJohn Marino 	      /* This statement might have become dead because of previous
2847*e4b17023SJohn Marino 		 reassociations.  */
2848*e4b17023SJohn Marino 	      if (has_zero_uses (gimple_get_lhs (stmt)))
2849*e4b17023SJohn Marino 		{
2850*e4b17023SJohn Marino 		  gsi_remove (&gsi, true);
2851*e4b17023SJohn Marino 		  release_defs (stmt);
2852*e4b17023SJohn Marino 		  /* We might end up removing the last stmt above which
2853*e4b17023SJohn Marino 		     places the iterator to the end of the sequence.
2854*e4b17023SJohn Marino 		     Reset it to the last stmt in this case which might
2855*e4b17023SJohn Marino 		     be the end of the sequence as well if we removed
2856*e4b17023SJohn Marino 		     the last statement of the sequence.  In which case
2857*e4b17023SJohn Marino 		     we need to bail out.  */
2858*e4b17023SJohn Marino 		  if (gsi_end_p (gsi))
2859*e4b17023SJohn Marino 		    {
2860*e4b17023SJohn Marino 		      gsi = gsi_last_bb (bb);
2861*e4b17023SJohn Marino 		      if (gsi_end_p (gsi))
2862*e4b17023SJohn Marino 			break;
2863*e4b17023SJohn Marino 		    }
2864*e4b17023SJohn Marino 		}
2865*e4b17023SJohn Marino 	      continue;
2866*e4b17023SJohn Marino 	    }
2867*e4b17023SJohn Marino 
2868*e4b17023SJohn Marino 	  lhs = gimple_assign_lhs (stmt);
2869*e4b17023SJohn Marino 	  rhs1 = gimple_assign_rhs1 (stmt);
2870*e4b17023SJohn Marino 	  rhs2 = gimple_assign_rhs2 (stmt);
2871*e4b17023SJohn Marino 
2872*e4b17023SJohn Marino 	  /* For non-bit or min/max operations we can't associate
2873*e4b17023SJohn Marino 	     all types.  Verify that here.  */
2874*e4b17023SJohn Marino 	  if (rhs_code != BIT_IOR_EXPR
2875*e4b17023SJohn Marino 	      && rhs_code != BIT_AND_EXPR
2876*e4b17023SJohn Marino 	      && rhs_code != BIT_XOR_EXPR
2877*e4b17023SJohn Marino 	      && rhs_code != MIN_EXPR
2878*e4b17023SJohn Marino 	      && rhs_code != MAX_EXPR
2879*e4b17023SJohn Marino 	      && (!can_reassociate_p (lhs)
2880*e4b17023SJohn Marino 		  || !can_reassociate_p (rhs1)
2881*e4b17023SJohn Marino 		  || !can_reassociate_p (rhs2)))
2882*e4b17023SJohn Marino 	    continue;
2883*e4b17023SJohn Marino 
2884*e4b17023SJohn Marino 	  if (associative_tree_code (rhs_code))
2885*e4b17023SJohn Marino 	    {
2886*e4b17023SJohn Marino 	      VEC(operand_entry_t, heap) *ops = NULL;
2887*e4b17023SJohn Marino 
2888*e4b17023SJohn Marino 	      /* There may be no immediate uses left by the time we
2889*e4b17023SJohn Marino 		 get here because we may have eliminated them all.  */
2890*e4b17023SJohn Marino 	      if (TREE_CODE (lhs) == SSA_NAME && has_zero_uses (lhs))
2891*e4b17023SJohn Marino 		continue;
2892*e4b17023SJohn Marino 
2893*e4b17023SJohn Marino 	      gimple_set_visited (stmt, true);
2894*e4b17023SJohn Marino 	      linearize_expr_tree (&ops, stmt, true, true);
2895*e4b17023SJohn Marino 	      VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
2896*e4b17023SJohn Marino 	      optimize_ops_list (rhs_code, &ops);
2897*e4b17023SJohn Marino 	      if (undistribute_ops_list (rhs_code, &ops,
2898*e4b17023SJohn Marino 					 loop_containing_stmt (stmt)))
2899*e4b17023SJohn Marino 		{
2900*e4b17023SJohn Marino 		  VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
2901*e4b17023SJohn Marino 		  optimize_ops_list (rhs_code, &ops);
2902*e4b17023SJohn Marino 		}
2903*e4b17023SJohn Marino 
2904*e4b17023SJohn Marino 	      if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR)
2905*e4b17023SJohn Marino 		optimize_range_tests (rhs_code, &ops);
2906*e4b17023SJohn Marino 
2907*e4b17023SJohn Marino 	      if (VEC_length (operand_entry_t, ops) == 1)
2908*e4b17023SJohn Marino 		{
2909*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
2910*e4b17023SJohn Marino 		    {
2911*e4b17023SJohn Marino 		      fprintf (dump_file, "Transforming ");
2912*e4b17023SJohn Marino 		      print_gimple_stmt (dump_file, stmt, 0, 0);
2913*e4b17023SJohn Marino 		    }
2914*e4b17023SJohn Marino 
2915*e4b17023SJohn Marino 		  rhs1 = gimple_assign_rhs1 (stmt);
2916*e4b17023SJohn Marino 		  gimple_assign_set_rhs_from_tree (&gsi,
2917*e4b17023SJohn Marino 						   VEC_last (operand_entry_t,
2918*e4b17023SJohn Marino 							     ops)->op);
2919*e4b17023SJohn Marino 		  update_stmt (stmt);
2920*e4b17023SJohn Marino 		  remove_visited_stmt_chain (rhs1);
2921*e4b17023SJohn Marino 
2922*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
2923*e4b17023SJohn Marino 		    {
2924*e4b17023SJohn Marino 		      fprintf (dump_file, " into ");
2925*e4b17023SJohn Marino 		      print_gimple_stmt (dump_file, stmt, 0, 0);
2926*e4b17023SJohn Marino 		    }
2927*e4b17023SJohn Marino 		}
2928*e4b17023SJohn Marino 	      else
2929*e4b17023SJohn Marino 		{
2930*e4b17023SJohn Marino 		  enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
2931*e4b17023SJohn Marino 		  int ops_num = VEC_length (operand_entry_t, ops);
2932*e4b17023SJohn Marino 		  int width = get_reassociation_width (ops_num, rhs_code, mode);
2933*e4b17023SJohn Marino 
2934*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
2935*e4b17023SJohn Marino 		    fprintf (dump_file,
2936*e4b17023SJohn Marino 			     "Width = %d was chosen for reassociation\n", width);
2937*e4b17023SJohn Marino 
2938*e4b17023SJohn Marino 		  if (width > 1
2939*e4b17023SJohn Marino 		      && VEC_length (operand_entry_t, ops) > 3)
2940*e4b17023SJohn Marino 		    rewrite_expr_tree_parallel (stmt, width, ops);
2941*e4b17023SJohn Marino 		  else
2942*e4b17023SJohn Marino 		    rewrite_expr_tree (stmt, 0, ops, false);
2943*e4b17023SJohn Marino 		}
2944*e4b17023SJohn Marino 
2945*e4b17023SJohn Marino 	      VEC_free (operand_entry_t, heap, ops);
2946*e4b17023SJohn Marino 	    }
2947*e4b17023SJohn Marino 	}
2948*e4b17023SJohn Marino     }
2949*e4b17023SJohn Marino   for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
2950*e4b17023SJohn Marino        son;
2951*e4b17023SJohn Marino        son = next_dom_son (CDI_POST_DOMINATORS, son))
2952*e4b17023SJohn Marino     reassociate_bb (son);
2953*e4b17023SJohn Marino }
2954*e4b17023SJohn Marino 
2955*e4b17023SJohn Marino void dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops);
2956*e4b17023SJohn Marino void debug_ops_vector (VEC (operand_entry_t, heap) *ops);
2957*e4b17023SJohn Marino 
2958*e4b17023SJohn Marino /* Dump the operand entry vector OPS to FILE.  */
2959*e4b17023SJohn Marino 
2960*e4b17023SJohn Marino void
2961*e4b17023SJohn Marino dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops)
2962*e4b17023SJohn Marino {
2963*e4b17023SJohn Marino   operand_entry_t oe;
2964*e4b17023SJohn Marino   unsigned int i;
2965*e4b17023SJohn Marino 
2966*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (operand_entry_t, ops, i, oe)
2967*e4b17023SJohn Marino     {
2968*e4b17023SJohn Marino       fprintf (file, "Op %d -> rank: %d, tree: ", i, oe->rank);
2969*e4b17023SJohn Marino       print_generic_expr (file, oe->op, 0);
2970*e4b17023SJohn Marino     }
2971*e4b17023SJohn Marino }
2972*e4b17023SJohn Marino 
2973*e4b17023SJohn Marino /* Dump the operand entry vector OPS to STDERR.  */
2974*e4b17023SJohn Marino 
2975*e4b17023SJohn Marino DEBUG_FUNCTION void
2976*e4b17023SJohn Marino debug_ops_vector (VEC (operand_entry_t, heap) *ops)
2977*e4b17023SJohn Marino {
2978*e4b17023SJohn Marino   dump_ops_vector (stderr, ops);
2979*e4b17023SJohn Marino }
2980*e4b17023SJohn Marino 
2981*e4b17023SJohn Marino static void
2982*e4b17023SJohn Marino do_reassoc (void)
2983*e4b17023SJohn Marino {
2984*e4b17023SJohn Marino   break_up_subtract_bb (ENTRY_BLOCK_PTR);
2985*e4b17023SJohn Marino   reassociate_bb (EXIT_BLOCK_PTR);
2986*e4b17023SJohn Marino }
2987*e4b17023SJohn Marino 
2988*e4b17023SJohn Marino /* Initialize the reassociation pass.  */
2989*e4b17023SJohn Marino 
2990*e4b17023SJohn Marino static void
2991*e4b17023SJohn Marino init_reassoc (void)
2992*e4b17023SJohn Marino {
2993*e4b17023SJohn Marino   int i;
2994*e4b17023SJohn Marino   long rank = 2;
2995*e4b17023SJohn Marino   tree param;
2996*e4b17023SJohn Marino   int *bbs = XNEWVEC (int, last_basic_block + 1);
2997*e4b17023SJohn Marino 
2998*e4b17023SJohn Marino   /* Find the loops, so that we can prevent moving calculations in
2999*e4b17023SJohn Marino      them.  */
3000*e4b17023SJohn Marino   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
3001*e4b17023SJohn Marino 
3002*e4b17023SJohn Marino   memset (&reassociate_stats, 0, sizeof (reassociate_stats));
3003*e4b17023SJohn Marino 
3004*e4b17023SJohn Marino   operand_entry_pool = create_alloc_pool ("operand entry pool",
3005*e4b17023SJohn Marino 					  sizeof (struct operand_entry), 30);
3006*e4b17023SJohn Marino   next_operand_entry_id = 0;
3007*e4b17023SJohn Marino 
3008*e4b17023SJohn Marino   /* Reverse RPO (Reverse Post Order) will give us something where
3009*e4b17023SJohn Marino      deeper loops come later.  */
3010*e4b17023SJohn Marino   pre_and_rev_post_order_compute (NULL, bbs, false);
3011*e4b17023SJohn Marino   bb_rank = XCNEWVEC (long, last_basic_block + 1);
3012*e4b17023SJohn Marino   operand_rank = pointer_map_create ();
3013*e4b17023SJohn Marino 
3014*e4b17023SJohn Marino   /* Give each argument a distinct rank.   */
3015*e4b17023SJohn Marino   for (param = DECL_ARGUMENTS (current_function_decl);
3016*e4b17023SJohn Marino        param;
3017*e4b17023SJohn Marino        param = DECL_CHAIN (param))
3018*e4b17023SJohn Marino     {
3019*e4b17023SJohn Marino       if (gimple_default_def (cfun, param) != NULL)
3020*e4b17023SJohn Marino 	{
3021*e4b17023SJohn Marino 	  tree def = gimple_default_def (cfun, param);
3022*e4b17023SJohn Marino 	  insert_operand_rank (def, ++rank);
3023*e4b17023SJohn Marino 	}
3024*e4b17023SJohn Marino     }
3025*e4b17023SJohn Marino 
3026*e4b17023SJohn Marino   /* Give the chain decl a distinct rank. */
3027*e4b17023SJohn Marino   if (cfun->static_chain_decl != NULL)
3028*e4b17023SJohn Marino     {
3029*e4b17023SJohn Marino       tree def = gimple_default_def (cfun, cfun->static_chain_decl);
3030*e4b17023SJohn Marino       if (def != NULL)
3031*e4b17023SJohn Marino 	insert_operand_rank (def, ++rank);
3032*e4b17023SJohn Marino     }
3033*e4b17023SJohn Marino 
3034*e4b17023SJohn Marino   /* Set up rank for each BB  */
3035*e4b17023SJohn Marino   for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
3036*e4b17023SJohn Marino     bb_rank[bbs[i]] = ++rank  << 16;
3037*e4b17023SJohn Marino 
3038*e4b17023SJohn Marino   free (bbs);
3039*e4b17023SJohn Marino   calculate_dominance_info (CDI_POST_DOMINATORS);
3040*e4b17023SJohn Marino   plus_negates = NULL;
3041*e4b17023SJohn Marino }
3042*e4b17023SJohn Marino 
3043*e4b17023SJohn Marino /* Cleanup after the reassociation pass, and print stats if
3044*e4b17023SJohn Marino    requested.  */
3045*e4b17023SJohn Marino 
3046*e4b17023SJohn Marino static void
3047*e4b17023SJohn Marino fini_reassoc (void)
3048*e4b17023SJohn Marino {
3049*e4b17023SJohn Marino   statistics_counter_event (cfun, "Linearized",
3050*e4b17023SJohn Marino 			    reassociate_stats.linearized);
3051*e4b17023SJohn Marino   statistics_counter_event (cfun, "Constants eliminated",
3052*e4b17023SJohn Marino 			    reassociate_stats.constants_eliminated);
3053*e4b17023SJohn Marino   statistics_counter_event (cfun, "Ops eliminated",
3054*e4b17023SJohn Marino 			    reassociate_stats.ops_eliminated);
3055*e4b17023SJohn Marino   statistics_counter_event (cfun, "Statements rewritten",
3056*e4b17023SJohn Marino 			    reassociate_stats.rewritten);
3057*e4b17023SJohn Marino 
3058*e4b17023SJohn Marino   pointer_map_destroy (operand_rank);
3059*e4b17023SJohn Marino   free_alloc_pool (operand_entry_pool);
3060*e4b17023SJohn Marino   free (bb_rank);
3061*e4b17023SJohn Marino   VEC_free (tree, heap, plus_negates);
3062*e4b17023SJohn Marino   free_dominance_info (CDI_POST_DOMINATORS);
3063*e4b17023SJohn Marino   loop_optimizer_finalize ();
3064*e4b17023SJohn Marino }
3065*e4b17023SJohn Marino 
3066*e4b17023SJohn Marino /* Gate and execute functions for Reassociation.  */
3067*e4b17023SJohn Marino 
3068*e4b17023SJohn Marino static unsigned int
3069*e4b17023SJohn Marino execute_reassoc (void)
3070*e4b17023SJohn Marino {
3071*e4b17023SJohn Marino   init_reassoc ();
3072*e4b17023SJohn Marino 
3073*e4b17023SJohn Marino   do_reassoc ();
3074*e4b17023SJohn Marino   repropagate_negates ();
3075*e4b17023SJohn Marino 
3076*e4b17023SJohn Marino   fini_reassoc ();
3077*e4b17023SJohn Marino   return 0;
3078*e4b17023SJohn Marino }
3079*e4b17023SJohn Marino 
3080*e4b17023SJohn Marino static bool
3081*e4b17023SJohn Marino gate_tree_ssa_reassoc (void)
3082*e4b17023SJohn Marino {
3083*e4b17023SJohn Marino   return flag_tree_reassoc != 0;
3084*e4b17023SJohn Marino }
3085*e4b17023SJohn Marino 
3086*e4b17023SJohn Marino struct gimple_opt_pass pass_reassoc =
3087*e4b17023SJohn Marino {
3088*e4b17023SJohn Marino  {
3089*e4b17023SJohn Marino   GIMPLE_PASS,
3090*e4b17023SJohn Marino   "reassoc",				/* name */
3091*e4b17023SJohn Marino   gate_tree_ssa_reassoc,		/* gate */
3092*e4b17023SJohn Marino   execute_reassoc,			/* execute */
3093*e4b17023SJohn Marino   NULL,					/* sub */
3094*e4b17023SJohn Marino   NULL,					/* next */
3095*e4b17023SJohn Marino   0,					/* static_pass_number */
3096*e4b17023SJohn Marino   TV_TREE_REASSOC,			/* tv_id */
3097*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
3098*e4b17023SJohn Marino   0,					/* properties_provided */
3099*e4b17023SJohn Marino   0,					/* properties_destroyed */
3100*e4b17023SJohn Marino   0,					/* todo_flags_start */
3101*e4b17023SJohn Marino   TODO_verify_ssa
3102*e4b17023SJohn Marino     | TODO_verify_flow
3103*e4b17023SJohn Marino     | TODO_ggc_collect			/* todo_flags_finish */
3104*e4b17023SJohn Marino  }
3105*e4b17023SJohn Marino };
3106