annotate gcc/tree-ssa-phiopt.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Optimization of PHI nodes by converting them into straightline code.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2004-2018 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Free Software Foundation; either version 3, or (at your option) any
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 later version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
111
kono
parents: 67
diff changeset
23 #include "backend.h"
kono
parents: 67
diff changeset
24 #include "insn-codes.h"
kono
parents: 67
diff changeset
25 #include "rtl.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 #include "tree.h"
111
kono
parents: 67
diff changeset
27 #include "gimple.h"
kono
parents: 67
diff changeset
28 #include "cfghooks.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 #include "tree-pass.h"
111
kono
parents: 67
diff changeset
30 #include "ssa.h"
kono
parents: 67
diff changeset
31 #include "optabs-tree.h"
kono
parents: 67
diff changeset
32 #include "insn-config.h"
kono
parents: 67
diff changeset
33 #include "gimple-pretty-print.h"
kono
parents: 67
diff changeset
34 #include "fold-const.h"
kono
parents: 67
diff changeset
35 #include "stor-layout.h"
kono
parents: 67
diff changeset
36 #include "cfganal.h"
kono
parents: 67
diff changeset
37 #include "gimplify.h"
kono
parents: 67
diff changeset
38 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
39 #include "gimplify-me.h"
kono
parents: 67
diff changeset
40 #include "tree-cfg.h"
kono
parents: 67
diff changeset
41 #include "tree-dfa.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 #include "domwalk.h"
111
kono
parents: 67
diff changeset
43 #include "cfgloop.h"
kono
parents: 67
diff changeset
44 #include "tree-data-ref.h"
kono
parents: 67
diff changeset
45 #include "tree-scalar-evolution.h"
kono
parents: 67
diff changeset
46 #include "tree-inline.h"
kono
parents: 67
diff changeset
47 #include "params.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
48 #include "case-cfn-macros.h"
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
49
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
50 static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 static bool conditional_replacement (basic_block, basic_block,
111
kono
parents: 67
diff changeset
52 edge, edge, gphi *, tree, tree);
kono
parents: 67
diff changeset
53 static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
kono
parents: 67
diff changeset
54 gimple *);
kono
parents: 67
diff changeset
55 static int value_replacement (basic_block, basic_block,
kono
parents: 67
diff changeset
56 edge, edge, gimple *, tree, tree);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 static bool minmax_replacement (basic_block, basic_block,
111
kono
parents: 67
diff changeset
58 edge, edge, gimple *, tree, tree);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 static bool abs_replacement (basic_block, basic_block,
111
kono
parents: 67
diff changeset
60 edge, edge, gimple *, tree, tree);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
61 static bool cond_removal_in_popcount_pattern (basic_block, basic_block,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
62 edge, edge, gimple *, tree, tree);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 static bool cond_store_replacement (basic_block, basic_block, edge, edge,
111
kono
parents: 67
diff changeset
64 hash_set<tree> *);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
65 static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
111
kono
parents: 67
diff changeset
66 static hash_set<tree> * get_non_trapping ();
kono
parents: 67
diff changeset
67 static void replace_phi_edge_with_variable (basic_block, edge, gimple *, tree);
kono
parents: 67
diff changeset
68 static void hoist_adjacent_loads (basic_block, basic_block,
kono
parents: 67
diff changeset
69 basic_block, basic_block);
kono
parents: 67
diff changeset
70 static bool gate_hoist_loads (void);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 /* This pass tries to transform conditional stores into unconditional
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 ones, enabling further simplifications with the simpler then and else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 blocks. In particular it replaces this:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 bb0:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 if (cond) goto bb2; else goto bb1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 bb1:
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
79 *p = RHS;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 bb2:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 with
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 bb0:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 if (cond) goto bb1; else goto bb2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 bb1:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 condtmp' = *p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 bb2:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 condtmp = PHI <RHS, condtmp'>
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
90 *p = condtmp;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 This transformation can only be done under several constraints,
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
93 documented below. It also replaces:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
94
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
95 bb0:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
96 if (cond) goto bb2; else goto bb1;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
97 bb1:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
98 *p = RHS1;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
99 goto bb3;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
100 bb2:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
101 *p = RHS2;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
102 bb3:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
103
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
104 with
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
105
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
106 bb0:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
107 if (cond) goto bb3; else goto bb1;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
108 bb1:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
109 bb3:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
110 condtmp = PHI <RHS1, RHS2>
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
111 *p = condtmp; */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 static unsigned int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 tree_ssa_cs_elim (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 {
111
kono
parents: 67
diff changeset
116 unsigned todo;
kono
parents: 67
diff changeset
117 /* ??? We are not interested in loop related info, but the following
kono
parents: 67
diff changeset
118 will create it, ICEing as we didn't init loops with pre-headers.
kono
parents: 67
diff changeset
119 An interfacing issue of find_data_references_in_bb. */
kono
parents: 67
diff changeset
120 loop_optimizer_init (LOOPS_NORMAL);
kono
parents: 67
diff changeset
121 scev_initialize ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
122 todo = tree_ssa_phiopt_worker (true, false, false);
111
kono
parents: 67
diff changeset
123 scev_finalize ();
kono
parents: 67
diff changeset
124 loop_optimizer_finalize ();
kono
parents: 67
diff changeset
125 return todo;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127
111
kono
parents: 67
diff changeset
128 /* Return the singleton PHI in the SEQ of PHIs for edges E0 and E1. */
kono
parents: 67
diff changeset
129
kono
parents: 67
diff changeset
130 static gphi *
kono
parents: 67
diff changeset
131 single_non_singleton_phi_for_edges (gimple_seq seq, edge e0, edge e1)
kono
parents: 67
diff changeset
132 {
kono
parents: 67
diff changeset
133 gimple_stmt_iterator i;
kono
parents: 67
diff changeset
134 gphi *phi = NULL;
kono
parents: 67
diff changeset
135 if (gimple_seq_singleton_p (seq))
kono
parents: 67
diff changeset
136 return as_a <gphi *> (gsi_stmt (gsi_start (seq)));
kono
parents: 67
diff changeset
137 for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
kono
parents: 67
diff changeset
138 {
kono
parents: 67
diff changeset
139 gphi *p = as_a <gphi *> (gsi_stmt (i));
kono
parents: 67
diff changeset
140 /* If the PHI arguments are equal then we can skip this PHI. */
kono
parents: 67
diff changeset
141 if (operand_equal_for_phi_arg_p (gimple_phi_arg_def (p, e0->dest_idx),
kono
parents: 67
diff changeset
142 gimple_phi_arg_def (p, e1->dest_idx)))
kono
parents: 67
diff changeset
143 continue;
kono
parents: 67
diff changeset
144
kono
parents: 67
diff changeset
145 /* If we already have a PHI that has the two edge arguments are
kono
parents: 67
diff changeset
146 different, then return it is not a singleton for these PHIs. */
kono
parents: 67
diff changeset
147 if (phi)
kono
parents: 67
diff changeset
148 return NULL;
kono
parents: 67
diff changeset
149
kono
parents: 67
diff changeset
150 phi = p;
kono
parents: 67
diff changeset
151 }
kono
parents: 67
diff changeset
152 return phi;
kono
parents: 67
diff changeset
153 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 /* The core routine of conditional store replacement and normal
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 phi optimizations. Both share much of the infrastructure in how
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 to match applicable basic block patterns. DO_STORE_ELIM is true
111
kono
parents: 67
diff changeset
158 when we want to do conditional store replacement, false otherwise.
kono
parents: 67
diff changeset
159 DO_HOIST_LOADS is true when we want to hoist adjacent loads out
kono
parents: 67
diff changeset
160 of diamond control flow patterns, false otherwise. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 static unsigned int
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
162 tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 basic_block *bb_order;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 unsigned n, i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 bool cfgchanged = false;
111
kono
parents: 67
diff changeset
168 hash_set<tree> *nontrap = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 if (do_store_elim)
111
kono
parents: 67
diff changeset
171 /* Calculate the set of non-trapping memory accesses. */
kono
parents: 67
diff changeset
172 nontrap = get_non_trapping ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 /* Search every basic block for COND_EXPR we may be able to optimize.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 We walk the blocks in order that guarantees that a block with
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 a single predecessor is processed before the predecessor.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 This ensures that we collapse inner ifs before visiting the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 outer ones, and also that we do not try to visit a removed
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 block. */
111
kono
parents: 67
diff changeset
181 bb_order = single_pred_before_succ_order ();
kono
parents: 67
diff changeset
182 n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
184 for (i = 0; i < n; i++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 {
111
kono
parents: 67
diff changeset
186 gimple *cond_stmt;
kono
parents: 67
diff changeset
187 gphi *phi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 basic_block bb1, bb2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 edge e1, e2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 tree arg0, arg1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 bb = bb_order[i];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 cond_stmt = last_stmt (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 /* Check to see if the last statement is a GIMPLE_COND. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 if (!cond_stmt
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 || gimple_code (cond_stmt) != GIMPLE_COND)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 e1 = EDGE_SUCC (bb, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 bb1 = e1->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 e2 = EDGE_SUCC (bb, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 bb2 = e2->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 /* We cannot do the optimization on abnormal edges. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 if ((e1->flags & EDGE_ABNORMAL) != 0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 || (e2->flags & EDGE_ABNORMAL) != 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 /* If either bb1's succ or bb2 or bb2's succ is non NULL. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 if (EDGE_COUNT (bb1->succs) == 0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 || bb2 == NULL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 || EDGE_COUNT (bb2->succs) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 /* Find the bb which is the fall through to the other. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 if (EDGE_SUCC (bb1, 0)->dest == bb2)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 ;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 else if (EDGE_SUCC (bb2, 0)->dest == bb1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 {
111
kono
parents: 67
diff changeset
221 std::swap (bb1, bb2);
kono
parents: 67
diff changeset
222 std::swap (e1, e2);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 }
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
224 else if (do_store_elim
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
225 && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
226 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
227 basic_block bb3 = EDGE_SUCC (bb1, 0)->dest;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
228
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
229 if (!single_succ_p (bb1)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
230 || (EDGE_SUCC (bb1, 0)->flags & EDGE_FALLTHRU) == 0
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
231 || !single_succ_p (bb2)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
232 || (EDGE_SUCC (bb2, 0)->flags & EDGE_FALLTHRU) == 0
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
233 || EDGE_COUNT (bb3->preds) != 2)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
234 continue;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
235 if (cond_if_else_store_replacement (bb1, bb2, bb3))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
236 cfgchanged = true;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
237 continue;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
238 }
111
kono
parents: 67
diff changeset
239 else if (do_hoist_loads
kono
parents: 67
diff changeset
240 && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
kono
parents: 67
diff changeset
241 {
kono
parents: 67
diff changeset
242 basic_block bb3 = EDGE_SUCC (bb1, 0)->dest;
kono
parents: 67
diff changeset
243
kono
parents: 67
diff changeset
244 if (!FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (cond_stmt)))
kono
parents: 67
diff changeset
245 && single_succ_p (bb1)
kono
parents: 67
diff changeset
246 && single_succ_p (bb2)
kono
parents: 67
diff changeset
247 && single_pred_p (bb1)
kono
parents: 67
diff changeset
248 && single_pred_p (bb2)
kono
parents: 67
diff changeset
249 && EDGE_COUNT (bb->succs) == 2
kono
parents: 67
diff changeset
250 && EDGE_COUNT (bb3->preds) == 2
kono
parents: 67
diff changeset
251 /* If one edge or the other is dominant, a conditional move
kono
parents: 67
diff changeset
252 is likely to perform worse than the well-predicted branch. */
kono
parents: 67
diff changeset
253 && !predictable_edge_p (EDGE_SUCC (bb, 0))
kono
parents: 67
diff changeset
254 && !predictable_edge_p (EDGE_SUCC (bb, 1)))
kono
parents: 67
diff changeset
255 hoist_adjacent_loads (bb, bb1, bb2, bb3);
kono
parents: 67
diff changeset
256 continue;
kono
parents: 67
diff changeset
257 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 else
111
kono
parents: 67
diff changeset
259 continue;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 e1 = EDGE_SUCC (bb1, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 /* Make sure that bb1 is just a fall through. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 if (!single_succ_p (bb1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 || (e1->flags & EDGE_FALLTHRU) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 /* Also make sure that bb1 only have one predecessor and that it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 is bb. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 if (!single_pred_p (bb1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 || single_pred (bb1) != bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 if (do_store_elim)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 /* bb1 is the middle block, bb2 the join block, bb the split block,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 e1 the fallthrough edge from bb1 to bb2. We can't do the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 optimization if the join block has more than two predecessors. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 if (EDGE_COUNT (bb2->preds) > 2)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 if (cond_store_replacement (bb1, bb2, e1, e2, nontrap))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 cfgchanged = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 gimple_seq phis = phi_nodes (bb2);
111
kono
parents: 67
diff changeset
287 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
288 bool candorest = true;
kono
parents: 67
diff changeset
289
kono
parents: 67
diff changeset
290 /* Value replacement can work with more than one PHI
kono
parents: 67
diff changeset
291 so try that first. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
292 if (!early_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
293 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
294 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
295 phi = as_a <gphi *> (gsi_stmt (gsi));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
296 arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
297 arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
298 if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
299 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
300 candorest = false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
301 cfgchanged = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
302 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
303 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
304 }
111
kono
parents: 67
diff changeset
305
kono
parents: 67
diff changeset
306 if (!candorest)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308
111
kono
parents: 67
diff changeset
309 phi = single_non_singleton_phi_for_edges (phis, e1, e2);
kono
parents: 67
diff changeset
310 if (!phi)
kono
parents: 67
diff changeset
311 continue;
kono
parents: 67
diff changeset
312
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 /* Something is wrong if we cannot find the arguments in the PHI
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 node. */
111
kono
parents: 67
diff changeset
318 gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
kono
parents: 67
diff changeset
319
kono
parents: 67
diff changeset
320 gphi *newphi = factor_out_conditional_conversion (e1, e2, phi,
kono
parents: 67
diff changeset
321 arg0, arg1,
kono
parents: 67
diff changeset
322 cond_stmt);
kono
parents: 67
diff changeset
323 if (newphi != NULL)
kono
parents: 67
diff changeset
324 {
kono
parents: 67
diff changeset
325 phi = newphi;
kono
parents: 67
diff changeset
326 /* factor_out_conditional_conversion may create a new PHI in
kono
parents: 67
diff changeset
327 BB2 and eliminate an existing PHI in BB2. Recompute values
kono
parents: 67
diff changeset
328 that may be affected by that change. */
kono
parents: 67
diff changeset
329 arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
kono
parents: 67
diff changeset
330 arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
kono
parents: 67
diff changeset
331 gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
kono
parents: 67
diff changeset
332 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 /* Do the replacement of conditional if it can be done. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
335 if (!early_p
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
336 && conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 cfgchanged = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 cfgchanged = true;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
340 else if (!early_p
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
341 && cond_removal_in_popcount_pattern (bb, bb1, e1, e2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
342 phi, arg0, arg1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
343 cfgchanged = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 cfgchanged = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 free (bb_order);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
350
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 if (do_store_elim)
111
kono
parents: 67
diff changeset
352 delete nontrap;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 /* If the CFG has changed, we should cleanup the CFG. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 if (cfgchanged && do_store_elim)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 /* In cond-store replacement we have added some loads on edges
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 and new VOPS (as we moved the store, and created a load). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 gsi_commit_edge_inserts ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
361 else if (cfgchanged)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 return TODO_cleanup_cfg;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366 /* Replace PHI node element whose edge is E in block BB with variable NEW.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 is known to have two edges, one of which must reach BB). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 replace_phi_edge_with_variable (basic_block cond_block,
111
kono
parents: 67
diff changeset
372 edge e, gimple *phi, tree new_tree)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
373 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
374 basic_block bb = gimple_bb (phi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 basic_block block_to_remove;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 gimple_stmt_iterator gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378 /* Change the PHI argument to new. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 /* Remove the empty basic block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 if (EDGE_SUCC (cond_block, 0)->dest == bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
383 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
111
kono
parents: 67
diff changeset
386 EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 EDGE_SUCC (cond_block, 1)->flags
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
111
kono
parents: 67
diff changeset
395 EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 delete_basic_block (block_to_remove);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 /* Eliminate the COND_EXPR at the end of COND_BLOCK. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 gsi = gsi_last_bb (cond_block);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403 gsi_remove (&gsi, true);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 fprintf (dump_file,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407 "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408 cond_block->index,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 bb->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411
111
kono
parents: 67
diff changeset
412 /* PR66726: Factor conversion out of COND_EXPR. If the arguments of the PHI
kono
parents: 67
diff changeset
413 stmt are CONVERT_STMT, factor out the conversion and perform the conversion
kono
parents: 67
diff changeset
414 to the result of PHI stmt. COND_STMT is the controlling predicate.
kono
parents: 67
diff changeset
415 Return the newly-created PHI, if any. */
kono
parents: 67
diff changeset
416
kono
parents: 67
diff changeset
417 static gphi *
kono
parents: 67
diff changeset
418 factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
kono
parents: 67
diff changeset
419 tree arg0, tree arg1, gimple *cond_stmt)
kono
parents: 67
diff changeset
420 {
kono
parents: 67
diff changeset
421 gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt;
kono
parents: 67
diff changeset
422 tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE;
kono
parents: 67
diff changeset
423 tree temp, result;
kono
parents: 67
diff changeset
424 gphi *newphi;
kono
parents: 67
diff changeset
425 gimple_stmt_iterator gsi, gsi_for_def;
kono
parents: 67
diff changeset
426 source_location locus = gimple_location (phi);
kono
parents: 67
diff changeset
427 enum tree_code convert_code;
kono
parents: 67
diff changeset
428
kono
parents: 67
diff changeset
429 /* Handle only PHI statements with two arguments. TODO: If all
kono
parents: 67
diff changeset
430 other arguments to PHI are INTEGER_CST or if their defining
kono
parents: 67
diff changeset
431 statement have the same unary operation, we can handle more
kono
parents: 67
diff changeset
432 than two arguments too. */
kono
parents: 67
diff changeset
433 if (gimple_phi_num_args (phi) != 2)
kono
parents: 67
diff changeset
434 return NULL;
kono
parents: 67
diff changeset
435
kono
parents: 67
diff changeset
436 /* First canonicalize to simplify tests. */
kono
parents: 67
diff changeset
437 if (TREE_CODE (arg0) != SSA_NAME)
kono
parents: 67
diff changeset
438 {
kono
parents: 67
diff changeset
439 std::swap (arg0, arg1);
kono
parents: 67
diff changeset
440 std::swap (e0, e1);
kono
parents: 67
diff changeset
441 }
kono
parents: 67
diff changeset
442
kono
parents: 67
diff changeset
443 if (TREE_CODE (arg0) != SSA_NAME
kono
parents: 67
diff changeset
444 || (TREE_CODE (arg1) != SSA_NAME
kono
parents: 67
diff changeset
445 && TREE_CODE (arg1) != INTEGER_CST))
kono
parents: 67
diff changeset
446 return NULL;
kono
parents: 67
diff changeset
447
kono
parents: 67
diff changeset
448 /* Check if arg0 is an SSA_NAME and the stmt which defines arg0 is
kono
parents: 67
diff changeset
449 a conversion. */
kono
parents: 67
diff changeset
450 arg0_def_stmt = SSA_NAME_DEF_STMT (arg0);
kono
parents: 67
diff changeset
451 if (!gimple_assign_cast_p (arg0_def_stmt))
kono
parents: 67
diff changeset
452 return NULL;
kono
parents: 67
diff changeset
453
kono
parents: 67
diff changeset
454 /* Use the RHS as new_arg0. */
kono
parents: 67
diff changeset
455 convert_code = gimple_assign_rhs_code (arg0_def_stmt);
kono
parents: 67
diff changeset
456 new_arg0 = gimple_assign_rhs1 (arg0_def_stmt);
kono
parents: 67
diff changeset
457 if (convert_code == VIEW_CONVERT_EXPR)
kono
parents: 67
diff changeset
458 {
kono
parents: 67
diff changeset
459 new_arg0 = TREE_OPERAND (new_arg0, 0);
kono
parents: 67
diff changeset
460 if (!is_gimple_reg_type (TREE_TYPE (new_arg0)))
kono
parents: 67
diff changeset
461 return NULL;
kono
parents: 67
diff changeset
462 }
kono
parents: 67
diff changeset
463
kono
parents: 67
diff changeset
464 if (TREE_CODE (arg1) == SSA_NAME)
kono
parents: 67
diff changeset
465 {
kono
parents: 67
diff changeset
466 /* Check if arg1 is an SSA_NAME and the stmt which defines arg1
kono
parents: 67
diff changeset
467 is a conversion. */
kono
parents: 67
diff changeset
468 arg1_def_stmt = SSA_NAME_DEF_STMT (arg1);
kono
parents: 67
diff changeset
469 if (!is_gimple_assign (arg1_def_stmt)
kono
parents: 67
diff changeset
470 || gimple_assign_rhs_code (arg1_def_stmt) != convert_code)
kono
parents: 67
diff changeset
471 return NULL;
kono
parents: 67
diff changeset
472
kono
parents: 67
diff changeset
473 /* Use the RHS as new_arg1. */
kono
parents: 67
diff changeset
474 new_arg1 = gimple_assign_rhs1 (arg1_def_stmt);
kono
parents: 67
diff changeset
475 if (convert_code == VIEW_CONVERT_EXPR)
kono
parents: 67
diff changeset
476 new_arg1 = TREE_OPERAND (new_arg1, 0);
kono
parents: 67
diff changeset
477 }
kono
parents: 67
diff changeset
478 else
kono
parents: 67
diff changeset
479 {
kono
parents: 67
diff changeset
480 /* If arg1 is an INTEGER_CST, fold it to new type. */
kono
parents: 67
diff changeset
481 if (INTEGRAL_TYPE_P (TREE_TYPE (new_arg0))
kono
parents: 67
diff changeset
482 && int_fits_type_p (arg1, TREE_TYPE (new_arg0)))
kono
parents: 67
diff changeset
483 {
kono
parents: 67
diff changeset
484 if (gimple_assign_cast_p (arg0_def_stmt))
kono
parents: 67
diff changeset
485 {
kono
parents: 67
diff changeset
486 /* For the INTEGER_CST case, we are just moving the
kono
parents: 67
diff changeset
487 conversion from one place to another, which can often
kono
parents: 67
diff changeset
488 hurt as the conversion moves further away from the
kono
parents: 67
diff changeset
489 statement that computes the value. So, perform this
kono
parents: 67
diff changeset
490 only if new_arg0 is an operand of COND_STMT, or
kono
parents: 67
diff changeset
491 if arg0_def_stmt is the only non-debug stmt in
kono
parents: 67
diff changeset
492 its basic block, because then it is possible this
kono
parents: 67
diff changeset
493 could enable further optimizations (minmax replacement
kono
parents: 67
diff changeset
494 etc.). See PR71016. */
kono
parents: 67
diff changeset
495 if (new_arg0 != gimple_cond_lhs (cond_stmt)
kono
parents: 67
diff changeset
496 && new_arg0 != gimple_cond_rhs (cond_stmt)
kono
parents: 67
diff changeset
497 && gimple_bb (arg0_def_stmt) == e0->src)
kono
parents: 67
diff changeset
498 {
kono
parents: 67
diff changeset
499 gsi = gsi_for_stmt (arg0_def_stmt);
kono
parents: 67
diff changeset
500 gsi_prev_nondebug (&gsi);
kono
parents: 67
diff changeset
501 if (!gsi_end_p (gsi))
kono
parents: 67
diff changeset
502 return NULL;
kono
parents: 67
diff changeset
503 gsi = gsi_for_stmt (arg0_def_stmt);
kono
parents: 67
diff changeset
504 gsi_next_nondebug (&gsi);
kono
parents: 67
diff changeset
505 if (!gsi_end_p (gsi))
kono
parents: 67
diff changeset
506 return NULL;
kono
parents: 67
diff changeset
507 }
kono
parents: 67
diff changeset
508 new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1);
kono
parents: 67
diff changeset
509 }
kono
parents: 67
diff changeset
510 else
kono
parents: 67
diff changeset
511 return NULL;
kono
parents: 67
diff changeset
512 }
kono
parents: 67
diff changeset
513 else
kono
parents: 67
diff changeset
514 return NULL;
kono
parents: 67
diff changeset
515 }
kono
parents: 67
diff changeset
516
kono
parents: 67
diff changeset
517 /* If arg0/arg1 have > 1 use, then this transformation actually increases
kono
parents: 67
diff changeset
518 the number of expressions evaluated at runtime. */
kono
parents: 67
diff changeset
519 if (!has_single_use (arg0)
kono
parents: 67
diff changeset
520 || (arg1_def_stmt && !has_single_use (arg1)))
kono
parents: 67
diff changeset
521 return NULL;
kono
parents: 67
diff changeset
522
kono
parents: 67
diff changeset
523 /* If types of new_arg0 and new_arg1 are different bailout. */
kono
parents: 67
diff changeset
524 if (!types_compatible_p (TREE_TYPE (new_arg0), TREE_TYPE (new_arg1)))
kono
parents: 67
diff changeset
525 return NULL;
kono
parents: 67
diff changeset
526
kono
parents: 67
diff changeset
527 /* Create a new PHI stmt. */
kono
parents: 67
diff changeset
528 result = PHI_RESULT (phi);
kono
parents: 67
diff changeset
529 temp = make_ssa_name (TREE_TYPE (new_arg0), NULL);
kono
parents: 67
diff changeset
530 newphi = create_phi_node (temp, gimple_bb (phi));
kono
parents: 67
diff changeset
531
kono
parents: 67
diff changeset
532 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
533 {
kono
parents: 67
diff changeset
534 fprintf (dump_file, "PHI ");
kono
parents: 67
diff changeset
535 print_generic_expr (dump_file, gimple_phi_result (phi));
kono
parents: 67
diff changeset
536 fprintf (dump_file,
kono
parents: 67
diff changeset
537 " changed to factor conversion out from COND_EXPR.\n");
kono
parents: 67
diff changeset
538 fprintf (dump_file, "New stmt with CAST that defines ");
kono
parents: 67
diff changeset
539 print_generic_expr (dump_file, result);
kono
parents: 67
diff changeset
540 fprintf (dump_file, ".\n");
kono
parents: 67
diff changeset
541 }
kono
parents: 67
diff changeset
542
kono
parents: 67
diff changeset
543 /* Remove the old cast(s) that has single use. */
kono
parents: 67
diff changeset
544 gsi_for_def = gsi_for_stmt (arg0_def_stmt);
kono
parents: 67
diff changeset
545 gsi_remove (&gsi_for_def, true);
kono
parents: 67
diff changeset
546 release_defs (arg0_def_stmt);
kono
parents: 67
diff changeset
547
kono
parents: 67
diff changeset
548 if (arg1_def_stmt)
kono
parents: 67
diff changeset
549 {
kono
parents: 67
diff changeset
550 gsi_for_def = gsi_for_stmt (arg1_def_stmt);
kono
parents: 67
diff changeset
551 gsi_remove (&gsi_for_def, true);
kono
parents: 67
diff changeset
552 release_defs (arg1_def_stmt);
kono
parents: 67
diff changeset
553 }
kono
parents: 67
diff changeset
554
kono
parents: 67
diff changeset
555 add_phi_arg (newphi, new_arg0, e0, locus);
kono
parents: 67
diff changeset
556 add_phi_arg (newphi, new_arg1, e1, locus);
kono
parents: 67
diff changeset
557
kono
parents: 67
diff changeset
558 /* Create the conversion stmt and insert it. */
kono
parents: 67
diff changeset
559 if (convert_code == VIEW_CONVERT_EXPR)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
560 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
561 temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
562 new_stmt = gimple_build_assign (result, temp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
563 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
564 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
565 new_stmt = gimple_build_assign (result, convert_code, temp);
111
kono
parents: 67
diff changeset
566 gsi = gsi_after_labels (gimple_bb (phi));
kono
parents: 67
diff changeset
567 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
kono
parents: 67
diff changeset
568
kono
parents: 67
diff changeset
569 /* Remove the original PHI stmt. */
kono
parents: 67
diff changeset
570 gsi = gsi_for_stmt (phi);
kono
parents: 67
diff changeset
571 gsi_remove (&gsi, true);
kono
parents: 67
diff changeset
572 return newphi;
kono
parents: 67
diff changeset
573 }
kono
parents: 67
diff changeset
574
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575 /* The function conditional_replacement does the main work of doing the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 conditional replacement. Return true if the replacement is done.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577 Otherwise return false.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 BB is the basic block where the replacement is going to be done on. ARG0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 is argument 0 from PHI. Likewise for ARG1. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582 conditional_replacement (basic_block cond_bb, basic_block middle_bb,
111
kono
parents: 67
diff changeset
583 edge e0, edge e1, gphi *phi,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584 tree arg0, tree arg1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586 tree result;
111
kono
parents: 67
diff changeset
587 gimple *stmt;
kono
parents: 67
diff changeset
588 gassign *new_stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 tree cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590 gimple_stmt_iterator gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 edge true_edge, false_edge;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 tree new_var, new_var2;
111
kono
parents: 67
diff changeset
593 bool neg;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595 /* FIXME: Gimplification of complex type is too hard for now. */
111
kono
parents: 67
diff changeset
596 /* We aren't prepared to handle vectors either (and it is a question
kono
parents: 67
diff changeset
597 if it would be worthwhile anyway). */
kono
parents: 67
diff changeset
598 if (!(INTEGRAL_TYPE_P (TREE_TYPE (arg0))
kono
parents: 67
diff changeset
599 || POINTER_TYPE_P (TREE_TYPE (arg0)))
kono
parents: 67
diff changeset
600 || !(INTEGRAL_TYPE_P (TREE_TYPE (arg1))
kono
parents: 67
diff changeset
601 || POINTER_TYPE_P (TREE_TYPE (arg1))))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603
111
kono
parents: 67
diff changeset
604 /* The PHI arguments have the constants 0 and 1, or 0 and -1, then
kono
parents: 67
diff changeset
605 convert it to the conditional. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 if ((integer_zerop (arg0) && integer_onep (arg1))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 || (integer_zerop (arg1) && integer_onep (arg0)))
111
kono
parents: 67
diff changeset
608 neg = false;
kono
parents: 67
diff changeset
609 else if ((integer_zerop (arg0) && integer_all_onesp (arg1))
kono
parents: 67
diff changeset
610 || (integer_zerop (arg1) && integer_all_onesp (arg0)))
kono
parents: 67
diff changeset
611 neg = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615 if (!empty_block_p (middle_bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618 /* At this point we know we have a GIMPLE_COND with two successors.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619 One successor is BB, the other successor is an empty block which
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
620 falls through into BB.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
621
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 There is a single PHI node at the join point (BB) and its arguments
111
kono
parents: 67
diff changeset
623 are constants (0, 1) or (0, -1).
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 So, given the condition COND, and the two PHI arguments, we can
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 rewrite this PHI into non-branching code:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628 dest = (COND) or dest = COND'
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630 We use the condition as-is if the argument associated with the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631 true edge has the value one or the argument associated with the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 false edge as the value zero. Note that those conditions are not
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 the same since only one of the outgoing edges from the GIMPLE_COND
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634 will directly reach BB and thus be associated with an argument. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
636 stmt = last_stmt (cond_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637 result = PHI_RESULT (phi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639 /* To handle special cases like floating point comparison, it is easier and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 less error-prone to build a tree and gimplify it on the fly though it is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 less efficient. */
111
kono
parents: 67
diff changeset
642 cond = fold_build2_loc (gimple_location (stmt),
kono
parents: 67
diff changeset
643 gimple_cond_code (stmt), boolean_type_node,
kono
parents: 67
diff changeset
644 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646 /* We need to know which is the true edge and which is the false
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647 edge so that we know when to invert the condition below. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
648 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 if ((e0 == true_edge && integer_zerop (arg0))
111
kono
parents: 67
diff changeset
650 || (e0 == false_edge && !integer_zerop (arg0))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651 || (e1 == true_edge && integer_zerop (arg1))
111
kono
parents: 67
diff changeset
652 || (e1 == false_edge && !integer_zerop (arg1)))
kono
parents: 67
diff changeset
653 cond = fold_build1_loc (gimple_location (stmt),
kono
parents: 67
diff changeset
654 TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
kono
parents: 67
diff changeset
655
kono
parents: 67
diff changeset
656 if (neg)
kono
parents: 67
diff changeset
657 {
kono
parents: 67
diff changeset
658 cond = fold_convert_loc (gimple_location (stmt),
kono
parents: 67
diff changeset
659 TREE_TYPE (result), cond);
kono
parents: 67
diff changeset
660 cond = fold_build1_loc (gimple_location (stmt),
kono
parents: 67
diff changeset
661 NEGATE_EXPR, TREE_TYPE (cond), cond);
kono
parents: 67
diff changeset
662 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
663
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
664 /* Insert our new statements at the end of conditional block before the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665 COND_STMT. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
666 gsi = gsi_for_stmt (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
667 new_var = force_gimple_operand_gsi (&gsi, cond, true, NULL, true,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
668 GSI_SAME_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
669
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (new_var)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
672 source_location locus_0, locus_1;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
673
111
kono
parents: 67
diff changeset
674 new_var2 = make_ssa_name (TREE_TYPE (result));
kono
parents: 67
diff changeset
675 new_stmt = gimple_build_assign (new_var2, CONVERT_EXPR, new_var);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
676 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
677 new_var = new_var2;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
678
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
679 /* Set the locus to the first argument, unless is doesn't have one. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
680 locus_0 = gimple_phi_arg_location (phi, 0);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
681 locus_1 = gimple_phi_arg_location (phi, 1);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
682 if (locus_0 == UNKNOWN_LOCATION)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
683 locus_0 = locus_1;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
684 gimple_set_location (new_stmt, locus_0);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
685 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
686
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
687 replace_phi_edge_with_variable (cond_bb, e1, phi, new_var);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
688
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
689 /* Note that we optimized this PHI. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
690 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
691 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
692
111
kono
parents: 67
diff changeset
693 /* Update *ARG which is defined in STMT so that it contains the
kono
parents: 67
diff changeset
694 computed value if that seems profitable. Return true if the
kono
parents: 67
diff changeset
695 statement is made dead by that rewriting. */
kono
parents: 67
diff changeset
696
kono
parents: 67
diff changeset
697 static bool
kono
parents: 67
diff changeset
698 jump_function_from_stmt (tree *arg, gimple *stmt)
kono
parents: 67
diff changeset
699 {
kono
parents: 67
diff changeset
700 enum tree_code code = gimple_assign_rhs_code (stmt);
kono
parents: 67
diff changeset
701 if (code == ADDR_EXPR)
kono
parents: 67
diff changeset
702 {
kono
parents: 67
diff changeset
703 /* For arg = &p->i transform it to p, if possible. */
kono
parents: 67
diff changeset
704 tree rhs1 = gimple_assign_rhs1 (stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
705 poly_int64 offset;
111
kono
parents: 67
diff changeset
706 tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0),
kono
parents: 67
diff changeset
707 &offset);
kono
parents: 67
diff changeset
708 if (tem
kono
parents: 67
diff changeset
709 && TREE_CODE (tem) == MEM_REF
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
710 && known_eq (mem_ref_offset (tem) + offset, 0))
111
kono
parents: 67
diff changeset
711 {
kono
parents: 67
diff changeset
712 *arg = TREE_OPERAND (tem, 0);
kono
parents: 67
diff changeset
713 return true;
kono
parents: 67
diff changeset
714 }
kono
parents: 67
diff changeset
715 }
kono
parents: 67
diff changeset
716 /* TODO: Much like IPA-CP jump-functions we want to handle constant
kono
parents: 67
diff changeset
717 additions symbolically here, and we'd need to update the comparison
kono
parents: 67
diff changeset
718 code that compares the arg + cst tuples in our caller. For now the
kono
parents: 67
diff changeset
719 code above exactly handles the VEC_BASE pattern from vec.h. */
kono
parents: 67
diff changeset
720 return false;
kono
parents: 67
diff changeset
721 }
kono
parents: 67
diff changeset
722
kono
parents: 67
diff changeset
723 /* RHS is a source argument in a BIT_AND_EXPR which feeds a conditional
kono
parents: 67
diff changeset
724 of the form SSA_NAME NE 0.
kono
parents: 67
diff changeset
725
kono
parents: 67
diff changeset
726 If RHS is fed by a simple EQ_EXPR comparison of two values, see if
kono
parents: 67
diff changeset
727 the two input values of the EQ_EXPR match arg0 and arg1.
kono
parents: 67
diff changeset
728
kono
parents: 67
diff changeset
729 If so update *code and return TRUE. Otherwise return FALSE. */
kono
parents: 67
diff changeset
730
kono
parents: 67
diff changeset
731 static bool
kono
parents: 67
diff changeset
732 rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1,
kono
parents: 67
diff changeset
733 enum tree_code *code, const_tree rhs)
kono
parents: 67
diff changeset
734 {
kono
parents: 67
diff changeset
735 /* Obviously if RHS is not an SSA_NAME, we can't look at the defining
kono
parents: 67
diff changeset
736 statement. */
kono
parents: 67
diff changeset
737 if (TREE_CODE (rhs) == SSA_NAME)
kono
parents: 67
diff changeset
738 {
kono
parents: 67
diff changeset
739 gimple *def1 = SSA_NAME_DEF_STMT (rhs);
kono
parents: 67
diff changeset
740
kono
parents: 67
diff changeset
741 /* Verify the defining statement has an EQ_EXPR on the RHS. */
kono
parents: 67
diff changeset
742 if (is_gimple_assign (def1) && gimple_assign_rhs_code (def1) == EQ_EXPR)
kono
parents: 67
diff changeset
743 {
kono
parents: 67
diff changeset
744 /* Finally verify the source operands of the EQ_EXPR are equal
kono
parents: 67
diff changeset
745 to arg0 and arg1. */
kono
parents: 67
diff changeset
746 tree op0 = gimple_assign_rhs1 (def1);
kono
parents: 67
diff changeset
747 tree op1 = gimple_assign_rhs2 (def1);
kono
parents: 67
diff changeset
748 if ((operand_equal_for_phi_arg_p (arg0, op0)
kono
parents: 67
diff changeset
749 && operand_equal_for_phi_arg_p (arg1, op1))
kono
parents: 67
diff changeset
750 || (operand_equal_for_phi_arg_p (arg0, op1)
kono
parents: 67
diff changeset
751 && operand_equal_for_phi_arg_p (arg1, op0)))
kono
parents: 67
diff changeset
752 {
kono
parents: 67
diff changeset
753 /* We will perform the optimization. */
kono
parents: 67
diff changeset
754 *code = gimple_assign_rhs_code (def1);
kono
parents: 67
diff changeset
755 return true;
kono
parents: 67
diff changeset
756 }
kono
parents: 67
diff changeset
757 }
kono
parents: 67
diff changeset
758 }
kono
parents: 67
diff changeset
759 return false;
kono
parents: 67
diff changeset
760 }
kono
parents: 67
diff changeset
761
kono
parents: 67
diff changeset
762 /* Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND.
kono
parents: 67
diff changeset
763
kono
parents: 67
diff changeset
764 Also return TRUE if arg0/arg1 are equal to the source arguments of a
kono
parents: 67
diff changeset
765 an EQ comparison feeding a BIT_AND_EXPR which feeds COND.
kono
parents: 67
diff changeset
766
kono
parents: 67
diff changeset
767 Return FALSE otherwise. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769 static bool
111
kono
parents: 67
diff changeset
770 operand_equal_for_value_replacement (const_tree arg0, const_tree arg1,
kono
parents: 67
diff changeset
771 enum tree_code *code, gimple *cond)
kono
parents: 67
diff changeset
772 {
kono
parents: 67
diff changeset
773 gimple *def;
kono
parents: 67
diff changeset
774 tree lhs = gimple_cond_lhs (cond);
kono
parents: 67
diff changeset
775 tree rhs = gimple_cond_rhs (cond);
kono
parents: 67
diff changeset
776
kono
parents: 67
diff changeset
777 if ((operand_equal_for_phi_arg_p (arg0, lhs)
kono
parents: 67
diff changeset
778 && operand_equal_for_phi_arg_p (arg1, rhs))
kono
parents: 67
diff changeset
779 || (operand_equal_for_phi_arg_p (arg1, lhs)
kono
parents: 67
diff changeset
780 && operand_equal_for_phi_arg_p (arg0, rhs)))
kono
parents: 67
diff changeset
781 return true;
kono
parents: 67
diff changeset
782
kono
parents: 67
diff changeset
783 /* Now handle more complex case where we have an EQ comparison
kono
parents: 67
diff changeset
784 which feeds a BIT_AND_EXPR which feeds COND.
kono
parents: 67
diff changeset
785
kono
parents: 67
diff changeset
786 First verify that COND is of the form SSA_NAME NE 0. */
kono
parents: 67
diff changeset
787 if (*code != NE_EXPR || !integer_zerop (rhs)
kono
parents: 67
diff changeset
788 || TREE_CODE (lhs) != SSA_NAME)
kono
parents: 67
diff changeset
789 return false;
kono
parents: 67
diff changeset
790
kono
parents: 67
diff changeset
791 /* Now ensure that SSA_NAME is set by a BIT_AND_EXPR. */
kono
parents: 67
diff changeset
792 def = SSA_NAME_DEF_STMT (lhs);
kono
parents: 67
diff changeset
793 if (!is_gimple_assign (def) || gimple_assign_rhs_code (def) != BIT_AND_EXPR)
kono
parents: 67
diff changeset
794 return false;
kono
parents: 67
diff changeset
795
kono
parents: 67
diff changeset
796 /* Now verify arg0/arg1 correspond to the source arguments of an
kono
parents: 67
diff changeset
797 EQ comparison feeding the BIT_AND_EXPR. */
kono
parents: 67
diff changeset
798
kono
parents: 67
diff changeset
799 tree tmp = gimple_assign_rhs1 (def);
kono
parents: 67
diff changeset
800 if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp))
kono
parents: 67
diff changeset
801 return true;
kono
parents: 67
diff changeset
802
kono
parents: 67
diff changeset
803 tmp = gimple_assign_rhs2 (def);
kono
parents: 67
diff changeset
804 if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp))
kono
parents: 67
diff changeset
805 return true;
kono
parents: 67
diff changeset
806
kono
parents: 67
diff changeset
807 return false;
kono
parents: 67
diff changeset
808 }
kono
parents: 67
diff changeset
809
kono
parents: 67
diff changeset
810 /* Returns true if ARG is a neutral element for operation CODE
kono
parents: 67
diff changeset
811 on the RIGHT side. */
kono
parents: 67
diff changeset
812
kono
parents: 67
diff changeset
813 static bool
kono
parents: 67
diff changeset
814 neutral_element_p (tree_code code, tree arg, bool right)
kono
parents: 67
diff changeset
815 {
kono
parents: 67
diff changeset
816 switch (code)
kono
parents: 67
diff changeset
817 {
kono
parents: 67
diff changeset
818 case PLUS_EXPR:
kono
parents: 67
diff changeset
819 case BIT_IOR_EXPR:
kono
parents: 67
diff changeset
820 case BIT_XOR_EXPR:
kono
parents: 67
diff changeset
821 return integer_zerop (arg);
kono
parents: 67
diff changeset
822
kono
parents: 67
diff changeset
823 case LROTATE_EXPR:
kono
parents: 67
diff changeset
824 case RROTATE_EXPR:
kono
parents: 67
diff changeset
825 case LSHIFT_EXPR:
kono
parents: 67
diff changeset
826 case RSHIFT_EXPR:
kono
parents: 67
diff changeset
827 case MINUS_EXPR:
kono
parents: 67
diff changeset
828 case POINTER_PLUS_EXPR:
kono
parents: 67
diff changeset
829 return right && integer_zerop (arg);
kono
parents: 67
diff changeset
830
kono
parents: 67
diff changeset
831 case MULT_EXPR:
kono
parents: 67
diff changeset
832 return integer_onep (arg);
kono
parents: 67
diff changeset
833
kono
parents: 67
diff changeset
834 case TRUNC_DIV_EXPR:
kono
parents: 67
diff changeset
835 case CEIL_DIV_EXPR:
kono
parents: 67
diff changeset
836 case FLOOR_DIV_EXPR:
kono
parents: 67
diff changeset
837 case ROUND_DIV_EXPR:
kono
parents: 67
diff changeset
838 case EXACT_DIV_EXPR:
kono
parents: 67
diff changeset
839 return right && integer_onep (arg);
kono
parents: 67
diff changeset
840
kono
parents: 67
diff changeset
841 case BIT_AND_EXPR:
kono
parents: 67
diff changeset
842 return integer_all_onesp (arg);
kono
parents: 67
diff changeset
843
kono
parents: 67
diff changeset
844 default:
kono
parents: 67
diff changeset
845 return false;
kono
parents: 67
diff changeset
846 }
kono
parents: 67
diff changeset
847 }
kono
parents: 67
diff changeset
848
kono
parents: 67
diff changeset
849 /* Returns true if ARG is an absorbing element for operation CODE. */
kono
parents: 67
diff changeset
850
kono
parents: 67
diff changeset
851 static bool
kono
parents: 67
diff changeset
852 absorbing_element_p (tree_code code, tree arg, bool right, tree rval)
kono
parents: 67
diff changeset
853 {
kono
parents: 67
diff changeset
854 switch (code)
kono
parents: 67
diff changeset
855 {
kono
parents: 67
diff changeset
856 case BIT_IOR_EXPR:
kono
parents: 67
diff changeset
857 return integer_all_onesp (arg);
kono
parents: 67
diff changeset
858
kono
parents: 67
diff changeset
859 case MULT_EXPR:
kono
parents: 67
diff changeset
860 case BIT_AND_EXPR:
kono
parents: 67
diff changeset
861 return integer_zerop (arg);
kono
parents: 67
diff changeset
862
kono
parents: 67
diff changeset
863 case LSHIFT_EXPR:
kono
parents: 67
diff changeset
864 case RSHIFT_EXPR:
kono
parents: 67
diff changeset
865 case LROTATE_EXPR:
kono
parents: 67
diff changeset
866 case RROTATE_EXPR:
kono
parents: 67
diff changeset
867 return !right && integer_zerop (arg);
kono
parents: 67
diff changeset
868
kono
parents: 67
diff changeset
869 case TRUNC_DIV_EXPR:
kono
parents: 67
diff changeset
870 case CEIL_DIV_EXPR:
kono
parents: 67
diff changeset
871 case FLOOR_DIV_EXPR:
kono
parents: 67
diff changeset
872 case ROUND_DIV_EXPR:
kono
parents: 67
diff changeset
873 case EXACT_DIV_EXPR:
kono
parents: 67
diff changeset
874 case TRUNC_MOD_EXPR:
kono
parents: 67
diff changeset
875 case CEIL_MOD_EXPR:
kono
parents: 67
diff changeset
876 case FLOOR_MOD_EXPR:
kono
parents: 67
diff changeset
877 case ROUND_MOD_EXPR:
kono
parents: 67
diff changeset
878 return (!right
kono
parents: 67
diff changeset
879 && integer_zerop (arg)
kono
parents: 67
diff changeset
880 && tree_single_nonzero_warnv_p (rval, NULL));
kono
parents: 67
diff changeset
881
kono
parents: 67
diff changeset
882 default:
kono
parents: 67
diff changeset
883 return false;
kono
parents: 67
diff changeset
884 }
kono
parents: 67
diff changeset
885 }
kono
parents: 67
diff changeset
886
kono
parents: 67
diff changeset
887 /* The function value_replacement does the main work of doing the value
kono
parents: 67
diff changeset
888 replacement. Return non-zero if the replacement is done. Otherwise return
kono
parents: 67
diff changeset
889 0. If we remove the middle basic block, return 2.
kono
parents: 67
diff changeset
890 BB is the basic block where the replacement is going to be done on. ARG0
kono
parents: 67
diff changeset
891 is argument 0 from the PHI. Likewise for ARG1. */
kono
parents: 67
diff changeset
892
kono
parents: 67
diff changeset
893 static int
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
894 value_replacement (basic_block cond_bb, basic_block middle_bb,
111
kono
parents: 67
diff changeset
895 edge e0, edge e1, gimple *phi,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
896 tree arg0, tree arg1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
897 {
111
kono
parents: 67
diff changeset
898 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
899 gimple *cond;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
900 edge true_edge, false_edge;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
901 enum tree_code code;
111
kono
parents: 67
diff changeset
902 bool emtpy_or_with_defined_p = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
903
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
904 /* If the type says honor signed zeros we cannot do this
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
905 optimization. */
111
kono
parents: 67
diff changeset
906 if (HONOR_SIGNED_ZEROS (arg1))
kono
parents: 67
diff changeset
907 return 0;
kono
parents: 67
diff changeset
908
kono
parents: 67
diff changeset
909 /* If there is a statement in MIDDLE_BB that defines one of the PHI
kono
parents: 67
diff changeset
910 arguments, then adjust arg0 or arg1. */
kono
parents: 67
diff changeset
911 gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
kono
parents: 67
diff changeset
912 while (!gsi_end_p (gsi))
kono
parents: 67
diff changeset
913 {
kono
parents: 67
diff changeset
914 gimple *stmt = gsi_stmt (gsi);
kono
parents: 67
diff changeset
915 tree lhs;
kono
parents: 67
diff changeset
916 gsi_next_nondebug (&gsi);
kono
parents: 67
diff changeset
917 if (!is_gimple_assign (stmt))
kono
parents: 67
diff changeset
918 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
919 if (gimple_code (stmt) != GIMPLE_PREDICT
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
920 && gimple_code (stmt) != GIMPLE_NOP)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
921 emtpy_or_with_defined_p = false;
111
kono
parents: 67
diff changeset
922 continue;
kono
parents: 67
diff changeset
923 }
kono
parents: 67
diff changeset
924 /* Now try to adjust arg0 or arg1 according to the computation
kono
parents: 67
diff changeset
925 in the statement. */
kono
parents: 67
diff changeset
926 lhs = gimple_assign_lhs (stmt);
kono
parents: 67
diff changeset
927 if (!(lhs == arg0
kono
parents: 67
diff changeset
928 && jump_function_from_stmt (&arg0, stmt))
kono
parents: 67
diff changeset
929 || (lhs == arg1
kono
parents: 67
diff changeset
930 && jump_function_from_stmt (&arg1, stmt)))
kono
parents: 67
diff changeset
931 emtpy_or_with_defined_p = false;
kono
parents: 67
diff changeset
932 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
933
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
934 cond = last_stmt (cond_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
935 code = gimple_cond_code (cond);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
936
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
937 /* This transformation is only valid for equality comparisons. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
938 if (code != NE_EXPR && code != EQ_EXPR)
111
kono
parents: 67
diff changeset
939 return 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
940
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
941 /* We need to know which is the true edge and which is the false
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
942 edge so that we know if have abs or negative abs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
943 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
944
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
945 /* At this point we know we have a COND_EXPR with two successors.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
946 One successor is BB, the other successor is an empty block which
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947 falls through into BB.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
949 The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
950
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
951 There is a single PHI node at the join point (BB) with two arguments.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
952
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
953 We now need to verify that the two arguments in the PHI node match
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
954 the two arguments to the equality comparison. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
955
111
kono
parents: 67
diff changeset
956 if (operand_equal_for_value_replacement (arg0, arg1, &code, cond))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
957 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
958 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 tree arg;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
961 /* For NE_EXPR, we want to build an assignment result = arg where
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
962 arg is the PHI argument associated with the true edge. For
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
963 EQ_EXPR we want the PHI argument associated with the false edge. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964 e = (code == NE_EXPR ? true_edge : false_edge);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
965
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
966 /* Unfortunately, E may not reach BB (it may instead have gone to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
967 OTHER_BLOCK). If that is the case, then we want the single outgoing
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
968 edge from OTHER_BLOCK which reaches BB and represents the desired
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
969 path from COND_BLOCK. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
970 if (e->dest == middle_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
971 e = single_succ_edge (e->dest);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
972
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
973 /* Now we know the incoming edge to BB that has the argument for the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
974 RHS of our new assignment statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
975 if (e0 == e)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
976 arg = arg0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978 arg = arg1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
979
111
kono
parents: 67
diff changeset
980 /* If the middle basic block was empty or is defining the
kono
parents: 67
diff changeset
981 PHI arguments and this is a single phi where the args are different
kono
parents: 67
diff changeset
982 for the edges e0 and e1 then we can remove the middle basic block. */
kono
parents: 67
diff changeset
983 if (emtpy_or_with_defined_p
kono
parents: 67
diff changeset
984 && single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)),
kono
parents: 67
diff changeset
985 e0, e1) == phi)
kono
parents: 67
diff changeset
986 {
kono
parents: 67
diff changeset
987 replace_phi_edge_with_variable (cond_bb, e1, phi, arg);
kono
parents: 67
diff changeset
988 /* Note that we optimized this PHI. */
kono
parents: 67
diff changeset
989 return 2;
kono
parents: 67
diff changeset
990 }
kono
parents: 67
diff changeset
991 else
kono
parents: 67
diff changeset
992 {
kono
parents: 67
diff changeset
993 /* Replace the PHI arguments with arg. */
kono
parents: 67
diff changeset
994 SET_PHI_ARG_DEF (phi, e0->dest_idx, arg);
kono
parents: 67
diff changeset
995 SET_PHI_ARG_DEF (phi, e1->dest_idx, arg);
kono
parents: 67
diff changeset
996 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
997 {
kono
parents: 67
diff changeset
998 fprintf (dump_file, "PHI ");
kono
parents: 67
diff changeset
999 print_generic_expr (dump_file, gimple_phi_result (phi));
kono
parents: 67
diff changeset
1000 fprintf (dump_file, " reduced for COND_EXPR in block %d to ",
kono
parents: 67
diff changeset
1001 cond_bb->index);
kono
parents: 67
diff changeset
1002 print_generic_expr (dump_file, arg);
kono
parents: 67
diff changeset
1003 fprintf (dump_file, ".\n");
kono
parents: 67
diff changeset
1004 }
kono
parents: 67
diff changeset
1005 return 1;
kono
parents: 67
diff changeset
1006 }
kono
parents: 67
diff changeset
1007
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1008 }
111
kono
parents: 67
diff changeset
1009
kono
parents: 67
diff changeset
1010 /* Now optimize (x != 0) ? x + y : y to just x + y. */
kono
parents: 67
diff changeset
1011 gsi = gsi_last_nondebug_bb (middle_bb);
kono
parents: 67
diff changeset
1012 if (gsi_end_p (gsi))
kono
parents: 67
diff changeset
1013 return 0;
kono
parents: 67
diff changeset
1014
kono
parents: 67
diff changeset
1015 gimple *assign = gsi_stmt (gsi);
kono
parents: 67
diff changeset
1016 if (!is_gimple_assign (assign)
kono
parents: 67
diff changeset
1017 || gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS
kono
parents: 67
diff changeset
1018 || (!INTEGRAL_TYPE_P (TREE_TYPE (arg0))
kono
parents: 67
diff changeset
1019 && !POINTER_TYPE_P (TREE_TYPE (arg0))))
kono
parents: 67
diff changeset
1020 return 0;
kono
parents: 67
diff changeset
1021
kono
parents: 67
diff changeset
1022 /* Punt if there are (degenerate) PHIs in middle_bb, there should not be. */
kono
parents: 67
diff changeset
1023 if (!gimple_seq_empty_p (phi_nodes (middle_bb)))
kono
parents: 67
diff changeset
1024 return 0;
kono
parents: 67
diff changeset
1025
kono
parents: 67
diff changeset
1026 /* Allow up to 2 cheap preparation statements that prepare argument
kono
parents: 67
diff changeset
1027 for assign, e.g.:
kono
parents: 67
diff changeset
1028 if (y_4 != 0)
kono
parents: 67
diff changeset
1029 goto <bb 3>;
kono
parents: 67
diff changeset
1030 else
kono
parents: 67
diff changeset
1031 goto <bb 4>;
kono
parents: 67
diff changeset
1032 <bb 3>:
kono
parents: 67
diff changeset
1033 _1 = (int) y_4;
kono
parents: 67
diff changeset
1034 iftmp.0_6 = x_5(D) r<< _1;
kono
parents: 67
diff changeset
1035 <bb 4>:
kono
parents: 67
diff changeset
1036 # iftmp.0_2 = PHI <iftmp.0_6(3), x_5(D)(2)>
kono
parents: 67
diff changeset
1037 or:
kono
parents: 67
diff changeset
1038 if (y_3(D) == 0)
kono
parents: 67
diff changeset
1039 goto <bb 4>;
kono
parents: 67
diff changeset
1040 else
kono
parents: 67
diff changeset
1041 goto <bb 3>;
kono
parents: 67
diff changeset
1042 <bb 3>:
kono
parents: 67
diff changeset
1043 y_4 = y_3(D) & 31;
kono
parents: 67
diff changeset
1044 _1 = (int) y_4;
kono
parents: 67
diff changeset
1045 _6 = x_5(D) r<< _1;
kono
parents: 67
diff changeset
1046 <bb 4>:
kono
parents: 67
diff changeset
1047 # _2 = PHI <x_5(D)(2), _6(3)> */
kono
parents: 67
diff changeset
1048 gimple *prep_stmt[2] = { NULL, NULL };
kono
parents: 67
diff changeset
1049 int prep_cnt;
kono
parents: 67
diff changeset
1050 for (prep_cnt = 0; ; prep_cnt++)
kono
parents: 67
diff changeset
1051 {
kono
parents: 67
diff changeset
1052 gsi_prev_nondebug (&gsi);
kono
parents: 67
diff changeset
1053 if (gsi_end_p (gsi))
kono
parents: 67
diff changeset
1054 break;
kono
parents: 67
diff changeset
1055
kono
parents: 67
diff changeset
1056 gimple *g = gsi_stmt (gsi);
kono
parents: 67
diff changeset
1057 if (gimple_code (g) == GIMPLE_LABEL)
kono
parents: 67
diff changeset
1058 break;
kono
parents: 67
diff changeset
1059
kono
parents: 67
diff changeset
1060 if (prep_cnt == 2 || !is_gimple_assign (g))
kono
parents: 67
diff changeset
1061 return 0;
kono
parents: 67
diff changeset
1062
kono
parents: 67
diff changeset
1063 tree lhs = gimple_assign_lhs (g);
kono
parents: 67
diff changeset
1064 tree rhs1 = gimple_assign_rhs1 (g);
kono
parents: 67
diff changeset
1065 use_operand_p use_p;
kono
parents: 67
diff changeset
1066 gimple *use_stmt;
kono
parents: 67
diff changeset
1067 if (TREE_CODE (lhs) != SSA_NAME
kono
parents: 67
diff changeset
1068 || TREE_CODE (rhs1) != SSA_NAME
kono
parents: 67
diff changeset
1069 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
kono
parents: 67
diff changeset
1070 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
kono
parents: 67
diff changeset
1071 || !single_imm_use (lhs, &use_p, &use_stmt)
kono
parents: 67
diff changeset
1072 || use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign))
kono
parents: 67
diff changeset
1073 return 0;
kono
parents: 67
diff changeset
1074 switch (gimple_assign_rhs_code (g))
kono
parents: 67
diff changeset
1075 {
kono
parents: 67
diff changeset
1076 CASE_CONVERT:
kono
parents: 67
diff changeset
1077 break;
kono
parents: 67
diff changeset
1078 case PLUS_EXPR:
kono
parents: 67
diff changeset
1079 case BIT_AND_EXPR:
kono
parents: 67
diff changeset
1080 case BIT_IOR_EXPR:
kono
parents: 67
diff changeset
1081 case BIT_XOR_EXPR:
kono
parents: 67
diff changeset
1082 if (TREE_CODE (gimple_assign_rhs2 (g)) != INTEGER_CST)
kono
parents: 67
diff changeset
1083 return 0;
kono
parents: 67
diff changeset
1084 break;
kono
parents: 67
diff changeset
1085 default:
kono
parents: 67
diff changeset
1086 return 0;
kono
parents: 67
diff changeset
1087 }
kono
parents: 67
diff changeset
1088 prep_stmt[prep_cnt] = g;
kono
parents: 67
diff changeset
1089 }
kono
parents: 67
diff changeset
1090
kono
parents: 67
diff changeset
1091 /* Only transform if it removes the condition. */
kono
parents: 67
diff changeset
1092 if (!single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)), e0, e1))
kono
parents: 67
diff changeset
1093 return 0;
kono
parents: 67
diff changeset
1094
kono
parents: 67
diff changeset
1095 /* Size-wise, this is always profitable. */
kono
parents: 67
diff changeset
1096 if (optimize_bb_for_speed_p (cond_bb)
kono
parents: 67
diff changeset
1097 /* The special case is useless if it has a low probability. */
kono
parents: 67
diff changeset
1098 && profile_status_for_fn (cfun) != PROFILE_ABSENT
kono
parents: 67
diff changeset
1099 && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even ()
kono
parents: 67
diff changeset
1100 /* If assign is cheap, there is no point avoiding it. */
kono
parents: 67
diff changeset
1101 && estimate_num_insns (bb_seq (middle_bb), &eni_time_weights)
kono
parents: 67
diff changeset
1102 >= 3 * estimate_num_insns (cond, &eni_time_weights))
kono
parents: 67
diff changeset
1103 return 0;
kono
parents: 67
diff changeset
1104
kono
parents: 67
diff changeset
1105 tree lhs = gimple_assign_lhs (assign);
kono
parents: 67
diff changeset
1106 tree rhs1 = gimple_assign_rhs1 (assign);
kono
parents: 67
diff changeset
1107 tree rhs2 = gimple_assign_rhs2 (assign);
kono
parents: 67
diff changeset
1108 enum tree_code code_def = gimple_assign_rhs_code (assign);
kono
parents: 67
diff changeset
1109 tree cond_lhs = gimple_cond_lhs (cond);
kono
parents: 67
diff changeset
1110 tree cond_rhs = gimple_cond_rhs (cond);
kono
parents: 67
diff changeset
1111
kono
parents: 67
diff changeset
1112 /* Propagate the cond_rhs constant through preparation stmts,
kono
parents: 67
diff changeset
1113 make sure UB isn't invoked while doing that. */
kono
parents: 67
diff changeset
1114 for (int i = prep_cnt - 1; i >= 0; --i)
kono
parents: 67
diff changeset
1115 {
kono
parents: 67
diff changeset
1116 gimple *g = prep_stmt[i];
kono
parents: 67
diff changeset
1117 tree grhs1 = gimple_assign_rhs1 (g);
kono
parents: 67
diff changeset
1118 if (!operand_equal_for_phi_arg_p (cond_lhs, grhs1))
kono
parents: 67
diff changeset
1119 return 0;
kono
parents: 67
diff changeset
1120 cond_lhs = gimple_assign_lhs (g);
kono
parents: 67
diff changeset
1121 cond_rhs = fold_convert (TREE_TYPE (grhs1), cond_rhs);
kono
parents: 67
diff changeset
1122 if (TREE_CODE (cond_rhs) != INTEGER_CST
kono
parents: 67
diff changeset
1123 || TREE_OVERFLOW (cond_rhs))
kono
parents: 67
diff changeset
1124 return 0;
kono
parents: 67
diff changeset
1125 if (gimple_assign_rhs_class (g) == GIMPLE_BINARY_RHS)
kono
parents: 67
diff changeset
1126 {
kono
parents: 67
diff changeset
1127 cond_rhs = int_const_binop (gimple_assign_rhs_code (g), cond_rhs,
kono
parents: 67
diff changeset
1128 gimple_assign_rhs2 (g));
kono
parents: 67
diff changeset
1129 if (TREE_OVERFLOW (cond_rhs))
kono
parents: 67
diff changeset
1130 return 0;
kono
parents: 67
diff changeset
1131 }
kono
parents: 67
diff changeset
1132 cond_rhs = fold_convert (TREE_TYPE (cond_lhs), cond_rhs);
kono
parents: 67
diff changeset
1133 if (TREE_CODE (cond_rhs) != INTEGER_CST
kono
parents: 67
diff changeset
1134 || TREE_OVERFLOW (cond_rhs))
kono
parents: 67
diff changeset
1135 return 0;
kono
parents: 67
diff changeset
1136 }
kono
parents: 67
diff changeset
1137
kono
parents: 67
diff changeset
1138 if (((code == NE_EXPR && e1 == false_edge)
kono
parents: 67
diff changeset
1139 || (code == EQ_EXPR && e1 == true_edge))
kono
parents: 67
diff changeset
1140 && arg0 == lhs
kono
parents: 67
diff changeset
1141 && ((arg1 == rhs1
kono
parents: 67
diff changeset
1142 && operand_equal_for_phi_arg_p (rhs2, cond_lhs)
kono
parents: 67
diff changeset
1143 && neutral_element_p (code_def, cond_rhs, true))
kono
parents: 67
diff changeset
1144 || (arg1 == rhs2
kono
parents: 67
diff changeset
1145 && operand_equal_for_phi_arg_p (rhs1, cond_lhs)
kono
parents: 67
diff changeset
1146 && neutral_element_p (code_def, cond_rhs, false))
kono
parents: 67
diff changeset
1147 || (operand_equal_for_phi_arg_p (arg1, cond_rhs)
kono
parents: 67
diff changeset
1148 && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs)
kono
parents: 67
diff changeset
1149 && absorbing_element_p (code_def, cond_rhs, true, rhs2))
kono
parents: 67
diff changeset
1150 || (operand_equal_for_phi_arg_p (rhs1, cond_lhs)
kono
parents: 67
diff changeset
1151 && absorbing_element_p (code_def,
kono
parents: 67
diff changeset
1152 cond_rhs, false, rhs2))))))
kono
parents: 67
diff changeset
1153 {
kono
parents: 67
diff changeset
1154 gsi = gsi_for_stmt (cond);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1155 /* Moving ASSIGN might change VR of lhs, e.g. when moving u_6
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1156 def-stmt in:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1157 if (n_5 != 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1158 goto <bb 3>;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1159 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1160 goto <bb 4>;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1161
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1162 <bb 3>:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1163 # RANGE [0, 4294967294]
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1164 u_6 = n_5 + 4294967295;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1165
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1166 <bb 4>:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1167 # u_3 = PHI <u_6(3), 4294967295(2)> */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1168 reset_flow_sensitive_info (lhs);
111
kono
parents: 67
diff changeset
1169 if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
kono
parents: 67
diff changeset
1170 {
kono
parents: 67
diff changeset
1171 /* If available, we can use VR of phi result at least. */
kono
parents: 67
diff changeset
1172 tree phires = gimple_phi_result (phi);
kono
parents: 67
diff changeset
1173 struct range_info_def *phires_range_info
kono
parents: 67
diff changeset
1174 = SSA_NAME_RANGE_INFO (phires);
kono
parents: 67
diff changeset
1175 if (phires_range_info)
kono
parents: 67
diff changeset
1176 duplicate_ssa_name_range_info (lhs, SSA_NAME_RANGE_TYPE (phires),
kono
parents: 67
diff changeset
1177 phires_range_info);
kono
parents: 67
diff changeset
1178 }
kono
parents: 67
diff changeset
1179 gimple_stmt_iterator gsi_from;
kono
parents: 67
diff changeset
1180 for (int i = prep_cnt - 1; i >= 0; --i)
kono
parents: 67
diff changeset
1181 {
kono
parents: 67
diff changeset
1182 tree plhs = gimple_assign_lhs (prep_stmt[i]);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1183 reset_flow_sensitive_info (plhs);
111
kono
parents: 67
diff changeset
1184 gsi_from = gsi_for_stmt (prep_stmt[i]);
kono
parents: 67
diff changeset
1185 gsi_move_before (&gsi_from, &gsi);
kono
parents: 67
diff changeset
1186 }
kono
parents: 67
diff changeset
1187 gsi_from = gsi_for_stmt (assign);
kono
parents: 67
diff changeset
1188 gsi_move_before (&gsi_from, &gsi);
kono
parents: 67
diff changeset
1189 replace_phi_edge_with_variable (cond_bb, e1, phi, lhs);
kono
parents: 67
diff changeset
1190 return 2;
kono
parents: 67
diff changeset
1191 }
kono
parents: 67
diff changeset
1192
kono
parents: 67
diff changeset
1193 return 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1194 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1195
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1196 /* The function minmax_replacement does the main work of doing the minmax
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1197 replacement. Return true if the replacement is done. Otherwise return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1198 false.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1199 BB is the basic block where the replacement is going to be done on. ARG0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1200 is argument 0 from the PHI. Likewise for ARG1. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1201
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1202 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1203 minmax_replacement (basic_block cond_bb, basic_block middle_bb,
111
kono
parents: 67
diff changeset
1204 edge e0, edge e1, gimple *phi,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1205 tree arg0, tree arg1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1206 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1207 tree result, type;
111
kono
parents: 67
diff changeset
1208 gcond *cond;
kono
parents: 67
diff changeset
1209 gassign *new_stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1210 edge true_edge, false_edge;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1211 enum tree_code cmp, minmax, ass_code;
111
kono
parents: 67
diff changeset
1212 tree smaller, alt_smaller, larger, alt_larger, arg_true, arg_false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1213 gimple_stmt_iterator gsi, gsi_from;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1214
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1215 type = TREE_TYPE (PHI_RESULT (phi));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1216
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1217 /* The optimization may be unsafe due to NaNs. */
111
kono
parents: 67
diff changeset
1218 if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1219 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1220
111
kono
parents: 67
diff changeset
1221 cond = as_a <gcond *> (last_stmt (cond_bb));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1222 cmp = gimple_cond_code (cond);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1223
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1224 /* This transformation is only valid for order comparisons. Record which
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1225 operand is smaller/larger if the result of the comparison is true. */
111
kono
parents: 67
diff changeset
1226 alt_smaller = NULL_TREE;
kono
parents: 67
diff changeset
1227 alt_larger = NULL_TREE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1228 if (cmp == LT_EXPR || cmp == LE_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1229 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1230 smaller = gimple_cond_lhs (cond);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1231 larger = gimple_cond_rhs (cond);
111
kono
parents: 67
diff changeset
1232 /* If we have smaller < CST it is equivalent to smaller <= CST-1.
kono
parents: 67
diff changeset
1233 Likewise smaller <= CST is equivalent to smaller < CST+1. */
kono
parents: 67
diff changeset
1234 if (TREE_CODE (larger) == INTEGER_CST)
kono
parents: 67
diff changeset
1235 {
kono
parents: 67
diff changeset
1236 if (cmp == LT_EXPR)
kono
parents: 67
diff changeset
1237 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1238 wi::overflow_type overflow;
111
kono
parents: 67
diff changeset
1239 wide_int alt = wi::sub (wi::to_wide (larger), 1,
kono
parents: 67
diff changeset
1240 TYPE_SIGN (TREE_TYPE (larger)),
kono
parents: 67
diff changeset
1241 &overflow);
kono
parents: 67
diff changeset
1242 if (! overflow)
kono
parents: 67
diff changeset
1243 alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt);
kono
parents: 67
diff changeset
1244 }
kono
parents: 67
diff changeset
1245 else
kono
parents: 67
diff changeset
1246 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1247 wi::overflow_type overflow;
111
kono
parents: 67
diff changeset
1248 wide_int alt = wi::add (wi::to_wide (larger), 1,
kono
parents: 67
diff changeset
1249 TYPE_SIGN (TREE_TYPE (larger)),
kono
parents: 67
diff changeset
1250 &overflow);
kono
parents: 67
diff changeset
1251 if (! overflow)
kono
parents: 67
diff changeset
1252 alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt);
kono
parents: 67
diff changeset
1253 }
kono
parents: 67
diff changeset
1254 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1255 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1256 else if (cmp == GT_EXPR || cmp == GE_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1257 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1258 smaller = gimple_cond_rhs (cond);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1259 larger = gimple_cond_lhs (cond);
111
kono
parents: 67
diff changeset
1260 /* If we have larger > CST it is equivalent to larger >= CST+1.
kono
parents: 67
diff changeset
1261 Likewise larger >= CST is equivalent to larger > CST-1. */
kono
parents: 67
diff changeset
1262 if (TREE_CODE (smaller) == INTEGER_CST)
kono
parents: 67
diff changeset
1263 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1264 wi::overflow_type overflow;
111
kono
parents: 67
diff changeset
1265 if (cmp == GT_EXPR)
kono
parents: 67
diff changeset
1266 {
kono
parents: 67
diff changeset
1267 wide_int alt = wi::add (wi::to_wide (smaller), 1,
kono
parents: 67
diff changeset
1268 TYPE_SIGN (TREE_TYPE (smaller)),
kono
parents: 67
diff changeset
1269 &overflow);
kono
parents: 67
diff changeset
1270 if (! overflow)
kono
parents: 67
diff changeset
1271 alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt);
kono
parents: 67
diff changeset
1272 }
kono
parents: 67
diff changeset
1273 else
kono
parents: 67
diff changeset
1274 {
kono
parents: 67
diff changeset
1275 wide_int alt = wi::sub (wi::to_wide (smaller), 1,
kono
parents: 67
diff changeset
1276 TYPE_SIGN (TREE_TYPE (smaller)),
kono
parents: 67
diff changeset
1277 &overflow);
kono
parents: 67
diff changeset
1278 if (! overflow)
kono
parents: 67
diff changeset
1279 alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt);
kono
parents: 67
diff changeset
1280 }
kono
parents: 67
diff changeset
1281 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1282 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1283 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1284 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1285
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1286 /* We need to know which is the true edge and which is the false
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1287 edge so that we know if have abs or negative abs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1288 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1289
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1290 /* Forward the edges over the middle basic block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1291 if (true_edge->dest == middle_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1292 true_edge = EDGE_SUCC (true_edge->dest, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1293 if (false_edge->dest == middle_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1294 false_edge = EDGE_SUCC (false_edge->dest, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1295
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1296 if (true_edge == e0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1297 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1298 gcc_assert (false_edge == e1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1299 arg_true = arg0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1300 arg_false = arg1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1301 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1302 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1303 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1304 gcc_assert (false_edge == e0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1305 gcc_assert (true_edge == e1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1306 arg_true = arg1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1307 arg_false = arg0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1308 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1309
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1310 if (empty_block_p (middle_bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1311 {
111
kono
parents: 67
diff changeset
1312 if ((operand_equal_for_phi_arg_p (arg_true, smaller)
kono
parents: 67
diff changeset
1313 || (alt_smaller
kono
parents: 67
diff changeset
1314 && operand_equal_for_phi_arg_p (arg_true, alt_smaller)))
kono
parents: 67
diff changeset
1315 && (operand_equal_for_phi_arg_p (arg_false, larger)
kono
parents: 67
diff changeset
1316 || (alt_larger
kono
parents: 67
diff changeset
1317 && operand_equal_for_phi_arg_p (arg_true, alt_larger))))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1318 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1319 /* Case
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1320
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1321 if (smaller < larger)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1322 rslt = smaller;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1323 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1324 rslt = larger; */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1325 minmax = MIN_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1326 }
111
kono
parents: 67
diff changeset
1327 else if ((operand_equal_for_phi_arg_p (arg_false, smaller)
kono
parents: 67
diff changeset
1328 || (alt_smaller
kono
parents: 67
diff changeset
1329 && operand_equal_for_phi_arg_p (arg_false, alt_smaller)))
kono
parents: 67
diff changeset
1330 && (operand_equal_for_phi_arg_p (arg_true, larger)
kono
parents: 67
diff changeset
1331 || (alt_larger
kono
parents: 67
diff changeset
1332 && operand_equal_for_phi_arg_p (arg_true, alt_larger))))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1333 minmax = MAX_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1334 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1335 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1336 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1337 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1338 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1339 /* Recognize the following case, assuming d <= u:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1340
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1341 if (a <= u)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1342 b = MAX (a, d);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1343 x = PHI <b, u>
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1344
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1345 This is equivalent to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1346
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1347 b = MAX (a, d);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1348 x = MIN (b, u); */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1349
111
kono
parents: 67
diff changeset
1350 gimple *assign = last_and_only_stmt (middle_bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1351 tree lhs, op0, op1, bound;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1352
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1353 if (!assign
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1354 || gimple_code (assign) != GIMPLE_ASSIGN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1355 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1356
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1357 lhs = gimple_assign_lhs (assign);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1358 ass_code = gimple_assign_rhs_code (assign);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1359 if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1360 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1361 op0 = gimple_assign_rhs1 (assign);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1362 op1 = gimple_assign_rhs2 (assign);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1363
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1364 if (true_edge->src == middle_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1365 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1366 /* We got here if the condition is true, i.e., SMALLER < LARGER. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1367 if (!operand_equal_for_phi_arg_p (lhs, arg_true))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1368 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1369
111
kono
parents: 67
diff changeset
1370 if (operand_equal_for_phi_arg_p (arg_false, larger)
kono
parents: 67
diff changeset
1371 || (alt_larger
kono
parents: 67
diff changeset
1372 && operand_equal_for_phi_arg_p (arg_false, alt_larger)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1373 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1374 /* Case
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1375
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1376 if (smaller < larger)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1377 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1378 r' = MAX_EXPR (smaller, bound)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1379 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1380 r = PHI <r', larger> --> to be turned to MIN_EXPR. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1381 if (ass_code != MAX_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1382 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1383
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1384 minmax = MIN_EXPR;
111
kono
parents: 67
diff changeset
1385 if (operand_equal_for_phi_arg_p (op0, smaller)
kono
parents: 67
diff changeset
1386 || (alt_smaller
kono
parents: 67
diff changeset
1387 && operand_equal_for_phi_arg_p (op0, alt_smaller)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1388 bound = op1;
111
kono
parents: 67
diff changeset
1389 else if (operand_equal_for_phi_arg_p (op1, smaller)
kono
parents: 67
diff changeset
1390 || (alt_smaller
kono
parents: 67
diff changeset
1391 && operand_equal_for_phi_arg_p (op1, alt_smaller)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1392 bound = op0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1393 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1394 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1395
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1396 /* We need BOUND <= LARGER. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1397 if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1398 bound, larger)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1399 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1400 }
111
kono
parents: 67
diff changeset
1401 else if (operand_equal_for_phi_arg_p (arg_false, smaller)
kono
parents: 67
diff changeset
1402 || (alt_smaller
kono
parents: 67
diff changeset
1403 && operand_equal_for_phi_arg_p (arg_false, alt_smaller)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1404 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1405 /* Case
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1406
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1407 if (smaller < larger)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1408 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1409 r' = MIN_EXPR (larger, bound)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1410 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1411 r = PHI <r', smaller> --> to be turned to MAX_EXPR. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1412 if (ass_code != MIN_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1413 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1414
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1415 minmax = MAX_EXPR;
111
kono
parents: 67
diff changeset
1416 if (operand_equal_for_phi_arg_p (op0, larger)
kono
parents: 67
diff changeset
1417 || (alt_larger
kono
parents: 67
diff changeset
1418 && operand_equal_for_phi_arg_p (op0, alt_larger)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1419 bound = op1;
111
kono
parents: 67
diff changeset
1420 else if (operand_equal_for_phi_arg_p (op1, larger)
kono
parents: 67
diff changeset
1421 || (alt_larger
kono
parents: 67
diff changeset
1422 && operand_equal_for_phi_arg_p (op1, alt_larger)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1423 bound = op0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1424 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1425 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1426
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1427 /* We need BOUND >= SMALLER. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1428 if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1429 bound, smaller)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1430 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1431 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1432 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1433 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1434 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1435 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1436 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1437 /* We got here if the condition is false, i.e., SMALLER > LARGER. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1438 if (!operand_equal_for_phi_arg_p (lhs, arg_false))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1439 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1440
111
kono
parents: 67
diff changeset
1441 if (operand_equal_for_phi_arg_p (arg_true, larger)
kono
parents: 67
diff changeset
1442 || (alt_larger
kono
parents: 67
diff changeset
1443 && operand_equal_for_phi_arg_p (arg_true, alt_larger)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1444 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1445 /* Case
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1446
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1447 if (smaller > larger)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1448 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1449 r' = MIN_EXPR (smaller, bound)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1450 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1451 r = PHI <r', larger> --> to be turned to MAX_EXPR. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1452 if (ass_code != MIN_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1453 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1454
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1455 minmax = MAX_EXPR;
111
kono
parents: 67
diff changeset
1456 if (operand_equal_for_phi_arg_p (op0, smaller)
kono
parents: 67
diff changeset
1457 || (alt_smaller
kono
parents: 67
diff changeset
1458 && operand_equal_for_phi_arg_p (op0, alt_smaller)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1459 bound = op1;
111
kono
parents: 67
diff changeset
1460 else if (operand_equal_for_phi_arg_p (op1, smaller)
kono
parents: 67
diff changeset
1461 || (alt_smaller
kono
parents: 67
diff changeset
1462 && operand_equal_for_phi_arg_p (op1, alt_smaller)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1463 bound = op0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1464 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1465 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1466
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1467 /* We need BOUND >= LARGER. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1468 if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1469 bound, larger)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1470 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1471 }
111
kono
parents: 67
diff changeset
1472 else if (operand_equal_for_phi_arg_p (arg_true, smaller)
kono
parents: 67
diff changeset
1473 || (alt_smaller
kono
parents: 67
diff changeset
1474 && operand_equal_for_phi_arg_p (arg_true, alt_smaller)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1475 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1476 /* Case
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1477
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1478 if (smaller > larger)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1479 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1480 r' = MAX_EXPR (larger, bound)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1481 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1482 r = PHI <r', smaller> --> to be turned to MIN_EXPR. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1483 if (ass_code != MAX_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1484 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1485
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1486 minmax = MIN_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1487 if (operand_equal_for_phi_arg_p (op0, larger))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1488 bound = op1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1489 else if (operand_equal_for_phi_arg_p (op1, larger))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1490 bound = op0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1491 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1492 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1493
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1494 /* We need BOUND <= SMALLER. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1495 if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1496 bound, smaller)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1497 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1498 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1499 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1500 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1501 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1502
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1503 /* Move the statement from the middle block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1504 gsi = gsi_last_bb (cond_bb);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1505 gsi_from = gsi_last_nondebug_bb (middle_bb);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1506 reset_flow_sensitive_info (SINGLE_SSA_TREE_OPERAND (gsi_stmt (gsi_from),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1507 SSA_OP_DEF));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1508 gsi_move_before (&gsi_from, &gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1509 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1510
111
kono
parents: 67
diff changeset
1511 /* Create an SSA var to hold the min/max result. If we're the only
kono
parents: 67
diff changeset
1512 things setting the target PHI, then we can clone the PHI
kono
parents: 67
diff changeset
1513 variable. Otherwise we must create a new one. */
kono
parents: 67
diff changeset
1514 result = PHI_RESULT (phi);
kono
parents: 67
diff changeset
1515 if (EDGE_COUNT (gimple_bb (phi)->preds) == 2)
kono
parents: 67
diff changeset
1516 result = duplicate_ssa_name (result, NULL);
kono
parents: 67
diff changeset
1517 else
kono
parents: 67
diff changeset
1518 result = make_ssa_name (TREE_TYPE (result));
kono
parents: 67
diff changeset
1519
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1520 /* Emit the statement to compute min/max. */
111
kono
parents: 67
diff changeset
1521 new_stmt = gimple_build_assign (result, minmax, arg0, arg1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1522 gsi = gsi_last_bb (cond_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1523 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1524
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1525 replace_phi_edge_with_variable (cond_bb, e1, phi, result);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1526
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1527 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1528 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1529
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1530 /* Convert
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1531
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1532 <bb 2>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1533 if (b_4(D) != 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1534 goto <bb 3>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1535 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1536 goto <bb 4>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1537
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1538 <bb 3>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1539 _2 = (unsigned long) b_4(D);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1540 _9 = __builtin_popcountl (_2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1541 OR
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1542 _9 = __builtin_popcountl (b_4(D));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1543
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1544 <bb 4>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1545 c_12 = PHI <0(2), _9(3)>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1546
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1547 Into
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1548 <bb 2>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1549 _2 = (unsigned long) b_4(D);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1550 _9 = __builtin_popcountl (_2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1551 OR
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1552 _9 = __builtin_popcountl (b_4(D));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1553
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1554 <bb 4>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1555 c_12 = PHI <_9(2)>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1556 */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1557
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1558 static bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1559 cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1560 edge e1, edge e2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1561 gimple *phi, tree arg0, tree arg1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1562 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1563 gimple *cond;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1564 gimple_stmt_iterator gsi, gsi_from;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1565 gimple *popcount;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1566 gimple *cast = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1567 tree lhs, arg;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1568
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1569 /* Check that
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1570 _2 = (unsigned long) b_4(D);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1571 _9 = __builtin_popcountl (_2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1572 OR
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1573 _9 = __builtin_popcountl (b_4(D));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1574 are the only stmts in the middle_bb. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1575
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1576 gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1577 if (gsi_end_p (gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1578 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1579 cast = gsi_stmt (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1580 gsi_next_nondebug (&gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1581 if (!gsi_end_p (gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1582 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1583 popcount = gsi_stmt (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1584 gsi_next_nondebug (&gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1585 if (!gsi_end_p (gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1586 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1587 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1588 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1589 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1590 popcount = cast;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1591 cast = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1592 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1593
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1594 /* Check that we have a popcount builtin. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1595 if (!is_gimple_call (popcount))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1596 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1597 combined_fn cfn = gimple_call_combined_fn (popcount);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1598 switch (cfn)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1599 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1600 CASE_CFN_POPCOUNT:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1601 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1602 default:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1603 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1604 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1605
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1606 arg = gimple_call_arg (popcount, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1607 lhs = gimple_get_lhs (popcount);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1608
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1609 if (cast)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1610 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1611 /* We have a cast stmt feeding popcount builtin. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1612 /* Check that we have a cast prior to that. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1613 if (gimple_code (cast) != GIMPLE_ASSIGN
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1614 || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (cast)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1615 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1616 /* Result of the cast stmt is the argument to the builtin. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1617 if (arg != gimple_assign_lhs (cast))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1618 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1619 arg = gimple_assign_rhs1 (cast);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1620 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1621
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1622 cond = last_stmt (cond_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1623
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1624 /* Cond_bb has a check for b_4 [!=|==] 0 before calling the popcount
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1625 builtin. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1626 if (gimple_code (cond) != GIMPLE_COND
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1627 || (gimple_cond_code (cond) != NE_EXPR
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1628 && gimple_cond_code (cond) != EQ_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1629 || !integer_zerop (gimple_cond_rhs (cond))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1630 || arg != gimple_cond_lhs (cond))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1631 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1632
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1633 /* Canonicalize. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1634 if ((e2->flags & EDGE_TRUE_VALUE
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1635 && gimple_cond_code (cond) == NE_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1636 || (e1->flags & EDGE_TRUE_VALUE
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1637 && gimple_cond_code (cond) == EQ_EXPR))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1638 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1639 std::swap (arg0, arg1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1640 std::swap (e1, e2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1641 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1643 /* Check PHI arguments. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1644 if (lhs != arg0 || !integer_zerop (arg1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1645 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1646
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1647 /* And insert the popcount builtin and cast stmt before the cond_bb. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1648 gsi = gsi_last_bb (cond_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1649 if (cast)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1650 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1651 gsi_from = gsi_for_stmt (cast);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1652 gsi_move_before (&gsi_from, &gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1653 reset_flow_sensitive_info (gimple_get_lhs (cast));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1654 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1655 gsi_from = gsi_for_stmt (popcount);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1656 gsi_move_before (&gsi_from, &gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1657 reset_flow_sensitive_info (gimple_get_lhs (popcount));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1658
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1659 /* Now update the PHI and remove unneeded bbs. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1660 replace_phi_edge_with_variable (cond_bb, e2, phi, lhs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1661 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1662 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1663
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1664 /* The function absolute_replacement does the main work of doing the absolute
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1665 replacement. Return true if the replacement is done. Otherwise return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1666 false.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1667 bb is the basic block where the replacement is going to be done on. arg0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1668 is argument 0 from the phi. Likewise for arg1. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1669
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1670 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1671 abs_replacement (basic_block cond_bb, basic_block middle_bb,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1672 edge e0 ATTRIBUTE_UNUSED, edge e1,
111
kono
parents: 67
diff changeset
1673 gimple *phi, tree arg0, tree arg1)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1674 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1675 tree result;
111
kono
parents: 67
diff changeset
1676 gassign *new_stmt;
kono
parents: 67
diff changeset
1677 gimple *cond;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1678 gimple_stmt_iterator gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1679 edge true_edge, false_edge;
111
kono
parents: 67
diff changeset
1680 gimple *assign;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1681 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1682 tree rhs, lhs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1683 bool negate;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1684 enum tree_code cond_code;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1685
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1686 /* If the type says honor signed zeros we cannot do this
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1687 optimization. */
111
kono
parents: 67
diff changeset
1688 if (HONOR_SIGNED_ZEROS (arg1))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1689 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1690
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1691 /* OTHER_BLOCK must have only one executable statement which must have the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1692 form arg0 = -arg1 or arg1 = -arg0. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1693
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1694 assign = last_and_only_stmt (middle_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1695 /* If we did not find the proper negation assignment, then we can not
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1696 optimize. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1697 if (assign == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1698 return false;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1699
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1700 /* If we got here, then we have found the only executable statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1701 in OTHER_BLOCK. If it is anything other than arg = -arg1 or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1702 arg1 = -arg0, then we can not optimize. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1703 if (gimple_code (assign) != GIMPLE_ASSIGN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1704 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1705
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1706 lhs = gimple_assign_lhs (assign);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1707
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1708 if (gimple_assign_rhs_code (assign) != NEGATE_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1709 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1710
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1711 rhs = gimple_assign_rhs1 (assign);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1712
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1713 /* The assignment has to be arg0 = -arg1 or arg1 = -arg0. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1714 if (!(lhs == arg0 && rhs == arg1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1715 && !(lhs == arg1 && rhs == arg0))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1716 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1717
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1718 cond = last_stmt (cond_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1719 result = PHI_RESULT (phi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1720
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1721 /* Only relationals comparing arg[01] against zero are interesting. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1722 cond_code = gimple_cond_code (cond);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1723 if (cond_code != GT_EXPR && cond_code != GE_EXPR
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1724 && cond_code != LT_EXPR && cond_code != LE_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1725 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1726
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1727 /* Make sure the conditional is arg[01] OP y. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1728 if (gimple_cond_lhs (cond) != rhs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1729 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1730
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1731 if (FLOAT_TYPE_P (TREE_TYPE (gimple_cond_rhs (cond)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1732 ? real_zerop (gimple_cond_rhs (cond))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1733 : integer_zerop (gimple_cond_rhs (cond)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1734 ;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1735 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1736 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1737
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1738 /* We need to know which is the true edge and which is the false
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1739 edge so that we know if have abs or negative abs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1740 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1741
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1742 /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1743 will need to negate the result. Similarly for LT_EXPR/LE_EXPR if
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1744 the false edge goes to OTHER_BLOCK. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1745 if (cond_code == GT_EXPR || cond_code == GE_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1746 e = true_edge;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1747 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1748 e = false_edge;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1749
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1750 if (e->dest == middle_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1751 negate = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1752 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1753 negate = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1754
111
kono
parents: 67
diff changeset
1755 /* If the code negates only iff positive then make sure to not
kono
parents: 67
diff changeset
1756 introduce undefined behavior when negating or computing the absolute.
kono
parents: 67
diff changeset
1757 ??? We could use range info if present to check for arg1 == INT_MIN. */
kono
parents: 67
diff changeset
1758 if (negate
kono
parents: 67
diff changeset
1759 && (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg1))
kono
parents: 67
diff changeset
1760 && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1))))
kono
parents: 67
diff changeset
1761 return false;
kono
parents: 67
diff changeset
1762
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1763 result = duplicate_ssa_name (result, NULL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1764
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1765 if (negate)
111
kono
parents: 67
diff changeset
1766 lhs = make_ssa_name (TREE_TYPE (result));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1767 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1768 lhs = result;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1769
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1770 /* Build the modify expression with abs expression. */
111
kono
parents: 67
diff changeset
1771 new_stmt = gimple_build_assign (lhs, ABS_EXPR, rhs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1772
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1773 gsi = gsi_last_bb (cond_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1774 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1775
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1776 if (negate)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1777 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1778 /* Get the right GSI. We want to insert after the recently
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1779 added ABS_EXPR statement (which we know is the first statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1780 in the block. */
111
kono
parents: 67
diff changeset
1781 new_stmt = gimple_build_assign (result, NEGATE_EXPR, lhs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1782
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1783 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1784 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1785
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1786 replace_phi_edge_with_variable (cond_bb, e1, phi, result);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1787
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1788 /* Note that we optimized this PHI. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1789 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1790 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1791
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1792 /* Auxiliary functions to determine the set of memory accesses which
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1793 can't trap because they are preceded by accesses to the same memory
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1794 portion. We do that for MEM_REFs, so we only need to track
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1795 the SSA_NAME of the pointer indirectly referenced. The algorithm
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1796 simply is a walk over all instructions in dominator order. When
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1797 we see an MEM_REF we determine if we've already seen a same
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1798 ref anywhere up to the root of the dominator tree. If we do the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1799 current access can't trap. If we don't see any dominating access
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1800 the current access might trap, but might also make later accesses
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1801 non-trapping, so we remember it. We need to be careful with loads
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1802 or stores, for instance a load might not trap, while a store would,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1803 so if we see a dominating read access this doesn't mean that a later
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1804 write access would not trap. Hence we also need to differentiate the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1805 type of access(es) seen.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1806
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1807 ??? We currently are very conservative and assume that a load might
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1808 trap even if a store doesn't (write-only memory). This probably is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1809 overly conservative. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1810
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1811 /* A hash-table of SSA_NAMEs, and in which basic block an MEM_REF
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1812 through it was seen, which would constitute a no-trap region for
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1813 same accesses. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1814 struct name_to_bb
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1815 {
111
kono
parents: 67
diff changeset
1816 unsigned int ssa_name_ver;
kono
parents: 67
diff changeset
1817 unsigned int phase;
kono
parents: 67
diff changeset
1818 bool store;
kono
parents: 67
diff changeset
1819 HOST_WIDE_INT offset, size;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1820 basic_block bb;
111
kono
parents: 67
diff changeset
1821 };
kono
parents: 67
diff changeset
1822
kono
parents: 67
diff changeset
1823 /* Hashtable helpers. */
kono
parents: 67
diff changeset
1824
kono
parents: 67
diff changeset
1825 struct ssa_names_hasher : free_ptr_hash <name_to_bb>
kono
parents: 67
diff changeset
1826 {
kono
parents: 67
diff changeset
1827 static inline hashval_t hash (const name_to_bb *);
kono
parents: 67
diff changeset
1828 static inline bool equal (const name_to_bb *, const name_to_bb *);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1829 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1830
111
kono
parents: 67
diff changeset
1831 /* Used for quick clearing of the hash-table when we see calls.
kono
parents: 67
diff changeset
1832 Hash entries with phase < nt_call_phase are invalid. */
kono
parents: 67
diff changeset
1833 static unsigned int nt_call_phase;
kono
parents: 67
diff changeset
1834
kono
parents: 67
diff changeset
1835 /* The hash function. */
kono
parents: 67
diff changeset
1836
kono
parents: 67
diff changeset
1837 inline hashval_t
kono
parents: 67
diff changeset
1838 ssa_names_hasher::hash (const name_to_bb *n)
kono
parents: 67
diff changeset
1839 {
kono
parents: 67
diff changeset
1840 return n->ssa_name_ver ^ (((hashval_t) n->store) << 31)
kono
parents: 67
diff changeset
1841 ^ (n->offset << 6) ^ (n->size << 3);
kono
parents: 67
diff changeset
1842 }
kono
parents: 67
diff changeset
1843
kono
parents: 67
diff changeset
1844 /* The equality function of *P1 and *P2. */
kono
parents: 67
diff changeset
1845
kono
parents: 67
diff changeset
1846 inline bool
kono
parents: 67
diff changeset
1847 ssa_names_hasher::equal (const name_to_bb *n1, const name_to_bb *n2)
kono
parents: 67
diff changeset
1848 {
kono
parents: 67
diff changeset
1849 return n1->ssa_name_ver == n2->ssa_name_ver
kono
parents: 67
diff changeset
1850 && n1->store == n2->store
kono
parents: 67
diff changeset
1851 && n1->offset == n2->offset
kono
parents: 67
diff changeset
1852 && n1->size == n2->size;
kono
parents: 67
diff changeset
1853 }
kono
parents: 67
diff changeset
1854
kono
parents: 67
diff changeset
1855 class nontrapping_dom_walker : public dom_walker
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1856 {
111
kono
parents: 67
diff changeset
1857 public:
kono
parents: 67
diff changeset
1858 nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
kono
parents: 67
diff changeset
1859 : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
kono
parents: 67
diff changeset
1860
kono
parents: 67
diff changeset
1861 virtual edge before_dom_children (basic_block);
kono
parents: 67
diff changeset
1862 virtual void after_dom_children (basic_block);
kono
parents: 67
diff changeset
1863
kono
parents: 67
diff changeset
1864 private:
kono
parents: 67
diff changeset
1865
kono
parents: 67
diff changeset
1866 /* We see the expression EXP in basic block BB. If it's an interesting
kono
parents: 67
diff changeset
1867 expression (an MEM_REF through an SSA_NAME) possibly insert the
kono
parents: 67
diff changeset
1868 expression into the set NONTRAP or the hash table of seen expressions.
kono
parents: 67
diff changeset
1869 STORE is true if this expression is on the LHS, otherwise it's on
kono
parents: 67
diff changeset
1870 the RHS. */
kono
parents: 67
diff changeset
1871 void add_or_mark_expr (basic_block, tree, bool);
kono
parents: 67
diff changeset
1872
kono
parents: 67
diff changeset
1873 hash_set<tree> *m_nontrapping;
kono
parents: 67
diff changeset
1874
kono
parents: 67
diff changeset
1875 /* The hash table for remembering what we've seen. */
kono
parents: 67
diff changeset
1876 hash_table<ssa_names_hasher> m_seen_ssa_names;
kono
parents: 67
diff changeset
1877 };
kono
parents: 67
diff changeset
1878
kono
parents: 67
diff changeset
1879 /* Called by walk_dominator_tree, when entering the block BB. */
kono
parents: 67
diff changeset
1880 edge
kono
parents: 67
diff changeset
1881 nontrapping_dom_walker::before_dom_children (basic_block bb)
kono
parents: 67
diff changeset
1882 {
kono
parents: 67
diff changeset
1883 edge e;
kono
parents: 67
diff changeset
1884 edge_iterator ei;
kono
parents: 67
diff changeset
1885 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
1886
kono
parents: 67
diff changeset
1887 /* If we haven't seen all our predecessors, clear the hash-table. */
kono
parents: 67
diff changeset
1888 FOR_EACH_EDGE (e, ei, bb->preds)
kono
parents: 67
diff changeset
1889 if ((((size_t)e->src->aux) & 2) == 0)
kono
parents: 67
diff changeset
1890 {
kono
parents: 67
diff changeset
1891 nt_call_phase++;
kono
parents: 67
diff changeset
1892 break;
kono
parents: 67
diff changeset
1893 }
kono
parents: 67
diff changeset
1894
kono
parents: 67
diff changeset
1895 /* Mark this BB as being on the path to dominator root and as visited. */
kono
parents: 67
diff changeset
1896 bb->aux = (void*)(1 | 2);
kono
parents: 67
diff changeset
1897
kono
parents: 67
diff changeset
1898 /* And walk the statements in order. */
kono
parents: 67
diff changeset
1899 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
1900 {
kono
parents: 67
diff changeset
1901 gimple *stmt = gsi_stmt (gsi);
kono
parents: 67
diff changeset
1902
kono
parents: 67
diff changeset
1903 if ((gimple_code (stmt) == GIMPLE_ASM && gimple_vdef (stmt))
kono
parents: 67
diff changeset
1904 || (is_gimple_call (stmt)
kono
parents: 67
diff changeset
1905 && (!nonfreeing_call_p (stmt) || !nonbarrier_call_p (stmt))))
kono
parents: 67
diff changeset
1906 nt_call_phase++;
kono
parents: 67
diff changeset
1907 else if (gimple_assign_single_p (stmt) && !gimple_has_volatile_ops (stmt))
kono
parents: 67
diff changeset
1908 {
kono
parents: 67
diff changeset
1909 add_or_mark_expr (bb, gimple_assign_lhs (stmt), true);
kono
parents: 67
diff changeset
1910 add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), false);
kono
parents: 67
diff changeset
1911 }
kono
parents: 67
diff changeset
1912 }
kono
parents: 67
diff changeset
1913 return NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1914 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1915
111
kono
parents: 67
diff changeset
1916 /* Called by walk_dominator_tree, when basic block BB is exited. */
kono
parents: 67
diff changeset
1917 void
kono
parents: 67
diff changeset
1918 nontrapping_dom_walker::after_dom_children (basic_block bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1919 {
111
kono
parents: 67
diff changeset
1920 /* This BB isn't on the path to dominator root anymore. */
kono
parents: 67
diff changeset
1921 bb->aux = (void*)2;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1922 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1923
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1924 /* We see the expression EXP in basic block BB. If it's an interesting
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1925 expression (an MEM_REF through an SSA_NAME) possibly insert the
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1926 expression into the set NONTRAP or the hash table of seen expressions.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1927 STORE is true if this expression is on the LHS, otherwise it's on
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1928 the RHS. */
111
kono
parents: 67
diff changeset
1929 void
kono
parents: 67
diff changeset
1930 nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1931 {
111
kono
parents: 67
diff changeset
1932 HOST_WIDE_INT size;
kono
parents: 67
diff changeset
1933
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1934 if (TREE_CODE (exp) == MEM_REF
111
kono
parents: 67
diff changeset
1935 && TREE_CODE (TREE_OPERAND (exp, 0)) == SSA_NAME
kono
parents: 67
diff changeset
1936 && tree_fits_shwi_p (TREE_OPERAND (exp, 1))
kono
parents: 67
diff changeset
1937 && (size = int_size_in_bytes (TREE_TYPE (exp))) > 0)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1938 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1939 tree name = TREE_OPERAND (exp, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1940 struct name_to_bb map;
111
kono
parents: 67
diff changeset
1941 name_to_bb **slot;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1942 struct name_to_bb *n2bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1943 basic_block found_bb = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1944
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1945 /* Try to find the last seen MEM_REF through the same
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1946 SSA_NAME, which can trap. */
111
kono
parents: 67
diff changeset
1947 map.ssa_name_ver = SSA_NAME_VERSION (name);
kono
parents: 67
diff changeset
1948 map.phase = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1949 map.bb = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1950 map.store = store;
111
kono
parents: 67
diff changeset
1951 map.offset = tree_to_shwi (TREE_OPERAND (exp, 1));
kono
parents: 67
diff changeset
1952 map.size = size;
kono
parents: 67
diff changeset
1953
kono
parents: 67
diff changeset
1954 slot = m_seen_ssa_names.find_slot (&map, INSERT);
kono
parents: 67
diff changeset
1955 n2bb = *slot;
kono
parents: 67
diff changeset
1956 if (n2bb && n2bb->phase >= nt_call_phase)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1957 found_bb = n2bb->bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1958
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1959 /* If we've found a trapping MEM_REF, _and_ it dominates EXP
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1960 (it's in a basic block on the path from us to the dominator root)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1961 then we can't trap. */
111
kono
parents: 67
diff changeset
1962 if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1963 {
111
kono
parents: 67
diff changeset
1964 m_nontrapping->add (exp);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1965 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1966 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1967 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1968 /* EXP might trap, so insert it into the hash table. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1969 if (n2bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1970 {
111
kono
parents: 67
diff changeset
1971 n2bb->phase = nt_call_phase;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1972 n2bb->bb = bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1973 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1974 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1975 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1976 n2bb = XNEW (struct name_to_bb);
111
kono
parents: 67
diff changeset
1977 n2bb->ssa_name_ver = SSA_NAME_VERSION (name);
kono
parents: 67
diff changeset
1978 n2bb->phase = nt_call_phase;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1979 n2bb->bb = bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1980 n2bb->store = store;
111
kono
parents: 67
diff changeset
1981 n2bb->offset = map.offset;
kono
parents: 67
diff changeset
1982 n2bb->size = size;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1983 *slot = n2bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1984 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1985 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1986 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1987 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1988
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1989 /* This is the entry point of gathering non trapping memory accesses.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1990 It will do a dominator walk over the whole function, and it will
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1991 make use of the bb->aux pointers. It returns a set of trees
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1992 (the MEM_REFs itself) which can't trap. */
111
kono
parents: 67
diff changeset
1993 static hash_set<tree> *
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1994 get_non_trapping (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1995 {
111
kono
parents: 67
diff changeset
1996 nt_call_phase = 0;
kono
parents: 67
diff changeset
1997 hash_set<tree> *nontrap = new hash_set<tree>;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1998 /* We're going to do a dominator walk, so ensure that we have
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1999 dominance information. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2000 calculate_dominance_info (CDI_DOMINATORS);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2001
111
kono
parents: 67
diff changeset
2002 nontrapping_dom_walker (CDI_DOMINATORS, nontrap)
kono
parents: 67
diff changeset
2003 .walk (cfun->cfg->x_entry_block_ptr);
kono
parents: 67
diff changeset
2004
kono
parents: 67
diff changeset
2005 clear_aux_for_blocks ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2006 return nontrap;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2007 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2008
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2009 /* Do the main work of conditional store replacement. We already know
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2010 that the recognized pattern looks like so:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2011
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2012 split:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2013 if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2014 MIDDLE_BB:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2015 something
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2016 fallthrough (edge E0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2017 JOIN_BB:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2018 some more
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2019
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2020 We check that MIDDLE_BB contains only one store, that that store
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2021 doesn't trap (not via NOTRAP, but via checking if an access to the same
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2022 memory location dominates us) and that the store has a "simple" RHS. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2023
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2024 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2025 cond_store_replacement (basic_block middle_bb, basic_block join_bb,
111
kono
parents: 67
diff changeset
2026 edge e0, edge e1, hash_set<tree> *nontrap)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2027 {
111
kono
parents: 67
diff changeset
2028 gimple *assign = last_and_only_stmt (middle_bb);
kono
parents: 67
diff changeset
2029 tree lhs, rhs, name, name2;
kono
parents: 67
diff changeset
2030 gphi *newphi;
kono
parents: 67
diff changeset
2031 gassign *new_stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2032 gimple_stmt_iterator gsi;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2033 source_location locus;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2034
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2035 /* Check if middle_bb contains of only one store. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2036 if (!assign
111
kono
parents: 67
diff changeset
2037 || !gimple_assign_single_p (assign)
kono
parents: 67
diff changeset
2038 || gimple_has_volatile_ops (assign))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2039 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2040
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2041 locus = gimple_location (assign);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2042 lhs = gimple_assign_lhs (assign);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2043 rhs = gimple_assign_rhs1 (assign);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2044 if (TREE_CODE (lhs) != MEM_REF
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2045 || TREE_CODE (TREE_OPERAND (lhs, 0)) != SSA_NAME
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2046 || !is_gimple_reg_type (TREE_TYPE (lhs)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2047 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2048
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2049 /* Prove that we can move the store down. We could also check
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2050 TREE_THIS_NOTRAP here, but in that case we also could move stores,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2051 whose value is not available readily, which we want to avoid. */
111
kono
parents: 67
diff changeset
2052 if (!nontrap->contains (lhs))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2053 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2054
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2055 /* Now we've checked the constraints, so do the transformation:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2056 1) Remove the single store. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2057 gsi = gsi_for_stmt (assign);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2058 unlink_stmt_vdef (assign);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2059 gsi_remove (&gsi, true);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2060 release_defs (assign);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2061
111
kono
parents: 67
diff changeset
2062 /* Make both store and load use alias-set zero as we have to
kono
parents: 67
diff changeset
2063 deal with the case of the store being a conditional change
kono
parents: 67
diff changeset
2064 of the dynamic type. */
kono
parents: 67
diff changeset
2065 lhs = unshare_expr (lhs);
kono
parents: 67
diff changeset
2066 tree *basep = &lhs;
kono
parents: 67
diff changeset
2067 while (handled_component_p (*basep))
kono
parents: 67
diff changeset
2068 basep = &TREE_OPERAND (*basep, 0);
kono
parents: 67
diff changeset
2069 if (TREE_CODE (*basep) == MEM_REF
kono
parents: 67
diff changeset
2070 || TREE_CODE (*basep) == TARGET_MEM_REF)
kono
parents: 67
diff changeset
2071 TREE_OPERAND (*basep, 1)
kono
parents: 67
diff changeset
2072 = fold_convert (ptr_type_node, TREE_OPERAND (*basep, 1));
kono
parents: 67
diff changeset
2073 else
kono
parents: 67
diff changeset
2074 *basep = build2 (MEM_REF, TREE_TYPE (*basep),
kono
parents: 67
diff changeset
2075 build_fold_addr_expr (*basep),
kono
parents: 67
diff changeset
2076 build_zero_cst (ptr_type_node));
kono
parents: 67
diff changeset
2077
kono
parents: 67
diff changeset
2078 /* 2) Insert a load from the memory of the store to the temporary
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2079 on the edge which did not contain the store. */
111
kono
parents: 67
diff changeset
2080 name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
kono
parents: 67
diff changeset
2081 new_stmt = gimple_build_assign (name, lhs);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2082 gimple_set_location (new_stmt, locus);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2083 gsi_insert_on_edge (e1, new_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2084
111
kono
parents: 67
diff changeset
2085 /* 3) Create a PHI node at the join block, with one argument
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2086 holding the old RHS, and the other holding the temporary
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2087 where we stored the old memory contents. */
111
kono
parents: 67
diff changeset
2088 name2 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
kono
parents: 67
diff changeset
2089 newphi = create_phi_node (name2, join_bb);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2090 add_phi_arg (newphi, rhs, e0, locus);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2091 add_phi_arg (newphi, name, e1, locus);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2092
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2093 lhs = unshare_expr (lhs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2094 new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2095
111
kono
parents: 67
diff changeset
2096 /* 4) Insert that PHI node. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2097 gsi = gsi_after_labels (join_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2098 if (gsi_end_p (gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2099 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2100 gsi = gsi_last_bb (join_bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2101 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2102 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2103 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2104 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2105
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2106 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2107 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2108
111
kono
parents: 67
diff changeset
2109 /* Do the main work of conditional store replacement. */
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2110
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2111 static bool
111
kono
parents: 67
diff changeset
2112 cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
kono
parents: 67
diff changeset
2113 basic_block join_bb, gimple *then_assign,
kono
parents: 67
diff changeset
2114 gimple *else_assign)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2115 {
111
kono
parents: 67
diff changeset
2116 tree lhs_base, lhs, then_rhs, else_rhs, name;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2117 source_location then_locus, else_locus;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2118 gimple_stmt_iterator gsi;
111
kono
parents: 67
diff changeset
2119 gphi *newphi;
kono
parents: 67
diff changeset
2120 gassign *new_stmt;
kono
parents: 67
diff changeset
2121
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2122 if (then_assign == NULL
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2123 || !gimple_assign_single_p (then_assign)
111
kono
parents: 67
diff changeset
2124 || gimple_clobber_p (then_assign)
kono
parents: 67
diff changeset
2125 || gimple_has_volatile_ops (then_assign)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2126 || else_assign == NULL
111
kono
parents: 67
diff changeset
2127 || !gimple_assign_single_p (else_assign)
kono
parents: 67
diff changeset
2128 || gimple_clobber_p (else_assign)
kono
parents: 67
diff changeset
2129 || gimple_has_volatile_ops (else_assign))
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2130 return false;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2131
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2132 lhs = gimple_assign_lhs (then_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2133 if (!is_gimple_reg_type (TREE_TYPE (lhs))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2134 || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2135 return false;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2136
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2137 lhs_base = get_base_address (lhs);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2138 if (lhs_base == NULL_TREE
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2139 || (!DECL_P (lhs_base) && TREE_CODE (lhs_base) != MEM_REF))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2140 return false;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2141
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2142 then_rhs = gimple_assign_rhs1 (then_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2143 else_rhs = gimple_assign_rhs1 (else_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2144 then_locus = gimple_location (then_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2145 else_locus = gimple_location (else_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2146
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2147 /* Now we've checked the constraints, so do the transformation:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2148 1) Remove the stores. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2149 gsi = gsi_for_stmt (then_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2150 unlink_stmt_vdef (then_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2151 gsi_remove (&gsi, true);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2152 release_defs (then_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2153
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2154 gsi = gsi_for_stmt (else_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2155 unlink_stmt_vdef (else_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2156 gsi_remove (&gsi, true);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2157 release_defs (else_assign);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2158
111
kono
parents: 67
diff changeset
2159 /* 2) Create a PHI node at the join block, with one argument
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2160 holding the old RHS, and the other holding the temporary
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2161 where we stored the old memory contents. */
111
kono
parents: 67
diff changeset
2162 name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
kono
parents: 67
diff changeset
2163 newphi = create_phi_node (name, join_bb);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2164 add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2165 add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2166
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2167 new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi));
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2168
111
kono
parents: 67
diff changeset
2169 /* 3) Insert that PHI node. */
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2170 gsi = gsi_after_labels (join_bb);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2171 if (gsi_end_p (gsi))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2172 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2173 gsi = gsi_last_bb (join_bb);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2174 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2175 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2176 else
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2177 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2178
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2179 return true;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2180 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2181
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2182 /* Return the single store in BB with VDEF or NULL if there are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2183 other stores in the BB or loads following the store. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2184
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2185 static gimple *
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2186 single_trailing_store_in_bb (basic_block bb, tree vdef)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2187 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2188 if (SSA_NAME_IS_DEFAULT_DEF (vdef))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2189 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2190 gimple *store = SSA_NAME_DEF_STMT (vdef);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2191 if (gimple_bb (store) != bb
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2192 || gimple_code (store) == GIMPLE_PHI)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2193 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2194
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2195 /* Verify there is no other store in this BB. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2196 if (!SSA_NAME_IS_DEFAULT_DEF (gimple_vuse (store))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2197 && gimple_bb (SSA_NAME_DEF_STMT (gimple_vuse (store))) == bb
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2198 && gimple_code (SSA_NAME_DEF_STMT (gimple_vuse (store))) != GIMPLE_PHI)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2199 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2200
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2201 /* Verify there is no load or store after the store. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2202 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2203 imm_use_iterator imm_iter;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2204 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_vdef (store))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2205 if (USE_STMT (use_p) != store
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2206 && gimple_bb (USE_STMT (use_p)) == bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2207 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2208
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2209 return store;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2210 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2211
111
kono
parents: 67
diff changeset
2212 /* Conditional store replacement. We already know
kono
parents: 67
diff changeset
2213 that the recognized pattern looks like so:
kono
parents: 67
diff changeset
2214
kono
parents: 67
diff changeset
2215 split:
kono
parents: 67
diff changeset
2216 if (cond) goto THEN_BB; else goto ELSE_BB (edge E1)
kono
parents: 67
diff changeset
2217 THEN_BB:
kono
parents: 67
diff changeset
2218 ...
kono
parents: 67
diff changeset
2219 X = Y;
kono
parents: 67
diff changeset
2220 ...
kono
parents: 67
diff changeset
2221 goto JOIN_BB;
kono
parents: 67
diff changeset
2222 ELSE_BB:
kono
parents: 67
diff changeset
2223 ...
kono
parents: 67
diff changeset
2224 X = Z;
kono
parents: 67
diff changeset
2225 ...
kono
parents: 67
diff changeset
2226 fallthrough (edge E0)
kono
parents: 67
diff changeset
2227 JOIN_BB:
kono
parents: 67
diff changeset
2228 some more
kono
parents: 67
diff changeset
2229
kono
parents: 67
diff changeset
2230 We check that it is safe to sink the store to JOIN_BB by verifying that
kono
parents: 67
diff changeset
2231 there are no read-after-write or write-after-write dependencies in
kono
parents: 67
diff changeset
2232 THEN_BB and ELSE_BB. */
kono
parents: 67
diff changeset
2233
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2234 static bool
111
kono
parents: 67
diff changeset
2235 cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
kono
parents: 67
diff changeset
2236 basic_block join_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2237 {
111
kono
parents: 67
diff changeset
2238 vec<data_reference_p> then_datarefs, else_datarefs;
kono
parents: 67
diff changeset
2239 vec<ddr_p> then_ddrs, else_ddrs;
kono
parents: 67
diff changeset
2240 gimple *then_store, *else_store;
kono
parents: 67
diff changeset
2241 bool found, ok = false, res;
kono
parents: 67
diff changeset
2242 struct data_dependence_relation *ddr;
kono
parents: 67
diff changeset
2243 data_reference_p then_dr, else_dr;
kono
parents: 67
diff changeset
2244 int i, j;
kono
parents: 67
diff changeset
2245 tree then_lhs, else_lhs;
kono
parents: 67
diff changeset
2246 basic_block blocks[3];
kono
parents: 67
diff changeset
2247
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2248 /* Handle the case with single store in THEN_BB and ELSE_BB. That is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2249 cheap enough to always handle as it allows us to elide dependence
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2250 checking. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2251 gphi *vphi = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2252 for (gphi_iterator si = gsi_start_phis (join_bb); !gsi_end_p (si);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2253 gsi_next (&si))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2254 if (virtual_operand_p (gimple_phi_result (si.phi ())))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2255 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2256 vphi = si.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2257 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2258 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2259 if (!vphi)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2260 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2261 tree then_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (then_bb));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2262 tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2263 gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2264 if (then_assign)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2265 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2266 gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2267 if (else_assign)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2268 return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2269 then_assign, else_assign);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2270 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2271
111
kono
parents: 67
diff changeset
2272 if (MAX_STORES_TO_SINK == 0)
kono
parents: 67
diff changeset
2273 return false;
kono
parents: 67
diff changeset
2274
kono
parents: 67
diff changeset
2275 /* Find data references. */
kono
parents: 67
diff changeset
2276 then_datarefs.create (1);
kono
parents: 67
diff changeset
2277 else_datarefs.create (1);
kono
parents: 67
diff changeset
2278 if ((find_data_references_in_bb (NULL, then_bb, &then_datarefs)
kono
parents: 67
diff changeset
2279 == chrec_dont_know)
kono
parents: 67
diff changeset
2280 || !then_datarefs.length ()
kono
parents: 67
diff changeset
2281 || (find_data_references_in_bb (NULL, else_bb, &else_datarefs)
kono
parents: 67
diff changeset
2282 == chrec_dont_know)
kono
parents: 67
diff changeset
2283 || !else_datarefs.length ())
kono
parents: 67
diff changeset
2284 {
kono
parents: 67
diff changeset
2285 free_data_refs (then_datarefs);
kono
parents: 67
diff changeset
2286 free_data_refs (else_datarefs);
kono
parents: 67
diff changeset
2287 return false;
kono
parents: 67
diff changeset
2288 }
kono
parents: 67
diff changeset
2289
kono
parents: 67
diff changeset
2290 /* Find pairs of stores with equal LHS. */
kono
parents: 67
diff changeset
2291 auto_vec<gimple *, 1> then_stores, else_stores;
kono
parents: 67
diff changeset
2292 FOR_EACH_VEC_ELT (then_datarefs, i, then_dr)
kono
parents: 67
diff changeset
2293 {
kono
parents: 67
diff changeset
2294 if (DR_IS_READ (then_dr))
kono
parents: 67
diff changeset
2295 continue;
kono
parents: 67
diff changeset
2296
kono
parents: 67
diff changeset
2297 then_store = DR_STMT (then_dr);
kono
parents: 67
diff changeset
2298 then_lhs = gimple_get_lhs (then_store);
kono
parents: 67
diff changeset
2299 if (then_lhs == NULL_TREE)
kono
parents: 67
diff changeset
2300 continue;
kono
parents: 67
diff changeset
2301 found = false;
kono
parents: 67
diff changeset
2302
kono
parents: 67
diff changeset
2303 FOR_EACH_VEC_ELT (else_datarefs, j, else_dr)
kono
parents: 67
diff changeset
2304 {
kono
parents: 67
diff changeset
2305 if (DR_IS_READ (else_dr))
kono
parents: 67
diff changeset
2306 continue;
kono
parents: 67
diff changeset
2307
kono
parents: 67
diff changeset
2308 else_store = DR_STMT (else_dr);
kono
parents: 67
diff changeset
2309 else_lhs = gimple_get_lhs (else_store);
kono
parents: 67
diff changeset
2310 if (else_lhs == NULL_TREE)
kono
parents: 67
diff changeset
2311 continue;
kono
parents: 67
diff changeset
2312
kono
parents: 67
diff changeset
2313 if (operand_equal_p (then_lhs, else_lhs, 0))
kono
parents: 67
diff changeset
2314 {
kono
parents: 67
diff changeset
2315 found = true;
kono
parents: 67
diff changeset
2316 break;
kono
parents: 67
diff changeset
2317 }
kono
parents: 67
diff changeset
2318 }
kono
parents: 67
diff changeset
2319
kono
parents: 67
diff changeset
2320 if (!found)
kono
parents: 67
diff changeset
2321 continue;
kono
parents: 67
diff changeset
2322
kono
parents: 67
diff changeset
2323 then_stores.safe_push (then_store);
kono
parents: 67
diff changeset
2324 else_stores.safe_push (else_store);
kono
parents: 67
diff changeset
2325 }
kono
parents: 67
diff changeset
2326
kono
parents: 67
diff changeset
2327 /* No pairs of stores found. */
kono
parents: 67
diff changeset
2328 if (!then_stores.length ()
kono
parents: 67
diff changeset
2329 || then_stores.length () > (unsigned) MAX_STORES_TO_SINK)
kono
parents: 67
diff changeset
2330 {
kono
parents: 67
diff changeset
2331 free_data_refs (then_datarefs);
kono
parents: 67
diff changeset
2332 free_data_refs (else_datarefs);
kono
parents: 67
diff changeset
2333 return false;
kono
parents: 67
diff changeset
2334 }
kono
parents: 67
diff changeset
2335
kono
parents: 67
diff changeset
2336 /* Compute and check data dependencies in both basic blocks. */
kono
parents: 67
diff changeset
2337 then_ddrs.create (1);
kono
parents: 67
diff changeset
2338 else_ddrs.create (1);
kono
parents: 67
diff changeset
2339 if (!compute_all_dependences (then_datarefs, &then_ddrs,
kono
parents: 67
diff changeset
2340 vNULL, false)
kono
parents: 67
diff changeset
2341 || !compute_all_dependences (else_datarefs, &else_ddrs,
kono
parents: 67
diff changeset
2342 vNULL, false))
kono
parents: 67
diff changeset
2343 {
kono
parents: 67
diff changeset
2344 free_dependence_relations (then_ddrs);
kono
parents: 67
diff changeset
2345 free_dependence_relations (else_ddrs);
kono
parents: 67
diff changeset
2346 free_data_refs (then_datarefs);
kono
parents: 67
diff changeset
2347 free_data_refs (else_datarefs);
kono
parents: 67
diff changeset
2348 return false;
kono
parents: 67
diff changeset
2349 }
kono
parents: 67
diff changeset
2350 blocks[0] = then_bb;
kono
parents: 67
diff changeset
2351 blocks[1] = else_bb;
kono
parents: 67
diff changeset
2352 blocks[2] = join_bb;
kono
parents: 67
diff changeset
2353 renumber_gimple_stmt_uids_in_blocks (blocks, 3);
kono
parents: 67
diff changeset
2354
kono
parents: 67
diff changeset
2355 /* Check that there are no read-after-write or write-after-write dependencies
kono
parents: 67
diff changeset
2356 in THEN_BB. */
kono
parents: 67
diff changeset
2357 FOR_EACH_VEC_ELT (then_ddrs, i, ddr)
kono
parents: 67
diff changeset
2358 {
kono
parents: 67
diff changeset
2359 struct data_reference *dra = DDR_A (ddr);
kono
parents: 67
diff changeset
2360 struct data_reference *drb = DDR_B (ddr);
kono
parents: 67
diff changeset
2361
kono
parents: 67
diff changeset
2362 if (DDR_ARE_DEPENDENT (ddr) != chrec_known
kono
parents: 67
diff changeset
2363 && ((DR_IS_READ (dra) && DR_IS_WRITE (drb)
kono
parents: 67
diff changeset
2364 && gimple_uid (DR_STMT (dra)) > gimple_uid (DR_STMT (drb)))
kono
parents: 67
diff changeset
2365 || (DR_IS_READ (drb) && DR_IS_WRITE (dra)
kono
parents: 67
diff changeset
2366 && gimple_uid (DR_STMT (drb)) > gimple_uid (DR_STMT (dra)))
kono
parents: 67
diff changeset
2367 || (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))))
kono
parents: 67
diff changeset
2368 {
kono
parents: 67
diff changeset
2369 free_dependence_relations (then_ddrs);
kono
parents: 67
diff changeset
2370 free_dependence_relations (else_ddrs);
kono
parents: 67
diff changeset
2371 free_data_refs (then_datarefs);
kono
parents: 67
diff changeset
2372 free_data_refs (else_datarefs);
kono
parents: 67
diff changeset
2373 return false;
kono
parents: 67
diff changeset
2374 }
kono
parents: 67
diff changeset
2375 }
kono
parents: 67
diff changeset
2376
kono
parents: 67
diff changeset
2377 /* Check that there are no read-after-write or write-after-write dependencies
kono
parents: 67
diff changeset
2378 in ELSE_BB. */
kono
parents: 67
diff changeset
2379 FOR_EACH_VEC_ELT (else_ddrs, i, ddr)
kono
parents: 67
diff changeset
2380 {
kono
parents: 67
diff changeset
2381 struct data_reference *dra = DDR_A (ddr);
kono
parents: 67
diff changeset
2382 struct data_reference *drb = DDR_B (ddr);
kono
parents: 67
diff changeset
2383
kono
parents: 67
diff changeset
2384 if (DDR_ARE_DEPENDENT (ddr) != chrec_known
kono
parents: 67
diff changeset
2385 && ((DR_IS_READ (dra) && DR_IS_WRITE (drb)
kono
parents: 67
diff changeset
2386 && gimple_uid (DR_STMT (dra)) > gimple_uid (DR_STMT (drb)))
kono
parents: 67
diff changeset
2387 || (DR_IS_READ (drb) && DR_IS_WRITE (dra)
kono
parents: 67
diff changeset
2388 && gimple_uid (DR_STMT (drb)) > gimple_uid (DR_STMT (dra)))
kono
parents: 67
diff changeset
2389 || (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))))
kono
parents: 67
diff changeset
2390 {
kono
parents: 67
diff changeset
2391 free_dependence_relations (then_ddrs);
kono
parents: 67
diff changeset
2392 free_dependence_relations (else_ddrs);
kono
parents: 67
diff changeset
2393 free_data_refs (then_datarefs);
kono
parents: 67
diff changeset
2394 free_data_refs (else_datarefs);
kono
parents: 67
diff changeset
2395 return false;
kono
parents: 67
diff changeset
2396 }
kono
parents: 67
diff changeset
2397 }
kono
parents: 67
diff changeset
2398
kono
parents: 67
diff changeset
2399 /* Sink stores with same LHS. */
kono
parents: 67
diff changeset
2400 FOR_EACH_VEC_ELT (then_stores, i, then_store)
kono
parents: 67
diff changeset
2401 {
kono
parents: 67
diff changeset
2402 else_store = else_stores[i];
kono
parents: 67
diff changeset
2403 res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
kono
parents: 67
diff changeset
2404 then_store, else_store);
kono
parents: 67
diff changeset
2405 ok = ok || res;
kono
parents: 67
diff changeset
2406 }
kono
parents: 67
diff changeset
2407
kono
parents: 67
diff changeset
2408 free_dependence_relations (then_ddrs);
kono
parents: 67
diff changeset
2409 free_dependence_relations (else_ddrs);
kono
parents: 67
diff changeset
2410 free_data_refs (then_datarefs);
kono
parents: 67
diff changeset
2411 free_data_refs (else_datarefs);
kono
parents: 67
diff changeset
2412
kono
parents: 67
diff changeset
2413 return ok;
kono
parents: 67
diff changeset
2414 }
kono
parents: 67
diff changeset
2415
kono
parents: 67
diff changeset
2416 /* Return TRUE if STMT has a VUSE whose corresponding VDEF is in BB. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2417
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2418 static bool
111
kono
parents: 67
diff changeset
2419 local_mem_dependence (gimple *stmt, basic_block bb)
kono
parents: 67
diff changeset
2420 {
kono
parents: 67
diff changeset
2421 tree vuse = gimple_vuse (stmt);
kono
parents: 67
diff changeset
2422 gimple *def;
kono
parents: 67
diff changeset
2423
kono
parents: 67
diff changeset
2424 if (!vuse)
kono
parents: 67
diff changeset
2425 return false;
kono
parents: 67
diff changeset
2426
kono
parents: 67
diff changeset
2427 def = SSA_NAME_DEF_STMT (vuse);
kono
parents: 67
diff changeset
2428 return (def && gimple_bb (def) == bb);
kono
parents: 67
diff changeset
2429 }
kono
parents: 67
diff changeset
2430
kono
parents: 67
diff changeset
2431 /* Given a "diamond" control-flow pattern where BB0 tests a condition,
kono
parents: 67
diff changeset
2432 BB1 and BB2 are "then" and "else" blocks dependent on this test,
kono
parents: 67
diff changeset
2433 and BB3 rejoins control flow following BB1 and BB2, look for
kono
parents: 67
diff changeset
2434 opportunities to hoist loads as follows. If BB3 contains a PHI of
kono
parents: 67
diff changeset
2435 two loads, one each occurring in BB1 and BB2, and the loads are
kono
parents: 67
diff changeset
2436 provably of adjacent fields in the same structure, then move both
kono
parents: 67
diff changeset
2437 loads into BB0. Of course this can only be done if there are no
kono
parents: 67
diff changeset
2438 dependencies preventing such motion.
kono
parents: 67
diff changeset
2439
kono
parents: 67
diff changeset
2440 One of the hoisted loads will always be speculative, so the
kono
parents: 67
diff changeset
2441 transformation is currently conservative:
kono
parents: 67
diff changeset
2442
kono
parents: 67
diff changeset
2443 - The fields must be strictly adjacent.
kono
parents: 67
diff changeset
2444 - The two fields must occupy a single memory block that is
kono
parents: 67
diff changeset
2445 guaranteed to not cross a page boundary.
kono
parents: 67
diff changeset
2446
kono
parents: 67
diff changeset
2447 The last is difficult to prove, as such memory blocks should be
kono
parents: 67
diff changeset
2448 aligned on the minimum of the stack alignment boundary and the
kono
parents: 67
diff changeset
2449 alignment guaranteed by heap allocation interfaces. Thus we rely
kono
parents: 67
diff changeset
2450 on a parameter for the alignment value.
kono
parents: 67
diff changeset
2451
kono
parents: 67
diff changeset
2452 Provided a good value is used for the last case, the first
kono
parents: 67
diff changeset
2453 restriction could possibly be relaxed. */
kono
parents: 67
diff changeset
2454
kono
parents: 67
diff changeset
2455 static void
kono
parents: 67
diff changeset
2456 hoist_adjacent_loads (basic_block bb0, basic_block bb1,
kono
parents: 67
diff changeset
2457 basic_block bb2, basic_block bb3)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2458 {
111
kono
parents: 67
diff changeset
2459 int param_align = PARAM_VALUE (PARAM_L1_CACHE_LINE_SIZE);
kono
parents: 67
diff changeset
2460 unsigned param_align_bits = (unsigned) (param_align * BITS_PER_UNIT);
kono
parents: 67
diff changeset
2461 gphi_iterator gsi;
kono
parents: 67
diff changeset
2462
kono
parents: 67
diff changeset
2463 /* Walk the phis in bb3 looking for an opportunity. We are looking
kono
parents: 67
diff changeset
2464 for phis of two SSA names, one each of which is defined in bb1 and
kono
parents: 67
diff changeset
2465 bb2. */
kono
parents: 67
diff changeset
2466 for (gsi = gsi_start_phis (bb3); !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
2467 {
kono
parents: 67
diff changeset
2468 gphi *phi_stmt = gsi.phi ();
kono
parents: 67
diff changeset
2469 gimple *def1, *def2;
kono
parents: 67
diff changeset
2470 tree arg1, arg2, ref1, ref2, field1, field2;
kono
parents: 67
diff changeset
2471 tree tree_offset1, tree_offset2, tree_size2, next;
kono
parents: 67
diff changeset
2472 int offset1, offset2, size2;
kono
parents: 67
diff changeset
2473 unsigned align1;
kono
parents: 67
diff changeset
2474 gimple_stmt_iterator gsi2;
kono
parents: 67
diff changeset
2475 basic_block bb_for_def1, bb_for_def2;
kono
parents: 67
diff changeset
2476
kono
parents: 67
diff changeset
2477 if (gimple_phi_num_args (phi_stmt) != 2
kono
parents: 67
diff changeset
2478 || virtual_operand_p (gimple_phi_result (phi_stmt)))
kono
parents: 67
diff changeset
2479 continue;
kono
parents: 67
diff changeset
2480
kono
parents: 67
diff changeset
2481 arg1 = gimple_phi_arg_def (phi_stmt, 0);
kono
parents: 67
diff changeset
2482 arg2 = gimple_phi_arg_def (phi_stmt, 1);
kono
parents: 67
diff changeset
2483
kono
parents: 67
diff changeset
2484 if (TREE_CODE (arg1) != SSA_NAME
kono
parents: 67
diff changeset
2485 || TREE_CODE (arg2) != SSA_NAME
kono
parents: 67
diff changeset
2486 || SSA_NAME_IS_DEFAULT_DEF (arg1)
kono
parents: 67
diff changeset
2487 || SSA_NAME_IS_DEFAULT_DEF (arg2))
kono
parents: 67
diff changeset
2488 continue;
kono
parents: 67
diff changeset
2489
kono
parents: 67
diff changeset
2490 def1 = SSA_NAME_DEF_STMT (arg1);
kono
parents: 67
diff changeset
2491 def2 = SSA_NAME_DEF_STMT (arg2);
kono
parents: 67
diff changeset
2492
kono
parents: 67
diff changeset
2493 if ((gimple_bb (def1) != bb1 || gimple_bb (def2) != bb2)
kono
parents: 67
diff changeset
2494 && (gimple_bb (def2) != bb1 || gimple_bb (def1) != bb2))
kono
parents: 67
diff changeset
2495 continue;
kono
parents: 67
diff changeset
2496
kono
parents: 67
diff changeset
2497 /* Check the mode of the arguments to be sure a conditional move
kono
parents: 67
diff changeset
2498 can be generated for it. */
kono
parents: 67
diff changeset
2499 if (optab_handler (movcc_optab, TYPE_MODE (TREE_TYPE (arg1)))
kono
parents: 67
diff changeset
2500 == CODE_FOR_nothing)
kono
parents: 67
diff changeset
2501 continue;
kono
parents: 67
diff changeset
2502
kono
parents: 67
diff changeset
2503 /* Both statements must be assignments whose RHS is a COMPONENT_REF. */
kono
parents: 67
diff changeset
2504 if (!gimple_assign_single_p (def1)
kono
parents: 67
diff changeset
2505 || !gimple_assign_single_p (def2)
kono
parents: 67
diff changeset
2506 || gimple_has_volatile_ops (def1)
kono
parents: 67
diff changeset
2507 || gimple_has_volatile_ops (def2))
kono
parents: 67
diff changeset
2508 continue;
kono
parents: 67
diff changeset
2509
kono
parents: 67
diff changeset
2510 ref1 = gimple_assign_rhs1 (def1);
kono
parents: 67
diff changeset
2511 ref2 = gimple_assign_rhs1 (def2);
kono
parents: 67
diff changeset
2512
kono
parents: 67
diff changeset
2513 if (TREE_CODE (ref1) != COMPONENT_REF
kono
parents: 67
diff changeset
2514 || TREE_CODE (ref2) != COMPONENT_REF)
kono
parents: 67
diff changeset
2515 continue;
kono
parents: 67
diff changeset
2516
kono
parents: 67
diff changeset
2517 /* The zeroth operand of the two component references must be
kono
parents: 67
diff changeset
2518 identical. It is not sufficient to compare get_base_address of
kono
parents: 67
diff changeset
2519 the two references, because this could allow for different
kono
parents: 67
diff changeset
2520 elements of the same array in the two trees. It is not safe to
kono
parents: 67
diff changeset
2521 assume that the existence of one array element implies the
kono
parents: 67
diff changeset
2522 existence of a different one. */
kono
parents: 67
diff changeset
2523 if (!operand_equal_p (TREE_OPERAND (ref1, 0), TREE_OPERAND (ref2, 0), 0))
kono
parents: 67
diff changeset
2524 continue;
kono
parents: 67
diff changeset
2525
kono
parents: 67
diff changeset
2526 field1 = TREE_OPERAND (ref1, 1);
kono
parents: 67
diff changeset
2527 field2 = TREE_OPERAND (ref2, 1);
kono
parents: 67
diff changeset
2528
kono
parents: 67
diff changeset
2529 /* Check for field adjacency, and ensure field1 comes first. */
kono
parents: 67
diff changeset
2530 for (next = DECL_CHAIN (field1);
kono
parents: 67
diff changeset
2531 next && TREE_CODE (next) != FIELD_DECL;
kono
parents: 67
diff changeset
2532 next = DECL_CHAIN (next))
kono
parents: 67
diff changeset
2533 ;
kono
parents: 67
diff changeset
2534
kono
parents: 67
diff changeset
2535 if (next != field2)
kono
parents: 67
diff changeset
2536 {
kono
parents: 67
diff changeset
2537 for (next = DECL_CHAIN (field2);
kono
parents: 67
diff changeset
2538 next && TREE_CODE (next) != FIELD_DECL;
kono
parents: 67
diff changeset
2539 next = DECL_CHAIN (next))
kono
parents: 67
diff changeset
2540 ;
kono
parents: 67
diff changeset
2541
kono
parents: 67
diff changeset
2542 if (next != field1)
kono
parents: 67
diff changeset
2543 continue;
kono
parents: 67
diff changeset
2544
kono
parents: 67
diff changeset
2545 std::swap (field1, field2);
kono
parents: 67
diff changeset
2546 std::swap (def1, def2);
kono
parents: 67
diff changeset
2547 }
kono
parents: 67
diff changeset
2548
kono
parents: 67
diff changeset
2549 bb_for_def1 = gimple_bb (def1);
kono
parents: 67
diff changeset
2550 bb_for_def2 = gimple_bb (def2);
kono
parents: 67
diff changeset
2551
kono
parents: 67
diff changeset
2552 /* Check for proper alignment of the first field. */
kono
parents: 67
diff changeset
2553 tree_offset1 = bit_position (field1);
kono
parents: 67
diff changeset
2554 tree_offset2 = bit_position (field2);
kono
parents: 67
diff changeset
2555 tree_size2 = DECL_SIZE (field2);
kono
parents: 67
diff changeset
2556
kono
parents: 67
diff changeset
2557 if (!tree_fits_uhwi_p (tree_offset1)
kono
parents: 67
diff changeset
2558 || !tree_fits_uhwi_p (tree_offset2)
kono
parents: 67
diff changeset
2559 || !tree_fits_uhwi_p (tree_size2))
kono
parents: 67
diff changeset
2560 continue;
kono
parents: 67
diff changeset
2561
kono
parents: 67
diff changeset
2562 offset1 = tree_to_uhwi (tree_offset1);
kono
parents: 67
diff changeset
2563 offset2 = tree_to_uhwi (tree_offset2);
kono
parents: 67
diff changeset
2564 size2 = tree_to_uhwi (tree_size2);
kono
parents: 67
diff changeset
2565 align1 = DECL_ALIGN (field1) % param_align_bits;
kono
parents: 67
diff changeset
2566
kono
parents: 67
diff changeset
2567 if (offset1 % BITS_PER_UNIT != 0)
kono
parents: 67
diff changeset
2568 continue;
kono
parents: 67
diff changeset
2569
kono
parents: 67
diff changeset
2570 /* For profitability, the two field references should fit within
kono
parents: 67
diff changeset
2571 a single cache line. */
kono
parents: 67
diff changeset
2572 if (align1 + offset2 - offset1 + size2 > param_align_bits)
kono
parents: 67
diff changeset
2573 continue;
kono
parents: 67
diff changeset
2574
kono
parents: 67
diff changeset
2575 /* The two expressions cannot be dependent upon vdefs defined
kono
parents: 67
diff changeset
2576 in bb1/bb2. */
kono
parents: 67
diff changeset
2577 if (local_mem_dependence (def1, bb_for_def1)
kono
parents: 67
diff changeset
2578 || local_mem_dependence (def2, bb_for_def2))
kono
parents: 67
diff changeset
2579 continue;
kono
parents: 67
diff changeset
2580
kono
parents: 67
diff changeset
2581 /* The conditions are satisfied; hoist the loads from bb1 and bb2 into
kono
parents: 67
diff changeset
2582 bb0. We hoist the first one first so that a cache miss is handled
kono
parents: 67
diff changeset
2583 efficiently regardless of hardware cache-fill policy. */
kono
parents: 67
diff changeset
2584 gsi2 = gsi_for_stmt (def1);
kono
parents: 67
diff changeset
2585 gsi_move_to_bb_end (&gsi2, bb0);
kono
parents: 67
diff changeset
2586 gsi2 = gsi_for_stmt (def2);
kono
parents: 67
diff changeset
2587 gsi_move_to_bb_end (&gsi2, bb0);
kono
parents: 67
diff changeset
2588
kono
parents: 67
diff changeset
2589 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
2590 {
kono
parents: 67
diff changeset
2591 fprintf (dump_file,
kono
parents: 67
diff changeset
2592 "\nHoisting adjacent loads from %d and %d into %d: \n",
kono
parents: 67
diff changeset
2593 bb_for_def1->index, bb_for_def2->index, bb0->index);
kono
parents: 67
diff changeset
2594 print_gimple_stmt (dump_file, def1, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents: 67
diff changeset
2595 print_gimple_stmt (dump_file, def2, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents: 67
diff changeset
2596 }
kono
parents: 67
diff changeset
2597 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2598 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2599
111
kono
parents: 67
diff changeset
2600 /* Determine whether we should attempt to hoist adjacent loads out of
kono
parents: 67
diff changeset
2601 diamond patterns in pass_phiopt. Always hoist loads if
kono
parents: 67
diff changeset
2602 -fhoist-adjacent-loads is specified and the target machine has
kono
parents: 67
diff changeset
2603 both a conditional move instruction and a defined cache line size. */
kono
parents: 67
diff changeset
2604
kono
parents: 67
diff changeset
2605 static bool
kono
parents: 67
diff changeset
2606 gate_hoist_loads (void)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2607 {
111
kono
parents: 67
diff changeset
2608 return (flag_hoist_adjacent_loads == 1
kono
parents: 67
diff changeset
2609 && PARAM_VALUE (PARAM_L1_CACHE_LINE_SIZE)
kono
parents: 67
diff changeset
2610 && HAVE_conditional_move);
kono
parents: 67
diff changeset
2611 }
kono
parents: 67
diff changeset
2612
kono
parents: 67
diff changeset
2613 /* This pass tries to replaces an if-then-else block with an
kono
parents: 67
diff changeset
2614 assignment. We have four kinds of transformations. Some of these
kono
parents: 67
diff changeset
2615 transformations are also performed by the ifcvt RTL optimizer.
kono
parents: 67
diff changeset
2616
kono
parents: 67
diff changeset
2617 Conditional Replacement
kono
parents: 67
diff changeset
2618 -----------------------
kono
parents: 67
diff changeset
2619
kono
parents: 67
diff changeset
2620 This transformation, implemented in conditional_replacement,
kono
parents: 67
diff changeset
2621 replaces
kono
parents: 67
diff changeset
2622
kono
parents: 67
diff changeset
2623 bb0:
kono
parents: 67
diff changeset
2624 if (cond) goto bb2; else goto bb1;
kono
parents: 67
diff changeset
2625 bb1:
kono
parents: 67
diff changeset
2626 bb2:
kono
parents: 67
diff changeset
2627 x = PHI <0 (bb1), 1 (bb0), ...>;
kono
parents: 67
diff changeset
2628
kono
parents: 67
diff changeset
2629 with
kono
parents: 67
diff changeset
2630
kono
parents: 67
diff changeset
2631 bb0:
kono
parents: 67
diff changeset
2632 x' = cond;
kono
parents: 67
diff changeset
2633 goto bb2;
kono
parents: 67
diff changeset
2634 bb2:
kono
parents: 67
diff changeset
2635 x = PHI <x' (bb0), ...>;
kono
parents: 67
diff changeset
2636
kono
parents: 67
diff changeset
2637 We remove bb1 as it becomes unreachable. This occurs often due to
kono
parents: 67
diff changeset
2638 gimplification of conditionals.
kono
parents: 67
diff changeset
2639
kono
parents: 67
diff changeset
2640 Value Replacement
kono
parents: 67
diff changeset
2641 -----------------
kono
parents: 67
diff changeset
2642
kono
parents: 67
diff changeset
2643 This transformation, implemented in value_replacement, replaces
kono
parents: 67
diff changeset
2644
kono
parents: 67
diff changeset
2645 bb0:
kono
parents: 67
diff changeset
2646 if (a != b) goto bb2; else goto bb1;
kono
parents: 67
diff changeset
2647 bb1:
kono
parents: 67
diff changeset
2648 bb2:
kono
parents: 67
diff changeset
2649 x = PHI <a (bb1), b (bb0), ...>;
kono
parents: 67
diff changeset
2650
kono
parents: 67
diff changeset
2651 with
kono
parents: 67
diff changeset
2652
kono
parents: 67
diff changeset
2653 bb0:
kono
parents: 67
diff changeset
2654 bb2:
kono
parents: 67
diff changeset
2655 x = PHI <b (bb0), ...>;
kono
parents: 67
diff changeset
2656
kono
parents: 67
diff changeset
2657 This opportunity can sometimes occur as a result of other
kono
parents: 67
diff changeset
2658 optimizations.
kono
parents: 67
diff changeset
2659
kono
parents: 67
diff changeset
2660
kono
parents: 67
diff changeset
2661 Another case caught by value replacement looks like this:
kono
parents: 67
diff changeset
2662
kono
parents: 67
diff changeset
2663 bb0:
kono
parents: 67
diff changeset
2664 t1 = a == CONST;
kono
parents: 67
diff changeset
2665 t2 = b > c;
kono
parents: 67
diff changeset
2666 t3 = t1 & t2;
kono
parents: 67
diff changeset
2667 if (t3 != 0) goto bb1; else goto bb2;
kono
parents: 67
diff changeset
2668 bb1:
kono
parents: 67
diff changeset
2669 bb2:
kono
parents: 67
diff changeset
2670 x = PHI (CONST, a)
kono
parents: 67
diff changeset
2671
kono
parents: 67
diff changeset
2672 Gets replaced with:
kono
parents: 67
diff changeset
2673 bb0:
kono
parents: 67
diff changeset
2674 bb2:
kono
parents: 67
diff changeset
2675 t1 = a == CONST;
kono
parents: 67
diff changeset
2676 t2 = b > c;
kono
parents: 67
diff changeset
2677 t3 = t1 & t2;
kono
parents: 67
diff changeset
2678 x = a;
kono
parents: 67
diff changeset
2679
kono
parents: 67
diff changeset
2680 ABS Replacement
kono
parents: 67
diff changeset
2681 ---------------
kono
parents: 67
diff changeset
2682
kono
parents: 67
diff changeset
2683 This transformation, implemented in abs_replacement, replaces
kono
parents: 67
diff changeset
2684
kono
parents: 67
diff changeset
2685 bb0:
kono
parents: 67
diff changeset
2686 if (a >= 0) goto bb2; else goto bb1;
kono
parents: 67
diff changeset
2687 bb1:
kono
parents: 67
diff changeset
2688 x = -a;
kono
parents: 67
diff changeset
2689 bb2:
kono
parents: 67
diff changeset
2690 x = PHI <x (bb1), a (bb0), ...>;
kono
parents: 67
diff changeset
2691
kono
parents: 67
diff changeset
2692 with
kono
parents: 67
diff changeset
2693
kono
parents: 67
diff changeset
2694 bb0:
kono
parents: 67
diff changeset
2695 x' = ABS_EXPR< a >;
kono
parents: 67
diff changeset
2696 bb2:
kono
parents: 67
diff changeset
2697 x = PHI <x' (bb0), ...>;
kono
parents: 67
diff changeset
2698
kono
parents: 67
diff changeset
2699 MIN/MAX Replacement
kono
parents: 67
diff changeset
2700 -------------------
kono
parents: 67
diff changeset
2701
kono
parents: 67
diff changeset
2702 This transformation, minmax_replacement replaces
kono
parents: 67
diff changeset
2703
kono
parents: 67
diff changeset
2704 bb0:
kono
parents: 67
diff changeset
2705 if (a <= b) goto bb2; else goto bb1;
kono
parents: 67
diff changeset
2706 bb1:
kono
parents: 67
diff changeset
2707 bb2:
kono
parents: 67
diff changeset
2708 x = PHI <b (bb1), a (bb0), ...>;
kono
parents: 67
diff changeset
2709
kono
parents: 67
diff changeset
2710 with
kono
parents: 67
diff changeset
2711
kono
parents: 67
diff changeset
2712 bb0:
kono
parents: 67
diff changeset
2713 x' = MIN_EXPR (a, b)
kono
parents: 67
diff changeset
2714 bb2:
kono
parents: 67
diff changeset
2715 x = PHI <x' (bb0), ...>;
kono
parents: 67
diff changeset
2716
kono
parents: 67
diff changeset
2717 A similar transformation is done for MAX_EXPR.
kono
parents: 67
diff changeset
2718
kono
parents: 67
diff changeset
2719
kono
parents: 67
diff changeset
2720 This pass also performs a fifth transformation of a slightly different
kono
parents: 67
diff changeset
2721 flavor.
kono
parents: 67
diff changeset
2722
kono
parents: 67
diff changeset
2723 Factor conversion in COND_EXPR
kono
parents: 67
diff changeset
2724 ------------------------------
kono
parents: 67
diff changeset
2725
kono
parents: 67
diff changeset
2726 This transformation factors the conversion out of COND_EXPR with
kono
parents: 67
diff changeset
2727 factor_out_conditional_conversion.
kono
parents: 67
diff changeset
2728
kono
parents: 67
diff changeset
2729 For example:
kono
parents: 67
diff changeset
2730 if (a <= CST) goto <bb 3>; else goto <bb 4>;
kono
parents: 67
diff changeset
2731 <bb 3>:
kono
parents: 67
diff changeset
2732 tmp = (int) a;
kono
parents: 67
diff changeset
2733 <bb 4>:
kono
parents: 67
diff changeset
2734 tmp = PHI <tmp, CST>
kono
parents: 67
diff changeset
2735
kono
parents: 67
diff changeset
2736 Into:
kono
parents: 67
diff changeset
2737 if (a <= CST) goto <bb 3>; else goto <bb 4>;
kono
parents: 67
diff changeset
2738 <bb 3>:
kono
parents: 67
diff changeset
2739 <bb 4>:
kono
parents: 67
diff changeset
2740 a = PHI <a, CST>
kono
parents: 67
diff changeset
2741 tmp = (int) a;
kono
parents: 67
diff changeset
2742
kono
parents: 67
diff changeset
2743 Adjacent Load Hoisting
kono
parents: 67
diff changeset
2744 ----------------------
kono
parents: 67
diff changeset
2745
kono
parents: 67
diff changeset
2746 This transformation replaces
kono
parents: 67
diff changeset
2747
kono
parents: 67
diff changeset
2748 bb0:
kono
parents: 67
diff changeset
2749 if (...) goto bb2; else goto bb1;
kono
parents: 67
diff changeset
2750 bb1:
kono
parents: 67
diff changeset
2751 x1 = (<expr>).field1;
kono
parents: 67
diff changeset
2752 goto bb3;
kono
parents: 67
diff changeset
2753 bb2:
kono
parents: 67
diff changeset
2754 x2 = (<expr>).field2;
kono
parents: 67
diff changeset
2755 bb3:
kono
parents: 67
diff changeset
2756 # x = PHI <x1, x2>;
kono
parents: 67
diff changeset
2757
kono
parents: 67
diff changeset
2758 with
kono
parents: 67
diff changeset
2759
kono
parents: 67
diff changeset
2760 bb0:
kono
parents: 67
diff changeset
2761 x1 = (<expr>).field1;
kono
parents: 67
diff changeset
2762 x2 = (<expr>).field2;
kono
parents: 67
diff changeset
2763 if (...) goto bb2; else goto bb1;
kono
parents: 67
diff changeset
2764 bb1:
kono
parents: 67
diff changeset
2765 goto bb3;
kono
parents: 67
diff changeset
2766 bb2:
kono
parents: 67
diff changeset
2767 bb3:
kono
parents: 67
diff changeset
2768 # x = PHI <x1, x2>;
kono
parents: 67
diff changeset
2769
kono
parents: 67
diff changeset
2770 The purpose of this transformation is to enable generation of conditional
kono
parents: 67
diff changeset
2771 move instructions such as Intel CMOVE or PowerPC ISEL. Because one of
kono
parents: 67
diff changeset
2772 the loads is speculative, the transformation is restricted to very
kono
parents: 67
diff changeset
2773 specific cases to avoid introducing a page fault. We are looking for
kono
parents: 67
diff changeset
2774 the common idiom:
kono
parents: 67
diff changeset
2775
kono
parents: 67
diff changeset
2776 if (...)
kono
parents: 67
diff changeset
2777 x = y->left;
kono
parents: 67
diff changeset
2778 else
kono
parents: 67
diff changeset
2779 x = y->right;
kono
parents: 67
diff changeset
2780
kono
parents: 67
diff changeset
2781 where left and right are typically adjacent pointers in a tree structure. */
kono
parents: 67
diff changeset
2782
kono
parents: 67
diff changeset
2783 namespace {
kono
parents: 67
diff changeset
2784
kono
parents: 67
diff changeset
2785 const pass_data pass_data_phiopt =
kono
parents: 67
diff changeset
2786 {
kono
parents: 67
diff changeset
2787 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
2788 "phiopt", /* name */
kono
parents: 67
diff changeset
2789 OPTGROUP_NONE, /* optinfo_flags */
kono
parents: 67
diff changeset
2790 TV_TREE_PHIOPT, /* tv_id */
kono
parents: 67
diff changeset
2791 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
2792 0, /* properties_provided */
kono
parents: 67
diff changeset
2793 0, /* properties_destroyed */
kono
parents: 67
diff changeset
2794 0, /* todo_flags_start */
kono
parents: 67
diff changeset
2795 0, /* todo_flags_finish */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2796 };
111
kono
parents: 67
diff changeset
2797
kono
parents: 67
diff changeset
2798 class pass_phiopt : public gimple_opt_pass
kono
parents: 67
diff changeset
2799 {
kono
parents: 67
diff changeset
2800 public:
kono
parents: 67
diff changeset
2801 pass_phiopt (gcc::context *ctxt)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2802 : gimple_opt_pass (pass_data_phiopt, ctxt), early_p (false)
111
kono
parents: 67
diff changeset
2803 {}
kono
parents: 67
diff changeset
2804
kono
parents: 67
diff changeset
2805 /* opt_pass methods: */
kono
parents: 67
diff changeset
2806 opt_pass * clone () { return new pass_phiopt (m_ctxt); }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2807 void set_pass_param (unsigned n, bool param)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2808 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2809 gcc_assert (n == 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2810 early_p = param;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2811 }
111
kono
parents: 67
diff changeset
2812 virtual bool gate (function *) { return flag_ssa_phiopt; }
kono
parents: 67
diff changeset
2813 virtual unsigned int execute (function *)
kono
parents: 67
diff changeset
2814 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2815 return tree_ssa_phiopt_worker (false,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2816 !early_p ? gate_hoist_loads () : false,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2817 early_p);
111
kono
parents: 67
diff changeset
2818 }
kono
parents: 67
diff changeset
2819
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2820 private:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2821 bool early_p;
111
kono
parents: 67
diff changeset
2822 }; // class pass_phiopt
kono
parents: 67
diff changeset
2823
kono
parents: 67
diff changeset
2824 } // anon namespace
kono
parents: 67
diff changeset
2825
kono
parents: 67
diff changeset
2826 gimple_opt_pass *
kono
parents: 67
diff changeset
2827 make_pass_phiopt (gcc::context *ctxt)
kono
parents: 67
diff changeset
2828 {
kono
parents: 67
diff changeset
2829 return new pass_phiopt (ctxt);
kono
parents: 67
diff changeset
2830 }
kono
parents: 67
diff changeset
2831
kono
parents: 67
diff changeset
2832 namespace {
kono
parents: 67
diff changeset
2833
kono
parents: 67
diff changeset
2834 const pass_data pass_data_cselim =
kono
parents: 67
diff changeset
2835 {
kono
parents: 67
diff changeset
2836 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
2837 "cselim", /* name */
kono
parents: 67
diff changeset
2838 OPTGROUP_NONE, /* optinfo_flags */
kono
parents: 67
diff changeset
2839 TV_TREE_PHIOPT, /* tv_id */
kono
parents: 67
diff changeset
2840 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
2841 0, /* properties_provided */
kono
parents: 67
diff changeset
2842 0, /* properties_destroyed */
kono
parents: 67
diff changeset
2843 0, /* todo_flags_start */
kono
parents: 67
diff changeset
2844 0, /* todo_flags_finish */
kono
parents: 67
diff changeset
2845 };
kono
parents: 67
diff changeset
2846
kono
parents: 67
diff changeset
2847 class pass_cselim : public gimple_opt_pass
kono
parents: 67
diff changeset
2848 {
kono
parents: 67
diff changeset
2849 public:
kono
parents: 67
diff changeset
2850 pass_cselim (gcc::context *ctxt)
kono
parents: 67
diff changeset
2851 : gimple_opt_pass (pass_data_cselim, ctxt)
kono
parents: 67
diff changeset
2852 {}
kono
parents: 67
diff changeset
2853
kono
parents: 67
diff changeset
2854 /* opt_pass methods: */
kono
parents: 67
diff changeset
2855 virtual bool gate (function *) { return flag_tree_cselim; }
kono
parents: 67
diff changeset
2856 virtual unsigned int execute (function *) { return tree_ssa_cs_elim (); }
kono
parents: 67
diff changeset
2857
kono
parents: 67
diff changeset
2858 }; // class pass_cselim
kono
parents: 67
diff changeset
2859
kono
parents: 67
diff changeset
2860 } // anon namespace
kono
parents: 67
diff changeset
2861
kono
parents: 67
diff changeset
2862 gimple_opt_pass *
kono
parents: 67
diff changeset
2863 make_pass_cselim (gcc::context *ctxt)
kono
parents: 67
diff changeset
2864 {
kono
parents: 67
diff changeset
2865 return new pass_cselim (ctxt);
kono
parents: 67
diff changeset
2866 }