LCOV - code coverage report
Current view: top level - gcc - tree-ssa-address.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.9 % 508 421
Test Date: 2024-04-13 14:00:49 Functions: 91.7 % 24 22
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Memory address lowering and addressing mode selection.
       2                 :             :    Copyright (C) 2004-2024 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                 :             : /* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions
      21                 :             :    that directly map to addressing modes of the target.  */
      22                 :             : 
      23                 :             : #include "config.h"
      24                 :             : #include "system.h"
      25                 :             : #include "coretypes.h"
      26                 :             : #include "backend.h"
      27                 :             : #include "target.h"
      28                 :             : #include "rtl.h"
      29                 :             : #include "tree.h"
      30                 :             : #include "gimple.h"
      31                 :             : #include "memmodel.h"
      32                 :             : #include "stringpool.h"
      33                 :             : #include "tree-vrp.h"
      34                 :             : #include "tree-ssanames.h"
      35                 :             : #include "expmed.h"
      36                 :             : #include "insn-config.h"
      37                 :             : #include "emit-rtl.h"
      38                 :             : #include "recog.h"
      39                 :             : #include "tree-pretty-print.h"
      40                 :             : #include "fold-const.h"
      41                 :             : #include "stor-layout.h"
      42                 :             : #include "gimple-iterator.h"
      43                 :             : #include "gimplify-me.h"
      44                 :             : #include "tree-ssa-loop-ivopts.h"
      45                 :             : #include "expr.h"
      46                 :             : #include "tree-dfa.h"
      47                 :             : #include "dumpfile.h"
      48                 :             : #include "tree-affine.h"
      49                 :             : #include "gimplify.h"
      50                 :             : #include "builtins.h"
      51                 :             : 
      52                 :             : /* FIXME: We compute address costs using RTL.  */
      53                 :             : #include "tree-ssa-address.h"
      54                 :             : 
      55                 :             : /* TODO -- handling of symbols (according to Richard Hendersons
      56                 :             :    comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
      57                 :             : 
      58                 :             :    There are at least 5 different kinds of symbols that we can run up against:
      59                 :             : 
      60                 :             :      (1) binds_local_p, small data area.
      61                 :             :      (2) binds_local_p, eg local statics
      62                 :             :      (3) !binds_local_p, eg global variables
      63                 :             :      (4) thread local, local_exec
      64                 :             :      (5) thread local, !local_exec
      65                 :             : 
      66                 :             :    Now, (1) won't appear often in an array context, but it certainly can.
      67                 :             :    All you have to do is set -GN high enough, or explicitly mark any
      68                 :             :    random object __attribute__((section (".sdata"))).
      69                 :             : 
      70                 :             :    All of these affect whether or not a symbol is in fact a valid address.
      71                 :             :    The only one tested here is (3).  And that result may very well
      72                 :             :    be incorrect for (4) or (5).
      73                 :             : 
      74                 :             :    An incorrect result here does not cause incorrect results out the
      75                 :             :    back end, because the expander in expr.cc validizes the address.  However
      76                 :             :    it would be nice to improve the handling here in order to produce more
      77                 :             :    precise results.  */
      78                 :             : 
      79                 :             : /* A "template" for memory address, used to determine whether the address is
      80                 :             :    valid for mode.  */
      81                 :             : 
      82                 :             : struct GTY (()) mem_addr_template {
      83                 :             :   rtx ref;                      /* The template.  */
      84                 :             :   rtx * GTY ((skip)) step_p;    /* The point in template where the step should be
      85                 :             :                                    filled in.  */
      86                 :             :   rtx * GTY ((skip)) off_p;     /* The point in template where the offset should
      87                 :             :                                    be filled in.  */
      88                 :             : };
      89                 :             : 
      90                 :             : 
      91                 :             : /* The templates.  Each of the low five bits of the index corresponds to one
      92                 :             :    component of TARGET_MEM_REF being present, while the high bits identify
      93                 :             :    the address space.  See TEMPL_IDX.  */
      94                 :             : 
      95                 :             : static GTY(()) vec<mem_addr_template, va_gc> *mem_addr_template_list;
      96                 :             : 
      97                 :             : #define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \
      98                 :             :   (((int) (AS) << 5) \
      99                 :             :    | ((SYMBOL != 0) << 4) \
     100                 :             :    | ((BASE != 0) << 3) \
     101                 :             :    | ((INDEX != 0) << 2) \
     102                 :             :    | ((STEP != 0) << 1) \
     103                 :             :    | (OFFSET != 0))
     104                 :             : 
     105                 :             : /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
     106                 :             :    STEP and OFFSET to *ADDR using address mode ADDRESS_MODE.  Stores pointers
     107                 :             :    to where step is placed to *STEP_P and offset to *OFFSET_P.  */
     108                 :             : 
     109                 :             : static void
     110                 :      900703 : gen_addr_rtx (machine_mode address_mode,
     111                 :             :               rtx symbol, rtx base, rtx index, rtx step, rtx offset,
     112                 :             :               rtx *addr, rtx **step_p, rtx **offset_p)
     113                 :             : {
     114                 :      900703 :   rtx act_elem;
     115                 :             : 
     116                 :      900703 :   *addr = NULL_RTX;
     117                 :      900703 :   if (step_p)
     118                 :      175222 :     *step_p = NULL;
     119                 :      900703 :   if (offset_p)
     120                 :      175222 :     *offset_p = NULL;
     121                 :             : 
     122                 :      900703 :   if (index && index != const0_rtx)
     123                 :             :     {
     124                 :      531410 :       act_elem = index;
     125                 :      531410 :       if (step)
     126                 :             :         {
     127                 :      255819 :           act_elem = gen_rtx_MULT (address_mode, act_elem, step);
     128                 :             : 
     129                 :      255819 :           if (step_p)
     130                 :       62730 :             *step_p = &XEXP (act_elem, 1);
     131                 :             :         }
     132                 :             : 
     133                 :      531410 :       *addr = act_elem;
     134                 :             :     }
     135                 :             : 
     136                 :      900703 :   if (base && base != const0_rtx)
     137                 :             :     {
     138                 :      698223 :       if (*addr)
     139                 :      329118 :         *addr = simplify_gen_binary (PLUS, address_mode, base, *addr);
     140                 :             :       else
     141                 :      369105 :         *addr = base;
     142                 :             :     }
     143                 :             : 
     144                 :      900703 :   if (symbol)
     145                 :             :     {
     146                 :      214370 :       act_elem = symbol;
     147                 :      214370 :       if (offset)
     148                 :             :         {
     149                 :       50251 :           act_elem = gen_rtx_PLUS (address_mode, act_elem, offset);
     150                 :             : 
     151                 :       50251 :           if (offset_p)
     152                 :       13181 :             *offset_p = &XEXP (act_elem, 1);
     153                 :             : 
     154                 :       50251 :           if (GET_CODE (symbol) == SYMBOL_REF
     155                 :       50251 :               || GET_CODE (symbol) == LABEL_REF
     156                 :       17537 :               || GET_CODE (symbol) == CONST)
     157                 :       32714 :             act_elem = gen_rtx_CONST (address_mode, act_elem);
     158                 :             :         }
     159                 :             : 
     160                 :      214370 :       if (*addr)
     161                 :      214182 :         *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
     162                 :             :       else
     163                 :         188 :         *addr = act_elem;
     164                 :             :     }
     165                 :      686333 :   else if (offset)
     166                 :             :     {
     167                 :      284152 :       if (*addr)
     168                 :             :         {
     169                 :      284152 :           *addr = gen_rtx_PLUS (address_mode, *addr, offset);
     170                 :      284152 :           if (offset_p)
     171                 :       62891 :             *offset_p = &XEXP (*addr, 1);
     172                 :             :         }
     173                 :             :       else
     174                 :             :         {
     175                 :           0 :           *addr = offset;
     176                 :           0 :           if (offset_p)
     177                 :           0 :             *offset_p = addr;
     178                 :             :         }
     179                 :             :     }
     180                 :             : 
     181                 :      900703 :   if (!*addr)
     182                 :           0 :     *addr = const0_rtx;
     183                 :      900703 : }
     184                 :             : 
     185                 :             : /* Returns address for TARGET_MEM_REF with parameters given by ADDR
     186                 :             :    in address space AS.
     187                 :             :    If REALLY_EXPAND is false, just make fake registers instead
     188                 :             :    of really expanding the operands, and perform the expansion in-place
     189                 :             :    by using one of the "templates".  */
     190                 :             : 
     191                 :             : rtx
     192                 :    16360134 : addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
     193                 :             :                   bool really_expand)
     194                 :             : {
     195                 :    16360134 :   scalar_int_mode address_mode = targetm.addr_space.address_mode (as);
     196                 :    16360134 :   scalar_int_mode pointer_mode = targetm.addr_space.pointer_mode (as);
     197                 :    16360134 :   rtx address, sym, bse, idx, st, off;
     198                 :    16360134 :   struct mem_addr_template *templ;
     199                 :             : 
     200                 :    16360134 :   if (addr->step && !integer_onep (addr->step))
     201                 :     4838607 :     st = immed_wide_int_const (wi::to_wide (addr->step), pointer_mode);
     202                 :             :   else
     203                 :             :     st = NULL_RTX;
     204                 :             : 
     205                 :    16360134 :   if (addr->offset && !integer_zerop (addr->offset))
     206                 :             :     {
     207                 :     6740748 :       poly_offset_int dc
     208                 :     6740748 :         = poly_offset_int::from (wi::to_poly_wide (addr->offset), SIGNED);
     209                 :     6740748 :       off = immed_wide_int_const (dc, pointer_mode);
     210                 :             :     }
     211                 :             :   else
     212                 :             :     off = NULL_RTX;
     213                 :             : 
     214                 :    16360134 :   if (!really_expand)
     215                 :             :     {
     216                 :    31269306 :       unsigned int templ_index
     217                 :    33892472 :         = TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off);
     218                 :             : 
     219                 :    31239367 :       if (templ_index >= vec_safe_length (mem_addr_template_list))
     220                 :       96271 :         vec_safe_grow_cleared (mem_addr_template_list, templ_index + 1, true);
     221                 :             : 
     222                 :             :       /* Reuse the templates for addresses, so that we do not waste memory.  */
     223                 :    15634653 :       templ = &(*mem_addr_template_list)[templ_index];
     224                 :    15634653 :       if (!templ->ref)
     225                 :             :         {
     226                 :      175222 :           sym = (addr->symbol ?
     227                 :       28625 :                  gen_rtx_SYMBOL_REF (pointer_mode, ggc_strdup ("test_symbol"))
     228                 :             :                  : NULL_RTX);
     229                 :      175222 :           bse = (addr->base ?
     230                 :      151101 :                  gen_raw_REG (pointer_mode, LAST_VIRTUAL_REGISTER + 1)
     231                 :             :                  : NULL_RTX);
     232                 :      175222 :           idx = (addr->index ?
     233                 :      128790 :                  gen_raw_REG (pointer_mode, LAST_VIRTUAL_REGISTER + 2)
     234                 :             :                  : NULL_RTX);
     235                 :             : 
     236                 :      175222 :           gen_addr_rtx (pointer_mode, sym, bse, idx,
     237                 :             :                         st? const0_rtx : NULL_RTX,
     238                 :             :                         off? const0_rtx : NULL_RTX,
     239                 :             :                         &templ->ref,
     240                 :             :                         &templ->step_p,
     241                 :             :                         &templ->off_p);
     242                 :             :         }
     243                 :             : 
     244                 :    15634653 :       if (st)
     245                 :     4645518 :         *templ->step_p = st;
     246                 :    15634653 :       if (off)
     247                 :     6482423 :         *templ->off_p = off;
     248                 :             : 
     249                 :    15634653 :       return templ->ref;
     250                 :             :     }
     251                 :             : 
     252                 :             :   /* Otherwise really expand the expressions.  */
     253                 :     1450962 :   sym = (addr->symbol
     254                 :      725481 :          ? expand_expr (addr->symbol, NULL_RTX, pointer_mode, EXPAND_NORMAL)
     255                 :             :          : NULL_RTX);
     256                 :     1450962 :   bse = (addr->base
     257                 :      725481 :          ? expand_expr (addr->base, NULL_RTX, pointer_mode, EXPAND_NORMAL)
     258                 :             :          : NULL_RTX);
     259                 :     1450962 :   idx = (addr->index
     260                 :      725481 :          ? expand_expr (addr->index, NULL_RTX, pointer_mode, EXPAND_NORMAL)
     261                 :             :          : NULL_RTX);
     262                 :             : 
     263                 :             :   /* addr->base could be an SSA_NAME that was set to a constant value.  The
     264                 :             :      call to expand_expr may expose that constant.  If so, fold the value
     265                 :             :      into OFF and clear BSE.  Otherwise we may later try to pull a mode from
     266                 :             :      BSE to generate a REG, which won't work with constants because they
     267                 :             :      are modeless.  */
     268                 :      725481 :   if (bse && GET_CODE (bse) == CONST_INT)
     269                 :             :     {
     270                 :          11 :       if (off)
     271                 :           5 :         off = simplify_gen_binary (PLUS, pointer_mode, bse, off);
     272                 :             :       else
     273                 :             :         off = bse;
     274                 :          11 :       gcc_assert (GET_CODE (off) == CONST_INT);
     275                 :             :       bse = NULL_RTX;
     276                 :             :     }
     277                 :      725481 :   gen_addr_rtx (pointer_mode, sym, bse, idx, st, off, &address, NULL, NULL);
     278                 :      725481 :   if (pointer_mode != address_mode)
     279                 :           8 :     address = convert_memory_address (address_mode, address);
     280                 :      725481 :   return address;
     281                 :             : }
     282                 :             : 
     283                 :             : /* implement addr_for_mem_ref() directly from a tree, which avoids exporting
     284                 :             :    the mem_address structure.  */
     285                 :             : 
     286                 :             : rtx
     287                 :      725481 : addr_for_mem_ref (tree exp, addr_space_t as, bool really_expand)
     288                 :             : {
     289                 :      725481 :   struct mem_address addr;
     290                 :      725481 :   get_address_description (exp, &addr);
     291                 :      725481 :   return addr_for_mem_ref (&addr, as, really_expand);
     292                 :             : }
     293                 :             : 
     294                 :             : /* Returns address of MEM_REF in TYPE.  */
     295                 :             : 
     296                 :             : tree
     297                 :       42221 : tree_mem_ref_addr (tree type, tree mem_ref)
     298                 :             : {
     299                 :       42221 :   tree addr;
     300                 :       42221 :   tree act_elem;
     301                 :       42221 :   tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
     302                 :       42221 :   tree addr_base = NULL_TREE, addr_off = NULL_TREE;
     303                 :             : 
     304                 :       42221 :   addr_base = fold_convert (type, TMR_BASE (mem_ref));
     305                 :             : 
     306                 :       42221 :   act_elem = TMR_INDEX (mem_ref);
     307                 :       42221 :   if (act_elem)
     308                 :             :     {
     309                 :        1955 :       if (step)
     310                 :        1632 :         act_elem = fold_build2 (MULT_EXPR, TREE_TYPE (act_elem),
     311                 :             :                                 act_elem, step);
     312                 :             :       addr_off = act_elem;
     313                 :             :     }
     314                 :             : 
     315                 :       42221 :   act_elem = TMR_INDEX2 (mem_ref);
     316                 :       42221 :   if (act_elem)
     317                 :             :     {
     318                 :           0 :       if (addr_off)
     319                 :           0 :         addr_off = fold_build2 (PLUS_EXPR, TREE_TYPE (addr_off),
     320                 :             :                                 addr_off, act_elem);
     321                 :             :       else
     322                 :             :         addr_off = act_elem;
     323                 :             :     }
     324                 :             : 
     325                 :       42221 :   if (offset && !integer_zerop (offset))
     326                 :             :     {
     327                 :       30995 :       if (addr_off)
     328                 :         478 :         addr_off = fold_build2 (PLUS_EXPR, TREE_TYPE (addr_off), addr_off,
     329                 :             :                                 fold_convert (TREE_TYPE (addr_off), offset));
     330                 :             :       else
     331                 :             :         addr_off = offset;
     332                 :             :     }
     333                 :             : 
     334                 :       42221 :   if (addr_off)
     335                 :       32472 :     addr = fold_build_pointer_plus (addr_base, addr_off);
     336                 :             :   else
     337                 :             :     addr = addr_base;
     338                 :             : 
     339                 :       42221 :   return addr;
     340                 :             : }
     341                 :             : 
     342                 :             : /* Returns true if a memory reference in MODE and with parameters given by
     343                 :             :    ADDR is valid on the current target.  */
     344                 :             : 
     345                 :             : bool
     346                 :     9888999 : valid_mem_ref_p (machine_mode mode, addr_space_t as,
     347                 :             :                  struct mem_address *addr, code_helper ch)
     348                 :             : {
     349                 :     9888999 :   rtx address;
     350                 :             : 
     351                 :     9888999 :   address = addr_for_mem_ref (addr, as, false);
     352                 :     9888999 :   if (!address)
     353                 :             :     return false;
     354                 :             : 
     355                 :     9888999 :   return memory_address_addr_space_p (mode, address, as, ch);
     356                 :             : }
     357                 :             : 
     358                 :             : /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
     359                 :             :    is valid on the current target and if so, creates and returns the
     360                 :             :    TARGET_MEM_REF.  If VERIFY is false omit the verification step.  */
     361                 :             : 
     362                 :             : static tree
     363                 :      770860 : create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr,
     364                 :             :                     bool verify)
     365                 :             : {
     366                 :      770860 :   tree base, index2;
     367                 :             : 
     368                 :      770860 :   if (verify
     369                 :      770860 :       && !valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
     370                 :       34318 :     return NULL_TREE;
     371                 :             : 
     372                 :      736542 :   if (addr->offset)
     373                 :      270601 :     addr->offset = fold_convert (alias_ptr_type, addr->offset);
     374                 :             :   else
     375                 :      465941 :     addr->offset = build_int_cst (alias_ptr_type, 0);
     376                 :             : 
     377                 :      736542 :   if (addr->symbol)
     378                 :             :     {
     379                 :      103936 :       base = addr->symbol;
     380                 :      103936 :       index2 = addr->base;
     381                 :             :     }
     382                 :      632606 :   else if (addr->base
     383                 :      632606 :            && POINTER_TYPE_P (TREE_TYPE (addr->base)))
     384                 :             :     {
     385                 :             :       base = addr->base;
     386                 :             :       index2 = NULL_TREE;
     387                 :             :     }
     388                 :             :   else
     389                 :             :     {
     390                 :          19 :       base = build_int_cst (build_pointer_type (type), 0);
     391                 :          19 :       index2 = addr->base;
     392                 :             :     }
     393                 :             : 
     394                 :             :   /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF.
     395                 :             :      ???  As IVOPTs does not follow restrictions to where the base
     396                 :             :      pointer may point to create a MEM_REF only if we know that
     397                 :             :      base is valid.  */
     398                 :      548511 :   if ((TREE_CODE (base) == ADDR_EXPR || TREE_CODE (base) == INTEGER_CST)
     399                 :      188050 :       && (!index2 || integer_zerop (index2))
     400                 :      917211 :       && (!addr->index || integer_zerop (addr->index)))
     401                 :         630 :     return fold_build2 (MEM_REF, type, base, addr->offset);
     402                 :             : 
     403                 :      735912 :   return build5 (TARGET_MEM_REF, type,
     404                 :      735912 :                  base, addr->offset, addr->index, addr->step, index2);
     405                 :             : }
     406                 :             : 
     407                 :             : /* Returns true if OBJ is an object whose address is a link time constant.  */
     408                 :             : 
     409                 :             : static bool
     410                 :     1355901 : fixed_address_object_p (tree obj)
     411                 :             : {
     412                 :     1355901 :   return (VAR_P (obj)
     413                 :     1322226 :           && (TREE_STATIC (obj) || DECL_EXTERNAL (obj))
     414                 :     1903352 :           && ! DECL_DLLIMPORT_P (obj));
     415                 :             : }
     416                 :             : 
     417                 :             : /* If ADDR contains an address of object that is a link time constant,
     418                 :             :    move it to PARTS->symbol.  */
     419                 :             : 
     420                 :             : void
     421                 :     4068483 : move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
     422                 :             : {
     423                 :     4068483 :   unsigned i;
     424                 :     4068483 :   tree val = NULL_TREE;
     425                 :             : 
     426                 :     8675937 :   for (i = 0; i < addr->n; i++)
     427                 :             :     {
     428                 :     5154905 :       if (addr->elts[i].coef != 1)
     429                 :     1080039 :         continue;
     430                 :             : 
     431                 :     4074866 :       val = addr->elts[i].val;
     432                 :     4074866 :       if (TREE_CODE (val) == ADDR_EXPR
     433                 :     4074866 :           && fixed_address_object_p (TREE_OPERAND (val, 0)))
     434                 :             :         break;
     435                 :             :     }
     436                 :             : 
     437                 :     4068483 :   if (i == addr->n)
     438                 :             :     return;
     439                 :             : 
     440                 :      547451 :   parts->symbol = val;
     441                 :      547451 :   aff_combination_remove_elt (addr, i);
     442                 :             : }
     443                 :             : 
     444                 :             : /* Return true if ADDR contains an instance of BASE_HINT and it's moved to
     445                 :             :    PARTS->base.  */
     446                 :             : 
     447                 :             : static bool
     448                 :      345305 : move_hint_to_base (tree type, struct mem_address *parts, tree base_hint,
     449                 :             :                    aff_tree *addr)
     450                 :             : {
     451                 :      345305 :   unsigned i;
     452                 :      345305 :   tree val = NULL_TREE;
     453                 :      345305 :   int qual;
     454                 :             : 
     455                 :      362699 :   for (i = 0; i < addr->n; i++)
     456                 :             :     {
     457                 :      362682 :       if (addr->elts[i].coef != 1)
     458                 :       16751 :         continue;
     459                 :             : 
     460                 :      345931 :       val = addr->elts[i].val;
     461                 :      345931 :       if (operand_equal_p (val, base_hint, 0))
     462                 :             :         break;
     463                 :             :     }
     464                 :             : 
     465                 :      345305 :   if (i == addr->n)
     466                 :             :     return false;
     467                 :             : 
     468                 :             :   /* Cast value to appropriate pointer type.  We cannot use a pointer
     469                 :             :      to TYPE directly, as the back-end will assume registers of pointer
     470                 :             :      type are aligned, and just the base itself may not actually be.
     471                 :             :      We use void pointer to the type's address space instead.  */
     472                 :      345288 :   qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type));
     473                 :      345288 :   type = build_qualified_type (void_type_node, qual);
     474                 :      345288 :   parts->base = fold_convert (build_pointer_type (type), val);
     475                 :      345288 :   aff_combination_remove_elt (addr, i);
     476                 :      345288 :   return true;
     477                 :             : }
     478                 :             : 
     479                 :             : /* If ADDR contains an address of a dereferenced pointer, move it to
     480                 :             :    PARTS->base.  */
     481                 :             : 
     482                 :             : static void
     483                 :      285733 : move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
     484                 :             : {
     485                 :      285733 :   unsigned i;
     486                 :      285733 :   tree val = NULL_TREE;
     487                 :             : 
     488                 :      285810 :   for (i = 0; i < addr->n; i++)
     489                 :             :     {
     490                 :      285791 :       if (addr->elts[i].coef != 1)
     491                 :          30 :         continue;
     492                 :             : 
     493                 :      285761 :       val = addr->elts[i].val;
     494                 :      285761 :       if (POINTER_TYPE_P (TREE_TYPE (val)))
     495                 :             :         break;
     496                 :             :     }
     497                 :             : 
     498                 :      285733 :   if (i == addr->n)
     499                 :             :     return;
     500                 :             : 
     501                 :      285714 :   parts->base = val;
     502                 :      285714 :   aff_combination_remove_elt (addr, i);
     503                 :             : }
     504                 :             : 
     505                 :             : /* Moves the loop variant part V in linear address ADDR to be the index
     506                 :             :    of PARTS.  */
     507                 :             : 
     508                 :             : static void
     509                 :      390002 : move_variant_to_index (struct mem_address *parts, aff_tree *addr, tree v)
     510                 :             : {
     511                 :      390002 :   unsigned i;
     512                 :      390002 :   tree val = NULL_TREE;
     513                 :             : 
     514                 :      390002 :   gcc_assert (!parts->index);
     515                 :      697707 :   for (i = 0; i < addr->n; i++)
     516                 :             :     {
     517                 :      697526 :       val = addr->elts[i].val;
     518                 :      697526 :       if (operand_equal_p (val, v, 0))
     519                 :             :         break;
     520                 :             :     }
     521                 :             : 
     522                 :      390002 :   if (i == addr->n)
     523                 :             :     return;
     524                 :             : 
     525                 :      389821 :   parts->index = fold_convert (sizetype, val);
     526                 :      389821 :   parts->step = wide_int_to_tree (sizetype, addr->elts[i].coef);
     527                 :      389821 :   aff_combination_remove_elt (addr, i);
     528                 :             : }
     529                 :             : 
     530                 :             : /* Adds ELT to PARTS.  */
     531                 :             : 
     532                 :             : static void
     533                 :       41107 : add_to_parts (struct mem_address *parts, tree elt)
     534                 :             : {
     535                 :       41107 :   tree type;
     536                 :             : 
     537                 :       41107 :   if (!parts->index)
     538                 :             :     {
     539                 :        5205 :       parts->index = fold_convert (sizetype, elt);
     540                 :        5205 :       return;
     541                 :             :     }
     542                 :             : 
     543                 :       35902 :   if (!parts->base)
     544                 :             :     {
     545                 :        7432 :       parts->base = elt;
     546                 :        7432 :       return;
     547                 :             :     }
     548                 :             : 
     549                 :             :   /* Add ELT to base.  */
     550                 :       28470 :   type = TREE_TYPE (parts->base);
     551                 :       28470 :   if (POINTER_TYPE_P (type))
     552                 :       23983 :     parts->base = fold_build_pointer_plus (parts->base, elt);
     553                 :             :   else
     554                 :        4487 :     parts->base = fold_build2 (PLUS_EXPR, type, parts->base, elt);
     555                 :             : }
     556                 :             : 
     557                 :             : /* Returns true if multiplying by RATIO is allowed in an address.  Test the
     558                 :             :    validity for a memory reference accessing memory of mode MODE in address
     559                 :             :    space AS.  */
     560                 :             : 
     561                 :             : static bool
     562                 :       16962 : multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, machine_mode mode,
     563                 :             :                                  addr_space_t as)
     564                 :             : {
     565                 :             : #define MAX_RATIO 128
     566                 :       16962 :   unsigned int data_index = (int) as * MAX_MACHINE_MODE + (int) mode;
     567                 :       16962 :   static vec<sbitmap> valid_mult_list;
     568                 :       16962 :   sbitmap valid_mult;
     569                 :             : 
     570                 :       33101 :   if (data_index >= valid_mult_list.length ())
     571                 :         966 :     valid_mult_list.safe_grow_cleared (data_index + 1, true);
     572                 :             : 
     573                 :       16962 :   valid_mult = valid_mult_list[data_index];
     574                 :       16962 :   if (!valid_mult)
     575                 :             :     {
     576                 :        1092 :       machine_mode address_mode = targetm.addr_space.address_mode (as);
     577                 :        1092 :       rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
     578                 :        1092 :       rtx reg2 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
     579                 :        1092 :       rtx addr, scaled;
     580                 :        1092 :       HOST_WIDE_INT i;
     581                 :             : 
     582                 :        1092 :       valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
     583                 :        1092 :       bitmap_clear (valid_mult);
     584                 :        1092 :       scaled = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
     585                 :        1092 :       addr = gen_rtx_fmt_ee (PLUS, address_mode, scaled, reg2);
     586                 :      281736 :       for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
     587                 :             :         {
     588                 :      280644 :           XEXP (scaled, 1) = gen_int_mode (i, address_mode);
     589                 :      280644 :           if (memory_address_addr_space_p (mode, addr, as)
     590                 :      280644 :               || memory_address_addr_space_p (mode, scaled, as))
     591                 :        4368 :             bitmap_set_bit (valid_mult, i + MAX_RATIO);
     592                 :             :         }
     593                 :             : 
     594                 :        1092 :       if (dump_file && (dump_flags & TDF_DETAILS))
     595                 :             :         {
     596                 :           0 :           fprintf (dump_file, "  allowed multipliers:");
     597                 :           0 :           for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
     598                 :           0 :             if (bitmap_bit_p (valid_mult, i + MAX_RATIO))
     599                 :           0 :               fprintf (dump_file, " %d", (int) i);
     600                 :           0 :           fprintf (dump_file, "\n");
     601                 :           0 :           fprintf (dump_file, "\n");
     602                 :             :         }
     603                 :             : 
     604                 :        1092 :       valid_mult_list[data_index] = valid_mult;
     605                 :             :     }
     606                 :             : 
     607                 :       16962 :   if (ratio > MAX_RATIO || ratio < -MAX_RATIO)
     608                 :             :     return false;
     609                 :             : 
     610                 :       16577 :   return bitmap_bit_p (valid_mult, ratio + MAX_RATIO);
     611                 :             : }
     612                 :             : 
     613                 :             : /* Finds the most expensive multiplication in ADDR that can be
     614                 :             :    expressed in an addressing mode and move the corresponding
     615                 :             :    element(s) to PARTS.  */
     616                 :             : 
     617                 :             : static void
     618                 :      345486 : most_expensive_mult_to_index (tree type, struct mem_address *parts,
     619                 :             :                               aff_tree *addr, bool speed)
     620                 :             : {
     621                 :      345486 :   addr_space_t as = TYPE_ADDR_SPACE (type);
     622                 :      345486 :   machine_mode address_mode = targetm.addr_space.address_mode (as);
     623                 :      345486 :   HOST_WIDE_INT coef;
     624                 :      345486 :   unsigned best_mult_cost = 0, acost;
     625                 :      345486 :   tree mult_elt = NULL_TREE, elt;
     626                 :      345486 :   unsigned i, j;
     627                 :      345486 :   enum tree_code op_code;
     628                 :             : 
     629                 :      345486 :   offset_int best_mult = 0;
     630                 :      363254 :   for (i = 0; i < addr->n; i++)
     631                 :             :     {
     632                 :       17768 :       if (!wi::fits_shwi_p (addr->elts[i].coef))
     633                 :           0 :         continue;
     634                 :             : 
     635                 :       17768 :       coef = addr->elts[i].coef.to_shwi ();
     636                 :       28040 :       if (coef == 1
     637                 :       17768 :           || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as))
     638                 :       10272 :         continue;
     639                 :             : 
     640                 :        7496 :       acost = mult_by_coeff_cost (coef, address_mode, speed);
     641                 :             : 
     642                 :        7496 :       if (acost > best_mult_cost)
     643                 :             :         {
     644                 :        7293 :           best_mult_cost = acost;
     645                 :        7293 :           best_mult = offset_int::from (addr->elts[i].coef, SIGNED);
     646                 :             :         }
     647                 :             :     }
     648                 :             : 
     649                 :      345486 :   if (!best_mult_cost)
     650                 :      338193 :     return;
     651                 :             : 
     652                 :             :   /* Collect elements multiplied by best_mult.  */
     653                 :       17675 :   for (i = j = 0; i < addr->n; i++)
     654                 :             :     {
     655                 :       10382 :       offset_int amult = offset_int::from (addr->elts[i].coef, SIGNED);
     656                 :       10382 :       offset_int amult_neg = -wi::sext (amult, TYPE_PRECISION (addr->type));
     657                 :             : 
     658                 :       10382 :       if (amult == best_mult)
     659                 :             :         op_code = PLUS_EXPR;
     660                 :        2926 :       else if (amult_neg == best_mult)
     661                 :             :         op_code = MINUS_EXPR;
     662                 :             :       else
     663                 :             :         {
     664                 :         217 :           addr->elts[j] = addr->elts[i];
     665                 :         217 :           j++;
     666                 :         217 :           continue;
     667                 :             :         }
     668                 :             : 
     669                 :       10165 :       elt = fold_convert (sizetype, addr->elts[i].val);
     670                 :       10165 :       if (mult_elt)
     671                 :        2872 :         mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
     672                 :        7293 :       else if (op_code == PLUS_EXPR)
     673                 :             :         mult_elt = elt;
     674                 :             :       else
     675                 :         400 :         mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
     676                 :             :     }
     677                 :        7293 :   addr->n = j;
     678                 :             : 
     679                 :        7293 :   parts->index = mult_elt;
     680                 :        7293 :   parts->step = wide_int_to_tree (sizetype, best_mult);
     681                 :             : }
     682                 :             : 
     683                 :             : /* Splits address ADDR for a memory access of type TYPE into PARTS.
     684                 :             :    If BASE_HINT is non-NULL, it specifies an SSA name to be used
     685                 :             :    preferentially as base of the reference, and IV_CAND is the selected
     686                 :             :    iv candidate used in ADDR.  Store true to VAR_IN_BASE if variant
     687                 :             :    part of address is split to PARTS.base.
     688                 :             : 
     689                 :             :    TODO -- be more clever about the distribution of the elements of ADDR
     690                 :             :    to PARTS.  Some architectures do not support anything but single
     691                 :             :    register in address, possibly with a small integer offset; while
     692                 :             :    create_mem_ref will simplify the address to an acceptable shape
     693                 :             :    later, it would be more efficient to know that asking for complicated
     694                 :             :    addressing modes is useless.  */
     695                 :             : 
     696                 :             : static void
     697                 :      735307 : addr_to_parts (tree type, aff_tree *addr, tree iv_cand, tree base_hint,
     698                 :             :                struct mem_address *parts, bool *var_in_base, bool speed)
     699                 :             : {
     700                 :      735307 :   tree part;
     701                 :      735307 :   unsigned i;
     702                 :             : 
     703                 :      735307 :   parts->symbol = NULL_TREE;
     704                 :      735307 :   parts->base = NULL_TREE;
     705                 :      735307 :   parts->index = NULL_TREE;
     706                 :      735307 :   parts->step = NULL_TREE;
     707                 :             : 
     708                 :      735307 :   if (maybe_ne (addr->offset, 0))
     709                 :      269380 :     parts->offset = wide_int_to_tree (sizetype, addr->offset);
     710                 :             :   else
     711                 :      465927 :     parts->offset = NULL_TREE;
     712                 :             : 
     713                 :             :   /* Try to find a symbol.  */
     714                 :      735307 :   move_fixed_address_to_symbol (parts, addr);
     715                 :             : 
     716                 :             :   /* Since at the moment there is no reliable way to know how to
     717                 :             :      distinguish between pointer and its offset, we decide if var
     718                 :             :      part is the pointer based on guess.  */
     719                 :      735307 :   *var_in_base = (base_hint != NULL && parts->symbol == NULL);
     720                 :      735307 :   if (*var_in_base)
     721                 :      345305 :     *var_in_base = move_hint_to_base (type, parts, base_hint, addr);
     722                 :             :   else
     723                 :      390002 :     move_variant_to_index (parts, addr, iv_cand);
     724                 :             : 
     725                 :             :   /* First move the most expensive feasible multiplication to index.  */
     726                 :      735307 :   if (!parts->index)
     727                 :      345486 :     most_expensive_mult_to_index (type, parts, addr, speed);
     728                 :             : 
     729                 :             :   /* Move pointer into base.  */
     730                 :      735307 :   if (!parts->symbol && !parts->base)
     731                 :      285733 :     move_pointer_to_base (parts, addr);
     732                 :             : 
     733                 :             :   /* Then try to process the remaining elements.  */
     734                 :      776414 :   for (i = 0; i < addr->n; i++)
     735                 :             :     {
     736                 :       41107 :       part = fold_convert (sizetype, addr->elts[i].val);
     737                 :       41107 :       if (addr->elts[i].coef != 1)
     738                 :       38525 :         part = fold_build2 (MULT_EXPR, sizetype, part,
     739                 :             :                             wide_int_to_tree (sizetype, addr->elts[i].coef));
     740                 :       41107 :       add_to_parts (parts, part);
     741                 :             :     }
     742                 :      735307 :   if (addr->rest)
     743                 :           0 :     add_to_parts (parts, fold_convert (sizetype, addr->rest));
     744                 :      735307 : }
     745                 :             : 
     746                 :             : /* Force the PARTS to register.  */
     747                 :             : 
     748                 :             : static void
     749                 :      735307 : gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
     750                 :             : {
     751                 :      735307 :   if (parts->base)
     752                 :      638434 :     parts->base = force_gimple_operand_gsi_1 (gsi, parts->base,
     753                 :             :                                             is_gimple_mem_ref_addr, NULL_TREE,
     754                 :             :                                             true, GSI_SAME_STMT);
     755                 :      735307 :   if (parts->index)
     756                 :      402319 :     parts->index = force_gimple_operand_gsi (gsi, parts->index,
     757                 :             :                                              true, NULL_TREE,
     758                 :             :                                              true, GSI_SAME_STMT);
     759                 :      735307 : }
     760                 :             : 
     761                 :             : /* Return true if the OFFSET in PARTS is the only thing that is making
     762                 :             :    it an invalid address for type TYPE.  */
     763                 :             : 
     764                 :             : static bool
     765                 :       19089 : mem_ref_valid_without_offset_p (tree type, mem_address parts)
     766                 :             : {
     767                 :       19089 :   if (!parts.base)
     768                 :           0 :     parts.base = parts.offset;
     769                 :       19089 :   parts.offset = NULL_TREE;
     770                 :       19089 :   return valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), &parts);
     771                 :             : }
     772                 :             : 
     773                 :             : /* Fold PARTS->offset into PARTS->base, so that there is no longer
     774                 :             :    a separate offset.  Emit any new instructions before GSI.  */
     775                 :             : 
     776                 :             : static void
     777                 :           0 : add_offset_to_base (gimple_stmt_iterator *gsi, mem_address *parts)
     778                 :             : {
     779                 :           0 :   tree tmp = parts->offset;
     780                 :           0 :   if (parts->base)
     781                 :             :     {
     782                 :           0 :       tmp = fold_build_pointer_plus (parts->base, tmp);
     783                 :           0 :       tmp = force_gimple_operand_gsi_1 (gsi, tmp, is_gimple_mem_ref_addr,
     784                 :             :                                         NULL_TREE, true, GSI_SAME_STMT);
     785                 :             :     }
     786                 :           0 :   parts->base = tmp;
     787                 :           0 :   parts->offset = NULL_TREE;
     788                 :           0 : }
     789                 :             : 
     790                 :             : /* Creates and returns a TARGET_MEM_REF for address ADDR.  If necessary
     791                 :             :    computations are emitted in front of GSI.  TYPE is the mode
     792                 :             :    of created memory reference. IV_CAND is the selected iv candidate in ADDR,
     793                 :             :    and BASE_HINT is non NULL if IV_CAND comes from a base address
     794                 :             :    object.  */
     795                 :             : 
     796                 :             : tree
     797                 :      735307 : create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
     798                 :             :                 tree alias_ptr_type, tree iv_cand, tree base_hint, bool speed)
     799                 :             : {
     800                 :      735307 :   bool var_in_base;
     801                 :      735307 :   tree mem_ref, tmp;
     802                 :      735307 :   struct mem_address parts;
     803                 :             : 
     804                 :      735307 :   addr_to_parts (type, addr, iv_cand, base_hint, &parts, &var_in_base, speed);
     805                 :      735307 :   gimplify_mem_ref_parts (gsi, &parts);
     806                 :      735307 :   mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     807                 :      735307 :   if (mem_ref)
     808                 :             :     return mem_ref;
     809                 :             : 
     810                 :             :   /* The expression is too complicated.  Try making it simpler.  */
     811                 :             : 
     812                 :             :   /* Merge symbol into other parts.  */
     813                 :       33635 :   if (parts.symbol)
     814                 :             :     {
     815                 :         980 :       tmp = parts.symbol;
     816                 :         980 :       parts.symbol = NULL_TREE;
     817                 :         980 :       gcc_assert (is_gimple_val (tmp));
     818                 :             : 
     819                 :         980 :       if (parts.base)
     820                 :             :         {
     821                 :          40 :           gcc_assert (useless_type_conversion_p (sizetype,
     822                 :             :                                                  TREE_TYPE (parts.base)));
     823                 :             : 
     824                 :          40 :           if (parts.index)
     825                 :             :             {
     826                 :             :               /* Add the symbol to base, eventually forcing it to register.  */
     827                 :          40 :               tmp = fold_build_pointer_plus (tmp, parts.base);
     828                 :          40 :               tmp = force_gimple_operand_gsi_1 (gsi, tmp,
     829                 :             :                                                 is_gimple_mem_ref_addr,
     830                 :             :                                                 NULL_TREE, true,
     831                 :             :                                                 GSI_SAME_STMT);
     832                 :             :             }
     833                 :             :           else
     834                 :             :             {
     835                 :             :               /* Move base to index, then move the symbol to base.  */
     836                 :           0 :               parts.index = parts.base;
     837                 :             :             }
     838                 :          40 :           parts.base = tmp;
     839                 :             :         }
     840                 :             :       else
     841                 :         940 :         parts.base = tmp;
     842                 :             : 
     843                 :         980 :       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     844                 :         980 :       if (mem_ref)
     845                 :             :         return mem_ref;
     846                 :             :     }
     847                 :             : 
     848                 :             :   /* Move multiplication to index by transforming address expression:
     849                 :             :        [... + index << step + ...]
     850                 :             :      into:
     851                 :             :        index' = index << step;
     852                 :             :        [... + index' + ,,,].  */
     853                 :       33338 :   if (parts.step && !integer_onep (parts.step))
     854                 :             :     {
     855                 :       33324 :       gcc_assert (parts.index);
     856                 :       33324 :       if (parts.offset && mem_ref_valid_without_offset_p (type, parts))
     857                 :             :         {
     858                 :           0 :           add_offset_to_base (gsi, &parts);
     859                 :           0 :           mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     860                 :           0 :           gcc_assert (mem_ref);
     861                 :             :           return mem_ref;
     862                 :             :         }
     863                 :             : 
     864                 :       33324 :       parts.index = force_gimple_operand_gsi (gsi,
     865                 :             :                                 fold_build2 (MULT_EXPR, sizetype,
     866                 :             :                                              parts.index, parts.step),
     867                 :             :                                 true, NULL_TREE, true, GSI_SAME_STMT);
     868                 :       33324 :       parts.step = NULL_TREE;
     869                 :             : 
     870                 :       33324 :       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     871                 :       33324 :       if (mem_ref)
     872                 :             :         return mem_ref;
     873                 :             :     }
     874                 :             : 
     875                 :             :   /* Add offset to invariant part by transforming address expression:
     876                 :             :        [base + index + offset]
     877                 :             :      into:
     878                 :             :        base' = base + offset;
     879                 :             :        [base' + index]
     880                 :             :      or:
     881                 :             :        index' = index + offset;
     882                 :             :        [base + index']
     883                 :             :      depending on which one is invariant.  */
     884                 :          14 :   if (parts.offset && !integer_zerop (parts.offset))
     885                 :             :     {
     886                 :          14 :       tree old_base = unshare_expr (parts.base);
     887                 :          14 :       tree old_index = unshare_expr (parts.index);
     888                 :          14 :       tree old_offset = unshare_expr (parts.offset);
     889                 :             : 
     890                 :          14 :       tmp = parts.offset;
     891                 :          14 :       parts.offset = NULL_TREE;
     892                 :             :       /* Add offset to invariant part.  */
     893                 :          14 :       if (!var_in_base)
     894                 :             :         {
     895                 :           8 :           if (parts.base)
     896                 :             :             {
     897                 :           8 :               tmp = fold_build_pointer_plus (parts.base, tmp);
     898                 :           8 :               tmp = force_gimple_operand_gsi_1 (gsi, tmp,
     899                 :             :                                                 is_gimple_mem_ref_addr,
     900                 :             :                                                 NULL_TREE, true,
     901                 :             :                                                 GSI_SAME_STMT);
     902                 :             :             }
     903                 :           8 :           parts.base = tmp;
     904                 :             :         }
     905                 :             :       else
     906                 :             :         {
     907                 :           6 :           if (parts.index)
     908                 :             :             {
     909                 :           0 :               tmp = fold_build_pointer_plus (parts.index, tmp);
     910                 :           0 :               tmp = force_gimple_operand_gsi_1 (gsi, tmp,
     911                 :             :                                                 is_gimple_mem_ref_addr,
     912                 :             :                                                 NULL_TREE, true,
     913                 :             :                                                 GSI_SAME_STMT);
     914                 :             :             }
     915                 :           6 :           parts.index = tmp;
     916                 :             :         }
     917                 :             : 
     918                 :          14 :       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     919                 :          14 :       if (mem_ref)
     920                 :             :         return mem_ref;
     921                 :             : 
     922                 :             :       /* Restore parts.base, index and offset so that we can check if
     923                 :             :          [base + offset] addressing mode is supported in next step.
     924                 :             :          This is necessary for targets only support [base + offset],
     925                 :             :          but not [base + index] addressing mode.  */
     926                 :           0 :       parts.base = old_base;
     927                 :           0 :       parts.index = old_index;
     928                 :           0 :       parts.offset = old_offset;
     929                 :             :     }
     930                 :             : 
     931                 :             :   /* Transform [base + index + ...] into:
     932                 :             :        base' = base + index;
     933                 :             :        [base' + ...].  */
     934                 :           0 :   if (parts.index)
     935                 :             :     {
     936                 :           0 :       tmp = parts.index;
     937                 :           0 :       parts.index = NULL_TREE;
     938                 :             :       /* Add index to base.  */
     939                 :           0 :       if (parts.base)
     940                 :             :         {
     941                 :           0 :           tmp = fold_build_pointer_plus (parts.base, tmp);
     942                 :           0 :           tmp = force_gimple_operand_gsi_1 (gsi, tmp,
     943                 :             :                                             is_gimple_mem_ref_addr,
     944                 :             :                                             NULL_TREE, true, GSI_SAME_STMT);
     945                 :             :         }
     946                 :           0 :       parts.base = tmp;
     947                 :             : 
     948                 :           0 :       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     949                 :           0 :       if (mem_ref)
     950                 :             :         return mem_ref;
     951                 :             :     }
     952                 :             : 
     953                 :             :   /* Transform [base + offset] into:
     954                 :             :        base' = base + offset;
     955                 :             :        [base'].  */
     956                 :           0 :   if (parts.offset && !integer_zerop (parts.offset))
     957                 :             :     {
     958                 :           0 :       add_offset_to_base (gsi, &parts);
     959                 :           0 :       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
     960                 :           0 :       if (mem_ref)
     961                 :             :         return mem_ref;
     962                 :             :     }
     963                 :             : 
     964                 :             :   /* Verify that the address is in the simplest possible shape
     965                 :             :      (only a register).  If we cannot create such a memory reference,
     966                 :             :      something is really wrong.  */
     967                 :           0 :   gcc_assert (parts.symbol == NULL_TREE);
     968                 :           0 :   gcc_assert (parts.index == NULL_TREE);
     969                 :           0 :   gcc_assert (!parts.step || integer_onep (parts.step));
     970                 :           0 :   gcc_assert (!parts.offset || integer_zerop (parts.offset));
     971                 :           0 :   gcc_unreachable ();
     972                 :             : }
     973                 :             : 
     974                 :             : /* Copies components of the address from OP to ADDR.  */
     975                 :             : 
     976                 :             : void
     977                 :     2387506 : get_address_description (tree op, struct mem_address *addr)
     978                 :             : {
     979                 :     2387506 :   if (TREE_CODE (TMR_BASE (op)) == ADDR_EXPR)
     980                 :             :     {
     981                 :      588305 :       addr->symbol = TMR_BASE (op);
     982                 :      588305 :       addr->base = TMR_INDEX2 (op);
     983                 :             :     }
     984                 :             :   else
     985                 :             :     {
     986                 :     1799201 :       addr->symbol = NULL_TREE;
     987                 :     1799201 :       if (TMR_INDEX2 (op))
     988                 :             :         {
     989                 :          77 :           gcc_assert (integer_zerop (TMR_BASE (op)));
     990                 :          77 :           addr->base = TMR_INDEX2 (op);
     991                 :             :         }
     992                 :             :       else
     993                 :     1799124 :         addr->base = TMR_BASE (op);
     994                 :             :     }
     995                 :     2387506 :   addr->index = TMR_INDEX (op);
     996                 :     2387506 :   addr->step = TMR_STEP (op);
     997                 :     2387506 :   addr->offset = TMR_OFFSET (op);
     998                 :     2387506 : }
     999                 :             : 
    1000                 :             : /* Copies the reference information from OLD_REF to NEW_REF, where
    1001                 :             :    NEW_REF should be either a MEM_REF or a TARGET_MEM_REF.  */
    1002                 :             : 
    1003                 :             : void
    1004                 :      748680 : copy_ref_info (tree new_ref, tree old_ref)
    1005                 :             : {
    1006                 :      748680 :   tree new_ptr_base = NULL_TREE;
    1007                 :             : 
    1008                 :      748680 :   gcc_assert (TREE_CODE (new_ref) == MEM_REF
    1009                 :             :               || TREE_CODE (new_ref) == TARGET_MEM_REF);
    1010                 :             : 
    1011                 :      748680 :   TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
    1012                 :      748680 :   TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
    1013                 :             : 
    1014                 :      748680 :   new_ptr_base = TREE_OPERAND (new_ref, 0);
    1015                 :             : 
    1016                 :      748680 :   tree base = get_base_address (old_ref);
    1017                 :      748680 :   if (!base)
    1018                 :             :     return;
    1019                 :             : 
    1020                 :             :   /* We can transfer points-to information from an old pointer
    1021                 :             :      or decl base to the new one.  */
    1022                 :      748680 :   if (new_ptr_base
    1023                 :      748680 :       && TREE_CODE (new_ptr_base) == SSA_NAME
    1024                 :     1310081 :       && !SSA_NAME_PTR_INFO (new_ptr_base))
    1025                 :             :     {
    1026                 :      285172 :       if ((TREE_CODE (base) == MEM_REF
    1027                 :      285172 :            || TREE_CODE (base) == TARGET_MEM_REF)
    1028                 :      240703 :           && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
    1029                 :      525875 :           && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
    1030                 :             :         {
    1031                 :      221774 :           duplicate_ssa_name_ptr_info
    1032                 :      221774 :             (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
    1033                 :      221774 :           reset_flow_sensitive_info (new_ptr_base);
    1034                 :             :         }
    1035                 :       63398 :       else if (VAR_P (base)
    1036                 :             :                || TREE_CODE (base) == PARM_DECL
    1037                 :             :                || TREE_CODE (base) == RESULT_DECL)
    1038                 :             :         {
    1039                 :       44469 :           struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
    1040                 :       44469 :           pt_solution_set_var (&pi->pt, base);
    1041                 :             :         }
    1042                 :             :     }
    1043                 :             : 
    1044                 :             :   /* We can transfer dependence info.  */
    1045                 :      748680 :   if (!MR_DEPENDENCE_CLIQUE (new_ref)
    1046                 :      748680 :       && (TREE_CODE (base) == MEM_REF
    1047                 :      748680 :           || TREE_CODE (base) == TARGET_MEM_REF)
    1048                 :     1343398 :       && MR_DEPENDENCE_CLIQUE (base))
    1049                 :             :     {
    1050                 :      148850 :       MR_DEPENDENCE_CLIQUE (new_ref) = MR_DEPENDENCE_CLIQUE (base);
    1051                 :      148850 :       MR_DEPENDENCE_BASE (new_ref) = MR_DEPENDENCE_BASE (base);
    1052                 :             :     }
    1053                 :             : 
    1054                 :             :   /* And alignment info.  Note we cannot transfer misalignment info
    1055                 :             :      since that sits on the SSA name but this is flow-sensitive info
    1056                 :             :      which we cannot transfer in this generic routine.  */
    1057                 :      748680 :   unsigned old_align = get_object_alignment (old_ref);
    1058                 :      748680 :   unsigned new_align = get_object_alignment (new_ref);
    1059                 :      748680 :   if (new_align < old_align)
    1060                 :         771 :     TREE_TYPE (new_ref) = build_aligned_type (TREE_TYPE (new_ref), old_align);
    1061                 :             : }
    1062                 :             : 
    1063                 :             : /* Move constants in target_mem_ref REF to offset.  Returns the new target
    1064                 :             :    mem ref if anything changes, NULL_TREE otherwise.  */
    1065                 :             : 
    1066                 :             : tree
    1067                 :     1662025 : maybe_fold_tmr (tree ref)
    1068                 :             : {
    1069                 :     1662025 :   struct mem_address addr;
    1070                 :     1662025 :   bool changed = false;
    1071                 :     1662025 :   tree new_ref, off;
    1072                 :             : 
    1073                 :     1662025 :   get_address_description (ref, &addr);
    1074                 :             : 
    1075                 :     1662025 :   if (addr.base
    1076                 :     1281520 :       && TREE_CODE (addr.base) == INTEGER_CST
    1077                 :     1662046 :       && !integer_zerop (addr.base))
    1078                 :             :     {
    1079                 :           0 :       addr.offset = fold_binary_to_constant (PLUS_EXPR,
    1080                 :           0 :                                              TREE_TYPE (addr.offset),
    1081                 :             :                                              addr.offset, addr.base);
    1082                 :           0 :       addr.base = NULL_TREE;
    1083                 :           0 :       changed = true;
    1084                 :             :     }
    1085                 :             : 
    1086                 :     1662025 :   if (addr.symbol
    1087                 :     1662025 :       && TREE_CODE (TREE_OPERAND (addr.symbol, 0)) == MEM_REF)
    1088                 :             :     {
    1089                 :           0 :       addr.offset = fold_binary_to_constant
    1090                 :           0 :                         (PLUS_EXPR, TREE_TYPE (addr.offset),
    1091                 :             :                          addr.offset,
    1092                 :           0 :                          TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 1));
    1093                 :           0 :       addr.symbol = TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 0);
    1094                 :           0 :       changed = true;
    1095                 :             :     }
    1096                 :     1662025 :   else if (addr.symbol
    1097                 :     1662025 :            && handled_component_p (TREE_OPERAND (addr.symbol, 0)))
    1098                 :             :     {
    1099                 :           0 :       poly_int64 offset;
    1100                 :           0 :       addr.symbol = build_fold_addr_expr
    1101                 :             :                       (get_addr_base_and_unit_offset
    1102                 :             :                          (TREE_OPERAND (addr.symbol, 0), &offset));
    1103                 :           0 :       addr.offset = int_const_binop (PLUS_EXPR,
    1104                 :           0 :                                      addr.offset, size_int (offset));
    1105                 :           0 :       changed = true;
    1106                 :             :     }
    1107                 :             : 
    1108                 :     1662025 :   if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
    1109                 :             :     {
    1110                 :        1235 :       off = addr.index;
    1111                 :        1235 :       if (addr.step)
    1112                 :             :         {
    1113                 :        1202 :           off = fold_binary_to_constant (MULT_EXPR, sizetype,
    1114                 :             :                                          off, addr.step);
    1115                 :        1202 :           addr.step = NULL_TREE;
    1116                 :             :         }
    1117                 :             : 
    1118                 :        1235 :       addr.offset = fold_binary_to_constant (PLUS_EXPR,
    1119                 :        1235 :                                              TREE_TYPE (addr.offset),
    1120                 :             :                                              addr.offset, off);
    1121                 :        1235 :       addr.index = NULL_TREE;
    1122                 :        1235 :       changed = true;
    1123                 :             :     }
    1124                 :             : 
    1125                 :     1662025 :   if (!changed)
    1126                 :             :     return NULL_TREE;
    1127                 :             : 
    1128                 :             :   /* If we have propagated something into this TARGET_MEM_REF and thus
    1129                 :             :      ended up folding it, always create a new TARGET_MEM_REF regardless
    1130                 :             :      if it is valid in this for on the target - the propagation result
    1131                 :             :      wouldn't be anyway.  */
    1132                 :        1235 :   new_ref = create_mem_ref_raw (TREE_TYPE (ref),
    1133                 :        1235 :                                 TREE_TYPE (addr.offset), &addr, false);
    1134                 :        1235 :   TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (ref);
    1135                 :        1235 :   TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (ref);
    1136                 :        1235 :   return new_ref;
    1137                 :             : }
    1138                 :             : 
    1139                 :             : /* Return the preferred index scale factor for accessing memory of mode
    1140                 :             :    MEM_MODE in the address space of pointer BASE.  Assume that we're
    1141                 :             :    optimizing for speed if SPEED is true and for size otherwise.  */
    1142                 :             : unsigned int
    1143                 :      451396 : preferred_mem_scale_factor (tree base, machine_mode mem_mode,
    1144                 :             :                             bool speed)
    1145                 :             : {
    1146                 :             :   /* For BLKmode, we can't do anything so return 1.  */
    1147                 :      451396 :   if (mem_mode == BLKmode)
    1148                 :             :     return 1;
    1149                 :             : 
    1150                 :      437800 :   struct mem_address parts = {};
    1151                 :      437800 :   addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
    1152                 :      437800 :   unsigned int fact = GET_MODE_UNIT_SIZE (mem_mode);
    1153                 :             : 
    1154                 :             :   /* Addressing mode "base + index".  */
    1155                 :      437800 :   parts.index = integer_one_node;
    1156                 :      437800 :   parts.base = integer_one_node;
    1157                 :      437800 :   rtx addr = addr_for_mem_ref (&parts, as, false);
    1158                 :      437800 :   unsigned cost = address_cost (addr, mem_mode, as, speed);
    1159                 :             : 
    1160                 :             :   /* Addressing mode "base + index << scale".  */
    1161                 :      437800 :   parts.step = wide_int_to_tree (sizetype, fact);
    1162                 :      437800 :   addr = addr_for_mem_ref (&parts, as, false);
    1163                 :      437800 :   unsigned new_cost = address_cost (addr, mem_mode, as, speed);
    1164                 :             : 
    1165                 :             :   /* Compare the cost of an address with an unscaled index with
    1166                 :             :      a scaled index and return factor if useful. */
    1167                 :      437800 :   if (new_cost < cost)
    1168                 :           0 :     return GET_MODE_UNIT_SIZE (mem_mode);
    1169                 :             :   return 1;
    1170                 :             : }
    1171                 :             : 
    1172                 :             : /* Dump PARTS to FILE.  */
    1173                 :             : 
    1174                 :             : extern void dump_mem_address (FILE *, struct mem_address *);
    1175                 :             : void
    1176                 :           0 : dump_mem_address (FILE *file, struct mem_address *parts)
    1177                 :             : {
    1178                 :           0 :   if (parts->symbol)
    1179                 :             :     {
    1180                 :           0 :       fprintf (file, "symbol: ");
    1181                 :           0 :       print_generic_expr (file, TREE_OPERAND (parts->symbol, 0), TDF_SLIM);
    1182                 :           0 :       fprintf (file, "\n");
    1183                 :             :     }
    1184                 :           0 :   if (parts->base)
    1185                 :             :     {
    1186                 :           0 :       fprintf (file, "base: ");
    1187                 :           0 :       print_generic_expr (file, parts->base, TDF_SLIM);
    1188                 :           0 :       fprintf (file, "\n");
    1189                 :             :     }
    1190                 :           0 :   if (parts->index)
    1191                 :             :     {
    1192                 :           0 :       fprintf (file, "index: ");
    1193                 :           0 :       print_generic_expr (file, parts->index, TDF_SLIM);
    1194                 :           0 :       fprintf (file, "\n");
    1195                 :             :     }
    1196                 :           0 :   if (parts->step)
    1197                 :             :     {
    1198                 :           0 :       fprintf (file, "step: ");
    1199                 :           0 :       print_generic_expr (file, parts->step, TDF_SLIM);
    1200                 :           0 :       fprintf (file, "\n");
    1201                 :             :     }
    1202                 :           0 :   if (parts->offset)
    1203                 :             :     {
    1204                 :           0 :       fprintf (file, "offset: ");
    1205                 :           0 :       print_generic_expr (file, parts->offset, TDF_SLIM);
    1206                 :           0 :       fprintf (file, "\n");
    1207                 :             :     }
    1208                 :           0 : }
    1209                 :             : 
    1210                 :             : #include "gt-tree-ssa-address.h"
        

Generated by: LCOV version 2.1-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.