LCOV - code coverage report
Current view: top level - gcc - tree-data-ref.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.0 % 60 57
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Data references and dependences detectors.
       2              :    Copyright (C) 2003-2026 Free Software Foundation, Inc.
       3              :    Contributed by Sebastian Pop <pop@cri.ensmp.fr>
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #ifndef GCC_TREE_DATA_REF_H
      22              : #define GCC_TREE_DATA_REF_H
      23              : 
      24              : #include "graphds.h"
      25              : #include "tree-chrec.h"
      26              : #include "opt-problem.h"
      27              : 
      28              : /*
      29              :   innermost_loop_behavior describes the evolution of the address of the memory
      30              :   reference in the innermost enclosing loop.  The address is expressed as
      31              :   BASE + STEP * # of iteration, and base is further decomposed as the base
      32              :   pointer (BASE_ADDRESS),  loop invariant offset (OFFSET) and
      33              :   constant offset (INIT).  Examples, in loop nest
      34              : 
      35              :   for (i = 0; i < 100; i++)
      36              :     for (j = 3; j < 100; j++)
      37              : 
      38              :                        Example 1                      Example 2
      39              :       data-ref         a[j].b[i][j]                   *(p + x + 16B + 4B * j)
      40              : 
      41              : 
      42              :   innermost_loop_behavior
      43              :       base_address     &a                             p
      44              :       offset           i * D_i                        x
      45              :       init             3 * D_j + offsetof (b)         28
      46              :       step             D_j                            4
      47              : 
      48              :   */
      49              : struct innermost_loop_behavior
      50              : {
      51              :   tree base_address;
      52              :   tree offset;
      53              :   tree init;
      54              :   tree step;
      55              : 
      56              :   /* BASE_ADDRESS is known to be misaligned by BASE_MISALIGNMENT bytes
      57              :      from an alignment boundary of BASE_ALIGNMENT bytes.  For example,
      58              :      if we had:
      59              : 
      60              :        struct S __attribute__((aligned(16))) { ... };
      61              : 
      62              :        char *ptr;
      63              :        ... *(struct S *) (ptr - 4) ...;
      64              : 
      65              :      the information would be:
      66              : 
      67              :        base_address:      ptr
      68              :        base_aligment:      16
      69              :        base_misalignment:   4
      70              :        init:               -4
      71              : 
      72              :      where init cancels the base misalignment.  If instead we had a
      73              :      reference to a particular field:
      74              : 
      75              :        struct S __attribute__((aligned(16))) { ... int f; ... };
      76              : 
      77              :        char *ptr;
      78              :        ... ((struct S *) (ptr - 4))->f ...;
      79              : 
      80              :      the information would be:
      81              : 
      82              :        base_address:      ptr
      83              :        base_aligment:      16
      84              :        base_misalignment:   4
      85              :        init:               -4 + offsetof (S, f)
      86              : 
      87              :      where base_address + init might also be misaligned, and by a different
      88              :      amount from base_address.  */
      89              :   unsigned int base_alignment;
      90              :   unsigned int base_misalignment;
      91              : 
      92              :   /* The largest power of two that divides OFFSET, capped to a suitably
      93              :      high value if the offset is zero.  This is a byte rather than a bit
      94              :      quantity.  */
      95              :   unsigned int offset_alignment;
      96              : 
      97              :   /* Likewise for STEP.  */
      98              :   unsigned int step_alignment;
      99              : };
     100              : 
     101              : /* Describes the evolutions of indices of the memory reference.  The indices
     102              :    are indices of the ARRAY_REFs, indexes in artificial dimensions
     103              :    added for member selection of records and the operands of MEM_REFs.
     104              :    BASE_OBJECT is the part of the reference that is loop-invariant
     105              :    (note that this reference does not have to cover the whole object
     106              :    being accessed, in which case UNCONSTRAINED_BASE is set; hence it is
     107              :    not recommended to use BASE_OBJECT in any code generation).
     108              :    For the examples above,
     109              : 
     110              :    base_object:        a                              *(p + x + 4B * j_0)
     111              :    indices:            {j_0, +, 1}_2                  {16, +, 4}_2
     112              :                        4
     113              :                        {i_0, +, 1}_1
     114              :                        {j_0, +, 1}_2
     115              : */
     116              : 
     117              : struct indices
     118              : {
     119              :   /* The object.  */
     120              :   tree base_object;
     121              : 
     122              :   /* A list of chrecs.  Access functions of the indices.  */
     123              :   vec<tree> access_fns;
     124              : 
     125              :   /* Whether BASE_OBJECT is an access representing the whole object
     126              :      or whether the access could not be constrained.  */
     127              :   bool unconstrained_base;
     128              : };
     129              : 
     130              : struct dr_alias
     131              : {
     132              :   /* The alias information that should be used for new pointers to this
     133              :      location.  */
     134              :   struct ptr_info_def *ptr_info;
     135              : };
     136              : 
     137              : /* An integer vector.  A vector formally consists of an element of a vector
     138              :    space. A vector space is a set that is closed under vector addition
     139              :    and scalar multiplication.  In this vector space, an element is a list of
     140              :    integers.  */
     141              : typedef HOST_WIDE_INT lambda_int;
     142              : typedef lambda_int *lambda_vector;
     143              : 
     144              : /* An integer matrix.  A matrix consists of m vectors of length n (IE
     145              :    all vectors are the same length).  */
     146              : typedef lambda_vector *lambda_matrix;
     147              : 
     148              : 
     149              : 
     150              : struct data_reference
     151              : {
     152              :   /* A pointer to the statement that contains this DR.  */
     153              :   gimple *stmt;
     154              : 
     155              :   /* A pointer to the memory reference.  */
     156              :   tree ref;
     157              : 
     158              :   /* Auxiliary info specific to a pass.  */
     159              :   void *aux;
     160              : 
     161              :   /* True when the data reference is in RHS of a stmt.  */
     162              :   bool is_read;
     163              : 
     164              :   /* True when the data reference is conditional within STMT,
     165              :      i.e. if it might not occur even when the statement is executed
     166              :      and runs to completion.  */
     167              :   bool is_conditional_in_stmt;
     168              : 
     169              :   /* Alias information for the data reference.  */
     170              :   struct dr_alias alias;
     171              : 
     172              :   /* Behavior of the memory reference in the innermost loop.  */
     173              :   struct innermost_loop_behavior innermost;
     174              : 
     175              :   /* Subscripts of this data reference.  */
     176              :   struct indices indices;
     177              : 
     178              :   /* Alternate subscripts initialized lazily and used by data-dependence
     179              :      analysis only when the main indices of two DRs are not comparable.
     180              :      Keep last to keep vec_info_shared::check_datarefs happy.  */
     181              :   struct indices alt_indices;
     182              : };
     183              : 
     184              : #define DR_STMT(DR)                (DR)->stmt
     185              : #define DR_REF(DR)                 (DR)->ref
     186              : #define DR_BASE_OBJECT(DR)         (DR)->indices.base_object
     187              : #define DR_UNCONSTRAINED_BASE(DR)  (DR)->indices.unconstrained_base
     188              : #define DR_ACCESS_FNS(DR)          (DR)->indices.access_fns
     189              : #define DR_ACCESS_FN(DR, I)        DR_ACCESS_FNS (DR)[I]
     190              : #define DR_NUM_DIMENSIONS(DR)      DR_ACCESS_FNS (DR).length ()
     191              : #define DR_IS_READ(DR)             (DR)->is_read
     192              : #define DR_IS_WRITE(DR)            (!DR_IS_READ (DR))
     193              : #define DR_IS_CONDITIONAL_IN_STMT(DR) (DR)->is_conditional_in_stmt
     194              : #define DR_BASE_ADDRESS(DR)        (DR)->innermost.base_address
     195              : #define DR_OFFSET(DR)              (DR)->innermost.offset
     196              : #define DR_INIT(DR)                (DR)->innermost.init
     197              : #define DR_STEP(DR)                (DR)->innermost.step
     198              : #define DR_PTR_INFO(DR)            (DR)->alias.ptr_info
     199              : #define DR_BASE_ALIGNMENT(DR)      (DR)->innermost.base_alignment
     200              : #define DR_BASE_MISALIGNMENT(DR)   (DR)->innermost.base_misalignment
     201              : #define DR_OFFSET_ALIGNMENT(DR)    (DR)->innermost.offset_alignment
     202              : #define DR_STEP_ALIGNMENT(DR)      (DR)->innermost.step_alignment
     203              : #define DR_INNERMOST(DR)           (DR)->innermost
     204              : 
     205              : typedef struct data_reference *data_reference_p;
     206              : 
     207              : /* This struct is used to store the information of a data reference,
     208              :    including the data ref itself and the segment length for aliasing
     209              :    checks.  This is used to merge alias checks.  */
     210              : 
     211              : class dr_with_seg_len
     212              : {
     213              : public:
     214        58428 :   dr_with_seg_len (data_reference_p d, tree len, unsigned HOST_WIDE_INT size,
     215              :                    unsigned int a)
     216        58428 :     : dr (d), seg_len (len), access_size (size), align (a) {}
     217              : 
     218              :   data_reference_p dr;
     219              :   /* The offset of the last access that needs to be checked minus
     220              :      the offset of the first.  */
     221              :   tree seg_len;
     222              :   /* A value that, when added to abs (SEG_LEN), gives the total number of
     223              :      bytes in the segment.  */
     224              :   poly_uint64 access_size;
     225              :   /* The minimum common alignment of DR's start address, SEG_LEN and
     226              :      ACCESS_SIZE.  */
     227              :   unsigned int align;
     228              : };
     229              : 
     230              : /* Flags that describe a potential alias between two dr_with_seg_lens.
     231              :    In general, each pair of dr_with_seg_lens represents a composite of
     232              :    multiple access pairs P, so testing flags like DR_IS_READ on the DRs
     233              :    does not give meaningful information.
     234              : 
     235              :    DR_ALIAS_RAW:
     236              :         There is a pair in P for which the second reference is a read
     237              :         and the first is a write.
     238              : 
     239              :    DR_ALIAS_WAR:
     240              :         There is a pair in P for which the second reference is a write
     241              :         and the first is a read.
     242              : 
     243              :    DR_ALIAS_WAW:
     244              :         There is a pair in P for which both references are writes.
     245              : 
     246              :    DR_ALIAS_ARBITRARY:
     247              :         Either
     248              :         (a) it isn't possible to classify one pair in P as RAW, WAW or WAR; or
     249              :         (b) there is a pair in P that breaks the ordering assumption below.
     250              : 
     251              :         This flag overrides the RAW, WAR and WAW flags above.
     252              : 
     253              :    DR_ALIAS_UNSWAPPED:
     254              :    DR_ALIAS_SWAPPED:
     255              :         Temporary flags that indicate whether there is a pair P whose
     256              :         DRs have or haven't been swapped around.
     257              : 
     258              :    DR_ALIAS_MIXED_STEPS:
     259              :         The DR_STEP for one of the data references in the pair does not
     260              :         accurately describe that reference for all members of P.  (Note
     261              :         that the flag does not say anything about whether the DR_STEPs
     262              :         of the two references in the pair are the same.)
     263              : 
     264              :    The ordering assumption mentioned above is that for every pair
     265              :    (DR_A, DR_B) in P:
     266              : 
     267              :    (1) The original code accesses n elements for DR_A and n elements for DR_B,
     268              :        interleaved as follows:
     269              : 
     270              :          one access of size DR_A.access_size at DR_A.dr
     271              :          one access of size DR_B.access_size at DR_B.dr
     272              :          one access of size DR_A.access_size at DR_A.dr + STEP_A
     273              :          one access of size DR_B.access_size at DR_B.dr + STEP_B
     274              :          one access of size DR_A.access_size at DR_A.dr + STEP_A * 2
     275              :          one access of size DR_B.access_size at DR_B.dr + STEP_B * 2
     276              :          ...
     277              : 
     278              :    (2) The new code accesses the same data in exactly two chunks:
     279              : 
     280              :          one group of accesses spanning |DR_A.seg_len| + DR_A.access_size
     281              :          one group of accesses spanning |DR_B.seg_len| + DR_B.access_size
     282              : 
     283              :    A pair might break this assumption if the DR_A and DR_B accesses
     284              :    in the original or the new code are mingled in some way.  For example,
     285              :    if DR_A.access_size represents the effect of two individual writes
     286              :    to nearby locations, the pair breaks the assumption if those writes
     287              :    occur either side of the access for DR_B.
     288              : 
     289              :    Note that DR_ALIAS_ARBITRARY describes whether the ordering assumption
     290              :    fails to hold for any individual pair in P.  If the assumption *does*
     291              :    hold for every pair in P, it doesn't matter whether it holds for the
     292              :    composite pair or not.  In other words, P should represent the complete
     293              :    set of pairs that the composite pair is testing, so only the ordering
     294              :    of two accesses in the same member of P matters.  */
     295              : const unsigned int DR_ALIAS_RAW = 1U << 0;
     296              : const unsigned int DR_ALIAS_WAR = 1U << 1;
     297              : const unsigned int DR_ALIAS_WAW = 1U << 2;
     298              : const unsigned int DR_ALIAS_ARBITRARY = 1U << 3;
     299              : const unsigned int DR_ALIAS_SWAPPED = 1U << 4;
     300              : const unsigned int DR_ALIAS_UNSWAPPED = 1U << 5;
     301              : const unsigned int DR_ALIAS_MIXED_STEPS = 1U << 6;
     302              : 
     303              : /* This struct contains two dr_with_seg_len objects with aliasing data
     304              :    refs.  Two comparisons are generated from them.  */
     305              : 
     306              : class dr_with_seg_len_pair_t
     307              : {
     308              : public:
     309              :   /* WELL_ORDERED indicates that the ordering assumption described above
     310              :      DR_ALIAS_ARBITRARY holds.  REORDERED indicates that it doesn't.  */
     311              :   enum sequencing { WELL_ORDERED, REORDERED };
     312              : 
     313              :   dr_with_seg_len_pair_t (const dr_with_seg_len &,
     314              :                           const dr_with_seg_len &, sequencing);
     315              : 
     316              :   dr_with_seg_len first;
     317              :   dr_with_seg_len second;
     318              :   unsigned int flags;
     319              : };
     320              : 
     321        58428 : inline dr_with_seg_len_pair_t::
     322              : dr_with_seg_len_pair_t (const dr_with_seg_len &d1, const dr_with_seg_len &d2,
     323        58428 :                         sequencing seq)
     324        58428 :   : first (d1), second (d2), flags (0)
     325              : {
     326        58428 :   if (DR_IS_READ (d1.dr) && DR_IS_WRITE (d2.dr))
     327        33521 :     flags |= DR_ALIAS_WAR;
     328        24907 :   else if (DR_IS_WRITE (d1.dr) && DR_IS_READ (d2.dr))
     329         6944 :     flags |= DR_ALIAS_RAW;
     330        17963 :   else if (DR_IS_WRITE (d1.dr) && DR_IS_WRITE (d2.dr))
     331        17963 :     flags |= DR_ALIAS_WAW;
     332              :   else
     333            0 :     gcc_unreachable ();
     334        58428 :   if (seq == REORDERED)
     335         6194 :     flags |= DR_ALIAS_ARBITRARY;
     336        58428 : }
     337              : 
     338              : enum data_dependence_direction {
     339              :   dir_positive,
     340              :   dir_negative,
     341              :   dir_equal,
     342              :   dir_positive_or_negative,
     343              :   dir_positive_or_equal,
     344              :   dir_negative_or_equal,
     345              :   dir_star,
     346              :   dir_independent
     347              : };
     348              : 
     349              : /* The description of the grid of iterations that overlap.  At most
     350              :    two loops are considered at the same time just now, hence at most
     351              :    two functions are needed.  For each of the functions, we store
     352              :    the vector of coefficients, f[0] + x * f[1] + y * f[2] + ...,
     353              :    where x, y, ... are variables.  */
     354              : 
     355              : #define MAX_DIM 2
     356              : 
     357              : /* Special values of N.  */
     358              : #define NO_DEPENDENCE 0
     359              : #define NOT_KNOWN (MAX_DIM + 1)
     360              : #define CF_NONTRIVIAL_P(CF) ((CF)->n != NO_DEPENDENCE && (CF)->n != NOT_KNOWN)
     361              : #define CF_NOT_KNOWN_P(CF) ((CF)->n == NOT_KNOWN)
     362              : #define CF_NO_DEPENDENCE_P(CF) ((CF)->n == NO_DEPENDENCE)
     363              : 
     364              : typedef vec<tree> affine_fn;
     365              : 
     366              : struct conflict_function
     367              : {
     368              :   unsigned n;
     369              :   affine_fn fns[MAX_DIM];
     370              : };
     371              : 
     372              : /* What is a subscript?  Given two array accesses a subscript is the
     373              :    tuple composed of the access functions for a given dimension.
     374              :    Example: Given A[f1][f2][f3] and B[g1][g2][g3], there are three
     375              :    subscripts: (f1, g1), (f2, g2), (f3, g3).  These three subscripts
     376              :    are stored in the data_dependence_relation structure under the form
     377              :    of an array of subscripts.  */
     378              : 
     379              : struct subscript
     380              : {
     381              :   /* The access functions of the two references.  */
     382              :   tree access_fn[2];
     383              : 
     384              :   /* A description of the iterations for which the elements are
     385              :      accessed twice.  */
     386              :   conflict_function *conflicting_iterations_in_a;
     387              :   conflict_function *conflicting_iterations_in_b;
     388              : 
     389              :   /* This field stores the information about the iteration domain
     390              :      validity of the dependence relation.  */
     391              :   tree last_conflict;
     392              : 
     393              :   /* Distance from the iteration that access a conflicting element in
     394              :      A to the iteration that access this same conflicting element in
     395              :      B.  The distance is a tree scalar expression, i.e. a constant or a
     396              :      symbolic expression, but certainly not a chrec function.  */
     397              :   tree distance;
     398              : };
     399              : 
     400              : typedef struct subscript *subscript_p;
     401              : 
     402              : #define SUB_ACCESS_FN(SUB, I) (SUB)->access_fn[I]
     403              : #define SUB_CONFLICTS_IN_A(SUB) (SUB)->conflicting_iterations_in_a
     404              : #define SUB_CONFLICTS_IN_B(SUB) (SUB)->conflicting_iterations_in_b
     405              : #define SUB_LAST_CONFLICT(SUB) (SUB)->last_conflict
     406              : #define SUB_DISTANCE(SUB) (SUB)->distance
     407              : 
     408              : /* A data_dependence_relation represents a relation between two
     409              :    data_references A and B.  */
     410              : 
     411              : struct data_dependence_relation
     412              : {
     413              : 
     414              :   struct data_reference *a;
     415              :   struct data_reference *b;
     416              : 
     417              :   /* A "yes/no/maybe" field for the dependence relation:
     418              : 
     419              :      - when "ARE_DEPENDENT == NULL_TREE", there exist a dependence
     420              :        relation between A and B, and the description of this relation
     421              :        is given in the SUBSCRIPTS array,
     422              : 
     423              :      - when "ARE_DEPENDENT == chrec_known", there is no dependence and
     424              :        SUBSCRIPTS is empty,
     425              : 
     426              :      - when "ARE_DEPENDENT == chrec_dont_know", there may be a dependence,
     427              :        but the analyzer cannot be more specific.  */
     428              :   tree are_dependent;
     429              : 
     430              :   /* If nonnull, COULD_BE_INDEPENDENT_P is true and the accesses are
     431              :      independent when the runtime addresses of OBJECT_A and OBJECT_B
     432              :      are different.  The addresses of both objects are invariant in the
     433              :      loop nest.  */
     434              :   tree object_a;
     435              :   tree object_b;
     436              : 
     437              :   /* For each subscript in the dependence test, there is an element in
     438              :      this array.  This is the attribute that labels the edge A->B of
     439              :      the data_dependence_relation.  */
     440              :   vec<subscript_p> subscripts;
     441              : 
     442              :   /* The analyzed loop nest.  */
     443              :   vec<loop_p> loop_nest;
     444              : 
     445              :   /* The classic direction vector.  */
     446              :   vec<lambda_vector> dir_vects;
     447              : 
     448              :   /* The classic distance vector.  */
     449              :   vec<lambda_vector> dist_vects;
     450              : 
     451              :   /* Is the dependence reversed with respect to the lexicographic order?  */
     452              :   bool reversed_p;
     453              : 
     454              :   /* When the dependence relation is affine, it can be represented by
     455              :      a distance vector.  */
     456              :   bool affine_p;
     457              : 
     458              :   /* Set to true when the dependence relation is on the same data
     459              :      access.  */
     460              :   bool self_reference_p;
     461              : 
     462              :   /* True if the dependence described is conservatively correct rather
     463              :      than exact, and if it is still possible for the accesses to be
     464              :      conditionally independent.  For example, the a and b references in:
     465              : 
     466              :        struct s *a, *b;
     467              :        for (int i = 0; i < n; ++i)
     468              :          a->f[i] += b->f[i];
     469              : 
     470              :      conservatively have a distance vector of (0), for the case in which
     471              :      a == b, but the accesses are independent if a != b.  Similarly,
     472              :      the a and b references in:
     473              : 
     474              :        struct s *a, *b;
     475              :        for (int i = 0; i < n; ++i)
     476              :          a[0].f[i] += b[i].f[i];
     477              : 
     478              :      conservatively have a distance vector of (0), but they are indepenent
     479              :      when a != b + i.  In contrast, the references in:
     480              : 
     481              :        struct s *a;
     482              :        for (int i = 0; i < n; ++i)
     483              :          a->f[i] += a->f[i];
     484              : 
     485              :      have the same distance vector of (0), but the accesses can never be
     486              :      independent.  */
     487              :   bool could_be_independent_p;
     488              : };
     489              : 
     490              : typedef struct data_dependence_relation *ddr_p;
     491              : 
     492              : #define DDR_A(DDR) (DDR)->a
     493              : #define DDR_B(DDR) (DDR)->b
     494              : #define DDR_AFFINE_P(DDR) (DDR)->affine_p
     495              : #define DDR_ARE_DEPENDENT(DDR) (DDR)->are_dependent
     496              : #define DDR_OBJECT_A(DDR) (DDR)->object_a
     497              : #define DDR_OBJECT_B(DDR) (DDR)->object_b
     498              : #define DDR_SUBSCRIPTS(DDR) (DDR)->subscripts
     499              : #define DDR_SUBSCRIPT(DDR, I) DDR_SUBSCRIPTS (DDR)[I]
     500              : #define DDR_NUM_SUBSCRIPTS(DDR) DDR_SUBSCRIPTS (DDR).length ()
     501              : 
     502              : #define DDR_LOOP_NEST(DDR) (DDR)->loop_nest
     503              : /* The size of the direction/distance vectors: the number of loops in
     504              :    the loop nest.  */
     505              : #define DDR_NB_LOOPS(DDR) (DDR_LOOP_NEST (DDR).length ())
     506              : #define DDR_SELF_REFERENCE(DDR) (DDR)->self_reference_p
     507              : 
     508              : #define DDR_DIST_VECTS(DDR) ((DDR)->dist_vects)
     509              : #define DDR_DIR_VECTS(DDR) ((DDR)->dir_vects)
     510              : #define DDR_NUM_DIST_VECTS(DDR) \
     511              :   (DDR_DIST_VECTS (DDR).length ())
     512              : #define DDR_NUM_DIR_VECTS(DDR) \
     513              :   (DDR_DIR_VECTS (DDR).length ())
     514              : #define DDR_DIR_VECT(DDR, I) \
     515              :   DDR_DIR_VECTS (DDR)[I]
     516              : #define DDR_DIST_VECT(DDR, I) \
     517              :   DDR_DIST_VECTS (DDR)[I]
     518              : #define DDR_REVERSED_P(DDR) (DDR)->reversed_p
     519              : #define DDR_COULD_BE_INDEPENDENT_P(DDR) (DDR)->could_be_independent_p
     520              : 
     521              : 
     522              : opt_result dr_analyze_innermost (innermost_loop_behavior *, tree,
     523              :                                  class loop *, const gimple *);
     524              : extern bool compute_data_dependences_for_loop (class loop *, bool,
     525              :                                                vec<loop_p> *,
     526              :                                                vec<data_reference_p> *,
     527              :                                                vec<ddr_p> *);
     528              : extern void debug_ddrs (vec<ddr_p> );
     529              : extern void dump_data_reference (FILE *, struct data_reference *);
     530              : extern void debug (data_reference &ref);
     531              : extern void debug (data_reference *ptr);
     532              : extern void debug_data_reference (struct data_reference *);
     533              : extern void debug_data_references (vec<data_reference_p> );
     534              : extern void debug (vec<data_reference_p> &ref);
     535              : extern void debug (vec<data_reference_p> *ptr);
     536              : extern void debug_data_dependence_relation (const data_dependence_relation *);
     537              : extern void dump_data_dependence_relations (FILE *, const vec<ddr_p> &);
     538              : extern void debug (vec<ddr_p> &ref);
     539              : extern void debug (vec<ddr_p> *ptr);
     540              : extern void debug_data_dependence_relations (vec<ddr_p> );
     541              : extern void free_dependence_relation (struct data_dependence_relation *);
     542              : extern void free_dependence_relations (vec<ddr_p>& );
     543              : extern void free_data_ref (data_reference_p);
     544              : extern void free_data_refs (vec<data_reference_p>& );
     545              : extern opt_result find_data_references_in_stmt (class loop *, gimple *,
     546              :                                                 vec<data_reference_p> *);
     547              : extern bool graphite_find_data_references_in_stmt (edge, loop_p, gimple *,
     548              :                                                    vec<data_reference_p> *);
     549              : tree find_data_references_in_loop (class loop *, vec<data_reference_p> *);
     550              : bool loop_nest_has_data_refs (loop_p loop);
     551              : struct data_reference *create_data_ref (edge, loop_p, tree, gimple *, bool,
     552              :                                         bool);
     553              : extern bool find_loop_nest (class loop *, vec<loop_p> *);
     554              : extern struct data_dependence_relation *initialize_data_dependence_relation
     555              :      (struct data_reference *, struct data_reference *, vec<loop_p>);
     556              : extern void compute_affine_dependence (struct data_dependence_relation *,
     557              :                                        loop_p);
     558              : extern void compute_self_dependence (struct data_dependence_relation *);
     559              : extern bool compute_all_dependences (const vec<data_reference_p> &,
     560              :                                      vec<ddr_p> *,
     561              :                                      const vec<loop_p> &, bool);
     562              : extern tree find_data_references_in_bb (class loop *, basic_block,
     563              :                                         vec<data_reference_p> *);
     564              : extern unsigned int dr_alignment (innermost_loop_behavior *);
     565              : extern tree get_base_for_alignment (tree, unsigned int *);
     566              : 
     567              : /* Return the alignment in bytes that DR is guaranteed to have at all
     568              :    times.  */
     569              : 
     570              : inline unsigned int
     571       123952 : dr_alignment (data_reference *dr)
     572              : {
     573        61976 :   return dr_alignment (&DR_INNERMOST (dr));
     574              : }
     575              : 
     576              : extern bool dr_may_alias_p (const struct data_reference *,
     577              :                             const struct data_reference *, class loop *);
     578              : extern bool dr_equal_offsets_p (struct data_reference *,
     579              :                                 struct data_reference *);
     580              : 
     581              : extern opt_result runtime_alias_check_p (ddr_p, class loop *, bool);
     582              : extern int data_ref_compare_tree (tree, tree);
     583              : extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *,
     584              :                                            poly_uint64);
     585              : extern void create_runtime_alias_checks (class loop *,
     586              :                                          const vec<dr_with_seg_len_pair_t> *,
     587              :                                          tree*);
     588              : extern tree dr_direction_indicator (struct data_reference *);
     589              : extern tree dr_zero_step_indicator (struct data_reference *);
     590              : extern bool dr_known_forward_stride_p (struct data_reference *);
     591              : 
     592              : /* Return true when the base objects of data references A and B are
     593              :    the same memory object.  */
     594              : 
     595              : inline bool
     596         2700 : same_data_refs_base_objects (data_reference_p a, data_reference_p b)
     597              : {
     598         5337 :   return DR_NUM_DIMENSIONS (a) == DR_NUM_DIMENSIONS (b)
     599         2700 :     && operand_equal_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b), 0);
     600              : }
     601              : 
     602              : /* Return true when the data references A and B are accessing the same
     603              :    memory object with the same access functions.  Optionally skip the
     604              :    last OFFSET dimensions in the data reference.  */
     605              : 
     606              : inline bool
     607         7701 : same_data_refs (data_reference_p a, data_reference_p b, int offset = 0)
     608              : {
     609         7701 :   unsigned int i;
     610              : 
     611              :   /* The references are exactly the same.  */
     612         7701 :   if (operand_equal_p (DR_REF (a), DR_REF (b), 0))
     613              :     return true;
     614              : 
     615         2700 :   if (!same_data_refs_base_objects (a, b))
     616              :     return false;
     617              : 
     618          115 :   for (i = offset; i < DR_NUM_DIMENSIONS (a); i++)
     619           57 :     if (!eq_evolutions_p (DR_ACCESS_FN (a, i), DR_ACCESS_FN (b, i)))
     620              :       return false;
     621              : 
     622              :   return true;
     623              : }
     624              : 
     625              : /* Returns true when all the dependences are computable.  */
     626              : 
     627              : inline bool
     628              : known_dependences_p (vec<ddr_p> dependence_relations)
     629              : {
     630              :   ddr_p ddr;
     631              :   unsigned int i;
     632              : 
     633              :   FOR_EACH_VEC_ELT (dependence_relations, i, ddr)
     634              :     if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
     635              :       return false;
     636              : 
     637              :   return true;
     638              : }
     639              : 
     640              : /* Returns the dependence level for a vector DIST of size LENGTH.
     641              :    LEVEL = 0 means a lexicographic dependence, i.e. a dependence due
     642              :    to the sequence of statements, not carried by any loop.  */
     643              : 
     644              : inline unsigned
     645          159 : dependence_level (lambda_vector dist_vect, int length)
     646              : {
     647          159 :   int i;
     648              : 
     649         1412 :   for (i = 0; i < length; i++)
     650         1098 :     if (dist_vect[i] != 0)
     651          639 :       return i + 1;
     652              : 
     653              :   return 0;
     654              : }
     655              : 
     656              : /* Return the dependence level for the DDR relation.  */
     657              : 
     658              : inline unsigned
     659              : ddr_dependence_level (ddr_p ddr)
     660              : {
     661              :   unsigned vector;
     662              :   unsigned level = 0;
     663              : 
     664              :   if (DDR_DIST_VECTS (ddr).exists ())
     665              :     level = dependence_level (DDR_DIST_VECT (ddr, 0), DDR_NB_LOOPS (ddr));
     666              : 
     667              :   for (vector = 1; vector < DDR_NUM_DIST_VECTS (ddr); vector++)
     668              :     level = MIN (level, dependence_level (DDR_DIST_VECT (ddr, vector),
     669              :                                           DDR_NB_LOOPS (ddr)));
     670              :   return level;
     671              : }
     672              : 
     673              : /* Return the index of the variable VAR in the LOOP_NEST array.  */
     674              : 
     675              : inline int
     676       158138 : index_in_loop_nest (int var, const vec<loop_p> &loop_nest)
     677              : {
     678       158138 :   class loop *loopi;
     679       158138 :   int var_index;
     680              : 
     681       163813 :   for (var_index = 0; loop_nest.iterate (var_index, &loopi); var_index++)
     682       163813 :     if (loopi->num == var)
     683       158138 :       return var_index;
     684              : 
     685            0 :   gcc_unreachable ();
     686              : }
     687              : 
     688              : /* Returns true when the data reference DR the form "A[i] = ..."
     689              :    with a stride equal to its unit type size.  */
     690              : 
     691              : inline bool
     692              : adjacent_dr_p (struct data_reference *dr)
     693              : {
     694              :   /* If this is a bitfield store bail out.  */
     695              :   if (TREE_CODE (DR_REF (dr)) == COMPONENT_REF
     696              :       && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1)))
     697              :     return false;
     698              : 
     699              :   if (!DR_STEP (dr)
     700              :       || TREE_CODE (DR_STEP (dr)) != INTEGER_CST)
     701              :     return false;
     702              : 
     703              :   return tree_int_cst_equal (fold_unary (ABS_EXPR, TREE_TYPE (DR_STEP (dr)),
     704              :                                          DR_STEP (dr)),
     705              :                              TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
     706              : }
     707              : 
     708              : void split_constant_offset (tree , tree *, tree *);
     709              : 
     710              : /* Compute the greatest common divisor of a VECTOR of SIZE numbers.  */
     711              : 
     712              : inline lambda_int
     713              : lambda_vector_gcd (lambda_vector vector, int size)
     714              : {
     715              :   int i;
     716              :   lambda_int gcd1 = 0;
     717              : 
     718              :   if (size > 0)
     719              :     {
     720              :       gcd1 = vector[0];
     721              :       for (i = 1; i < size; i++)
     722              :         gcd1 = gcd (gcd1, vector[i]);
     723              :     }
     724              :   return gcd1;
     725              : }
     726              : 
     727              : /* Allocate a new vector of given SIZE.  */
     728              : 
     729              : inline lambda_vector
     730      2265998 : lambda_vector_new (int size)
     731              : {
     732              :   /* ???  We shouldn't abuse the GC allocator here.  */
     733      2265998 :   return ggc_cleared_vec_alloc<lambda_int> (size);
     734              : }
     735              : 
     736              : /* Clear out vector VEC1 of length SIZE.  */
     737              : 
     738              : inline void
     739          638 : lambda_vector_clear (lambda_vector vec1, int size)
     740              : {
     741          638 :   memset (vec1, 0, size * sizeof (*vec1));
     742            0 : }
     743              : 
     744              : /* Returns true when the vector V is lexicographically positive, in
     745              :    other words, when the first nonzero element is positive.  */
     746              : 
     747              : inline bool
     748        51838 : lambda_vector_lexico_pos (lambda_vector v,
     749              :                           unsigned n)
     750              : {
     751        51838 :   unsigned i;
     752        52588 :   for (i = 0; i < n; i++)
     753              :     {
     754        51958 :       if (v[i] == 0)
     755          686 :         continue;
     756        51272 :       if (v[i] < 0)
     757              :         return false;
     758              :       if (v[i] > 0)
     759              :         return true;
     760              :     }
     761              :   return true;
     762              : }
     763              : 
     764              : /* Return true if vector VEC1 of length SIZE is the zero vector.  */
     765              : 
     766              : inline bool
     767        42559 : lambda_vector_zerop (lambda_vector vec1, int size)
     768              : {
     769        42559 :   int i;
     770        89957 :   for (i = 0; i < size; i++)
     771        53082 :     if (vec1[i] != 0)
     772              :       return false;
     773              :   return true;
     774              : }
     775              : 
     776              : /* Allocate a matrix of M rows x  N cols.  */
     777              : 
     778              : inline lambda_matrix
     779      5062717 : lambda_matrix_new (int m, int n, struct obstack *lambda_obstack)
     780              : {
     781      5062717 :   lambda_matrix mat;
     782      5062717 :   int i;
     783              : 
     784      5062717 :   mat = XOBNEWVEC (lambda_obstack, lambda_vector, m);
     785              : 
     786     15187376 :   for (i = 0; i < m; i++)
     787     10124659 :     mat[i] = XOBNEWVEC (lambda_obstack, lambda_int, n);
     788              : 
     789      5062717 :   return mat;
     790              : }
     791              : 
     792              : #endif  /* GCC_TREE_DATA_REF_H  */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.