tree-ssa-loop.c 17.9 KB
Newer Older
1
/* Loop optimizations over tree-ssa.
2
   Copyright (C) 2003-2016 Free Software Foundation, Inc.
H.J. Lu committed
3

4
This file is part of GCC.
H.J. Lu committed
5

6 7
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; either version 3, or (at your option) any
9
later version.
H.J. Lu committed
10

11 12 13 14
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
H.J. Lu committed
15

16
You should have received a copy of the GNU General Public License
17 18
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
19 20 21 22

#include "config.h"
#include "system.h"
#include "coretypes.h"
23
#include "backend.h"
24
#include "tree.h"
25
#include "gimple.h"
26 27
#include "tree-pass.h"
#include "tm_p.h"
28
#include "fold-const.h"
29
#include "gimple-iterator.h"
30 31 32
#include "tree-ssa-loop-ivopts.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
33
#include "tree-ssa-loop.h"
34 35
#include "cfgloop.h"
#include "tree-inline.h"
36
#include "tree-scalar-evolution.h"
37
#include "tree-vectorizer.h"
Tom de Vries committed
38
#include "omp-low.h"
Tom de Vries committed
39
#include "diagnostic-core.h"
40

41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
/* A pass making sure loops are fixed up.  */

namespace {

const pass_data pass_data_fix_loops =
{
  GIMPLE_PASS, /* type */
  "fix_loops", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_TREE_LOOP, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_fix_loops : public gimple_opt_pass
{
public:
  pass_fix_loops (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_fix_loops, ctxt)
  {}

  /* opt_pass methods: */
  virtual bool gate (function *) { return flag_tree_loop_optimize; }

  virtual unsigned int execute (function *fn);
}; // class pass_fix_loops

unsigned int
pass_fix_loops::execute (function *)
{
  if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
    {
      calculate_dominance_info (CDI_DOMINATORS);
      fix_loop_structure (NULL);
    }
  return 0;
}

} // anon namespace

gimple_opt_pass *
make_pass_fix_loops (gcc::context *ctxt)
{
  return new pass_fix_loops (ctxt);
}


92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
/* Gate for loop pass group.  The group is controlled by -ftree-loop-optimize
   but we also avoid running it when the IL doesn't contain any loop.  */

static bool
gate_loop (function *fn)
{
  if (!flag_tree_loop_optimize)
    return false;

  /* For -fdump-passes which runs before loop discovery print the
     state of -ftree-loop-optimize.  */
  if (!loops_for_fn (fn))
    return true;

  return number_of_loops (fn) > 1;
}

109 110
/* The loop superpass.  */

111 112 113 114 115 116 117 118 119 120 121 122
namespace {

const pass_data pass_data_tree_loop =
{
  GIMPLE_PASS, /* type */
  "loop", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_TREE_LOOP, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
123
  0, /* todo_flags_finish */
124 125
};

126 127 128
class pass_tree_loop : public gimple_opt_pass
{
public:
129 130
  pass_tree_loop (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_tree_loop, ctxt)
131 132 133
  {}

  /* opt_pass methods: */
134
  virtual bool gate (function *fn) { return gate_loop (fn); }
135 136 137 138 139 140 141 142 143 144 145

}; // class pass_tree_loop

} // anon namespace

gimple_opt_pass *
make_pass_tree_loop (gcc::context *ctxt)
{
  return new pass_tree_loop (ctxt);
}

Tom de Vries committed
146 147 148 149 150
/* Gate for oacc kernels pass group.  */

static bool
gate_oacc_kernels (function *fn)
{
151
  if (!flag_openacc)
Tom de Vries committed
152 153 154 155 156
    return false;

  tree oacc_function_attr = get_oacc_fn_attrib (fn->decl);
  if (oacc_function_attr == NULL_TREE)
    return false;
157
  if (!oacc_fn_attrib_kernels_p (oacc_function_attr))
Tom de Vries committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
    return false;

  struct loop *loop;
  FOR_EACH_LOOP (loop, 0)
    if (loop->in_oacc_kernels_region)
      return true;

  return false;
}

/* The oacc kernels superpass.  */

namespace {

const pass_data pass_data_oacc_kernels =
{
  GIMPLE_PASS, /* type */
  "oacc_kernels", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_TREE_LOOP, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_oacc_kernels : public gimple_opt_pass
{
public:
  pass_oacc_kernels (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_oacc_kernels, ctxt)
  {}

  /* opt_pass methods: */
  virtual bool gate (function *fn) { return gate_oacc_kernels (fn); }

}; // class pass_oacc_kernels

} // anon namespace

gimple_opt_pass *
make_pass_oacc_kernels (gcc::context *ctxt)
{
  return new pass_oacc_kernels (ctxt);
}

Tom de Vries committed
205 206
/* The ipa oacc superpass.  */

Tom de Vries committed
207 208
namespace {

Tom de Vries committed
209
const pass_data pass_data_ipa_oacc =
Tom de Vries committed
210
{
Tom de Vries committed
211 212
  SIMPLE_IPA_PASS, /* type */
  "ipa_oacc", /* name */
Tom de Vries committed
213 214 215 216 217 218 219 220 221
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_TREE_LOOP, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

Tom de Vries committed
222
class pass_ipa_oacc : public simple_ipa_opt_pass
Tom de Vries committed
223 224
{
public:
Tom de Vries committed
225 226
  pass_ipa_oacc (gcc::context *ctxt)
    : simple_ipa_opt_pass (pass_data_ipa_oacc, ctxt)
Tom de Vries committed
227 228 229
  {}

  /* opt_pass methods: */
Tom de Vries committed
230 231 232 233
  virtual bool gate (function *)
  {
    return (optimize
	    && flag_openacc
234 235
	    /* Don't bother doing anything if the program has errors.  */
	    && !seen_error ());
Tom de Vries committed
236
  }
Tom de Vries committed
237

Tom de Vries committed
238
}; // class pass_ipa_oacc
Tom de Vries committed
239 240 241

} // anon namespace

Tom de Vries committed
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
simple_ipa_opt_pass *
make_pass_ipa_oacc (gcc::context *ctxt)
{
  return new pass_ipa_oacc (ctxt);
}

/* The ipa oacc kernels pass.  */

namespace {

const pass_data pass_data_ipa_oacc_kernels =
{
  SIMPLE_IPA_PASS, /* type */
  "ipa_oacc_kernels", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_TREE_LOOP, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_ipa_oacc_kernels : public simple_ipa_opt_pass
{
public:
  pass_ipa_oacc_kernels (gcc::context *ctxt)
    : simple_ipa_opt_pass (pass_data_ipa_oacc_kernels, ctxt)
  {}

}; // class pass_ipa_oacc_kernels

} // anon namespace

simple_ipa_opt_pass *
make_pass_ipa_oacc_kernels (gcc::context *ctxt)
Tom de Vries committed
278
{
Tom de Vries committed
279
  return new pass_ipa_oacc_kernels (ctxt);
Tom de Vries committed
280 281
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
/* The no-loop superpass.  */

namespace {

const pass_data pass_data_tree_no_loop =
{
  GIMPLE_PASS, /* type */
  "no_loop", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_TREE_NOLOOP, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_tree_no_loop : public gimple_opt_pass
{
public:
  pass_tree_no_loop (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_tree_no_loop, ctxt)
  {}

  /* opt_pass methods: */
  virtual bool gate (function *fn) { return !gate_loop (fn); }

}; // class pass_tree_no_loop

} // anon namespace

gimple_opt_pass *
make_pass_tree_no_loop (gcc::context *ctxt)
{
  return new pass_tree_no_loop (ctxt);
}


320 321
/* Loop optimizer initialization.  */

322 323 324 325 326 327 328 329 330 331 332 333 334
namespace {

const pass_data pass_data_tree_loop_init =
{
  GIMPLE_PASS, /* type */
  "loopinit", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_NONE, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
335 336
};

337 338 339
class pass_tree_loop_init : public gimple_opt_pass
{
public:
340 341
  pass_tree_loop_init (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_tree_loop_init, ctxt)
342 343 344
  {}

  /* opt_pass methods: */
345
  virtual unsigned int execute (function *);
346 347 348

}; // class pass_tree_loop_init

349
unsigned int
350
pass_tree_loop_init::execute (function *fun ATTRIBUTE_UNUSED)
351
{
352 353 354 355 356 357
  /* When processing a loop in the loop pipeline, we should be able to assert
     that:
       (loops_state_satisfies_p (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS
					      | LOOP_CLOSED_SSA)
	&& scev_initialized_p ())
  */
358 359 360 361 362 363 364 365
  loop_optimizer_init (LOOPS_NORMAL
		       | LOOPS_HAVE_RECORDED_EXITS);
  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
  scev_initialize ();

  return 0;
}

366 367 368 369 370 371 372 373
} // anon namespace

gimple_opt_pass *
make_pass_tree_loop_init (gcc::context *ctxt)
{
  return new pass_tree_loop_init (ctxt);
}

374 375
/* Loop autovectorization.  */

376 377 378 379 380 381 382 383 384 385 386 387 388
namespace {

const pass_data pass_data_vectorize =
{
  GIMPLE_PASS, /* type */
  "vect", /* name */
  OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
  TV_TREE_VECTORIZATION, /* tv_id */
  ( PROP_cfg | PROP_ssa ), /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
389 390
};

391 392 393
class pass_vectorize : public gimple_opt_pass
{
public:
394 395
  pass_vectorize (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_vectorize, ctxt)
396 397 398
  {}

  /* opt_pass methods: */
399 400 401 402 403
  virtual bool gate (function *fun)
    {
      return flag_tree_loop_vectorize || fun->has_force_vectorize_loops;
    }

404
  virtual unsigned int execute (function *);
405 406 407

}; // class pass_vectorize

408 409 410 411 412 413 414 415 416
unsigned int
pass_vectorize::execute (function *fun)
{
  if (number_of_loops (fun) <= 1)
    return 0;

  return vectorize_loops ();
}

417 418 419 420 421 422 423 424
} // anon namespace

gimple_opt_pass *
make_pass_vectorize (gcc::context *ctxt)
{
  return new pass_vectorize (ctxt);
}

425 426
/* Propagation of constants using scev.  */

427 428 429 430 431 432 433 434 435 436 437 438 439 440
namespace {

const pass_data pass_data_scev_cprop =
{
  GIMPLE_PASS, /* type */
  "sccp", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_SCEV_CONST, /* tv_id */
  ( PROP_cfg | PROP_ssa ), /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  ( TODO_cleanup_cfg
    | TODO_update_ssa_only_virtuals ), /* todo_flags_finish */
441 442
};

443 444 445
class pass_scev_cprop : public gimple_opt_pass
{
public:
446 447
  pass_scev_cprop (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_scev_cprop, ctxt)
448 449 450
  {}

  /* opt_pass methods: */
451
  virtual bool gate (function *) { return flag_tree_scev_cprop; }
452
  virtual unsigned int execute (function *) { return scev_const_prop (); }
453 454 455 456 457 458 459 460 461 462 463

}; // class pass_scev_cprop

} // anon namespace

gimple_opt_pass *
make_pass_scev_cprop (gcc::context *ctxt)
{
  return new pass_scev_cprop (ctxt);
}

464 465
/* Record bounds on numbers of iterations of loops.  */

466 467 468 469 470 471 472 473 474 475 476 477 478
namespace {

const pass_data pass_data_record_bounds =
{
  GIMPLE_PASS, /* type */
  "*record_bounds", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_TREE_LOOP_BOUNDS, /* tv_id */
  ( PROP_cfg | PROP_ssa ), /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
479 480
};

481 482 483
class pass_record_bounds : public gimple_opt_pass
{
public:
484 485
  pass_record_bounds (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_record_bounds, ctxt)
486 487 488
  {}

  /* opt_pass methods: */
489
  virtual unsigned int execute (function *);
490 491 492

}; // class pass_record_bounds

493 494 495 496 497 498 499 500 501 502 503
unsigned int
pass_record_bounds::execute (function *fun)
{
  if (number_of_loops (fun) <= 1)
    return 0;

  estimate_numbers_of_iterations ();
  scev_reset ();
  return 0;
}

504 505 506 507 508 509 510 511
} // anon namespace

gimple_opt_pass *
make_pass_record_bounds (gcc::context *ctxt)
{
  return new pass_record_bounds (ctxt);
}

512 513
/* Induction variable optimizations.  */

514 515 516 517 518 519 520 521 522 523 524 525 526
namespace {

const pass_data pass_data_iv_optimize =
{
  GIMPLE_PASS, /* type */
  "ivopts", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_TREE_LOOP_IVOPTS, /* tv_id */
  ( PROP_cfg | PROP_ssa ), /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  TODO_update_ssa, /* todo_flags_finish */
527 528
};

529 530 531
class pass_iv_optimize : public gimple_opt_pass
{
public:
532 533
  pass_iv_optimize (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_iv_optimize, ctxt)
534 535 536
  {}

  /* opt_pass methods: */
537
  virtual bool gate (function *) { return flag_ivopts != 0; }
538
  virtual unsigned int execute (function *);
539 540 541

}; // class pass_iv_optimize

542 543 544 545 546 547 548 549 550 551
unsigned int
pass_iv_optimize::execute (function *fun)
{
  if (number_of_loops (fun) <= 1)
    return 0;

  tree_ssa_iv_optimize ();
  return 0;
}

552 553 554 555 556 557 558 559
} // anon namespace

gimple_opt_pass *
make_pass_iv_optimize (gcc::context *ctxt)
{
  return new pass_iv_optimize (ctxt);
}

560 561
/* Loop optimizer finalization.  */

562
static unsigned int
563 564
tree_ssa_loop_done (void)
{
565
  free_numbers_of_iterations_estimates (cfun);
566
  scev_finalize ();
567
  loop_optimizer_finalize ();
568
  return 0;
569
}
H.J. Lu committed
570

571 572 573 574 575 576 577 578 579 580 581 582
namespace {

const pass_data pass_data_tree_loop_done =
{
  GIMPLE_PASS, /* type */
  "loopdone", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_NONE, /* tv_id */
  PROP_cfg, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
583
  TODO_cleanup_cfg, /* todo_flags_finish */
584
};
585 586 587 588

class pass_tree_loop_done : public gimple_opt_pass
{
public:
589 590
  pass_tree_loop_done (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_tree_loop_done, ctxt)
591 592 593
  {}

  /* opt_pass methods: */
594
  virtual unsigned int execute (function *) { return tree_ssa_loop_done (); }
595 596 597 598 599 600 601 602 603 604

}; // class pass_tree_loop_done

} // anon namespace

gimple_opt_pass *
make_pass_tree_loop_done (gcc::context *ctxt)
{
  return new pass_tree_loop_done (ctxt);
}
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771

/* Calls CBCK for each index in memory reference ADDR_P.  There are two
   kinds situations handled; in each of these cases, the memory reference
   and DATA are passed to the callback:

   Access to an array: ARRAY_{RANGE_}REF (base, index).  In this case we also
   pass the pointer to the index to the callback.

   Pointer dereference: INDIRECT_REF (addr).  In this case we also pass the
   pointer to addr to the callback.

   If the callback returns false, the whole search stops and false is returned.
   Otherwise the function returns true after traversing through the whole
   reference *ADDR_P.  */

bool
for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
{
  tree *nxt, *idx;

  for (; ; addr_p = nxt)
    {
      switch (TREE_CODE (*addr_p))
	{
	case SSA_NAME:
	  return cbck (*addr_p, addr_p, data);

	case MEM_REF:
	  nxt = &TREE_OPERAND (*addr_p, 0);
	  return cbck (*addr_p, nxt, data);

	case BIT_FIELD_REF:
	case VIEW_CONVERT_EXPR:
	case REALPART_EXPR:
	case IMAGPART_EXPR:
	  nxt = &TREE_OPERAND (*addr_p, 0);
	  break;

	case COMPONENT_REF:
	  /* If the component has varying offset, it behaves like index
	     as well.  */
	  idx = &TREE_OPERAND (*addr_p, 2);
	  if (*idx
	      && !cbck (*addr_p, idx, data))
	    return false;

	  nxt = &TREE_OPERAND (*addr_p, 0);
	  break;

	case ARRAY_REF:
	case ARRAY_RANGE_REF:
	  nxt = &TREE_OPERAND (*addr_p, 0);
	  if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
	    return false;
	  break;

	case VAR_DECL:
	case PARM_DECL:
	case CONST_DECL:
	case STRING_CST:
	case RESULT_DECL:
	case VECTOR_CST:
	case COMPLEX_CST:
	case INTEGER_CST:
	case REAL_CST:
	case FIXED_CST:
	case CONSTRUCTOR:
	  return true;

	case ADDR_EXPR:
	  gcc_assert (is_gimple_min_invariant (*addr_p));
	  return true;

	case TARGET_MEM_REF:
	  idx = &TMR_BASE (*addr_p);
	  if (*idx
	      && !cbck (*addr_p, idx, data))
	    return false;
	  idx = &TMR_INDEX (*addr_p);
	  if (*idx
	      && !cbck (*addr_p, idx, data))
	    return false;
	  idx = &TMR_INDEX2 (*addr_p);
	  if (*idx
	      && !cbck (*addr_p, idx, data))
	    return false;
	  return true;

	default:
    	  gcc_unreachable ();
	}
    }
}


/* The name and the length of the currently generated variable
   for lsm.  */
#define MAX_LSM_NAME_LENGTH 40
static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
static int lsm_tmp_name_length;

/* Adds S to lsm_tmp_name.  */

static void
lsm_tmp_name_add (const char *s)
{
  int l = strlen (s) + lsm_tmp_name_length;
  if (l > MAX_LSM_NAME_LENGTH)
    return;

  strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
  lsm_tmp_name_length = l;
}

/* Stores the name for temporary variable that replaces REF to
   lsm_tmp_name.  */

static void
gen_lsm_tmp_name (tree ref)
{
  const char *name;

  switch (TREE_CODE (ref))
    {
    case MEM_REF:
    case TARGET_MEM_REF:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      lsm_tmp_name_add ("_");
      break;

    case ADDR_EXPR:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      break;

    case BIT_FIELD_REF:
    case VIEW_CONVERT_EXPR:
    case ARRAY_RANGE_REF:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      break;

    case REALPART_EXPR:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      lsm_tmp_name_add ("_RE");
      break;

    case IMAGPART_EXPR:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      lsm_tmp_name_add ("_IM");
      break;

    case COMPONENT_REF:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      lsm_tmp_name_add ("_");
      name = get_name (TREE_OPERAND (ref, 1));
      if (!name)
	name = "F";
      lsm_tmp_name_add (name);
      break;

    case ARRAY_REF:
      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
      lsm_tmp_name_add ("_I");
      break;

    case SSA_NAME:
    case VAR_DECL:
    case PARM_DECL:
772 773
    case FUNCTION_DECL:
    case LABEL_DECL:
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
      name = get_name (ref);
      if (!name)
	name = "D";
      lsm_tmp_name_add (name);
      break;

    case STRING_CST:
      lsm_tmp_name_add ("S");
      break;

    case RESULT_DECL:
      lsm_tmp_name_add ("R");
      break;

    case INTEGER_CST:
789
    default:
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
      /* Nothing.  */
      break;
    }
}

/* Determines name for temporary variable that replaces REF.
   The name is accumulated into the lsm_tmp_name variable.
   N is added to the name of the temporary.  */

char *
get_lsm_tmp_name (tree ref, unsigned n, const char *suffix)
{
  char ns[2];

  lsm_tmp_name_length = 0;
  gen_lsm_tmp_name (ref);
  lsm_tmp_name_add ("_lsm");
  if (n < 10)
    {
      ns[0] = '0' + n;
      ns[1] = 0;
      lsm_tmp_name_add (ns);
    }
  return lsm_tmp_name;
  if (suffix != NULL)
    lsm_tmp_name_add (suffix);
}

/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS.  */

unsigned
tree_num_loop_insns (struct loop *loop, eni_weights *weights)
{
  basic_block *body = get_loop_body (loop);
  gimple_stmt_iterator gsi;
  unsigned size = 0, i;

  for (i = 0; i < loop->num_nodes; i++)
    for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
      size += estimate_num_insns (gsi_stmt (gsi), weights);
  free (body);

  return size;
}