LCOV - code coverage report
Current view: top level - gcc - tree-affine.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.2 % 529 472
Test Date: 2026-02-28 14:20:25 Functions: 93.1 % 29 27
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Operations with affine combinations of trees.
       2              :    Copyright (C) 2005-2026 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 it
       7              : 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.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT
      12              : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "backend.h"
      24              : #include "rtl.h"
      25              : #include "tree.h"
      26              : #include "gimple.h"
      27              : #include "ssa.h"
      28              : #include "tree-pretty-print.h"
      29              : #include "fold-const.h"
      30              : #include "tree-affine.h"
      31              : #include "gimplify.h"
      32              : #include "dumpfile.h"
      33              : #include "cfgexpand.h"
      34              : #include "value-query.h"
      35              : 
      36              : /* Extends CST as appropriate for the affine combinations COMB.  */
      37              : 
      38              : static widest_int
      39    142597225 : wide_int_ext_for_comb (const widest_int &cst, tree type)
      40              : {
      41    142597225 :   return wi::sext (cst, TYPE_PRECISION (type));
      42              : }
      43              : 
      44              : /* Likewise for polynomial offsets.  */
      45              : 
      46              : static poly_widest_int
      47    206528490 : wide_int_ext_for_comb (const poly_widest_int &cst, tree type)
      48              : {
      49    206528490 :   return wi::sext (cst, TYPE_PRECISION (type));
      50              : }
      51              : 
      52              : /* Initializes affine combination COMB so that its value is zero in TYPE.  */
      53              : 
      54              : static void
      55    169815186 : aff_combination_zero (aff_tree *comb, tree type)
      56              : {
      57    169815186 :   int i;
      58    169815186 :   comb->type = type;
      59    169815186 :   comb->offset = 0;
      60    169815186 :   comb->n = 0;
      61   1528336674 :   for (i = 0; i < MAX_AFF_ELTS; i++)
      62   1358521488 :     comb->elts[i].coef = 0;
      63    169815186 :   comb->rest = NULL_TREE;
      64    169815186 : }
      65              : 
      66              : /* Sets COMB to CST.  */
      67              : 
      68              : void
      69     87901782 : aff_combination_const (aff_tree *comb, tree type, const poly_widest_int &cst)
      70              : {
      71     87901782 :   aff_combination_zero (comb, type);
      72     87901782 :   comb->offset = wide_int_ext_for_comb (cst, comb->type);;
      73     87901782 : }
      74              : 
      75              : /* Sets COMB to single element ELT.  */
      76              : 
      77              : void
      78     42354035 : aff_combination_elt (aff_tree *comb, tree type, tree elt)
      79              : {
      80     42354035 :   aff_combination_zero (comb, type);
      81              : 
      82     42354035 :   comb->n = 1;
      83     42354035 :   comb->elts[0].val = elt;
      84     42354035 :   comb->elts[0].coef = 1;
      85     42354035 : }
      86              : 
      87              : /* Scales COMB by SCALE.  */
      88              : 
      89              : void
      90     38939375 : aff_combination_scale (aff_tree *comb, const widest_int &scale_in)
      91              : {
      92     38939375 :   unsigned i, j;
      93              : 
      94     38939375 :   widest_int scale = wide_int_ext_for_comb (scale_in, comb->type);
      95     38939375 :   if (scale == 1)
      96              :     return;
      97              : 
      98     28352364 :   if (scale == 0)
      99              :     {
     100          148 :       aff_combination_zero (comb, comb->type);
     101          148 :       return;
     102              :     }
     103              : 
     104     28352216 :   comb->offset = wide_int_ext_for_comb (scale * comb->offset, comb->type);
     105     51527586 :   for (i = 0, j = 0; i < comb->n; i++)
     106              :     {
     107     23175370 :       widest_int new_coef
     108     23175370 :         = wide_int_ext_for_comb (scale * comb->elts[i].coef, comb->type);
     109              :       /* A coefficient may become zero due to overflow.  Remove the zero
     110              :          elements.  */
     111     23175370 :       if (new_coef == 0)
     112            2 :         continue;
     113     23175368 :       comb->elts[j].coef = new_coef;
     114     23175368 :       comb->elts[j].val = comb->elts[i].val;
     115     23175368 :       j++;
     116     23175370 :     }
     117     28352216 :   comb->n = j;
     118              : 
     119     28352216 :   if (comb->rest)
     120              :     {
     121          138 :       tree type = comb->type;
     122          138 :       if (POINTER_TYPE_P (type))
     123          105 :         type = sizetype;
     124          138 :       if (comb->n < MAX_AFF_ELTS)
     125              :         {
     126            0 :           comb->elts[comb->n].coef = scale;
     127            0 :           comb->elts[comb->n].val = comb->rest;
     128            0 :           comb->rest = NULL_TREE;
     129            0 :           comb->n++;
     130              :         }
     131              :       else
     132          138 :         comb->rest = fold_build2 (MULT_EXPR, type, comb->rest,
     133              :                                   wide_int_to_tree (type, scale));
     134              :     }
     135     38939375 : }
     136              : 
     137              : /* Adds ELT * SCALE to COMB.  */
     138              : 
     139              : void
     140     31596502 : aff_combination_add_elt (aff_tree *comb, tree elt, const widest_int &scale_in)
     141              : {
     142     31596502 :   unsigned i;
     143     31596502 :   tree type;
     144              : 
     145     31596502 :   widest_int scale = wide_int_ext_for_comb (scale_in, comb->type);
     146     31596502 :   if (scale == 0)
     147              :     return;
     148              : 
     149     44881678 :   for (i = 0; i < comb->n; i++)
     150     21793182 :     if (operand_equal_p (comb->elts[i].val, elt, 0))
     151              :       {
     152      8508006 :         widest_int new_coef
     153      8508006 :           = wide_int_ext_for_comb (comb->elts[i].coef + scale, comb->type);
     154      8508006 :         if (new_coef != 0)
     155              :           {
     156       120762 :             comb->elts[i].coef = new_coef;
     157       120762 :             return;
     158              :           }
     159              : 
     160      8387244 :         comb->n--;
     161      8387244 :         comb->elts[i] = comb->elts[comb->n];
     162              : 
     163      8387244 :         if (comb->rest)
     164              :           {
     165          166 :             gcc_assert (comb->n == MAX_AFF_ELTS - 1);
     166          166 :             comb->elts[comb->n].coef = 1;
     167          166 :             comb->elts[comb->n].val = comb->rest;
     168          166 :             comb->rest = NULL_TREE;
     169          166 :             comb->n++;
     170              :           }
     171      8387244 :         return;
     172      8508006 :       }
     173     23088496 :   if (comb->n < MAX_AFF_ELTS)
     174              :     {
     175     23087939 :       comb->elts[comb->n].coef = scale;
     176     23087939 :       comb->elts[comb->n].val = elt;
     177     23087939 :       comb->n++;
     178     23087939 :       return;
     179              :     }
     180              : 
     181          557 :   type = comb->type;
     182          557 :   if (POINTER_TYPE_P (type))
     183          274 :     type = sizetype;
     184              : 
     185          557 :   if (scale == 1)
     186          420 :     elt = fold_convert (type, elt);
     187              :   else
     188          137 :     elt = fold_build2 (MULT_EXPR, type,
     189              :                        fold_convert (type, elt),
     190              :                        wide_int_to_tree (type, scale));
     191              : 
     192          557 :   if (comb->rest)
     193           14 :     comb->rest = fold_build2 (PLUS_EXPR, type, comb->rest,
     194              :                               elt);
     195              :   else
     196          543 :     comb->rest = elt;
     197     31596502 : }
     198              : 
     199              : /* Adds CST to C.  */
     200              : 
     201              : static void
     202     90149636 : aff_combination_add_cst (aff_tree *c, const poly_widest_int &cst)
     203              : {
     204     90149636 :   c->offset = wide_int_ext_for_comb (c->offset + cst, c->type);
     205     90149636 : }
     206              : 
     207              : /* Adds COMB2 to COMB1.  */
     208              : 
     209              : void
     210     86100441 : aff_combination_add (aff_tree *comb1, aff_tree *comb2)
     211              : {
     212     86100441 :   unsigned i;
     213              : 
     214     86100441 :   aff_combination_add_cst (comb1, comb2->offset);
     215    192803503 :   for (i = 0; i < comb2->n; i++)
     216     20602621 :     aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
     217     86100441 :   if (comb2->rest)
     218          138 :     aff_combination_add_elt (comb1, comb2->rest, 1);
     219     86100441 : }
     220              : 
     221              : /* Converts affine combination COMB to TYPE.  */
     222              : 
     223              : void
     224     28439742 : aff_combination_convert (aff_tree *comb, tree type)
     225              : {
     226     28439742 :   unsigned i, j;
     227     28439742 :   tree comb_type = comb->type;
     228              : 
     229     28439742 :   if  (TYPE_PRECISION (type) > TYPE_PRECISION (comb_type))
     230              :     {
     231       854232 :       tree val = fold_convert (type, aff_combination_to_tree (comb));
     232       854232 :       tree_to_aff_combination (val, type, comb);
     233       854232 :       return;
     234              :     }
     235              : 
     236     27585510 :   comb->type = type;
     237     27585510 :   if (comb->rest && !POINTER_TYPE_P (type))
     238          170 :     comb->rest = fold_convert (type, comb->rest);
     239              : 
     240     27585510 :   if (TYPE_PRECISION (type) == TYPE_PRECISION (comb_type))
     241              :     return;
     242              : 
     243       124856 :   comb->offset = wide_int_ext_for_comb (comb->offset, comb->type);
     244       162424 :   for (i = j = 0; i < comb->n; i++)
     245              :     {
     246        37568 :       if (comb->elts[i].coef == 0)
     247            0 :         continue;
     248        37568 :       comb->elts[j].coef = comb->elts[i].coef;
     249        37568 :       comb->elts[j].val = fold_convert (type, comb->elts[i].val);
     250        37568 :       j++;
     251              :     }
     252              : 
     253       124856 :   comb->n = j;
     254       124856 :   if (comb->n < MAX_AFF_ELTS && comb->rest)
     255              :     {
     256            0 :       comb->elts[comb->n].coef = 1;
     257            0 :       comb->elts[comb->n].val = comb->rest;
     258            0 :       comb->rest = NULL_TREE;
     259            0 :       comb->n++;
     260              :     }
     261              : }
     262              : 
     263              : /* Tries to handle OP0 CODE OP1 as affine combination of parts.  Returns
     264              :    true when that was successful and returns the combination in COMB.  */
     265              : 
     266              : static bool
     267     24454632 : expr_to_aff_combination (aff_tree *comb, tree_code code, tree type,
     268              :                          tree op0, tree op1 = NULL_TREE)
     269              : {
     270     24454632 :   aff_tree tmp;
     271              : 
     272     24454632 :   switch (code)
     273              :     {
     274       372955 :     case POINTER_PLUS_EXPR:
     275       372955 :       tree_to_aff_combination (op0, type, comb);
     276       372955 :       tree_to_aff_combination (op1, sizetype, &tmp);
     277       372955 :       aff_combination_add (comb, &tmp);
     278       372955 :       return true;
     279              : 
     280     13948772 :     case PLUS_EXPR:
     281     13948772 :     case MINUS_EXPR:
     282     13948772 :       tree_to_aff_combination (op0, type, comb);
     283     13948772 :       tree_to_aff_combination (op1, type, &tmp);
     284     13948772 :       if (code == MINUS_EXPR)
     285       594791 :         aff_combination_scale (&tmp, -1);
     286     13948772 :       aff_combination_add (comb, &tmp);
     287     13948772 :       return true;
     288              : 
     289      6953318 :     case MULT_EXPR:
     290      6953318 :       if (TREE_CODE (op1) != INTEGER_CST)
     291              :         break;
     292      6031119 :       tree_to_aff_combination (op0, type, comb);
     293      6031119 :       aff_combination_scale (comb, wi::to_widest (op1));
     294      6031119 :       return true;
     295              : 
     296       101389 :     case NEGATE_EXPR:
     297       101389 :       tree_to_aff_combination (op0, type, comb);
     298       101389 :       aff_combination_scale (comb, -1);
     299       101389 :       return true;
     300              : 
     301         8356 :     case BIT_NOT_EXPR:
     302              :       /* ~x = -x - 1 */
     303         8356 :       tree_to_aff_combination (op0, type, comb);
     304         8356 :       aff_combination_scale (comb, -1);
     305         8356 :       aff_combination_add_cst (comb, -1);
     306         8356 :       return true;
     307              : 
     308      3069842 :     CASE_CONVERT:
     309      3069842 :       {
     310      3069842 :         tree otype = type;
     311      3069842 :         tree inner = op0;
     312      3069842 :         tree itype = TREE_TYPE (inner);
     313      3069842 :         enum tree_code icode = TREE_CODE (inner);
     314              : 
     315              :         /* STRIP_NOPS  */
     316      3069842 :         if (tree_nop_conversion_p (otype, itype))
     317              :           {
     318        13126 :             tree_to_aff_combination (op0, type, comb);
     319        13126 :             return true;
     320              :           }
     321              : 
     322              :         /* In principle this is a valid folding, but it isn't necessarily
     323              :            an optimization, so do it here and not in fold_unary.  */
     324      3056716 :         if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR)
     325       231777 :             && TREE_CODE (itype) == INTEGER_TYPE
     326       231777 :             && TREE_CODE (otype) == INTEGER_TYPE
     327      3288489 :             && TYPE_PRECISION (otype) > TYPE_PRECISION (itype))
     328              :           {
     329       178701 :             tree op0 = TREE_OPERAND (inner, 0), op1 = TREE_OPERAND (inner, 1);
     330              : 
     331              :             /* If inner type has undefined overflow behavior, fold conversion
     332              :                for below two cases:
     333              :                  (T1)(X *+- CST) -> (T1)X *+- (T1)CST
     334              :                  (T1)(X + X)     -> (T1)X + (T1)X.  */
     335       178701 :             if (TYPE_OVERFLOW_UNDEFINED (itype)
     336        81832 :                 && (TREE_CODE (op1) == INTEGER_CST
     337         3821 :                     || (icode == PLUS_EXPR && operand_equal_p (op0, op1, 0))))
     338              :               {
     339        78011 :                 op0 = fold_convert (otype, op0);
     340        78011 :                 op1 = fold_convert (otype, op1);
     341        83476 :                 return expr_to_aff_combination (comb, icode, otype, op0, op1);
     342              :               }
     343       100690 :             wide_int minv, maxv;
     344              :             /* If inner type has wrapping overflow behavior, fold conversion
     345              :                for below case:
     346              :                  (T1)(X *+- CST) -> (T1)X *+- (T1)CST
     347              :                if X *+- CST doesn't overflow by range information.  */
     348       100690 :             int_range_max vr;
     349       100690 :             if (TYPE_UNSIGNED (itype)
     350        96647 :                 && TYPE_OVERFLOW_WRAPS (itype)
     351        96647 :                 && TREE_CODE (op1) == INTEGER_CST
     352       143612 :                 && get_range_query (cfun)->range_of_expr (vr, op0)
     353        71806 :                 && !vr.varying_p ()
     354       116990 :                 && !vr.undefined_p ())
     355              :               {
     356        16286 :                 wide_int minv = vr.lower_bound ();
     357        16286 :                 wide_int maxv = vr.upper_bound ();
     358        16286 :                 wi::overflow_type overflow = wi::OVF_NONE;
     359        16286 :                 signop sign = UNSIGNED;
     360        16286 :                 if (icode == PLUS_EXPR)
     361        12423 :                   wi::add (maxv, wi::to_wide (op1), sign, &overflow);
     362         3863 :                 else if (icode == MULT_EXPR)
     363         3863 :                   wi::mul (maxv, wi::to_wide (op1), sign, &overflow);
     364              :                 else
     365            0 :                   wi::sub (minv, wi::to_wide (op1), sign, &overflow);
     366              : 
     367        16286 :                 if (overflow == wi::OVF_NONE)
     368              :                   {
     369         5465 :                     op0 = fold_convert (otype, op0);
     370         5465 :                     op1 = fold_convert (otype, op1);
     371         5465 :                     return expr_to_aff_combination (comb, icode, otype, op0,
     372              :                                                     op1);
     373              :                   }
     374        16286 :               }
     375       100690 :           }
     376              :       }
     377              :       break;
     378              : 
     379       922199 :     default:;
     380              :     }
     381              : 
     382              :   return false;
     383     24454632 : }
     384              : 
     385              : /* Splits EXPR into an affine combination of parts.  */
     386              : 
     387              : void
     388    145528063 : tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
     389              : {
     390    145528063 :   aff_tree tmp;
     391    145528063 :   enum tree_code code;
     392    145528063 :   tree core, toffset;
     393    145528063 :   poly_int64 bitpos, bitsize, bytepos;
     394    145528063 :   machine_mode mode;
     395    145528063 :   int unsignedp, reversep, volatilep;
     396              : 
     397    145528063 :   STRIP_NOPS (expr);
     398              : 
     399    145528063 :   code = TREE_CODE (expr);
     400    145528063 :   switch (code)
     401              :     {
     402     21086584 :     case POINTER_PLUS_EXPR:
     403     21086584 :     case PLUS_EXPR:
     404     21086584 :     case MINUS_EXPR:
     405     21086584 :     case MULT_EXPR:
     406     21086584 :       if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, 0),
     407     21086584 :                                    TREE_OPERAND (expr, 1)))
     408              :         return;
     409              :       break;
     410              : 
     411       109046 :     case NEGATE_EXPR:
     412       109046 :     case BIT_NOT_EXPR:
     413       109046 :       if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, 0)))
     414              :         return;
     415              :       break;
     416              : 
     417      3041457 :     CASE_CONVERT:
     418              :       /* ???  TREE_TYPE (expr) should be equal to type here, but IVOPTS
     419              :          calls this with not showing an outer widening cast.  */
     420      3041457 :       if (expr_to_aff_combination (comb, code,
     421      3041457 :                                    TREE_TYPE (expr), TREE_OPERAND (expr, 0)))
     422              :         {
     423        83476 :           aff_combination_convert (comb, type);
     424        83476 :           return;
     425              :         }
     426              :       break;
     427              : 
     428      9750938 :     case ADDR_EXPR:
     429              :       /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.  */
     430      9750938 :       if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
     431              :         {
     432       590421 :           expr = TREE_OPERAND (expr, 0);
     433       590421 :           tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
     434       590421 :           tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
     435       590421 :           aff_combination_add (comb, &tmp);
     436       590421 :           return;
     437              :         }
     438      9160517 :       core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
     439              :                                   &toffset, &mode, &unsignedp, &reversep,
     440              :                                   &volatilep);
     441     18321034 :       if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos))
     442              :         break;
     443      9160517 :       aff_combination_const (comb, type, bytepos);
     444      9160517 :       if (TREE_CODE (core) == MEM_REF)
     445              :         {
     446       244224 :           tree mem_offset = TREE_OPERAND (core, 1);
     447       244224 :           aff_combination_add_cst (comb, wi::to_poly_widest (mem_offset));
     448       244224 :           core = TREE_OPERAND (core, 0);
     449              :         }
     450              :       else
     451      8916293 :         core = build_fold_addr_expr (core);
     452              : 
     453      9160517 :       if (TREE_CODE (core) == ADDR_EXPR)
     454      8916293 :         aff_combination_add_elt (comb, core, 1);
     455              :       else
     456              :         {
     457       244224 :           tree_to_aff_combination (core, type, &tmp);
     458       244224 :           aff_combination_add (comb, &tmp);
     459              :         }
     460      9160517 :       if (toffset)
     461              :         {
     462        63291 :           tree_to_aff_combination (toffset, type, &tmp);
     463        63291 :           aff_combination_add (comb, &tmp);
     464              :         }
     465              :       return;
     466              : 
     467    111540038 :     default:
     468    111540038 :       {
     469    111540038 :         if (poly_int_tree_p (expr))
     470              :           {
     471     73015395 :             aff_combination_const (comb, type, wi::to_poly_widest (expr));
     472     73015395 :             return;
     473              :           }
     474              :         break;
     475              :       }
     476              :     }
     477              : 
     478     42338776 :   aff_combination_elt (comb, type, expr);
     479    145528063 : }
     480              : 
     481              : /* Creates EXPR + ELT * SCALE in TYPE.  EXPR is taken from affine
     482              :    combination COMB.  */
     483              : 
     484              : static tree
     485     40377972 : add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
     486              : {
     487     40377972 :   enum tree_code code;
     488              : 
     489     40377972 :   widest_int scale = wide_int_ext_for_comb (scale_in, type);
     490              : 
     491     40377972 :   elt = fold_convert (type, elt);
     492     40377972 :   if (scale == 1)
     493              :     {
     494     34401445 :       if (!expr)
     495              :         return elt;
     496              : 
     497     13508020 :       return fold_build2 (PLUS_EXPR, type, expr, elt);
     498              :     }
     499              : 
     500      5976527 :   if (scale == -1)
     501              :     {
     502      2787235 :       if (!expr)
     503      1667992 :         return fold_build1 (NEGATE_EXPR, type, elt);
     504              : 
     505      1119243 :       return fold_build2 (MINUS_EXPR, type, expr, elt);
     506              :     }
     507              : 
     508      3189292 :   if (!expr)
     509      1903874 :     return fold_build2 (MULT_EXPR, type, elt, wide_int_to_tree (type, scale));
     510              : 
     511      1285418 :   if (wi::neg_p (scale))
     512              :     {
     513       367947 :       code = MINUS_EXPR;
     514       367947 :       scale = -scale;
     515              :     }
     516              :   else
     517              :     code = PLUS_EXPR;
     518              : 
     519      1285418 :   elt = fold_build2 (MULT_EXPR, type, elt, wide_int_to_tree (type, scale));
     520      1285418 :   return fold_build2 (code, type, expr, elt);
     521     40377972 : }
     522              : 
     523              : /* Makes tree from the affine combination COMB.  */
     524              : 
     525              : tree
     526     24465291 : aff_combination_to_tree (aff_tree *comb)
     527              : {
     528     24465291 :   tree type = comb->type, base = NULL_TREE, expr = NULL_TREE;
     529     24465291 :   unsigned i;
     530     24465291 :   poly_widest_int off;
     531     24465291 :   int sgn;
     532              : 
     533     24465291 :   gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
     534              : 
     535     24465291 :   i = 0;
     536     24465291 :   if (POINTER_TYPE_P (type))
     537              :     {
     538       117984 :       type = sizetype;
     539       121987 :       if (comb->n > 0 && comb->elts[0].coef == 1
     540       235814 :           && POINTER_TYPE_P (TREE_TYPE (comb->elts[0].val)))
     541              :         {
     542       113827 :           base = comb->elts[0].val;
     543       113827 :           ++i;
     544              :         }
     545              :     }
     546              : 
     547     40377742 :   for (; i < comb->n; i++)
     548     15912451 :     expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef);
     549              : 
     550     24465291 :   if (comb->rest)
     551          230 :     expr = add_elt_to_tree (expr, type, comb->rest, 1);
     552              : 
     553              :   /* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is
     554              :      unsigned.  */
     555     24465291 :   if (known_lt (comb->offset, 0))
     556              :     {
     557      2184777 :       off = -comb->offset;
     558      2184777 :       sgn = -1;
     559              :     }
     560              :   else
     561              :     {
     562     22280514 :       off = comb->offset;
     563     22280514 :       sgn = 1;
     564              :     }
     565     24465291 :   expr = add_elt_to_tree (expr, type, wide_int_to_tree (type, off), sgn);
     566              : 
     567     24465291 :   if (base)
     568       113827 :     return fold_build_pointer_plus (base, expr);
     569              :   else
     570     24351464 :     return fold_convert (comb->type, expr);
     571     24465291 : }
     572              : 
     573              : /* Copies the tree elements of COMB to ensure that they are not shared.  */
     574              : 
     575              : void
     576      1824658 : unshare_aff_combination (aff_tree *comb)
     577              : {
     578      1824658 :   unsigned i;
     579              : 
     580      3898384 :   for (i = 0; i < comb->n; i++)
     581      2073726 :     comb->elts[i].val = unshare_expr (comb->elts[i].val);
     582      1824658 :   if (comb->rest)
     583            0 :     comb->rest = unshare_expr (comb->rest);
     584      1824658 : }
     585              : 
     586              : /* Remove M-th element from COMB.  */
     587              : 
     588              : void
     589      1762768 : aff_combination_remove_elt (aff_tree *comb, unsigned m)
     590              : {
     591      1762768 :   comb->n--;
     592      1762768 :   if (m <= comb->n)
     593      1762768 :     comb->elts[m] = comb->elts[comb->n];
     594      1762768 :   if (comb->rest)
     595              :     {
     596            0 :       comb->elts[comb->n].coef = 1;
     597            0 :       comb->elts[comb->n].val = comb->rest;
     598            0 :       comb->rest = NULL_TREE;
     599            0 :       comb->n++;
     600              :     }
     601      1762768 : }
     602              : 
     603              : /* Adds C * COEF * VAL to R.  VAL may be NULL, in that case only
     604              :    C * COEF is added to R.  */
     605              : 
     606              : 
     607              : static void
     608      3796615 : aff_combination_add_product (aff_tree *c, const widest_int &coef, tree val,
     609              :                              aff_tree *r)
     610              : {
     611      3796615 :   unsigned i;
     612      3796615 :   tree aval, type;
     613              : 
     614      5134547 :   for (i = 0; i < c->n; i++)
     615              :     {
     616      1337932 :       aval = c->elts[i].val;
     617      1337932 :       if (val)
     618              :         {
     619            0 :           type = TREE_TYPE (aval);
     620            0 :           aval = fold_build2 (MULT_EXPR, type, aval,
     621              :                               fold_convert (type, val));
     622              :         }
     623              : 
     624      1337932 :       aff_combination_add_elt (r, aval, coef * c->elts[i].coef);
     625              :     }
     626              : 
     627      3796615 :   if (c->rest)
     628              :     {
     629            0 :       aval = c->rest;
     630            0 :       if (val)
     631              :         {
     632            0 :           type = TREE_TYPE (aval);
     633            0 :           aval = fold_build2 (MULT_EXPR, type, aval,
     634              :                               fold_convert (type, val));
     635              :         }
     636              : 
     637            0 :       aff_combination_add_elt (r, aval, coef);
     638              :     }
     639              : 
     640      3796615 :   if (val)
     641              :     {
     642            0 :       if (c->offset.is_constant ())
     643              :         /* Access coeffs[0] directly, for efficiency.  */
     644            0 :         aff_combination_add_elt (r, val, coef * c->offset.coeffs[0]);
     645              :       else
     646              :         {
     647              :           /* c->offset is polynomial, so multiply VAL rather than COEF
     648              :              by it.  */
     649              :           tree offset = wide_int_to_tree (TREE_TYPE (val), c->offset);
     650              :           val = fold_build2 (MULT_EXPR, TREE_TYPE (val), val, offset);
     651              :           aff_combination_add_elt (r, val, coef);
     652              :         }
     653              :     }
     654              :   else
     655      3796615 :     aff_combination_add_cst (r, coef * c->offset);
     656      3796615 : }
     657              : 
     658              : /* Multiplies C1 by C2, storing the result to R  */
     659              : 
     660              : void
     661      3796615 : aff_combination_mult (aff_tree *c1, aff_tree *c2, aff_tree *r)
     662              : {
     663      3796615 :   unsigned i;
     664      3796615 :   gcc_assert (TYPE_PRECISION (c1->type) == TYPE_PRECISION (c2->type));
     665              : 
     666      3796615 :   aff_combination_zero (r, c1->type);
     667              : 
     668      7593230 :   for (i = 0; i < c2->n; i++)
     669            0 :     aff_combination_add_product (c1, c2->elts[i].coef, c2->elts[i].val, r);
     670      3796615 :   if (c2->rest)
     671            0 :     aff_combination_add_product (c1, 1, c2->rest, r);
     672      3796615 :   if (c2->offset.is_constant ())
     673              :     /* Access coeffs[0] directly, for efficiency.  */
     674      3796615 :     aff_combination_add_product (c1, c2->offset.coeffs[0], NULL, r);
     675              :   else
     676              :     {
     677              :       /* c2->offset is polynomial, so do the multiplication in tree form.  */
     678              :       tree offset = wide_int_to_tree (c2->type, c2->offset);
     679              :       aff_combination_add_product (c1, 1, offset, r);
     680              :     }
     681      3796615 : }
     682              : 
     683              : /* Returns the element of COMB whose value is VAL, or NULL if no such
     684              :    element exists.  If IDX is not NULL, it is set to the index of VAL in
     685              :    COMB.  */
     686              : 
     687              : static class aff_comb_elt *
     688      1233287 : aff_combination_find_elt (aff_tree *comb, tree val, unsigned *idx)
     689              : {
     690      1233287 :   unsigned i;
     691              : 
     692      1550302 :   for (i = 0; i < comb->n; i++)
     693      1238556 :     if (operand_equal_p (comb->elts[i].val, val, 0))
     694              :       {
     695       921541 :         if (idx)
     696            0 :           *idx = i;
     697              : 
     698       921541 :         return &comb->elts[i];
     699              :       }
     700              : 
     701              :   return NULL;
     702              : }
     703              : 
     704              : /* Element of the cache that maps ssa name NAME to its expanded form
     705              :    as an affine expression EXPANSION.  */
     706              : 
     707       272960 : class name_expansion
     708              : {
     709              : public:
     710              :   aff_tree expansion;
     711              : 
     712              :   /* True if the expansion for the name is just being generated.  */
     713              :   unsigned in_progress : 1;
     714              : };
     715              : 
     716              : /* Expands SSA names in COMB recursively.  CACHE is used to cache the
     717              :    results.  */
     718              : 
     719              : void
     720     35029695 : aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
     721              :                         hash_map<tree, name_expansion *> **cache)
     722              : {
     723     35029695 :   unsigned i;
     724    105089085 :   aff_tree to_add, current, curre;
     725     35029695 :   tree e;
     726     35029695 :   gimple *def;
     727     35029695 :   widest_int scale;
     728     35029695 :   class name_expansion *exp;
     729              : 
     730     35029695 :   aff_combination_zero (&to_add, comb->type);
     731     38625834 :   for (i = 0; i < comb->n; i++)
     732              :     {
     733      3596139 :       tree type, name;
     734      3596139 :       enum tree_code code;
     735              : 
     736      3596139 :       e = comb->elts[i].val;
     737      3596139 :       type = TREE_TYPE (e);
     738      3596139 :       name = e;
     739              :       /* Look through some conversions.  */
     740      3412892 :       if (CONVERT_EXPR_P (e)
     741      3596139 :           && (TYPE_PRECISION (type)
     742       183247 :               >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (e, 0)))))
     743       136005 :         name = TREE_OPERAND (e, 0);
     744      3596139 :       if (TREE_CODE (name) != SSA_NAME)
     745      2863228 :         continue;
     746      3324528 :       def = SSA_NAME_DEF_STMT (name);
     747      3324528 :       if (!is_gimple_assign (def) || gimple_assign_lhs (def) != name)
     748      1899035 :         continue;
     749              : 
     750      1425493 :       code = gimple_assign_rhs_code (def);
     751      1444267 :       if (code != SSA_NAME
     752      1425019 :           && !IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
     753      1444271 :           && (get_gimple_rhs_class (code) != GIMPLE_SINGLE_RHS
     754        18778 :               || !is_gimple_min_invariant (gimple_assign_rhs1 (def))))
     755        18774 :         continue;
     756              : 
     757              :       /* We do not know whether the reference retains its value at the
     758              :          place where the expansion is used.  */
     759      1406719 :       if (TREE_CODE_CLASS (code) == tcc_reference)
     760       512831 :         continue;
     761              : 
     762       893888 :       name_expansion **slot = NULL;
     763       893888 :       if (*cache)
     764       771212 :         slot = (*cache)->get (name);
     765       771212 :       exp = slot ? *slot : NULL;
     766       893888 :       if (!exp)
     767              :         {
     768              :           /* Only bother to handle cases tree_to_aff_combination will.  */
     769       229217 :           switch (code)
     770              :             {
     771       104985 :             case POINTER_PLUS_EXPR:
     772       104985 :             case PLUS_EXPR:
     773       104985 :             case MINUS_EXPR:
     774       104985 :             case MULT_EXPR:
     775       104985 :               if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
     776              :                                             gimple_assign_rhs1 (def),
     777              :                                             gimple_assign_rhs2 (def)))
     778        66047 :                 continue;
     779              :               break;
     780          699 :             case NEGATE_EXPR:
     781          699 :             case BIT_NOT_EXPR:
     782          699 :               if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
     783              :                                             gimple_assign_rhs1 (def)))
     784            0 :                 continue;
     785              :               break;
     786        28385 :             CASE_CONVERT:
     787        28385 :               if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
     788              :                                             gimple_assign_rhs1 (def)))
     789              :                 /* This makes us always expand conversions which we did
     790              :                    in the past and makes gcc.dg/tree-ssa/ivopts-lt-2.c
     791              :                    PASS, eliminating one induction variable in IVOPTs.
     792              :                    ???  But it is really excessive and we should try
     793              :                    harder to do without it.  */
     794        30518 :                 aff_combination_elt (&current, TREE_TYPE (name),
     795        15259 :                                      fold_convert (TREE_TYPE (name),
     796              :                                                    gimple_assign_rhs1 (def)));
     797              :               break;
     798          218 :             case ADDR_EXPR:
     799          218 :             case INTEGER_CST:
     800          218 :             case POLY_INT_CST:
     801          218 :               tree_to_aff_combination (gimple_assign_rhs1 (def),
     802          218 :                                        TREE_TYPE (name), &current);
     803          218 :               break;
     804        94930 :             default:
     805        94930 :               continue;
     806              :             }
     807        68240 :           exp = XNEW (class name_expansion);
     808        68240 :           ::new (static_cast<void *> (exp)) name_expansion ();
     809        68240 :           exp->in_progress = 1;
     810        68240 :           if (!*cache)
     811        29444 :             *cache = new hash_map<tree, name_expansion *>;
     812        68240 :           (*cache)->put (name, exp);
     813        68240 :           aff_combination_expand (&current, cache);
     814        68240 :           exp->expansion = current;
     815        68240 :           exp->in_progress = 0;
     816              :         }
     817              :       else
     818              :         {
     819              :           /* Since we follow the definitions in the SSA form, we should not
     820              :              enter a cycle unless we pass through a phi node.  */
     821       664671 :           gcc_assert (!exp->in_progress);
     822       664671 :           current = exp->expansion;
     823              :         }
     824       732911 :       if (!useless_type_conversion_p (comb->type, current.type))
     825       105922 :         aff_combination_convert (&current, comb->type);
     826              : 
     827              :       /* Accumulate the new terms to TO_ADD, so that we do not modify
     828              :          COMB while traversing it; include the term -coef * E, to remove
     829              :          it from COMB.  */
     830       732911 :       scale = comb->elts[i].coef;
     831       732911 :       aff_combination_zero (&curre, comb->type);
     832       732911 :       aff_combination_add_elt (&curre, e, -scale);
     833       732911 :       aff_combination_scale (&current, scale);
     834       732911 :       aff_combination_add (&to_add, &current);
     835       732911 :       aff_combination_add (&to_add, &curre);
     836              :     }
     837     35029695 :   aff_combination_add (comb, &to_add);
     838     35029695 : }
     839              : 
     840              : /* Similar to tree_to_aff_combination, but follows SSA name definitions
     841              :    and expands them recursively.  CACHE is used to cache the expansions
     842              :    of the ssa names, to avoid exponential time complexity for cases
     843              :    like
     844              : 
     845              :    a1 = a0 + a0;
     846              :    a2 = a1 + a1;
     847              :    a3 = a2 + a2;
     848              :    ...  */
     849              : 
     850              : void
     851     34846311 : tree_to_aff_combination_expand (tree expr, tree type, aff_tree *comb,
     852              :                                 hash_map<tree, name_expansion *> **cache)
     853              : {
     854     34846311 :   tree_to_aff_combination (expr, type, comb);
     855     34846311 :   aff_combination_expand (comb, cache);
     856     34846311 : }
     857              : 
     858              : /* Frees memory occupied by struct name_expansion in *VALUE.  Callback for
     859              :    hash_map::traverse.  */
     860              : 
     861              : bool
     862        68240 : free_name_expansion (tree const &, name_expansion **value, void *)
     863              : {
     864        68240 :   (*value)->~name_expansion ();
     865        68240 :   free (*value);
     866        68240 :   return true;
     867              : }
     868              : 
     869              : /* Frees memory allocated for the CACHE used by
     870              :    tree_to_aff_combination_expand.  */
     871              : 
     872              : void
     873      1737031 : free_affine_expand_cache (hash_map<tree, name_expansion *> **cache)
     874              : {
     875      1737031 :   if (!*cache)
     876              :     return;
     877              : 
     878        97684 :   (*cache)->traverse<void *, free_name_expansion> (NULL);
     879        58888 :   delete (*cache);
     880        29444 :   *cache = NULL;
     881              : }
     882              : 
     883              : /* If VAL == CST * DIV for any constant CST, returns true.
     884              :    and if *MULT_SET is true, additionally compares CST and MULT
     885              :    and if they are different, returns false.  If true is returned, CST is
     886              :    stored to MULT and MULT_SET is set to true unless VAL and DIV are both zero
     887              :    in which case neither MULT nor MULT_SET are updated.  */
     888              : 
     889              : static bool
     890     17421937 : wide_int_constant_multiple_p (const poly_widest_int &val,
     891              :                               const poly_widest_int &div,
     892              :                               bool *mult_set, poly_widest_int *mult)
     893              : {
     894     17421937 :   poly_widest_int cst;
     895              : 
     896     17421937 :   if (known_eq (val, 0))
     897              :     {
     898      1213611 :       if (known_eq (div, 0))
     899              :         return true;
     900              : 
     901          249 :       if (*mult_set && maybe_ne (*mult, 0))
     902            0 :         return false;
     903          249 :       *mult_set = true;
     904          249 :       *mult = 0;
     905          249 :       return true;
     906              :     }
     907              : 
     908     16208326 :   if (maybe_eq (div, 0))
     909              :     return false;
     910              : 
     911     16207165 :   if (!multiple_p (val, div, &cst))
     912              :     return false;
     913              : 
     914     14383417 :   if (*mult_set && maybe_ne (*mult, cst))
     915              :     return false;
     916              : 
     917     14363617 :   *mult_set = true;
     918     14363617 :   *mult = cst;
     919     14363617 :   return true;
     920     17421937 : }
     921              : 
     922              : /* Returns true if VAL = X * DIV for some constant X.  If this is the case,
     923              :    X is stored to MULT.  */
     924              : 
     925              : bool
     926     17341196 : aff_combination_constant_multiple_p (aff_tree *val, aff_tree *div,
     927              :                                      poly_widest_int *mult)
     928              : {
     929     17341196 :   bool mult_set = false;
     930     17341196 :   unsigned i;
     931              : 
     932     17341196 :   if (val->n == 0 && known_eq (val->offset, 0))
     933              :     {
     934        49124 :       *mult = 0;
     935        49124 :       return true;
     936              :     }
     937     17292072 :   if (val->n != div->n)
     938              :     return false;
     939              : 
     940     16500396 :   if (val->rest || div->rest)
     941              :     return false;
     942              : 
     943     16500396 :   if (!wide_int_constant_multiple_p (val->offset, div->offset,
     944              :                                      &mult_set, mult))
     945              :     return false;
     946              : 
     947     15577228 :   for (i = 0; i < div->n; i++)
     948              :     {
     949      1233287 :       class aff_comb_elt *elt
     950      1233287 :               = aff_combination_find_elt (val, div->elts[i].val, NULL);
     951      1233287 :       if (!elt)
     952              :         return false;
     953       921541 :       if (!wide_int_constant_multiple_p (elt->coef, div->elts[i].coef,
     954              :                                          &mult_set, mult))
     955              :         return false;
     956              :     }
     957              : 
     958     14343941 :   gcc_assert (mult_set);
     959              :   return true;
     960              : }
     961              : 
     962              : /* Prints the affine VAL to the FILE. */
     963              : 
     964              : static void
     965            0 : print_aff (FILE *file, aff_tree *val)
     966              : {
     967            0 :   unsigned i;
     968            0 :   signop sgn = TYPE_SIGN (val->type);
     969            0 :   if (POINTER_TYPE_P (val->type))
     970            0 :     sgn = SIGNED;
     971            0 :   fprintf (file, "{\n  type = ");
     972            0 :   print_generic_expr (file, val->type, TDF_VOPS|TDF_MEMSYMS);
     973            0 :   fprintf (file, "\n  offset = ");
     974            0 :   print_dec (val->offset, file, sgn);
     975            0 :   if (val->n > 0)
     976              :     {
     977            0 :       fprintf (file, "\n  elements = {\n");
     978            0 :       for (i = 0; i < val->n; i++)
     979              :         {
     980            0 :           fprintf (file, "    [%d] = ", i);
     981            0 :           print_generic_expr (file, val->elts[i].val, TDF_VOPS|TDF_MEMSYMS);
     982              : 
     983            0 :           fprintf (file, " * ");
     984            0 :           print_dec (val->elts[i].coef, file, sgn);
     985            0 :           if (i != val->n - 1)
     986            0 :             fprintf (file, ", \n");
     987              :         }
     988            0 :       fprintf (file, "\n  }");
     989              :   }
     990            0 :   if (val->rest)
     991              :     {
     992            0 :       fprintf (file, "\n  rest = ");
     993            0 :       print_generic_expr (file, val->rest, TDF_VOPS|TDF_MEMSYMS);
     994              :     }
     995            0 :   fprintf (file, "\n}");
     996            0 : }
     997              : 
     998              : /* Prints the affine VAL to the standard error, used for debugging.  */
     999              : 
    1000              : DEBUG_FUNCTION void
    1001            0 : debug_aff (aff_tree *val)
    1002              : {
    1003            0 :   print_aff (stderr, val);
    1004            0 :   fprintf (stderr, "\n");
    1005            0 : }
    1006              : 
    1007              : /* Computes address of the reference REF in ADDR.  The size of the accessed
    1008              :    location is stored to SIZE.  Returns the ultimate containing object to
    1009              :    which REF refers.  */
    1010              : 
    1011              : tree
    1012      5506420 : get_inner_reference_aff (tree ref, aff_tree *addr, poly_widest_int *size)
    1013              : {
    1014      5506420 :   poly_int64 bitsize, bitpos;
    1015      5506420 :   tree toff;
    1016      5506420 :   machine_mode mode;
    1017      5506420 :   int uns, rev, vol;
    1018      5506420 :   aff_tree tmp;
    1019      5506420 :   tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode,
    1020              :                                    &uns, &rev, &vol);
    1021      5506420 :   tree base_addr = build_fold_addr_expr (base);
    1022              : 
    1023              :   /* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT.  */
    1024              : 
    1025      5506420 :   tree_to_aff_combination (base_addr, sizetype, addr);
    1026              : 
    1027      5506420 :   if (toff)
    1028              :     {
    1029       164707 :       tree_to_aff_combination (toff, sizetype, &tmp);
    1030       164707 :       aff_combination_add (addr, &tmp);
    1031              :     }
    1032              : 
    1033      5506420 :   aff_combination_const (&tmp, sizetype, bits_to_bytes_round_down (bitpos));
    1034      5506420 :   aff_combination_add (addr, &tmp);
    1035              : 
    1036      5506420 :   *size = bits_to_bytes_round_up (bitsize);
    1037              : 
    1038     11012840 :   return base;
    1039      5506420 : }
    1040              : 
    1041              : /* Returns true if a region of size SIZE1 at position 0 and a region of
    1042              :    size SIZE2 at position DIFF cannot overlap.  */
    1043              : 
    1044              : bool
    1045      2753302 : aff_comb_cannot_overlap_p (aff_tree *diff, const poly_widest_int &size1,
    1046              :                            const poly_widest_int &size2)
    1047              : {
    1048              :   /* Unless the difference is a constant, we fail.  */
    1049      2753302 :   if (diff->n != 0)
    1050              :     return false;
    1051              : 
    1052      1814657 :   if (!ordered_p (diff->offset, 0))
    1053              :     return false;
    1054              : 
    1055      1814657 :   if (maybe_lt (diff->offset, 0))
    1056              :     {
    1057              :       /* The second object is before the first one, we succeed if the last
    1058              :          element of the second object is before the start of the first one.  */
    1059       240176 :       return known_le (diff->offset + size2, 0);
    1060              :     }
    1061              :   else
    1062              :     {
    1063              :       /* We succeed if the second object starts after the first one ends.  */
    1064      1574481 :       return known_le (size1, diff->offset);
    1065              :     }
    1066              : }
    1067              : 
        

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.