OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [tree-ssa-forwprop.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Forward propagation of expressions for single use variables.
2
   Copyright (C) 2004, 2005, 2007 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 "tm.h"
24
#include "ggc.h"
25
#include "tree.h"
26
#include "rtl.h"
27
#include "tm_p.h"
28
#include "basic-block.h"
29
#include "timevar.h"
30
#include "diagnostic.h"
31
#include "tree-flow.h"
32
#include "tree-pass.h"
33
#include "tree-dump.h"
34
#include "langhooks.h"
35
 
36
/* This pass propagates the RHS of assignment statements into use
37
   sites of the LHS of the assignment.  It's basically a specialized
38
   form of tree combination.   It is hoped all of this can disappear
39
   when we have a generalized tree combiner.
40
 
41
   Note carefully that after propagation the resulting statement
42
   must still be a proper gimple statement.  Right now we simply
43
   only perform propagations we know will result in valid gimple
44
   code.  One day we'll want to generalize this code.
45
 
46
   One class of common cases we handle is forward propagating a single use
47
   variable into a COND_EXPR.
48
 
49
     bb0:
50
       x = a COND b;
51
       if (x) goto ... else goto ...
52
 
53
   Will be transformed into:
54
 
55
     bb0:
56
       if (a COND b) goto ... else goto ...
57
 
58
   Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
59
 
60
   Or (assuming c1 and c2 are constants):
61
 
62
     bb0:
63
       x = a + c1;
64
       if (x EQ/NEQ c2) goto ... else goto ...
65
 
66
   Will be transformed into:
67
 
68
     bb0:
69
        if (a EQ/NEQ (c2 - c1)) goto ... else goto ...
70
 
71
   Similarly for x = a - c1.
72
 
73
   Or
74
 
75
     bb0:
76
       x = !a
77
       if (x) goto ... else goto ...
78
 
79
   Will be transformed into:
80
 
81
     bb0:
82
        if (a == 0) goto ... else goto ...
83
 
84
   Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
85
   For these cases, we propagate A into all, possibly more than one,
86
   COND_EXPRs that use X.
87
 
88
   Or
89
 
90
     bb0:
91
       x = (typecast) a
92
       if (x) goto ... else goto ...
93
 
94
   Will be transformed into:
95
 
96
     bb0:
97
        if (a != 0) goto ... else goto ...
98
 
99
   (Assuming a is an integral type and x is a boolean or x is an
100
    integral and a is a boolean.)
101
 
102
   Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
103
   For these cases, we propagate A into all, possibly more than one,
104
   COND_EXPRs that use X.
105
 
106
   In addition to eliminating the variable and the statement which assigns
107
   a value to the variable, we may be able to later thread the jump without
108
   adding insane complexity in the dominator optimizer.
109
 
110
   Also note these transformations can cascade.  We handle this by having
111
   a worklist of COND_EXPR statements to examine.  As we make a change to
112
   a statement, we put it back on the worklist to examine on the next
113
   iteration of the main loop.
114
 
115
   A second class of propagation opportunities arises for ADDR_EXPR
116
   nodes.
117
 
118
     ptr = &x->y->z;
119
     res = *ptr;
120
 
121
   Will get turned into
122
 
123
     res = x->y->z;
124
 
125
   Or
126
 
127
     ptr = &x[0];
128
     ptr2 = ptr + <constant>;
129
 
130
   Will get turned into
131
 
132
     ptr2 = &x[constant/elementsize];
133
 
134
  Or
135
 
136
     ptr = &x[0];
137
     offset = index * element_size;
138
     offset_p = (pointer) offset;
139
     ptr2 = ptr + offset_p
140
 
141
  Will get turned into:
142
 
143
     ptr2 = &x[index];
144
 
145
  We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to
146
  allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent
147
  {NOT_EXPR,NEG_EXPR}.
148
 
149
   This will (of course) be extended as other needs arise.  */
150
 
151
 
152
/* Set to true if we delete EH edges during the optimization.  */
153
static bool cfg_changed;
154
 
155
 
156
/* Given an SSA_NAME VAR, return true if and only if VAR is defined by
157
   a comparison.  */
158
 
159
static bool
160
ssa_name_defined_by_comparison_p (tree var)
161
{
162
  tree def = SSA_NAME_DEF_STMT (var);
163
 
164
  if (TREE_CODE (def) == MODIFY_EXPR)
165
    {
166
      tree rhs = TREE_OPERAND (def, 1);
167
      return COMPARISON_CLASS_P (rhs);
168
    }
169
 
170
  return 0;
171
}
172
 
173
/* Forward propagate a single-use variable into COND once.  Return a
174
   new condition if successful.  Return NULL_TREE otherwise.  */
175
 
176
static tree
177
forward_propagate_into_cond_1 (tree cond, tree *test_var_p)
178
{
179
  tree new_cond = NULL_TREE;
180
  enum tree_code cond_code = TREE_CODE (cond);
181
  tree test_var = NULL_TREE;
182
  tree def;
183
  tree def_rhs;
184
 
185
  /* If the condition is not a lone variable or an equality test of an
186
     SSA_NAME against an integral constant, then we do not have an
187
     optimizable case.
188
 
189
     Note these conditions also ensure the COND_EXPR has no
190
     virtual operands or other side effects.  */
191
  if (cond_code != SSA_NAME
192
      && !((cond_code == EQ_EXPR || cond_code == NE_EXPR)
193
           && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
194
           && CONSTANT_CLASS_P (TREE_OPERAND (cond, 1))
195
           && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))))
196
    return NULL_TREE;
197
 
198
  /* Extract the single variable used in the test into TEST_VAR.  */
199
  if (cond_code == SSA_NAME)
200
    test_var = cond;
201
  else
202
    test_var = TREE_OPERAND (cond, 0);
203
 
204
  /* Now get the defining statement for TEST_VAR.  Skip this case if
205
     it's not defined by some MODIFY_EXPR.  */
206
  def = SSA_NAME_DEF_STMT (test_var);
207
  if (TREE_CODE (def) != MODIFY_EXPR)
208
    return NULL_TREE;
209
 
210
  def_rhs = TREE_OPERAND (def, 1);
211
 
212
  /* If TEST_VAR is set by adding or subtracting a constant
213
     from an SSA_NAME, then it is interesting to us as we
214
     can adjust the constant in the conditional and thus
215
     eliminate the arithmetic operation.  */
216
  if (TREE_CODE (def_rhs) == PLUS_EXPR
217
      || TREE_CODE (def_rhs) == MINUS_EXPR)
218
    {
219
      tree op0 = TREE_OPERAND (def_rhs, 0);
220
      tree op1 = TREE_OPERAND (def_rhs, 1);
221
 
222
      /* The first operand must be an SSA_NAME and the second
223
         operand must be a constant.  */
224
      if (TREE_CODE (op0) != SSA_NAME
225
          || !CONSTANT_CLASS_P (op1)
226
          || !INTEGRAL_TYPE_P (TREE_TYPE (op1)))
227
        return NULL_TREE;
228
 
229
      /* Don't propagate if the first operand occurs in
230
         an abnormal PHI.  */
231
      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
232
        return NULL_TREE;
233
 
234
      if (has_single_use (test_var))
235
        {
236
          enum tree_code new_code;
237
          tree t;
238
 
239
          /* If the variable was defined via X + C, then we must
240
             subtract C from the constant in the conditional.
241
             Otherwise we add C to the constant in the
242
             conditional.  The result must fold into a valid
243
             gimple operand to be optimizable.  */
244
          new_code = (TREE_CODE (def_rhs) == PLUS_EXPR
245
                      ? MINUS_EXPR : PLUS_EXPR);
246
          t = int_const_binop (new_code, TREE_OPERAND (cond, 1), op1, 0);
247
          if (!is_gimple_val (t))
248
            return NULL_TREE;
249
 
250
          new_cond = build2 (cond_code, boolean_type_node, op0, t);
251
        }
252
    }
253
 
254
  /* These cases require comparisons of a naked SSA_NAME or
255
     comparison of an SSA_NAME against zero or one.  */
256
  else if (TREE_CODE (cond) == SSA_NAME
257
           || integer_zerop (TREE_OPERAND (cond, 1))
258
           || integer_onep (TREE_OPERAND (cond, 1)))
259
    {
260
      /* If TEST_VAR is set from a relational operation
261
         between two SSA_NAMEs or a combination of an SSA_NAME
262
         and a constant, then it is interesting.  */
263
      if (COMPARISON_CLASS_P (def_rhs))
264
        {
265
          tree op0 = TREE_OPERAND (def_rhs, 0);
266
          tree op1 = TREE_OPERAND (def_rhs, 1);
267
 
268
          /* Both operands of DEF_RHS must be SSA_NAMEs or
269
             constants.  */
270
          if ((TREE_CODE (op0) != SSA_NAME
271
               && !is_gimple_min_invariant (op0))
272
              || (TREE_CODE (op1) != SSA_NAME
273
                  && !is_gimple_min_invariant (op1)))
274
            return NULL_TREE;
275
 
276
          /* Don't propagate if the first operand occurs in
277
             an abnormal PHI.  */
278
          if (TREE_CODE (op0) == SSA_NAME
279
              && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
280
            return NULL_TREE;
281
 
282
          /* Don't propagate if the second operand occurs in
283
             an abnormal PHI.  */
284
          if (TREE_CODE (op1) == SSA_NAME
285
              && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))
286
            return NULL_TREE;
287
 
288
          if (has_single_use (test_var))
289
            {
290
              /* TEST_VAR was set from a relational operator.  */
291
              new_cond = build2 (TREE_CODE (def_rhs),
292
                                 boolean_type_node, op0, op1);
293
 
294
              /* Invert the conditional if necessary.  */
295
              if ((cond_code == EQ_EXPR
296
                   && integer_zerop (TREE_OPERAND (cond, 1)))
297
                  || (cond_code == NE_EXPR
298
                      && integer_onep (TREE_OPERAND (cond, 1))))
299
                {
300
                  new_cond = invert_truthvalue (new_cond);
301
 
302
                  /* If we did not get a simple relational
303
                     expression or bare SSA_NAME, then we can
304
                     not optimize this case.  */
305
                  if (!COMPARISON_CLASS_P (new_cond)
306
                      && TREE_CODE (new_cond) != SSA_NAME)
307
                    new_cond = NULL_TREE;
308
                }
309
            }
310
        }
311
 
312
      /* If TEST_VAR is set from a TRUTH_NOT_EXPR, then it
313
         is interesting.  */
314
      else if (TREE_CODE (def_rhs) == TRUTH_NOT_EXPR)
315
        {
316
          enum tree_code new_code;
317
 
318
          def_rhs = TREE_OPERAND (def_rhs, 0);
319
 
320
          /* DEF_RHS must be an SSA_NAME or constant.  */
321
          if (TREE_CODE (def_rhs) != SSA_NAME
322
              && !is_gimple_min_invariant (def_rhs))
323
            return NULL_TREE;
324
 
325
          /* Don't propagate if the operand occurs in
326
             an abnormal PHI.  */
327
          if (TREE_CODE (def_rhs) == SSA_NAME
328
              && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def_rhs))
329
            return NULL_TREE;
330
 
331
          if (cond_code == SSA_NAME
332
              || (cond_code == NE_EXPR
333
                  && integer_zerop (TREE_OPERAND (cond, 1)))
334
              || (cond_code == EQ_EXPR
335
                  && integer_onep (TREE_OPERAND (cond, 1))))
336
            new_code = EQ_EXPR;
337
          else
338
            new_code = NE_EXPR;
339
 
340
          new_cond = build2 (new_code, boolean_type_node, def_rhs,
341
                             fold_convert (TREE_TYPE (def_rhs),
342
                                           integer_zero_node));
343
        }
344
 
345
      /* If TEST_VAR was set from a cast of an integer type
346
         to a boolean type or a cast of a boolean to an
347
         integral, then it is interesting.  */
348
      else if (TREE_CODE (def_rhs) == NOP_EXPR
349
               || TREE_CODE (def_rhs) == CONVERT_EXPR)
350
        {
351
          tree outer_type;
352
          tree inner_type;
353
 
354
          outer_type = TREE_TYPE (def_rhs);
355
          inner_type = TREE_TYPE (TREE_OPERAND (def_rhs, 0));
356
 
357
          if ((TREE_CODE (outer_type) == BOOLEAN_TYPE
358
               && INTEGRAL_TYPE_P (inner_type))
359
              || (TREE_CODE (inner_type) == BOOLEAN_TYPE
360
                  && INTEGRAL_TYPE_P (outer_type)))
361
            ;
362
          else if (INTEGRAL_TYPE_P (outer_type)
363
                   && INTEGRAL_TYPE_P (inner_type)
364
                   && TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME
365
                   && ssa_name_defined_by_comparison_p (TREE_OPERAND (def_rhs,
366
                                                                      0)))
367
            ;
368
          else
369
            return NULL_TREE;
370
 
371
          /* Don't propagate if the operand occurs in
372
             an abnormal PHI.  */
373
          if (TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME
374
              && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND
375
                                                  (def_rhs, 0)))
376
            return NULL_TREE;
377
 
378
          if (has_single_use (test_var))
379
            {
380
              enum tree_code new_code;
381
              tree new_arg;
382
 
383
              if (cond_code == SSA_NAME
384
                  || (cond_code == NE_EXPR
385
                      && integer_zerop (TREE_OPERAND (cond, 1)))
386
                  || (cond_code == EQ_EXPR
387
                      && integer_onep (TREE_OPERAND (cond, 1))))
388
                new_code = NE_EXPR;
389
              else
390
                new_code = EQ_EXPR;
391
 
392
              new_arg = TREE_OPERAND (def_rhs, 0);
393
              new_cond = build2 (new_code, boolean_type_node, new_arg,
394
                                 fold_convert (TREE_TYPE (new_arg),
395
                                               integer_zero_node));
396
            }
397
        }
398
    }
399
 
400
  *test_var_p = test_var;
401
  return new_cond;
402
}
403
 
404
/* COND is a condition of the form:
405
 
406
     x == const or x != const
407
 
408
   Look back to x's defining statement and see if x is defined as
409
 
410
     x = (type) y;
411
 
412
   If const is unchanged if we convert it to type, then we can build
413
   the equivalent expression:
414
 
415
 
416
      y == const or y != const
417
 
418
   Which may allow further optimizations.
419
 
420
   Return the equivalent comparison or NULL if no such equivalent comparison
421
   was found.  */
422
 
423
static tree
424
find_equivalent_equality_comparison (tree cond)
425
{
426
  tree op0 = TREE_OPERAND (cond, 0);
427
  tree op1 = TREE_OPERAND (cond, 1);
428
  tree def_stmt = SSA_NAME_DEF_STMT (op0);
429
 
430
  while (def_stmt
431
         && TREE_CODE (def_stmt) == MODIFY_EXPR
432
         && TREE_CODE (TREE_OPERAND (def_stmt, 1)) == SSA_NAME)
433
    def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (def_stmt, 1));
434
 
435
  /* OP0 might have been a parameter, so first make sure it
436
     was defined by a MODIFY_EXPR.  */
437
  if (def_stmt && TREE_CODE (def_stmt) == MODIFY_EXPR)
438
    {
439
      tree def_rhs = TREE_OPERAND (def_stmt, 1);
440
 
441
      /* If either operand to the comparison is a pointer to
442
         a function, then we can not apply this optimization
443
         as some targets require function pointers to be
444
         canonicalized and in this case this optimization would
445
         eliminate a necessary canonicalization.  */
446
      if ((POINTER_TYPE_P (TREE_TYPE (op0))
447
           && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == FUNCTION_TYPE)
448
          || (POINTER_TYPE_P (TREE_TYPE (op1))
449
              && TREE_CODE (TREE_TYPE (TREE_TYPE (op1))) == FUNCTION_TYPE))
450
        return NULL;
451
 
452
      /* Now make sure the RHS of the MODIFY_EXPR is a typecast.  */
453
      if ((TREE_CODE (def_rhs) == NOP_EXPR
454
           || TREE_CODE (def_rhs) == CONVERT_EXPR)
455
          && TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME)
456
        {
457
          tree def_rhs_inner = TREE_OPERAND (def_rhs, 0);
458
          tree def_rhs_inner_type = TREE_TYPE (def_rhs_inner);
459
          tree new;
460
 
461
          if (TYPE_PRECISION (def_rhs_inner_type)
462
              > TYPE_PRECISION (TREE_TYPE (def_rhs)))
463
            return NULL;
464
 
465
          /* If the inner type of the conversion is a pointer to
466
             a function, then we can not apply this optimization
467
             as some targets require function pointers to be
468
             canonicalized.  This optimization would result in
469
             canonicalization of the pointer when it was not originally
470
             needed/intended.  */
471
          if (POINTER_TYPE_P (def_rhs_inner_type)
472
              && TREE_CODE (TREE_TYPE (def_rhs_inner_type)) == FUNCTION_TYPE)
473
            return NULL;
474
 
475
          /* What we want to prove is that if we convert OP1 to
476
             the type of the object inside the NOP_EXPR that the
477
             result is still equivalent to SRC.
478
 
479
             If that is true, the build and return new equivalent
480
             condition which uses the source of the typecast and the
481
             new constant (which has only changed its type).  */
482
          new = fold_build1 (TREE_CODE (def_rhs), def_rhs_inner_type, op1);
483
          STRIP_USELESS_TYPE_CONVERSION (new);
484
          if (is_gimple_val (new) && tree_int_cst_equal (new, op1))
485
            return build2 (TREE_CODE (cond), TREE_TYPE (cond),
486
                           def_rhs_inner, new);
487
        }
488
    }
489
  return NULL;
490
}
491
 
492
/* STMT is a COND_EXPR
493
 
494
   This routine attempts to find equivalent forms of the condition
495
   which we may be able to optimize better.  */
496
 
497
static void
498
simplify_cond (tree stmt)
499
{
500
  tree cond = COND_EXPR_COND (stmt);
501
 
502
  if (COMPARISON_CLASS_P (cond))
503
    {
504
      tree op0 = TREE_OPERAND (cond, 0);
505
      tree op1 = TREE_OPERAND (cond, 1);
506
 
507
      if (TREE_CODE (op0) == SSA_NAME && is_gimple_min_invariant (op1))
508
        {
509
          /* First see if we have test of an SSA_NAME against a constant
510
             where the SSA_NAME is defined by an earlier typecast which
511
             is irrelevant when performing tests against the given
512
             constant.  */
513
          if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
514
            {
515
              tree new_cond = find_equivalent_equality_comparison (cond);
516
 
517
              if (new_cond)
518
                {
519
                  COND_EXPR_COND (stmt) = new_cond;
520
                  update_stmt (stmt);
521
                }
522
            }
523
        }
524
    }
525
}
526
 
527
/* Forward propagate a single-use variable into COND_EXPR as many
528
   times as possible.  */
529
 
530
static void
531
forward_propagate_into_cond (tree cond_expr)
532
{
533
  gcc_assert (TREE_CODE (cond_expr) == COND_EXPR);
534
 
535
  while (1)
536
    {
537
      tree test_var = NULL_TREE;
538
      tree cond = COND_EXPR_COND (cond_expr);
539
      tree new_cond = forward_propagate_into_cond_1 (cond, &test_var);
540
 
541
      /* Return if unsuccessful.  */
542
      if (new_cond == NULL_TREE)
543
        break;
544
 
545
      /* Dump details.  */
546
      if (dump_file && (dump_flags & TDF_DETAILS))
547
        {
548
          fprintf (dump_file, "  Replaced '");
549
          print_generic_expr (dump_file, cond, dump_flags);
550
          fprintf (dump_file, "' with '");
551
          print_generic_expr (dump_file, new_cond, dump_flags);
552
          fprintf (dump_file, "'\n");
553
        }
554
 
555
      COND_EXPR_COND (cond_expr) = new_cond;
556
      update_stmt (cond_expr);
557
 
558
      if (has_zero_uses (test_var))
559
        {
560
          tree def = SSA_NAME_DEF_STMT (test_var);
561
          block_stmt_iterator bsi = bsi_for_stmt (def);
562
          bsi_remove (&bsi, true);
563
        }
564
    }
565
 
566
  /* There are further simplifications that can be performed
567
     on COND_EXPRs.  Specifically, when comparing an SSA_NAME
568
     against a constant where the SSA_NAME is the result of a
569
     conversion.  Perhaps this should be folded into the rest
570
     of the COND_EXPR simplification code.  */
571
  simplify_cond (cond_expr);
572
}
573
 
574
/* We've just substituted an ADDR_EXPR into stmt.  Update all the
575
   relevant data structures to match.  */
576
 
577
static void
578
tidy_after_forward_propagate_addr (tree stmt)
579
{
580
  /* We may have turned a trapping insn into a non-trapping insn.  */
581
  if (maybe_clean_or_replace_eh_stmt (stmt, stmt)
582
      && tree_purge_dead_eh_edges (bb_for_stmt (stmt)))
583
    cfg_changed = true;
584
 
585
  if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR)
586
     recompute_tree_invariant_for_addr_expr (TREE_OPERAND (stmt, 1));
587
 
588
  mark_new_vars_to_rename (stmt);
589
}
590
 
591
/* STMT defines LHS which is contains the address of the 0th element
592
   in an array.  USE_STMT uses LHS to compute the address of an
593
   arbitrary element within the array.  The (variable) byte offset
594
   of the element is contained in OFFSET.
595
 
596
   We walk back through the use-def chains of OFFSET to verify that
597
   it is indeed computing the offset of an element within the array
598
   and extract the index corresponding to the given byte offset.
599
 
600
   We then try to fold the entire address expression into a form
601
   &array[index].
602
 
603
   If we are successful, we replace the right hand side of USE_STMT
604
   with the new address computation.  */
605
 
606
static bool
607
forward_propagate_addr_into_variable_array_index (tree offset, tree lhs,
608
                                                  tree stmt, tree use_stmt)
609
{
610
  tree index;
611
 
612
  /* The offset must be defined by a simple MODIFY_EXPR statement.  */
613
  if (TREE_CODE (offset) != MODIFY_EXPR)
614
    return false;
615
 
616
  /* The RHS of the statement which defines OFFSET must be a gimple
617
     cast of another SSA_NAME.  */
618
  offset = TREE_OPERAND (offset, 1);
619
  if (!is_gimple_cast (offset))
620
    return false;
621
 
622
  offset = TREE_OPERAND (offset, 0);
623
  if (TREE_CODE (offset) != SSA_NAME)
624
    return false;
625
 
626
  /* Get the defining statement of the offset before type
627
     conversion.  */
628
  offset = SSA_NAME_DEF_STMT (offset);
629
 
630
  /* The statement which defines OFFSET before type conversion
631
     must be a simple MODIFY_EXPR.  */
632
  if (TREE_CODE (offset) != MODIFY_EXPR)
633
    return false;
634
 
635
  /* The RHS of the statement which defines OFFSET must be a
636
     multiplication of an object by the size of the array elements.
637
     This implicitly verifies that the size of the array elements
638
     is constant.  */
639
  offset = TREE_OPERAND (offset, 1);
640
  if (TREE_CODE (offset) != MULT_EXPR
641
      || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
642
      || !simple_cst_equal (TREE_OPERAND (offset, 1),
643
                            TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs)))))
644
    return false;
645
 
646
  /* The first operand to the MULT_EXPR is the desired index.  */
647
  index = TREE_OPERAND (offset, 0);
648
 
649
  /* Replace the pointer addition with array indexing.  */
650
  TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1));
651
  TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 0), 1) = index;
652
 
653
  /* That should have created gimple, so there is no need to
654
     record information to undo the propagation.  */
655
  fold_stmt_inplace (use_stmt);
656
  tidy_after_forward_propagate_addr (use_stmt);
657
  return true;
658
}
659
 
660
/* STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>.
661
 
662
   Try to forward propagate the ADDR_EXPR into the use USE_STMT.
663
   Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
664
   node or for recovery of array indexing from pointer arithmetic.
665
 
666
   CHANGED is an optional pointer to a boolean variable set to true if
667
   either the LHS or RHS was changed in the USE_STMT.
668
 
669
   Return true if the propagation was successful (the propagation can
670
   be not totally successful, yet things may have been changed).  */
671
 
672
static bool
673
forward_propagate_addr_expr_1 (tree stmt, tree use_stmt, bool *changed)
674
{
675
  tree name = TREE_OPERAND (stmt, 0);
676
  tree lhs, rhs, array_ref;
677
 
678
  /* Strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS.
679
     ADDR_EXPR will not appear on the LHS.  */
680
  lhs = TREE_OPERAND (use_stmt, 0);
681
  while (TREE_CODE (lhs) == COMPONENT_REF || TREE_CODE (lhs) == ARRAY_REF)
682
    lhs = TREE_OPERAND (lhs, 0);
683
 
684
  /* Now see if the LHS node is an INDIRECT_REF using NAME.  If so,
685
     propagate the ADDR_EXPR into the use of NAME and fold the result.  */
686
  if (TREE_CODE (lhs) == INDIRECT_REF && TREE_OPERAND (lhs, 0) == name)
687
    {
688
      /* This should always succeed in creating gimple, so there is
689
         no need to save enough state to undo this propagation.  */
690
      TREE_OPERAND (lhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
691
      fold_stmt_inplace (use_stmt);
692
      tidy_after_forward_propagate_addr (use_stmt);
693
      if (changed)
694
        *changed = true;
695
    }
696
 
697
  /* Trivial case.  The use statement could be a trivial copy.  We
698
     go ahead and handle that case here since it's trivial and
699
     removes the need to run copy-prop before this pass to get
700
     the best results.  Also note that by handling this case here
701
     we can catch some cascading effects, ie the single use is
702
     in a copy, and the copy is used later by a single INDIRECT_REF
703
     for example.  */
704
  else if (TREE_CODE (lhs) == SSA_NAME && TREE_OPERAND (use_stmt, 1) == name)
705
    {
706
      TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1));
707
      tidy_after_forward_propagate_addr (use_stmt);
708
      if (changed)
709
        *changed = true;
710
      return true;
711
    }
712
 
713
  /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
714
     nodes from the RHS.  */
715
  rhs = TREE_OPERAND (use_stmt, 1);
716
  while (TREE_CODE (rhs) == COMPONENT_REF
717
         || TREE_CODE (rhs) == ARRAY_REF
718
         || TREE_CODE (rhs) == ADDR_EXPR)
719
    rhs = TREE_OPERAND (rhs, 0);
720
 
721
  /* Now see if the RHS node is an INDIRECT_REF using NAME.  If so,
722
     propagate the ADDR_EXPR into the use of NAME and fold the result.  */
723
  if (TREE_CODE (rhs) == INDIRECT_REF && TREE_OPERAND (rhs, 0) == name)
724
    {
725
      /* This should always succeed in creating gimple, so there is
726
         no need to save enough state to undo this propagation.  */
727
      TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
728
      fold_stmt_inplace (use_stmt);
729
      tidy_after_forward_propagate_addr (use_stmt);
730
      if (changed)
731
        *changed = true;
732
      return true;
733
    }
734
 
735
  /* The remaining cases are all for turning pointer arithmetic into
736
     array indexing.  They only apply when we have the address of
737
     element zero in an array.  If that is not the case then there
738
     is nothing to do.  */
739
  array_ref = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
740
  if (TREE_CODE (array_ref) != ARRAY_REF
741
      || TREE_CODE (TREE_TYPE (TREE_OPERAND (array_ref, 0))) != ARRAY_TYPE
742
      || !integer_zerop (TREE_OPERAND (array_ref, 1)))
743
    return false;
744
 
745
  /* If the use of the ADDR_EXPR must be a PLUS_EXPR, or else there
746
     is nothing to do. */
747
  if (TREE_CODE (rhs) != PLUS_EXPR)
748
    return false;
749
 
750
  /* Try to optimize &x[0] + C where C is a multiple of the size
751
     of the elements in X into &x[C/element size].  */
752
  if (TREE_OPERAND (rhs, 0) == name
753
      && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
754
    {
755
      tree orig = unshare_expr (rhs);
756
      TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
757
 
758
      /* If folding succeeds, then we have just exposed new variables
759
         in USE_STMT which will need to be renamed.  If folding fails,
760
         then we need to put everything back the way it was.  */
761
      if (fold_stmt_inplace (use_stmt))
762
        {
763
          tidy_after_forward_propagate_addr (use_stmt);
764
          if (changed)
765
            *changed = true;
766
          return true;
767
        }
768
      else
769
        {
770
          TREE_OPERAND (use_stmt, 1) = orig;
771
          update_stmt (use_stmt);
772
          return false;
773
        }
774
    }
775
 
776
  /* Try to optimize &x[0] + OFFSET where OFFSET is defined by
777
     converting a multiplication of an index by the size of the
778
     array elements, then the result is converted into the proper
779
     type for the arithmetic.  */
780
  if (TREE_OPERAND (rhs, 0) == name
781
      && TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME
782
      /* Avoid problems with IVopts creating PLUS_EXPRs with a
783
         different type than their operands.  */
784
      && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
785
    {
786
      bool res;
787
      tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
788
 
789
      res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs,
790
                                                              stmt, use_stmt);
791
      if (res && changed)
792
        *changed = true;
793
      return res;
794
    }
795
 
796
  /* Same as the previous case, except the operands of the PLUS_EXPR
797
     were reversed.  */
798
  if (TREE_OPERAND (rhs, 1) == name
799
      && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
800
      /* Avoid problems with IVopts creating PLUS_EXPRs with a
801
         different type than their operands.  */
802
      && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
803
    {
804
      bool res;
805
      tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
806
      res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs,
807
                                                              stmt, use_stmt);
808
      if (res && changed)
809
        *changed = true;
810
      return res;
811
    }
812
  return false;
813
}
814
 
815
/* STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>.
816
   SOME is a pointer to a boolean value indicating whether we
817
   propagated the address expression anywhere.
818
 
819
   Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME.
820
   Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
821
   node or for recovery of array indexing from pointer arithmetic.
822
   Returns true, if all uses have been propagated into.  */
823
 
824
static bool
825
forward_propagate_addr_expr (tree stmt, bool *some)
826
{
827
  int stmt_loop_depth = bb_for_stmt (stmt)->loop_depth;
828
  tree name = TREE_OPERAND (stmt, 0);
829
  imm_use_iterator iter;
830
  tree use_stmt;
831
  bool all = true;
832
 
833
  FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
834
    {
835
      bool result;
836
 
837
      /* If the use is not in a simple assignment statement, then
838
         there is nothing we can do.  */
839
      if (TREE_CODE (use_stmt) != MODIFY_EXPR)
840
        {
841
          all = false;
842
          continue;
843
        }
844
 
845
      /* If the use is in a deeper loop nest, then we do not want
846
         to propagate the ADDR_EXPR into the loop as that is likely
847
         adding expression evaluations into the loop.  */
848
      if (bb_for_stmt (use_stmt)->loop_depth > stmt_loop_depth)
849
        {
850
          all = false;
851
          continue;
852
        }
853
 
854
      /* If the use_stmt has side-effects, don't propagate into it.  */
855
      if (stmt_ann (use_stmt)->has_volatile_ops)
856
        {
857
          all = false;
858
          continue;
859
        }
860
 
861
      result = forward_propagate_addr_expr_1 (stmt, use_stmt, some);
862
      *some |= result;
863
      all &= result;
864
    }
865
 
866
  return all;
867
}
868
 
869
/* If we have lhs = ~x (STMT), look and see if earlier we had x = ~y.
870
   If so, we can change STMT into lhs = y which can later be copy
871
   propagated.  Similarly for negation.
872
 
873
   This could trivially be formulated as a forward propagation
874
   to immediate uses.  However, we already had an implementation
875
   from DOM which used backward propagation via the use-def links.
876
 
877
   It turns out that backward propagation is actually faster as
878
   there's less work to do for each NOT/NEG expression we find.
879
   Backwards propagation needs to look at the statement in a single
880
   backlink.  Forward propagation needs to look at potentially more
881
   than one forward link.  */
882
 
883
static void
884
simplify_not_neg_expr (tree stmt)
885
{
886
  tree rhs = TREE_OPERAND (stmt, 1);
887
  tree rhs_def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
888
 
889
  /* See if the RHS_DEF_STMT has the same form as our statement.  */
890
  if (TREE_CODE (rhs_def_stmt) == MODIFY_EXPR
891
      && TREE_CODE (TREE_OPERAND (rhs_def_stmt, 1)) == TREE_CODE (rhs))
892
    {
893
      tree rhs_def_operand = TREE_OPERAND (TREE_OPERAND (rhs_def_stmt, 1), 0);
894
 
895
      /* Verify that RHS_DEF_OPERAND is a suitable SSA_NAME.  */
896
      if (TREE_CODE (rhs_def_operand) == SSA_NAME
897
          && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand))
898
        {
899
          TREE_OPERAND (stmt, 1) = rhs_def_operand;
900
          update_stmt (stmt);
901
        }
902
    }
903
}
904
 
905
/* STMT is a SWITCH_EXPR for which we attempt to find equivalent forms of
906
   the condition which we may be able to optimize better.  */
907
 
908
static void
909
simplify_switch_expr (tree stmt)
910
{
911
  tree cond = SWITCH_COND (stmt);
912
  tree def, to, ti;
913
 
914
  /* The optimization that we really care about is removing unnecessary
915
     casts.  That will let us do much better in propagating the inferred
916
     constant at the switch target.  */
917
  if (TREE_CODE (cond) == SSA_NAME)
918
    {
919
      def = SSA_NAME_DEF_STMT (cond);
920
      if (TREE_CODE (def) == MODIFY_EXPR)
921
        {
922
          def = TREE_OPERAND (def, 1);
923
          if (TREE_CODE (def) == NOP_EXPR)
924
            {
925
              int need_precision;
926
              bool fail;
927
 
928
              def = TREE_OPERAND (def, 0);
929
 
930
#ifdef ENABLE_CHECKING
931
              /* ??? Why was Jeff testing this?  We are gimple...  */
932
              gcc_assert (is_gimple_val (def));
933
#endif
934
 
935
              to = TREE_TYPE (cond);
936
              ti = TREE_TYPE (def);
937
 
938
              /* If we have an extension that preserves value, then we
939
                 can copy the source value into the switch.  */
940
 
941
              need_precision = TYPE_PRECISION (ti);
942
              fail = false;
943
              if (! INTEGRAL_TYPE_P (ti))
944
                fail = true;
945
              else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti))
946
                fail = true;
947
              else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti))
948
                need_precision += 1;
949
              if (TYPE_PRECISION (to) < need_precision)
950
                fail = true;
951
 
952
              if (!fail)
953
                {
954
                  SWITCH_COND (stmt) = def;
955
                  update_stmt (stmt);
956
                }
957
            }
958
        }
959
    }
960
}
961
 
962
/* Main entry point for the forward propagation optimizer.  */
963
 
964
static unsigned int
965
tree_ssa_forward_propagate_single_use_vars (void)
966
{
967
  basic_block bb;
968
  unsigned int todoflags = 0;
969
 
970
  cfg_changed = false;
971
 
972
  FOR_EACH_BB (bb)
973
    {
974
      block_stmt_iterator bsi;
975
 
976
      /* Note we update BSI within the loop as necessary.  */
977
      for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
978
        {
979
          tree stmt = bsi_stmt (bsi);
980
 
981
          /* If this statement sets an SSA_NAME to an address,
982
             try to propagate the address into the uses of the SSA_NAME.  */
983
          if (TREE_CODE (stmt) == MODIFY_EXPR)
984
            {
985
              tree lhs = TREE_OPERAND (stmt, 0);
986
              tree rhs = TREE_OPERAND (stmt, 1);
987
 
988
 
989
              if (TREE_CODE (lhs) != SSA_NAME)
990
                {
991
                  bsi_next (&bsi);
992
                  continue;
993
                }
994
 
995
              if (TREE_CODE (rhs) == ADDR_EXPR)
996
                {
997
                  bool some = false;
998
                  if (forward_propagate_addr_expr (stmt, &some))
999
                    bsi_remove (&bsi, true);
1000
                  else
1001
                    bsi_next (&bsi);
1002
                  if (some)
1003
                    todoflags |= TODO_update_smt_usage;
1004
                }
1005
              else if ((TREE_CODE (rhs) == BIT_NOT_EXPR
1006
                        || TREE_CODE (rhs) == NEGATE_EXPR)
1007
                       && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
1008
                {
1009
                  simplify_not_neg_expr (stmt);
1010
                  bsi_next (&bsi);
1011
                }
1012
              else
1013
                bsi_next (&bsi);
1014
            }
1015
          else if (TREE_CODE (stmt) == SWITCH_EXPR)
1016
            {
1017
              simplify_switch_expr (stmt);
1018
              bsi_next (&bsi);
1019
            }
1020
          else if (TREE_CODE (stmt) == COND_EXPR)
1021
            {
1022
              forward_propagate_into_cond (stmt);
1023
              bsi_next (&bsi);
1024
            }
1025
          else
1026
            bsi_next (&bsi);
1027
        }
1028
    }
1029
 
1030
  if (cfg_changed)
1031
    cleanup_tree_cfg ();
1032
  return todoflags;
1033
}
1034
 
1035
 
1036
static bool
1037
gate_forwprop (void)
1038
{
1039
  return 1;
1040
}
1041
 
1042
struct tree_opt_pass pass_forwprop = {
1043
  "forwprop",                   /* name */
1044
  gate_forwprop,                /* gate */
1045
  tree_ssa_forward_propagate_single_use_vars,   /* execute */
1046
  NULL,                         /* sub */
1047
  NULL,                         /* next */
1048
  0,                             /* static_pass_number */
1049
  TV_TREE_FORWPROP,             /* tv_id */
1050
  PROP_cfg | PROP_ssa
1051
    | PROP_alias,               /* properties_required */
1052
  0,                             /* properties_provided */
1053
  PROP_smt_usage,               /* properties_destroyed */
1054
  0,                             /* todo_flags_start */
1055
  TODO_dump_func /* todo_flags_finish */
1056
  | TODO_ggc_collect
1057
  | TODO_update_ssa | TODO_verify_ssa,
1058
 
1059
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.