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

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.