1 /* Support routines for Value Range Propagation (VRP). 2 Copyright (C) 2005-2018 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GCC is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "backend.h" 24 #include "tree.h" 25 #include "gimple.h" 26 #include "tree-pass.h" 27 #include "ssa.h" 28 #include "gimple-pretty-print.h" 29 #include "cfganal.h" 30 #include "gimple-fold.h" 31 #include "tree-eh.h" 32 #include "gimple-iterator.h" 33 #include "tree-cfg.h" 34 #include "tree-ssa-loop-manip.h" 35 #include "tree-ssa-loop.h" 36 #include "cfgloop.h" 37 #include "tree-scalar-evolution.h" 38 #include "tree-ssa-propagate.h" 39 #include "alloc-pool.h" 40 #include "domwalk.h" 41 #include "tree-cfgcleanup.h" 42 #include "vr-values.h" 43 #include "gimple-ssa-evrp-analyze.h" 44 45 class evrp_folder : public substitute_and_fold_engine 46 { 47 public: 48 tree get_value (tree) FINAL OVERRIDE; 49 evrp_folder (class vr_values *vr_values_) : vr_values (vr_values_) { } 50 class vr_values *vr_values; 51 52 private: 53 DISABLE_COPY_AND_ASSIGN (evrp_folder); 54 }; 55 56 tree 57 evrp_folder::get_value (tree op) 58 { 59 return vr_values->op_with_constant_singleton_value_range (op); 60 } 61 62 /* evrp_dom_walker visits the basic blocks in the dominance order and set 63 the Value Ranges (VR) for SSA_NAMEs in the scope. Use this VR to 64 discover more VRs. */ 65 66 class evrp_dom_walker : public dom_walker 67 { 68 public: 69 evrp_dom_walker () 70 : dom_walker (CDI_DOMINATORS), 71 evrp_folder (evrp_range_analyzer.get_vr_values ()) 72 { 73 need_eh_cleanup = BITMAP_ALLOC (NULL); 74 } 75 ~evrp_dom_walker () 76 { 77 BITMAP_FREE (need_eh_cleanup); 78 } 79 virtual edge before_dom_children (basic_block); 80 virtual void after_dom_children (basic_block); 81 void cleanup (void); 82 83 private: 84 DISABLE_COPY_AND_ASSIGN (evrp_dom_walker); 85 bitmap need_eh_cleanup; 86 auto_vec<gimple *> stmts_to_fixup; 87 auto_vec<gimple *> stmts_to_remove; 88 89 class evrp_range_analyzer evrp_range_analyzer; 90 class evrp_folder evrp_folder; 91 }; 92 93 edge 94 evrp_dom_walker::before_dom_children (basic_block bb) 95 { 96 if (dump_file && (dump_flags & TDF_DETAILS)) 97 fprintf (dump_file, "Visiting BB%d\n", bb->index); 98 99 evrp_range_analyzer.enter (bb); 100 101 for (gphi_iterator gpi = gsi_start_phis (bb); 102 !gsi_end_p (gpi); gsi_next (&gpi)) 103 { 104 gphi *phi = gpi.phi (); 105 tree lhs = PHI_RESULT (phi); 106 if (virtual_operand_p (lhs)) 107 continue; 108 109 value_range *vr = evrp_range_analyzer.get_value_range (lhs); 110 /* Mark PHIs whose lhs we fully propagate for removal. */ 111 tree val = value_range_constant_singleton (vr); 112 if (val && may_propagate_copy (lhs, val)) 113 { 114 stmts_to_remove.safe_push (phi); 115 continue; 116 } 117 } 118 119 edge taken_edge = NULL; 120 121 /* Visit all other stmts and discover any new VRs possible. */ 122 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); 123 !gsi_end_p (gsi); gsi_next (&gsi)) 124 { 125 gimple *stmt = gsi_stmt (gsi); 126 tree output = NULL_TREE; 127 gimple *old_stmt = stmt; 128 bool was_noreturn = (is_gimple_call (stmt) 129 && gimple_call_noreturn_p (stmt)); 130 131 if (dump_file && (dump_flags & TDF_DETAILS)) 132 { 133 fprintf (dump_file, "Visiting stmt "); 134 print_gimple_stmt (dump_file, stmt, 0); 135 } 136 137 evrp_range_analyzer.record_ranges_from_stmt (stmt, false); 138 139 if (gcond *cond = dyn_cast <gcond *> (stmt)) 140 { 141 evrp_range_analyzer.vrp_visit_cond_stmt (cond, &taken_edge); 142 if (taken_edge) 143 { 144 if (taken_edge->flags & EDGE_TRUE_VALUE) 145 gimple_cond_make_true (cond); 146 else if (taken_edge->flags & EDGE_FALSE_VALUE) 147 gimple_cond_make_false (cond); 148 else 149 gcc_unreachable (); 150 update_stmt (stmt); 151 } 152 } 153 else if (stmt_interesting_for_vrp (stmt)) 154 { 155 output = get_output_for_vrp (stmt); 156 if (output) 157 { 158 tree val; 159 value_range *vr = evrp_range_analyzer.get_value_range (output); 160 161 /* Mark stmts whose output we fully propagate for removal. */ 162 if ((vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE) 163 && (val = value_range_constant_singleton (vr)) 164 && may_propagate_copy (output, val) 165 && !stmt_could_throw_p (stmt) 166 && !gimple_has_side_effects (stmt)) 167 { 168 stmts_to_remove.safe_push (stmt); 169 continue; 170 } 171 } 172 } 173 174 /* Try folding stmts with the VR discovered. */ 175 bool did_replace = evrp_folder.replace_uses_in (stmt); 176 if (fold_stmt (&gsi, follow_single_use_edges) 177 || did_replace) 178 { 179 stmt = gsi_stmt (gsi); 180 update_stmt (stmt); 181 did_replace = true; 182 } 183 184 if (did_replace) 185 { 186 /* If we cleaned up EH information from the statement, 187 remove EH edges. */ 188 if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt)) 189 bitmap_set_bit (need_eh_cleanup, bb->index); 190 191 /* If we turned a not noreturn call into a noreturn one 192 schedule it for fixup. */ 193 if (!was_noreturn 194 && is_gimple_call (stmt) 195 && gimple_call_noreturn_p (stmt)) 196 stmts_to_fixup.safe_push (stmt); 197 198 if (gimple_assign_single_p (stmt)) 199 { 200 tree rhs = gimple_assign_rhs1 (stmt); 201 if (TREE_CODE (rhs) == ADDR_EXPR) 202 recompute_tree_invariant_for_addr_expr (rhs); 203 } 204 } 205 } 206 207 /* Visit BB successor PHI nodes and replace PHI args. */ 208 edge e; 209 edge_iterator ei; 210 FOR_EACH_EDGE (e, ei, bb->succs) 211 { 212 for (gphi_iterator gpi = gsi_start_phis (e->dest); 213 !gsi_end_p (gpi); gsi_next (&gpi)) 214 { 215 gphi *phi = gpi.phi (); 216 use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e); 217 tree arg = USE_FROM_PTR (use_p); 218 if (TREE_CODE (arg) != SSA_NAME 219 || virtual_operand_p (arg)) 220 continue; 221 value_range *vr = evrp_range_analyzer.get_value_range (arg); 222 tree val = value_range_constant_singleton (vr); 223 if (val && may_propagate_copy (arg, val)) 224 propagate_value (use_p, val); 225 } 226 } 227 228 return taken_edge; 229 } 230 231 void 232 evrp_dom_walker::after_dom_children (basic_block bb) 233 { 234 evrp_range_analyzer.leave (bb); 235 } 236 237 /* Perform any cleanups after the main phase of EVRP has completed. */ 238 239 void 240 evrp_dom_walker::cleanup (void) 241 { 242 if (dump_file) 243 { 244 fprintf (dump_file, "\nValue ranges after Early VRP:\n\n"); 245 evrp_range_analyzer.dump_all_value_ranges (dump_file); 246 fprintf (dump_file, "\n"); 247 } 248 249 /* Remove stmts in reverse order to make debug stmt creation possible. */ 250 while (! stmts_to_remove.is_empty ()) 251 { 252 gimple *stmt = stmts_to_remove.pop (); 253 if (dump_file && dump_flags & TDF_DETAILS) 254 { 255 fprintf (dump_file, "Removing dead stmt "); 256 print_gimple_stmt (dump_file, stmt, 0); 257 fprintf (dump_file, "\n"); 258 } 259 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 260 if (gimple_code (stmt) == GIMPLE_PHI) 261 remove_phi_node (&gsi, true); 262 else 263 { 264 unlink_stmt_vdef (stmt); 265 gsi_remove (&gsi, true); 266 release_defs (stmt); 267 } 268 } 269 270 if (!bitmap_empty_p (need_eh_cleanup)) 271 gimple_purge_all_dead_eh_edges (need_eh_cleanup); 272 273 /* Fixup stmts that became noreturn calls. This may require splitting 274 blocks and thus isn't possible during the dominator walk. Do this 275 in reverse order so we don't inadvertedly remove a stmt we want to 276 fixup by visiting a dominating now noreturn call first. */ 277 while (!stmts_to_fixup.is_empty ()) 278 { 279 gimple *stmt = stmts_to_fixup.pop (); 280 fixup_noreturn_call (stmt); 281 } 282 } 283 284 /* Main entry point for the early vrp pass which is a simplified non-iterative 285 version of vrp where basic blocks are visited in dominance order. Value 286 ranges discovered in early vrp will also be used by ipa-vrp. */ 287 288 static unsigned int 289 execute_early_vrp () 290 { 291 /* Ideally this setup code would move into the ctor for the dominator 292 walk. However, this setup can change the number of blocks which 293 invalidates the internal arrays that are set up by the dominator 294 walker. */ 295 loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); 296 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); 297 scev_initialize (); 298 calculate_dominance_info (CDI_DOMINATORS); 299 300 /* Walk stmts in dominance order and propagate VRP. */ 301 evrp_dom_walker walker; 302 walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); 303 walker.cleanup (); 304 305 scev_finalize (); 306 loop_optimizer_finalize (); 307 return 0; 308 } 309 310 namespace { 311 312 const pass_data pass_data_early_vrp = 313 { 314 GIMPLE_PASS, /* type */ 315 "evrp", /* name */ 316 OPTGROUP_NONE, /* optinfo_flags */ 317 TV_TREE_EARLY_VRP, /* tv_id */ 318 PROP_ssa, /* properties_required */ 319 0, /* properties_provided */ 320 0, /* properties_destroyed */ 321 0, /* todo_flags_start */ 322 ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ), 323 }; 324 325 class pass_early_vrp : public gimple_opt_pass 326 { 327 public: 328 pass_early_vrp (gcc::context *ctxt) 329 : gimple_opt_pass (pass_data_early_vrp, ctxt) 330 {} 331 332 /* opt_pass methods: */ 333 opt_pass * clone () { return new pass_early_vrp (m_ctxt); } 334 virtual bool gate (function *) 335 { 336 return flag_tree_vrp != 0; 337 } 338 virtual unsigned int execute (function *) 339 { return execute_early_vrp (); } 340 341 }; // class pass_vrp 342 } // anon namespace 343 344 gimple_opt_pass * 345 make_pass_early_vrp (gcc::context *ctxt) 346 { 347 return new pass_early_vrp (ctxt); 348 } 349 350