138fd1498Szrj /* Reassociation for trees.
238fd1498Szrj    Copyright (C) 2005-2018 Free Software Foundation, Inc.
338fd1498Szrj    Contributed by Daniel Berlin <dan@dberlin.org>
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify
838fd1498Szrj it under the terms of the GNU General Public License as published by
938fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj any later version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful,
1338fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1538fd1498Szrj GNU General Public License for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "coretypes.h"
2438fd1498Szrj #include "backend.h"
2538fd1498Szrj #include "target.h"
2638fd1498Szrj #include "rtl.h"
2738fd1498Szrj #include "tree.h"
2838fd1498Szrj #include "gimple.h"
2938fd1498Szrj #include "cfghooks.h"
3038fd1498Szrj #include "alloc-pool.h"
3138fd1498Szrj #include "tree-pass.h"
3238fd1498Szrj #include "memmodel.h"
3338fd1498Szrj #include "tm_p.h"
3438fd1498Szrj #include "ssa.h"
3538fd1498Szrj #include "optabs-tree.h"
3638fd1498Szrj #include "gimple-pretty-print.h"
3738fd1498Szrj #include "diagnostic-core.h"
3838fd1498Szrj #include "fold-const.h"
3938fd1498Szrj #include "stor-layout.h"
4038fd1498Szrj #include "cfganal.h"
4138fd1498Szrj #include "gimple-fold.h"
4238fd1498Szrj #include "tree-eh.h"
4338fd1498Szrj #include "gimple-iterator.h"
4438fd1498Szrj #include "gimplify-me.h"
4538fd1498Szrj #include "tree-cfg.h"
4638fd1498Szrj #include "tree-ssa-loop.h"
4738fd1498Szrj #include "flags.h"
4838fd1498Szrj #include "tree-ssa.h"
4938fd1498Szrj #include "langhooks.h"
5038fd1498Szrj #include "cfgloop.h"
5138fd1498Szrj #include "params.h"
5238fd1498Szrj #include "builtins.h"
5338fd1498Szrj #include "gimplify.h"
5438fd1498Szrj #include "case-cfn-macros.h"
5538fd1498Szrj 
5638fd1498Szrj /*  This is a simple global reassociation pass.  It is, in part, based
5738fd1498Szrj     on the LLVM pass of the same name (They do some things more/less
5838fd1498Szrj     than we do, in different orders, etc).
5938fd1498Szrj 
6038fd1498Szrj     It consists of five steps:
6138fd1498Szrj 
6238fd1498Szrj     1. Breaking up subtract operations into addition + negate, where
6338fd1498Szrj     it would promote the reassociation of adds.
6438fd1498Szrj 
6538fd1498Szrj     2. Left linearization of the expression trees, so that (A+B)+(C+D)
6638fd1498Szrj     becomes (((A+B)+C)+D), which is easier for us to rewrite later.
6738fd1498Szrj     During linearization, we place the operands of the binary
6838fd1498Szrj     expressions into a vector of operand_entry_*
6938fd1498Szrj 
7038fd1498Szrj     3. Optimization of the operand lists, eliminating things like a +
7138fd1498Szrj     -a, a & a, etc.
7238fd1498Szrj 
7338fd1498Szrj     3a. Combine repeated factors with the same occurrence counts
7438fd1498Szrj     into a __builtin_powi call that will later be optimized into
7538fd1498Szrj     an optimal number of multiplies.
7638fd1498Szrj 
7738fd1498Szrj     4. Rewrite the expression trees we linearized and optimized so
7838fd1498Szrj     they are in proper rank order.
7938fd1498Szrj 
8038fd1498Szrj     5. Repropagate negates, as nothing else will clean it up ATM.
8138fd1498Szrj 
8238fd1498Szrj     A bit of theory on #4, since nobody seems to write anything down
8338fd1498Szrj     about why it makes sense to do it the way they do it:
8438fd1498Szrj 
8538fd1498Szrj     We could do this much nicer theoretically, but don't (for reasons
8638fd1498Szrj     explained after how to do it theoretically nice :P).
8738fd1498Szrj 
8838fd1498Szrj     In order to promote the most redundancy elimination, you want
8938fd1498Szrj     binary expressions whose operands are the same rank (or
9038fd1498Szrj     preferably, the same value) exposed to the redundancy eliminator,
9138fd1498Szrj     for possible elimination.
9238fd1498Szrj 
9338fd1498Szrj     So the way to do this if we really cared, is to build the new op
9438fd1498Szrj     tree from the leaves to the roots, merging as you go, and putting the
9538fd1498Szrj     new op on the end of the worklist, until you are left with one
9638fd1498Szrj     thing on the worklist.
9738fd1498Szrj 
9838fd1498Szrj     IE if you have to rewrite the following set of operands (listed with
9938fd1498Szrj     rank in parentheses), with opcode PLUS_EXPR:
10038fd1498Szrj 
10138fd1498Szrj     a (1),  b (1),  c (1),  d (2), e (2)
10238fd1498Szrj 
10338fd1498Szrj 
10438fd1498Szrj     We start with our merge worklist empty, and the ops list with all of
10538fd1498Szrj     those on it.
10638fd1498Szrj 
10738fd1498Szrj     You want to first merge all leaves of the same rank, as much as
10838fd1498Szrj     possible.
10938fd1498Szrj 
11038fd1498Szrj     So first build a binary op of
11138fd1498Szrj 
11238fd1498Szrj     mergetmp = a + b, and put "mergetmp" on the merge worklist.
11338fd1498Szrj 
11438fd1498Szrj     Because there is no three operand form of PLUS_EXPR, c is not going to
11538fd1498Szrj     be exposed to redundancy elimination as a rank 1 operand.
11638fd1498Szrj 
11738fd1498Szrj     So you might as well throw it on the merge worklist (you could also
11838fd1498Szrj     consider it to now be a rank two operand, and merge it with d and e,
11938fd1498Szrj     but in this case, you then have evicted e from a binary op. So at
12038fd1498Szrj     least in this situation, you can't win.)
12138fd1498Szrj 
12238fd1498Szrj     Then build a binary op of d + e
12338fd1498Szrj     mergetmp2 = d + e
12438fd1498Szrj 
12538fd1498Szrj     and put mergetmp2 on the merge worklist.
12638fd1498Szrj 
12738fd1498Szrj     so merge worklist = {mergetmp, c, mergetmp2}
12838fd1498Szrj 
12938fd1498Szrj     Continue building binary ops of these operations until you have only
13038fd1498Szrj     one operation left on the worklist.
13138fd1498Szrj 
13238fd1498Szrj     So we have
13338fd1498Szrj 
13438fd1498Szrj     build binary op
13538fd1498Szrj     mergetmp3 = mergetmp + c
13638fd1498Szrj 
13738fd1498Szrj     worklist = {mergetmp2, mergetmp3}
13838fd1498Szrj 
13938fd1498Szrj     mergetmp4 = mergetmp2 + mergetmp3
14038fd1498Szrj 
14138fd1498Szrj     worklist = {mergetmp4}
14238fd1498Szrj 
14338fd1498Szrj     because we have one operation left, we can now just set the original
14438fd1498Szrj     statement equal to the result of that operation.
14538fd1498Szrj 
14638fd1498Szrj     This will at least expose a + b  and d + e to redundancy elimination
14738fd1498Szrj     as binary operations.
14838fd1498Szrj 
14938fd1498Szrj     For extra points, you can reuse the old statements to build the
15038fd1498Szrj     mergetmps, since you shouldn't run out.
15138fd1498Szrj 
15238fd1498Szrj     So why don't we do this?
15338fd1498Szrj 
15438fd1498Szrj     Because it's expensive, and rarely will help.  Most trees we are
15538fd1498Szrj     reassociating have 3 or less ops.  If they have 2 ops, they already
15638fd1498Szrj     will be written into a nice single binary op.  If you have 3 ops, a
15738fd1498Szrj     single simple check suffices to tell you whether the first two are of the
15838fd1498Szrj     same rank.  If so, you know to order it
15938fd1498Szrj 
16038fd1498Szrj     mergetmp = op1 + op2
16138fd1498Szrj     newstmt = mergetmp + op3
16238fd1498Szrj 
16338fd1498Szrj     instead of
16438fd1498Szrj     mergetmp = op2 + op3
16538fd1498Szrj     newstmt = mergetmp + op1
16638fd1498Szrj 
16738fd1498Szrj     If all three are of the same rank, you can't expose them all in a
16838fd1498Szrj     single binary operator anyway, so the above is *still* the best you
16938fd1498Szrj     can do.
17038fd1498Szrj 
17138fd1498Szrj     Thus, this is what we do.  When we have three ops left, we check to see
17238fd1498Szrj     what order to put them in, and call it a day.  As a nod to vector sum
17338fd1498Szrj     reduction, we check if any of the ops are really a phi node that is a
17438fd1498Szrj     destructive update for the associating op, and keep the destructive
17538fd1498Szrj     update together for vector sum reduction recognition.  */
17638fd1498Szrj 
17738fd1498Szrj /* Enable insertion of __builtin_powi calls during execute_reassoc.  See
17838fd1498Szrj    point 3a in the pass header comment.  */
17938fd1498Szrj static bool reassoc_insert_powi_p;
18038fd1498Szrj 
18138fd1498Szrj /* Statistics */
18238fd1498Szrj static struct
18338fd1498Szrj {
18438fd1498Szrj   int linearized;
18538fd1498Szrj   int constants_eliminated;
18638fd1498Szrj   int ops_eliminated;
18738fd1498Szrj   int rewritten;
18838fd1498Szrj   int pows_encountered;
18938fd1498Szrj   int pows_created;
19038fd1498Szrj } reassociate_stats;
19138fd1498Szrj 
19238fd1498Szrj /* Operator, rank pair.  */
19338fd1498Szrj struct operand_entry
19438fd1498Szrj {
19538fd1498Szrj   unsigned int rank;
19638fd1498Szrj   unsigned int id;
19738fd1498Szrj   tree op;
19838fd1498Szrj   unsigned int count;
19938fd1498Szrj   gimple *stmt_to_insert;
20038fd1498Szrj };
20138fd1498Szrj 
20238fd1498Szrj static object_allocator<operand_entry> operand_entry_pool
20338fd1498Szrj   ("operand entry pool");
20438fd1498Szrj 
20538fd1498Szrj /* This is used to assign a unique ID to each struct operand_entry
20638fd1498Szrj    so that qsort results are identical on different hosts.  */
20738fd1498Szrj static unsigned int next_operand_entry_id;
20838fd1498Szrj 
20938fd1498Szrj /* Starting rank number for a given basic block, so that we can rank
21038fd1498Szrj    operations using unmovable instructions in that BB based on the bb
21138fd1498Szrj    depth.  */
21238fd1498Szrj static long *bb_rank;
21338fd1498Szrj 
21438fd1498Szrj /* Operand->rank hashtable.  */
21538fd1498Szrj static hash_map<tree, long> *operand_rank;
21638fd1498Szrj 
21738fd1498Szrj /* Vector of SSA_NAMEs on which after reassociate_bb is done with
21838fd1498Szrj    all basic blocks the CFG should be adjusted - basic blocks
21938fd1498Szrj    split right after that SSA_NAME's definition statement and before
22038fd1498Szrj    the only use, which must be a bit ior.  */
22138fd1498Szrj static vec<tree> reassoc_branch_fixups;
22238fd1498Szrj 
22338fd1498Szrj /* Forward decls.  */
22438fd1498Szrj static long get_rank (tree);
22538fd1498Szrj static bool reassoc_stmt_dominates_stmt_p (gimple *, gimple *);
22638fd1498Szrj 
22738fd1498Szrj /* Wrapper around gsi_remove, which adjusts gimple_uid of debug stmts
22838fd1498Szrj    possibly added by gsi_remove.  */
22938fd1498Szrj 
23038fd1498Szrj bool
reassoc_remove_stmt(gimple_stmt_iterator * gsi)23138fd1498Szrj reassoc_remove_stmt (gimple_stmt_iterator *gsi)
23238fd1498Szrj {
23338fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
23438fd1498Szrj 
23538fd1498Szrj   if (!MAY_HAVE_DEBUG_BIND_STMTS || gimple_code (stmt) == GIMPLE_PHI)
23638fd1498Szrj     return gsi_remove (gsi, true);
23738fd1498Szrj 
23838fd1498Szrj   gimple_stmt_iterator prev = *gsi;
23938fd1498Szrj   gsi_prev (&prev);
24038fd1498Szrj   unsigned uid = gimple_uid (stmt);
24138fd1498Szrj   basic_block bb = gimple_bb (stmt);
24238fd1498Szrj   bool ret = gsi_remove (gsi, true);
24338fd1498Szrj   if (!gsi_end_p (prev))
24438fd1498Szrj     gsi_next (&prev);
24538fd1498Szrj   else
24638fd1498Szrj     prev = gsi_start_bb (bb);
24738fd1498Szrj   gimple *end_stmt = gsi_stmt (*gsi);
24838fd1498Szrj   while ((stmt = gsi_stmt (prev)) != end_stmt)
24938fd1498Szrj     {
25038fd1498Szrj       gcc_assert (stmt && is_gimple_debug (stmt) && gimple_uid (stmt) == 0);
25138fd1498Szrj       gimple_set_uid (stmt, uid);
25238fd1498Szrj       gsi_next (&prev);
25338fd1498Szrj     }
25438fd1498Szrj   return ret;
25538fd1498Szrj }
25638fd1498Szrj 
25738fd1498Szrj /* Bias amount for loop-carried phis.  We want this to be larger than
25838fd1498Szrj    the depth of any reassociation tree we can see, but not larger than
25938fd1498Szrj    the rank difference between two blocks.  */
26038fd1498Szrj #define PHI_LOOP_BIAS (1 << 15)
26138fd1498Szrj 
26238fd1498Szrj /* Rank assigned to a phi statement.  If STMT is a loop-carried phi of
26338fd1498Szrj    an innermost loop, and the phi has only a single use which is inside
26438fd1498Szrj    the loop, then the rank is the block rank of the loop latch plus an
26538fd1498Szrj    extra bias for the loop-carried dependence.  This causes expressions
26638fd1498Szrj    calculated into an accumulator variable to be independent for each
26738fd1498Szrj    iteration of the loop.  If STMT is some other phi, the rank is the
26838fd1498Szrj    block rank of its containing block.  */
26938fd1498Szrj static long
phi_rank(gimple * stmt)27038fd1498Szrj phi_rank (gimple *stmt)
27138fd1498Szrj {
27238fd1498Szrj   basic_block bb = gimple_bb (stmt);
27338fd1498Szrj   struct loop *father = bb->loop_father;
27438fd1498Szrj   tree res;
27538fd1498Szrj   unsigned i;
27638fd1498Szrj   use_operand_p use;
27738fd1498Szrj   gimple *use_stmt;
27838fd1498Szrj 
27938fd1498Szrj   /* We only care about real loops (those with a latch).  */
28038fd1498Szrj   if (!father->latch)
28138fd1498Szrj     return bb_rank[bb->index];
28238fd1498Szrj 
28338fd1498Szrj   /* Interesting phis must be in headers of innermost loops.  */
28438fd1498Szrj   if (bb != father->header
28538fd1498Szrj       || father->inner)
28638fd1498Szrj     return bb_rank[bb->index];
28738fd1498Szrj 
28838fd1498Szrj   /* Ignore virtual SSA_NAMEs.  */
28938fd1498Szrj   res = gimple_phi_result (stmt);
29038fd1498Szrj   if (virtual_operand_p (res))
29138fd1498Szrj     return bb_rank[bb->index];
29238fd1498Szrj 
29338fd1498Szrj   /* The phi definition must have a single use, and that use must be
29438fd1498Szrj      within the loop.  Otherwise this isn't an accumulator pattern.  */
29538fd1498Szrj   if (!single_imm_use (res, &use, &use_stmt)
29638fd1498Szrj       || gimple_bb (use_stmt)->loop_father != father)
29738fd1498Szrj     return bb_rank[bb->index];
29838fd1498Szrj 
29938fd1498Szrj   /* Look for phi arguments from within the loop.  If found, bias this phi.  */
30038fd1498Szrj   for (i = 0; i < gimple_phi_num_args (stmt); i++)
30138fd1498Szrj     {
30238fd1498Szrj       tree arg = gimple_phi_arg_def (stmt, i);
30338fd1498Szrj       if (TREE_CODE (arg) == SSA_NAME
30438fd1498Szrj 	  && !SSA_NAME_IS_DEFAULT_DEF (arg))
30538fd1498Szrj 	{
30638fd1498Szrj 	  gimple *def_stmt = SSA_NAME_DEF_STMT (arg);
30738fd1498Szrj 	  if (gimple_bb (def_stmt)->loop_father == father)
30838fd1498Szrj 	    return bb_rank[father->latch->index] + PHI_LOOP_BIAS;
30938fd1498Szrj 	}
31038fd1498Szrj     }
31138fd1498Szrj 
31238fd1498Szrj   /* Must be an uninteresting phi.  */
31338fd1498Szrj   return bb_rank[bb->index];
31438fd1498Szrj }
31538fd1498Szrj 
31638fd1498Szrj /* If EXP is an SSA_NAME defined by a PHI statement that represents a
31738fd1498Szrj    loop-carried dependence of an innermost loop, return TRUE; else
31838fd1498Szrj    return FALSE.  */
31938fd1498Szrj static bool
loop_carried_phi(tree exp)32038fd1498Szrj loop_carried_phi (tree exp)
32138fd1498Szrj {
32238fd1498Szrj   gimple *phi_stmt;
32338fd1498Szrj   long block_rank;
32438fd1498Szrj 
32538fd1498Szrj   if (TREE_CODE (exp) != SSA_NAME
32638fd1498Szrj       || SSA_NAME_IS_DEFAULT_DEF (exp))
32738fd1498Szrj     return false;
32838fd1498Szrj 
32938fd1498Szrj   phi_stmt = SSA_NAME_DEF_STMT (exp);
33038fd1498Szrj 
33138fd1498Szrj   if (gimple_code (SSA_NAME_DEF_STMT (exp)) != GIMPLE_PHI)
33238fd1498Szrj     return false;
33338fd1498Szrj 
33438fd1498Szrj   /* Non-loop-carried phis have block rank.  Loop-carried phis have
33538fd1498Szrj      an additional bias added in.  If this phi doesn't have block rank,
33638fd1498Szrj      it's biased and should not be propagated.  */
33738fd1498Szrj   block_rank = bb_rank[gimple_bb (phi_stmt)->index];
33838fd1498Szrj 
33938fd1498Szrj   if (phi_rank (phi_stmt) != block_rank)
34038fd1498Szrj     return true;
34138fd1498Szrj 
34238fd1498Szrj   return false;
34338fd1498Szrj }
34438fd1498Szrj 
34538fd1498Szrj /* Return the maximum of RANK and the rank that should be propagated
34638fd1498Szrj    from expression OP.  For most operands, this is just the rank of OP.
34738fd1498Szrj    For loop-carried phis, the value is zero to avoid undoing the bias
34838fd1498Szrj    in favor of the phi.  */
34938fd1498Szrj static long
propagate_rank(long rank,tree op)35038fd1498Szrj propagate_rank (long rank, tree op)
35138fd1498Szrj {
35238fd1498Szrj   long op_rank;
35338fd1498Szrj 
35438fd1498Szrj   if (loop_carried_phi (op))
35538fd1498Szrj     return rank;
35638fd1498Szrj 
35738fd1498Szrj   op_rank = get_rank (op);
35838fd1498Szrj 
35938fd1498Szrj   return MAX (rank, op_rank);
36038fd1498Szrj }
36138fd1498Szrj 
36238fd1498Szrj /* Look up the operand rank structure for expression E.  */
36338fd1498Szrj 
36438fd1498Szrj static inline long
find_operand_rank(tree e)36538fd1498Szrj find_operand_rank (tree e)
36638fd1498Szrj {
36738fd1498Szrj   long *slot = operand_rank->get (e);
36838fd1498Szrj   return slot ? *slot : -1;
36938fd1498Szrj }
37038fd1498Szrj 
37138fd1498Szrj /* Insert {E,RANK} into the operand rank hashtable.  */
37238fd1498Szrj 
37338fd1498Szrj static inline void
insert_operand_rank(tree e,long rank)37438fd1498Szrj insert_operand_rank (tree e, long rank)
37538fd1498Szrj {
37638fd1498Szrj   gcc_assert (rank > 0);
37738fd1498Szrj   gcc_assert (!operand_rank->put (e, rank));
37838fd1498Szrj }
37938fd1498Szrj 
38038fd1498Szrj /* Given an expression E, return the rank of the expression.  */
38138fd1498Szrj 
38238fd1498Szrj static long
get_rank(tree e)38338fd1498Szrj get_rank (tree e)
38438fd1498Szrj {
38538fd1498Szrj   /* SSA_NAME's have the rank of the expression they are the result
38638fd1498Szrj      of.
38738fd1498Szrj      For globals and uninitialized values, the rank is 0.
38838fd1498Szrj      For function arguments, use the pre-setup rank.
38938fd1498Szrj      For PHI nodes, stores, asm statements, etc, we use the rank of
39038fd1498Szrj      the BB.
39138fd1498Szrj      For simple operations, the rank is the maximum rank of any of
39238fd1498Szrj      its operands, or the bb_rank, whichever is less.
39338fd1498Szrj      I make no claims that this is optimal, however, it gives good
39438fd1498Szrj      results.  */
39538fd1498Szrj 
39638fd1498Szrj   /* We make an exception to the normal ranking system to break
39738fd1498Szrj      dependences of accumulator variables in loops.  Suppose we
39838fd1498Szrj      have a simple one-block loop containing:
39938fd1498Szrj 
40038fd1498Szrj        x_1 = phi(x_0, x_2)
40138fd1498Szrj        b = a + x_1
40238fd1498Szrj        c = b + d
40338fd1498Szrj        x_2 = c + e
40438fd1498Szrj 
40538fd1498Szrj      As shown, each iteration of the calculation into x is fully
40638fd1498Szrj      dependent upon the iteration before it.  We would prefer to
40738fd1498Szrj      see this in the form:
40838fd1498Szrj 
40938fd1498Szrj        x_1 = phi(x_0, x_2)
41038fd1498Szrj        b = a + d
41138fd1498Szrj        c = b + e
41238fd1498Szrj        x_2 = c + x_1
41338fd1498Szrj 
41438fd1498Szrj      If the loop is unrolled, the calculations of b and c from
41538fd1498Szrj      different iterations can be interleaved.
41638fd1498Szrj 
41738fd1498Szrj      To obtain this result during reassociation, we bias the rank
41838fd1498Szrj      of the phi definition x_1 upward, when it is recognized as an
41938fd1498Szrj      accumulator pattern.  The artificial rank causes it to be
42038fd1498Szrj      added last, providing the desired independence.  */
42138fd1498Szrj 
42238fd1498Szrj   if (TREE_CODE (e) == SSA_NAME)
42338fd1498Szrj     {
42438fd1498Szrj       ssa_op_iter iter;
42538fd1498Szrj       gimple *stmt;
42638fd1498Szrj       long rank;
42738fd1498Szrj       tree op;
42838fd1498Szrj 
42938fd1498Szrj       if (SSA_NAME_IS_DEFAULT_DEF (e))
43038fd1498Szrj 	return find_operand_rank (e);
43138fd1498Szrj 
43238fd1498Szrj       stmt = SSA_NAME_DEF_STMT (e);
43338fd1498Szrj       if (gimple_code (stmt) == GIMPLE_PHI)
43438fd1498Szrj 	return phi_rank (stmt);
43538fd1498Szrj 
43638fd1498Szrj       if (!is_gimple_assign (stmt))
43738fd1498Szrj 	return bb_rank[gimple_bb (stmt)->index];
43838fd1498Szrj 
43938fd1498Szrj       /* If we already have a rank for this expression, use that.  */
44038fd1498Szrj       rank = find_operand_rank (e);
44138fd1498Szrj       if (rank != -1)
44238fd1498Szrj 	return rank;
44338fd1498Szrj 
44438fd1498Szrj       /* Otherwise, find the maximum rank for the operands.  As an
44538fd1498Szrj 	 exception, remove the bias from loop-carried phis when propagating
44638fd1498Szrj 	 the rank so that dependent operations are not also biased.  */
44738fd1498Szrj       /* Simply walk over all SSA uses - this takes advatage of the
44838fd1498Szrj          fact that non-SSA operands are is_gimple_min_invariant and
44938fd1498Szrj 	 thus have rank 0.  */
45038fd1498Szrj       rank = 0;
45138fd1498Szrj       FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
45238fd1498Szrj 	rank = propagate_rank (rank, op);
45338fd1498Szrj 
45438fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
45538fd1498Szrj 	{
45638fd1498Szrj 	  fprintf (dump_file, "Rank for ");
45738fd1498Szrj 	  print_generic_expr (dump_file, e);
45838fd1498Szrj 	  fprintf (dump_file, " is %ld\n", (rank + 1));
45938fd1498Szrj 	}
46038fd1498Szrj 
46138fd1498Szrj       /* Note the rank in the hashtable so we don't recompute it.  */
46238fd1498Szrj       insert_operand_rank (e, (rank + 1));
46338fd1498Szrj       return (rank + 1);
46438fd1498Szrj     }
46538fd1498Szrj 
46638fd1498Szrj   /* Constants, globals, etc., are rank 0 */
46738fd1498Szrj   return 0;
46838fd1498Szrj }
46938fd1498Szrj 
47038fd1498Szrj 
47138fd1498Szrj /* We want integer ones to end up last no matter what, since they are
47238fd1498Szrj    the ones we can do the most with.  */
47338fd1498Szrj #define INTEGER_CONST_TYPE 1 << 4
47438fd1498Szrj #define FLOAT_ONE_CONST_TYPE 1 << 3
47538fd1498Szrj #define FLOAT_CONST_TYPE 1 << 2
47638fd1498Szrj #define OTHER_CONST_TYPE 1 << 1
47738fd1498Szrj 
47838fd1498Szrj /* Classify an invariant tree into integer, float, or other, so that
47938fd1498Szrj    we can sort them to be near other constants of the same type.  */
48038fd1498Szrj static inline int
constant_type(tree t)48138fd1498Szrj constant_type (tree t)
48238fd1498Szrj {
48338fd1498Szrj   if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
48438fd1498Szrj     return INTEGER_CONST_TYPE;
48538fd1498Szrj   else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (t)))
48638fd1498Szrj     {
48738fd1498Szrj       /* Sort -1.0 and 1.0 constants last, while in some cases
48838fd1498Szrj 	 const_binop can't optimize some inexact operations, multiplication
48938fd1498Szrj 	 by -1.0 or 1.0 can be always merged with others.  */
49038fd1498Szrj       if (real_onep (t) || real_minus_onep (t))
49138fd1498Szrj 	return FLOAT_ONE_CONST_TYPE;
49238fd1498Szrj       return FLOAT_CONST_TYPE;
49338fd1498Szrj     }
49438fd1498Szrj   else
49538fd1498Szrj     return OTHER_CONST_TYPE;
49638fd1498Szrj }
49738fd1498Szrj 
49838fd1498Szrj /* qsort comparison function to sort operand entries PA and PB by rank
49938fd1498Szrj    so that the sorted array is ordered by rank in decreasing order.  */
50038fd1498Szrj static int
sort_by_operand_rank(const void * pa,const void * pb)50138fd1498Szrj sort_by_operand_rank (const void *pa, const void *pb)
50238fd1498Szrj {
50338fd1498Szrj   const operand_entry *oea = *(const operand_entry *const *)pa;
50438fd1498Szrj   const operand_entry *oeb = *(const operand_entry *const *)pb;
50538fd1498Szrj 
50638fd1498Szrj   if (oeb->rank != oea->rank)
50738fd1498Szrj     return oeb->rank > oea->rank ? 1 : -1;
50838fd1498Szrj 
50938fd1498Szrj   /* It's nicer for optimize_expression if constants that are likely
51038fd1498Szrj      to fold when added/multiplied/whatever are put next to each
51138fd1498Szrj      other.  Since all constants have rank 0, order them by type.  */
51238fd1498Szrj   if (oea->rank == 0)
51338fd1498Szrj     {
51438fd1498Szrj       if (constant_type (oeb->op) != constant_type (oea->op))
51538fd1498Szrj 	return constant_type (oea->op) - constant_type (oeb->op);
51638fd1498Szrj       else
51738fd1498Szrj 	/* To make sorting result stable, we use unique IDs to determine
51838fd1498Szrj 	   order.  */
51938fd1498Szrj 	return oeb->id > oea->id ? 1 : -1;
52038fd1498Szrj     }
52138fd1498Szrj 
52238fd1498Szrj   if (TREE_CODE (oea->op) != SSA_NAME)
52338fd1498Szrj     {
52438fd1498Szrj       if (TREE_CODE (oeb->op) != SSA_NAME)
52538fd1498Szrj 	return oeb->id > oea->id ? 1 : -1;
52638fd1498Szrj       else
52738fd1498Szrj 	return 1;
52838fd1498Szrj     }
52938fd1498Szrj   else if (TREE_CODE (oeb->op) != SSA_NAME)
53038fd1498Szrj     return -1;
53138fd1498Szrj 
53238fd1498Szrj   /* Lastly, make sure the versions that are the same go next to each
53338fd1498Szrj      other.  */
53438fd1498Szrj   if (SSA_NAME_VERSION (oeb->op) != SSA_NAME_VERSION (oea->op))
53538fd1498Szrj     {
53638fd1498Szrj       /* As SSA_NAME_VERSION is assigned pretty randomly, because we reuse
53738fd1498Szrj 	 versions of removed SSA_NAMEs, so if possible, prefer to sort
53838fd1498Szrj 	 based on basic block and gimple_uid of the SSA_NAME_DEF_STMT.
53938fd1498Szrj 	 See PR60418.  */
54038fd1498Szrj       gimple *stmta = SSA_NAME_DEF_STMT (oea->op);
54138fd1498Szrj       gimple *stmtb = SSA_NAME_DEF_STMT (oeb->op);
54238fd1498Szrj       basic_block bba = gimple_bb (stmta);
54338fd1498Szrj       basic_block bbb = gimple_bb (stmtb);
54438fd1498Szrj       if (bbb != bba)
54538fd1498Szrj 	{
54638fd1498Szrj 	  /* One of the SSA_NAMEs can be defined in oeN->stmt_to_insert
54738fd1498Szrj 	     but the other might not.  */
54838fd1498Szrj 	  if (!bba)
54938fd1498Szrj 	    return 1;
55038fd1498Szrj 	  if (!bbb)
55138fd1498Szrj 	    return -1;
55238fd1498Szrj 	  /* If neither is, compare bb_rank.  */
55338fd1498Szrj 	  if (bb_rank[bbb->index] != bb_rank[bba->index])
55438fd1498Szrj 	    return (bb_rank[bbb->index] >> 16) - (bb_rank[bba->index] >> 16);
55538fd1498Szrj 	}
55638fd1498Szrj 
55738fd1498Szrj       bool da = reassoc_stmt_dominates_stmt_p (stmta, stmtb);
55838fd1498Szrj       bool db = reassoc_stmt_dominates_stmt_p (stmtb, stmta);
55938fd1498Szrj       if (da != db)
56038fd1498Szrj 	return da ? 1 : -1;
56138fd1498Szrj 
56238fd1498Szrj       return SSA_NAME_VERSION (oeb->op) > SSA_NAME_VERSION (oea->op) ? 1 : -1;
56338fd1498Szrj     }
56438fd1498Szrj 
56538fd1498Szrj   return oeb->id > oea->id ? 1 : -1;
56638fd1498Szrj }
56738fd1498Szrj 
56838fd1498Szrj /* Add an operand entry to *OPS for the tree operand OP.  */
56938fd1498Szrj 
57038fd1498Szrj static void
57138fd1498Szrj add_to_ops_vec (vec<operand_entry *> *ops, tree op, gimple *stmt_to_insert = NULL)
57238fd1498Szrj {
57338fd1498Szrj   operand_entry *oe = operand_entry_pool.allocate ();
57438fd1498Szrj 
57538fd1498Szrj   oe->op = op;
57638fd1498Szrj   oe->rank = get_rank (op);
57738fd1498Szrj   oe->id = next_operand_entry_id++;
57838fd1498Szrj   oe->count = 1;
57938fd1498Szrj   oe->stmt_to_insert = stmt_to_insert;
58038fd1498Szrj   ops->safe_push (oe);
58138fd1498Szrj }
58238fd1498Szrj 
58338fd1498Szrj /* Add an operand entry to *OPS for the tree operand OP with repeat
58438fd1498Szrj    count REPEAT.  */
58538fd1498Szrj 
58638fd1498Szrj static void
add_repeat_to_ops_vec(vec<operand_entry * > * ops,tree op,HOST_WIDE_INT repeat)58738fd1498Szrj add_repeat_to_ops_vec (vec<operand_entry *> *ops, tree op,
58838fd1498Szrj 		       HOST_WIDE_INT repeat)
58938fd1498Szrj {
59038fd1498Szrj   operand_entry *oe = operand_entry_pool.allocate ();
59138fd1498Szrj 
59238fd1498Szrj   oe->op = op;
59338fd1498Szrj   oe->rank = get_rank (op);
59438fd1498Szrj   oe->id = next_operand_entry_id++;
59538fd1498Szrj   oe->count = repeat;
59638fd1498Szrj   oe->stmt_to_insert = NULL;
59738fd1498Szrj   ops->safe_push (oe);
59838fd1498Szrj 
59938fd1498Szrj   reassociate_stats.pows_encountered++;
60038fd1498Szrj }
60138fd1498Szrj 
60238fd1498Szrj /* Return true if STMT is reassociable operation containing a binary
60338fd1498Szrj    operation with tree code CODE, and is inside LOOP.  */
60438fd1498Szrj 
60538fd1498Szrj static bool
is_reassociable_op(gimple * stmt,enum tree_code code,struct loop * loop)60638fd1498Szrj is_reassociable_op (gimple *stmt, enum tree_code code, struct loop *loop)
60738fd1498Szrj {
60838fd1498Szrj   basic_block bb = gimple_bb (stmt);
60938fd1498Szrj 
61038fd1498Szrj   if (gimple_bb (stmt) == NULL)
61138fd1498Szrj     return false;
61238fd1498Szrj 
61338fd1498Szrj   if (!flow_bb_inside_loop_p (loop, bb))
61438fd1498Szrj     return false;
61538fd1498Szrj 
61638fd1498Szrj   if (is_gimple_assign (stmt)
61738fd1498Szrj       && gimple_assign_rhs_code (stmt) == code
61838fd1498Szrj       && has_single_use (gimple_assign_lhs (stmt)))
61938fd1498Szrj     {
62038fd1498Szrj       tree rhs1 = gimple_assign_rhs1 (stmt);
62138fd1498Szrj       tree rhs2 = gimple_assign_rhs1 (stmt);
62238fd1498Szrj       if (TREE_CODE (rhs1) == SSA_NAME
62338fd1498Szrj 	  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
62438fd1498Szrj 	return false;
62538fd1498Szrj       if (rhs2
62638fd1498Szrj 	  && TREE_CODE (rhs2) == SSA_NAME
62738fd1498Szrj 	  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs2))
62838fd1498Szrj 	return false;
62938fd1498Szrj       return true;
63038fd1498Szrj     }
63138fd1498Szrj 
63238fd1498Szrj   return false;
63338fd1498Szrj }
63438fd1498Szrj 
63538fd1498Szrj 
63638fd1498Szrj /* Return true if STMT is a nop-conversion.  */
63738fd1498Szrj 
63838fd1498Szrj static bool
gimple_nop_conversion_p(gimple * stmt)63938fd1498Szrj gimple_nop_conversion_p (gimple *stmt)
64038fd1498Szrj {
64138fd1498Szrj   if (gassign *ass = dyn_cast <gassign *> (stmt))
64238fd1498Szrj     {
64338fd1498Szrj       if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (ass))
64438fd1498Szrj 	  && tree_nop_conversion_p (TREE_TYPE (gimple_assign_lhs (ass)),
64538fd1498Szrj 				    TREE_TYPE (gimple_assign_rhs1 (ass))))
64638fd1498Szrj 	return true;
64738fd1498Szrj     }
64838fd1498Szrj   return false;
64938fd1498Szrj }
65038fd1498Szrj 
65138fd1498Szrj /* Given NAME, if NAME is defined by a unary operation OPCODE, return the
65238fd1498Szrj    operand of the negate operation.  Otherwise, return NULL.  */
65338fd1498Szrj 
65438fd1498Szrj static tree
get_unary_op(tree name,enum tree_code opcode)65538fd1498Szrj get_unary_op (tree name, enum tree_code opcode)
65638fd1498Szrj {
65738fd1498Szrj   gimple *stmt = SSA_NAME_DEF_STMT (name);
65838fd1498Szrj 
65938fd1498Szrj   /* Look through nop conversions (sign changes).  */
66038fd1498Szrj   if (gimple_nop_conversion_p (stmt)
66138fd1498Szrj       && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
66238fd1498Szrj     stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
66338fd1498Szrj 
66438fd1498Szrj   if (!is_gimple_assign (stmt))
66538fd1498Szrj     return NULL_TREE;
66638fd1498Szrj 
66738fd1498Szrj   if (gimple_assign_rhs_code (stmt) == opcode)
66838fd1498Szrj     return gimple_assign_rhs1 (stmt);
66938fd1498Szrj   return NULL_TREE;
67038fd1498Szrj }
67138fd1498Szrj 
67238fd1498Szrj /* Return true if OP1 and OP2 have the same value if casted to either type.  */
67338fd1498Szrj 
67438fd1498Szrj static bool
ops_equal_values_p(tree op1,tree op2)67538fd1498Szrj ops_equal_values_p (tree op1, tree op2)
67638fd1498Szrj {
67738fd1498Szrj   if (op1 == op2)
67838fd1498Szrj     return true;
67938fd1498Szrj 
68038fd1498Szrj   tree orig_op1 = op1;
68138fd1498Szrj   if (TREE_CODE (op1) == SSA_NAME)
68238fd1498Szrj     {
68338fd1498Szrj       gimple *stmt = SSA_NAME_DEF_STMT (op1);
68438fd1498Szrj       if (gimple_nop_conversion_p (stmt))
68538fd1498Szrj 	{
68638fd1498Szrj 	  op1 = gimple_assign_rhs1 (stmt);
68738fd1498Szrj 	  if (op1 == op2)
68838fd1498Szrj 	    return true;
68938fd1498Szrj 	}
69038fd1498Szrj     }
69138fd1498Szrj 
69238fd1498Szrj   if (TREE_CODE (op2) == SSA_NAME)
69338fd1498Szrj     {
69438fd1498Szrj       gimple *stmt = SSA_NAME_DEF_STMT (op2);
69538fd1498Szrj       if (gimple_nop_conversion_p (stmt))
69638fd1498Szrj 	{
69738fd1498Szrj 	  op2 = gimple_assign_rhs1 (stmt);
69838fd1498Szrj 	  if (op1 == op2
69938fd1498Szrj 	      || orig_op1 == op2)
70038fd1498Szrj 	    return true;
70138fd1498Szrj 	}
70238fd1498Szrj     }
70338fd1498Szrj 
70438fd1498Szrj   return false;
70538fd1498Szrj }
70638fd1498Szrj 
70738fd1498Szrj 
70838fd1498Szrj /* If CURR and LAST are a pair of ops that OPCODE allows us to
70938fd1498Szrj    eliminate through equivalences, do so, remove them from OPS, and
71038fd1498Szrj    return true.  Otherwise, return false.  */
71138fd1498Szrj 
71238fd1498Szrj static bool
eliminate_duplicate_pair(enum tree_code opcode,vec<operand_entry * > * ops,bool * all_done,unsigned int i,operand_entry * curr,operand_entry * last)71338fd1498Szrj eliminate_duplicate_pair (enum tree_code opcode,
71438fd1498Szrj 			  vec<operand_entry *> *ops,
71538fd1498Szrj 			  bool *all_done,
71638fd1498Szrj 			  unsigned int i,
71738fd1498Szrj 			  operand_entry *curr,
71838fd1498Szrj 			  operand_entry *last)
71938fd1498Szrj {
72038fd1498Szrj 
72138fd1498Szrj   /* If we have two of the same op, and the opcode is & |, min, or max,
72238fd1498Szrj      we can eliminate one of them.
72338fd1498Szrj      If we have two of the same op, and the opcode is ^, we can
72438fd1498Szrj      eliminate both of them.  */
72538fd1498Szrj 
72638fd1498Szrj   if (last && last->op == curr->op)
72738fd1498Szrj     {
72838fd1498Szrj       switch (opcode)
72938fd1498Szrj 	{
73038fd1498Szrj 	case MAX_EXPR:
73138fd1498Szrj 	case MIN_EXPR:
73238fd1498Szrj 	case BIT_IOR_EXPR:
73338fd1498Szrj 	case BIT_AND_EXPR:
73438fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
73538fd1498Szrj 	    {
73638fd1498Szrj 	      fprintf (dump_file, "Equivalence: ");
73738fd1498Szrj 	      print_generic_expr (dump_file, curr->op);
73838fd1498Szrj 	      fprintf (dump_file, " [&|minmax] ");
73938fd1498Szrj 	      print_generic_expr (dump_file, last->op);
74038fd1498Szrj 	      fprintf (dump_file, " -> ");
74138fd1498Szrj 	      print_generic_stmt (dump_file, last->op);
74238fd1498Szrj 	    }
74338fd1498Szrj 
74438fd1498Szrj 	  ops->ordered_remove (i);
74538fd1498Szrj 	  reassociate_stats.ops_eliminated ++;
74638fd1498Szrj 
74738fd1498Szrj 	  return true;
74838fd1498Szrj 
74938fd1498Szrj 	case BIT_XOR_EXPR:
75038fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
75138fd1498Szrj 	    {
75238fd1498Szrj 	      fprintf (dump_file, "Equivalence: ");
75338fd1498Szrj 	      print_generic_expr (dump_file, curr->op);
75438fd1498Szrj 	      fprintf (dump_file, " ^ ");
75538fd1498Szrj 	      print_generic_expr (dump_file, last->op);
75638fd1498Szrj 	      fprintf (dump_file, " -> nothing\n");
75738fd1498Szrj 	    }
75838fd1498Szrj 
75938fd1498Szrj 	  reassociate_stats.ops_eliminated += 2;
76038fd1498Szrj 
76138fd1498Szrj 	  if (ops->length () == 2)
76238fd1498Szrj 	    {
76338fd1498Szrj 	      ops->truncate (0);
76438fd1498Szrj 	      add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (last->op)));
76538fd1498Szrj 	      *all_done = true;
76638fd1498Szrj 	    }
76738fd1498Szrj 	  else
76838fd1498Szrj 	    {
76938fd1498Szrj 	      ops->ordered_remove (i-1);
77038fd1498Szrj 	      ops->ordered_remove (i-1);
77138fd1498Szrj 	    }
77238fd1498Szrj 
77338fd1498Szrj 	  return true;
77438fd1498Szrj 
77538fd1498Szrj 	default:
77638fd1498Szrj 	  break;
77738fd1498Szrj 	}
77838fd1498Szrj     }
77938fd1498Szrj   return false;
78038fd1498Szrj }
78138fd1498Szrj 
78238fd1498Szrj static vec<tree> plus_negates;
78338fd1498Szrj 
78438fd1498Szrj /* If OPCODE is PLUS_EXPR, CURR->OP is a negate expression or a bitwise not
78538fd1498Szrj    expression, look in OPS for a corresponding positive operation to cancel
78638fd1498Szrj    it out.  If we find one, remove the other from OPS, replace
78738fd1498Szrj    OPS[CURRINDEX] with 0 or -1, respectively, and return true.  Otherwise,
78838fd1498Szrj    return false. */
78938fd1498Szrj 
79038fd1498Szrj static bool
eliminate_plus_minus_pair(enum tree_code opcode,vec<operand_entry * > * ops,unsigned int currindex,operand_entry * curr)79138fd1498Szrj eliminate_plus_minus_pair (enum tree_code opcode,
79238fd1498Szrj 			   vec<operand_entry *> *ops,
79338fd1498Szrj 			   unsigned int currindex,
79438fd1498Szrj 			   operand_entry *curr)
79538fd1498Szrj {
79638fd1498Szrj   tree negateop;
79738fd1498Szrj   tree notop;
79838fd1498Szrj   unsigned int i;
79938fd1498Szrj   operand_entry *oe;
80038fd1498Szrj 
80138fd1498Szrj   if (opcode != PLUS_EXPR || TREE_CODE (curr->op) != SSA_NAME)
80238fd1498Szrj     return false;
80338fd1498Szrj 
80438fd1498Szrj   negateop = get_unary_op (curr->op, NEGATE_EXPR);
80538fd1498Szrj   notop = get_unary_op (curr->op, BIT_NOT_EXPR);
80638fd1498Szrj   if (negateop == NULL_TREE && notop == NULL_TREE)
80738fd1498Szrj     return false;
80838fd1498Szrj 
80938fd1498Szrj   /* Any non-negated version will have a rank that is one less than
81038fd1498Szrj      the current rank.  So once we hit those ranks, if we don't find
81138fd1498Szrj      one, we can stop.  */
81238fd1498Szrj 
81338fd1498Szrj   for (i = currindex + 1;
81438fd1498Szrj        ops->iterate (i, &oe)
81538fd1498Szrj        && oe->rank >= curr->rank - 1 ;
81638fd1498Szrj        i++)
81738fd1498Szrj     {
81838fd1498Szrj       if (negateop
81938fd1498Szrj 	  && ops_equal_values_p (oe->op, negateop))
82038fd1498Szrj 	{
82138fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
82238fd1498Szrj 	    {
82338fd1498Szrj 	      fprintf (dump_file, "Equivalence: ");
82438fd1498Szrj 	      print_generic_expr (dump_file, negateop);
82538fd1498Szrj 	      fprintf (dump_file, " + -");
82638fd1498Szrj 	      print_generic_expr (dump_file, oe->op);
82738fd1498Szrj 	      fprintf (dump_file, " -> 0\n");
82838fd1498Szrj 	    }
82938fd1498Szrj 
83038fd1498Szrj 	  ops->ordered_remove (i);
83138fd1498Szrj 	  add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (oe->op)));
83238fd1498Szrj 	  ops->ordered_remove (currindex);
83338fd1498Szrj 	  reassociate_stats.ops_eliminated ++;
83438fd1498Szrj 
83538fd1498Szrj 	  return true;
83638fd1498Szrj 	}
83738fd1498Szrj       else if (notop
83838fd1498Szrj 	       && ops_equal_values_p (oe->op, notop))
83938fd1498Szrj 	{
84038fd1498Szrj 	  tree op_type = TREE_TYPE (oe->op);
84138fd1498Szrj 
84238fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
84338fd1498Szrj 	    {
84438fd1498Szrj 	      fprintf (dump_file, "Equivalence: ");
84538fd1498Szrj 	      print_generic_expr (dump_file, notop);
84638fd1498Szrj 	      fprintf (dump_file, " + ~");
84738fd1498Szrj 	      print_generic_expr (dump_file, oe->op);
84838fd1498Szrj 	      fprintf (dump_file, " -> -1\n");
84938fd1498Szrj 	    }
85038fd1498Szrj 
85138fd1498Szrj 	  ops->ordered_remove (i);
85238fd1498Szrj 	  add_to_ops_vec (ops, build_all_ones_cst (op_type));
85338fd1498Szrj 	  ops->ordered_remove (currindex);
85438fd1498Szrj 	  reassociate_stats.ops_eliminated ++;
85538fd1498Szrj 
85638fd1498Szrj 	  return true;
85738fd1498Szrj 	}
85838fd1498Szrj     }
85938fd1498Szrj 
86038fd1498Szrj   /* If CURR->OP is a negate expr without nop conversion in a plus expr:
86138fd1498Szrj      save it for later inspection in repropagate_negates().  */
86238fd1498Szrj   if (negateop != NULL_TREE
86338fd1498Szrj       && gimple_assign_rhs_code (SSA_NAME_DEF_STMT (curr->op)) == NEGATE_EXPR)
86438fd1498Szrj     plus_negates.safe_push (curr->op);
86538fd1498Szrj 
86638fd1498Szrj   return false;
86738fd1498Szrj }
86838fd1498Szrj 
86938fd1498Szrj /* If OPCODE is BIT_IOR_EXPR, BIT_AND_EXPR, and, CURR->OP is really a
87038fd1498Szrj    bitwise not expression, look in OPS for a corresponding operand to
87138fd1498Szrj    cancel it out.  If we find one, remove the other from OPS, replace
87238fd1498Szrj    OPS[CURRINDEX] with 0, and return true.  Otherwise, return
87338fd1498Szrj    false. */
87438fd1498Szrj 
87538fd1498Szrj static bool
eliminate_not_pairs(enum tree_code opcode,vec<operand_entry * > * ops,unsigned int currindex,operand_entry * curr)87638fd1498Szrj eliminate_not_pairs (enum tree_code opcode,
87738fd1498Szrj 		     vec<operand_entry *> *ops,
87838fd1498Szrj 		     unsigned int currindex,
87938fd1498Szrj 		     operand_entry *curr)
88038fd1498Szrj {
88138fd1498Szrj   tree notop;
88238fd1498Szrj   unsigned int i;
88338fd1498Szrj   operand_entry *oe;
88438fd1498Szrj 
88538fd1498Szrj   if ((opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
88638fd1498Szrj       || TREE_CODE (curr->op) != SSA_NAME)
88738fd1498Szrj     return false;
88838fd1498Szrj 
88938fd1498Szrj   notop = get_unary_op (curr->op, BIT_NOT_EXPR);
89038fd1498Szrj   if (notop == NULL_TREE)
89138fd1498Szrj     return false;
89238fd1498Szrj 
89338fd1498Szrj   /* Any non-not version will have a rank that is one less than
89438fd1498Szrj      the current rank.  So once we hit those ranks, if we don't find
89538fd1498Szrj      one, we can stop.  */
89638fd1498Szrj 
89738fd1498Szrj   for (i = currindex + 1;
89838fd1498Szrj        ops->iterate (i, &oe)
89938fd1498Szrj        && oe->rank >= curr->rank - 1;
90038fd1498Szrj        i++)
90138fd1498Szrj     {
90238fd1498Szrj       if (oe->op == notop)
90338fd1498Szrj 	{
90438fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
90538fd1498Szrj 	    {
90638fd1498Szrj 	      fprintf (dump_file, "Equivalence: ");
90738fd1498Szrj 	      print_generic_expr (dump_file, notop);
90838fd1498Szrj 	      if (opcode == BIT_AND_EXPR)
90938fd1498Szrj 		fprintf (dump_file, " & ~");
91038fd1498Szrj 	      else if (opcode == BIT_IOR_EXPR)
91138fd1498Szrj 		fprintf (dump_file, " | ~");
91238fd1498Szrj 	      print_generic_expr (dump_file, oe->op);
91338fd1498Szrj 	      if (opcode == BIT_AND_EXPR)
91438fd1498Szrj 		fprintf (dump_file, " -> 0\n");
91538fd1498Szrj 	      else if (opcode == BIT_IOR_EXPR)
91638fd1498Szrj 		fprintf (dump_file, " -> -1\n");
91738fd1498Szrj 	    }
91838fd1498Szrj 
91938fd1498Szrj 	  if (opcode == BIT_AND_EXPR)
92038fd1498Szrj 	    oe->op = build_zero_cst (TREE_TYPE (oe->op));
92138fd1498Szrj 	  else if (opcode == BIT_IOR_EXPR)
92238fd1498Szrj 	    oe->op = build_all_ones_cst (TREE_TYPE (oe->op));
92338fd1498Szrj 
92438fd1498Szrj 	  reassociate_stats.ops_eliminated += ops->length () - 1;
92538fd1498Szrj 	  ops->truncate (0);
92638fd1498Szrj 	  ops->quick_push (oe);
92738fd1498Szrj 	  return true;
92838fd1498Szrj 	}
92938fd1498Szrj     }
93038fd1498Szrj 
93138fd1498Szrj   return false;
93238fd1498Szrj }
93338fd1498Szrj 
93438fd1498Szrj /* Use constant value that may be present in OPS to try to eliminate
93538fd1498Szrj    operands.  Note that this function is only really used when we've
93638fd1498Szrj    eliminated ops for other reasons, or merged constants.  Across
93738fd1498Szrj    single statements, fold already does all of this, plus more.  There
93838fd1498Szrj    is little point in duplicating logic, so I've only included the
93938fd1498Szrj    identities that I could ever construct testcases to trigger.  */
94038fd1498Szrj 
94138fd1498Szrj static void
eliminate_using_constants(enum tree_code opcode,vec<operand_entry * > * ops)94238fd1498Szrj eliminate_using_constants (enum tree_code opcode,
94338fd1498Szrj 			   vec<operand_entry *> *ops)
94438fd1498Szrj {
94538fd1498Szrj   operand_entry *oelast = ops->last ();
94638fd1498Szrj   tree type = TREE_TYPE (oelast->op);
94738fd1498Szrj 
94838fd1498Szrj   if (oelast->rank == 0
94938fd1498Szrj       && (ANY_INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type)))
95038fd1498Szrj     {
95138fd1498Szrj       switch (opcode)
95238fd1498Szrj 	{
95338fd1498Szrj 	case BIT_AND_EXPR:
95438fd1498Szrj 	  if (integer_zerop (oelast->op))
95538fd1498Szrj 	    {
95638fd1498Szrj 	      if (ops->length () != 1)
95738fd1498Szrj 		{
95838fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
95938fd1498Szrj 		    fprintf (dump_file, "Found & 0, removing all other ops\n");
96038fd1498Szrj 
96138fd1498Szrj 		  reassociate_stats.ops_eliminated += ops->length () - 1;
96238fd1498Szrj 
96338fd1498Szrj 		  ops->truncate (0);
96438fd1498Szrj 		  ops->quick_push (oelast);
96538fd1498Szrj 		  return;
96638fd1498Szrj 		}
96738fd1498Szrj 	    }
96838fd1498Szrj 	  else if (integer_all_onesp (oelast->op))
96938fd1498Szrj 	    {
97038fd1498Szrj 	      if (ops->length () != 1)
97138fd1498Szrj 		{
97238fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
97338fd1498Szrj 		    fprintf (dump_file, "Found & -1, removing\n");
97438fd1498Szrj 		  ops->pop ();
97538fd1498Szrj 		  reassociate_stats.ops_eliminated++;
97638fd1498Szrj 		}
97738fd1498Szrj 	    }
97838fd1498Szrj 	  break;
97938fd1498Szrj 	case BIT_IOR_EXPR:
98038fd1498Szrj 	  if (integer_all_onesp (oelast->op))
98138fd1498Szrj 	    {
98238fd1498Szrj 	      if (ops->length () != 1)
98338fd1498Szrj 		{
98438fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
98538fd1498Szrj 		    fprintf (dump_file, "Found | -1, removing all other ops\n");
98638fd1498Szrj 
98738fd1498Szrj 		  reassociate_stats.ops_eliminated += ops->length () - 1;
98838fd1498Szrj 
98938fd1498Szrj 		  ops->truncate (0);
99038fd1498Szrj 		  ops->quick_push (oelast);
99138fd1498Szrj 		  return;
99238fd1498Szrj 		}
99338fd1498Szrj 	    }
99438fd1498Szrj 	  else if (integer_zerop (oelast->op))
99538fd1498Szrj 	    {
99638fd1498Szrj 	      if (ops->length () != 1)
99738fd1498Szrj 		{
99838fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
99938fd1498Szrj 		    fprintf (dump_file, "Found | 0, removing\n");
100038fd1498Szrj 		  ops->pop ();
100138fd1498Szrj 		  reassociate_stats.ops_eliminated++;
100238fd1498Szrj 		}
100338fd1498Szrj 	    }
100438fd1498Szrj 	  break;
100538fd1498Szrj 	case MULT_EXPR:
100638fd1498Szrj 	  if (integer_zerop (oelast->op)
100738fd1498Szrj 	      || (FLOAT_TYPE_P (type)
100838fd1498Szrj 		  && !HONOR_NANS (type)
100938fd1498Szrj 		  && !HONOR_SIGNED_ZEROS (type)
101038fd1498Szrj 		  && real_zerop (oelast->op)))
101138fd1498Szrj 	    {
101238fd1498Szrj 	      if (ops->length () != 1)
101338fd1498Szrj 		{
101438fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
101538fd1498Szrj 		    fprintf (dump_file, "Found * 0, removing all other ops\n");
101638fd1498Szrj 
101738fd1498Szrj 		  reassociate_stats.ops_eliminated += ops->length () - 1;
1018*58e805e6Szrj 		  ops->truncate (0);
101938fd1498Szrj 		  ops->quick_push (oelast);
102038fd1498Szrj 		  return;
102138fd1498Szrj 		}
102238fd1498Szrj 	    }
102338fd1498Szrj 	  else if (integer_onep (oelast->op)
102438fd1498Szrj 		   || (FLOAT_TYPE_P (type)
102538fd1498Szrj 		       && !HONOR_SNANS (type)
102638fd1498Szrj 		       && real_onep (oelast->op)))
102738fd1498Szrj 	    {
102838fd1498Szrj 	      if (ops->length () != 1)
102938fd1498Szrj 		{
103038fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
103138fd1498Szrj 		    fprintf (dump_file, "Found * 1, removing\n");
103238fd1498Szrj 		  ops->pop ();
103338fd1498Szrj 		  reassociate_stats.ops_eliminated++;
103438fd1498Szrj 		  return;
103538fd1498Szrj 		}
103638fd1498Szrj 	    }
103738fd1498Szrj 	  break;
103838fd1498Szrj 	case BIT_XOR_EXPR:
103938fd1498Szrj 	case PLUS_EXPR:
104038fd1498Szrj 	case MINUS_EXPR:
104138fd1498Szrj 	  if (integer_zerop (oelast->op)
104238fd1498Szrj 	      || (FLOAT_TYPE_P (type)
104338fd1498Szrj 		  && (opcode == PLUS_EXPR || opcode == MINUS_EXPR)
104438fd1498Szrj 		  && fold_real_zero_addition_p (type, oelast->op,
104538fd1498Szrj 						opcode == MINUS_EXPR)))
104638fd1498Szrj 	    {
104738fd1498Szrj 	      if (ops->length () != 1)
104838fd1498Szrj 		{
104938fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
105038fd1498Szrj 		    fprintf (dump_file, "Found [|^+] 0, removing\n");
105138fd1498Szrj 		  ops->pop ();
105238fd1498Szrj 		  reassociate_stats.ops_eliminated++;
105338fd1498Szrj 		  return;
105438fd1498Szrj 		}
105538fd1498Szrj 	    }
105638fd1498Szrj 	  break;
105738fd1498Szrj 	default:
105838fd1498Szrj 	  break;
105938fd1498Szrj 	}
106038fd1498Szrj     }
106138fd1498Szrj }
106238fd1498Szrj 
106338fd1498Szrj 
106438fd1498Szrj static void linearize_expr_tree (vec<operand_entry *> *, gimple *,
106538fd1498Szrj 				 bool, bool);
106638fd1498Szrj 
106738fd1498Szrj /* Structure for tracking and counting operands.  */
106838fd1498Szrj struct oecount {
106938fd1498Szrj   unsigned int cnt;
107038fd1498Szrj   unsigned int id;
107138fd1498Szrj   enum tree_code oecode;
107238fd1498Szrj   tree op;
107338fd1498Szrj };
107438fd1498Szrj 
107538fd1498Szrj 
107638fd1498Szrj /* The heap for the oecount hashtable and the sorted list of operands.  */
107738fd1498Szrj static vec<oecount> cvec;
107838fd1498Szrj 
107938fd1498Szrj 
108038fd1498Szrj /* Oecount hashtable helpers.  */
108138fd1498Szrj 
108238fd1498Szrj struct oecount_hasher : int_hash <int, 0, 1>
108338fd1498Szrj {
108438fd1498Szrj   static inline hashval_t hash (int);
108538fd1498Szrj   static inline bool equal (int, int);
108638fd1498Szrj };
108738fd1498Szrj 
108838fd1498Szrj /* Hash function for oecount.  */
108938fd1498Szrj 
109038fd1498Szrj inline hashval_t
hash(int p)109138fd1498Szrj oecount_hasher::hash (int p)
109238fd1498Szrj {
109338fd1498Szrj   const oecount *c = &cvec[p - 42];
109438fd1498Szrj   return htab_hash_pointer (c->op) ^ (hashval_t)c->oecode;
109538fd1498Szrj }
109638fd1498Szrj 
109738fd1498Szrj /* Comparison function for oecount.  */
109838fd1498Szrj 
109938fd1498Szrj inline bool
equal(int p1,int p2)110038fd1498Szrj oecount_hasher::equal (int p1, int p2)
110138fd1498Szrj {
110238fd1498Szrj   const oecount *c1 = &cvec[p1 - 42];
110338fd1498Szrj   const oecount *c2 = &cvec[p2 - 42];
110438fd1498Szrj   return c1->oecode == c2->oecode && c1->op == c2->op;
110538fd1498Szrj }
110638fd1498Szrj 
110738fd1498Szrj /* Comparison function for qsort sorting oecount elements by count.  */
110838fd1498Szrj 
110938fd1498Szrj static int
oecount_cmp(const void * p1,const void * p2)111038fd1498Szrj oecount_cmp (const void *p1, const void *p2)
111138fd1498Szrj {
111238fd1498Szrj   const oecount *c1 = (const oecount *)p1;
111338fd1498Szrj   const oecount *c2 = (const oecount *)p2;
111438fd1498Szrj   if (c1->cnt != c2->cnt)
111538fd1498Szrj     return c1->cnt > c2->cnt ? 1 : -1;
111638fd1498Szrj   else
111738fd1498Szrj     /* If counts are identical, use unique IDs to stabilize qsort.  */
111838fd1498Szrj     return c1->id > c2->id ? 1 : -1;
111938fd1498Szrj }
112038fd1498Szrj 
112138fd1498Szrj /* Return TRUE iff STMT represents a builtin call that raises OP
112238fd1498Szrj    to some exponent.  */
112338fd1498Szrj 
112438fd1498Szrj static bool
stmt_is_power_of_op(gimple * stmt,tree op)112538fd1498Szrj stmt_is_power_of_op (gimple *stmt, tree op)
112638fd1498Szrj {
112738fd1498Szrj   if (!is_gimple_call (stmt))
112838fd1498Szrj     return false;
112938fd1498Szrj 
113038fd1498Szrj   switch (gimple_call_combined_fn (stmt))
113138fd1498Szrj     {
113238fd1498Szrj     CASE_CFN_POW:
113338fd1498Szrj     CASE_CFN_POWI:
113438fd1498Szrj       return (operand_equal_p (gimple_call_arg (stmt, 0), op, 0));
113538fd1498Szrj 
113638fd1498Szrj     default:
113738fd1498Szrj       return false;
113838fd1498Szrj     }
113938fd1498Szrj }
114038fd1498Szrj 
114138fd1498Szrj /* Given STMT which is a __builtin_pow* call, decrement its exponent
114238fd1498Szrj    in place and return the result.  Assumes that stmt_is_power_of_op
114338fd1498Szrj    was previously called for STMT and returned TRUE.  */
114438fd1498Szrj 
114538fd1498Szrj static HOST_WIDE_INT
decrement_power(gimple * stmt)114638fd1498Szrj decrement_power (gimple *stmt)
114738fd1498Szrj {
114838fd1498Szrj   REAL_VALUE_TYPE c, cint;
114938fd1498Szrj   HOST_WIDE_INT power;
115038fd1498Szrj   tree arg1;
115138fd1498Szrj 
115238fd1498Szrj   switch (gimple_call_combined_fn (stmt))
115338fd1498Szrj     {
115438fd1498Szrj     CASE_CFN_POW:
115538fd1498Szrj       arg1 = gimple_call_arg (stmt, 1);
115638fd1498Szrj       c = TREE_REAL_CST (arg1);
115738fd1498Szrj       power = real_to_integer (&c) - 1;
115838fd1498Szrj       real_from_integer (&cint, VOIDmode, power, SIGNED);
115938fd1498Szrj       gimple_call_set_arg (stmt, 1, build_real (TREE_TYPE (arg1), cint));
116038fd1498Szrj       return power;
116138fd1498Szrj 
116238fd1498Szrj     CASE_CFN_POWI:
116338fd1498Szrj       arg1 = gimple_call_arg (stmt, 1);
116438fd1498Szrj       power = TREE_INT_CST_LOW (arg1) - 1;
116538fd1498Szrj       gimple_call_set_arg (stmt, 1, build_int_cst (TREE_TYPE (arg1), power));
116638fd1498Szrj       return power;
116738fd1498Szrj 
116838fd1498Szrj     default:
116938fd1498Szrj       gcc_unreachable ();
117038fd1498Szrj     }
117138fd1498Szrj }
117238fd1498Szrj 
117338fd1498Szrj /* Replace SSA defined by STMT and replace all its uses with new
117438fd1498Szrj    SSA.  Also return the new SSA.  */
117538fd1498Szrj 
117638fd1498Szrj static tree
make_new_ssa_for_def(gimple * stmt,enum tree_code opcode,tree op)117738fd1498Szrj make_new_ssa_for_def (gimple *stmt, enum tree_code opcode, tree op)
117838fd1498Szrj {
117938fd1498Szrj   gimple *use_stmt;
118038fd1498Szrj   use_operand_p use;
118138fd1498Szrj   imm_use_iterator iter;
118238fd1498Szrj   tree new_lhs, new_debug_lhs = NULL_TREE;
118338fd1498Szrj   tree lhs = gimple_get_lhs (stmt);
118438fd1498Szrj 
118538fd1498Szrj   new_lhs = make_ssa_name (TREE_TYPE (lhs));
118638fd1498Szrj   gimple_set_lhs (stmt, new_lhs);
118738fd1498Szrj 
118838fd1498Szrj   /* Also need to update GIMPLE_DEBUGs.  */
118938fd1498Szrj   FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
119038fd1498Szrj     {
119138fd1498Szrj       tree repl = new_lhs;
119238fd1498Szrj       if (is_gimple_debug (use_stmt))
119338fd1498Szrj 	{
119438fd1498Szrj 	  if (new_debug_lhs == NULL_TREE)
119538fd1498Szrj 	    {
119638fd1498Szrj 	      new_debug_lhs = make_node (DEBUG_EXPR_DECL);
119738fd1498Szrj 	      gdebug *def_temp
119838fd1498Szrj 		= gimple_build_debug_bind (new_debug_lhs,
119938fd1498Szrj 					   build2 (opcode, TREE_TYPE (lhs),
120038fd1498Szrj 						   new_lhs, op),
120138fd1498Szrj 					   stmt);
120238fd1498Szrj 	      DECL_ARTIFICIAL (new_debug_lhs) = 1;
120338fd1498Szrj 	      TREE_TYPE (new_debug_lhs) = TREE_TYPE (lhs);
120438fd1498Szrj 	      SET_DECL_MODE (new_debug_lhs, TYPE_MODE (TREE_TYPE (lhs)));
120538fd1498Szrj 	      gimple_set_uid (def_temp, gimple_uid (stmt));
120638fd1498Szrj 	      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
120738fd1498Szrj 	      gsi_insert_after (&gsi, def_temp, GSI_SAME_STMT);
120838fd1498Szrj 	    }
120938fd1498Szrj 	  repl = new_debug_lhs;
121038fd1498Szrj 	}
121138fd1498Szrj       FOR_EACH_IMM_USE_ON_STMT (use, iter)
121238fd1498Szrj 	SET_USE (use, repl);
121338fd1498Szrj       update_stmt (use_stmt);
121438fd1498Szrj     }
121538fd1498Szrj   return new_lhs;
121638fd1498Szrj }
121738fd1498Szrj 
121838fd1498Szrj /* Replace all SSAs defined in STMTS_TO_FIX and replace its
121938fd1498Szrj    uses with new SSAs.  Also do this for the stmt that defines DEF
122038fd1498Szrj    if *DEF is not OP.  */
122138fd1498Szrj 
122238fd1498Szrj static void
make_new_ssa_for_all_defs(tree * def,enum tree_code opcode,tree op,vec<gimple * > & stmts_to_fix)122338fd1498Szrj make_new_ssa_for_all_defs (tree *def, enum tree_code opcode, tree op,
122438fd1498Szrj 			   vec<gimple *> &stmts_to_fix)
122538fd1498Szrj {
122638fd1498Szrj   unsigned i;
122738fd1498Szrj   gimple *stmt;
122838fd1498Szrj 
122938fd1498Szrj   if (*def != op
123038fd1498Szrj       && TREE_CODE (*def) == SSA_NAME
123138fd1498Szrj       && (stmt = SSA_NAME_DEF_STMT (*def))
123238fd1498Szrj       && gimple_code (stmt) != GIMPLE_NOP)
123338fd1498Szrj     *def = make_new_ssa_for_def (stmt, opcode, op);
123438fd1498Szrj 
123538fd1498Szrj   FOR_EACH_VEC_ELT (stmts_to_fix, i, stmt)
123638fd1498Szrj     make_new_ssa_for_def (stmt, opcode, op);
123738fd1498Szrj }
123838fd1498Szrj 
123938fd1498Szrj /* Find the single immediate use of STMT's LHS, and replace it
124038fd1498Szrj    with OP.  Remove STMT.  If STMT's LHS is the same as *DEF,
124138fd1498Szrj    replace *DEF with OP as well.  */
124238fd1498Szrj 
124338fd1498Szrj static void
propagate_op_to_single_use(tree op,gimple * stmt,tree * def)124438fd1498Szrj propagate_op_to_single_use (tree op, gimple *stmt, tree *def)
124538fd1498Szrj {
124638fd1498Szrj   tree lhs;
124738fd1498Szrj   gimple *use_stmt;
124838fd1498Szrj   use_operand_p use;
124938fd1498Szrj   gimple_stmt_iterator gsi;
125038fd1498Szrj 
125138fd1498Szrj   if (is_gimple_call (stmt))
125238fd1498Szrj     lhs = gimple_call_lhs (stmt);
125338fd1498Szrj   else
125438fd1498Szrj     lhs = gimple_assign_lhs (stmt);
125538fd1498Szrj 
125638fd1498Szrj   gcc_assert (has_single_use (lhs));
125738fd1498Szrj   single_imm_use (lhs, &use, &use_stmt);
125838fd1498Szrj   if (lhs == *def)
125938fd1498Szrj     *def = op;
126038fd1498Szrj   SET_USE (use, op);
126138fd1498Szrj   if (TREE_CODE (op) != SSA_NAME)
126238fd1498Szrj     update_stmt (use_stmt);
126338fd1498Szrj   gsi = gsi_for_stmt (stmt);
126438fd1498Szrj   unlink_stmt_vdef (stmt);
126538fd1498Szrj   reassoc_remove_stmt (&gsi);
126638fd1498Szrj   release_defs (stmt);
126738fd1498Szrj }
126838fd1498Szrj 
126938fd1498Szrj /* Walks the linear chain with result *DEF searching for an operation
127038fd1498Szrj    with operand OP and code OPCODE removing that from the chain.  *DEF
127138fd1498Szrj    is updated if there is only one operand but no operation left.  */
127238fd1498Szrj 
127338fd1498Szrj static void
zero_one_operation(tree * def,enum tree_code opcode,tree op)127438fd1498Szrj zero_one_operation (tree *def, enum tree_code opcode, tree op)
127538fd1498Szrj {
127638fd1498Szrj   tree orig_def = *def;
127738fd1498Szrj   gimple *stmt = SSA_NAME_DEF_STMT (*def);
127838fd1498Szrj   /* PR72835 - Record the stmt chain that has to be updated such that
127938fd1498Szrj      we dont use the same LHS when the values computed are different.  */
128038fd1498Szrj   auto_vec<gimple *, 64> stmts_to_fix;
128138fd1498Szrj 
128238fd1498Szrj   do
128338fd1498Szrj     {
128438fd1498Szrj       tree name;
128538fd1498Szrj 
128638fd1498Szrj       if (opcode == MULT_EXPR)
128738fd1498Szrj 	{
128838fd1498Szrj 	  if (stmt_is_power_of_op (stmt, op))
128938fd1498Szrj 	    {
129038fd1498Szrj 	      if (decrement_power (stmt) == 1)
129138fd1498Szrj 		{
129238fd1498Szrj 		  if (stmts_to_fix.length () > 0)
129338fd1498Szrj 		    stmts_to_fix.pop ();
129438fd1498Szrj 		  propagate_op_to_single_use (op, stmt, def);
129538fd1498Szrj 		}
129638fd1498Szrj 	      break;
129738fd1498Szrj 	    }
129838fd1498Szrj 	  else if (gimple_assign_rhs_code (stmt) == NEGATE_EXPR)
129938fd1498Szrj 	    {
130038fd1498Szrj 	      if (gimple_assign_rhs1 (stmt) == op)
130138fd1498Szrj 		{
130238fd1498Szrj 		  tree cst = build_minus_one_cst (TREE_TYPE (op));
130338fd1498Szrj 		  if (stmts_to_fix.length () > 0)
130438fd1498Szrj 		    stmts_to_fix.pop ();
130538fd1498Szrj 		  propagate_op_to_single_use (cst, stmt, def);
130638fd1498Szrj 		  break;
130738fd1498Szrj 		}
130838fd1498Szrj 	      else if (integer_minus_onep (op)
130938fd1498Szrj 		       || real_minus_onep (op))
131038fd1498Szrj 		{
131138fd1498Szrj 		  gimple_assign_set_rhs_code
131238fd1498Szrj 		    (stmt, TREE_CODE (gimple_assign_rhs1 (stmt)));
131338fd1498Szrj 		  break;
131438fd1498Szrj 		}
131538fd1498Szrj 	    }
131638fd1498Szrj 	}
131738fd1498Szrj 
131838fd1498Szrj       name = gimple_assign_rhs1 (stmt);
131938fd1498Szrj 
132038fd1498Szrj       /* If this is the operation we look for and one of the operands
132138fd1498Szrj          is ours simply propagate the other operand into the stmts
132238fd1498Szrj 	 single use.  */
132338fd1498Szrj       if (gimple_assign_rhs_code (stmt) == opcode
132438fd1498Szrj 	  && (name == op
132538fd1498Szrj 	      || gimple_assign_rhs2 (stmt) == op))
132638fd1498Szrj 	{
132738fd1498Szrj 	  if (name == op)
132838fd1498Szrj 	    name = gimple_assign_rhs2 (stmt);
132938fd1498Szrj 	  if (stmts_to_fix.length () > 0)
133038fd1498Szrj 	    stmts_to_fix.pop ();
133138fd1498Szrj 	  propagate_op_to_single_use (name, stmt, def);
133238fd1498Szrj 	  break;
133338fd1498Szrj 	}
133438fd1498Szrj 
133538fd1498Szrj       /* We might have a multiply of two __builtin_pow* calls, and
133638fd1498Szrj 	 the operand might be hiding in the rightmost one.  Likewise
133738fd1498Szrj 	 this can happen for a negate.  */
133838fd1498Szrj       if (opcode == MULT_EXPR
133938fd1498Szrj 	  && gimple_assign_rhs_code (stmt) == opcode
134038fd1498Szrj 	  && TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME
134138fd1498Szrj 	  && has_single_use (gimple_assign_rhs2 (stmt)))
134238fd1498Szrj 	{
134338fd1498Szrj 	  gimple *stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
134438fd1498Szrj 	  if (stmt_is_power_of_op (stmt2, op))
134538fd1498Szrj 	    {
134638fd1498Szrj 	      if (decrement_power (stmt2) == 1)
134738fd1498Szrj 		propagate_op_to_single_use (op, stmt2, def);
134838fd1498Szrj 	      else
134938fd1498Szrj 		stmts_to_fix.safe_push (stmt2);
135038fd1498Szrj 	      break;
135138fd1498Szrj 	    }
135238fd1498Szrj 	  else if (is_gimple_assign (stmt2)
135338fd1498Szrj 		   && gimple_assign_rhs_code (stmt2) == NEGATE_EXPR)
135438fd1498Szrj 	    {
135538fd1498Szrj 	      if (gimple_assign_rhs1 (stmt2) == op)
135638fd1498Szrj 		{
135738fd1498Szrj 		  tree cst = build_minus_one_cst (TREE_TYPE (op));
135838fd1498Szrj 		  propagate_op_to_single_use (cst, stmt2, def);
135938fd1498Szrj 		  break;
136038fd1498Szrj 		}
136138fd1498Szrj 	      else if (integer_minus_onep (op)
136238fd1498Szrj 		       || real_minus_onep (op))
136338fd1498Szrj 		{
136438fd1498Szrj 		  stmts_to_fix.safe_push (stmt2);
136538fd1498Szrj 		  gimple_assign_set_rhs_code
136638fd1498Szrj 		    (stmt2, TREE_CODE (gimple_assign_rhs1 (stmt2)));
136738fd1498Szrj 		  break;
136838fd1498Szrj 		}
136938fd1498Szrj 	    }
137038fd1498Szrj 	}
137138fd1498Szrj 
137238fd1498Szrj       /* Continue walking the chain.  */
137338fd1498Szrj       gcc_assert (name != op
137438fd1498Szrj 		  && TREE_CODE (name) == SSA_NAME);
137538fd1498Szrj       stmt = SSA_NAME_DEF_STMT (name);
137638fd1498Szrj       stmts_to_fix.safe_push (stmt);
137738fd1498Szrj     }
137838fd1498Szrj   while (1);
137938fd1498Szrj 
138038fd1498Szrj   if (stmts_to_fix.length () > 0 || *def == orig_def)
138138fd1498Szrj     make_new_ssa_for_all_defs (def, opcode, op, stmts_to_fix);
138238fd1498Szrj }
138338fd1498Szrj 
138438fd1498Szrj /* Returns true if statement S1 dominates statement S2.  Like
138538fd1498Szrj    stmt_dominates_stmt_p, but uses stmt UIDs to optimize.  */
138638fd1498Szrj 
138738fd1498Szrj static bool
reassoc_stmt_dominates_stmt_p(gimple * s1,gimple * s2)138838fd1498Szrj reassoc_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
138938fd1498Szrj {
139038fd1498Szrj   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
139138fd1498Szrj 
139238fd1498Szrj   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
139338fd1498Szrj      SSA_NAME.  Assume it lives at the beginning of function and
139438fd1498Szrj      thus dominates everything.  */
139538fd1498Szrj   if (!bb1 || s1 == s2)
139638fd1498Szrj     return true;
139738fd1498Szrj 
139838fd1498Szrj   /* If bb2 is NULL, it doesn't dominate any stmt with a bb.  */
139938fd1498Szrj   if (!bb2)
140038fd1498Szrj     return false;
140138fd1498Szrj 
140238fd1498Szrj   if (bb1 == bb2)
140338fd1498Szrj     {
140438fd1498Szrj       /* PHIs in the same basic block are assumed to be
140538fd1498Szrj 	 executed all in parallel, if only one stmt is a PHI,
140638fd1498Szrj 	 it dominates the other stmt in the same basic block.  */
140738fd1498Szrj       if (gimple_code (s1) == GIMPLE_PHI)
140838fd1498Szrj 	return true;
140938fd1498Szrj 
141038fd1498Szrj       if (gimple_code (s2) == GIMPLE_PHI)
141138fd1498Szrj 	return false;
141238fd1498Szrj 
141338fd1498Szrj       gcc_assert (gimple_uid (s1) && gimple_uid (s2));
141438fd1498Szrj 
141538fd1498Szrj       if (gimple_uid (s1) < gimple_uid (s2))
141638fd1498Szrj 	return true;
141738fd1498Szrj 
141838fd1498Szrj       if (gimple_uid (s1) > gimple_uid (s2))
141938fd1498Szrj 	return false;
142038fd1498Szrj 
142138fd1498Szrj       gimple_stmt_iterator gsi = gsi_for_stmt (s1);
142238fd1498Szrj       unsigned int uid = gimple_uid (s1);
142338fd1498Szrj       for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi))
142438fd1498Szrj 	{
142538fd1498Szrj 	  gimple *s = gsi_stmt (gsi);
142638fd1498Szrj 	  if (gimple_uid (s) != uid)
142738fd1498Szrj 	    break;
142838fd1498Szrj 	  if (s == s2)
142938fd1498Szrj 	    return true;
143038fd1498Szrj 	}
143138fd1498Szrj 
143238fd1498Szrj       return false;
143338fd1498Szrj     }
143438fd1498Szrj 
143538fd1498Szrj   return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
143638fd1498Szrj }
143738fd1498Szrj 
143838fd1498Szrj /* Insert STMT after INSERT_POINT.  */
143938fd1498Szrj 
144038fd1498Szrj static void
insert_stmt_after(gimple * stmt,gimple * insert_point)144138fd1498Szrj insert_stmt_after (gimple *stmt, gimple *insert_point)
144238fd1498Szrj {
144338fd1498Szrj   gimple_stmt_iterator gsi;
144438fd1498Szrj   basic_block bb;
144538fd1498Szrj 
144638fd1498Szrj   if (gimple_code (insert_point) == GIMPLE_PHI)
144738fd1498Szrj     bb = gimple_bb (insert_point);
144838fd1498Szrj   else if (!stmt_ends_bb_p (insert_point))
144938fd1498Szrj     {
145038fd1498Szrj       gsi = gsi_for_stmt (insert_point);
145138fd1498Szrj       gimple_set_uid (stmt, gimple_uid (insert_point));
145238fd1498Szrj       gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
145338fd1498Szrj       return;
145438fd1498Szrj     }
145538fd1498Szrj   else
145638fd1498Szrj     /* We assume INSERT_POINT is a SSA_NAME_DEF_STMT of some SSA_NAME,
145738fd1498Szrj        thus if it must end a basic block, it should be a call that can
145838fd1498Szrj        throw, or some assignment that can throw.  If it throws, the LHS
145938fd1498Szrj        of it will not be initialized though, so only valid places using
146038fd1498Szrj        the SSA_NAME should be dominated by the fallthru edge.  */
146138fd1498Szrj     bb = find_fallthru_edge (gimple_bb (insert_point)->succs)->dest;
146238fd1498Szrj   gsi = gsi_after_labels (bb);
146338fd1498Szrj   if (gsi_end_p (gsi))
146438fd1498Szrj     {
146538fd1498Szrj       gimple_stmt_iterator gsi2 = gsi_last_bb (bb);
146638fd1498Szrj       gimple_set_uid (stmt,
146738fd1498Szrj 		      gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2)));
146838fd1498Szrj     }
146938fd1498Szrj   else
147038fd1498Szrj     gimple_set_uid (stmt, gimple_uid (gsi_stmt (gsi)));
147138fd1498Szrj   gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
147238fd1498Szrj }
147338fd1498Szrj 
147438fd1498Szrj /* Builds one statement performing OP1 OPCODE OP2 using TMPVAR for
147538fd1498Szrj    the result.  Places the statement after the definition of either
147638fd1498Szrj    OP1 or OP2.  Returns the new statement.  */
147738fd1498Szrj 
147838fd1498Szrj static gimple *
build_and_add_sum(tree type,tree op1,tree op2,enum tree_code opcode)147938fd1498Szrj build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
148038fd1498Szrj {
148138fd1498Szrj   gimple *op1def = NULL, *op2def = NULL;
148238fd1498Szrj   gimple_stmt_iterator gsi;
148338fd1498Szrj   tree op;
148438fd1498Szrj   gassign *sum;
148538fd1498Szrj 
148638fd1498Szrj   /* Create the addition statement.  */
148738fd1498Szrj   op = make_ssa_name (type);
148838fd1498Szrj   sum = gimple_build_assign (op, opcode, op1, op2);
148938fd1498Szrj 
149038fd1498Szrj   /* Find an insertion place and insert.  */
149138fd1498Szrj   if (TREE_CODE (op1) == SSA_NAME)
149238fd1498Szrj     op1def = SSA_NAME_DEF_STMT (op1);
149338fd1498Szrj   if (TREE_CODE (op2) == SSA_NAME)
149438fd1498Szrj     op2def = SSA_NAME_DEF_STMT (op2);
149538fd1498Szrj   if ((!op1def || gimple_nop_p (op1def))
149638fd1498Szrj       && (!op2def || gimple_nop_p (op2def)))
149738fd1498Szrj     {
149838fd1498Szrj       gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
149938fd1498Szrj       if (gsi_end_p (gsi))
150038fd1498Szrj 	{
150138fd1498Szrj 	  gimple_stmt_iterator gsi2
150238fd1498Szrj 	    = gsi_last_bb (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
150338fd1498Szrj 	  gimple_set_uid (sum,
150438fd1498Szrj 			  gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2)));
150538fd1498Szrj 	}
150638fd1498Szrj       else
150738fd1498Szrj 	gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
150838fd1498Szrj       gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
150938fd1498Szrj     }
151038fd1498Szrj   else
151138fd1498Szrj     {
151238fd1498Szrj       gimple *insert_point;
151338fd1498Szrj       if ((!op1def || gimple_nop_p (op1def))
151438fd1498Szrj 	   || (op2def && !gimple_nop_p (op2def)
151538fd1498Szrj 	       && reassoc_stmt_dominates_stmt_p (op1def, op2def)))
151638fd1498Szrj 	insert_point = op2def;
151738fd1498Szrj       else
151838fd1498Szrj 	insert_point = op1def;
151938fd1498Szrj       insert_stmt_after (sum, insert_point);
152038fd1498Szrj     }
152138fd1498Szrj   update_stmt (sum);
152238fd1498Szrj 
152338fd1498Szrj   return sum;
152438fd1498Szrj }
152538fd1498Szrj 
152638fd1498Szrj /* Perform un-distribution of divisions and multiplications.
152738fd1498Szrj    A * X + B * X is transformed into (A + B) * X and A / X + B / X
152838fd1498Szrj    to (A + B) / X for real X.
152938fd1498Szrj 
153038fd1498Szrj    The algorithm is organized as follows.
153138fd1498Szrj 
153238fd1498Szrj     - First we walk the addition chain *OPS looking for summands that
153338fd1498Szrj       are defined by a multiplication or a real division.  This results
153438fd1498Szrj       in the candidates bitmap with relevant indices into *OPS.
153538fd1498Szrj 
153638fd1498Szrj     - Second we build the chains of multiplications or divisions for
153738fd1498Szrj       these candidates, counting the number of occurrences of (operand, code)
153838fd1498Szrj       pairs in all of the candidates chains.
153938fd1498Szrj 
154038fd1498Szrj     - Third we sort the (operand, code) pairs by number of occurrence and
154138fd1498Szrj       process them starting with the pair with the most uses.
154238fd1498Szrj 
154338fd1498Szrj       * For each such pair we walk the candidates again to build a
154438fd1498Szrj         second candidate bitmap noting all multiplication/division chains
154538fd1498Szrj 	that have at least one occurrence of (operand, code).
154638fd1498Szrj 
154738fd1498Szrj       * We build an alternate addition chain only covering these
154838fd1498Szrj         candidates with one (operand, code) operation removed from their
154938fd1498Szrj 	multiplication/division chain.
155038fd1498Szrj 
155138fd1498Szrj       * The first candidate gets replaced by the alternate addition chain
155238fd1498Szrj         multiplied/divided by the operand.
155338fd1498Szrj 
155438fd1498Szrj       * All candidate chains get disabled for further processing and
155538fd1498Szrj         processing of (operand, code) pairs continues.
155638fd1498Szrj 
155738fd1498Szrj   The alternate addition chains built are re-processed by the main
155838fd1498Szrj   reassociation algorithm which allows optimizing a * x * y + b * y * x
155938fd1498Szrj   to (a + b ) * x * y in one invocation of the reassociation pass.  */
156038fd1498Szrj 
156138fd1498Szrj static bool
undistribute_ops_list(enum tree_code opcode,vec<operand_entry * > * ops,struct loop * loop)156238fd1498Szrj undistribute_ops_list (enum tree_code opcode,
156338fd1498Szrj 		       vec<operand_entry *> *ops, struct loop *loop)
156438fd1498Szrj {
156538fd1498Szrj   unsigned int length = ops->length ();
156638fd1498Szrj   operand_entry *oe1;
156738fd1498Szrj   unsigned i, j;
156838fd1498Szrj   unsigned nr_candidates, nr_candidates2;
156938fd1498Szrj   sbitmap_iterator sbi0;
157038fd1498Szrj   vec<operand_entry *> *subops;
157138fd1498Szrj   bool changed = false;
157238fd1498Szrj   unsigned int next_oecount_id = 0;
157338fd1498Szrj 
157438fd1498Szrj   if (length <= 1
157538fd1498Szrj       || opcode != PLUS_EXPR)
157638fd1498Szrj     return false;
157738fd1498Szrj 
157838fd1498Szrj   /* Build a list of candidates to process.  */
157938fd1498Szrj   auto_sbitmap candidates (length);
158038fd1498Szrj   bitmap_clear (candidates);
158138fd1498Szrj   nr_candidates = 0;
158238fd1498Szrj   FOR_EACH_VEC_ELT (*ops, i, oe1)
158338fd1498Szrj     {
158438fd1498Szrj       enum tree_code dcode;
158538fd1498Szrj       gimple *oe1def;
158638fd1498Szrj 
158738fd1498Szrj       if (TREE_CODE (oe1->op) != SSA_NAME)
158838fd1498Szrj 	continue;
158938fd1498Szrj       oe1def = SSA_NAME_DEF_STMT (oe1->op);
159038fd1498Szrj       if (!is_gimple_assign (oe1def))
159138fd1498Szrj 	continue;
159238fd1498Szrj       dcode = gimple_assign_rhs_code (oe1def);
159338fd1498Szrj       if ((dcode != MULT_EXPR
159438fd1498Szrj 	   && dcode != RDIV_EXPR)
159538fd1498Szrj 	  || !is_reassociable_op (oe1def, dcode, loop))
159638fd1498Szrj 	continue;
159738fd1498Szrj 
159838fd1498Szrj       bitmap_set_bit (candidates, i);
159938fd1498Szrj       nr_candidates++;
160038fd1498Szrj     }
160138fd1498Szrj 
160238fd1498Szrj   if (nr_candidates < 2)
160338fd1498Szrj     return false;
160438fd1498Szrj 
160538fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
160638fd1498Szrj     {
160738fd1498Szrj       fprintf (dump_file, "searching for un-distribute opportunities ");
160838fd1498Szrj       print_generic_expr (dump_file,
160938fd1498Szrj 	(*ops)[bitmap_first_set_bit (candidates)]->op, 0);
161038fd1498Szrj       fprintf (dump_file, " %d\n", nr_candidates);
161138fd1498Szrj     }
161238fd1498Szrj 
161338fd1498Szrj   /* Build linearized sub-operand lists and the counting table.  */
161438fd1498Szrj   cvec.create (0);
161538fd1498Szrj 
161638fd1498Szrj   hash_table<oecount_hasher> ctable (15);
161738fd1498Szrj 
161838fd1498Szrj   /* ??? Macro arguments cannot have multi-argument template types in
161938fd1498Szrj      them.  This typedef is needed to workaround that limitation.  */
162038fd1498Szrj   typedef vec<operand_entry *> vec_operand_entry_t_heap;
162138fd1498Szrj   subops = XCNEWVEC (vec_operand_entry_t_heap, ops->length ());
162238fd1498Szrj   EXECUTE_IF_SET_IN_BITMAP (candidates, 0, i, sbi0)
162338fd1498Szrj     {
162438fd1498Szrj       gimple *oedef;
162538fd1498Szrj       enum tree_code oecode;
162638fd1498Szrj       unsigned j;
162738fd1498Szrj 
162838fd1498Szrj       oedef = SSA_NAME_DEF_STMT ((*ops)[i]->op);
162938fd1498Szrj       oecode = gimple_assign_rhs_code (oedef);
163038fd1498Szrj       linearize_expr_tree (&subops[i], oedef,
163138fd1498Szrj 			   associative_tree_code (oecode), false);
163238fd1498Szrj 
163338fd1498Szrj       FOR_EACH_VEC_ELT (subops[i], j, oe1)
163438fd1498Szrj 	{
163538fd1498Szrj 	  oecount c;
163638fd1498Szrj 	  int *slot;
163738fd1498Szrj 	  int idx;
163838fd1498Szrj 	  c.oecode = oecode;
163938fd1498Szrj 	  c.cnt = 1;
164038fd1498Szrj 	  c.id = next_oecount_id++;
164138fd1498Szrj 	  c.op = oe1->op;
164238fd1498Szrj 	  cvec.safe_push (c);
164338fd1498Szrj 	  idx = cvec.length () + 41;
164438fd1498Szrj 	  slot = ctable.find_slot (idx, INSERT);
164538fd1498Szrj 	  if (!*slot)
164638fd1498Szrj 	    {
164738fd1498Szrj 	      *slot = idx;
164838fd1498Szrj 	    }
164938fd1498Szrj 	  else
165038fd1498Szrj 	    {
165138fd1498Szrj 	      cvec.pop ();
165238fd1498Szrj 	      cvec[*slot - 42].cnt++;
165338fd1498Szrj 	    }
165438fd1498Szrj 	}
165538fd1498Szrj     }
165638fd1498Szrj 
165738fd1498Szrj   /* Sort the counting table.  */
165838fd1498Szrj   cvec.qsort (oecount_cmp);
165938fd1498Szrj 
166038fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
166138fd1498Szrj     {
166238fd1498Szrj       oecount *c;
166338fd1498Szrj       fprintf (dump_file, "Candidates:\n");
166438fd1498Szrj       FOR_EACH_VEC_ELT (cvec, j, c)
166538fd1498Szrj 	{
166638fd1498Szrj 	  fprintf (dump_file, "  %u %s: ", c->cnt,
166738fd1498Szrj 		   c->oecode == MULT_EXPR
166838fd1498Szrj 		   ? "*" : c->oecode == RDIV_EXPR ? "/" : "?");
166938fd1498Szrj 	  print_generic_expr (dump_file, c->op);
167038fd1498Szrj 	  fprintf (dump_file, "\n");
167138fd1498Szrj 	}
167238fd1498Szrj     }
167338fd1498Szrj 
167438fd1498Szrj   /* Process the (operand, code) pairs in order of most occurrence.  */
167538fd1498Szrj   auto_sbitmap candidates2 (length);
167638fd1498Szrj   while (!cvec.is_empty ())
167738fd1498Szrj     {
167838fd1498Szrj       oecount *c = &cvec.last ();
167938fd1498Szrj       if (c->cnt < 2)
168038fd1498Szrj 	break;
168138fd1498Szrj 
168238fd1498Szrj       /* Now collect the operands in the outer chain that contain
168338fd1498Szrj          the common operand in their inner chain.  */
168438fd1498Szrj       bitmap_clear (candidates2);
168538fd1498Szrj       nr_candidates2 = 0;
168638fd1498Szrj       EXECUTE_IF_SET_IN_BITMAP (candidates, 0, i, sbi0)
168738fd1498Szrj 	{
168838fd1498Szrj 	  gimple *oedef;
168938fd1498Szrj 	  enum tree_code oecode;
169038fd1498Szrj 	  unsigned j;
169138fd1498Szrj 	  tree op = (*ops)[i]->op;
169238fd1498Szrj 
169338fd1498Szrj 	  /* If we undistributed in this chain already this may be
169438fd1498Szrj 	     a constant.  */
169538fd1498Szrj 	  if (TREE_CODE (op) != SSA_NAME)
169638fd1498Szrj 	    continue;
169738fd1498Szrj 
169838fd1498Szrj 	  oedef = SSA_NAME_DEF_STMT (op);
169938fd1498Szrj 	  oecode = gimple_assign_rhs_code (oedef);
170038fd1498Szrj 	  if (oecode != c->oecode)
170138fd1498Szrj 	    continue;
170238fd1498Szrj 
170338fd1498Szrj 	  FOR_EACH_VEC_ELT (subops[i], j, oe1)
170438fd1498Szrj 	    {
170538fd1498Szrj 	      if (oe1->op == c->op)
170638fd1498Szrj 		{
170738fd1498Szrj 		  bitmap_set_bit (candidates2, i);
170838fd1498Szrj 		  ++nr_candidates2;
170938fd1498Szrj 		  break;
171038fd1498Szrj 		}
171138fd1498Szrj 	    }
171238fd1498Szrj 	}
171338fd1498Szrj 
171438fd1498Szrj       if (nr_candidates2 >= 2)
171538fd1498Szrj 	{
171638fd1498Szrj 	  operand_entry *oe1, *oe2;
171738fd1498Szrj 	  gimple *prod;
171838fd1498Szrj 	  int first = bitmap_first_set_bit (candidates2);
171938fd1498Szrj 
172038fd1498Szrj 	  /* Build the new addition chain.  */
172138fd1498Szrj 	  oe1 = (*ops)[first];
172238fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
172338fd1498Szrj 	    {
172438fd1498Szrj 	      fprintf (dump_file, "Building (");
172538fd1498Szrj 	      print_generic_expr (dump_file, oe1->op);
172638fd1498Szrj 	    }
172738fd1498Szrj 	  zero_one_operation (&oe1->op, c->oecode, c->op);
172838fd1498Szrj 	  EXECUTE_IF_SET_IN_BITMAP (candidates2, first+1, i, sbi0)
172938fd1498Szrj 	    {
173038fd1498Szrj 	      gimple *sum;
173138fd1498Szrj 	      oe2 = (*ops)[i];
173238fd1498Szrj 	      if (dump_file && (dump_flags & TDF_DETAILS))
173338fd1498Szrj 		{
173438fd1498Szrj 		  fprintf (dump_file, " + ");
173538fd1498Szrj 		  print_generic_expr (dump_file, oe2->op);
173638fd1498Szrj 		}
173738fd1498Szrj 	      zero_one_operation (&oe2->op, c->oecode, c->op);
173838fd1498Szrj 	      sum = build_and_add_sum (TREE_TYPE (oe1->op),
173938fd1498Szrj 				       oe1->op, oe2->op, opcode);
174038fd1498Szrj 	      oe2->op = build_zero_cst (TREE_TYPE (oe2->op));
174138fd1498Szrj 	      oe2->rank = 0;
174238fd1498Szrj 	      oe1->op = gimple_get_lhs (sum);
174338fd1498Szrj 	    }
174438fd1498Szrj 
174538fd1498Szrj 	  /* Apply the multiplication/division.  */
174638fd1498Szrj 	  prod = build_and_add_sum (TREE_TYPE (oe1->op),
174738fd1498Szrj 				    oe1->op, c->op, c->oecode);
174838fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
174938fd1498Szrj 	    {
175038fd1498Szrj 	      fprintf (dump_file, ") %s ", c->oecode == MULT_EXPR ? "*" : "/");
175138fd1498Szrj 	      print_generic_expr (dump_file, c->op);
175238fd1498Szrj 	      fprintf (dump_file, "\n");
175338fd1498Szrj 	    }
175438fd1498Szrj 
175538fd1498Szrj 	  /* Record it in the addition chain and disable further
175638fd1498Szrj 	     undistribution with this op.  */
175738fd1498Szrj 	  oe1->op = gimple_assign_lhs (prod);
175838fd1498Szrj 	  oe1->rank = get_rank (oe1->op);
175938fd1498Szrj 	  subops[first].release ();
176038fd1498Szrj 
176138fd1498Szrj 	  changed = true;
176238fd1498Szrj 	}
176338fd1498Szrj 
176438fd1498Szrj       cvec.pop ();
176538fd1498Szrj     }
176638fd1498Szrj 
176738fd1498Szrj   for (i = 0; i < ops->length (); ++i)
176838fd1498Szrj     subops[i].release ();
176938fd1498Szrj   free (subops);
177038fd1498Szrj   cvec.release ();
177138fd1498Szrj 
177238fd1498Szrj   return changed;
177338fd1498Szrj }
177438fd1498Szrj 
177538fd1498Szrj /* If OPCODE is BIT_IOR_EXPR or BIT_AND_EXPR and CURR is a comparison
177638fd1498Szrj    expression, examine the other OPS to see if any of them are comparisons
177738fd1498Szrj    of the same values, which we may be able to combine or eliminate.
177838fd1498Szrj    For example, we can rewrite (a < b) | (a == b) as (a <= b).  */
177938fd1498Szrj 
178038fd1498Szrj static bool
eliminate_redundant_comparison(enum tree_code opcode,vec<operand_entry * > * ops,unsigned int currindex,operand_entry * curr)178138fd1498Szrj eliminate_redundant_comparison (enum tree_code opcode,
178238fd1498Szrj 				vec<operand_entry *> *ops,
178338fd1498Szrj 				unsigned int currindex,
178438fd1498Szrj 				operand_entry *curr)
178538fd1498Szrj {
178638fd1498Szrj   tree op1, op2;
178738fd1498Szrj   enum tree_code lcode, rcode;
178838fd1498Szrj   gimple *def1, *def2;
178938fd1498Szrj   int i;
179038fd1498Szrj   operand_entry *oe;
179138fd1498Szrj 
179238fd1498Szrj   if (opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
179338fd1498Szrj     return false;
179438fd1498Szrj 
179538fd1498Szrj   /* Check that CURR is a comparison.  */
179638fd1498Szrj   if (TREE_CODE (curr->op) != SSA_NAME)
179738fd1498Szrj     return false;
179838fd1498Szrj   def1 = SSA_NAME_DEF_STMT (curr->op);
179938fd1498Szrj   if (!is_gimple_assign (def1))
180038fd1498Szrj     return false;
180138fd1498Szrj   lcode = gimple_assign_rhs_code (def1);
180238fd1498Szrj   if (TREE_CODE_CLASS (lcode) != tcc_comparison)
180338fd1498Szrj     return false;
180438fd1498Szrj   op1 = gimple_assign_rhs1 (def1);
180538fd1498Szrj   op2 = gimple_assign_rhs2 (def1);
180638fd1498Szrj 
180738fd1498Szrj   /* Now look for a similar comparison in the remaining OPS.  */
180838fd1498Szrj   for (i = currindex + 1; ops->iterate (i, &oe); i++)
180938fd1498Szrj     {
181038fd1498Szrj       tree t;
181138fd1498Szrj 
181238fd1498Szrj       if (TREE_CODE (oe->op) != SSA_NAME)
181338fd1498Szrj 	continue;
181438fd1498Szrj       def2 = SSA_NAME_DEF_STMT (oe->op);
181538fd1498Szrj       if (!is_gimple_assign (def2))
181638fd1498Szrj 	continue;
181738fd1498Szrj       rcode = gimple_assign_rhs_code (def2);
181838fd1498Szrj       if (TREE_CODE_CLASS (rcode) != tcc_comparison)
181938fd1498Szrj 	continue;
182038fd1498Szrj 
182138fd1498Szrj       /* If we got here, we have a match.  See if we can combine the
182238fd1498Szrj 	 two comparisons.  */
182338fd1498Szrj       if (opcode == BIT_IOR_EXPR)
182438fd1498Szrj 	t = maybe_fold_or_comparisons (lcode, op1, op2,
182538fd1498Szrj 				       rcode, gimple_assign_rhs1 (def2),
182638fd1498Szrj 				       gimple_assign_rhs2 (def2));
182738fd1498Szrj       else
182838fd1498Szrj 	t = maybe_fold_and_comparisons (lcode, op1, op2,
182938fd1498Szrj 					rcode, gimple_assign_rhs1 (def2),
183038fd1498Szrj 					gimple_assign_rhs2 (def2));
183138fd1498Szrj       if (!t)
183238fd1498Szrj 	continue;
183338fd1498Szrj 
183438fd1498Szrj       /* maybe_fold_and_comparisons and maybe_fold_or_comparisons
183538fd1498Szrj 	 always give us a boolean_type_node value back.  If the original
183638fd1498Szrj 	 BIT_AND_EXPR or BIT_IOR_EXPR was of a wider integer type,
183738fd1498Szrj 	 we need to convert.  */
183838fd1498Szrj       if (!useless_type_conversion_p (TREE_TYPE (curr->op), TREE_TYPE (t)))
183938fd1498Szrj 	t = fold_convert (TREE_TYPE (curr->op), t);
184038fd1498Szrj 
184138fd1498Szrj       if (TREE_CODE (t) != INTEGER_CST
184238fd1498Szrj 	  && !operand_equal_p (t, curr->op, 0))
184338fd1498Szrj 	{
184438fd1498Szrj 	  enum tree_code subcode;
184538fd1498Szrj 	  tree newop1, newop2;
184638fd1498Szrj 	  if (!COMPARISON_CLASS_P (t))
184738fd1498Szrj 	    continue;
184838fd1498Szrj 	  extract_ops_from_tree (t, &subcode, &newop1, &newop2);
184938fd1498Szrj 	  STRIP_USELESS_TYPE_CONVERSION (newop1);
185038fd1498Szrj 	  STRIP_USELESS_TYPE_CONVERSION (newop2);
185138fd1498Szrj 	  if (!is_gimple_val (newop1) || !is_gimple_val (newop2))
185238fd1498Szrj 	    continue;
185338fd1498Szrj 	}
185438fd1498Szrj 
185538fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
185638fd1498Szrj 	{
185738fd1498Szrj 	  fprintf (dump_file, "Equivalence: ");
185838fd1498Szrj 	  print_generic_expr (dump_file, curr->op);
185938fd1498Szrj 	  fprintf (dump_file, " %s ", op_symbol_code (opcode));
186038fd1498Szrj 	  print_generic_expr (dump_file, oe->op);
186138fd1498Szrj 	  fprintf (dump_file, " -> ");
186238fd1498Szrj 	  print_generic_expr (dump_file, t);
186338fd1498Szrj 	  fprintf (dump_file, "\n");
186438fd1498Szrj 	}
186538fd1498Szrj 
186638fd1498Szrj       /* Now we can delete oe, as it has been subsumed by the new combined
186738fd1498Szrj          expression t.  */
186838fd1498Szrj       ops->ordered_remove (i);
186938fd1498Szrj       reassociate_stats.ops_eliminated ++;
187038fd1498Szrj 
187138fd1498Szrj       /* If t is the same as curr->op, we're done.  Otherwise we must
187238fd1498Szrj 	 replace curr->op with t.  Special case is if we got a constant
187338fd1498Szrj 	 back, in which case we add it to the end instead of in place of
187438fd1498Szrj 	 the current entry.  */
187538fd1498Szrj       if (TREE_CODE (t) == INTEGER_CST)
187638fd1498Szrj 	{
187738fd1498Szrj 	  ops->ordered_remove (currindex);
187838fd1498Szrj 	  add_to_ops_vec (ops, t);
187938fd1498Szrj 	}
188038fd1498Szrj       else if (!operand_equal_p (t, curr->op, 0))
188138fd1498Szrj 	{
188238fd1498Szrj 	  gimple *sum;
188338fd1498Szrj 	  enum tree_code subcode;
188438fd1498Szrj 	  tree newop1;
188538fd1498Szrj 	  tree newop2;
188638fd1498Szrj 	  gcc_assert (COMPARISON_CLASS_P (t));
188738fd1498Szrj 	  extract_ops_from_tree (t, &subcode, &newop1, &newop2);
188838fd1498Szrj 	  STRIP_USELESS_TYPE_CONVERSION (newop1);
188938fd1498Szrj 	  STRIP_USELESS_TYPE_CONVERSION (newop2);
189038fd1498Szrj 	  gcc_checking_assert (is_gimple_val (newop1)
189138fd1498Szrj 			       && is_gimple_val (newop2));
189238fd1498Szrj 	  sum = build_and_add_sum (TREE_TYPE (t), newop1, newop2, subcode);
189338fd1498Szrj 	  curr->op = gimple_get_lhs (sum);
189438fd1498Szrj 	}
189538fd1498Szrj       return true;
189638fd1498Szrj     }
189738fd1498Szrj 
189838fd1498Szrj   return false;
189938fd1498Szrj }
190038fd1498Szrj 
190138fd1498Szrj 
190238fd1498Szrj /* Transform repeated addition of same values into multiply with
190338fd1498Szrj    constant.  */
190438fd1498Szrj static bool
transform_add_to_multiply(vec<operand_entry * > * ops)190538fd1498Szrj transform_add_to_multiply (vec<operand_entry *> *ops)
190638fd1498Szrj {
190738fd1498Szrj   operand_entry *oe;
190838fd1498Szrj   tree op = NULL_TREE;
190938fd1498Szrj   int j;
191038fd1498Szrj   int i, start = -1, end = 0, count = 0;
191138fd1498Szrj   auto_vec<std::pair <int, int> > indxs;
191238fd1498Szrj   bool changed = false;
191338fd1498Szrj 
191438fd1498Szrj   if (!INTEGRAL_TYPE_P (TREE_TYPE ((*ops)[0]->op))
191538fd1498Szrj       && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE ((*ops)[0]->op))
191638fd1498Szrj 	  || !flag_unsafe_math_optimizations))
191738fd1498Szrj     return false;
191838fd1498Szrj 
191938fd1498Szrj   /* Look for repeated operands.  */
192038fd1498Szrj   FOR_EACH_VEC_ELT (*ops, i, oe)
192138fd1498Szrj     {
192238fd1498Szrj       if (start == -1)
192338fd1498Szrj 	{
192438fd1498Szrj 	  count = 1;
192538fd1498Szrj 	  op = oe->op;
192638fd1498Szrj 	  start = i;
192738fd1498Szrj 	}
192838fd1498Szrj       else if (operand_equal_p (oe->op, op, 0))
192938fd1498Szrj 	{
193038fd1498Szrj 	  count++;
193138fd1498Szrj 	  end = i;
193238fd1498Szrj 	}
193338fd1498Szrj       else
193438fd1498Szrj 	{
193538fd1498Szrj 	  if (count > 1)
193638fd1498Szrj 	    indxs.safe_push (std::make_pair (start, end));
193738fd1498Szrj 	  count = 1;
193838fd1498Szrj 	  op = oe->op;
193938fd1498Szrj 	  start = i;
194038fd1498Szrj 	}
194138fd1498Szrj     }
194238fd1498Szrj 
194338fd1498Szrj   if (count > 1)
194438fd1498Szrj     indxs.safe_push (std::make_pair (start, end));
194538fd1498Szrj 
194638fd1498Szrj   for (j = indxs.length () - 1; j >= 0; --j)
194738fd1498Szrj     {
194838fd1498Szrj       /* Convert repeated operand addition to multiplication.  */
194938fd1498Szrj       start = indxs[j].first;
195038fd1498Szrj       end = indxs[j].second;
195138fd1498Szrj       op = (*ops)[start]->op;
195238fd1498Szrj       count = end - start + 1;
195338fd1498Szrj       for (i = end; i >= start; --i)
195438fd1498Szrj 	ops->unordered_remove (i);
195538fd1498Szrj       tree tmp = make_ssa_name (TREE_TYPE (op));
195638fd1498Szrj       tree cst = build_int_cst (integer_type_node, count);
195738fd1498Szrj       gassign *mul_stmt
195838fd1498Szrj 	= gimple_build_assign (tmp, MULT_EXPR,
195938fd1498Szrj 			       op, fold_convert (TREE_TYPE (op), cst));
196038fd1498Szrj       gimple_set_visited (mul_stmt, true);
196138fd1498Szrj       add_to_ops_vec (ops, tmp, mul_stmt);
196238fd1498Szrj       changed = true;
196338fd1498Szrj     }
196438fd1498Szrj 
196538fd1498Szrj   return changed;
196638fd1498Szrj }
196738fd1498Szrj 
196838fd1498Szrj 
196938fd1498Szrj /* Perform various identities and other optimizations on the list of
197038fd1498Szrj    operand entries, stored in OPS.  The tree code for the binary
197138fd1498Szrj    operation between all the operands is OPCODE.  */
197238fd1498Szrj 
197338fd1498Szrj static void
optimize_ops_list(enum tree_code opcode,vec<operand_entry * > * ops)197438fd1498Szrj optimize_ops_list (enum tree_code opcode,
197538fd1498Szrj 		   vec<operand_entry *> *ops)
197638fd1498Szrj {
197738fd1498Szrj   unsigned int length = ops->length ();
197838fd1498Szrj   unsigned int i;
197938fd1498Szrj   operand_entry *oe;
198038fd1498Szrj   operand_entry *oelast = NULL;
198138fd1498Szrj   bool iterate = false;
198238fd1498Szrj 
198338fd1498Szrj   if (length == 1)
198438fd1498Szrj     return;
198538fd1498Szrj 
198638fd1498Szrj   oelast = ops->last ();
198738fd1498Szrj 
198838fd1498Szrj   /* If the last two are constants, pop the constants off, merge them
198938fd1498Szrj      and try the next two.  */
199038fd1498Szrj   if (oelast->rank == 0 && is_gimple_min_invariant (oelast->op))
199138fd1498Szrj     {
199238fd1498Szrj       operand_entry *oelm1 = (*ops)[length - 2];
199338fd1498Szrj 
199438fd1498Szrj       if (oelm1->rank == 0
199538fd1498Szrj 	  && is_gimple_min_invariant (oelm1->op)
199638fd1498Szrj 	  && useless_type_conversion_p (TREE_TYPE (oelm1->op),
199738fd1498Szrj 				       TREE_TYPE (oelast->op)))
199838fd1498Szrj 	{
199938fd1498Szrj 	  tree folded = fold_binary (opcode, TREE_TYPE (oelm1->op),
200038fd1498Szrj 				     oelm1->op, oelast->op);
200138fd1498Szrj 
200238fd1498Szrj 	  if (folded && is_gimple_min_invariant (folded))
200338fd1498Szrj 	    {
200438fd1498Szrj 	      if (dump_file && (dump_flags & TDF_DETAILS))
200538fd1498Szrj 		fprintf (dump_file, "Merging constants\n");
200638fd1498Szrj 
200738fd1498Szrj 	      ops->pop ();
200838fd1498Szrj 	      ops->pop ();
200938fd1498Szrj 
201038fd1498Szrj 	      add_to_ops_vec (ops, folded);
201138fd1498Szrj 	      reassociate_stats.constants_eliminated++;
201238fd1498Szrj 
201338fd1498Szrj 	      optimize_ops_list (opcode, ops);
201438fd1498Szrj 	      return;
201538fd1498Szrj 	    }
201638fd1498Szrj 	}
201738fd1498Szrj     }
201838fd1498Szrj 
201938fd1498Szrj   eliminate_using_constants (opcode, ops);
202038fd1498Szrj   oelast = NULL;
202138fd1498Szrj 
202238fd1498Szrj   for (i = 0; ops->iterate (i, &oe);)
202338fd1498Szrj     {
202438fd1498Szrj       bool done = false;
202538fd1498Szrj 
202638fd1498Szrj       if (eliminate_not_pairs (opcode, ops, i, oe))
202738fd1498Szrj 	return;
202838fd1498Szrj       if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast)
202938fd1498Szrj 	  || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe))
203038fd1498Szrj 	  || (!done && eliminate_redundant_comparison (opcode, ops, i, oe)))
203138fd1498Szrj 	{
203238fd1498Szrj 	  if (done)
203338fd1498Szrj 	    return;
203438fd1498Szrj 	  iterate = true;
203538fd1498Szrj 	  oelast = NULL;
203638fd1498Szrj 	  continue;
203738fd1498Szrj 	}
203838fd1498Szrj       oelast = oe;
203938fd1498Szrj       i++;
204038fd1498Szrj     }
204138fd1498Szrj 
204238fd1498Szrj   length = ops->length ();
204338fd1498Szrj   oelast = ops->last ();
204438fd1498Szrj 
204538fd1498Szrj   if (iterate)
204638fd1498Szrj     optimize_ops_list (opcode, ops);
204738fd1498Szrj }
204838fd1498Szrj 
204938fd1498Szrj /* The following functions are subroutines to optimize_range_tests and allow
205038fd1498Szrj    it to try to change a logical combination of comparisons into a range
205138fd1498Szrj    test.
205238fd1498Szrj 
205338fd1498Szrj    For example, both
205438fd1498Szrj 	X == 2 || X == 5 || X == 3 || X == 4
205538fd1498Szrj    and
205638fd1498Szrj 	X >= 2 && X <= 5
205738fd1498Szrj    are converted to
205838fd1498Szrj 	(unsigned) (X - 2) <= 3
205938fd1498Szrj 
206038fd1498Szrj    For more information see comments above fold_test_range in fold-const.c,
206138fd1498Szrj    this implementation is for GIMPLE.  */
206238fd1498Szrj 
206338fd1498Szrj struct range_entry
206438fd1498Szrj {
206538fd1498Szrj   tree exp;
206638fd1498Szrj   tree low;
206738fd1498Szrj   tree high;
206838fd1498Szrj   bool in_p;
206938fd1498Szrj   bool strict_overflow_p;
207038fd1498Szrj   unsigned int idx, next;
207138fd1498Szrj };
207238fd1498Szrj 
207338fd1498Szrj /* This is similar to make_range in fold-const.c, but on top of
207438fd1498Szrj    GIMPLE instead of trees.  If EXP is non-NULL, it should be
207538fd1498Szrj    an SSA_NAME and STMT argument is ignored, otherwise STMT
207638fd1498Szrj    argument should be a GIMPLE_COND.  */
207738fd1498Szrj 
207838fd1498Szrj static void
init_range_entry(struct range_entry * r,tree exp,gimple * stmt)207938fd1498Szrj init_range_entry (struct range_entry *r, tree exp, gimple *stmt)
208038fd1498Szrj {
208138fd1498Szrj   int in_p;
208238fd1498Szrj   tree low, high;
208338fd1498Szrj   bool is_bool, strict_overflow_p;
208438fd1498Szrj 
208538fd1498Szrj   r->exp = NULL_TREE;
208638fd1498Szrj   r->in_p = false;
208738fd1498Szrj   r->strict_overflow_p = false;
208838fd1498Szrj   r->low = NULL_TREE;
208938fd1498Szrj   r->high = NULL_TREE;
209038fd1498Szrj   if (exp != NULL_TREE
209138fd1498Szrj       && (TREE_CODE (exp) != SSA_NAME || !INTEGRAL_TYPE_P (TREE_TYPE (exp))))
209238fd1498Szrj     return;
209338fd1498Szrj 
209438fd1498Szrj   /* Start with simply saying "EXP != 0" and then look at the code of EXP
209538fd1498Szrj      and see if we can refine the range.  Some of the cases below may not
209638fd1498Szrj      happen, but it doesn't seem worth worrying about this.  We "continue"
209738fd1498Szrj      the outer loop when we've changed something; otherwise we "break"
209838fd1498Szrj      the switch, which will "break" the while.  */
209938fd1498Szrj   low = exp ? build_int_cst (TREE_TYPE (exp), 0) : boolean_false_node;
210038fd1498Szrj   high = low;
210138fd1498Szrj   in_p = 0;
210238fd1498Szrj   strict_overflow_p = false;
210338fd1498Szrj   is_bool = false;
210438fd1498Szrj   if (exp == NULL_TREE)
210538fd1498Szrj     is_bool = true;
210638fd1498Szrj   else if (TYPE_PRECISION (TREE_TYPE (exp)) == 1)
210738fd1498Szrj     {
210838fd1498Szrj       if (TYPE_UNSIGNED (TREE_TYPE (exp)))
210938fd1498Szrj 	is_bool = true;
211038fd1498Szrj       else
211138fd1498Szrj 	return;
211238fd1498Szrj     }
211338fd1498Szrj   else if (TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE)
211438fd1498Szrj     is_bool = true;
211538fd1498Szrj 
211638fd1498Szrj   while (1)
211738fd1498Szrj     {
211838fd1498Szrj       enum tree_code code;
211938fd1498Szrj       tree arg0, arg1, exp_type;
212038fd1498Szrj       tree nexp;
212138fd1498Szrj       location_t loc;
212238fd1498Szrj 
212338fd1498Szrj       if (exp != NULL_TREE)
212438fd1498Szrj 	{
212538fd1498Szrj 	  if (TREE_CODE (exp) != SSA_NAME
212638fd1498Szrj 	      || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
212738fd1498Szrj 	    break;
212838fd1498Szrj 
212938fd1498Szrj 	  stmt = SSA_NAME_DEF_STMT (exp);
213038fd1498Szrj 	  if (!is_gimple_assign (stmt))
213138fd1498Szrj 	    break;
213238fd1498Szrj 
213338fd1498Szrj 	  code = gimple_assign_rhs_code (stmt);
213438fd1498Szrj 	  arg0 = gimple_assign_rhs1 (stmt);
213538fd1498Szrj 	  arg1 = gimple_assign_rhs2 (stmt);
213638fd1498Szrj 	  exp_type = TREE_TYPE (exp);
213738fd1498Szrj 	}
213838fd1498Szrj       else
213938fd1498Szrj 	{
214038fd1498Szrj 	  code = gimple_cond_code (stmt);
214138fd1498Szrj 	  arg0 = gimple_cond_lhs (stmt);
214238fd1498Szrj 	  arg1 = gimple_cond_rhs (stmt);
214338fd1498Szrj 	  exp_type = boolean_type_node;
214438fd1498Szrj 	}
214538fd1498Szrj 
214638fd1498Szrj       if (TREE_CODE (arg0) != SSA_NAME)
214738fd1498Szrj 	break;
214838fd1498Szrj       loc = gimple_location (stmt);
214938fd1498Szrj       switch (code)
215038fd1498Szrj 	{
215138fd1498Szrj 	case BIT_NOT_EXPR:
215238fd1498Szrj 	  if (TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE
215338fd1498Szrj 	      /* Ensure the range is either +[-,0], +[0,0],
215438fd1498Szrj 		 -[-,0], -[0,0] or +[1,-], +[1,1], -[1,-] or
215538fd1498Szrj 		 -[1,1].  If it is e.g. +[-,-] or -[-,-]
215638fd1498Szrj 		 or similar expression of unconditional true or
215738fd1498Szrj 		 false, it should not be negated.  */
215838fd1498Szrj 	      && ((high && integer_zerop (high))
215938fd1498Szrj 		  || (low && integer_onep (low))))
216038fd1498Szrj 	    {
216138fd1498Szrj 	      in_p = !in_p;
216238fd1498Szrj 	      exp = arg0;
216338fd1498Szrj 	      continue;
216438fd1498Szrj 	    }
216538fd1498Szrj 	  break;
216638fd1498Szrj 	case SSA_NAME:
216738fd1498Szrj 	  exp = arg0;
216838fd1498Szrj 	  continue;
216938fd1498Szrj 	CASE_CONVERT:
217038fd1498Szrj 	  if (is_bool)
2171*58e805e6Szrj 	    {
2172*58e805e6Szrj 	      if ((TYPE_PRECISION (exp_type) == 1
2173*58e805e6Szrj 		   || TREE_CODE (exp_type) == BOOLEAN_TYPE)
2174*58e805e6Szrj 		  && TYPE_PRECISION (TREE_TYPE (arg0)) > 1)
2175*58e805e6Szrj 		return;
2176*58e805e6Szrj 	    }
2177*58e805e6Szrj 	  else if (TYPE_PRECISION (TREE_TYPE (arg0)) == 1)
217838fd1498Szrj 	    {
217938fd1498Szrj 	      if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
218038fd1498Szrj 		is_bool = true;
218138fd1498Szrj 	      else
218238fd1498Szrj 		return;
218338fd1498Szrj 	    }
218438fd1498Szrj 	  else if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE)
218538fd1498Szrj 	    is_bool = true;
218638fd1498Szrj 	  goto do_default;
218738fd1498Szrj 	case EQ_EXPR:
218838fd1498Szrj 	case NE_EXPR:
218938fd1498Szrj 	case LT_EXPR:
219038fd1498Szrj 	case LE_EXPR:
219138fd1498Szrj 	case GE_EXPR:
219238fd1498Szrj 	case GT_EXPR:
219338fd1498Szrj 	  is_bool = true;
219438fd1498Szrj 	  /* FALLTHRU */
219538fd1498Szrj 	default:
219638fd1498Szrj 	  if (!is_bool)
219738fd1498Szrj 	    return;
219838fd1498Szrj 	do_default:
219938fd1498Szrj 	  nexp = make_range_step (loc, code, arg0, arg1, exp_type,
220038fd1498Szrj 				  &low, &high, &in_p,
220138fd1498Szrj 				  &strict_overflow_p);
220238fd1498Szrj 	  if (nexp != NULL_TREE)
220338fd1498Szrj 	    {
220438fd1498Szrj 	      exp = nexp;
220538fd1498Szrj 	      gcc_assert (TREE_CODE (exp) == SSA_NAME);
220638fd1498Szrj 	      continue;
220738fd1498Szrj 	    }
220838fd1498Szrj 	  break;
220938fd1498Szrj 	}
221038fd1498Szrj       break;
221138fd1498Szrj     }
221238fd1498Szrj   if (is_bool)
221338fd1498Szrj     {
221438fd1498Szrj       r->exp = exp;
221538fd1498Szrj       r->in_p = in_p;
221638fd1498Szrj       r->low = low;
221738fd1498Szrj       r->high = high;
221838fd1498Szrj       r->strict_overflow_p = strict_overflow_p;
221938fd1498Szrj     }
222038fd1498Szrj }
222138fd1498Szrj 
222238fd1498Szrj /* Comparison function for qsort.  Sort entries
222338fd1498Szrj    without SSA_NAME exp first, then with SSA_NAMEs sorted
222438fd1498Szrj    by increasing SSA_NAME_VERSION, and for the same SSA_NAMEs
222538fd1498Szrj    by increasing ->low and if ->low is the same, by increasing
222638fd1498Szrj    ->high.  ->low == NULL_TREE means minimum, ->high == NULL_TREE
222738fd1498Szrj    maximum.  */
222838fd1498Szrj 
222938fd1498Szrj static int
range_entry_cmp(const void * a,const void * b)223038fd1498Szrj range_entry_cmp (const void *a, const void *b)
223138fd1498Szrj {
223238fd1498Szrj   const struct range_entry *p = (const struct range_entry *) a;
223338fd1498Szrj   const struct range_entry *q = (const struct range_entry *) b;
223438fd1498Szrj 
223538fd1498Szrj   if (p->exp != NULL_TREE && TREE_CODE (p->exp) == SSA_NAME)
223638fd1498Szrj     {
223738fd1498Szrj       if (q->exp != NULL_TREE && TREE_CODE (q->exp) == SSA_NAME)
223838fd1498Szrj 	{
223938fd1498Szrj 	  /* Group range_entries for the same SSA_NAME together.  */
224038fd1498Szrj 	  if (SSA_NAME_VERSION (p->exp) < SSA_NAME_VERSION (q->exp))
224138fd1498Szrj 	    return -1;
224238fd1498Szrj 	  else if (SSA_NAME_VERSION (p->exp) > SSA_NAME_VERSION (q->exp))
224338fd1498Szrj 	    return 1;
224438fd1498Szrj 	  /* If ->low is different, NULL low goes first, then by
224538fd1498Szrj 	     ascending low.  */
224638fd1498Szrj 	  if (p->low != NULL_TREE)
224738fd1498Szrj 	    {
224838fd1498Szrj 	      if (q->low != NULL_TREE)
224938fd1498Szrj 		{
225038fd1498Szrj 		  tree tem = fold_binary (LT_EXPR, boolean_type_node,
225138fd1498Szrj 					  p->low, q->low);
225238fd1498Szrj 		  if (tem && integer_onep (tem))
225338fd1498Szrj 		    return -1;
225438fd1498Szrj 		  tem = fold_binary (GT_EXPR, boolean_type_node,
225538fd1498Szrj 				     p->low, q->low);
225638fd1498Szrj 		  if (tem && integer_onep (tem))
225738fd1498Szrj 		    return 1;
225838fd1498Szrj 		}
225938fd1498Szrj 	      else
226038fd1498Szrj 		return 1;
226138fd1498Szrj 	    }
226238fd1498Szrj 	  else if (q->low != NULL_TREE)
226338fd1498Szrj 	    return -1;
226438fd1498Szrj 	  /* If ->high is different, NULL high goes last, before that by
226538fd1498Szrj 	     ascending high.  */
226638fd1498Szrj 	  if (p->high != NULL_TREE)
226738fd1498Szrj 	    {
226838fd1498Szrj 	      if (q->high != NULL_TREE)
226938fd1498Szrj 		{
227038fd1498Szrj 		  tree tem = fold_binary (LT_EXPR, boolean_type_node,
227138fd1498Szrj 					  p->high, q->high);
227238fd1498Szrj 		  if (tem && integer_onep (tem))
227338fd1498Szrj 		    return -1;
227438fd1498Szrj 		  tem = fold_binary (GT_EXPR, boolean_type_node,
227538fd1498Szrj 				     p->high, q->high);
227638fd1498Szrj 		  if (tem && integer_onep (tem))
227738fd1498Szrj 		    return 1;
227838fd1498Szrj 		}
227938fd1498Szrj 	      else
228038fd1498Szrj 		return -1;
228138fd1498Szrj 	    }
228238fd1498Szrj 	  else if (q->high != NULL_TREE)
228338fd1498Szrj 	    return 1;
228438fd1498Szrj 	  /* If both ranges are the same, sort below by ascending idx.  */
228538fd1498Szrj 	}
228638fd1498Szrj       else
228738fd1498Szrj 	return 1;
228838fd1498Szrj     }
228938fd1498Szrj   else if (q->exp != NULL_TREE && TREE_CODE (q->exp) == SSA_NAME)
229038fd1498Szrj     return -1;
229138fd1498Szrj 
229238fd1498Szrj   if (p->idx < q->idx)
229338fd1498Szrj     return -1;
229438fd1498Szrj   else
229538fd1498Szrj     {
229638fd1498Szrj       gcc_checking_assert (p->idx > q->idx);
229738fd1498Szrj       return 1;
229838fd1498Szrj     }
229938fd1498Szrj }
230038fd1498Szrj 
230138fd1498Szrj /* Helper function for update_range_test.  Force EXPR into an SSA_NAME,
230238fd1498Szrj    insert needed statements BEFORE or after GSI.  */
230338fd1498Szrj 
230438fd1498Szrj static tree
force_into_ssa_name(gimple_stmt_iterator * gsi,tree expr,bool before)230538fd1498Szrj force_into_ssa_name (gimple_stmt_iterator *gsi, tree expr, bool before)
230638fd1498Szrj {
230738fd1498Szrj   enum gsi_iterator_update m = before ? GSI_SAME_STMT : GSI_CONTINUE_LINKING;
230838fd1498Szrj   tree ret = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE, before, m);
230938fd1498Szrj   if (TREE_CODE (ret) != SSA_NAME)
231038fd1498Szrj     {
231138fd1498Szrj       gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (ret)), ret);
231238fd1498Szrj       if (before)
231338fd1498Szrj 	gsi_insert_before (gsi, g, GSI_SAME_STMT);
231438fd1498Szrj       else
231538fd1498Szrj 	gsi_insert_after (gsi, g, GSI_CONTINUE_LINKING);
231638fd1498Szrj       ret = gimple_assign_lhs (g);
231738fd1498Szrj     }
231838fd1498Szrj   return ret;
231938fd1498Szrj }
232038fd1498Szrj 
232138fd1498Szrj /* Helper routine of optimize_range_test.
232238fd1498Szrj    [EXP, IN_P, LOW, HIGH, STRICT_OVERFLOW_P] is a merged range for
232338fd1498Szrj    RANGE and OTHERRANGE through OTHERRANGE + COUNT - 1 ranges,
232438fd1498Szrj    OPCODE and OPS are arguments of optimize_range_tests.  If OTHERRANGE
232538fd1498Szrj    is NULL, OTHERRANGEP should not be and then OTHERRANGEP points to
232638fd1498Szrj    an array of COUNT pointers to other ranges.  Return
232738fd1498Szrj    true if the range merge has been successful.
232838fd1498Szrj    If OPCODE is ERROR_MARK, this is called from within
232938fd1498Szrj    maybe_optimize_range_tests and is performing inter-bb range optimization.
233038fd1498Szrj    In that case, whether an op is BIT_AND_EXPR or BIT_IOR_EXPR is found in
233138fd1498Szrj    oe->rank.  */
233238fd1498Szrj 
233338fd1498Szrj static bool
update_range_test(struct range_entry * range,struct range_entry * otherrange,struct range_entry ** otherrangep,unsigned int count,enum tree_code opcode,vec<operand_entry * > * ops,tree exp,gimple_seq seq,bool in_p,tree low,tree high,bool strict_overflow_p)233438fd1498Szrj update_range_test (struct range_entry *range, struct range_entry *otherrange,
233538fd1498Szrj 		   struct range_entry **otherrangep,
233638fd1498Szrj 		   unsigned int count, enum tree_code opcode,
233738fd1498Szrj 		   vec<operand_entry *> *ops, tree exp, gimple_seq seq,
233838fd1498Szrj 		   bool in_p, tree low, tree high, bool strict_overflow_p)
233938fd1498Szrj {
234038fd1498Szrj   operand_entry *oe = (*ops)[range->idx];
234138fd1498Szrj   tree op = oe->op;
234238fd1498Szrj   gimple *stmt = op ? SSA_NAME_DEF_STMT (op)
234338fd1498Szrj 		    : last_stmt (BASIC_BLOCK_FOR_FN (cfun, oe->id));
234438fd1498Szrj   location_t loc = gimple_location (stmt);
234538fd1498Szrj   tree optype = op ? TREE_TYPE (op) : boolean_type_node;
234638fd1498Szrj   tree tem = build_range_check (loc, optype, unshare_expr (exp),
234738fd1498Szrj 				in_p, low, high);
234838fd1498Szrj   enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON;
234938fd1498Szrj   gimple_stmt_iterator gsi;
235038fd1498Szrj   unsigned int i, uid;
235138fd1498Szrj 
235238fd1498Szrj   if (tem == NULL_TREE)
235338fd1498Szrj     return false;
235438fd1498Szrj 
235538fd1498Szrj   /* If op is default def SSA_NAME, there is no place to insert the
235638fd1498Szrj      new comparison.  Give up, unless we can use OP itself as the
235738fd1498Szrj      range test.  */
235838fd1498Szrj   if (op && SSA_NAME_IS_DEFAULT_DEF (op))
235938fd1498Szrj     {
236038fd1498Szrj       if (op == range->exp
236138fd1498Szrj 	  && ((TYPE_PRECISION (optype) == 1 && TYPE_UNSIGNED (optype))
236238fd1498Szrj 	      || TREE_CODE (optype) == BOOLEAN_TYPE)
236338fd1498Szrj 	  && (op == tem
236438fd1498Szrj 	      || (TREE_CODE (tem) == EQ_EXPR
236538fd1498Szrj 		  && TREE_OPERAND (tem, 0) == op
236638fd1498Szrj 		  && integer_onep (TREE_OPERAND (tem, 1))))
236738fd1498Szrj 	  && opcode != BIT_IOR_EXPR
236838fd1498Szrj 	  && (opcode != ERROR_MARK || oe->rank != BIT_IOR_EXPR))
236938fd1498Szrj 	{
237038fd1498Szrj 	  stmt = NULL;
237138fd1498Szrj 	  tem = op;
237238fd1498Szrj 	}
237338fd1498Szrj       else
237438fd1498Szrj 	return false;
237538fd1498Szrj     }
237638fd1498Szrj 
237738fd1498Szrj   if (strict_overflow_p && issue_strict_overflow_warning (wc))
237838fd1498Szrj     warning_at (loc, OPT_Wstrict_overflow,
237938fd1498Szrj 		"assuming signed overflow does not occur "
238038fd1498Szrj 		"when simplifying range test");
238138fd1498Szrj 
238238fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
238338fd1498Szrj     {
238438fd1498Szrj       struct range_entry *r;
238538fd1498Szrj       fprintf (dump_file, "Optimizing range tests ");
238638fd1498Szrj       print_generic_expr (dump_file, range->exp);
238738fd1498Szrj       fprintf (dump_file, " %c[", range->in_p ? '+' : '-');
238838fd1498Szrj       print_generic_expr (dump_file, range->low);
238938fd1498Szrj       fprintf (dump_file, ", ");
239038fd1498Szrj       print_generic_expr (dump_file, range->high);
239138fd1498Szrj       fprintf (dump_file, "]");
239238fd1498Szrj       for (i = 0; i < count; i++)
239338fd1498Szrj 	{
239438fd1498Szrj 	  if (otherrange)
239538fd1498Szrj 	    r = otherrange + i;
239638fd1498Szrj 	  else
239738fd1498Szrj 	    r = otherrangep[i];
239838fd1498Szrj 	  if (r->exp
239938fd1498Szrj 	      && r->exp != range->exp
240038fd1498Szrj 	      && TREE_CODE (r->exp) == SSA_NAME)
240138fd1498Szrj 	    {
240238fd1498Szrj 	      fprintf (dump_file, " and ");
240338fd1498Szrj 	      print_generic_expr (dump_file, r->exp);
240438fd1498Szrj 	    }
240538fd1498Szrj 	  else
240638fd1498Szrj 	    fprintf (dump_file, " and");
240738fd1498Szrj 	  fprintf (dump_file, " %c[", r->in_p ? '+' : '-');
240838fd1498Szrj 	  print_generic_expr (dump_file, r->low);
240938fd1498Szrj 	  fprintf (dump_file, ", ");
241038fd1498Szrj 	  print_generic_expr (dump_file, r->high);
241138fd1498Szrj 	  fprintf (dump_file, "]");
241238fd1498Szrj 	}
241338fd1498Szrj       fprintf (dump_file, "\n into ");
241438fd1498Szrj       print_generic_expr (dump_file, tem);
241538fd1498Szrj       fprintf (dump_file, "\n");
241638fd1498Szrj     }
241738fd1498Szrj 
241838fd1498Szrj   if (opcode == BIT_IOR_EXPR
241938fd1498Szrj       || (opcode == ERROR_MARK && oe->rank == BIT_IOR_EXPR))
242038fd1498Szrj     tem = invert_truthvalue_loc (loc, tem);
242138fd1498Szrj 
242238fd1498Szrj   tem = fold_convert_loc (loc, optype, tem);
242338fd1498Szrj   if (stmt)
242438fd1498Szrj     {
242538fd1498Szrj       gsi = gsi_for_stmt (stmt);
242638fd1498Szrj       uid = gimple_uid (stmt);
242738fd1498Szrj     }
242838fd1498Szrj   else
242938fd1498Szrj     {
243038fd1498Szrj       gsi = gsi_none ();
243138fd1498Szrj       uid = 0;
243238fd1498Szrj     }
243338fd1498Szrj   if (stmt == NULL)
243438fd1498Szrj     gcc_checking_assert (tem == op);
243538fd1498Szrj   /* In rare cases range->exp can be equal to lhs of stmt.
243638fd1498Szrj      In that case we have to insert after the stmt rather then before
243738fd1498Szrj      it.  If stmt is a PHI, insert it at the start of the basic block.  */
243838fd1498Szrj   else if (op != range->exp)
243938fd1498Szrj     {
244038fd1498Szrj       gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
244138fd1498Szrj       tem = force_into_ssa_name (&gsi, tem, true);
244238fd1498Szrj       gsi_prev (&gsi);
244338fd1498Szrj     }
244438fd1498Szrj   else if (gimple_code (stmt) != GIMPLE_PHI)
244538fd1498Szrj     {
244638fd1498Szrj       gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
244738fd1498Szrj       tem = force_into_ssa_name (&gsi, tem, false);
244838fd1498Szrj     }
244938fd1498Szrj   else
245038fd1498Szrj     {
245138fd1498Szrj       gsi = gsi_after_labels (gimple_bb (stmt));
245238fd1498Szrj       if (!gsi_end_p (gsi))
245338fd1498Szrj 	uid = gimple_uid (gsi_stmt (gsi));
245438fd1498Szrj       else
245538fd1498Szrj 	{
245638fd1498Szrj 	  gsi = gsi_start_bb (gimple_bb (stmt));
245738fd1498Szrj 	  uid = 1;
245838fd1498Szrj 	  while (!gsi_end_p (gsi))
245938fd1498Szrj 	    {
246038fd1498Szrj 	      uid = gimple_uid (gsi_stmt (gsi));
246138fd1498Szrj 	      gsi_next (&gsi);
246238fd1498Szrj 	    }
246338fd1498Szrj 	}
246438fd1498Szrj       gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
246538fd1498Szrj       tem = force_into_ssa_name (&gsi, tem, true);
246638fd1498Szrj       if (gsi_end_p (gsi))
246738fd1498Szrj 	gsi = gsi_last_bb (gimple_bb (stmt));
246838fd1498Szrj       else
246938fd1498Szrj 	gsi_prev (&gsi);
247038fd1498Szrj     }
247138fd1498Szrj   for (; !gsi_end_p (gsi); gsi_prev (&gsi))
247238fd1498Szrj     if (gimple_uid (gsi_stmt (gsi)))
247338fd1498Szrj       break;
247438fd1498Szrj     else
247538fd1498Szrj       gimple_set_uid (gsi_stmt (gsi), uid);
247638fd1498Szrj 
247738fd1498Szrj   oe->op = tem;
247838fd1498Szrj   range->exp = exp;
247938fd1498Szrj   range->low = low;
248038fd1498Szrj   range->high = high;
248138fd1498Szrj   range->in_p = in_p;
248238fd1498Szrj   range->strict_overflow_p = false;
248338fd1498Szrj 
248438fd1498Szrj   for (i = 0; i < count; i++)
248538fd1498Szrj     {
248638fd1498Szrj       if (otherrange)
248738fd1498Szrj 	range = otherrange + i;
248838fd1498Szrj       else
248938fd1498Szrj 	range = otherrangep[i];
249038fd1498Szrj       oe = (*ops)[range->idx];
249138fd1498Szrj       /* Now change all the other range test immediate uses, so that
249238fd1498Szrj 	 those tests will be optimized away.  */
249338fd1498Szrj       if (opcode == ERROR_MARK)
249438fd1498Szrj 	{
249538fd1498Szrj 	  if (oe->op)
249638fd1498Szrj 	    oe->op = build_int_cst (TREE_TYPE (oe->op),
249738fd1498Szrj 				    oe->rank == BIT_IOR_EXPR ? 0 : 1);
249838fd1498Szrj 	  else
249938fd1498Szrj 	    oe->op = (oe->rank == BIT_IOR_EXPR
250038fd1498Szrj 		      ? boolean_false_node : boolean_true_node);
250138fd1498Szrj 	}
250238fd1498Szrj       else
250338fd1498Szrj 	oe->op = error_mark_node;
250438fd1498Szrj       range->exp = NULL_TREE;
250538fd1498Szrj       range->low = NULL_TREE;
250638fd1498Szrj       range->high = NULL_TREE;
250738fd1498Szrj     }
250838fd1498Szrj   return true;
250938fd1498Szrj }
251038fd1498Szrj 
251138fd1498Szrj /* Optimize X == CST1 || X == CST2
251238fd1498Szrj    if popcount (CST1 ^ CST2) == 1 into
251338fd1498Szrj    (X & ~(CST1 ^ CST2)) == (CST1 & ~(CST1 ^ CST2)).
251438fd1498Szrj    Similarly for ranges.  E.g.
251538fd1498Szrj    X != 2 && X != 3 && X != 10 && X != 11
251638fd1498Szrj    will be transformed by the previous optimization into
251738fd1498Szrj    !((X - 2U) <= 1U || (X - 10U) <= 1U)
251838fd1498Szrj    and this loop can transform that into
251938fd1498Szrj    !(((X & ~8) - 2U) <= 1U).  */
252038fd1498Szrj 
252138fd1498Szrj static bool
optimize_range_tests_xor(enum tree_code opcode,tree type,tree lowi,tree lowj,tree highi,tree highj,vec<operand_entry * > * ops,struct range_entry * rangei,struct range_entry * rangej)252238fd1498Szrj optimize_range_tests_xor (enum tree_code opcode, tree type,
252338fd1498Szrj 			  tree lowi, tree lowj, tree highi, tree highj,
252438fd1498Szrj 			  vec<operand_entry *> *ops,
252538fd1498Szrj 			  struct range_entry *rangei,
252638fd1498Szrj 			  struct range_entry *rangej)
252738fd1498Szrj {
252838fd1498Szrj   tree lowxor, highxor, tem, exp;
252938fd1498Szrj   /* Check lowi ^ lowj == highi ^ highj and
253038fd1498Szrj      popcount (lowi ^ lowj) == 1.  */
253138fd1498Szrj   lowxor = fold_binary (BIT_XOR_EXPR, type, lowi, lowj);
253238fd1498Szrj   if (lowxor == NULL_TREE || TREE_CODE (lowxor) != INTEGER_CST)
253338fd1498Szrj     return false;
253438fd1498Szrj   if (!integer_pow2p (lowxor))
253538fd1498Szrj     return false;
253638fd1498Szrj   highxor = fold_binary (BIT_XOR_EXPR, type, highi, highj);
253738fd1498Szrj   if (!tree_int_cst_equal (lowxor, highxor))
253838fd1498Szrj     return false;
253938fd1498Szrj 
254038fd1498Szrj   tem = fold_build1 (BIT_NOT_EXPR, type, lowxor);
254138fd1498Szrj   exp = fold_build2 (BIT_AND_EXPR, type, rangei->exp, tem);
254238fd1498Szrj   lowj = fold_build2 (BIT_AND_EXPR, type, lowi, tem);
254338fd1498Szrj   highj = fold_build2 (BIT_AND_EXPR, type, highi, tem);
254438fd1498Szrj   if (update_range_test (rangei, rangej, NULL, 1, opcode, ops, exp,
254538fd1498Szrj 			 NULL, rangei->in_p, lowj, highj,
254638fd1498Szrj 			 rangei->strict_overflow_p
254738fd1498Szrj 			 || rangej->strict_overflow_p))
254838fd1498Szrj     return true;
254938fd1498Szrj   return false;
255038fd1498Szrj }
255138fd1498Szrj 
255238fd1498Szrj /* Optimize X == CST1 || X == CST2
255338fd1498Szrj    if popcount (CST2 - CST1) == 1 into
255438fd1498Szrj    ((X - CST1) & ~(CST2 - CST1)) == 0.
255538fd1498Szrj    Similarly for ranges.  E.g.
255638fd1498Szrj    X == 43 || X == 76 || X == 44 || X == 78 || X == 77 || X == 46
255738fd1498Szrj    || X == 75 || X == 45
255838fd1498Szrj    will be transformed by the previous optimization into
255938fd1498Szrj    (X - 43U) <= 3U || (X - 75U) <= 3U
256038fd1498Szrj    and this loop can transform that into
256138fd1498Szrj    ((X - 43U) & ~(75U - 43U)) <= 3U.  */
256238fd1498Szrj static bool
optimize_range_tests_diff(enum tree_code opcode,tree type,tree lowi,tree lowj,tree highi,tree highj,vec<operand_entry * > * ops,struct range_entry * rangei,struct range_entry * rangej)256338fd1498Szrj optimize_range_tests_diff (enum tree_code opcode, tree type,
256438fd1498Szrj 			   tree lowi, tree lowj, tree highi, tree highj,
256538fd1498Szrj 			   vec<operand_entry *> *ops,
256638fd1498Szrj 			   struct range_entry *rangei,
256738fd1498Szrj 			   struct range_entry *rangej)
256838fd1498Szrj {
256938fd1498Szrj   tree tem1, tem2, mask;
257038fd1498Szrj   /* Check highi - lowi == highj - lowj.  */
257138fd1498Szrj   tem1 = fold_binary (MINUS_EXPR, type, highi, lowi);
257238fd1498Szrj   if (tem1 == NULL_TREE || TREE_CODE (tem1) != INTEGER_CST)
257338fd1498Szrj     return false;
257438fd1498Szrj   tem2 = fold_binary (MINUS_EXPR, type, highj, lowj);
257538fd1498Szrj   if (!tree_int_cst_equal (tem1, tem2))
257638fd1498Szrj     return false;
257738fd1498Szrj   /* Check popcount (lowj - lowi) == 1.  */
257838fd1498Szrj   tem1 = fold_binary (MINUS_EXPR, type, lowj, lowi);
257938fd1498Szrj   if (tem1 == NULL_TREE || TREE_CODE (tem1) != INTEGER_CST)
258038fd1498Szrj     return false;
258138fd1498Szrj   if (!integer_pow2p (tem1))
258238fd1498Szrj     return false;
258338fd1498Szrj 
258438fd1498Szrj   type = unsigned_type_for (type);
258538fd1498Szrj   tem1 = fold_convert (type, tem1);
258638fd1498Szrj   tem2 = fold_convert (type, tem2);
258738fd1498Szrj   lowi = fold_convert (type, lowi);
258838fd1498Szrj   mask = fold_build1 (BIT_NOT_EXPR, type, tem1);
258938fd1498Szrj   tem1 = fold_build2 (MINUS_EXPR, type,
259038fd1498Szrj 		      fold_convert (type, rangei->exp), lowi);
259138fd1498Szrj   tem1 = fold_build2 (BIT_AND_EXPR, type, tem1, mask);
259238fd1498Szrj   lowj = build_int_cst (type, 0);
259338fd1498Szrj   if (update_range_test (rangei, rangej, NULL, 1, opcode, ops, tem1,
259438fd1498Szrj 			 NULL, rangei->in_p, lowj, tem2,
259538fd1498Szrj 			 rangei->strict_overflow_p
259638fd1498Szrj 			 || rangej->strict_overflow_p))
259738fd1498Szrj     return true;
259838fd1498Szrj   return false;
259938fd1498Szrj }
260038fd1498Szrj 
260138fd1498Szrj /* It does some common checks for function optimize_range_tests_xor and
260238fd1498Szrj    optimize_range_tests_diff.
260338fd1498Szrj    If OPTIMIZE_XOR is TRUE, it calls optimize_range_tests_xor.
260438fd1498Szrj    Else it calls optimize_range_tests_diff.  */
260538fd1498Szrj 
260638fd1498Szrj static bool
optimize_range_tests_1(enum tree_code opcode,int first,int length,bool optimize_xor,vec<operand_entry * > * ops,struct range_entry * ranges)260738fd1498Szrj optimize_range_tests_1 (enum tree_code opcode, int first, int length,
260838fd1498Szrj 			bool optimize_xor, vec<operand_entry *> *ops,
260938fd1498Szrj 			struct range_entry *ranges)
261038fd1498Szrj {
261138fd1498Szrj   int i, j;
261238fd1498Szrj   bool any_changes = false;
261338fd1498Szrj   for (i = first; i < length; i++)
261438fd1498Szrj     {
261538fd1498Szrj       tree lowi, highi, lowj, highj, type, tem;
261638fd1498Szrj 
261738fd1498Szrj       if (ranges[i].exp == NULL_TREE || ranges[i].in_p)
261838fd1498Szrj 	continue;
261938fd1498Szrj       type = TREE_TYPE (ranges[i].exp);
262038fd1498Szrj       if (!INTEGRAL_TYPE_P (type))
262138fd1498Szrj 	continue;
262238fd1498Szrj       lowi = ranges[i].low;
262338fd1498Szrj       if (lowi == NULL_TREE)
262438fd1498Szrj 	lowi = TYPE_MIN_VALUE (type);
262538fd1498Szrj       highi = ranges[i].high;
262638fd1498Szrj       if (highi == NULL_TREE)
262738fd1498Szrj 	continue;
262838fd1498Szrj       for (j = i + 1; j < length && j < i + 64; j++)
262938fd1498Szrj 	{
263038fd1498Szrj 	  bool changes;
263138fd1498Szrj 	  if (ranges[i].exp != ranges[j].exp || ranges[j].in_p)
263238fd1498Szrj 	    continue;
263338fd1498Szrj 	  lowj = ranges[j].low;
263438fd1498Szrj 	  if (lowj == NULL_TREE)
263538fd1498Szrj 	    continue;
263638fd1498Szrj 	  highj = ranges[j].high;
263738fd1498Szrj 	  if (highj == NULL_TREE)
263838fd1498Szrj 	    highj = TYPE_MAX_VALUE (type);
263938fd1498Szrj 	  /* Check lowj > highi.  */
264038fd1498Szrj 	  tem = fold_binary (GT_EXPR, boolean_type_node,
264138fd1498Szrj 			     lowj, highi);
264238fd1498Szrj 	  if (tem == NULL_TREE || !integer_onep (tem))
264338fd1498Szrj 	    continue;
264438fd1498Szrj 	  if (optimize_xor)
264538fd1498Szrj 	    changes = optimize_range_tests_xor (opcode, type, lowi, lowj,
264638fd1498Szrj 						highi, highj, ops,
264738fd1498Szrj 						ranges + i, ranges + j);
264838fd1498Szrj 	  else
264938fd1498Szrj 	    changes = optimize_range_tests_diff (opcode, type, lowi, lowj,
265038fd1498Szrj 						 highi, highj, ops,
265138fd1498Szrj 						 ranges + i, ranges + j);
265238fd1498Szrj 	  if (changes)
265338fd1498Szrj 	    {
265438fd1498Szrj 	      any_changes = true;
265538fd1498Szrj 	      break;
265638fd1498Szrj 	    }
265738fd1498Szrj 	}
265838fd1498Szrj     }
265938fd1498Szrj   return any_changes;
266038fd1498Szrj }
266138fd1498Szrj 
266238fd1498Szrj /* Helper function of optimize_range_tests_to_bit_test.  Handle a single
266338fd1498Szrj    range, EXP, LOW, HIGH, compute bit mask of bits to test and return
266438fd1498Szrj    EXP on success, NULL otherwise.  */
266538fd1498Szrj 
266638fd1498Szrj static tree
extract_bit_test_mask(tree exp,int prec,tree totallow,tree low,tree high,wide_int * mask,tree * totallowp)266738fd1498Szrj extract_bit_test_mask (tree exp, int prec, tree totallow, tree low, tree high,
266838fd1498Szrj 		       wide_int *mask, tree *totallowp)
266938fd1498Szrj {
267038fd1498Szrj   tree tem = int_const_binop (MINUS_EXPR, high, low);
267138fd1498Szrj   if (tem == NULL_TREE
267238fd1498Szrj       || TREE_CODE (tem) != INTEGER_CST
267338fd1498Szrj       || TREE_OVERFLOW (tem)
267438fd1498Szrj       || tree_int_cst_sgn (tem) == -1
267538fd1498Szrj       || compare_tree_int (tem, prec) != -1)
267638fd1498Szrj     return NULL_TREE;
267738fd1498Szrj 
267838fd1498Szrj   unsigned HOST_WIDE_INT max = tree_to_uhwi (tem) + 1;
267938fd1498Szrj   *mask = wi::shifted_mask (0, max, false, prec);
268038fd1498Szrj   if (TREE_CODE (exp) == BIT_AND_EXPR
268138fd1498Szrj       && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
268238fd1498Szrj     {
268338fd1498Szrj       widest_int msk = wi::to_widest (TREE_OPERAND (exp, 1));
268438fd1498Szrj       msk = wi::zext (~msk, TYPE_PRECISION (TREE_TYPE (exp)));
268538fd1498Szrj       if (wi::popcount (msk) == 1
268638fd1498Szrj 	  && wi::ltu_p (msk, prec - max))
268738fd1498Szrj 	{
268838fd1498Szrj 	  *mask |= wi::shifted_mask (msk.to_uhwi (), max, false, prec);
268938fd1498Szrj 	  max += msk.to_uhwi ();
269038fd1498Szrj 	  exp = TREE_OPERAND (exp, 0);
269138fd1498Szrj 	  if (integer_zerop (low)
269238fd1498Szrj 	      && TREE_CODE (exp) == PLUS_EXPR
269338fd1498Szrj 	      && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
269438fd1498Szrj 	    {
269538fd1498Szrj 	      tree ret = TREE_OPERAND (exp, 0);
269638fd1498Szrj 	      STRIP_NOPS (ret);
269738fd1498Szrj 	      widest_int bias
269838fd1498Szrj 	        = wi::neg (wi::sext (wi::to_widest (TREE_OPERAND (exp, 1)),
269938fd1498Szrj 				     TYPE_PRECISION (TREE_TYPE (low))));
270038fd1498Szrj 	      tree tbias = wide_int_to_tree (TREE_TYPE (ret), bias);
270138fd1498Szrj 	      if (totallowp)
270238fd1498Szrj 		{
270338fd1498Szrj 		  *totallowp = tbias;
270438fd1498Szrj 		  return ret;
270538fd1498Szrj 		}
270638fd1498Szrj 	      else if (!tree_int_cst_lt (totallow, tbias))
270738fd1498Szrj 		return NULL_TREE;
270838fd1498Szrj 	      bias = wi::to_widest (tbias);
270938fd1498Szrj 	      bias -= wi::to_widest (totallow);
271038fd1498Szrj 	      if (bias >= 0 && bias < prec - max)
271138fd1498Szrj 		{
271238fd1498Szrj 		  *mask = wi::lshift (*mask, bias);
271338fd1498Szrj 		  return ret;
271438fd1498Szrj 		}
271538fd1498Szrj 	    }
271638fd1498Szrj 	}
271738fd1498Szrj     }
271838fd1498Szrj   if (totallowp)
271938fd1498Szrj     return exp;
272038fd1498Szrj   if (!tree_int_cst_lt (totallow, low))
272138fd1498Szrj     return exp;
272238fd1498Szrj   tem = int_const_binop (MINUS_EXPR, low, totallow);
272338fd1498Szrj   if (tem == NULL_TREE
272438fd1498Szrj       || TREE_CODE (tem) != INTEGER_CST
272538fd1498Szrj       || TREE_OVERFLOW (tem)
272638fd1498Szrj       || compare_tree_int (tem, prec - max) == 1)
272738fd1498Szrj     return NULL_TREE;
272838fd1498Szrj 
272938fd1498Szrj   *mask = wi::lshift (*mask, wi::to_widest (tem));
273038fd1498Szrj   return exp;
273138fd1498Szrj }
273238fd1498Szrj 
273338fd1498Szrj /* Attempt to optimize small range tests using bit test.
273438fd1498Szrj    E.g.
273538fd1498Szrj    X != 43 && X != 76 && X != 44 && X != 78 && X != 49
273638fd1498Szrj    && X != 77 && X != 46 && X != 75 && X != 45 && X != 82
273738fd1498Szrj    has been by earlier optimizations optimized into:
273838fd1498Szrj    ((X - 43U) & ~32U) > 3U && X != 49 && X != 82
273938fd1498Szrj    As all the 43 through 82 range is less than 64 numbers,
274038fd1498Szrj    for 64-bit word targets optimize that into:
274138fd1498Szrj    (X - 43U) > 40U && ((1 << (X - 43U)) & 0x8F0000004FULL) == 0  */
274238fd1498Szrj 
274338fd1498Szrj static bool
optimize_range_tests_to_bit_test(enum tree_code opcode,int first,int length,vec<operand_entry * > * ops,struct range_entry * ranges)274438fd1498Szrj optimize_range_tests_to_bit_test (enum tree_code opcode, int first, int length,
274538fd1498Szrj 				  vec<operand_entry *> *ops,
274638fd1498Szrj 				  struct range_entry *ranges)
274738fd1498Szrj {
274838fd1498Szrj   int i, j;
274938fd1498Szrj   bool any_changes = false;
275038fd1498Szrj   int prec = GET_MODE_BITSIZE (word_mode);
275138fd1498Szrj   auto_vec<struct range_entry *, 64> candidates;
275238fd1498Szrj 
275338fd1498Szrj   for (i = first; i < length - 2; i++)
275438fd1498Szrj     {
275538fd1498Szrj       tree lowi, highi, lowj, highj, type;
275638fd1498Szrj 
275738fd1498Szrj       if (ranges[i].exp == NULL_TREE || ranges[i].in_p)
275838fd1498Szrj 	continue;
275938fd1498Szrj       type = TREE_TYPE (ranges[i].exp);
276038fd1498Szrj       if (!INTEGRAL_TYPE_P (type))
276138fd1498Szrj 	continue;
276238fd1498Szrj       lowi = ranges[i].low;
276338fd1498Szrj       if (lowi == NULL_TREE)
276438fd1498Szrj 	lowi = TYPE_MIN_VALUE (type);
276538fd1498Szrj       highi = ranges[i].high;
276638fd1498Szrj       if (highi == NULL_TREE)
276738fd1498Szrj 	continue;
276838fd1498Szrj       wide_int mask;
276938fd1498Szrj       tree exp = extract_bit_test_mask (ranges[i].exp, prec, lowi, lowi,
277038fd1498Szrj 					highi, &mask, &lowi);
277138fd1498Szrj       if (exp == NULL_TREE)
277238fd1498Szrj 	continue;
277338fd1498Szrj       bool strict_overflow_p = ranges[i].strict_overflow_p;
277438fd1498Szrj       candidates.truncate (0);
277538fd1498Szrj       int end = MIN (i + 64, length);
277638fd1498Szrj       for (j = i + 1; j < end; j++)
277738fd1498Szrj 	{
277838fd1498Szrj 	  tree exp2;
277938fd1498Szrj 	  if (ranges[j].exp == NULL_TREE || ranges[j].in_p)
278038fd1498Szrj 	    continue;
278138fd1498Szrj 	  if (ranges[j].exp == exp)
278238fd1498Szrj 	    ;
278338fd1498Szrj 	  else if (TREE_CODE (ranges[j].exp) == BIT_AND_EXPR)
278438fd1498Szrj 	    {
278538fd1498Szrj 	      exp2 = TREE_OPERAND (ranges[j].exp, 0);
278638fd1498Szrj 	      if (exp2 == exp)
278738fd1498Szrj 		;
278838fd1498Szrj 	      else if (TREE_CODE (exp2) == PLUS_EXPR)
278938fd1498Szrj 		{
279038fd1498Szrj 		  exp2 = TREE_OPERAND (exp2, 0);
279138fd1498Szrj 		  STRIP_NOPS (exp2);
279238fd1498Szrj 		  if (exp2 != exp)
279338fd1498Szrj 		    continue;
279438fd1498Szrj 		}
279538fd1498Szrj 	      else
279638fd1498Szrj 		continue;
279738fd1498Szrj 	    }
279838fd1498Szrj 	  else
279938fd1498Szrj 	    continue;
280038fd1498Szrj 	  lowj = ranges[j].low;
280138fd1498Szrj 	  if (lowj == NULL_TREE)
280238fd1498Szrj 	    continue;
280338fd1498Szrj 	  highj = ranges[j].high;
280438fd1498Szrj 	  if (highj == NULL_TREE)
280538fd1498Szrj 	    highj = TYPE_MAX_VALUE (type);
280638fd1498Szrj 	  wide_int mask2;
280738fd1498Szrj 	  exp2 = extract_bit_test_mask (ranges[j].exp, prec, lowi, lowj,
280838fd1498Szrj 					highj, &mask2, NULL);
280938fd1498Szrj 	  if (exp2 != exp)
281038fd1498Szrj 	    continue;
281138fd1498Szrj 	  mask |= mask2;
281238fd1498Szrj 	  strict_overflow_p |= ranges[j].strict_overflow_p;
281338fd1498Szrj 	  candidates.safe_push (&ranges[j]);
281438fd1498Szrj 	}
281538fd1498Szrj 
281638fd1498Szrj       /* If we need otherwise 3 or more comparisons, use a bit test.  */
281738fd1498Szrj       if (candidates.length () >= 2)
281838fd1498Szrj 	{
281938fd1498Szrj 	  tree high = wide_int_to_tree (TREE_TYPE (lowi),
282038fd1498Szrj 					wi::to_widest (lowi)
282138fd1498Szrj 					+ prec - 1 - wi::clz (mask));
282238fd1498Szrj 	  operand_entry *oe = (*ops)[ranges[i].idx];
282338fd1498Szrj 	  tree op = oe->op;
282438fd1498Szrj 	  gimple *stmt = op ? SSA_NAME_DEF_STMT (op)
282538fd1498Szrj 			    : last_stmt (BASIC_BLOCK_FOR_FN (cfun, oe->id));
282638fd1498Szrj 	  location_t loc = gimple_location (stmt);
282738fd1498Szrj 	  tree optype = op ? TREE_TYPE (op) : boolean_type_node;
282838fd1498Szrj 
282938fd1498Szrj 	  /* See if it isn't cheaper to pretend the minimum value of the
283038fd1498Szrj 	     range is 0, if maximum value is small enough.
283138fd1498Szrj 	     We can avoid then subtraction of the minimum value, but the
283238fd1498Szrj 	     mask constant could be perhaps more expensive.  */
283338fd1498Szrj 	  if (compare_tree_int (lowi, 0) > 0
283438fd1498Szrj 	      && compare_tree_int (high, prec) < 0)
283538fd1498Szrj 	    {
283638fd1498Szrj 	      int cost_diff;
283738fd1498Szrj 	      HOST_WIDE_INT m = tree_to_uhwi (lowi);
283838fd1498Szrj 	      rtx reg = gen_raw_REG (word_mode, 10000);
283938fd1498Szrj 	      bool speed_p = optimize_bb_for_speed_p (gimple_bb (stmt));
284038fd1498Szrj 	      cost_diff = set_rtx_cost (gen_rtx_PLUS (word_mode, reg,
284138fd1498Szrj 						      GEN_INT (-m)), speed_p);
284238fd1498Szrj 	      rtx r = immed_wide_int_const (mask, word_mode);
284338fd1498Szrj 	      cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r),
284438fd1498Szrj 					 word_mode, speed_p);
284538fd1498Szrj 	      r = immed_wide_int_const (wi::lshift (mask, m), word_mode);
284638fd1498Szrj 	      cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r),
284738fd1498Szrj 					 word_mode, speed_p);
284838fd1498Szrj 	      if (cost_diff > 0)
284938fd1498Szrj 		{
285038fd1498Szrj 		  mask = wi::lshift (mask, m);
285138fd1498Szrj 		  lowi = build_zero_cst (TREE_TYPE (lowi));
285238fd1498Szrj 		}
285338fd1498Szrj 	    }
285438fd1498Szrj 
285538fd1498Szrj 	  tree tem = build_range_check (loc, optype, unshare_expr (exp),
285638fd1498Szrj 					false, lowi, high);
285738fd1498Szrj 	  if (tem == NULL_TREE || is_gimple_val (tem))
285838fd1498Szrj 	    continue;
285938fd1498Szrj 	  tree etype = unsigned_type_for (TREE_TYPE (exp));
286038fd1498Szrj 	  exp = fold_build2_loc (loc, MINUS_EXPR, etype,
286138fd1498Szrj 				 fold_convert_loc (loc, etype, exp),
286238fd1498Szrj 				 fold_convert_loc (loc, etype, lowi));
286338fd1498Szrj 	  exp = fold_convert_loc (loc, integer_type_node, exp);
286438fd1498Szrj 	  tree word_type = lang_hooks.types.type_for_mode (word_mode, 1);
286538fd1498Szrj 	  exp = fold_build2_loc (loc, LSHIFT_EXPR, word_type,
286638fd1498Szrj 				 build_int_cst (word_type, 1), exp);
286738fd1498Szrj 	  exp = fold_build2_loc (loc, BIT_AND_EXPR, word_type, exp,
286838fd1498Szrj 				 wide_int_to_tree (word_type, mask));
286938fd1498Szrj 	  exp = fold_build2_loc (loc, EQ_EXPR, optype, exp,
287038fd1498Szrj 				 build_zero_cst (word_type));
287138fd1498Szrj 	  if (is_gimple_val (exp))
287238fd1498Szrj 	    continue;
287338fd1498Szrj 
287438fd1498Szrj 	  /* The shift might have undefined behavior if TEM is true,
287538fd1498Szrj 	     but reassociate_bb isn't prepared to have basic blocks
287638fd1498Szrj 	     split when it is running.  So, temporarily emit a code
287738fd1498Szrj 	     with BIT_IOR_EXPR instead of &&, and fix it up in
287838fd1498Szrj 	     branch_fixup.  */
287938fd1498Szrj 	  gimple_seq seq;
288038fd1498Szrj 	  tem = force_gimple_operand (tem, &seq, true, NULL_TREE);
288138fd1498Szrj 	  gcc_assert (TREE_CODE (tem) == SSA_NAME);
288238fd1498Szrj 	  gimple_set_visited (SSA_NAME_DEF_STMT (tem), true);
288338fd1498Szrj 	  gimple_seq seq2;
288438fd1498Szrj 	  exp = force_gimple_operand (exp, &seq2, true, NULL_TREE);
288538fd1498Szrj 	  gimple_seq_add_seq_without_update (&seq, seq2);
288638fd1498Szrj 	  gcc_assert (TREE_CODE (exp) == SSA_NAME);
288738fd1498Szrj 	  gimple_set_visited (SSA_NAME_DEF_STMT (exp), true);
288838fd1498Szrj 	  gimple *g = gimple_build_assign (make_ssa_name (optype),
288938fd1498Szrj 					   BIT_IOR_EXPR, tem, exp);
289038fd1498Szrj 	  gimple_set_location (g, loc);
289138fd1498Szrj 	  gimple_seq_add_stmt_without_update (&seq, g);
289238fd1498Szrj 	  exp = gimple_assign_lhs (g);
289338fd1498Szrj 	  tree val = build_zero_cst (optype);
289438fd1498Szrj 	  if (update_range_test (&ranges[i], NULL, candidates.address (),
289538fd1498Szrj 				 candidates.length (), opcode, ops, exp,
289638fd1498Szrj 				 seq, false, val, val, strict_overflow_p))
289738fd1498Szrj 	    {
289838fd1498Szrj 	      any_changes = true;
289938fd1498Szrj 	      reassoc_branch_fixups.safe_push (tem);
290038fd1498Szrj 	    }
290138fd1498Szrj 	  else
290238fd1498Szrj 	    gimple_seq_discard (seq);
290338fd1498Szrj 	}
290438fd1498Szrj     }
290538fd1498Szrj   return any_changes;
290638fd1498Szrj }
290738fd1498Szrj 
290838fd1498Szrj /* Optimize x != 0 && y != 0 && z != 0 into (x | y | z) != 0
290938fd1498Szrj    and similarly x != -1 && y != -1 && y != -1 into (x & y & z) != -1.  */
291038fd1498Szrj 
291138fd1498Szrj static bool
optimize_range_tests_cmp_bitwise(enum tree_code opcode,int first,int length,vec<operand_entry * > * ops,struct range_entry * ranges)291238fd1498Szrj optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
291338fd1498Szrj 				  vec<operand_entry *> *ops,
291438fd1498Szrj 				  struct range_entry *ranges)
291538fd1498Szrj {
291638fd1498Szrj   int i;
291738fd1498Szrj   unsigned int b;
291838fd1498Szrj   bool any_changes = false;
291938fd1498Szrj   auto_vec<int, 128> buckets;
292038fd1498Szrj   auto_vec<int, 32> chains;
292138fd1498Szrj   auto_vec<struct range_entry *, 32> candidates;
292238fd1498Szrj 
292338fd1498Szrj   for (i = first; i < length; i++)
292438fd1498Szrj     {
292538fd1498Szrj       if (ranges[i].exp == NULL_TREE
292638fd1498Szrj 	  || TREE_CODE (ranges[i].exp) != SSA_NAME
292738fd1498Szrj 	  || !ranges[i].in_p
292838fd1498Szrj 	  || TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) <= 1
292938fd1498Szrj 	  || TREE_CODE (TREE_TYPE (ranges[i].exp)) == BOOLEAN_TYPE
293038fd1498Szrj 	  || ranges[i].low == NULL_TREE
293138fd1498Szrj 	  || ranges[i].low != ranges[i].high)
293238fd1498Szrj 	continue;
293338fd1498Szrj 
293438fd1498Szrj       bool zero_p = integer_zerop (ranges[i].low);
293538fd1498Szrj       if (!zero_p && !integer_all_onesp (ranges[i].low))
293638fd1498Szrj 	continue;
293738fd1498Szrj 
293838fd1498Szrj       b = TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) * 2 + !zero_p;
293938fd1498Szrj       if (buckets.length () <= b)
294038fd1498Szrj 	buckets.safe_grow_cleared (b + 1);
294138fd1498Szrj       if (chains.length () <= (unsigned) i)
294238fd1498Szrj 	chains.safe_grow (i + 1);
294338fd1498Szrj       chains[i] = buckets[b];
294438fd1498Szrj       buckets[b] = i + 1;
294538fd1498Szrj     }
294638fd1498Szrj 
294738fd1498Szrj   FOR_EACH_VEC_ELT (buckets, b, i)
294838fd1498Szrj     if (i && chains[i - 1])
294938fd1498Szrj       {
295038fd1498Szrj 	int j, k = i;
295138fd1498Szrj 	for (j = chains[i - 1]; j; j = chains[j - 1])
295238fd1498Szrj 	  {
295338fd1498Szrj 	    gimple *gk = SSA_NAME_DEF_STMT (ranges[k - 1].exp);
295438fd1498Szrj 	    gimple *gj = SSA_NAME_DEF_STMT (ranges[j - 1].exp);
295538fd1498Szrj 	    if (reassoc_stmt_dominates_stmt_p (gk, gj))
295638fd1498Szrj 	      k = j;
295738fd1498Szrj 	  }
295838fd1498Szrj 	tree type1 = TREE_TYPE (ranges[k - 1].exp);
295938fd1498Szrj 	tree type2 = NULL_TREE;
296038fd1498Szrj 	bool strict_overflow_p = false;
296138fd1498Szrj 	candidates.truncate (0);
296238fd1498Szrj 	for (j = i; j; j = chains[j - 1])
296338fd1498Szrj 	  {
296438fd1498Szrj 	    tree type = TREE_TYPE (ranges[j - 1].exp);
296538fd1498Szrj 	    strict_overflow_p |= ranges[j - 1].strict_overflow_p;
296638fd1498Szrj 	    if (j == k
296738fd1498Szrj 		|| useless_type_conversion_p (type1, type))
296838fd1498Szrj 	      ;
296938fd1498Szrj 	    else if (type2 == NULL_TREE
297038fd1498Szrj 		     || useless_type_conversion_p (type2, type))
297138fd1498Szrj 	      {
297238fd1498Szrj 		if (type2 == NULL_TREE)
297338fd1498Szrj 		  type2 = type;
297438fd1498Szrj 		candidates.safe_push (&ranges[j - 1]);
297538fd1498Szrj 	      }
297638fd1498Szrj 	  }
297738fd1498Szrj 	unsigned l = candidates.length ();
297838fd1498Szrj 	for (j = i; j; j = chains[j - 1])
297938fd1498Szrj 	  {
298038fd1498Szrj 	    tree type = TREE_TYPE (ranges[j - 1].exp);
298138fd1498Szrj 	    if (j == k)
298238fd1498Szrj 	      continue;
298338fd1498Szrj 	    if (useless_type_conversion_p (type1, type))
298438fd1498Szrj 	      ;
298538fd1498Szrj 	    else if (type2 == NULL_TREE
298638fd1498Szrj 		     || useless_type_conversion_p (type2, type))
298738fd1498Szrj 	      continue;
298838fd1498Szrj 	    candidates.safe_push (&ranges[j - 1]);
298938fd1498Szrj 	  }
299038fd1498Szrj 	gimple_seq seq = NULL;
299138fd1498Szrj 	tree op = NULL_TREE;
299238fd1498Szrj 	unsigned int id;
299338fd1498Szrj 	struct range_entry *r;
299438fd1498Szrj 	candidates.safe_push (&ranges[k - 1]);
299538fd1498Szrj 	FOR_EACH_VEC_ELT (candidates, id, r)
299638fd1498Szrj 	  {
299738fd1498Szrj 	    gimple *g;
299838fd1498Szrj 	    if (id == 0)
299938fd1498Szrj 	      {
300038fd1498Szrj 		op = r->exp;
300138fd1498Szrj 		continue;
300238fd1498Szrj 	      }
300338fd1498Szrj 	    if (id == l)
300438fd1498Szrj 	      {
300538fd1498Szrj 		g = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, op);
300638fd1498Szrj 		gimple_seq_add_stmt_without_update (&seq, g);
300738fd1498Szrj 		op = gimple_assign_lhs (g);
300838fd1498Szrj 	      }
300938fd1498Szrj 	    tree type = TREE_TYPE (r->exp);
301038fd1498Szrj 	    tree exp = r->exp;
301138fd1498Szrj 	    if (id >= l && !useless_type_conversion_p (type1, type))
301238fd1498Szrj 	      {
301338fd1498Szrj 		g = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, exp);
301438fd1498Szrj 		gimple_seq_add_stmt_without_update (&seq, g);
301538fd1498Szrj 		exp = gimple_assign_lhs (g);
301638fd1498Szrj 	      }
301738fd1498Szrj 	    g = gimple_build_assign (make_ssa_name (id >= l ? type1 : type2),
301838fd1498Szrj 				     (b & 1) ? BIT_AND_EXPR : BIT_IOR_EXPR,
301938fd1498Szrj 				     op, exp);
302038fd1498Szrj 	    gimple_seq_add_stmt_without_update (&seq, g);
302138fd1498Szrj 	    op = gimple_assign_lhs (g);
302238fd1498Szrj 	  }
302338fd1498Szrj 	candidates.pop ();
302438fd1498Szrj 	if (update_range_test (&ranges[k - 1], NULL, candidates.address (),
302538fd1498Szrj 			       candidates.length (), opcode, ops, op,
302638fd1498Szrj 			       seq, true, ranges[k - 1].low,
302738fd1498Szrj 			       ranges[k - 1].low, strict_overflow_p))
302838fd1498Szrj 	  any_changes = true;
302938fd1498Szrj 	else
303038fd1498Szrj 	  gimple_seq_discard (seq);
303138fd1498Szrj       }
303238fd1498Szrj 
303338fd1498Szrj   return any_changes;
303438fd1498Szrj }
303538fd1498Szrj 
303638fd1498Szrj /* Attempt to optimize for signed a and b where b is known to be >= 0:
303738fd1498Szrj    a >= 0 && a < b into (unsigned) a < (unsigned) b
303838fd1498Szrj    a >= 0 && a <= b into (unsigned) a <= (unsigned) b  */
303938fd1498Szrj 
304038fd1498Szrj static bool
optimize_range_tests_var_bound(enum tree_code opcode,int first,int length,vec<operand_entry * > * ops,struct range_entry * ranges,basic_block first_bb)304138fd1498Szrj optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
304238fd1498Szrj 				vec<operand_entry *> *ops,
304338fd1498Szrj 				struct range_entry *ranges,
304438fd1498Szrj 				basic_block first_bb)
304538fd1498Szrj {
304638fd1498Szrj   int i;
304738fd1498Szrj   bool any_changes = false;
304838fd1498Szrj   hash_map<tree, int> *map = NULL;
304938fd1498Szrj 
305038fd1498Szrj   for (i = first; i < length; i++)
305138fd1498Szrj     {
305238fd1498Szrj       if (ranges[i].exp == NULL_TREE
305338fd1498Szrj 	  || TREE_CODE (ranges[i].exp) != SSA_NAME
305438fd1498Szrj 	  || !ranges[i].in_p)
305538fd1498Szrj 	continue;
305638fd1498Szrj 
305738fd1498Szrj       tree type = TREE_TYPE (ranges[i].exp);
305838fd1498Szrj       if (!INTEGRAL_TYPE_P (type)
305938fd1498Szrj 	  || TYPE_UNSIGNED (type)
306038fd1498Szrj 	  || ranges[i].low == NULL_TREE
306138fd1498Szrj 	  || !integer_zerop (ranges[i].low)
306238fd1498Szrj 	  || ranges[i].high != NULL_TREE)
306338fd1498Szrj 	continue;
306438fd1498Szrj       /* EXP >= 0 here.  */
306538fd1498Szrj       if (map == NULL)
306638fd1498Szrj 	map = new hash_map <tree, int>;
306738fd1498Szrj       map->put (ranges[i].exp, i);
306838fd1498Szrj     }
306938fd1498Szrj 
307038fd1498Szrj   if (map == NULL)
307138fd1498Szrj     return false;
307238fd1498Szrj 
307338fd1498Szrj   for (i = 0; i < length; i++)
307438fd1498Szrj     {
307538fd1498Szrj       bool in_p = ranges[i].in_p;
307638fd1498Szrj       if (ranges[i].low == NULL_TREE
307738fd1498Szrj 	  || ranges[i].high == NULL_TREE)
307838fd1498Szrj 	continue;
307938fd1498Szrj       if (!integer_zerop (ranges[i].low)
308038fd1498Szrj 	  || !integer_zerop (ranges[i].high))
308138fd1498Szrj 	{
308238fd1498Szrj 	  if (ranges[i].exp
308338fd1498Szrj 	      && TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) == 1
308438fd1498Szrj 	      && TYPE_UNSIGNED (TREE_TYPE (ranges[i].exp))
308538fd1498Szrj 	      && integer_onep (ranges[i].low)
308638fd1498Szrj 	      && integer_onep (ranges[i].high))
308738fd1498Szrj 	    in_p = !in_p;
308838fd1498Szrj 	  else
308938fd1498Szrj 	    continue;
309038fd1498Szrj 	}
309138fd1498Szrj 
309238fd1498Szrj       gimple *stmt;
309338fd1498Szrj       tree_code ccode;
309438fd1498Szrj       tree rhs1, rhs2;
309538fd1498Szrj       if (ranges[i].exp)
309638fd1498Szrj 	{
309738fd1498Szrj 	  if (TREE_CODE (ranges[i].exp) != SSA_NAME)
309838fd1498Szrj 	    continue;
309938fd1498Szrj 	  stmt = SSA_NAME_DEF_STMT (ranges[i].exp);
310038fd1498Szrj 	  if (!is_gimple_assign (stmt))
310138fd1498Szrj 	    continue;
310238fd1498Szrj 	  ccode = gimple_assign_rhs_code (stmt);
310338fd1498Szrj 	  rhs1 = gimple_assign_rhs1 (stmt);
310438fd1498Szrj 	  rhs2 = gimple_assign_rhs2 (stmt);
310538fd1498Szrj 	}
310638fd1498Szrj       else
310738fd1498Szrj 	{
310838fd1498Szrj 	  operand_entry *oe = (*ops)[ranges[i].idx];
310938fd1498Szrj 	  stmt = last_stmt (BASIC_BLOCK_FOR_FN (cfun, oe->id));
311038fd1498Szrj 	  if (gimple_code (stmt) != GIMPLE_COND)
311138fd1498Szrj 	    continue;
311238fd1498Szrj 	  ccode = gimple_cond_code (stmt);
311338fd1498Szrj 	  rhs1 = gimple_cond_lhs (stmt);
311438fd1498Szrj 	  rhs2 = gimple_cond_rhs (stmt);
311538fd1498Szrj 	}
311638fd1498Szrj 
311738fd1498Szrj       if (TREE_CODE (rhs1) != SSA_NAME
311838fd1498Szrj 	  || rhs2 == NULL_TREE
311938fd1498Szrj 	  || TREE_CODE (rhs2) != SSA_NAME)
312038fd1498Szrj 	continue;
312138fd1498Szrj 
312238fd1498Szrj       switch (ccode)
312338fd1498Szrj 	{
312438fd1498Szrj 	case GT_EXPR:
312538fd1498Szrj 	case GE_EXPR:
312638fd1498Szrj 	case LT_EXPR:
312738fd1498Szrj 	case LE_EXPR:
312838fd1498Szrj 	  break;
312938fd1498Szrj 	default:
313038fd1498Szrj 	  continue;
313138fd1498Szrj 	}
313238fd1498Szrj       if (in_p)
313338fd1498Szrj 	ccode = invert_tree_comparison (ccode, false);
313438fd1498Szrj       switch (ccode)
313538fd1498Szrj 	{
313638fd1498Szrj 	case GT_EXPR:
313738fd1498Szrj 	case GE_EXPR:
313838fd1498Szrj 	  std::swap (rhs1, rhs2);
313938fd1498Szrj 	  ccode = swap_tree_comparison (ccode);
314038fd1498Szrj 	  break;
314138fd1498Szrj 	case LT_EXPR:
314238fd1498Szrj 	case LE_EXPR:
314338fd1498Szrj 	  break;
314438fd1498Szrj 	default:
314538fd1498Szrj 	  gcc_unreachable ();
314638fd1498Szrj 	}
314738fd1498Szrj 
314838fd1498Szrj       int *idx = map->get (rhs1);
314938fd1498Szrj       if (idx == NULL)
315038fd1498Szrj 	continue;
315138fd1498Szrj 
315238fd1498Szrj       /* maybe_optimize_range_tests allows statements without side-effects
315338fd1498Szrj 	 in the basic blocks as long as they are consumed in the same bb.
315438fd1498Szrj 	 Make sure rhs2's def stmt is not among them, otherwise we can't
315538fd1498Szrj 	 use safely get_nonzero_bits on it.  E.g. in:
315638fd1498Szrj 	  # RANGE [-83, 1] NONZERO 173
315738fd1498Szrj 	  # k_32 = PHI <k_47(13), k_12(9)>
315838fd1498Szrj 	 ...
315938fd1498Szrj 	  if (k_32 >= 0)
316038fd1498Szrj 	    goto <bb 5>; [26.46%]
316138fd1498Szrj 	  else
316238fd1498Szrj 	    goto <bb 9>; [73.54%]
316338fd1498Szrj 
316438fd1498Szrj 	  <bb 5> [local count: 140323371]:
316538fd1498Szrj 	  # RANGE [0, 1] NONZERO 1
316638fd1498Szrj 	  _5 = (int) k_32;
316738fd1498Szrj 	  # RANGE [0, 4] NONZERO 4
316838fd1498Szrj 	  _21 = _5 << 2;
316938fd1498Szrj 	  # RANGE [0, 4] NONZERO 4
317038fd1498Szrj 	  iftmp.0_44 = (char) _21;
317138fd1498Szrj 	  if (k_32 < iftmp.0_44)
317238fd1498Szrj 	    goto <bb 6>; [84.48%]
317338fd1498Szrj 	  else
317438fd1498Szrj 	    goto <bb 9>; [15.52%]
317538fd1498Szrj 	 the ranges on _5/_21/iftmp.0_44 are flow sensitive, assume that
317638fd1498Szrj 	 k_32 >= 0.  If we'd optimize k_32 >= 0 to true and k_32 < iftmp.0_44
317738fd1498Szrj 	 to (unsigned) k_32 < (unsigned) iftmp.0_44, then we would execute
317838fd1498Szrj 	 those stmts even for negative k_32 and the value ranges would be no
317938fd1498Szrj 	 longer guaranteed and so the optimization would be invalid.  */
318038fd1498Szrj       if (opcode == ERROR_MARK)
318138fd1498Szrj 	{
318238fd1498Szrj 	  gimple *g = SSA_NAME_DEF_STMT (rhs2);
318338fd1498Szrj 	  basic_block bb2 = gimple_bb (g);
318438fd1498Szrj 	  if (bb2
318538fd1498Szrj 	      && bb2 != first_bb
318638fd1498Szrj 	      && dominated_by_p (CDI_DOMINATORS, bb2, first_bb))
318738fd1498Szrj 	    {
318838fd1498Szrj 	      /* As an exception, handle a few common cases.  */
318938fd1498Szrj 	      if (gimple_assign_cast_p (g)
319038fd1498Szrj 		  && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (g)))
319138fd1498Szrj 		  && TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)))
319238fd1498Szrj 		  && (TYPE_PRECISION (TREE_TYPE (rhs2))
319338fd1498Szrj 		      > TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (g)))))
319438fd1498Szrj 		/* Zero-extension is always ok.  */ ;
319538fd1498Szrj 	      else if (is_gimple_assign (g)
319638fd1498Szrj 		       && gimple_assign_rhs_code (g) == BIT_AND_EXPR
319738fd1498Szrj 		       && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
319838fd1498Szrj 		       && !wi::neg_p (wi::to_wide (gimple_assign_rhs2 (g))))
319938fd1498Szrj 		/* Masking with INTEGER_CST with MSB clear is always ok
320038fd1498Szrj 		   too.  */ ;
320138fd1498Szrj 	      else
320238fd1498Szrj 		continue;
320338fd1498Szrj 	    }
320438fd1498Szrj 	}
320538fd1498Szrj 
320638fd1498Szrj       wide_int nz = get_nonzero_bits (rhs2);
320738fd1498Szrj       if (wi::neg_p (nz))
320838fd1498Szrj 	continue;
320938fd1498Szrj 
321038fd1498Szrj       /* We have EXP < RHS2 or EXP <= RHS2 where EXP >= 0
321138fd1498Szrj 	 and RHS2 is known to be RHS2 >= 0.  */
321238fd1498Szrj       tree utype = unsigned_type_for (TREE_TYPE (rhs1));
321338fd1498Szrj 
321438fd1498Szrj       enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON;
321538fd1498Szrj       if ((ranges[*idx].strict_overflow_p
321638fd1498Szrj 	   || ranges[i].strict_overflow_p)
321738fd1498Szrj 	  && issue_strict_overflow_warning (wc))
321838fd1498Szrj 	warning_at (gimple_location (stmt), OPT_Wstrict_overflow,
321938fd1498Szrj 		    "assuming signed overflow does not occur "
322038fd1498Szrj 		    "when simplifying range test");
322138fd1498Szrj 
322238fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
322338fd1498Szrj 	{
322438fd1498Szrj 	  struct range_entry *r = &ranges[*idx];
322538fd1498Szrj 	  fprintf (dump_file, "Optimizing range test ");
322638fd1498Szrj 	  print_generic_expr (dump_file, r->exp);
322738fd1498Szrj 	  fprintf (dump_file, " +[");
322838fd1498Szrj 	  print_generic_expr (dump_file, r->low);
322938fd1498Szrj 	  fprintf (dump_file, ", ");
323038fd1498Szrj 	  print_generic_expr (dump_file, r->high);
323138fd1498Szrj 	  fprintf (dump_file, "] and comparison ");
323238fd1498Szrj 	  print_generic_expr (dump_file, rhs1);
323338fd1498Szrj 	  fprintf (dump_file, " %s ", op_symbol_code (ccode));
323438fd1498Szrj 	  print_generic_expr (dump_file, rhs2);
323538fd1498Szrj 	  fprintf (dump_file, "\n into (");
323638fd1498Szrj 	  print_generic_expr (dump_file, utype);
323738fd1498Szrj 	  fprintf (dump_file, ") ");
323838fd1498Szrj 	  print_generic_expr (dump_file, rhs1);
323938fd1498Szrj 	  fprintf (dump_file, " %s (", op_symbol_code (ccode));
324038fd1498Szrj 	  print_generic_expr (dump_file, utype);
324138fd1498Szrj 	  fprintf (dump_file, ") ");
324238fd1498Szrj 	  print_generic_expr (dump_file, rhs2);
324338fd1498Szrj 	  fprintf (dump_file, "\n");
324438fd1498Szrj 	}
324538fd1498Szrj 
324638fd1498Szrj       operand_entry *oe = (*ops)[ranges[i].idx];
324738fd1498Szrj       ranges[i].in_p = 0;
324838fd1498Szrj       if (opcode == BIT_IOR_EXPR
324938fd1498Szrj 	  || (opcode == ERROR_MARK && oe->rank == BIT_IOR_EXPR))
325038fd1498Szrj 	{
325138fd1498Szrj 	  ranges[i].in_p = 1;
325238fd1498Szrj 	  ccode = invert_tree_comparison (ccode, false);
325338fd1498Szrj 	}
325438fd1498Szrj 
325538fd1498Szrj       unsigned int uid = gimple_uid (stmt);
325638fd1498Szrj       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
325738fd1498Szrj       gimple *g = gimple_build_assign (make_ssa_name (utype), NOP_EXPR, rhs1);
325838fd1498Szrj       gimple_set_uid (g, uid);
325938fd1498Szrj       rhs1 = gimple_assign_lhs (g);
326038fd1498Szrj       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
326138fd1498Szrj       g = gimple_build_assign (make_ssa_name (utype), NOP_EXPR, rhs2);
326238fd1498Szrj       gimple_set_uid (g, uid);
326338fd1498Szrj       rhs2 = gimple_assign_lhs (g);
326438fd1498Szrj       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
326538fd1498Szrj       if (tree_swap_operands_p (rhs1, rhs2))
326638fd1498Szrj 	{
326738fd1498Szrj 	  std::swap (rhs1, rhs2);
326838fd1498Szrj 	  ccode = swap_tree_comparison (ccode);
326938fd1498Szrj 	}
327038fd1498Szrj       if (gimple_code (stmt) == GIMPLE_COND)
327138fd1498Szrj 	{
327238fd1498Szrj 	  gcond *c = as_a <gcond *> (stmt);
327338fd1498Szrj 	  gimple_cond_set_code (c, ccode);
327438fd1498Szrj 	  gimple_cond_set_lhs (c, rhs1);
327538fd1498Szrj 	  gimple_cond_set_rhs (c, rhs2);
327638fd1498Szrj 	  update_stmt (stmt);
327738fd1498Szrj 	}
327838fd1498Szrj       else
327938fd1498Szrj 	{
328038fd1498Szrj 	  tree ctype = oe->op ? TREE_TYPE (oe->op) : boolean_type_node;
328138fd1498Szrj 	  if (!INTEGRAL_TYPE_P (ctype)
328238fd1498Szrj 	      || (TREE_CODE (ctype) != BOOLEAN_TYPE
328338fd1498Szrj 		  && TYPE_PRECISION (ctype) != 1))
328438fd1498Szrj 	    ctype = boolean_type_node;
328538fd1498Szrj 	  g = gimple_build_assign (make_ssa_name (ctype), ccode, rhs1, rhs2);
328638fd1498Szrj 	  gimple_set_uid (g, uid);
328738fd1498Szrj 	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
328838fd1498Szrj 	  if (oe->op && ctype != TREE_TYPE (oe->op))
328938fd1498Szrj 	    {
329038fd1498Szrj 	      g = gimple_build_assign (make_ssa_name (TREE_TYPE (oe->op)),
329138fd1498Szrj 				       NOP_EXPR, gimple_assign_lhs (g));
329238fd1498Szrj 	      gimple_set_uid (g, uid);
329338fd1498Szrj 	      gsi_insert_before (&gsi, g, GSI_SAME_STMT);
329438fd1498Szrj 	    }
329538fd1498Szrj 	  ranges[i].exp = gimple_assign_lhs (g);
329638fd1498Szrj 	  oe->op = ranges[i].exp;
329738fd1498Szrj 	  ranges[i].low = build_zero_cst (TREE_TYPE (ranges[i].exp));
329838fd1498Szrj 	  ranges[i].high = ranges[i].low;
329938fd1498Szrj 	}
330038fd1498Szrj       ranges[i].strict_overflow_p = false;
330138fd1498Szrj       oe = (*ops)[ranges[*idx].idx];
330238fd1498Szrj       /* Now change all the other range test immediate uses, so that
330338fd1498Szrj 	 those tests will be optimized away.  */
330438fd1498Szrj       if (opcode == ERROR_MARK)
330538fd1498Szrj 	{
330638fd1498Szrj 	  if (oe->op)
330738fd1498Szrj 	    oe->op = build_int_cst (TREE_TYPE (oe->op),
330838fd1498Szrj 				    oe->rank == BIT_IOR_EXPR ? 0 : 1);
330938fd1498Szrj 	  else
331038fd1498Szrj 	    oe->op = (oe->rank == BIT_IOR_EXPR
331138fd1498Szrj 		      ? boolean_false_node : boolean_true_node);
331238fd1498Szrj 	}
331338fd1498Szrj       else
331438fd1498Szrj 	oe->op = error_mark_node;
331538fd1498Szrj       ranges[*idx].exp = NULL_TREE;
331638fd1498Szrj       ranges[*idx].low = NULL_TREE;
331738fd1498Szrj       ranges[*idx].high = NULL_TREE;
331838fd1498Szrj       any_changes = true;
331938fd1498Szrj     }
332038fd1498Szrj 
332138fd1498Szrj   delete map;
332238fd1498Szrj   return any_changes;
332338fd1498Szrj }
332438fd1498Szrj 
332538fd1498Szrj /* Optimize range tests, similarly how fold_range_test optimizes
332638fd1498Szrj    it on trees.  The tree code for the binary
332738fd1498Szrj    operation between all the operands is OPCODE.
332838fd1498Szrj    If OPCODE is ERROR_MARK, optimize_range_tests is called from within
332938fd1498Szrj    maybe_optimize_range_tests for inter-bb range optimization.
333038fd1498Szrj    In that case if oe->op is NULL, oe->id is bb->index whose
333138fd1498Szrj    GIMPLE_COND is && or ||ed into the test, and oe->rank says
333238fd1498Szrj    the actual opcode.
333338fd1498Szrj    FIRST_BB is the first basic block if OPCODE is ERROR_MARK.  */
333438fd1498Szrj 
333538fd1498Szrj static bool
optimize_range_tests(enum tree_code opcode,vec<operand_entry * > * ops,basic_block first_bb)333638fd1498Szrj optimize_range_tests (enum tree_code opcode,
333738fd1498Szrj 		      vec<operand_entry *> *ops, basic_block first_bb)
333838fd1498Szrj {
333938fd1498Szrj   unsigned int length = ops->length (), i, j, first;
334038fd1498Szrj   operand_entry *oe;
334138fd1498Szrj   struct range_entry *ranges;
334238fd1498Szrj   bool any_changes = false;
334338fd1498Szrj 
334438fd1498Szrj   if (length == 1)
334538fd1498Szrj     return false;
334638fd1498Szrj 
334738fd1498Szrj   ranges = XNEWVEC (struct range_entry, length);
334838fd1498Szrj   for (i = 0; i < length; i++)
334938fd1498Szrj     {
335038fd1498Szrj       oe = (*ops)[i];
335138fd1498Szrj       ranges[i].idx = i;
335238fd1498Szrj       init_range_entry (ranges + i, oe->op,
335338fd1498Szrj 			oe->op
335438fd1498Szrj 			? NULL
335538fd1498Szrj 			: last_stmt (BASIC_BLOCK_FOR_FN (cfun, oe->id)));
335638fd1498Szrj       /* For | invert it now, we will invert it again before emitting
335738fd1498Szrj 	 the optimized expression.  */
335838fd1498Szrj       if (opcode == BIT_IOR_EXPR
335938fd1498Szrj 	  || (opcode == ERROR_MARK && oe->rank == BIT_IOR_EXPR))
336038fd1498Szrj 	ranges[i].in_p = !ranges[i].in_p;
336138fd1498Szrj     }
336238fd1498Szrj 
336338fd1498Szrj   qsort (ranges, length, sizeof (*ranges), range_entry_cmp);
336438fd1498Szrj   for (i = 0; i < length; i++)
336538fd1498Szrj     if (ranges[i].exp != NULL_TREE && TREE_CODE (ranges[i].exp) == SSA_NAME)
336638fd1498Szrj       break;
336738fd1498Szrj 
336838fd1498Szrj   /* Try to merge ranges.  */
336938fd1498Szrj   for (first = i; i < length; i++)
337038fd1498Szrj     {
337138fd1498Szrj       tree low = ranges[i].low;
337238fd1498Szrj       tree high = ranges[i].high;
337338fd1498Szrj       int in_p = ranges[i].in_p;
337438fd1498Szrj       bool strict_overflow_p = ranges[i].strict_overflow_p;
337538fd1498Szrj       int update_fail_count = 0;
337638fd1498Szrj 
337738fd1498Szrj       for (j = i + 1; j < length; j++)
337838fd1498Szrj 	{
337938fd1498Szrj 	  if (ranges[i].exp != ranges[j].exp)
338038fd1498Szrj 	    break;
338138fd1498Szrj 	  if (!merge_ranges (&in_p, &low, &high, in_p, low, high,
338238fd1498Szrj 			     ranges[j].in_p, ranges[j].low, ranges[j].high))
338338fd1498Szrj 	    break;
338438fd1498Szrj 	  strict_overflow_p |= ranges[j].strict_overflow_p;
338538fd1498Szrj 	}
338638fd1498Szrj 
338738fd1498Szrj       if (j == i + 1)
338838fd1498Szrj 	continue;
338938fd1498Szrj 
339038fd1498Szrj       if (update_range_test (ranges + i, ranges + i + 1, NULL, j - i - 1,
339138fd1498Szrj 			     opcode, ops, ranges[i].exp, NULL, in_p,
339238fd1498Szrj 			     low, high, strict_overflow_p))
339338fd1498Szrj 	{
339438fd1498Szrj 	  i = j - 1;
339538fd1498Szrj 	  any_changes = true;
339638fd1498Szrj 	}
339738fd1498Szrj       /* Avoid quadratic complexity if all merge_ranges calls would succeed,
339838fd1498Szrj 	 while update_range_test would fail.  */
339938fd1498Szrj       else if (update_fail_count == 64)
340038fd1498Szrj 	i = j - 1;
340138fd1498Szrj       else
340238fd1498Szrj 	++update_fail_count;
340338fd1498Szrj     }
340438fd1498Szrj 
340538fd1498Szrj   any_changes |= optimize_range_tests_1 (opcode, first, length, true,
340638fd1498Szrj 					 ops, ranges);
340738fd1498Szrj 
340838fd1498Szrj   if (BRANCH_COST (optimize_function_for_speed_p (cfun), false) >= 2)
340938fd1498Szrj     any_changes |= optimize_range_tests_1 (opcode, first, length, false,
341038fd1498Szrj 					   ops, ranges);
341138fd1498Szrj   if (lshift_cheap_p (optimize_function_for_speed_p (cfun)))
341238fd1498Szrj     any_changes |= optimize_range_tests_to_bit_test (opcode, first, length,
341338fd1498Szrj 						     ops, ranges);
341438fd1498Szrj   any_changes |= optimize_range_tests_cmp_bitwise (opcode, first, length,
341538fd1498Szrj 						   ops, ranges);
341638fd1498Szrj   any_changes |= optimize_range_tests_var_bound (opcode, first, length, ops,
341738fd1498Szrj 						 ranges, first_bb);
341838fd1498Szrj 
341938fd1498Szrj   if (any_changes && opcode != ERROR_MARK)
342038fd1498Szrj     {
342138fd1498Szrj       j = 0;
342238fd1498Szrj       FOR_EACH_VEC_ELT (*ops, i, oe)
342338fd1498Szrj 	{
342438fd1498Szrj 	  if (oe->op == error_mark_node)
342538fd1498Szrj 	    continue;
342638fd1498Szrj 	  else if (i != j)
342738fd1498Szrj 	    (*ops)[j] = oe;
342838fd1498Szrj 	  j++;
342938fd1498Szrj 	}
343038fd1498Szrj       ops->truncate (j);
343138fd1498Szrj     }
343238fd1498Szrj 
343338fd1498Szrj   XDELETEVEC (ranges);
343438fd1498Szrj   return any_changes;
343538fd1498Szrj }
343638fd1498Szrj 
343738fd1498Szrj /* A subroutine of optimize_vec_cond_expr to extract and canonicalize
343838fd1498Szrj    the operands of the VEC_COND_EXPR.  Returns ERROR_MARK on failure,
343938fd1498Szrj    otherwise the comparison code.  */
344038fd1498Szrj 
344138fd1498Szrj static tree_code
ovce_extract_ops(tree var,gassign ** rets,bool * reti)344238fd1498Szrj ovce_extract_ops (tree var, gassign **rets, bool *reti)
344338fd1498Szrj {
344438fd1498Szrj   if (TREE_CODE (var) != SSA_NAME)
344538fd1498Szrj     return ERROR_MARK;
344638fd1498Szrj 
344738fd1498Szrj   gassign *stmt = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (var));
344838fd1498Szrj   if (stmt == NULL)
344938fd1498Szrj     return ERROR_MARK;
345038fd1498Szrj 
345138fd1498Szrj   /* ??? If we start creating more COND_EXPR, we could perform
345238fd1498Szrj      this same optimization with them.	For now, simplify.  */
345338fd1498Szrj   if (gimple_assign_rhs_code (stmt) != VEC_COND_EXPR)
345438fd1498Szrj     return ERROR_MARK;
345538fd1498Szrj 
345638fd1498Szrj   tree cond = gimple_assign_rhs1 (stmt);
345738fd1498Szrj   tree_code cmp = TREE_CODE (cond);
345838fd1498Szrj   if (TREE_CODE_CLASS (cmp) != tcc_comparison)
345938fd1498Szrj     return ERROR_MARK;
346038fd1498Szrj 
346138fd1498Szrj   /* ??? For now, allow only canonical true and false result vectors.
346238fd1498Szrj      We could expand this to other constants should the need arise,
346338fd1498Szrj      but at the moment we don't create them.  */
346438fd1498Szrj   tree t = gimple_assign_rhs2 (stmt);
346538fd1498Szrj   tree f = gimple_assign_rhs3 (stmt);
346638fd1498Szrj   bool inv;
346738fd1498Szrj   if (integer_all_onesp (t))
346838fd1498Szrj     inv = false;
346938fd1498Szrj   else if (integer_all_onesp (f))
347038fd1498Szrj     {
347138fd1498Szrj       cmp = invert_tree_comparison (cmp, false);
347238fd1498Szrj       inv = true;
347338fd1498Szrj     }
347438fd1498Szrj   else
347538fd1498Szrj     return ERROR_MARK;
347638fd1498Szrj   if (!integer_zerop (f))
347738fd1498Szrj     return ERROR_MARK;
347838fd1498Szrj 
347938fd1498Szrj   /* Success!  */
348038fd1498Szrj   if (rets)
348138fd1498Szrj     *rets = stmt;
348238fd1498Szrj   if (reti)
348338fd1498Szrj     *reti = inv;
348438fd1498Szrj   return cmp;
348538fd1498Szrj }
348638fd1498Szrj 
348738fd1498Szrj /* Optimize the condition of VEC_COND_EXPRs which have been combined
348838fd1498Szrj    with OPCODE (either BIT_AND_EXPR or BIT_IOR_EXPR).  */
348938fd1498Szrj 
349038fd1498Szrj static bool
optimize_vec_cond_expr(tree_code opcode,vec<operand_entry * > * ops)349138fd1498Szrj optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops)
349238fd1498Szrj {
349338fd1498Szrj   unsigned int length = ops->length (), i, j;
349438fd1498Szrj   bool any_changes = false;
349538fd1498Szrj 
349638fd1498Szrj   if (length == 1)
349738fd1498Szrj     return false;
349838fd1498Szrj 
349938fd1498Szrj   for (i = 0; i < length; ++i)
350038fd1498Szrj     {
350138fd1498Szrj       tree elt0 = (*ops)[i]->op;
350238fd1498Szrj 
350338fd1498Szrj       gassign *stmt0;
350438fd1498Szrj       bool invert;
350538fd1498Szrj       tree_code cmp0 = ovce_extract_ops (elt0, &stmt0, &invert);
350638fd1498Szrj       if (cmp0 == ERROR_MARK)
350738fd1498Szrj 	continue;
350838fd1498Szrj 
350938fd1498Szrj       for (j = i + 1; j < length; ++j)
351038fd1498Szrj 	{
351138fd1498Szrj 	  tree &elt1 = (*ops)[j]->op;
351238fd1498Szrj 
351338fd1498Szrj 	  gassign *stmt1;
351438fd1498Szrj 	  tree_code cmp1 = ovce_extract_ops (elt1, &stmt1, NULL);
351538fd1498Szrj 	  if (cmp1 == ERROR_MARK)
351638fd1498Szrj 	    continue;
351738fd1498Szrj 
351838fd1498Szrj 	  tree cond0 = gimple_assign_rhs1 (stmt0);
351938fd1498Szrj 	  tree x0 = TREE_OPERAND (cond0, 0);
352038fd1498Szrj 	  tree y0 = TREE_OPERAND (cond0, 1);
352138fd1498Szrj 
352238fd1498Szrj 	  tree cond1 = gimple_assign_rhs1 (stmt1);
352338fd1498Szrj 	  tree x1 = TREE_OPERAND (cond1, 0);
352438fd1498Szrj 	  tree y1 = TREE_OPERAND (cond1, 1);
352538fd1498Szrj 
352638fd1498Szrj 	  tree comb;
352738fd1498Szrj 	  if (opcode == BIT_AND_EXPR)
352838fd1498Szrj 	    comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1);
352938fd1498Szrj 	  else if (opcode == BIT_IOR_EXPR)
353038fd1498Szrj 	    comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1);
353138fd1498Szrj 	  else
353238fd1498Szrj 	    gcc_unreachable ();
353338fd1498Szrj 	  if (comb == NULL)
353438fd1498Szrj 	    continue;
353538fd1498Szrj 
353638fd1498Szrj 	  /* Success! */
353738fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
353838fd1498Szrj 	    {
353938fd1498Szrj 	      fprintf (dump_file, "Transforming ");
354038fd1498Szrj 	      print_generic_expr (dump_file, cond0);
354138fd1498Szrj 	      fprintf (dump_file, " %c ", opcode == BIT_AND_EXPR ? '&' : '|');
354238fd1498Szrj 	      print_generic_expr (dump_file, cond1);
354338fd1498Szrj 	      fprintf (dump_file, " into ");
354438fd1498Szrj 	      print_generic_expr (dump_file, comb);
354538fd1498Szrj 	      fputc ('\n', dump_file);
354638fd1498Szrj 	    }
354738fd1498Szrj 
354838fd1498Szrj 	  gimple_assign_set_rhs1 (stmt0, comb);
354938fd1498Szrj 	  if (invert)
355038fd1498Szrj 	    std::swap (*gimple_assign_rhs2_ptr (stmt0),
355138fd1498Szrj 		       *gimple_assign_rhs3_ptr (stmt0));
355238fd1498Szrj 	  update_stmt (stmt0);
355338fd1498Szrj 
355438fd1498Szrj 	  elt1 = error_mark_node;
355538fd1498Szrj 	  any_changes = true;
355638fd1498Szrj 	}
355738fd1498Szrj     }
355838fd1498Szrj 
355938fd1498Szrj   if (any_changes)
356038fd1498Szrj     {
356138fd1498Szrj       operand_entry *oe;
356238fd1498Szrj       j = 0;
356338fd1498Szrj       FOR_EACH_VEC_ELT (*ops, i, oe)
356438fd1498Szrj 	{
356538fd1498Szrj 	  if (oe->op == error_mark_node)
356638fd1498Szrj 	    continue;
356738fd1498Szrj 	  else if (i != j)
356838fd1498Szrj 	    (*ops)[j] = oe;
356938fd1498Szrj 	  j++;
357038fd1498Szrj 	}
357138fd1498Szrj       ops->truncate (j);
357238fd1498Szrj     }
357338fd1498Szrj 
357438fd1498Szrj   return any_changes;
357538fd1498Szrj }
357638fd1498Szrj 
357738fd1498Szrj /* Return true if STMT is a cast like:
357838fd1498Szrj    <bb N>:
357938fd1498Szrj    ...
358038fd1498Szrj    _123 = (int) _234;
358138fd1498Szrj 
358238fd1498Szrj    <bb M>:
358338fd1498Szrj    # _345 = PHI <_123(N), 1(...), 1(...)>
358438fd1498Szrj    where _234 has bool type, _123 has single use and
358538fd1498Szrj    bb N has a single successor M.  This is commonly used in
358638fd1498Szrj    the last block of a range test.
358738fd1498Szrj 
358838fd1498Szrj    Also Return true if STMT is tcc_compare like:
358938fd1498Szrj    <bb N>:
359038fd1498Szrj    ...
359138fd1498Szrj    _234 = a_2(D) == 2;
359238fd1498Szrj 
359338fd1498Szrj    <bb M>:
359438fd1498Szrj    # _345 = PHI <_234(N), 1(...), 1(...)>
359538fd1498Szrj    _346 = (int) _345;
359638fd1498Szrj    where _234 has booltype, single use and
359738fd1498Szrj    bb N has a single successor M.  This is commonly used in
359838fd1498Szrj    the last block of a range test.  */
359938fd1498Szrj 
360038fd1498Szrj static bool
final_range_test_p(gimple * stmt)360138fd1498Szrj final_range_test_p (gimple *stmt)
360238fd1498Szrj {
360338fd1498Szrj   basic_block bb, rhs_bb, lhs_bb;
360438fd1498Szrj   edge e;
360538fd1498Szrj   tree lhs, rhs;
360638fd1498Szrj   use_operand_p use_p;
360738fd1498Szrj   gimple *use_stmt;
360838fd1498Szrj 
360938fd1498Szrj   if (!gimple_assign_cast_p (stmt)
361038fd1498Szrj       && (!is_gimple_assign (stmt)
361138fd1498Szrj 	  || (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
361238fd1498Szrj 	      != tcc_comparison)))
361338fd1498Szrj     return false;
361438fd1498Szrj   bb = gimple_bb (stmt);
361538fd1498Szrj   if (!single_succ_p (bb))
361638fd1498Szrj     return false;
361738fd1498Szrj   e = single_succ_edge (bb);
361838fd1498Szrj   if (e->flags & EDGE_COMPLEX)
361938fd1498Szrj     return false;
362038fd1498Szrj 
362138fd1498Szrj   lhs = gimple_assign_lhs (stmt);
362238fd1498Szrj   rhs = gimple_assign_rhs1 (stmt);
362338fd1498Szrj   if (gimple_assign_cast_p (stmt)
362438fd1498Szrj       && (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
362538fd1498Szrj 	  || TREE_CODE (rhs) != SSA_NAME
362638fd1498Szrj 	  || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE))
362738fd1498Szrj     return false;
362838fd1498Szrj 
362938fd1498Szrj   if (!gimple_assign_cast_p (stmt)
363038fd1498Szrj       && (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE))
363138fd1498Szrj       return false;
363238fd1498Szrj 
363338fd1498Szrj   /* Test whether lhs is consumed only by a PHI in the only successor bb.  */
363438fd1498Szrj   if (!single_imm_use (lhs, &use_p, &use_stmt))
363538fd1498Szrj     return false;
363638fd1498Szrj 
363738fd1498Szrj   if (gimple_code (use_stmt) != GIMPLE_PHI
363838fd1498Szrj       || gimple_bb (use_stmt) != e->dest)
363938fd1498Szrj     return false;
364038fd1498Szrj 
364138fd1498Szrj   /* And that the rhs is defined in the same loop.  */
364238fd1498Szrj   if (gimple_assign_cast_p (stmt))
364338fd1498Szrj     {
364438fd1498Szrj       if (TREE_CODE (rhs) != SSA_NAME
364538fd1498Szrj 	  || !(rhs_bb = gimple_bb (SSA_NAME_DEF_STMT (rhs)))
364638fd1498Szrj 	  || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), rhs_bb))
364738fd1498Szrj 	return false;
364838fd1498Szrj     }
364938fd1498Szrj   else
365038fd1498Szrj     {
365138fd1498Szrj       if (TREE_CODE (lhs) != SSA_NAME
365238fd1498Szrj 	  || !(lhs_bb = gimple_bb (SSA_NAME_DEF_STMT (lhs)))
365338fd1498Szrj 	  || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), lhs_bb))
365438fd1498Szrj 	return false;
365538fd1498Szrj     }
365638fd1498Szrj 
365738fd1498Szrj   return true;
365838fd1498Szrj }
365938fd1498Szrj 
366038fd1498Szrj /* Return true if BB is suitable basic block for inter-bb range test
366138fd1498Szrj    optimization.  If BACKWARD is true, BB should be the only predecessor
366238fd1498Szrj    of TEST_BB, and *OTHER_BB is either NULL and filled by the routine,
366338fd1498Szrj    or compared with to find a common basic block to which all conditions
366438fd1498Szrj    branch to if true resp. false.  If BACKWARD is false, TEST_BB should
366538fd1498Szrj    be the only predecessor of BB.  */
366638fd1498Szrj 
366738fd1498Szrj static bool
suitable_cond_bb(basic_block bb,basic_block test_bb,basic_block * other_bb,bool backward)366838fd1498Szrj suitable_cond_bb (basic_block bb, basic_block test_bb, basic_block *other_bb,
366938fd1498Szrj 		  bool backward)
367038fd1498Szrj {
367138fd1498Szrj   edge_iterator ei, ei2;
367238fd1498Szrj   edge e, e2;
367338fd1498Szrj   gimple *stmt;
367438fd1498Szrj   gphi_iterator gsi;
367538fd1498Szrj   bool other_edge_seen = false;
367638fd1498Szrj   bool is_cond;
367738fd1498Szrj 
367838fd1498Szrj   if (test_bb == bb)
367938fd1498Szrj     return false;
368038fd1498Szrj   /* Check last stmt first.  */
368138fd1498Szrj   stmt = last_stmt (bb);
368238fd1498Szrj   if (stmt == NULL
368338fd1498Szrj       || (gimple_code (stmt) != GIMPLE_COND
368438fd1498Szrj 	  && (backward || !final_range_test_p (stmt)))
368538fd1498Szrj       || gimple_visited_p (stmt)
368638fd1498Szrj       || stmt_could_throw_p (stmt)
368738fd1498Szrj       || *other_bb == bb)
368838fd1498Szrj     return false;
368938fd1498Szrj   is_cond = gimple_code (stmt) == GIMPLE_COND;
369038fd1498Szrj   if (is_cond)
369138fd1498Szrj     {
369238fd1498Szrj       /* If last stmt is GIMPLE_COND, verify that one of the succ edges
369338fd1498Szrj 	 goes to the next bb (if BACKWARD, it is TEST_BB), and the other
369438fd1498Szrj 	 to *OTHER_BB (if not set yet, try to find it out).  */
369538fd1498Szrj       if (EDGE_COUNT (bb->succs) != 2)
369638fd1498Szrj 	return false;
369738fd1498Szrj       FOR_EACH_EDGE (e, ei, bb->succs)
369838fd1498Szrj 	{
369938fd1498Szrj 	  if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
370038fd1498Szrj 	    return false;
370138fd1498Szrj 	  if (e->dest == test_bb)
370238fd1498Szrj 	    {
370338fd1498Szrj 	      if (backward)
370438fd1498Szrj 		continue;
370538fd1498Szrj 	      else
370638fd1498Szrj 		return false;
370738fd1498Szrj 	    }
370838fd1498Szrj 	  if (e->dest == bb)
370938fd1498Szrj 	    return false;
371038fd1498Szrj 	  if (*other_bb == NULL)
371138fd1498Szrj 	    {
371238fd1498Szrj 	      FOR_EACH_EDGE (e2, ei2, test_bb->succs)
371338fd1498Szrj 		if (!(e2->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
371438fd1498Szrj 		  return false;
371538fd1498Szrj 		else if (e->dest == e2->dest)
371638fd1498Szrj 		  *other_bb = e->dest;
371738fd1498Szrj 	      if (*other_bb == NULL)
371838fd1498Szrj 		return false;
371938fd1498Szrj 	    }
372038fd1498Szrj 	  if (e->dest == *other_bb)
372138fd1498Szrj 	    other_edge_seen = true;
372238fd1498Szrj 	  else if (backward)
372338fd1498Szrj 	    return false;
372438fd1498Szrj 	}
372538fd1498Szrj       if (*other_bb == NULL || !other_edge_seen)
372638fd1498Szrj 	return false;
372738fd1498Szrj     }
372838fd1498Szrj   else if (single_succ (bb) != *other_bb)
372938fd1498Szrj     return false;
373038fd1498Szrj 
373138fd1498Szrj   /* Now check all PHIs of *OTHER_BB.  */
373238fd1498Szrj   e = find_edge (bb, *other_bb);
373338fd1498Szrj   e2 = find_edge (test_bb, *other_bb);
373438fd1498Szrj   for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
373538fd1498Szrj     {
373638fd1498Szrj       gphi *phi = gsi.phi ();
373738fd1498Szrj       /* If both BB and TEST_BB end with GIMPLE_COND, all PHI arguments
373838fd1498Szrj 	 corresponding to BB and TEST_BB predecessor must be the same.  */
373938fd1498Szrj       if (!operand_equal_p (gimple_phi_arg_def (phi, e->dest_idx),
374038fd1498Szrj 			    gimple_phi_arg_def (phi, e2->dest_idx), 0))
374138fd1498Szrj 	{
374238fd1498Szrj 	  /* Otherwise, if one of the blocks doesn't end with GIMPLE_COND,
374338fd1498Szrj 	     one of the PHIs should have the lhs of the last stmt in
374438fd1498Szrj 	     that block as PHI arg and that PHI should have 0 or 1
374538fd1498Szrj 	     corresponding to it in all other range test basic blocks
374638fd1498Szrj 	     considered.  */
374738fd1498Szrj 	  if (!is_cond)
374838fd1498Szrj 	    {
374938fd1498Szrj 	      if (gimple_phi_arg_def (phi, e->dest_idx)
375038fd1498Szrj 		  == gimple_assign_lhs (stmt)
375138fd1498Szrj 		  && (integer_zerop (gimple_phi_arg_def (phi, e2->dest_idx))
375238fd1498Szrj 		      || integer_onep (gimple_phi_arg_def (phi,
375338fd1498Szrj 							   e2->dest_idx))))
375438fd1498Szrj 		continue;
375538fd1498Szrj 	    }
375638fd1498Szrj 	  else
375738fd1498Szrj 	    {
375838fd1498Szrj 	      gimple *test_last = last_stmt (test_bb);
375938fd1498Szrj 	      if (gimple_code (test_last) != GIMPLE_COND
376038fd1498Szrj 		  && gimple_phi_arg_def (phi, e2->dest_idx)
376138fd1498Szrj 		     == gimple_assign_lhs (test_last)
376238fd1498Szrj 		  && (integer_zerop (gimple_phi_arg_def (phi, e->dest_idx))
376338fd1498Szrj 		      || integer_onep (gimple_phi_arg_def (phi, e->dest_idx))))
376438fd1498Szrj 		continue;
376538fd1498Szrj 	    }
376638fd1498Szrj 
376738fd1498Szrj 	  return false;
376838fd1498Szrj 	}
376938fd1498Szrj     }
377038fd1498Szrj   return true;
377138fd1498Szrj }
377238fd1498Szrj 
377338fd1498Szrj /* Return true if BB doesn't have side-effects that would disallow
377438fd1498Szrj    range test optimization, all SSA_NAMEs set in the bb are consumed
377538fd1498Szrj    in the bb and there are no PHIs.  */
377638fd1498Szrj 
377738fd1498Szrj static bool
no_side_effect_bb(basic_block bb)377838fd1498Szrj no_side_effect_bb (basic_block bb)
377938fd1498Szrj {
378038fd1498Szrj   gimple_stmt_iterator gsi;
378138fd1498Szrj   gimple *last;
378238fd1498Szrj 
378338fd1498Szrj   if (!gimple_seq_empty_p (phi_nodes (bb)))
378438fd1498Szrj     return false;
378538fd1498Szrj   last = last_stmt (bb);
378638fd1498Szrj   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
378738fd1498Szrj     {
378838fd1498Szrj       gimple *stmt = gsi_stmt (gsi);
378938fd1498Szrj       tree lhs;
379038fd1498Szrj       imm_use_iterator imm_iter;
379138fd1498Szrj       use_operand_p use_p;
379238fd1498Szrj 
379338fd1498Szrj       if (is_gimple_debug (stmt))
379438fd1498Szrj 	continue;
379538fd1498Szrj       if (gimple_has_side_effects (stmt))
379638fd1498Szrj 	return false;
379738fd1498Szrj       if (stmt == last)
379838fd1498Szrj 	return true;
379938fd1498Szrj       if (!is_gimple_assign (stmt))
380038fd1498Szrj 	return false;
380138fd1498Szrj       lhs = gimple_assign_lhs (stmt);
380238fd1498Szrj       if (TREE_CODE (lhs) != SSA_NAME)
380338fd1498Szrj 	return false;
380438fd1498Szrj       if (gimple_assign_rhs_could_trap_p (stmt))
380538fd1498Szrj 	return false;
380638fd1498Szrj       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
380738fd1498Szrj 	{
380838fd1498Szrj 	  gimple *use_stmt = USE_STMT (use_p);
380938fd1498Szrj 	  if (is_gimple_debug (use_stmt))
381038fd1498Szrj 	    continue;
381138fd1498Szrj 	  if (gimple_bb (use_stmt) != bb)
381238fd1498Szrj 	    return false;
381338fd1498Szrj 	}
381438fd1498Szrj     }
381538fd1498Szrj   return false;
381638fd1498Szrj }
381738fd1498Szrj 
381838fd1498Szrj /* If VAR is set by CODE (BIT_{AND,IOR}_EXPR) which is reassociable,
381938fd1498Szrj    return true and fill in *OPS recursively.  */
382038fd1498Szrj 
382138fd1498Szrj static bool
get_ops(tree var,enum tree_code code,vec<operand_entry * > * ops,struct loop * loop)382238fd1498Szrj get_ops (tree var, enum tree_code code, vec<operand_entry *> *ops,
382338fd1498Szrj 	 struct loop *loop)
382438fd1498Szrj {
382538fd1498Szrj   gimple *stmt = SSA_NAME_DEF_STMT (var);
382638fd1498Szrj   tree rhs[2];
382738fd1498Szrj   int i;
382838fd1498Szrj 
382938fd1498Szrj   if (!is_reassociable_op (stmt, code, loop))
383038fd1498Szrj     return false;
383138fd1498Szrj 
383238fd1498Szrj   rhs[0] = gimple_assign_rhs1 (stmt);
383338fd1498Szrj   rhs[1] = gimple_assign_rhs2 (stmt);
383438fd1498Szrj   gimple_set_visited (stmt, true);
383538fd1498Szrj   for (i = 0; i < 2; i++)
383638fd1498Szrj     if (TREE_CODE (rhs[i]) == SSA_NAME
383738fd1498Szrj 	&& !get_ops (rhs[i], code, ops, loop)
383838fd1498Szrj 	&& has_single_use (rhs[i]))
383938fd1498Szrj       {
384038fd1498Szrj 	operand_entry *oe = operand_entry_pool.allocate ();
384138fd1498Szrj 
384238fd1498Szrj 	oe->op = rhs[i];
384338fd1498Szrj 	oe->rank = code;
384438fd1498Szrj 	oe->id = 0;
384538fd1498Szrj 	oe->count = 1;
384638fd1498Szrj 	oe->stmt_to_insert = NULL;
384738fd1498Szrj 	ops->safe_push (oe);
384838fd1498Szrj       }
384938fd1498Szrj   return true;
385038fd1498Szrj }
385138fd1498Szrj 
385238fd1498Szrj /* Find the ops that were added by get_ops starting from VAR, see if
385338fd1498Szrj    they were changed during update_range_test and if yes, create new
385438fd1498Szrj    stmts.  */
385538fd1498Szrj 
385638fd1498Szrj static tree
update_ops(tree var,enum tree_code code,vec<operand_entry * > ops,unsigned int * pidx,struct loop * loop)385738fd1498Szrj update_ops (tree var, enum tree_code code, vec<operand_entry *> ops,
385838fd1498Szrj 	    unsigned int *pidx, struct loop *loop)
385938fd1498Szrj {
386038fd1498Szrj   gimple *stmt = SSA_NAME_DEF_STMT (var);
386138fd1498Szrj   tree rhs[4];
386238fd1498Szrj   int i;
386338fd1498Szrj 
386438fd1498Szrj   if (!is_reassociable_op (stmt, code, loop))
386538fd1498Szrj     return NULL;
386638fd1498Szrj 
386738fd1498Szrj   rhs[0] = gimple_assign_rhs1 (stmt);
386838fd1498Szrj   rhs[1] = gimple_assign_rhs2 (stmt);
386938fd1498Szrj   rhs[2] = rhs[0];
387038fd1498Szrj   rhs[3] = rhs[1];
387138fd1498Szrj   for (i = 0; i < 2; i++)
387238fd1498Szrj     if (TREE_CODE (rhs[i]) == SSA_NAME)
387338fd1498Szrj       {
387438fd1498Szrj 	rhs[2 + i] = update_ops (rhs[i], code, ops, pidx, loop);
387538fd1498Szrj 	if (rhs[2 + i] == NULL_TREE)
387638fd1498Szrj 	  {
387738fd1498Szrj 	    if (has_single_use (rhs[i]))
387838fd1498Szrj 	      rhs[2 + i] = ops[(*pidx)++]->op;
387938fd1498Szrj 	    else
388038fd1498Szrj 	      rhs[2 + i] = rhs[i];
388138fd1498Szrj 	  }
388238fd1498Szrj       }
388338fd1498Szrj   if ((rhs[2] != rhs[0] || rhs[3] != rhs[1])
388438fd1498Szrj       && (rhs[2] != rhs[1] || rhs[3] != rhs[0]))
388538fd1498Szrj     {
388638fd1498Szrj       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
388738fd1498Szrj       var = make_ssa_name (TREE_TYPE (var));
388838fd1498Szrj       gassign *g = gimple_build_assign (var, gimple_assign_rhs_code (stmt),
388938fd1498Szrj 					rhs[2], rhs[3]);
389038fd1498Szrj       gimple_set_uid (g, gimple_uid (stmt));
389138fd1498Szrj       gimple_set_visited (g, true);
389238fd1498Szrj       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
389338fd1498Szrj     }
389438fd1498Szrj   return var;
389538fd1498Szrj }
389638fd1498Szrj 
389738fd1498Szrj /* Structure to track the initial value passed to get_ops and
389838fd1498Szrj    the range in the ops vector for each basic block.  */
389938fd1498Szrj 
390038fd1498Szrj struct inter_bb_range_test_entry
390138fd1498Szrj {
390238fd1498Szrj   tree op;
390338fd1498Szrj   unsigned int first_idx, last_idx;
390438fd1498Szrj };
390538fd1498Szrj 
390638fd1498Szrj /* Inter-bb range test optimization.
390738fd1498Szrj 
390838fd1498Szrj    Returns TRUE if a gimple conditional is optimized to a true/false,
390938fd1498Szrj    otherwise return FALSE.
391038fd1498Szrj 
391138fd1498Szrj    This indicates to the caller that it should run a CFG cleanup pass
391238fd1498Szrj    once reassociation is completed.  */
391338fd1498Szrj 
391438fd1498Szrj static bool
maybe_optimize_range_tests(gimple * stmt)391538fd1498Szrj maybe_optimize_range_tests (gimple *stmt)
391638fd1498Szrj {
391738fd1498Szrj   basic_block first_bb = gimple_bb (stmt);
391838fd1498Szrj   basic_block last_bb = first_bb;
391938fd1498Szrj   basic_block other_bb = NULL;
392038fd1498Szrj   basic_block bb;
392138fd1498Szrj   edge_iterator ei;
392238fd1498Szrj   edge e;
392338fd1498Szrj   auto_vec<operand_entry *> ops;
392438fd1498Szrj   auto_vec<inter_bb_range_test_entry> bbinfo;
392538fd1498Szrj   bool any_changes = false;
392638fd1498Szrj   bool cfg_cleanup_needed = false;
392738fd1498Szrj 
392838fd1498Szrj   /* Consider only basic blocks that end with GIMPLE_COND or
392938fd1498Szrj      a cast statement satisfying final_range_test_p.  All
393038fd1498Szrj      but the last bb in the first_bb .. last_bb range
393138fd1498Szrj      should end with GIMPLE_COND.  */
393238fd1498Szrj   if (gimple_code (stmt) == GIMPLE_COND)
393338fd1498Szrj     {
393438fd1498Szrj       if (EDGE_COUNT (first_bb->succs) != 2)
393538fd1498Szrj 	return cfg_cleanup_needed;
393638fd1498Szrj     }
393738fd1498Szrj   else if (final_range_test_p (stmt))
393838fd1498Szrj     other_bb = single_succ (first_bb);
393938fd1498Szrj   else
394038fd1498Szrj     return cfg_cleanup_needed;
394138fd1498Szrj 
394238fd1498Szrj   if (stmt_could_throw_p (stmt))
394338fd1498Szrj     return cfg_cleanup_needed;
394438fd1498Szrj 
394538fd1498Szrj   /* As relative ordering of post-dominator sons isn't fixed,
394638fd1498Szrj      maybe_optimize_range_tests can be called first on any
394738fd1498Szrj      bb in the range we want to optimize.  So, start searching
394838fd1498Szrj      backwards, if first_bb can be set to a predecessor.  */
394938fd1498Szrj   while (single_pred_p (first_bb))
395038fd1498Szrj     {
395138fd1498Szrj       basic_block pred_bb = single_pred (first_bb);
395238fd1498Szrj       if (!suitable_cond_bb (pred_bb, first_bb, &other_bb, true))
395338fd1498Szrj 	break;
395438fd1498Szrj       if (!no_side_effect_bb (first_bb))
395538fd1498Szrj 	break;
395638fd1498Szrj       first_bb = pred_bb;
395738fd1498Szrj     }
395838fd1498Szrj   /* If first_bb is last_bb, other_bb hasn't been computed yet.
395938fd1498Szrj      Before starting forward search in last_bb successors, find
396038fd1498Szrj      out the other_bb.  */
396138fd1498Szrj   if (first_bb == last_bb)
396238fd1498Szrj     {
396338fd1498Szrj       other_bb = NULL;
396438fd1498Szrj       /* As non-GIMPLE_COND last stmt always terminates the range,
396538fd1498Szrj 	 if forward search didn't discover anything, just give up.  */
396638fd1498Szrj       if (gimple_code (stmt) != GIMPLE_COND)
396738fd1498Szrj 	return cfg_cleanup_needed;
396838fd1498Szrj       /* Look at both successors.  Either it ends with a GIMPLE_COND
396938fd1498Szrj 	 and satisfies suitable_cond_bb, or ends with a cast and
397038fd1498Szrj 	 other_bb is that cast's successor.  */
397138fd1498Szrj       FOR_EACH_EDGE (e, ei, first_bb->succs)
397238fd1498Szrj 	if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))
397338fd1498Szrj 	    || e->dest == first_bb)
397438fd1498Szrj 	  return cfg_cleanup_needed;
397538fd1498Szrj 	else if (single_pred_p (e->dest))
397638fd1498Szrj 	  {
397738fd1498Szrj 	    stmt = last_stmt (e->dest);
397838fd1498Szrj 	    if (stmt
397938fd1498Szrj 		&& gimple_code (stmt) == GIMPLE_COND
398038fd1498Szrj 		&& EDGE_COUNT (e->dest->succs) == 2)
398138fd1498Szrj 	      {
398238fd1498Szrj 		if (suitable_cond_bb (first_bb, e->dest, &other_bb, true))
398338fd1498Szrj 		  break;
398438fd1498Szrj 		else
398538fd1498Szrj 		  other_bb = NULL;
398638fd1498Szrj 	      }
398738fd1498Szrj 	    else if (stmt
398838fd1498Szrj 		     && final_range_test_p (stmt)
398938fd1498Szrj 		     && find_edge (first_bb, single_succ (e->dest)))
399038fd1498Szrj 	      {
399138fd1498Szrj 		other_bb = single_succ (e->dest);
399238fd1498Szrj 		if (other_bb == first_bb)
399338fd1498Szrj 		  other_bb = NULL;
399438fd1498Szrj 	      }
399538fd1498Szrj 	  }
399638fd1498Szrj       if (other_bb == NULL)
399738fd1498Szrj 	return cfg_cleanup_needed;
399838fd1498Szrj     }
399938fd1498Szrj   /* Now do the forward search, moving last_bb to successor bbs
400038fd1498Szrj      that aren't other_bb.  */
400138fd1498Szrj   while (EDGE_COUNT (last_bb->succs) == 2)
400238fd1498Szrj     {
400338fd1498Szrj       FOR_EACH_EDGE (e, ei, last_bb->succs)
400438fd1498Szrj 	if (e->dest != other_bb)
400538fd1498Szrj 	  break;
400638fd1498Szrj       if (e == NULL)
400738fd1498Szrj 	break;
400838fd1498Szrj       if (!single_pred_p (e->dest))
400938fd1498Szrj 	break;
401038fd1498Szrj       if (!suitable_cond_bb (e->dest, last_bb, &other_bb, false))
401138fd1498Szrj 	break;
401238fd1498Szrj       if (!no_side_effect_bb (e->dest))
401338fd1498Szrj 	break;
401438fd1498Szrj       last_bb = e->dest;
401538fd1498Szrj     }
401638fd1498Szrj   if (first_bb == last_bb)
401738fd1498Szrj     return cfg_cleanup_needed;
401838fd1498Szrj   /* Here basic blocks first_bb through last_bb's predecessor
401938fd1498Szrj      end with GIMPLE_COND, all of them have one of the edges to
402038fd1498Szrj      other_bb and another to another block in the range,
402138fd1498Szrj      all blocks except first_bb don't have side-effects and
402238fd1498Szrj      last_bb ends with either GIMPLE_COND, or cast satisfying
402338fd1498Szrj      final_range_test_p.  */
402438fd1498Szrj   for (bb = last_bb; ; bb = single_pred (bb))
402538fd1498Szrj     {
402638fd1498Szrj       enum tree_code code;
402738fd1498Szrj       tree lhs, rhs;
402838fd1498Szrj       inter_bb_range_test_entry bb_ent;
402938fd1498Szrj 
403038fd1498Szrj       bb_ent.op = NULL_TREE;
403138fd1498Szrj       bb_ent.first_idx = ops.length ();
403238fd1498Szrj       bb_ent.last_idx = bb_ent.first_idx;
403338fd1498Szrj       e = find_edge (bb, other_bb);
403438fd1498Szrj       stmt = last_stmt (bb);
403538fd1498Szrj       gimple_set_visited (stmt, true);
403638fd1498Szrj       if (gimple_code (stmt) != GIMPLE_COND)
403738fd1498Szrj 	{
403838fd1498Szrj 	  use_operand_p use_p;
403938fd1498Szrj 	  gimple *phi;
404038fd1498Szrj 	  edge e2;
404138fd1498Szrj 	  unsigned int d;
404238fd1498Szrj 
404338fd1498Szrj 	  lhs = gimple_assign_lhs (stmt);
404438fd1498Szrj 	  rhs = gimple_assign_rhs1 (stmt);
404538fd1498Szrj 	  gcc_assert (bb == last_bb);
404638fd1498Szrj 
404738fd1498Szrj 	  /* stmt is
404838fd1498Szrj 	     _123 = (int) _234;
404938fd1498Szrj 	     OR
405038fd1498Szrj 	     _234 = a_2(D) == 2;
405138fd1498Szrj 
405238fd1498Szrj 	     followed by:
405338fd1498Szrj 	     <bb M>:
405438fd1498Szrj 	     # _345 = PHI <_123(N), 1(...), 1(...)>
405538fd1498Szrj 
405638fd1498Szrj 	     or 0 instead of 1.  If it is 0, the _234
405738fd1498Szrj 	     range test is anded together with all the
405838fd1498Szrj 	     other range tests, if it is 1, it is ored with
405938fd1498Szrj 	     them.  */
406038fd1498Szrj 	  single_imm_use (lhs, &use_p, &phi);
406138fd1498Szrj 	  gcc_assert (gimple_code (phi) == GIMPLE_PHI);
406238fd1498Szrj 	  e2 = find_edge (first_bb, other_bb);
406338fd1498Szrj 	  d = e2->dest_idx;
406438fd1498Szrj 	  gcc_assert (gimple_phi_arg_def (phi, e->dest_idx) == lhs);
406538fd1498Szrj 	  if (integer_zerop (gimple_phi_arg_def (phi, d)))
406638fd1498Szrj 	    code = BIT_AND_EXPR;
406738fd1498Szrj 	  else
406838fd1498Szrj 	    {
406938fd1498Szrj 	      gcc_checking_assert (integer_onep (gimple_phi_arg_def (phi, d)));
407038fd1498Szrj 	      code = BIT_IOR_EXPR;
407138fd1498Szrj 	    }
407238fd1498Szrj 
407338fd1498Szrj 	  /* If _234 SSA_NAME_DEF_STMT is
407438fd1498Szrj 	     _234 = _567 | _789;
407538fd1498Szrj 	     (or &, corresponding to 1/0 in the phi arguments,
407638fd1498Szrj 	     push into ops the individual range test arguments
407738fd1498Szrj 	     of the bitwise or resp. and, recursively.  */
407838fd1498Szrj 	  if (TREE_CODE (rhs) == SSA_NAME
407938fd1498Szrj 	      && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
408038fd1498Szrj 		  != tcc_comparison)
408138fd1498Szrj 	      && !get_ops (rhs, code, &ops,
408238fd1498Szrj 			loop_containing_stmt (stmt))
408338fd1498Szrj 	      && has_single_use (rhs))
408438fd1498Szrj 	    {
408538fd1498Szrj 	      /* Otherwise, push the _234 range test itself.  */
408638fd1498Szrj 	      operand_entry *oe = operand_entry_pool.allocate ();
408738fd1498Szrj 
408838fd1498Szrj 	      oe->op = rhs;
408938fd1498Szrj 	      oe->rank = code;
409038fd1498Szrj 	      oe->id = 0;
409138fd1498Szrj 	      oe->count = 1;
409238fd1498Szrj 	      oe->stmt_to_insert = NULL;
409338fd1498Szrj 	      ops.safe_push (oe);
409438fd1498Szrj 	      bb_ent.last_idx++;
409538fd1498Szrj 	      bb_ent.op = rhs;
409638fd1498Szrj 	    }
409738fd1498Szrj 	  else if (is_gimple_assign (stmt)
409838fd1498Szrj 		   && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
409938fd1498Szrj 		       == tcc_comparison)
410038fd1498Szrj 		   && !get_ops (lhs, code, &ops,
410138fd1498Szrj 				loop_containing_stmt (stmt))
410238fd1498Szrj 		   && has_single_use (lhs))
410338fd1498Szrj 	    {
410438fd1498Szrj 	      operand_entry *oe = operand_entry_pool.allocate ();
410538fd1498Szrj 	      oe->op = lhs;
410638fd1498Szrj 	      oe->rank = code;
410738fd1498Szrj 	      oe->id = 0;
410838fd1498Szrj 	      oe->count = 1;
410938fd1498Szrj 	      ops.safe_push (oe);
411038fd1498Szrj 	      bb_ent.last_idx++;
411138fd1498Szrj 	      bb_ent.op = lhs;
411238fd1498Szrj 	    }
411338fd1498Szrj 	  else
411438fd1498Szrj 	    {
411538fd1498Szrj 	      bb_ent.last_idx = ops.length ();
411638fd1498Szrj 	      bb_ent.op = rhs;
411738fd1498Szrj 	    }
411838fd1498Szrj 	  bbinfo.safe_push (bb_ent);
411938fd1498Szrj 	  continue;
412038fd1498Szrj 	}
412138fd1498Szrj       /* Otherwise stmt is GIMPLE_COND.  */
412238fd1498Szrj       code = gimple_cond_code (stmt);
412338fd1498Szrj       lhs = gimple_cond_lhs (stmt);
412438fd1498Szrj       rhs = gimple_cond_rhs (stmt);
412538fd1498Szrj       if (TREE_CODE (lhs) == SSA_NAME
412638fd1498Szrj 	  && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
412738fd1498Szrj 	  && ((code != EQ_EXPR && code != NE_EXPR)
412838fd1498Szrj 	      || rhs != boolean_false_node
412938fd1498Szrj 		 /* Either push into ops the individual bitwise
413038fd1498Szrj 		    or resp. and operands, depending on which
413138fd1498Szrj 		    edge is other_bb.  */
413238fd1498Szrj 	      || !get_ops (lhs, (((e->flags & EDGE_TRUE_VALUE) == 0)
413338fd1498Szrj 				 ^ (code == EQ_EXPR))
413438fd1498Szrj 				? BIT_AND_EXPR : BIT_IOR_EXPR, &ops,
413538fd1498Szrj 			   loop_containing_stmt (stmt))))
413638fd1498Szrj 	{
413738fd1498Szrj 	  /* Or push the GIMPLE_COND stmt itself.  */
413838fd1498Szrj 	  operand_entry *oe = operand_entry_pool.allocate ();
413938fd1498Szrj 
414038fd1498Szrj 	  oe->op = NULL;
414138fd1498Szrj 	  oe->rank = (e->flags & EDGE_TRUE_VALUE)
414238fd1498Szrj 		     ? BIT_IOR_EXPR : BIT_AND_EXPR;
414338fd1498Szrj 	  /* oe->op = NULL signs that there is no SSA_NAME
414438fd1498Szrj 	     for the range test, and oe->id instead is the
414538fd1498Szrj 	     basic block number, at which's end the GIMPLE_COND
414638fd1498Szrj 	     is.  */
414738fd1498Szrj 	  oe->id = bb->index;
414838fd1498Szrj 	  oe->count = 1;
414938fd1498Szrj 	  oe->stmt_to_insert = NULL;
415038fd1498Szrj 	  ops.safe_push (oe);
415138fd1498Szrj 	  bb_ent.op = NULL;
415238fd1498Szrj 	  bb_ent.last_idx++;
415338fd1498Szrj 	}
415438fd1498Szrj       else if (ops.length () > bb_ent.first_idx)
415538fd1498Szrj 	{
415638fd1498Szrj 	  bb_ent.op = lhs;
415738fd1498Szrj 	  bb_ent.last_idx = ops.length ();
415838fd1498Szrj 	}
415938fd1498Szrj       bbinfo.safe_push (bb_ent);
416038fd1498Szrj       if (bb == first_bb)
416138fd1498Szrj 	break;
416238fd1498Szrj     }
416338fd1498Szrj   if (ops.length () > 1)
416438fd1498Szrj     any_changes = optimize_range_tests (ERROR_MARK, &ops, first_bb);
416538fd1498Szrj   if (any_changes)
416638fd1498Szrj     {
416738fd1498Szrj       unsigned int idx, max_idx = 0;
416838fd1498Szrj       /* update_ops relies on has_single_use predicates returning the
416938fd1498Szrj 	 same values as it did during get_ops earlier.  Additionally it
417038fd1498Szrj 	 never removes statements, only adds new ones and it should walk
417138fd1498Szrj 	 from the single imm use and check the predicate already before
417238fd1498Szrj 	 making those changes.
417338fd1498Szrj 	 On the other side, the handling of GIMPLE_COND directly can turn
417438fd1498Szrj 	 previously multiply used SSA_NAMEs into single use SSA_NAMEs, so
417538fd1498Szrj 	 it needs to be done in a separate loop afterwards.  */
417638fd1498Szrj       for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
417738fd1498Szrj 	{
417838fd1498Szrj 	  if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
417938fd1498Szrj 	      && bbinfo[idx].op != NULL_TREE)
418038fd1498Szrj 	    {
418138fd1498Szrj 	      tree new_op;
418238fd1498Szrj 
418338fd1498Szrj 	      max_idx = idx;
418438fd1498Szrj 	      stmt = last_stmt (bb);
418538fd1498Szrj 	      new_op = update_ops (bbinfo[idx].op,
418638fd1498Szrj 				   (enum tree_code)
418738fd1498Szrj 				   ops[bbinfo[idx].first_idx]->rank,
418838fd1498Szrj 				   ops, &bbinfo[idx].first_idx,
418938fd1498Szrj 				   loop_containing_stmt (stmt));
419038fd1498Szrj 	      if (new_op == NULL_TREE)
419138fd1498Szrj 		{
419238fd1498Szrj 		  gcc_assert (bb == last_bb);
419338fd1498Szrj 		  new_op = ops[bbinfo[idx].first_idx++]->op;
419438fd1498Szrj 		}
419538fd1498Szrj 	      if (bbinfo[idx].op != new_op)
419638fd1498Szrj 		{
419738fd1498Szrj 		  imm_use_iterator iter;
419838fd1498Szrj 		  use_operand_p use_p;
419938fd1498Szrj 		  gimple *use_stmt, *cast_or_tcc_cmp_stmt = NULL;
420038fd1498Szrj 
420138fd1498Szrj 		  FOR_EACH_IMM_USE_STMT (use_stmt, iter, bbinfo[idx].op)
420238fd1498Szrj 		    if (is_gimple_debug (use_stmt))
420338fd1498Szrj 		      continue;
420438fd1498Szrj 		    else if (gimple_code (use_stmt) == GIMPLE_COND
420538fd1498Szrj 			     || gimple_code (use_stmt) == GIMPLE_PHI)
420638fd1498Szrj 		      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
420738fd1498Szrj 			SET_USE (use_p, new_op);
420838fd1498Szrj 		    else if ((is_gimple_assign (use_stmt)
420938fd1498Szrj 			      && (TREE_CODE_CLASS
421038fd1498Szrj 				  (gimple_assign_rhs_code (use_stmt))
421138fd1498Szrj 				  == tcc_comparison)))
421238fd1498Szrj 		      cast_or_tcc_cmp_stmt = use_stmt;
421338fd1498Szrj 		    else if (gimple_assign_cast_p (use_stmt))
421438fd1498Szrj 		      cast_or_tcc_cmp_stmt = use_stmt;
421538fd1498Szrj 		    else
421638fd1498Szrj 		      gcc_unreachable ();
421738fd1498Szrj 
421838fd1498Szrj 		  if (cast_or_tcc_cmp_stmt)
421938fd1498Szrj 		    {
422038fd1498Szrj 		      gcc_assert (bb == last_bb);
422138fd1498Szrj 		      tree lhs = gimple_assign_lhs (cast_or_tcc_cmp_stmt);
422238fd1498Szrj 		      tree new_lhs = make_ssa_name (TREE_TYPE (lhs));
422338fd1498Szrj 		      enum tree_code rhs_code
422438fd1498Szrj 			= gimple_assign_cast_p (cast_or_tcc_cmp_stmt)
422538fd1498Szrj 			? gimple_assign_rhs_code (cast_or_tcc_cmp_stmt)
422638fd1498Szrj 			: CONVERT_EXPR;
422738fd1498Szrj 		      gassign *g;
422838fd1498Szrj 		      if (is_gimple_min_invariant (new_op))
422938fd1498Szrj 			{
423038fd1498Szrj 			  new_op = fold_convert (TREE_TYPE (lhs), new_op);
423138fd1498Szrj 			  g = gimple_build_assign (new_lhs, new_op);
423238fd1498Szrj 			}
423338fd1498Szrj 		      else
423438fd1498Szrj 			g = gimple_build_assign (new_lhs, rhs_code, new_op);
423538fd1498Szrj 		      gimple_stmt_iterator gsi
423638fd1498Szrj 			= gsi_for_stmt (cast_or_tcc_cmp_stmt);
423738fd1498Szrj 		      gimple_set_uid (g, gimple_uid (cast_or_tcc_cmp_stmt));
423838fd1498Szrj 		      gimple_set_visited (g, true);
423938fd1498Szrj 		      gsi_insert_before (&gsi, g, GSI_SAME_STMT);
424038fd1498Szrj 		      FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
424138fd1498Szrj 			if (is_gimple_debug (use_stmt))
424238fd1498Szrj 			  continue;
424338fd1498Szrj 			else if (gimple_code (use_stmt) == GIMPLE_COND
424438fd1498Szrj 				 || gimple_code (use_stmt) == GIMPLE_PHI)
424538fd1498Szrj 			  FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
424638fd1498Szrj 			    SET_USE (use_p, new_lhs);
424738fd1498Szrj 			else
424838fd1498Szrj 			  gcc_unreachable ();
424938fd1498Szrj 		    }
425038fd1498Szrj 		}
425138fd1498Szrj 	    }
425238fd1498Szrj 	  if (bb == first_bb)
425338fd1498Szrj 	    break;
425438fd1498Szrj 	}
425538fd1498Szrj       for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
425638fd1498Szrj 	{
425738fd1498Szrj 	  if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
425838fd1498Szrj 	      && bbinfo[idx].op == NULL_TREE
425938fd1498Szrj 	      && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
426038fd1498Szrj 	    {
426138fd1498Szrj 	      gcond *cond_stmt = as_a <gcond *> (last_stmt (bb));
426238fd1498Szrj 
426338fd1498Szrj 	      if (idx > max_idx)
426438fd1498Szrj 		max_idx = idx;
426538fd1498Szrj 
426638fd1498Szrj 	      /* If we collapse the conditional to a true/false
426738fd1498Szrj 		 condition, then bubble that knowledge up to our caller.  */
426838fd1498Szrj 	      if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
426938fd1498Szrj 		{
427038fd1498Szrj 		  gimple_cond_make_false (cond_stmt);
427138fd1498Szrj 		  cfg_cleanup_needed = true;
427238fd1498Szrj 		}
427338fd1498Szrj 	      else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
427438fd1498Szrj 		{
427538fd1498Szrj 		  gimple_cond_make_true (cond_stmt);
427638fd1498Szrj 		  cfg_cleanup_needed = true;
427738fd1498Szrj 		}
427838fd1498Szrj 	      else
427938fd1498Szrj 		{
428038fd1498Szrj 		  gimple_cond_set_code (cond_stmt, NE_EXPR);
428138fd1498Szrj 		  gimple_cond_set_lhs (cond_stmt,
428238fd1498Szrj 				       ops[bbinfo[idx].first_idx]->op);
428338fd1498Szrj 		  gimple_cond_set_rhs (cond_stmt, boolean_false_node);
428438fd1498Szrj 		}
428538fd1498Szrj 	      update_stmt (cond_stmt);
428638fd1498Szrj 	    }
428738fd1498Szrj 	  if (bb == first_bb)
428838fd1498Szrj 	    break;
428938fd1498Szrj 	}
429038fd1498Szrj 
429138fd1498Szrj       /* The above changes could result in basic blocks after the first
429238fd1498Szrj 	 modified one, up to and including last_bb, to be executed even if
429338fd1498Szrj 	 they would not be in the original program.  If the value ranges of
429438fd1498Szrj 	 assignment lhs' in those bbs were dependent on the conditions
429538fd1498Szrj 	 guarding those basic blocks which now can change, the VRs might
429638fd1498Szrj 	 be incorrect.  As no_side_effect_bb should ensure those SSA_NAMEs
429738fd1498Szrj 	 are only used within the same bb, it should be not a big deal if
429838fd1498Szrj 	 we just reset all the VRs in those bbs.  See PR68671.  */
429938fd1498Szrj       for (bb = last_bb, idx = 0; idx < max_idx; bb = single_pred (bb), idx++)
430038fd1498Szrj 	reset_flow_sensitive_info_in_bb (bb);
430138fd1498Szrj     }
430238fd1498Szrj   return cfg_cleanup_needed;
430338fd1498Szrj }
430438fd1498Szrj 
430538fd1498Szrj /* Return true if OPERAND is defined by a PHI node which uses the LHS
430638fd1498Szrj    of STMT in it's operands.  This is also known as a "destructive
430738fd1498Szrj    update" operation.  */
430838fd1498Szrj 
430938fd1498Szrj static bool
is_phi_for_stmt(gimple * stmt,tree operand)431038fd1498Szrj is_phi_for_stmt (gimple *stmt, tree operand)
431138fd1498Szrj {
431238fd1498Szrj   gimple *def_stmt;
431338fd1498Szrj   gphi *def_phi;
431438fd1498Szrj   tree lhs;
431538fd1498Szrj   use_operand_p arg_p;
431638fd1498Szrj   ssa_op_iter i;
431738fd1498Szrj 
431838fd1498Szrj   if (TREE_CODE (operand) != SSA_NAME)
431938fd1498Szrj     return false;
432038fd1498Szrj 
432138fd1498Szrj   lhs = gimple_assign_lhs (stmt);
432238fd1498Szrj 
432338fd1498Szrj   def_stmt = SSA_NAME_DEF_STMT (operand);
432438fd1498Szrj   def_phi = dyn_cast <gphi *> (def_stmt);
432538fd1498Szrj   if (!def_phi)
432638fd1498Szrj     return false;
432738fd1498Szrj 
432838fd1498Szrj   FOR_EACH_PHI_ARG (arg_p, def_phi, i, SSA_OP_USE)
432938fd1498Szrj     if (lhs == USE_FROM_PTR (arg_p))
433038fd1498Szrj       return true;
433138fd1498Szrj   return false;
433238fd1498Szrj }
433338fd1498Szrj 
433438fd1498Szrj /* Remove def stmt of VAR if VAR has zero uses and recurse
433538fd1498Szrj    on rhs1 operand if so.  */
433638fd1498Szrj 
433738fd1498Szrj static void
remove_visited_stmt_chain(tree var)433838fd1498Szrj remove_visited_stmt_chain (tree var)
433938fd1498Szrj {
434038fd1498Szrj   gimple *stmt;
434138fd1498Szrj   gimple_stmt_iterator gsi;
434238fd1498Szrj 
434338fd1498Szrj   while (1)
434438fd1498Szrj     {
434538fd1498Szrj       if (TREE_CODE (var) != SSA_NAME || !has_zero_uses (var))
434638fd1498Szrj 	return;
434738fd1498Szrj       stmt = SSA_NAME_DEF_STMT (var);
434838fd1498Szrj       if (is_gimple_assign (stmt) && gimple_visited_p (stmt))
434938fd1498Szrj 	{
435038fd1498Szrj 	  var = gimple_assign_rhs1 (stmt);
435138fd1498Szrj 	  gsi = gsi_for_stmt (stmt);
435238fd1498Szrj 	  reassoc_remove_stmt (&gsi);
435338fd1498Szrj 	  release_defs (stmt);
435438fd1498Szrj 	}
435538fd1498Szrj       else
435638fd1498Szrj 	return;
435738fd1498Szrj     }
435838fd1498Szrj }
435938fd1498Szrj 
436038fd1498Szrj /* This function checks three consequtive operands in
436138fd1498Szrj    passed operands vector OPS starting from OPINDEX and
436238fd1498Szrj    swaps two operands if it is profitable for binary operation
436338fd1498Szrj    consuming OPINDEX + 1 abnd OPINDEX + 2 operands.
436438fd1498Szrj 
436538fd1498Szrj    We pair ops with the same rank if possible.
436638fd1498Szrj 
436738fd1498Szrj    The alternative we try is to see if STMT is a destructive
436838fd1498Szrj    update style statement, which is like:
436938fd1498Szrj    b = phi (a, ...)
437038fd1498Szrj    a = c + b;
437138fd1498Szrj    In that case, we want to use the destructive update form to
437238fd1498Szrj    expose the possible vectorizer sum reduction opportunity.
437338fd1498Szrj    In that case, the third operand will be the phi node. This
437438fd1498Szrj    check is not performed if STMT is null.
437538fd1498Szrj 
437638fd1498Szrj    We could, of course, try to be better as noted above, and do a
437738fd1498Szrj    lot of work to try to find these opportunities in >3 operand
437838fd1498Szrj    cases, but it is unlikely to be worth it.  */
437938fd1498Szrj 
438038fd1498Szrj static void
swap_ops_for_binary_stmt(vec<operand_entry * > ops,unsigned int opindex,gimple * stmt)438138fd1498Szrj swap_ops_for_binary_stmt (vec<operand_entry *> ops,
438238fd1498Szrj 			  unsigned int opindex, gimple *stmt)
438338fd1498Szrj {
438438fd1498Szrj   operand_entry *oe1, *oe2, *oe3;
438538fd1498Szrj 
438638fd1498Szrj   oe1 = ops[opindex];
438738fd1498Szrj   oe2 = ops[opindex + 1];
438838fd1498Szrj   oe3 = ops[opindex + 2];
438938fd1498Szrj 
439038fd1498Szrj   if ((oe1->rank == oe2->rank
439138fd1498Szrj        && oe2->rank != oe3->rank)
439238fd1498Szrj       || (stmt && is_phi_for_stmt (stmt, oe3->op)
439338fd1498Szrj 	  && !is_phi_for_stmt (stmt, oe1->op)
439438fd1498Szrj 	  && !is_phi_for_stmt (stmt, oe2->op)))
439538fd1498Szrj     std::swap (*oe1, *oe3);
439638fd1498Szrj   else if ((oe1->rank == oe3->rank
439738fd1498Szrj 	    && oe2->rank != oe3->rank)
439838fd1498Szrj 	   || (stmt && is_phi_for_stmt (stmt, oe2->op)
439938fd1498Szrj 	       && !is_phi_for_stmt (stmt, oe1->op)
440038fd1498Szrj 	       && !is_phi_for_stmt (stmt, oe3->op)))
440138fd1498Szrj     std::swap (*oe1, *oe2);
440238fd1498Szrj }
440338fd1498Szrj 
440438fd1498Szrj /* If definition of RHS1 or RHS2 dominates STMT, return the later of those
440538fd1498Szrj    two definitions, otherwise return STMT.  */
440638fd1498Szrj 
440738fd1498Szrj static inline gimple *
find_insert_point(gimple * stmt,tree rhs1,tree rhs2)440838fd1498Szrj find_insert_point (gimple *stmt, tree rhs1, tree rhs2)
440938fd1498Szrj {
441038fd1498Szrj   if (TREE_CODE (rhs1) == SSA_NAME
441138fd1498Szrj       && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs1)))
441238fd1498Szrj     stmt = SSA_NAME_DEF_STMT (rhs1);
441338fd1498Szrj   if (TREE_CODE (rhs2) == SSA_NAME
441438fd1498Szrj       && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs2)))
441538fd1498Szrj     stmt = SSA_NAME_DEF_STMT (rhs2);
441638fd1498Szrj   return stmt;
441738fd1498Szrj }
441838fd1498Szrj 
441938fd1498Szrj /* If the stmt that defines operand has to be inserted, insert it
442038fd1498Szrj    before the use.  */
442138fd1498Szrj static void
insert_stmt_before_use(gimple * stmt,gimple * stmt_to_insert)442238fd1498Szrj insert_stmt_before_use (gimple *stmt, gimple *stmt_to_insert)
442338fd1498Szrj {
442438fd1498Szrj   gcc_assert (is_gimple_assign (stmt_to_insert));
442538fd1498Szrj   tree rhs1 = gimple_assign_rhs1 (stmt_to_insert);
442638fd1498Szrj   tree rhs2 = gimple_assign_rhs2 (stmt_to_insert);
442738fd1498Szrj   gimple *insert_point = find_insert_point (stmt, rhs1, rhs2);
442838fd1498Szrj   gimple_stmt_iterator gsi = gsi_for_stmt (insert_point);
442938fd1498Szrj   gimple_set_uid (stmt_to_insert, gimple_uid (insert_point));
443038fd1498Szrj 
443138fd1498Szrj   /* If the insert point is not stmt, then insert_point would be
443238fd1498Szrj      the point where operand rhs1 or rhs2 is defined. In this case,
443338fd1498Szrj      stmt_to_insert has to be inserted afterwards. This would
443438fd1498Szrj      only happen when the stmt insertion point is flexible. */
443538fd1498Szrj   if (stmt == insert_point)
443638fd1498Szrj     gsi_insert_before (&gsi, stmt_to_insert, GSI_NEW_STMT);
443738fd1498Szrj   else
443838fd1498Szrj     insert_stmt_after (stmt_to_insert, insert_point);
443938fd1498Szrj }
444038fd1498Szrj 
444138fd1498Szrj 
444238fd1498Szrj /* Recursively rewrite our linearized statements so that the operators
444338fd1498Szrj    match those in OPS[OPINDEX], putting the computation in rank
444438fd1498Szrj    order.  Return new lhs.
444538fd1498Szrj    CHANGED is true if we shouldn't reuse the lhs SSA_NAME both in
444638fd1498Szrj    the current stmt and during recursive invocations.
444738fd1498Szrj    NEXT_CHANGED is true if we shouldn't reuse the lhs SSA_NAME in
444838fd1498Szrj    recursive invocations.  */
444938fd1498Szrj 
445038fd1498Szrj static tree
rewrite_expr_tree(gimple * stmt,unsigned int opindex,vec<operand_entry * > ops,bool changed,bool next_changed)445138fd1498Szrj rewrite_expr_tree (gimple *stmt, unsigned int opindex,
445238fd1498Szrj 		   vec<operand_entry *> ops, bool changed, bool next_changed)
445338fd1498Szrj {
445438fd1498Szrj   tree rhs1 = gimple_assign_rhs1 (stmt);
445538fd1498Szrj   tree rhs2 = gimple_assign_rhs2 (stmt);
445638fd1498Szrj   tree lhs = gimple_assign_lhs (stmt);
445738fd1498Szrj   operand_entry *oe;
445838fd1498Szrj 
445938fd1498Szrj   /* The final recursion case for this function is that you have
446038fd1498Szrj      exactly two operations left.
446138fd1498Szrj      If we had exactly one op in the entire list to start with, we
446238fd1498Szrj      would have never called this function, and the tail recursion
446338fd1498Szrj      rewrites them one at a time.  */
446438fd1498Szrj   if (opindex + 2 == ops.length ())
446538fd1498Szrj     {
446638fd1498Szrj       operand_entry *oe1, *oe2;
446738fd1498Szrj 
446838fd1498Szrj       oe1 = ops[opindex];
446938fd1498Szrj       oe2 = ops[opindex + 1];
447038fd1498Szrj 
447138fd1498Szrj       if (rhs1 != oe1->op || rhs2 != oe2->op)
447238fd1498Szrj 	{
447338fd1498Szrj 	  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
447438fd1498Szrj 	  unsigned int uid = gimple_uid (stmt);
447538fd1498Szrj 
447638fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
447738fd1498Szrj 	    {
447838fd1498Szrj 	      fprintf (dump_file, "Transforming ");
447938fd1498Szrj 	      print_gimple_stmt (dump_file, stmt, 0);
448038fd1498Szrj 	    }
448138fd1498Szrj 
448238fd1498Szrj 	  /* If the stmt that defines operand has to be inserted, insert it
448338fd1498Szrj 	     before the use.  */
448438fd1498Szrj 	  if (oe1->stmt_to_insert)
448538fd1498Szrj 	    insert_stmt_before_use (stmt, oe1->stmt_to_insert);
448638fd1498Szrj 	  if (oe2->stmt_to_insert)
448738fd1498Szrj 	    insert_stmt_before_use (stmt, oe2->stmt_to_insert);
448838fd1498Szrj 	  /* Even when changed is false, reassociation could have e.g. removed
448938fd1498Szrj 	     some redundant operations, so unless we are just swapping the
449038fd1498Szrj 	     arguments or unless there is no change at all (then we just
449138fd1498Szrj 	     return lhs), force creation of a new SSA_NAME.  */
449238fd1498Szrj 	  if (changed || ((rhs1 != oe2->op || rhs2 != oe1->op) && opindex))
449338fd1498Szrj 	    {
449438fd1498Szrj 	      gimple *insert_point
449538fd1498Szrj 		= find_insert_point (stmt, oe1->op, oe2->op);
449638fd1498Szrj 	      lhs = make_ssa_name (TREE_TYPE (lhs));
449738fd1498Szrj 	      stmt
449838fd1498Szrj 		= gimple_build_assign (lhs, gimple_assign_rhs_code (stmt),
449938fd1498Szrj 				       oe1->op, oe2->op);
450038fd1498Szrj 	      gimple_set_uid (stmt, uid);
450138fd1498Szrj 	      gimple_set_visited (stmt, true);
450238fd1498Szrj 	      if (insert_point == gsi_stmt (gsi))
450338fd1498Szrj 		gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
450438fd1498Szrj 	      else
450538fd1498Szrj 		insert_stmt_after (stmt, insert_point);
450638fd1498Szrj 	    }
450738fd1498Szrj 	  else
450838fd1498Szrj 	    {
450938fd1498Szrj 	      gcc_checking_assert (find_insert_point (stmt, oe1->op, oe2->op)
451038fd1498Szrj 				   == stmt);
451138fd1498Szrj 	      gimple_assign_set_rhs1 (stmt, oe1->op);
451238fd1498Szrj 	      gimple_assign_set_rhs2 (stmt, oe2->op);
451338fd1498Szrj 	      update_stmt (stmt);
451438fd1498Szrj 	    }
451538fd1498Szrj 
451638fd1498Szrj 	  if (rhs1 != oe1->op && rhs1 != oe2->op)
451738fd1498Szrj 	    remove_visited_stmt_chain (rhs1);
451838fd1498Szrj 
451938fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
452038fd1498Szrj 	    {
452138fd1498Szrj 	      fprintf (dump_file, " into ");
452238fd1498Szrj 	      print_gimple_stmt (dump_file, stmt, 0);
452338fd1498Szrj 	    }
452438fd1498Szrj 	}
452538fd1498Szrj       return lhs;
452638fd1498Szrj     }
452738fd1498Szrj 
452838fd1498Szrj   /* If we hit here, we should have 3 or more ops left.  */
452938fd1498Szrj   gcc_assert (opindex + 2 < ops.length ());
453038fd1498Szrj 
453138fd1498Szrj   /* Rewrite the next operator.  */
453238fd1498Szrj   oe = ops[opindex];
453338fd1498Szrj 
453438fd1498Szrj   /* If the stmt that defines operand has to be inserted, insert it
453538fd1498Szrj      before the use.  */
453638fd1498Szrj   if (oe->stmt_to_insert)
453738fd1498Szrj     insert_stmt_before_use (stmt, oe->stmt_to_insert);
453838fd1498Szrj 
453938fd1498Szrj   /* Recurse on the LHS of the binary operator, which is guaranteed to
454038fd1498Szrj      be the non-leaf side.  */
454138fd1498Szrj   tree new_rhs1
454238fd1498Szrj     = rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops,
454338fd1498Szrj 			 changed || oe->op != rhs2 || next_changed,
454438fd1498Szrj 			 false);
454538fd1498Szrj 
454638fd1498Szrj   if (oe->op != rhs2 || new_rhs1 != rhs1)
454738fd1498Szrj     {
454838fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
454938fd1498Szrj 	{
455038fd1498Szrj 	  fprintf (dump_file, "Transforming ");
455138fd1498Szrj 	  print_gimple_stmt (dump_file, stmt, 0);
455238fd1498Szrj 	}
455338fd1498Szrj 
455438fd1498Szrj       /* If changed is false, this is either opindex == 0
455538fd1498Szrj 	 or all outer rhs2's were equal to corresponding oe->op,
455638fd1498Szrj 	 and powi_result is NULL.
455738fd1498Szrj 	 That means lhs is equivalent before and after reassociation.
455838fd1498Szrj 	 Otherwise ensure the old lhs SSA_NAME is not reused and
455938fd1498Szrj 	 create a new stmt as well, so that any debug stmts will be
456038fd1498Szrj 	 properly adjusted.  */
456138fd1498Szrj       if (changed)
456238fd1498Szrj 	{
456338fd1498Szrj 	  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
456438fd1498Szrj 	  unsigned int uid = gimple_uid (stmt);
456538fd1498Szrj 	  gimple *insert_point = find_insert_point (stmt, new_rhs1, oe->op);
456638fd1498Szrj 
456738fd1498Szrj 	  lhs = make_ssa_name (TREE_TYPE (lhs));
456838fd1498Szrj 	  stmt = gimple_build_assign (lhs, gimple_assign_rhs_code (stmt),
456938fd1498Szrj 				      new_rhs1, oe->op);
457038fd1498Szrj 	  gimple_set_uid (stmt, uid);
457138fd1498Szrj 	  gimple_set_visited (stmt, true);
457238fd1498Szrj 	  if (insert_point == gsi_stmt (gsi))
457338fd1498Szrj 	    gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
457438fd1498Szrj 	  else
457538fd1498Szrj 	    insert_stmt_after (stmt, insert_point);
457638fd1498Szrj 	}
457738fd1498Szrj       else
457838fd1498Szrj 	{
457938fd1498Szrj 	  gcc_checking_assert (find_insert_point (stmt, new_rhs1, oe->op)
458038fd1498Szrj 			       == stmt);
458138fd1498Szrj 	  gimple_assign_set_rhs1 (stmt, new_rhs1);
458238fd1498Szrj 	  gimple_assign_set_rhs2 (stmt, oe->op);
458338fd1498Szrj 	  update_stmt (stmt);
458438fd1498Szrj 	}
458538fd1498Szrj 
458638fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
458738fd1498Szrj 	{
458838fd1498Szrj 	  fprintf (dump_file, " into ");
458938fd1498Szrj 	  print_gimple_stmt (dump_file, stmt, 0);
459038fd1498Szrj 	}
459138fd1498Szrj     }
459238fd1498Szrj   return lhs;
459338fd1498Szrj }
459438fd1498Szrj 
459538fd1498Szrj /* Find out how many cycles we need to compute statements chain.
459638fd1498Szrj    OPS_NUM holds number os statements in a chain.  CPU_WIDTH is a
459738fd1498Szrj    maximum number of independent statements we may execute per cycle.  */
459838fd1498Szrj 
459938fd1498Szrj static int
get_required_cycles(int ops_num,int cpu_width)460038fd1498Szrj get_required_cycles (int ops_num, int cpu_width)
460138fd1498Szrj {
460238fd1498Szrj   int res;
460338fd1498Szrj   int elog;
460438fd1498Szrj   unsigned int rest;
460538fd1498Szrj 
460638fd1498Szrj   /* While we have more than 2 * cpu_width operands
460738fd1498Szrj      we may reduce number of operands by cpu_width
460838fd1498Szrj      per cycle.  */
460938fd1498Szrj   res = ops_num / (2 * cpu_width);
461038fd1498Szrj 
461138fd1498Szrj   /* Remained operands count may be reduced twice per cycle
461238fd1498Szrj      until we have only one operand.  */
461338fd1498Szrj   rest = (unsigned)(ops_num - res * cpu_width);
461438fd1498Szrj   elog = exact_log2 (rest);
461538fd1498Szrj   if (elog >= 0)
461638fd1498Szrj     res += elog;
461738fd1498Szrj   else
461838fd1498Szrj     res += floor_log2 (rest) + 1;
461938fd1498Szrj 
462038fd1498Szrj   return res;
462138fd1498Szrj }
462238fd1498Szrj 
462338fd1498Szrj /* Returns an optimal number of registers to use for computation of
462438fd1498Szrj    given statements.  */
462538fd1498Szrj 
462638fd1498Szrj static int
get_reassociation_width(int ops_num,enum tree_code opc,machine_mode mode)462738fd1498Szrj get_reassociation_width (int ops_num, enum tree_code opc,
462838fd1498Szrj 			 machine_mode mode)
462938fd1498Szrj {
463038fd1498Szrj   int param_width = PARAM_VALUE (PARAM_TREE_REASSOC_WIDTH);
463138fd1498Szrj   int width;
463238fd1498Szrj   int width_min;
463338fd1498Szrj   int cycles_best;
463438fd1498Szrj 
463538fd1498Szrj   if (param_width > 0)
463638fd1498Szrj     width = param_width;
463738fd1498Szrj   else
463838fd1498Szrj     width = targetm.sched.reassociation_width (opc, mode);
463938fd1498Szrj 
464038fd1498Szrj   if (width == 1)
464138fd1498Szrj     return width;
464238fd1498Szrj 
464338fd1498Szrj   /* Get the minimal time required for sequence computation.  */
464438fd1498Szrj   cycles_best = get_required_cycles (ops_num, width);
464538fd1498Szrj 
464638fd1498Szrj   /* Check if we may use less width and still compute sequence for
464738fd1498Szrj      the same time.  It will allow us to reduce registers usage.
464838fd1498Szrj      get_required_cycles is monotonically increasing with lower width
464938fd1498Szrj      so we can perform a binary search for the minimal width that still
465038fd1498Szrj      results in the optimal cycle count.  */
465138fd1498Szrj   width_min = 1;
465238fd1498Szrj   while (width > width_min)
465338fd1498Szrj     {
465438fd1498Szrj       int width_mid = (width + width_min) / 2;
465538fd1498Szrj 
465638fd1498Szrj       if (get_required_cycles (ops_num, width_mid) == cycles_best)
465738fd1498Szrj 	width = width_mid;
465838fd1498Szrj       else if (width_min < width_mid)
465938fd1498Szrj 	width_min = width_mid;
466038fd1498Szrj       else
466138fd1498Szrj 	break;
466238fd1498Szrj     }
466338fd1498Szrj 
466438fd1498Szrj   return width;
466538fd1498Szrj }
466638fd1498Szrj 
466738fd1498Szrj /* Recursively rewrite our linearized statements so that the operators
466838fd1498Szrj    match those in OPS[OPINDEX], putting the computation in rank
466938fd1498Szrj    order and trying to allow operations to be executed in
467038fd1498Szrj    parallel.  */
467138fd1498Szrj 
467238fd1498Szrj static void
rewrite_expr_tree_parallel(gassign * stmt,int width,vec<operand_entry * > ops)467338fd1498Szrj rewrite_expr_tree_parallel (gassign *stmt, int width,
467438fd1498Szrj 			    vec<operand_entry *> ops)
467538fd1498Szrj {
467638fd1498Szrj   enum tree_code opcode = gimple_assign_rhs_code (stmt);
467738fd1498Szrj   int op_num = ops.length ();
467838fd1498Szrj   gcc_assert (op_num > 0);
467938fd1498Szrj   int stmt_num = op_num - 1;
468038fd1498Szrj   gimple **stmts = XALLOCAVEC (gimple *, stmt_num);
468138fd1498Szrj   int op_index = op_num - 1;
468238fd1498Szrj   int stmt_index = 0;
468338fd1498Szrj   int ready_stmts_end = 0;
468438fd1498Szrj   int i = 0;
468538fd1498Szrj   gimple *stmt1 = NULL, *stmt2 = NULL;
468638fd1498Szrj   tree last_rhs1 = gimple_assign_rhs1 (stmt);
468738fd1498Szrj 
468838fd1498Szrj   /* We start expression rewriting from the top statements.
468938fd1498Szrj      So, in this loop we create a full list of statements
469038fd1498Szrj      we will work with.  */
469138fd1498Szrj   stmts[stmt_num - 1] = stmt;
469238fd1498Szrj   for (i = stmt_num - 2; i >= 0; i--)
469338fd1498Szrj     stmts[i] = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmts[i+1]));
469438fd1498Szrj 
469538fd1498Szrj   for (i = 0; i < stmt_num; i++)
469638fd1498Szrj     {
469738fd1498Szrj       tree op1, op2;
469838fd1498Szrj 
469938fd1498Szrj       /* Determine whether we should use results of
470038fd1498Szrj 	 already handled statements or not.  */
470138fd1498Szrj       if (ready_stmts_end == 0
470238fd1498Szrj 	  && (i - stmt_index >= width || op_index < 1))
470338fd1498Szrj 	ready_stmts_end = i;
470438fd1498Szrj 
470538fd1498Szrj       /* Now we choose operands for the next statement.  Non zero
470638fd1498Szrj 	 value in ready_stmts_end means here that we should use
470738fd1498Szrj 	 the result of already generated statements as new operand.  */
470838fd1498Szrj       if (ready_stmts_end > 0)
470938fd1498Szrj 	{
471038fd1498Szrj 	  op1 = gimple_assign_lhs (stmts[stmt_index++]);
471138fd1498Szrj 	  if (ready_stmts_end > stmt_index)
471238fd1498Szrj 	    op2 = gimple_assign_lhs (stmts[stmt_index++]);
471338fd1498Szrj 	  else if (op_index >= 0)
471438fd1498Szrj 	    {
471538fd1498Szrj 	      operand_entry *oe = ops[op_index--];
471638fd1498Szrj 	      stmt2 = oe->stmt_to_insert;
471738fd1498Szrj 	      op2 = oe->op;
471838fd1498Szrj 	    }
471938fd1498Szrj 	  else
472038fd1498Szrj 	    {
472138fd1498Szrj 	      gcc_assert (stmt_index < i);
472238fd1498Szrj 	      op2 = gimple_assign_lhs (stmts[stmt_index++]);
472338fd1498Szrj 	    }
472438fd1498Szrj 
472538fd1498Szrj 	  if (stmt_index >= ready_stmts_end)
472638fd1498Szrj 	    ready_stmts_end = 0;
472738fd1498Szrj 	}
472838fd1498Szrj       else
472938fd1498Szrj 	{
473038fd1498Szrj 	  if (op_index > 1)
473138fd1498Szrj 	    swap_ops_for_binary_stmt (ops, op_index - 2, NULL);
473238fd1498Szrj 	  operand_entry *oe2 = ops[op_index--];
473338fd1498Szrj 	  operand_entry *oe1 = ops[op_index--];
473438fd1498Szrj 	  op2 = oe2->op;
473538fd1498Szrj 	  stmt2 = oe2->stmt_to_insert;
473638fd1498Szrj 	  op1 = oe1->op;
473738fd1498Szrj 	  stmt1 = oe1->stmt_to_insert;
473838fd1498Szrj 	}
473938fd1498Szrj 
474038fd1498Szrj       /* If we emit the last statement then we should put
474138fd1498Szrj 	 operands into the last statement.  It will also
474238fd1498Szrj 	 break the loop.  */
474338fd1498Szrj       if (op_index < 0 && stmt_index == i)
474438fd1498Szrj 	i = stmt_num - 1;
474538fd1498Szrj 
474638fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
474738fd1498Szrj 	{
474838fd1498Szrj 	  fprintf (dump_file, "Transforming ");
474938fd1498Szrj 	  print_gimple_stmt (dump_file, stmts[i], 0);
475038fd1498Szrj 	}
475138fd1498Szrj 
475238fd1498Szrj       /* If the stmt that defines operand has to be inserted, insert it
475338fd1498Szrj 	 before the use.  */
475438fd1498Szrj       if (stmt1)
475538fd1498Szrj 	insert_stmt_before_use (stmts[i], stmt1);
475638fd1498Szrj       if (stmt2)
475738fd1498Szrj 	insert_stmt_before_use (stmts[i], stmt2);
475838fd1498Szrj       stmt1 = stmt2 = NULL;
475938fd1498Szrj 
476038fd1498Szrj       /* We keep original statement only for the last one.  All
476138fd1498Szrj 	 others are recreated.  */
476238fd1498Szrj       if (i == stmt_num - 1)
476338fd1498Szrj 	{
476438fd1498Szrj 	  gimple_assign_set_rhs1 (stmts[i], op1);
476538fd1498Szrj 	  gimple_assign_set_rhs2 (stmts[i], op2);
476638fd1498Szrj 	  update_stmt (stmts[i]);
476738fd1498Szrj 	}
476838fd1498Szrj       else
476938fd1498Szrj 	{
477038fd1498Szrj 	  stmts[i] = build_and_add_sum (TREE_TYPE (last_rhs1), op1, op2, opcode);
477138fd1498Szrj 	}
477238fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
477338fd1498Szrj 	{
477438fd1498Szrj 	  fprintf (dump_file, " into ");
477538fd1498Szrj 	  print_gimple_stmt (dump_file, stmts[i], 0);
477638fd1498Szrj 	}
477738fd1498Szrj     }
477838fd1498Szrj 
477938fd1498Szrj   remove_visited_stmt_chain (last_rhs1);
478038fd1498Szrj }
478138fd1498Szrj 
478238fd1498Szrj /* Transform STMT, which is really (A +B) + (C + D) into the left
478338fd1498Szrj    linear form, ((A+B)+C)+D.
478438fd1498Szrj    Recurse on D if necessary.  */
478538fd1498Szrj 
478638fd1498Szrj static void
linearize_expr(gimple * stmt)478738fd1498Szrj linearize_expr (gimple *stmt)
478838fd1498Szrj {
478938fd1498Szrj   gimple_stmt_iterator gsi;
479038fd1498Szrj   gimple *binlhs = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
479138fd1498Szrj   gimple *binrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
479238fd1498Szrj   gimple *oldbinrhs = binrhs;
479338fd1498Szrj   enum tree_code rhscode = gimple_assign_rhs_code (stmt);
479438fd1498Szrj   gimple *newbinrhs = NULL;
479538fd1498Szrj   struct loop *loop = loop_containing_stmt (stmt);
479638fd1498Szrj   tree lhs = gimple_assign_lhs (stmt);
479738fd1498Szrj 
479838fd1498Szrj   gcc_assert (is_reassociable_op (binlhs, rhscode, loop)
479938fd1498Szrj 	      && is_reassociable_op (binrhs, rhscode, loop));
480038fd1498Szrj 
480138fd1498Szrj   gsi = gsi_for_stmt (stmt);
480238fd1498Szrj 
480338fd1498Szrj   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
480438fd1498Szrj   binrhs = gimple_build_assign (make_ssa_name (TREE_TYPE (lhs)),
480538fd1498Szrj 				gimple_assign_rhs_code (binrhs),
480638fd1498Szrj 				gimple_assign_lhs (binlhs),
480738fd1498Szrj 				gimple_assign_rhs2 (binrhs));
480838fd1498Szrj   gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (binrhs));
480938fd1498Szrj   gsi_insert_before (&gsi, binrhs, GSI_SAME_STMT);
481038fd1498Szrj   gimple_set_uid (binrhs, gimple_uid (stmt));
481138fd1498Szrj 
481238fd1498Szrj   if (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
481338fd1498Szrj     newbinrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
481438fd1498Szrj 
481538fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
481638fd1498Szrj     {
481738fd1498Szrj       fprintf (dump_file, "Linearized: ");
481838fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
481938fd1498Szrj     }
482038fd1498Szrj 
482138fd1498Szrj   reassociate_stats.linearized++;
482238fd1498Szrj   update_stmt (stmt);
482338fd1498Szrj 
482438fd1498Szrj   gsi = gsi_for_stmt (oldbinrhs);
482538fd1498Szrj   reassoc_remove_stmt (&gsi);
482638fd1498Szrj   release_defs (oldbinrhs);
482738fd1498Szrj 
482838fd1498Szrj   gimple_set_visited (stmt, true);
482938fd1498Szrj   gimple_set_visited (binlhs, true);
483038fd1498Szrj   gimple_set_visited (binrhs, true);
483138fd1498Szrj 
483238fd1498Szrj   /* Tail recurse on the new rhs if it still needs reassociation.  */
483338fd1498Szrj   if (newbinrhs && is_reassociable_op (newbinrhs, rhscode, loop))
483438fd1498Szrj     /* ??? This should probably be linearize_expr (newbinrhs) but I don't
483538fd1498Szrj 	   want to change the algorithm while converting to tuples.  */
483638fd1498Szrj     linearize_expr (stmt);
483738fd1498Szrj }
483838fd1498Szrj 
483938fd1498Szrj /* If LHS has a single immediate use that is a GIMPLE_ASSIGN statement, return
484038fd1498Szrj    it.  Otherwise, return NULL.  */
484138fd1498Szrj 
484238fd1498Szrj static gimple *
get_single_immediate_use(tree lhs)484338fd1498Szrj get_single_immediate_use (tree lhs)
484438fd1498Szrj {
484538fd1498Szrj   use_operand_p immuse;
484638fd1498Szrj   gimple *immusestmt;
484738fd1498Szrj 
484838fd1498Szrj   if (TREE_CODE (lhs) == SSA_NAME
484938fd1498Szrj       && single_imm_use (lhs, &immuse, &immusestmt)
485038fd1498Szrj       && is_gimple_assign (immusestmt))
485138fd1498Szrj     return immusestmt;
485238fd1498Szrj 
485338fd1498Szrj   return NULL;
485438fd1498Szrj }
485538fd1498Szrj 
485638fd1498Szrj /* Recursively negate the value of TONEGATE, and return the SSA_NAME
485738fd1498Szrj    representing the negated value.  Insertions of any necessary
485838fd1498Szrj    instructions go before GSI.
485938fd1498Szrj    This function is recursive in that, if you hand it "a_5" as the
486038fd1498Szrj    value to negate, and a_5 is defined by "a_5 = b_3 + b_4", it will
486138fd1498Szrj    transform b_3 + b_4 into a_5 = -b_3 + -b_4.  */
486238fd1498Szrj 
486338fd1498Szrj static tree
negate_value(tree tonegate,gimple_stmt_iterator * gsip)486438fd1498Szrj negate_value (tree tonegate, gimple_stmt_iterator *gsip)
486538fd1498Szrj {
486638fd1498Szrj   gimple *negatedefstmt = NULL;
486738fd1498Szrj   tree resultofnegate;
486838fd1498Szrj   gimple_stmt_iterator gsi;
486938fd1498Szrj   unsigned int uid;
487038fd1498Szrj 
487138fd1498Szrj   /* If we are trying to negate a name, defined by an add, negate the
487238fd1498Szrj      add operands instead.  */
487338fd1498Szrj   if (TREE_CODE (tonegate) == SSA_NAME)
487438fd1498Szrj     negatedefstmt = SSA_NAME_DEF_STMT (tonegate);
487538fd1498Szrj   if (TREE_CODE (tonegate) == SSA_NAME
487638fd1498Szrj       && is_gimple_assign (negatedefstmt)
487738fd1498Szrj       && TREE_CODE (gimple_assign_lhs (negatedefstmt)) == SSA_NAME
487838fd1498Szrj       && has_single_use (gimple_assign_lhs (negatedefstmt))
487938fd1498Szrj       && gimple_assign_rhs_code (negatedefstmt) == PLUS_EXPR)
488038fd1498Szrj     {
488138fd1498Szrj       tree rhs1 = gimple_assign_rhs1 (negatedefstmt);
488238fd1498Szrj       tree rhs2 = gimple_assign_rhs2 (negatedefstmt);
488338fd1498Szrj       tree lhs = gimple_assign_lhs (negatedefstmt);
488438fd1498Szrj       gimple *g;
488538fd1498Szrj 
488638fd1498Szrj       gsi = gsi_for_stmt (negatedefstmt);
488738fd1498Szrj       rhs1 = negate_value (rhs1, &gsi);
488838fd1498Szrj 
488938fd1498Szrj       gsi = gsi_for_stmt (negatedefstmt);
489038fd1498Szrj       rhs2 = negate_value (rhs2, &gsi);
489138fd1498Szrj 
489238fd1498Szrj       gsi = gsi_for_stmt (negatedefstmt);
489338fd1498Szrj       lhs = make_ssa_name (TREE_TYPE (lhs));
489438fd1498Szrj       gimple_set_visited (negatedefstmt, true);
489538fd1498Szrj       g = gimple_build_assign (lhs, PLUS_EXPR, rhs1, rhs2);
489638fd1498Szrj       gimple_set_uid (g, gimple_uid (negatedefstmt));
489738fd1498Szrj       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
489838fd1498Szrj       return lhs;
489938fd1498Szrj     }
490038fd1498Szrj 
490138fd1498Szrj   tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
490238fd1498Szrj   resultofnegate = force_gimple_operand_gsi (gsip, tonegate, true,
490338fd1498Szrj 					     NULL_TREE, true, GSI_SAME_STMT);
490438fd1498Szrj   gsi = *gsip;
490538fd1498Szrj   uid = gimple_uid (gsi_stmt (gsi));
490638fd1498Szrj   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
490738fd1498Szrj     {
490838fd1498Szrj       gimple *stmt = gsi_stmt (gsi);
490938fd1498Szrj       if (gimple_uid (stmt) != 0)
491038fd1498Szrj 	break;
491138fd1498Szrj       gimple_set_uid (stmt, uid);
491238fd1498Szrj     }
491338fd1498Szrj   return resultofnegate;
491438fd1498Szrj }
491538fd1498Szrj 
491638fd1498Szrj /* Return true if we should break up the subtract in STMT into an add
491738fd1498Szrj    with negate.  This is true when we the subtract operands are really
491838fd1498Szrj    adds, or the subtract itself is used in an add expression.  In
491938fd1498Szrj    either case, breaking up the subtract into an add with negate
492038fd1498Szrj    exposes the adds to reassociation.  */
492138fd1498Szrj 
492238fd1498Szrj static bool
should_break_up_subtract(gimple * stmt)492338fd1498Szrj should_break_up_subtract (gimple *stmt)
492438fd1498Szrj {
492538fd1498Szrj   tree lhs = gimple_assign_lhs (stmt);
492638fd1498Szrj   tree binlhs = gimple_assign_rhs1 (stmt);
492738fd1498Szrj   tree binrhs = gimple_assign_rhs2 (stmt);
492838fd1498Szrj   gimple *immusestmt;
492938fd1498Szrj   struct loop *loop = loop_containing_stmt (stmt);
493038fd1498Szrj 
493138fd1498Szrj   if (TREE_CODE (binlhs) == SSA_NAME
493238fd1498Szrj       && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR, loop))
493338fd1498Szrj     return true;
493438fd1498Szrj 
493538fd1498Szrj   if (TREE_CODE (binrhs) == SSA_NAME
493638fd1498Szrj       && is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), PLUS_EXPR, loop))
493738fd1498Szrj     return true;
493838fd1498Szrj 
493938fd1498Szrj   if (TREE_CODE (lhs) == SSA_NAME
494038fd1498Szrj       && (immusestmt = get_single_immediate_use (lhs))
494138fd1498Szrj       && is_gimple_assign (immusestmt)
494238fd1498Szrj       && (gimple_assign_rhs_code (immusestmt) == PLUS_EXPR
494338fd1498Szrj 	  || (gimple_assign_rhs_code (immusestmt) == MINUS_EXPR
494438fd1498Szrj 	      && gimple_assign_rhs1 (immusestmt) == lhs)
494538fd1498Szrj 	  || gimple_assign_rhs_code (immusestmt) == MULT_EXPR))
494638fd1498Szrj     return true;
494738fd1498Szrj   return false;
494838fd1498Szrj }
494938fd1498Szrj 
495038fd1498Szrj /* Transform STMT from A - B into A + -B.  */
495138fd1498Szrj 
495238fd1498Szrj static void
break_up_subtract(gimple * stmt,gimple_stmt_iterator * gsip)495338fd1498Szrj break_up_subtract (gimple *stmt, gimple_stmt_iterator *gsip)
495438fd1498Szrj {
495538fd1498Szrj   tree rhs1 = gimple_assign_rhs1 (stmt);
495638fd1498Szrj   tree rhs2 = gimple_assign_rhs2 (stmt);
495738fd1498Szrj 
495838fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
495938fd1498Szrj     {
496038fd1498Szrj       fprintf (dump_file, "Breaking up subtract ");
496138fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
496238fd1498Szrj     }
496338fd1498Szrj 
496438fd1498Szrj   rhs2 = negate_value (rhs2, gsip);
496538fd1498Szrj   gimple_assign_set_rhs_with_ops (gsip, PLUS_EXPR, rhs1, rhs2);
496638fd1498Szrj   update_stmt (stmt);
496738fd1498Szrj }
496838fd1498Szrj 
496938fd1498Szrj /* Determine whether STMT is a builtin call that raises an SSA name
497038fd1498Szrj    to an integer power and has only one use.  If so, and this is early
497138fd1498Szrj    reassociation and unsafe math optimizations are permitted, place
497238fd1498Szrj    the SSA name in *BASE and the exponent in *EXPONENT, and return TRUE.
497338fd1498Szrj    If any of these conditions does not hold, return FALSE.  */
497438fd1498Szrj 
497538fd1498Szrj static bool
acceptable_pow_call(gcall * stmt,tree * base,HOST_WIDE_INT * exponent)497638fd1498Szrj acceptable_pow_call (gcall *stmt, tree *base, HOST_WIDE_INT *exponent)
497738fd1498Szrj {
497838fd1498Szrj   tree arg1;
497938fd1498Szrj   REAL_VALUE_TYPE c, cint;
498038fd1498Szrj 
498138fd1498Szrj   switch (gimple_call_combined_fn (stmt))
498238fd1498Szrj     {
498338fd1498Szrj     CASE_CFN_POW:
498438fd1498Szrj       if (flag_errno_math)
498538fd1498Szrj 	return false;
498638fd1498Szrj 
498738fd1498Szrj       *base = gimple_call_arg (stmt, 0);
498838fd1498Szrj       arg1 = gimple_call_arg (stmt, 1);
498938fd1498Szrj 
499038fd1498Szrj       if (TREE_CODE (arg1) != REAL_CST)
499138fd1498Szrj 	return false;
499238fd1498Szrj 
499338fd1498Szrj       c = TREE_REAL_CST (arg1);
499438fd1498Szrj 
499538fd1498Szrj       if (REAL_EXP (&c) > HOST_BITS_PER_WIDE_INT)
499638fd1498Szrj 	return false;
499738fd1498Szrj 
499838fd1498Szrj       *exponent = real_to_integer (&c);
499938fd1498Szrj       real_from_integer (&cint, VOIDmode, *exponent, SIGNED);
500038fd1498Szrj       if (!real_identical (&c, &cint))
500138fd1498Szrj 	return false;
500238fd1498Szrj 
500338fd1498Szrj       break;
500438fd1498Szrj 
500538fd1498Szrj     CASE_CFN_POWI:
500638fd1498Szrj       *base = gimple_call_arg (stmt, 0);
500738fd1498Szrj       arg1 = gimple_call_arg (stmt, 1);
500838fd1498Szrj 
500938fd1498Szrj       if (!tree_fits_shwi_p (arg1))
501038fd1498Szrj 	return false;
501138fd1498Szrj 
501238fd1498Szrj       *exponent = tree_to_shwi (arg1);
501338fd1498Szrj       break;
501438fd1498Szrj 
501538fd1498Szrj     default:
501638fd1498Szrj       return false;
501738fd1498Szrj     }
501838fd1498Szrj 
501938fd1498Szrj   /* Expanding negative exponents is generally unproductive, so we don't
502038fd1498Szrj      complicate matters with those.  Exponents of zero and one should
502138fd1498Szrj      have been handled by expression folding.  */
502238fd1498Szrj   if (*exponent < 2 || TREE_CODE (*base) != SSA_NAME)
502338fd1498Szrj     return false;
502438fd1498Szrj 
502538fd1498Szrj   return true;
502638fd1498Szrj }
502738fd1498Szrj 
502838fd1498Szrj /* Try to derive and add operand entry for OP to *OPS.  Return false if
502938fd1498Szrj    unsuccessful.  */
503038fd1498Szrj 
503138fd1498Szrj static bool
try_special_add_to_ops(vec<operand_entry * > * ops,enum tree_code code,tree op,gimple * def_stmt)503238fd1498Szrj try_special_add_to_ops (vec<operand_entry *> *ops,
503338fd1498Szrj 			enum tree_code code,
503438fd1498Szrj 			tree op, gimple* def_stmt)
503538fd1498Szrj {
503638fd1498Szrj   tree base = NULL_TREE;
503738fd1498Szrj   HOST_WIDE_INT exponent = 0;
503838fd1498Szrj 
503938fd1498Szrj   if (TREE_CODE (op) != SSA_NAME
504038fd1498Szrj       || ! has_single_use (op))
504138fd1498Szrj     return false;
504238fd1498Szrj 
504338fd1498Szrj   if (code == MULT_EXPR
504438fd1498Szrj       && reassoc_insert_powi_p
504538fd1498Szrj       && flag_unsafe_math_optimizations
504638fd1498Szrj       && is_gimple_call (def_stmt)
504738fd1498Szrj       && acceptable_pow_call (as_a <gcall *> (def_stmt), &base, &exponent))
504838fd1498Szrj     {
504938fd1498Szrj       add_repeat_to_ops_vec (ops, base, exponent);
505038fd1498Szrj       gimple_set_visited (def_stmt, true);
505138fd1498Szrj       return true;
505238fd1498Szrj     }
505338fd1498Szrj   else if (code == MULT_EXPR
505438fd1498Szrj 	   && is_gimple_assign (def_stmt)
505538fd1498Szrj 	   && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR
505638fd1498Szrj 	   && !HONOR_SNANS (TREE_TYPE (op))
505738fd1498Szrj 	   && (!HONOR_SIGNED_ZEROS (TREE_TYPE (op))
505838fd1498Szrj 	       || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (op))))
505938fd1498Szrj     {
506038fd1498Szrj       tree rhs1 = gimple_assign_rhs1 (def_stmt);
506138fd1498Szrj       tree cst = build_minus_one_cst (TREE_TYPE (op));
506238fd1498Szrj       add_to_ops_vec (ops, rhs1);
506338fd1498Szrj       add_to_ops_vec (ops, cst);
506438fd1498Szrj       gimple_set_visited (def_stmt, true);
506538fd1498Szrj       return true;
506638fd1498Szrj     }
506738fd1498Szrj 
506838fd1498Szrj   return false;
506938fd1498Szrj }
507038fd1498Szrj 
507138fd1498Szrj /* Recursively linearize a binary expression that is the RHS of STMT.
507238fd1498Szrj    Place the operands of the expression tree in the vector named OPS.  */
507338fd1498Szrj 
507438fd1498Szrj static void
linearize_expr_tree(vec<operand_entry * > * ops,gimple * stmt,bool is_associative,bool set_visited)507538fd1498Szrj linearize_expr_tree (vec<operand_entry *> *ops, gimple *stmt,
507638fd1498Szrj 		     bool is_associative, bool set_visited)
507738fd1498Szrj {
507838fd1498Szrj   tree binlhs = gimple_assign_rhs1 (stmt);
507938fd1498Szrj   tree binrhs = gimple_assign_rhs2 (stmt);
508038fd1498Szrj   gimple *binlhsdef = NULL, *binrhsdef = NULL;
508138fd1498Szrj   bool binlhsisreassoc = false;
508238fd1498Szrj   bool binrhsisreassoc = false;
508338fd1498Szrj   enum tree_code rhscode = gimple_assign_rhs_code (stmt);
508438fd1498Szrj   struct loop *loop = loop_containing_stmt (stmt);
508538fd1498Szrj 
508638fd1498Szrj   if (set_visited)
508738fd1498Szrj     gimple_set_visited (stmt, true);
508838fd1498Szrj 
508938fd1498Szrj   if (TREE_CODE (binlhs) == SSA_NAME)
509038fd1498Szrj     {
509138fd1498Szrj       binlhsdef = SSA_NAME_DEF_STMT (binlhs);
509238fd1498Szrj       binlhsisreassoc = (is_reassociable_op (binlhsdef, rhscode, loop)
509338fd1498Szrj 			 && !stmt_could_throw_p (binlhsdef));
509438fd1498Szrj     }
509538fd1498Szrj 
509638fd1498Szrj   if (TREE_CODE (binrhs) == SSA_NAME)
509738fd1498Szrj     {
509838fd1498Szrj       binrhsdef = SSA_NAME_DEF_STMT (binrhs);
509938fd1498Szrj       binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
510038fd1498Szrj 			 && !stmt_could_throw_p (binrhsdef));
510138fd1498Szrj     }
510238fd1498Szrj 
510338fd1498Szrj   /* If the LHS is not reassociable, but the RHS is, we need to swap
510438fd1498Szrj      them.  If neither is reassociable, there is nothing we can do, so
510538fd1498Szrj      just put them in the ops vector.  If the LHS is reassociable,
510638fd1498Szrj      linearize it.  If both are reassociable, then linearize the RHS
510738fd1498Szrj      and the LHS.  */
510838fd1498Szrj 
510938fd1498Szrj   if (!binlhsisreassoc)
511038fd1498Szrj     {
511138fd1498Szrj       /* If this is not a associative operation like division, give up.  */
511238fd1498Szrj       if (!is_associative)
511338fd1498Szrj 	{
511438fd1498Szrj 	  add_to_ops_vec (ops, binrhs);
511538fd1498Szrj 	  return;
511638fd1498Szrj 	}
511738fd1498Szrj 
511838fd1498Szrj       if (!binrhsisreassoc)
511938fd1498Szrj 	{
512038fd1498Szrj 	  if (!try_special_add_to_ops (ops, rhscode, binrhs, binrhsdef))
512138fd1498Szrj 	    add_to_ops_vec (ops, binrhs);
512238fd1498Szrj 
512338fd1498Szrj 	  if (!try_special_add_to_ops (ops, rhscode, binlhs, binlhsdef))
512438fd1498Szrj 	    add_to_ops_vec (ops, binlhs);
512538fd1498Szrj 
512638fd1498Szrj 	  return;
512738fd1498Szrj 	}
512838fd1498Szrj 
512938fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
513038fd1498Szrj 	{
513138fd1498Szrj 	  fprintf (dump_file, "swapping operands of ");
513238fd1498Szrj 	  print_gimple_stmt (dump_file, stmt, 0);
513338fd1498Szrj 	}
513438fd1498Szrj 
513538fd1498Szrj       swap_ssa_operands (stmt,
513638fd1498Szrj 			 gimple_assign_rhs1_ptr (stmt),
513738fd1498Szrj 			 gimple_assign_rhs2_ptr (stmt));
513838fd1498Szrj       update_stmt (stmt);
513938fd1498Szrj 
514038fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
514138fd1498Szrj 	{
514238fd1498Szrj 	  fprintf (dump_file, " is now ");
514338fd1498Szrj 	  print_gimple_stmt (dump_file, stmt, 0);
514438fd1498Szrj 	}
514538fd1498Szrj 
514638fd1498Szrj       /* We want to make it so the lhs is always the reassociative op,
514738fd1498Szrj 	 so swap.  */
514838fd1498Szrj       std::swap (binlhs, binrhs);
514938fd1498Szrj     }
515038fd1498Szrj   else if (binrhsisreassoc)
515138fd1498Szrj     {
515238fd1498Szrj       linearize_expr (stmt);
515338fd1498Szrj       binlhs = gimple_assign_rhs1 (stmt);
515438fd1498Szrj       binrhs = gimple_assign_rhs2 (stmt);
515538fd1498Szrj     }
515638fd1498Szrj 
515738fd1498Szrj   gcc_assert (TREE_CODE (binrhs) != SSA_NAME
515838fd1498Szrj 	      || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
515938fd1498Szrj 				      rhscode, loop));
516038fd1498Szrj   linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs),
516138fd1498Szrj 		       is_associative, set_visited);
516238fd1498Szrj 
516338fd1498Szrj   if (!try_special_add_to_ops (ops, rhscode, binrhs, binrhsdef))
516438fd1498Szrj     add_to_ops_vec (ops, binrhs);
516538fd1498Szrj }
516638fd1498Szrj 
516738fd1498Szrj /* Repropagate the negates back into subtracts, since no other pass
516838fd1498Szrj    currently does it.  */
516938fd1498Szrj 
517038fd1498Szrj static void
repropagate_negates(void)517138fd1498Szrj repropagate_negates (void)
517238fd1498Szrj {
517338fd1498Szrj   unsigned int i = 0;
517438fd1498Szrj   tree negate;
517538fd1498Szrj 
517638fd1498Szrj   FOR_EACH_VEC_ELT (plus_negates, i, negate)
517738fd1498Szrj     {
517838fd1498Szrj       gimple *user = get_single_immediate_use (negate);
517938fd1498Szrj 
518038fd1498Szrj       if (!user || !is_gimple_assign (user))
518138fd1498Szrj 	continue;
518238fd1498Szrj 
518338fd1498Szrj       /* The negate operand can be either operand of a PLUS_EXPR
518438fd1498Szrj 	 (it can be the LHS if the RHS is a constant for example).
518538fd1498Szrj 
518638fd1498Szrj 	 Force the negate operand to the RHS of the PLUS_EXPR, then
518738fd1498Szrj 	 transform the PLUS_EXPR into a MINUS_EXPR.  */
518838fd1498Szrj       if (gimple_assign_rhs_code (user) == PLUS_EXPR)
518938fd1498Szrj 	{
519038fd1498Szrj 	  /* If the negated operand appears on the LHS of the
519138fd1498Szrj 	     PLUS_EXPR, exchange the operands of the PLUS_EXPR
519238fd1498Szrj 	     to force the negated operand to the RHS of the PLUS_EXPR.  */
519338fd1498Szrj 	  if (gimple_assign_rhs1 (user) == negate)
519438fd1498Szrj 	    {
519538fd1498Szrj 	      swap_ssa_operands (user,
519638fd1498Szrj 				 gimple_assign_rhs1_ptr (user),
519738fd1498Szrj 				 gimple_assign_rhs2_ptr (user));
519838fd1498Szrj 	    }
519938fd1498Szrj 
520038fd1498Szrj 	  /* Now transform the PLUS_EXPR into a MINUS_EXPR and replace
520138fd1498Szrj 	     the RHS of the PLUS_EXPR with the operand of the NEGATE_EXPR.  */
520238fd1498Szrj 	  if (gimple_assign_rhs2 (user) == negate)
520338fd1498Szrj 	    {
520438fd1498Szrj 	      tree rhs1 = gimple_assign_rhs1 (user);
520538fd1498Szrj 	      tree rhs2 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (negate));
520638fd1498Szrj 	      gimple_stmt_iterator gsi = gsi_for_stmt (user);
520738fd1498Szrj 	      gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, rhs1, rhs2);
520838fd1498Szrj 	      update_stmt (user);
520938fd1498Szrj 	    }
521038fd1498Szrj 	}
521138fd1498Szrj       else if (gimple_assign_rhs_code (user) == MINUS_EXPR)
521238fd1498Szrj 	{
521338fd1498Szrj 	  if (gimple_assign_rhs1 (user) == negate)
521438fd1498Szrj 	    {
521538fd1498Szrj 	      /* We have
521638fd1498Szrj 	           x = -a
521738fd1498Szrj 		   y = x - b
521838fd1498Szrj 		 which we transform into
521938fd1498Szrj 		   x = a + b
522038fd1498Szrj 		   y = -x .
522138fd1498Szrj 		 This pushes down the negate which we possibly can merge
522238fd1498Szrj 		 into some other operation, hence insert it into the
522338fd1498Szrj 		 plus_negates vector.  */
522438fd1498Szrj 	      gimple *feed = SSA_NAME_DEF_STMT (negate);
522538fd1498Szrj 	      tree a = gimple_assign_rhs1 (feed);
522638fd1498Szrj 	      tree b = gimple_assign_rhs2 (user);
522738fd1498Szrj 	      gimple_stmt_iterator gsi = gsi_for_stmt (feed);
522838fd1498Szrj 	      gimple_stmt_iterator gsi2 = gsi_for_stmt (user);
522938fd1498Szrj 	      tree x = make_ssa_name (TREE_TYPE (gimple_assign_lhs (feed)));
523038fd1498Szrj 	      gimple *g = gimple_build_assign (x, PLUS_EXPR, a, b);
523138fd1498Szrj 	      gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
523238fd1498Szrj 	      gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, x);
523338fd1498Szrj 	      user = gsi_stmt (gsi2);
523438fd1498Szrj 	      update_stmt (user);
523538fd1498Szrj 	      reassoc_remove_stmt (&gsi);
523638fd1498Szrj 	      release_defs (feed);
523738fd1498Szrj 	      plus_negates.safe_push (gimple_assign_lhs (user));
523838fd1498Szrj 	    }
523938fd1498Szrj 	  else
524038fd1498Szrj 	    {
524138fd1498Szrj 	      /* Transform "x = -a; y = b - x" into "y = b + a", getting
524238fd1498Szrj 	         rid of one operation.  */
524338fd1498Szrj 	      gimple *feed = SSA_NAME_DEF_STMT (negate);
524438fd1498Szrj 	      tree a = gimple_assign_rhs1 (feed);
524538fd1498Szrj 	      tree rhs1 = gimple_assign_rhs1 (user);
524638fd1498Szrj 	      gimple_stmt_iterator gsi = gsi_for_stmt (user);
524738fd1498Szrj 	      gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, rhs1, a);
524838fd1498Szrj 	      update_stmt (gsi_stmt (gsi));
524938fd1498Szrj 	    }
525038fd1498Szrj 	}
525138fd1498Szrj     }
525238fd1498Szrj }
525338fd1498Szrj 
525438fd1498Szrj /* Returns true if OP is of a type for which we can do reassociation.
525538fd1498Szrj    That is for integral or non-saturating fixed-point types, and for
525638fd1498Szrj    floating point type when associative-math is enabled.  */
525738fd1498Szrj 
525838fd1498Szrj static bool
can_reassociate_p(tree op)525938fd1498Szrj can_reassociate_p (tree op)
526038fd1498Szrj {
526138fd1498Szrj   tree type = TREE_TYPE (op);
526238fd1498Szrj   if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
526338fd1498Szrj     return false;
526438fd1498Szrj   if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
526538fd1498Szrj       || NON_SAT_FIXED_POINT_TYPE_P (type)
526638fd1498Szrj       || (flag_associative_math && FLOAT_TYPE_P (type)))
526738fd1498Szrj     return true;
526838fd1498Szrj   return false;
526938fd1498Szrj }
527038fd1498Szrj 
527138fd1498Szrj /* Break up subtract operations in block BB.
527238fd1498Szrj 
527338fd1498Szrj    We do this top down because we don't know whether the subtract is
527438fd1498Szrj    part of a possible chain of reassociation except at the top.
527538fd1498Szrj 
527638fd1498Szrj    IE given
527738fd1498Szrj    d = f + g
527838fd1498Szrj    c = a + e
527938fd1498Szrj    b = c - d
528038fd1498Szrj    q = b - r
528138fd1498Szrj    k = t - q
528238fd1498Szrj 
528338fd1498Szrj    we want to break up k = t - q, but we won't until we've transformed q
528438fd1498Szrj    = b - r, which won't be broken up until we transform b = c - d.
528538fd1498Szrj 
528638fd1498Szrj    En passant, clear the GIMPLE visited flag on every statement
528738fd1498Szrj    and set UIDs within each basic block.  */
528838fd1498Szrj 
528938fd1498Szrj static void
break_up_subtract_bb(basic_block bb)529038fd1498Szrj break_up_subtract_bb (basic_block bb)
529138fd1498Szrj {
529238fd1498Szrj   gimple_stmt_iterator gsi;
529338fd1498Szrj   basic_block son;
529438fd1498Szrj   unsigned int uid = 1;
529538fd1498Szrj 
529638fd1498Szrj   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
529738fd1498Szrj     {
529838fd1498Szrj       gimple *stmt = gsi_stmt (gsi);
529938fd1498Szrj       gimple_set_visited (stmt, false);
530038fd1498Szrj       gimple_set_uid (stmt, uid++);
530138fd1498Szrj 
530238fd1498Szrj       if (!is_gimple_assign (stmt)
530338fd1498Szrj 	  || !can_reassociate_p (gimple_assign_lhs (stmt)))
530438fd1498Szrj 	continue;
530538fd1498Szrj 
530638fd1498Szrj       /* Look for simple gimple subtract operations.  */
530738fd1498Szrj       if (gimple_assign_rhs_code (stmt) == MINUS_EXPR)
530838fd1498Szrj 	{
530938fd1498Szrj 	  if (!can_reassociate_p (gimple_assign_rhs1 (stmt))
531038fd1498Szrj 	      || !can_reassociate_p (gimple_assign_rhs2 (stmt)))
531138fd1498Szrj 	    continue;
531238fd1498Szrj 
531338fd1498Szrj 	  /* Check for a subtract used only in an addition.  If this
531438fd1498Szrj 	     is the case, transform it into add of a negate for better
531538fd1498Szrj 	     reassociation.  IE transform C = A-B into C = A + -B if C
531638fd1498Szrj 	     is only used in an addition.  */
531738fd1498Szrj 	  if (should_break_up_subtract (stmt))
531838fd1498Szrj 	    break_up_subtract (stmt, &gsi);
531938fd1498Szrj 	}
532038fd1498Szrj       else if (gimple_assign_rhs_code (stmt) == NEGATE_EXPR
532138fd1498Szrj 	       && can_reassociate_p (gimple_assign_rhs1 (stmt)))
532238fd1498Szrj 	plus_negates.safe_push (gimple_assign_lhs (stmt));
532338fd1498Szrj     }
532438fd1498Szrj   for (son = first_dom_son (CDI_DOMINATORS, bb);
532538fd1498Szrj        son;
532638fd1498Szrj        son = next_dom_son (CDI_DOMINATORS, son))
532738fd1498Szrj     break_up_subtract_bb (son);
532838fd1498Szrj }
532938fd1498Szrj 
533038fd1498Szrj /* Used for repeated factor analysis.  */
533138fd1498Szrj struct repeat_factor
533238fd1498Szrj {
533338fd1498Szrj   /* An SSA name that occurs in a multiply chain.  */
533438fd1498Szrj   tree factor;
533538fd1498Szrj 
533638fd1498Szrj   /* Cached rank of the factor.  */
533738fd1498Szrj   unsigned rank;
533838fd1498Szrj 
533938fd1498Szrj   /* Number of occurrences of the factor in the chain.  */
534038fd1498Szrj   HOST_WIDE_INT count;
534138fd1498Szrj 
534238fd1498Szrj   /* An SSA name representing the product of this factor and
534338fd1498Szrj      all factors appearing later in the repeated factor vector.  */
534438fd1498Szrj   tree repr;
534538fd1498Szrj };
534638fd1498Szrj 
534738fd1498Szrj 
534838fd1498Szrj static vec<repeat_factor> repeat_factor_vec;
534938fd1498Szrj 
535038fd1498Szrj /* Used for sorting the repeat factor vector.  Sort primarily by
535138fd1498Szrj    ascending occurrence count, secondarily by descending rank.  */
535238fd1498Szrj 
535338fd1498Szrj static int
compare_repeat_factors(const void * x1,const void * x2)535438fd1498Szrj compare_repeat_factors (const void *x1, const void *x2)
535538fd1498Szrj {
535638fd1498Szrj   const repeat_factor *rf1 = (const repeat_factor *) x1;
535738fd1498Szrj   const repeat_factor *rf2 = (const repeat_factor *) x2;
535838fd1498Szrj 
535938fd1498Szrj   if (rf1->count != rf2->count)
536038fd1498Szrj     return rf1->count - rf2->count;
536138fd1498Szrj 
536238fd1498Szrj   return rf2->rank - rf1->rank;
536338fd1498Szrj }
536438fd1498Szrj 
536538fd1498Szrj /* Look for repeated operands in OPS in the multiply tree rooted at
536638fd1498Szrj    STMT.  Replace them with an optimal sequence of multiplies and powi
536738fd1498Szrj    builtin calls, and remove the used operands from OPS.  Return an
536838fd1498Szrj    SSA name representing the value of the replacement sequence.  */
536938fd1498Szrj 
537038fd1498Szrj static tree
attempt_builtin_powi(gimple * stmt,vec<operand_entry * > * ops)537138fd1498Szrj attempt_builtin_powi (gimple *stmt, vec<operand_entry *> *ops)
537238fd1498Szrj {
537338fd1498Szrj   unsigned i, j, vec_len;
537438fd1498Szrj   int ii;
537538fd1498Szrj   operand_entry *oe;
537638fd1498Szrj   repeat_factor *rf1, *rf2;
537738fd1498Szrj   repeat_factor rfnew;
537838fd1498Szrj   tree result = NULL_TREE;
537938fd1498Szrj   tree target_ssa, iter_result;
538038fd1498Szrj   tree type = TREE_TYPE (gimple_get_lhs (stmt));
538138fd1498Szrj   tree powi_fndecl = mathfn_built_in (type, BUILT_IN_POWI);
538238fd1498Szrj   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
538338fd1498Szrj   gimple *mul_stmt, *pow_stmt;
538438fd1498Szrj 
538538fd1498Szrj   /* Nothing to do if BUILT_IN_POWI doesn't exist for this type and
538638fd1498Szrj      target.  */
538738fd1498Szrj   if (!powi_fndecl)
538838fd1498Szrj     return NULL_TREE;
538938fd1498Szrj 
539038fd1498Szrj   /* Allocate the repeated factor vector.  */
539138fd1498Szrj   repeat_factor_vec.create (10);
539238fd1498Szrj 
539338fd1498Szrj   /* Scan the OPS vector for all SSA names in the product and build
539438fd1498Szrj      up a vector of occurrence counts for each factor.  */
539538fd1498Szrj   FOR_EACH_VEC_ELT (*ops, i, oe)
539638fd1498Szrj     {
539738fd1498Szrj       if (TREE_CODE (oe->op) == SSA_NAME)
539838fd1498Szrj 	{
539938fd1498Szrj 	  FOR_EACH_VEC_ELT (repeat_factor_vec, j, rf1)
540038fd1498Szrj 	    {
540138fd1498Szrj 	      if (rf1->factor == oe->op)
540238fd1498Szrj 		{
540338fd1498Szrj 		  rf1->count += oe->count;
540438fd1498Szrj 		  break;
540538fd1498Szrj 		}
540638fd1498Szrj 	    }
540738fd1498Szrj 
540838fd1498Szrj 	  if (j >= repeat_factor_vec.length ())
540938fd1498Szrj 	    {
541038fd1498Szrj 	      rfnew.factor = oe->op;
541138fd1498Szrj 	      rfnew.rank = oe->rank;
541238fd1498Szrj 	      rfnew.count = oe->count;
541338fd1498Szrj 	      rfnew.repr = NULL_TREE;
541438fd1498Szrj 	      repeat_factor_vec.safe_push (rfnew);
541538fd1498Szrj 	    }
541638fd1498Szrj 	}
541738fd1498Szrj     }
541838fd1498Szrj 
541938fd1498Szrj   /* Sort the repeated factor vector by (a) increasing occurrence count,
542038fd1498Szrj      and (b) decreasing rank.  */
542138fd1498Szrj   repeat_factor_vec.qsort (compare_repeat_factors);
542238fd1498Szrj 
542338fd1498Szrj   /* It is generally best to combine as many base factors as possible
542438fd1498Szrj      into a product before applying __builtin_powi to the result.
542538fd1498Szrj      However, the sort order chosen for the repeated factor vector
542638fd1498Szrj      allows us to cache partial results for the product of the base
542738fd1498Szrj      factors for subsequent use.  When we already have a cached partial
542838fd1498Szrj      result from a previous iteration, it is best to make use of it
542938fd1498Szrj      before looking for another __builtin_pow opportunity.
543038fd1498Szrj 
543138fd1498Szrj      As an example, consider x * x * y * y * y * z * z * z * z.
543238fd1498Szrj      We want to first compose the product x * y * z, raise it to the
543338fd1498Szrj      second power, then multiply this by y * z, and finally multiply
543438fd1498Szrj      by z.  This can be done in 5 multiplies provided we cache y * z
543538fd1498Szrj      for use in both expressions:
543638fd1498Szrj 
543738fd1498Szrj         t1 = y * z
543838fd1498Szrj 	t2 = t1 * x
543938fd1498Szrj 	t3 = t2 * t2
544038fd1498Szrj 	t4 = t1 * t3
544138fd1498Szrj 	result = t4 * z
544238fd1498Szrj 
544338fd1498Szrj      If we instead ignored the cached y * z and first multiplied by
544438fd1498Szrj      the __builtin_pow opportunity z * z, we would get the inferior:
544538fd1498Szrj 
544638fd1498Szrj         t1 = y * z
544738fd1498Szrj 	t2 = t1 * x
544838fd1498Szrj 	t3 = t2 * t2
544938fd1498Szrj 	t4 = z * z
545038fd1498Szrj 	t5 = t3 * t4
545138fd1498Szrj         result = t5 * y  */
545238fd1498Szrj 
545338fd1498Szrj   vec_len = repeat_factor_vec.length ();
545438fd1498Szrj 
545538fd1498Szrj   /* Repeatedly look for opportunities to create a builtin_powi call.  */
545638fd1498Szrj   while (true)
545738fd1498Szrj     {
545838fd1498Szrj       HOST_WIDE_INT power;
545938fd1498Szrj 
546038fd1498Szrj       /* First look for the largest cached product of factors from
546138fd1498Szrj 	 preceding iterations.  If found, create a builtin_powi for
546238fd1498Szrj 	 it if the minimum occurrence count for its factors is at
546338fd1498Szrj 	 least 2, or just use this cached product as our next
546438fd1498Szrj 	 multiplicand if the minimum occurrence count is 1.  */
546538fd1498Szrj       FOR_EACH_VEC_ELT (repeat_factor_vec, j, rf1)
546638fd1498Szrj 	{
546738fd1498Szrj 	  if (rf1->repr && rf1->count > 0)
546838fd1498Szrj 	    break;
546938fd1498Szrj 	}
547038fd1498Szrj 
547138fd1498Szrj       if (j < vec_len)
547238fd1498Szrj 	{
547338fd1498Szrj 	  power = rf1->count;
547438fd1498Szrj 
547538fd1498Szrj 	  if (power == 1)
547638fd1498Szrj 	    {
547738fd1498Szrj 	      iter_result = rf1->repr;
547838fd1498Szrj 
547938fd1498Szrj 	      if (dump_file && (dump_flags & TDF_DETAILS))
548038fd1498Szrj 		{
548138fd1498Szrj 		  unsigned elt;
548238fd1498Szrj 		  repeat_factor *rf;
548338fd1498Szrj 		  fputs ("Multiplying by cached product ", dump_file);
548438fd1498Szrj 		  for (elt = j; elt < vec_len; elt++)
548538fd1498Szrj 		    {
548638fd1498Szrj 		      rf = &repeat_factor_vec[elt];
548738fd1498Szrj 		      print_generic_expr (dump_file, rf->factor);
548838fd1498Szrj 		      if (elt < vec_len - 1)
548938fd1498Szrj 			fputs (" * ", dump_file);
549038fd1498Szrj 		    }
549138fd1498Szrj 		  fputs ("\n", dump_file);
549238fd1498Szrj 		}
549338fd1498Szrj 	    }
549438fd1498Szrj 	  else
549538fd1498Szrj 	    {
549638fd1498Szrj 	      iter_result = make_temp_ssa_name (type, NULL, "reassocpow");
549738fd1498Szrj 	      pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr,
549838fd1498Szrj 					    build_int_cst (integer_type_node,
549938fd1498Szrj 							   power));
550038fd1498Szrj 	      gimple_call_set_lhs (pow_stmt, iter_result);
550138fd1498Szrj 	      gimple_set_location (pow_stmt, gimple_location (stmt));
550238fd1498Szrj 	      gimple_set_uid (pow_stmt, gimple_uid (stmt));
550338fd1498Szrj 	      gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT);
550438fd1498Szrj 
550538fd1498Szrj 	      if (dump_file && (dump_flags & TDF_DETAILS))
550638fd1498Szrj 		{
550738fd1498Szrj 		  unsigned elt;
550838fd1498Szrj 		  repeat_factor *rf;
550938fd1498Szrj 		  fputs ("Building __builtin_pow call for cached product (",
551038fd1498Szrj 			 dump_file);
551138fd1498Szrj 		  for (elt = j; elt < vec_len; elt++)
551238fd1498Szrj 		    {
551338fd1498Szrj 		      rf = &repeat_factor_vec[elt];
551438fd1498Szrj 		      print_generic_expr (dump_file, rf->factor);
551538fd1498Szrj 		      if (elt < vec_len - 1)
551638fd1498Szrj 			fputs (" * ", dump_file);
551738fd1498Szrj 		    }
551838fd1498Szrj 		  fprintf (dump_file, ")^" HOST_WIDE_INT_PRINT_DEC"\n",
551938fd1498Szrj 			   power);
552038fd1498Szrj 		}
552138fd1498Szrj 	    }
552238fd1498Szrj 	}
552338fd1498Szrj       else
552438fd1498Szrj 	{
552538fd1498Szrj 	  /* Otherwise, find the first factor in the repeated factor
552638fd1498Szrj 	     vector whose occurrence count is at least 2.  If no such
552738fd1498Szrj 	     factor exists, there are no builtin_powi opportunities
552838fd1498Szrj 	     remaining.  */
552938fd1498Szrj 	  FOR_EACH_VEC_ELT (repeat_factor_vec, j, rf1)
553038fd1498Szrj 	    {
553138fd1498Szrj 	      if (rf1->count >= 2)
553238fd1498Szrj 		break;
553338fd1498Szrj 	    }
553438fd1498Szrj 
553538fd1498Szrj 	  if (j >= vec_len)
553638fd1498Szrj 	    break;
553738fd1498Szrj 
553838fd1498Szrj 	  power = rf1->count;
553938fd1498Szrj 
554038fd1498Szrj 	  if (dump_file && (dump_flags & TDF_DETAILS))
554138fd1498Szrj 	    {
554238fd1498Szrj 	      unsigned elt;
554338fd1498Szrj 	      repeat_factor *rf;
554438fd1498Szrj 	      fputs ("Building __builtin_pow call for (", dump_file);
554538fd1498Szrj 	      for (elt = j; elt < vec_len; elt++)
554638fd1498Szrj 		{
554738fd1498Szrj 		  rf = &repeat_factor_vec[elt];
554838fd1498Szrj 		  print_generic_expr (dump_file, rf->factor);
554938fd1498Szrj 		  if (elt < vec_len - 1)
555038fd1498Szrj 		    fputs (" * ", dump_file);
555138fd1498Szrj 		}
555238fd1498Szrj 	      fprintf (dump_file, ")^" HOST_WIDE_INT_PRINT_DEC"\n", power);
555338fd1498Szrj 	    }
555438fd1498Szrj 
555538fd1498Szrj 	  reassociate_stats.pows_created++;
555638fd1498Szrj 
555738fd1498Szrj 	  /* Visit each element of the vector in reverse order (so that
555838fd1498Szrj 	     high-occurrence elements are visited first, and within the
555938fd1498Szrj 	     same occurrence count, lower-ranked elements are visited
556038fd1498Szrj 	     first).  Form a linear product of all elements in this order
556138fd1498Szrj 	     whose occurrencce count is at least that of element J.
556238fd1498Szrj 	     Record the SSA name representing the product of each element
556338fd1498Szrj 	     with all subsequent elements in the vector.  */
556438fd1498Szrj 	  if (j == vec_len - 1)
556538fd1498Szrj 	    rf1->repr = rf1->factor;
556638fd1498Szrj 	  else
556738fd1498Szrj 	    {
556838fd1498Szrj 	      for (ii = vec_len - 2; ii >= (int)j; ii--)
556938fd1498Szrj 		{
557038fd1498Szrj 		  tree op1, op2;
557138fd1498Szrj 
557238fd1498Szrj 		  rf1 = &repeat_factor_vec[ii];
557338fd1498Szrj 		  rf2 = &repeat_factor_vec[ii + 1];
557438fd1498Szrj 
557538fd1498Szrj 		  /* Init the last factor's representative to be itself.  */
557638fd1498Szrj 		  if (!rf2->repr)
557738fd1498Szrj 		    rf2->repr = rf2->factor;
557838fd1498Szrj 
557938fd1498Szrj 		  op1 = rf1->factor;
558038fd1498Szrj 		  op2 = rf2->repr;
558138fd1498Szrj 
558238fd1498Szrj 		  target_ssa = make_temp_ssa_name (type, NULL, "reassocpow");
558338fd1498Szrj 		  mul_stmt = gimple_build_assign (target_ssa, MULT_EXPR,
558438fd1498Szrj 						  op1, op2);
558538fd1498Szrj 		  gimple_set_location (mul_stmt, gimple_location (stmt));
558638fd1498Szrj 		  gimple_set_uid (mul_stmt, gimple_uid (stmt));
558738fd1498Szrj 		  gsi_insert_before (&gsi, mul_stmt, GSI_SAME_STMT);
558838fd1498Szrj 		  rf1->repr = target_ssa;
558938fd1498Szrj 
559038fd1498Szrj 		  /* Don't reprocess the multiply we just introduced.  */
559138fd1498Szrj 		  gimple_set_visited (mul_stmt, true);
559238fd1498Szrj 		}
559338fd1498Szrj 	    }
559438fd1498Szrj 
559538fd1498Szrj 	  /* Form a call to __builtin_powi for the maximum product
559638fd1498Szrj 	     just formed, raised to the power obtained earlier.  */
559738fd1498Szrj 	  rf1 = &repeat_factor_vec[j];
559838fd1498Szrj 	  iter_result = make_temp_ssa_name (type, NULL, "reassocpow");
559938fd1498Szrj 	  pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr,
560038fd1498Szrj 					build_int_cst (integer_type_node,
560138fd1498Szrj 						       power));
560238fd1498Szrj 	  gimple_call_set_lhs (pow_stmt, iter_result);
560338fd1498Szrj 	  gimple_set_location (pow_stmt, gimple_location (stmt));
560438fd1498Szrj 	  gimple_set_uid (pow_stmt, gimple_uid (stmt));
560538fd1498Szrj 	  gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT);
560638fd1498Szrj 	}
560738fd1498Szrj 
560838fd1498Szrj       /* If we previously formed at least one other builtin_powi call,
560938fd1498Szrj 	 form the product of this one and those others.  */
561038fd1498Szrj       if (result)
561138fd1498Szrj 	{
561238fd1498Szrj 	  tree new_result = make_temp_ssa_name (type, NULL, "reassocpow");
561338fd1498Szrj 	  mul_stmt = gimple_build_assign (new_result, MULT_EXPR,
561438fd1498Szrj 					  result, iter_result);
561538fd1498Szrj 	  gimple_set_location (mul_stmt, gimple_location (stmt));
561638fd1498Szrj 	  gimple_set_uid (mul_stmt, gimple_uid (stmt));
561738fd1498Szrj 	  gsi_insert_before (&gsi, mul_stmt, GSI_SAME_STMT);
561838fd1498Szrj 	  gimple_set_visited (mul_stmt, true);
561938fd1498Szrj 	  result = new_result;
562038fd1498Szrj 	}
562138fd1498Szrj       else
562238fd1498Szrj 	result = iter_result;
562338fd1498Szrj 
562438fd1498Szrj       /* Decrement the occurrence count of each element in the product
562538fd1498Szrj 	 by the count found above, and remove this many copies of each
562638fd1498Szrj 	 factor from OPS.  */
562738fd1498Szrj       for (i = j; i < vec_len; i++)
562838fd1498Szrj 	{
562938fd1498Szrj 	  unsigned k = power;
563038fd1498Szrj 	  unsigned n;
563138fd1498Szrj 
563238fd1498Szrj 	  rf1 = &repeat_factor_vec[i];
563338fd1498Szrj 	  rf1->count -= power;
563438fd1498Szrj 
563538fd1498Szrj 	  FOR_EACH_VEC_ELT_REVERSE (*ops, n, oe)
563638fd1498Szrj 	    {
563738fd1498Szrj 	      if (oe->op == rf1->factor)
563838fd1498Szrj 		{
563938fd1498Szrj 		  if (oe->count <= k)
564038fd1498Szrj 		    {
564138fd1498Szrj 		      ops->ordered_remove (n);
564238fd1498Szrj 		      k -= oe->count;
564338fd1498Szrj 
564438fd1498Szrj 		      if (k == 0)
564538fd1498Szrj 			break;
564638fd1498Szrj 		    }
564738fd1498Szrj 		  else
564838fd1498Szrj 		    {
564938fd1498Szrj 		      oe->count -= k;
565038fd1498Szrj 		      break;
565138fd1498Szrj 		    }
565238fd1498Szrj 		}
565338fd1498Szrj 	    }
565438fd1498Szrj 	}
565538fd1498Szrj     }
565638fd1498Szrj 
565738fd1498Szrj   /* At this point all elements in the repeated factor vector have a
565838fd1498Szrj      remaining occurrence count of 0 or 1, and those with a count of 1
565938fd1498Szrj      don't have cached representatives.  Re-sort the ops vector and
566038fd1498Szrj      clean up.  */
566138fd1498Szrj   ops->qsort (sort_by_operand_rank);
566238fd1498Szrj   repeat_factor_vec.release ();
566338fd1498Szrj 
566438fd1498Szrj   /* Return the final product computed herein.  Note that there may
566538fd1498Szrj      still be some elements with single occurrence count left in OPS;
566638fd1498Szrj      those will be handled by the normal reassociation logic.  */
566738fd1498Szrj   return result;
566838fd1498Szrj }
566938fd1498Szrj 
567038fd1498Szrj /* Attempt to optimize
567138fd1498Szrj    CST1 * copysign (CST2, y) -> copysign (CST1 * CST2, y) if CST1 > 0, or
567238fd1498Szrj    CST1 * copysign (CST2, y) -> -copysign (CST1 * CST2, y) if CST1 < 0.  */
567338fd1498Szrj 
567438fd1498Szrj static void
attempt_builtin_copysign(vec<operand_entry * > * ops)567538fd1498Szrj attempt_builtin_copysign (vec<operand_entry *> *ops)
567638fd1498Szrj {
567738fd1498Szrj   operand_entry *oe;
567838fd1498Szrj   unsigned int i;
567938fd1498Szrj   unsigned int length = ops->length ();
568038fd1498Szrj   tree cst = ops->last ()->op;
568138fd1498Szrj 
568238fd1498Szrj   if (length == 1 || TREE_CODE (cst) != REAL_CST)
568338fd1498Szrj     return;
568438fd1498Szrj 
568538fd1498Szrj   FOR_EACH_VEC_ELT (*ops, i, oe)
568638fd1498Szrj     {
568738fd1498Szrj       if (TREE_CODE (oe->op) == SSA_NAME
568838fd1498Szrj 	  && has_single_use (oe->op))
568938fd1498Szrj 	{
569038fd1498Szrj 	  gimple *def_stmt = SSA_NAME_DEF_STMT (oe->op);
569138fd1498Szrj 	  if (gcall *old_call = dyn_cast <gcall *> (def_stmt))
569238fd1498Szrj 	    {
569338fd1498Szrj 	      tree arg0, arg1;
569438fd1498Szrj 	      switch (gimple_call_combined_fn (old_call))
569538fd1498Szrj 		{
569638fd1498Szrj 		CASE_CFN_COPYSIGN:
569738fd1498Szrj 		CASE_CFN_COPYSIGN_FN:
569838fd1498Szrj 		  arg0 = gimple_call_arg (old_call, 0);
569938fd1498Szrj 		  arg1 = gimple_call_arg (old_call, 1);
570038fd1498Szrj 		  /* The first argument of copysign must be a constant,
570138fd1498Szrj 		     otherwise there's nothing to do.  */
570238fd1498Szrj 		  if (TREE_CODE (arg0) == REAL_CST)
570338fd1498Szrj 		    {
570438fd1498Szrj 		      tree type = TREE_TYPE (arg0);
570538fd1498Szrj 		      tree mul = const_binop (MULT_EXPR, type, cst, arg0);
570638fd1498Szrj 		      /* If we couldn't fold to a single constant, skip it.
570738fd1498Szrj 			 That happens e.g. for inexact multiplication when
570838fd1498Szrj 			 -frounding-math.  */
570938fd1498Szrj 		      if (mul == NULL_TREE)
571038fd1498Szrj 			break;
571138fd1498Szrj 		      /* Instead of adjusting OLD_CALL, let's build a new
571238fd1498Szrj 			 call to not leak the LHS and prevent keeping bogus
571338fd1498Szrj 			 debug statements.  DCE will clean up the old call.  */
571438fd1498Szrj 		      gcall *new_call;
571538fd1498Szrj 		      if (gimple_call_internal_p (old_call))
571638fd1498Szrj 			new_call = gimple_build_call_internal
571738fd1498Szrj 			  (IFN_COPYSIGN, 2, mul, arg1);
571838fd1498Szrj 		      else
571938fd1498Szrj 			new_call = gimple_build_call
572038fd1498Szrj 			  (gimple_call_fndecl (old_call), 2, mul, arg1);
572138fd1498Szrj 		      tree lhs = make_ssa_name (type);
572238fd1498Szrj 		      gimple_call_set_lhs (new_call, lhs);
572338fd1498Szrj 		      gimple_set_location (new_call,
572438fd1498Szrj 					   gimple_location (old_call));
572538fd1498Szrj 		      insert_stmt_after (new_call, old_call);
572638fd1498Szrj 		      /* We've used the constant, get rid of it.  */
572738fd1498Szrj 		      ops->pop ();
572838fd1498Szrj 		      bool cst1_neg = real_isneg (TREE_REAL_CST_PTR (cst));
572938fd1498Szrj 		      /* Handle the CST1 < 0 case by negating the result.  */
573038fd1498Szrj 		      if (cst1_neg)
573138fd1498Szrj 			{
573238fd1498Szrj 			  tree negrhs = make_ssa_name (TREE_TYPE (lhs));
573338fd1498Szrj 			  gimple *negate_stmt
573438fd1498Szrj 			    = gimple_build_assign (negrhs, NEGATE_EXPR, lhs);
573538fd1498Szrj 			  insert_stmt_after (negate_stmt, new_call);
573638fd1498Szrj 			  oe->op = negrhs;
573738fd1498Szrj 			}
573838fd1498Szrj 		      else
573938fd1498Szrj 			oe->op = lhs;
574038fd1498Szrj 		      if (dump_file && (dump_flags & TDF_DETAILS))
574138fd1498Szrj 			{
574238fd1498Szrj 			  fprintf (dump_file, "Optimizing copysign: ");
574338fd1498Szrj 			  print_generic_expr (dump_file, cst);
574438fd1498Szrj 			  fprintf (dump_file, " * COPYSIGN (");
574538fd1498Szrj 			  print_generic_expr (dump_file, arg0);
574638fd1498Szrj 			  fprintf (dump_file, ", ");
574738fd1498Szrj 			  print_generic_expr (dump_file, arg1);
574838fd1498Szrj 			  fprintf (dump_file, ") into %sCOPYSIGN (",
574938fd1498Szrj 				   cst1_neg ? "-" : "");
575038fd1498Szrj 			  print_generic_expr (dump_file, mul);
575138fd1498Szrj 			  fprintf (dump_file, ", ");
575238fd1498Szrj 			  print_generic_expr (dump_file, arg1);
575338fd1498Szrj 			  fprintf (dump_file, "\n");
575438fd1498Szrj 			}
575538fd1498Szrj 		      return;
575638fd1498Szrj 		    }
575738fd1498Szrj 		  break;
575838fd1498Szrj 		default:
575938fd1498Szrj 		  break;
576038fd1498Szrj 		}
576138fd1498Szrj 	    }
576238fd1498Szrj 	}
576338fd1498Szrj     }
576438fd1498Szrj }
576538fd1498Szrj 
576638fd1498Szrj /* Transform STMT at *GSI into a copy by replacing its rhs with NEW_RHS.  */
576738fd1498Szrj 
576838fd1498Szrj static void
transform_stmt_to_copy(gimple_stmt_iterator * gsi,gimple * stmt,tree new_rhs)576938fd1498Szrj transform_stmt_to_copy (gimple_stmt_iterator *gsi, gimple *stmt, tree new_rhs)
577038fd1498Szrj {
577138fd1498Szrj   tree rhs1;
577238fd1498Szrj 
577338fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
577438fd1498Szrj     {
577538fd1498Szrj       fprintf (dump_file, "Transforming ");
577638fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
577738fd1498Szrj     }
577838fd1498Szrj 
577938fd1498Szrj   rhs1 = gimple_assign_rhs1 (stmt);
578038fd1498Szrj   gimple_assign_set_rhs_from_tree (gsi, new_rhs);
578138fd1498Szrj   update_stmt (stmt);
578238fd1498Szrj   remove_visited_stmt_chain (rhs1);
578338fd1498Szrj 
578438fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
578538fd1498Szrj     {
578638fd1498Szrj       fprintf (dump_file, " into ");
578738fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
578838fd1498Szrj     }
578938fd1498Szrj }
579038fd1498Szrj 
579138fd1498Szrj /* Transform STMT at *GSI into a multiply of RHS1 and RHS2.  */
579238fd1498Szrj 
579338fd1498Szrj static void
transform_stmt_to_multiply(gimple_stmt_iterator * gsi,gimple * stmt,tree rhs1,tree rhs2)579438fd1498Szrj transform_stmt_to_multiply (gimple_stmt_iterator *gsi, gimple *stmt,
579538fd1498Szrj 			    tree rhs1, tree rhs2)
579638fd1498Szrj {
579738fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
579838fd1498Szrj     {
579938fd1498Szrj       fprintf (dump_file, "Transforming ");
580038fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
580138fd1498Szrj     }
580238fd1498Szrj 
580338fd1498Szrj   gimple_assign_set_rhs_with_ops (gsi, MULT_EXPR, rhs1, rhs2);
580438fd1498Szrj   update_stmt (gsi_stmt (*gsi));
580538fd1498Szrj   remove_visited_stmt_chain (rhs1);
580638fd1498Szrj 
580738fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
580838fd1498Szrj     {
580938fd1498Szrj       fprintf (dump_file, " into ");
581038fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
581138fd1498Szrj     }
581238fd1498Szrj }
581338fd1498Szrj 
581438fd1498Szrj /* Reassociate expressions in basic block BB and its post-dominator as
581538fd1498Szrj    children.
581638fd1498Szrj 
581738fd1498Szrj    Bubble up return status from maybe_optimize_range_tests.  */
581838fd1498Szrj 
581938fd1498Szrj static bool
reassociate_bb(basic_block bb)582038fd1498Szrj reassociate_bb (basic_block bb)
582138fd1498Szrj {
582238fd1498Szrj   gimple_stmt_iterator gsi;
582338fd1498Szrj   basic_block son;
582438fd1498Szrj   gimple *stmt = last_stmt (bb);
582538fd1498Szrj   bool cfg_cleanup_needed = false;
582638fd1498Szrj 
582738fd1498Szrj   if (stmt && !gimple_visited_p (stmt))
582838fd1498Szrj     cfg_cleanup_needed |= maybe_optimize_range_tests (stmt);
582938fd1498Szrj 
583038fd1498Szrj   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
583138fd1498Szrj     {
583238fd1498Szrj       stmt = gsi_stmt (gsi);
583338fd1498Szrj 
583438fd1498Szrj       if (is_gimple_assign (stmt)
583538fd1498Szrj 	  && !stmt_could_throw_p (stmt))
583638fd1498Szrj 	{
583738fd1498Szrj 	  tree lhs, rhs1, rhs2;
583838fd1498Szrj 	  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
583938fd1498Szrj 
584038fd1498Szrj 	  /* If this is not a gimple binary expression, there is
584138fd1498Szrj 	     nothing for us to do with it.  */
584238fd1498Szrj 	  if (get_gimple_rhs_class (rhs_code) != GIMPLE_BINARY_RHS)
584338fd1498Szrj 	    continue;
584438fd1498Szrj 
584538fd1498Szrj 	  /* If this was part of an already processed statement,
584638fd1498Szrj 	     we don't need to touch it again. */
584738fd1498Szrj 	  if (gimple_visited_p (stmt))
584838fd1498Szrj 	    {
584938fd1498Szrj 	      /* This statement might have become dead because of previous
585038fd1498Szrj 		 reassociations.  */
585138fd1498Szrj 	      if (has_zero_uses (gimple_get_lhs (stmt)))
585238fd1498Szrj 		{
585338fd1498Szrj 		  reassoc_remove_stmt (&gsi);
585438fd1498Szrj 		  release_defs (stmt);
585538fd1498Szrj 		  /* We might end up removing the last stmt above which
585638fd1498Szrj 		     places the iterator to the end of the sequence.
585738fd1498Szrj 		     Reset it to the last stmt in this case which might
585838fd1498Szrj 		     be the end of the sequence as well if we removed
585938fd1498Szrj 		     the last statement of the sequence.  In which case
586038fd1498Szrj 		     we need to bail out.  */
586138fd1498Szrj 		  if (gsi_end_p (gsi))
586238fd1498Szrj 		    {
586338fd1498Szrj 		      gsi = gsi_last_bb (bb);
586438fd1498Szrj 		      if (gsi_end_p (gsi))
586538fd1498Szrj 			break;
586638fd1498Szrj 		    }
586738fd1498Szrj 		}
586838fd1498Szrj 	      continue;
586938fd1498Szrj 	    }
587038fd1498Szrj 
587138fd1498Szrj 	  lhs = gimple_assign_lhs (stmt);
587238fd1498Szrj 	  rhs1 = gimple_assign_rhs1 (stmt);
587338fd1498Szrj 	  rhs2 = gimple_assign_rhs2 (stmt);
587438fd1498Szrj 
587538fd1498Szrj 	  /* For non-bit or min/max operations we can't associate
587638fd1498Szrj 	     all types.  Verify that here.  */
587738fd1498Szrj 	  if (rhs_code != BIT_IOR_EXPR
587838fd1498Szrj 	      && rhs_code != BIT_AND_EXPR
587938fd1498Szrj 	      && rhs_code != BIT_XOR_EXPR
588038fd1498Szrj 	      && rhs_code != MIN_EXPR
588138fd1498Szrj 	      && rhs_code != MAX_EXPR
588238fd1498Szrj 	      && (!can_reassociate_p (lhs)
588338fd1498Szrj 		  || !can_reassociate_p (rhs1)
588438fd1498Szrj 		  || !can_reassociate_p (rhs2)))
588538fd1498Szrj 	    continue;
588638fd1498Szrj 
588738fd1498Szrj 	  if (associative_tree_code (rhs_code))
588838fd1498Szrj 	    {
588938fd1498Szrj 	      auto_vec<operand_entry *> ops;
589038fd1498Szrj 	      tree powi_result = NULL_TREE;
589138fd1498Szrj 	      bool is_vector = VECTOR_TYPE_P (TREE_TYPE (lhs));
589238fd1498Szrj 
589338fd1498Szrj 	      /* There may be no immediate uses left by the time we
589438fd1498Szrj 		 get here because we may have eliminated them all.  */
589538fd1498Szrj 	      if (TREE_CODE (lhs) == SSA_NAME && has_zero_uses (lhs))
589638fd1498Szrj 		continue;
589738fd1498Szrj 
589838fd1498Szrj 	      gimple_set_visited (stmt, true);
589938fd1498Szrj 	      linearize_expr_tree (&ops, stmt, true, true);
590038fd1498Szrj 	      ops.qsort (sort_by_operand_rank);
590138fd1498Szrj 	      int orig_len = ops.length ();
590238fd1498Szrj 	      optimize_ops_list (rhs_code, &ops);
590338fd1498Szrj 	      if (undistribute_ops_list (rhs_code, &ops,
590438fd1498Szrj 					 loop_containing_stmt (stmt)))
590538fd1498Szrj 		{
590638fd1498Szrj 		  ops.qsort (sort_by_operand_rank);
590738fd1498Szrj 		  optimize_ops_list (rhs_code, &ops);
590838fd1498Szrj 		}
590938fd1498Szrj 
591038fd1498Szrj 	      if (rhs_code == PLUS_EXPR
591138fd1498Szrj 		  && transform_add_to_multiply (&ops))
591238fd1498Szrj 		ops.qsort (sort_by_operand_rank);
591338fd1498Szrj 
591438fd1498Szrj 	      if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR)
591538fd1498Szrj 		{
591638fd1498Szrj 		  if (is_vector)
591738fd1498Szrj 		    optimize_vec_cond_expr (rhs_code, &ops);
591838fd1498Szrj 		  else
591938fd1498Szrj 		    optimize_range_tests (rhs_code, &ops, NULL);
592038fd1498Szrj 	        }
592138fd1498Szrj 
592238fd1498Szrj 	      if (rhs_code == MULT_EXPR && !is_vector)
592338fd1498Szrj 	        {
592438fd1498Szrj 		  attempt_builtin_copysign (&ops);
592538fd1498Szrj 
592638fd1498Szrj 		  if (reassoc_insert_powi_p
592738fd1498Szrj 		      && flag_unsafe_math_optimizations)
592838fd1498Szrj 		    powi_result = attempt_builtin_powi (stmt, &ops);
592938fd1498Szrj 		}
593038fd1498Szrj 
593138fd1498Szrj 	      operand_entry *last;
593238fd1498Szrj 	      bool negate_result = false;
593338fd1498Szrj 	      if (ops.length () > 1
593438fd1498Szrj 		  && rhs_code == MULT_EXPR)
593538fd1498Szrj 		{
593638fd1498Szrj 		  last = ops.last ();
593738fd1498Szrj 		  if ((integer_minus_onep (last->op)
593838fd1498Szrj 		       || real_minus_onep (last->op))
593938fd1498Szrj 		      && !HONOR_SNANS (TREE_TYPE (lhs))
594038fd1498Szrj 		      && (!HONOR_SIGNED_ZEROS (TREE_TYPE (lhs))
594138fd1498Szrj 			  || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (lhs))))
594238fd1498Szrj 		    {
594338fd1498Szrj 		      ops.pop ();
594438fd1498Szrj 		      negate_result = true;
594538fd1498Szrj 		    }
594638fd1498Szrj 		}
594738fd1498Szrj 
594838fd1498Szrj 	      tree new_lhs = lhs;
594938fd1498Szrj 	      /* If the operand vector is now empty, all operands were
595038fd1498Szrj 		 consumed by the __builtin_powi optimization.  */
595138fd1498Szrj 	      if (ops.length () == 0)
595238fd1498Szrj 		transform_stmt_to_copy (&gsi, stmt, powi_result);
595338fd1498Szrj 	      else if (ops.length () == 1)
595438fd1498Szrj 		{
595538fd1498Szrj 		  tree last_op = ops.last ()->op;
595638fd1498Szrj 
595738fd1498Szrj 		  /* If the stmt that defines operand has to be inserted, insert it
595838fd1498Szrj 		     before the use.  */
595938fd1498Szrj 		  if (ops.last ()->stmt_to_insert)
596038fd1498Szrj 		    insert_stmt_before_use (stmt, ops.last ()->stmt_to_insert);
596138fd1498Szrj 		  if (powi_result)
596238fd1498Szrj 		    transform_stmt_to_multiply (&gsi, stmt, last_op,
596338fd1498Szrj 						powi_result);
596438fd1498Szrj 		  else
596538fd1498Szrj 		    transform_stmt_to_copy (&gsi, stmt, last_op);
596638fd1498Szrj 		}
596738fd1498Szrj 	      else
596838fd1498Szrj 		{
596938fd1498Szrj 		  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
597038fd1498Szrj 		  int ops_num = ops.length ();
597138fd1498Szrj 		  int width = get_reassociation_width (ops_num, rhs_code, mode);
597238fd1498Szrj 
597338fd1498Szrj 		  if (dump_file && (dump_flags & TDF_DETAILS))
597438fd1498Szrj 		    fprintf (dump_file,
597538fd1498Szrj 			     "Width = %d was chosen for reassociation\n", width);
597638fd1498Szrj 
597738fd1498Szrj 
597838fd1498Szrj 		  /* For binary bit operations, if there are at least 3
597938fd1498Szrj 		     operands and the last last operand in OPS is a constant,
598038fd1498Szrj 		     move it to the front.  This helps ensure that we generate
598138fd1498Szrj 		     (X & Y) & C rather than (X & C) & Y.  The former will
598238fd1498Szrj 		     often match a canonical bit test when we get to RTL.  */
598338fd1498Szrj 		  if (ops.length () > 2
598438fd1498Szrj 		      && (rhs_code == BIT_AND_EXPR
598538fd1498Szrj 		          || rhs_code == BIT_IOR_EXPR
598638fd1498Szrj 		          || rhs_code == BIT_XOR_EXPR)
598738fd1498Szrj 		      && TREE_CODE (ops.last ()->op) == INTEGER_CST)
598838fd1498Szrj 		    std::swap (*ops[0], *ops[ops_num - 1]);
598938fd1498Szrj 
599038fd1498Szrj 		  if (width > 1
599138fd1498Szrj 		      && ops.length () > 3)
599238fd1498Szrj 		    rewrite_expr_tree_parallel (as_a <gassign *> (stmt),
599338fd1498Szrj 						width, ops);
599438fd1498Szrj 		  else
599538fd1498Szrj                     {
599638fd1498Szrj                       /* When there are three operands left, we want
599738fd1498Szrj                          to make sure the ones that get the double
599838fd1498Szrj                          binary op are chosen wisely.  */
599938fd1498Szrj                       int len = ops.length ();
600038fd1498Szrj                       if (len >= 3)
600138fd1498Szrj                         swap_ops_for_binary_stmt (ops, len - 3, stmt);
600238fd1498Szrj 
600338fd1498Szrj 		      new_lhs = rewrite_expr_tree (stmt, 0, ops,
600438fd1498Szrj 						   powi_result != NULL
600538fd1498Szrj 						   || negate_result,
600638fd1498Szrj 						   len != orig_len);
600738fd1498Szrj                     }
600838fd1498Szrj 
600938fd1498Szrj 		  /* If we combined some repeated factors into a
601038fd1498Szrj 		     __builtin_powi call, multiply that result by the
601138fd1498Szrj 		     reassociated operands.  */
601238fd1498Szrj 		  if (powi_result)
601338fd1498Szrj 		    {
601438fd1498Szrj 		      gimple *mul_stmt, *lhs_stmt = SSA_NAME_DEF_STMT (lhs);
601538fd1498Szrj 		      tree type = TREE_TYPE (lhs);
601638fd1498Szrj 		      tree target_ssa = make_temp_ssa_name (type, NULL,
601738fd1498Szrj 							    "reassocpow");
601838fd1498Szrj 		      gimple_set_lhs (lhs_stmt, target_ssa);
601938fd1498Szrj 		      update_stmt (lhs_stmt);
602038fd1498Szrj 		      if (lhs != new_lhs)
602138fd1498Szrj 			{
602238fd1498Szrj 			  target_ssa = new_lhs;
602338fd1498Szrj 			  new_lhs = lhs;
602438fd1498Szrj 			}
602538fd1498Szrj 		      mul_stmt = gimple_build_assign (lhs, MULT_EXPR,
602638fd1498Szrj 						      powi_result, target_ssa);
602738fd1498Szrj 		      gimple_set_location (mul_stmt, gimple_location (stmt));
602838fd1498Szrj 		      gimple_set_uid (mul_stmt, gimple_uid (stmt));
602938fd1498Szrj 		      gsi_insert_after (&gsi, mul_stmt, GSI_NEW_STMT);
603038fd1498Szrj 		    }
603138fd1498Szrj 		}
603238fd1498Szrj 
603338fd1498Szrj 	      if (negate_result)
603438fd1498Szrj 		{
603538fd1498Szrj 		  stmt = SSA_NAME_DEF_STMT (lhs);
603638fd1498Szrj 		  tree tmp = make_ssa_name (TREE_TYPE (lhs));
603738fd1498Szrj 		  gimple_set_lhs (stmt, tmp);
603838fd1498Szrj 		  if (lhs != new_lhs)
603938fd1498Szrj 		    tmp = new_lhs;
604038fd1498Szrj 		  gassign *neg_stmt = gimple_build_assign (lhs, NEGATE_EXPR,
604138fd1498Szrj 							   tmp);
604238fd1498Szrj 		  gimple_set_uid (neg_stmt, gimple_uid (stmt));
604338fd1498Szrj 		  gsi_insert_after (&gsi, neg_stmt, GSI_NEW_STMT);
604438fd1498Szrj 		  update_stmt (stmt);
604538fd1498Szrj 		}
604638fd1498Szrj 	    }
604738fd1498Szrj 	}
604838fd1498Szrj     }
604938fd1498Szrj   for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
605038fd1498Szrj        son;
605138fd1498Szrj        son = next_dom_son (CDI_POST_DOMINATORS, son))
605238fd1498Szrj     cfg_cleanup_needed |= reassociate_bb (son);
605338fd1498Szrj 
605438fd1498Szrj   return cfg_cleanup_needed;
605538fd1498Szrj }
605638fd1498Szrj 
605738fd1498Szrj /* Add jumps around shifts for range tests turned into bit tests.
605838fd1498Szrj    For each SSA_NAME VAR we have code like:
605938fd1498Szrj    VAR = ...; // final stmt of range comparison
606038fd1498Szrj    // bit test here...;
606138fd1498Szrj    OTHERVAR = ...; // final stmt of the bit test sequence
606238fd1498Szrj    RES = VAR | OTHERVAR;
606338fd1498Szrj    Turn the above into:
606438fd1498Szrj    VAR = ...;
606538fd1498Szrj    if (VAR != 0)
606638fd1498Szrj      goto <l3>;
606738fd1498Szrj    else
606838fd1498Szrj      goto <l2>;
606938fd1498Szrj    <l2>:
607038fd1498Szrj    // bit test here...;
607138fd1498Szrj    OTHERVAR = ...;
607238fd1498Szrj    <l3>:
607338fd1498Szrj    # RES = PHI<1(l1), OTHERVAR(l2)>;  */
607438fd1498Szrj 
607538fd1498Szrj static void
branch_fixup(void)607638fd1498Szrj branch_fixup (void)
607738fd1498Szrj {
607838fd1498Szrj   tree var;
607938fd1498Szrj   unsigned int i;
608038fd1498Szrj 
608138fd1498Szrj   FOR_EACH_VEC_ELT (reassoc_branch_fixups, i, var)
608238fd1498Szrj     {
608338fd1498Szrj       gimple *def_stmt = SSA_NAME_DEF_STMT (var);
608438fd1498Szrj       gimple *use_stmt;
608538fd1498Szrj       use_operand_p use;
608638fd1498Szrj       bool ok = single_imm_use (var, &use, &use_stmt);
608738fd1498Szrj       gcc_assert (ok
608838fd1498Szrj 		  && is_gimple_assign (use_stmt)
608938fd1498Szrj 		  && gimple_assign_rhs_code (use_stmt) == BIT_IOR_EXPR
609038fd1498Szrj 		  && gimple_bb (def_stmt) == gimple_bb (use_stmt));
609138fd1498Szrj 
609238fd1498Szrj       basic_block cond_bb = gimple_bb (def_stmt);
609338fd1498Szrj       basic_block then_bb = split_block (cond_bb, def_stmt)->dest;
609438fd1498Szrj       basic_block merge_bb = split_block (then_bb, use_stmt)->dest;
609538fd1498Szrj 
609638fd1498Szrj       gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt);
609738fd1498Szrj       gimple *g = gimple_build_cond (NE_EXPR, var,
609838fd1498Szrj 				     build_zero_cst (TREE_TYPE (var)),
609938fd1498Szrj 				     NULL_TREE, NULL_TREE);
610038fd1498Szrj       location_t loc = gimple_location (use_stmt);
610138fd1498Szrj       gimple_set_location (g, loc);
610238fd1498Szrj       gsi_insert_after (&gsi, g, GSI_NEW_STMT);
610338fd1498Szrj 
610438fd1498Szrj       edge etrue = make_edge (cond_bb, merge_bb, EDGE_TRUE_VALUE);
610538fd1498Szrj       etrue->probability = profile_probability::even ();
610638fd1498Szrj       edge efalse = find_edge (cond_bb, then_bb);
610738fd1498Szrj       efalse->flags = EDGE_FALSE_VALUE;
610838fd1498Szrj       efalse->probability -= etrue->probability;
610938fd1498Szrj       then_bb->count -= etrue->count ();
611038fd1498Szrj 
611138fd1498Szrj       tree othervar = NULL_TREE;
611238fd1498Szrj       if (gimple_assign_rhs1 (use_stmt) == var)
611338fd1498Szrj 	othervar = gimple_assign_rhs2 (use_stmt);
611438fd1498Szrj       else if (gimple_assign_rhs2 (use_stmt) == var)
611538fd1498Szrj 	othervar = gimple_assign_rhs1 (use_stmt);
611638fd1498Szrj       else
611738fd1498Szrj 	gcc_unreachable ();
611838fd1498Szrj       tree lhs = gimple_assign_lhs (use_stmt);
611938fd1498Szrj       gphi *phi = create_phi_node (lhs, merge_bb);
612038fd1498Szrj       add_phi_arg (phi, build_one_cst (TREE_TYPE (lhs)), etrue, loc);
612138fd1498Szrj       add_phi_arg (phi, othervar, single_succ_edge (then_bb), loc);
612238fd1498Szrj       gsi = gsi_for_stmt (use_stmt);
612338fd1498Szrj       gsi_remove (&gsi, true);
612438fd1498Szrj 
612538fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, merge_bb, cond_bb);
612638fd1498Szrj       set_immediate_dominator (CDI_POST_DOMINATORS, cond_bb, merge_bb);
612738fd1498Szrj     }
612838fd1498Szrj   reassoc_branch_fixups.release ();
612938fd1498Szrj }
613038fd1498Szrj 
613138fd1498Szrj void dump_ops_vector (FILE *file, vec<operand_entry *> ops);
613238fd1498Szrj void debug_ops_vector (vec<operand_entry *> ops);
613338fd1498Szrj 
613438fd1498Szrj /* Dump the operand entry vector OPS to FILE.  */
613538fd1498Szrj 
613638fd1498Szrj void
dump_ops_vector(FILE * file,vec<operand_entry * > ops)613738fd1498Szrj dump_ops_vector (FILE *file, vec<operand_entry *> ops)
613838fd1498Szrj {
613938fd1498Szrj   operand_entry *oe;
614038fd1498Szrj   unsigned int i;
614138fd1498Szrj 
614238fd1498Szrj   FOR_EACH_VEC_ELT (ops, i, oe)
614338fd1498Szrj     {
614438fd1498Szrj       fprintf (file, "Op %d -> rank: %d, tree: ", i, oe->rank);
614538fd1498Szrj       print_generic_expr (file, oe->op);
614638fd1498Szrj       fprintf (file, "\n");
614738fd1498Szrj     }
614838fd1498Szrj }
614938fd1498Szrj 
615038fd1498Szrj /* Dump the operand entry vector OPS to STDERR.  */
615138fd1498Szrj 
615238fd1498Szrj DEBUG_FUNCTION void
debug_ops_vector(vec<operand_entry * > ops)615338fd1498Szrj debug_ops_vector (vec<operand_entry *> ops)
615438fd1498Szrj {
615538fd1498Szrj   dump_ops_vector (stderr, ops);
615638fd1498Szrj }
615738fd1498Szrj 
615838fd1498Szrj /* Bubble up return status from reassociate_bb.  */
615938fd1498Szrj 
616038fd1498Szrj static bool
do_reassoc(void)616138fd1498Szrj do_reassoc (void)
616238fd1498Szrj {
616338fd1498Szrj   break_up_subtract_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
616438fd1498Szrj   return reassociate_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
616538fd1498Szrj }
616638fd1498Szrj 
616738fd1498Szrj /* Initialize the reassociation pass.  */
616838fd1498Szrj 
616938fd1498Szrj static void
init_reassoc(void)617038fd1498Szrj init_reassoc (void)
617138fd1498Szrj {
617238fd1498Szrj   int i;
617338fd1498Szrj   long rank = 2;
617438fd1498Szrj   int *bbs = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
617538fd1498Szrj 
617638fd1498Szrj   /* Find the loops, so that we can prevent moving calculations in
617738fd1498Szrj      them.  */
617838fd1498Szrj   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
617938fd1498Szrj 
618038fd1498Szrj   memset (&reassociate_stats, 0, sizeof (reassociate_stats));
618138fd1498Szrj 
618238fd1498Szrj   next_operand_entry_id = 0;
618338fd1498Szrj 
618438fd1498Szrj   /* Reverse RPO (Reverse Post Order) will give us something where
618538fd1498Szrj      deeper loops come later.  */
618638fd1498Szrj   pre_and_rev_post_order_compute (NULL, bbs, false);
618738fd1498Szrj   bb_rank = XCNEWVEC (long, last_basic_block_for_fn (cfun));
618838fd1498Szrj   operand_rank = new hash_map<tree, long>;
618938fd1498Szrj 
619038fd1498Szrj   /* Give each default definition a distinct rank.  This includes
619138fd1498Szrj      parameters and the static chain.  Walk backwards over all
619238fd1498Szrj      SSA names so that we get proper rank ordering according
619338fd1498Szrj      to tree_swap_operands_p.  */
619438fd1498Szrj   for (i = num_ssa_names - 1; i > 0; --i)
619538fd1498Szrj     {
619638fd1498Szrj       tree name = ssa_name (i);
619738fd1498Szrj       if (name && SSA_NAME_IS_DEFAULT_DEF (name))
619838fd1498Szrj 	insert_operand_rank (name, ++rank);
619938fd1498Szrj     }
620038fd1498Szrj 
620138fd1498Szrj   /* Set up rank for each BB  */
620238fd1498Szrj   for (i = 0; i < n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS; i++)
620338fd1498Szrj     bb_rank[bbs[i]] = ++rank << 16;
620438fd1498Szrj 
620538fd1498Szrj   free (bbs);
620638fd1498Szrj   calculate_dominance_info (CDI_POST_DOMINATORS);
620738fd1498Szrj   plus_negates = vNULL;
620838fd1498Szrj }
620938fd1498Szrj 
621038fd1498Szrj /* Cleanup after the reassociation pass, and print stats if
621138fd1498Szrj    requested.  */
621238fd1498Szrj 
621338fd1498Szrj static void
fini_reassoc(void)621438fd1498Szrj fini_reassoc (void)
621538fd1498Szrj {
621638fd1498Szrj   statistics_counter_event (cfun, "Linearized",
621738fd1498Szrj 			    reassociate_stats.linearized);
621838fd1498Szrj   statistics_counter_event (cfun, "Constants eliminated",
621938fd1498Szrj 			    reassociate_stats.constants_eliminated);
622038fd1498Szrj   statistics_counter_event (cfun, "Ops eliminated",
622138fd1498Szrj 			    reassociate_stats.ops_eliminated);
622238fd1498Szrj   statistics_counter_event (cfun, "Statements rewritten",
622338fd1498Szrj 			    reassociate_stats.rewritten);
622438fd1498Szrj   statistics_counter_event (cfun, "Built-in pow[i] calls encountered",
622538fd1498Szrj 			    reassociate_stats.pows_encountered);
622638fd1498Szrj   statistics_counter_event (cfun, "Built-in powi calls created",
622738fd1498Szrj 			    reassociate_stats.pows_created);
622838fd1498Szrj 
622938fd1498Szrj   delete operand_rank;
623038fd1498Szrj   operand_entry_pool.release ();
623138fd1498Szrj   free (bb_rank);
623238fd1498Szrj   plus_negates.release ();
623338fd1498Szrj   free_dominance_info (CDI_POST_DOMINATORS);
623438fd1498Szrj   loop_optimizer_finalize ();
623538fd1498Szrj }
623638fd1498Szrj 
623738fd1498Szrj /* Gate and execute functions for Reassociation.  If INSERT_POWI_P, enable
623838fd1498Szrj    insertion of __builtin_powi calls.
623938fd1498Szrj 
624038fd1498Szrj    Returns TODO_cfg_cleanup if a CFG cleanup pass is desired due to
624138fd1498Szrj    optimization of a gimple conditional.  Otherwise returns zero.  */
624238fd1498Szrj 
624338fd1498Szrj static unsigned int
execute_reassoc(bool insert_powi_p)624438fd1498Szrj execute_reassoc (bool insert_powi_p)
624538fd1498Szrj {
624638fd1498Szrj   reassoc_insert_powi_p = insert_powi_p;
624738fd1498Szrj 
624838fd1498Szrj   init_reassoc ();
624938fd1498Szrj 
625038fd1498Szrj   bool cfg_cleanup_needed;
625138fd1498Szrj   cfg_cleanup_needed = do_reassoc ();
625238fd1498Szrj   repropagate_negates ();
625338fd1498Szrj   branch_fixup ();
625438fd1498Szrj 
625538fd1498Szrj   fini_reassoc ();
625638fd1498Szrj   return cfg_cleanup_needed ? TODO_cleanup_cfg : 0;
625738fd1498Szrj }
625838fd1498Szrj 
625938fd1498Szrj namespace {
626038fd1498Szrj 
626138fd1498Szrj const pass_data pass_data_reassoc =
626238fd1498Szrj {
626338fd1498Szrj   GIMPLE_PASS, /* type */
626438fd1498Szrj   "reassoc", /* name */
626538fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
626638fd1498Szrj   TV_TREE_REASSOC, /* tv_id */
626738fd1498Szrj   ( PROP_cfg | PROP_ssa ), /* properties_required */
626838fd1498Szrj   0, /* properties_provided */
626938fd1498Szrj   0, /* properties_destroyed */
627038fd1498Szrj   0, /* todo_flags_start */
627138fd1498Szrj   TODO_update_ssa_only_virtuals, /* todo_flags_finish */
627238fd1498Szrj };
627338fd1498Szrj 
627438fd1498Szrj class pass_reassoc : public gimple_opt_pass
627538fd1498Szrj {
627638fd1498Szrj public:
pass_reassoc(gcc::context * ctxt)627738fd1498Szrj   pass_reassoc (gcc::context *ctxt)
627838fd1498Szrj     : gimple_opt_pass (pass_data_reassoc, ctxt), insert_powi_p (false)
627938fd1498Szrj   {}
628038fd1498Szrj 
628138fd1498Szrj   /* opt_pass methods: */
clone()628238fd1498Szrj   opt_pass * clone () { return new pass_reassoc (m_ctxt); }
set_pass_param(unsigned int n,bool param)628338fd1498Szrj   void set_pass_param (unsigned int n, bool param)
628438fd1498Szrj     {
628538fd1498Szrj       gcc_assert (n == 0);
628638fd1498Szrj       insert_powi_p = param;
628738fd1498Szrj     }
gate(function *)628838fd1498Szrj   virtual bool gate (function *) { return flag_tree_reassoc != 0; }
execute(function *)628938fd1498Szrj   virtual unsigned int execute (function *)
629038fd1498Szrj     { return execute_reassoc (insert_powi_p); }
629138fd1498Szrj 
629238fd1498Szrj  private:
629338fd1498Szrj   /* Enable insertion of __builtin_powi calls during execute_reassoc.  See
629438fd1498Szrj      point 3a in the pass header comment.  */
629538fd1498Szrj   bool insert_powi_p;
629638fd1498Szrj }; // class pass_reassoc
629738fd1498Szrj 
629838fd1498Szrj } // anon namespace
629938fd1498Szrj 
630038fd1498Szrj gimple_opt_pass *
make_pass_reassoc(gcc::context * ctxt)630138fd1498Szrj make_pass_reassoc (gcc::context *ctxt)
630238fd1498Szrj {
630338fd1498Szrj   return new pass_reassoc (ctxt);
630438fd1498Szrj }
6305