LCOV - code coverage report
Current view: top level - gcc - avoid-store-forwarding.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.3 % 293 250
Test Date: 2025-06-21 16:26:05 Functions: 100.0 % 8 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Avoid store forwarding optimization pass.
       2                 :             :    Copyright (C) 2024-2025 Free Software Foundation, Inc.
       3                 :             :    Contributed by VRULL GmbH.
       4                 :             : 
       5                 :             :    This file is part of GCC.
       6                 :             : 
       7                 :             :    GCC is free software; you can redistribute it and/or modify it
       8                 :             :    under the terms of the GNU General Public License as published by
       9                 :             :    the Free Software Foundation; either version 3, or (at your option)
      10                 :             :    any later version.
      11                 :             : 
      12                 :             :    GCC is distributed in the hope that it will be useful, but
      13                 :             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :    General Public License for more details.
      16                 :             : 
      17                 :             :    You should have received a copy of the GNU General Public License
      18                 :             :    along with GCC; see the file COPYING3.  If not see
      19                 :             :    <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : #include "avoid-store-forwarding.h"
      22                 :             : #include "config.h"
      23                 :             : #include "system.h"
      24                 :             : #include "coretypes.h"
      25                 :             : #include "backend.h"
      26                 :             : #include "target.h"
      27                 :             : #include "rtl.h"
      28                 :             : #include "alias.h"
      29                 :             : #include "rtlanal.h"
      30                 :             : #include "cfgrtl.h"
      31                 :             : #include "tree-pass.h"
      32                 :             : #include "cselib.h"
      33                 :             : #include "predict.h"
      34                 :             : #include "insn-config.h"
      35                 :             : #include "expmed.h"
      36                 :             : #include "recog.h"
      37                 :             : #include "regset.h"
      38                 :             : #include "df.h"
      39                 :             : #include "expr.h"
      40                 :             : #include "memmodel.h"
      41                 :             : #include "emit-rtl.h"
      42                 :             : #include "vec.h"
      43                 :             : 
      44                 :             : /* This pass tries to detect and avoid cases of store forwarding.
      45                 :             :    On many processors there is a large penalty when smaller stores are
      46                 :             :    forwarded to larger loads.  The idea used to avoid the stall is to move
      47                 :             :    the store after the load and in addition emit a bit insert sequence so
      48                 :             :    the load register has the correct value.  For example the following:
      49                 :             : 
      50                 :             :      strb    w2, [x1, 1]
      51                 :             :      ldr     x0, [x1]
      52                 :             : 
      53                 :             :    Will be transformed to:
      54                 :             : 
      55                 :             :      ldr     x0, [x1]
      56                 :             :      strb    w2, [x1]
      57                 :             :      bfi     x0, x2, 0, 8
      58                 :             : */
      59                 :             : 
      60                 :             : namespace {
      61                 :             : 
      62                 :             : const pass_data pass_data_avoid_store_forwarding =
      63                 :             : {
      64                 :             :   RTL_PASS, /* type.  */
      65                 :             :   "avoid_store_forwarding", /* name.  */
      66                 :             :   OPTGROUP_NONE, /* optinfo_flags.  */
      67                 :             :   TV_AVOID_STORE_FORWARDING, /* tv_id.  */
      68                 :             :   0, /* properties_required.  */
      69                 :             :   0, /* properties_provided.  */
      70                 :             :   0, /* properties_destroyed.  */
      71                 :             :   0, /* todo_flags_start.  */
      72                 :             :   TODO_df_finish /* todo_flags_finish.  */
      73                 :             : };
      74                 :             : 
      75                 :             : class pass_rtl_avoid_store_forwarding : public rtl_opt_pass
      76                 :             : {
      77                 :             : public:
      78                 :      285081 :   pass_rtl_avoid_store_forwarding (gcc::context *ctxt)
      79                 :      570162 :     : rtl_opt_pass (pass_data_avoid_store_forwarding, ctxt)
      80                 :             :   {}
      81                 :             : 
      82                 :             :   /* opt_pass methods: */
      83                 :     1449863 :   virtual bool gate (function *)
      84                 :             :     {
      85                 :     1449863 :       return flag_avoid_store_forwarding && optimize >= 1;
      86                 :             :     }
      87                 :             : 
      88                 :             :   virtual unsigned int execute (function *) override;
      89                 :             : }; // class pass_rtl_avoid_store_forwarding
      90                 :             : 
      91                 :             : /* Handler for finding and avoiding store forwardings.  */
      92                 :             : 
      93                 :             : class store_forwarding_analyzer
      94                 :             : {
      95                 :             : public:
      96                 :             :   unsigned int stats_sf_detected = 0;
      97                 :             :   unsigned int stats_sf_avoided = 0;
      98                 :             : 
      99                 :             :   bool is_store_forwarding (rtx store_mem, rtx load_mem,
     100                 :             :                             HOST_WIDE_INT *off_val);
     101                 :             :   bool process_store_forwarding (vec<store_fwd_info> &, rtx_insn *load_insn,
     102                 :             :                                  rtx load_mem);
     103                 :             :   void avoid_store_forwarding (basic_block);
     104                 :             :   void update_stats (function *);
     105                 :             : };
     106                 :             : 
     107                 :             : /* Return a bit insertion sequence that would make DEST have the correct value
     108                 :             :    if the store represented by STORE_INFO were to be moved after DEST.  */
     109                 :             : 
     110                 :             : static rtx_insn *
     111                 :          53 : generate_bit_insert_sequence (store_fwd_info *store_info, rtx dest)
     112                 :             : {
     113                 :             :   /* Memory size should be a constant at this stage.  */
     114                 :          53 :   unsigned HOST_WIDE_INT store_size
     115                 :          53 :     = MEM_SIZE (store_info->store_mem).to_constant ();
     116                 :             : 
     117                 :          53 :   start_sequence ();
     118                 :             : 
     119                 :          53 :   unsigned HOST_WIDE_INT bitsize = store_size * BITS_PER_UNIT;
     120                 :          53 :   unsigned HOST_WIDE_INT start = store_info->offset * BITS_PER_UNIT;
     121                 :             : 
     122                 :             :   /* Adjust START for machines with BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN.
     123                 :             :      Given that the bytes will be reversed in this case, we need to
     124                 :             :      calculate the starting position from the end of the destination
     125                 :             :      register.  */
     126                 :          53 :   if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
     127                 :             :     {
     128                 :             :       unsigned HOST_WIDE_INT load_mode_bitsize
     129                 :             :         = (GET_MODE_BITSIZE (GET_MODE (dest))).to_constant ();
     130                 :             :       start = load_mode_bitsize - bitsize - start;
     131                 :             :     }
     132                 :             : 
     133                 :          53 :   rtx mov_reg = store_info->mov_reg;
     134                 :          53 :   store_bit_field (dest, bitsize, start, 0, 0, GET_MODE (mov_reg), mov_reg,
     135                 :             :                    false, false);
     136                 :             : 
     137                 :          53 :   rtx_insn *insns = get_insns ();
     138                 :          53 :   unshare_all_rtl_in_chain (insns);
     139                 :          53 :   end_sequence ();
     140                 :             : 
     141                 :         367 :   for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
     142                 :         314 :     if (contains_mem_rtx_p (PATTERN (insn))
     143                 :         314 :         || recog_memoized (insn) < 0)
     144                 :           0 :       return NULL;
     145                 :             : 
     146                 :             :   return insns;
     147                 :             : }
     148                 :             : 
     149                 :             : /* Return true iff a store to STORE_MEM would write to a sub-region of bytes
     150                 :             :    from what LOAD_MEM would read.  If true also store the relative byte offset
     151                 :             :    of the store within the load to OFF_VAL.  */
     152                 :             : 
     153                 :         356 : bool store_forwarding_analyzer::
     154                 :             : is_store_forwarding (rtx store_mem, rtx load_mem, HOST_WIDE_INT *off_val)
     155                 :             : {
     156                 :         356 :   poly_int64 load_offset, store_offset;
     157                 :         356 :   rtx load_base = strip_offset (XEXP (load_mem, 0), &load_offset);
     158                 :         356 :   rtx store_base = strip_offset (XEXP (store_mem, 0), &store_offset);
     159                 :         356 :   return (MEM_SIZE (load_mem).is_constant ()
     160                 :         356 :           && rtx_equal_p (load_base, store_base)
     161                 :         281 :           && known_subrange_p (store_offset, MEM_SIZE (store_mem),
     162                 :         281 :                                load_offset, MEM_SIZE (load_mem))
     163                 :          79 :           && (store_offset - load_offset).is_constant (off_val));
     164                 :             : }
     165                 :             : 
     166                 :             : /* Given a list of small stores that are forwarded to LOAD_INSN, try to
     167                 :             :    rearrange them so that a store-forwarding penalty doesn't occur.
     168                 :             :    The stores must be given in reverse program order, starting from the
     169                 :             :    one closer to LOAD_INSN.  */
     170                 :             : 
     171                 :          13 : bool store_forwarding_analyzer::
     172                 :             : process_store_forwarding (vec<store_fwd_info> &stores, rtx_insn *load_insn,
     173                 :             :                           rtx load_mem)
     174                 :             : {
     175                 :          13 :   machine_mode load_mem_mode = GET_MODE (load_mem);
     176                 :             :   /* Memory sizes should be constants at this stage.  */
     177                 :          13 :   HOST_WIDE_INT load_size = MEM_SIZE (load_mem).to_constant ();
     178                 :             : 
     179                 :             :   /* If the stores cover all the bytes of the load, then we can eliminate
     180                 :             :      the load entirely and use the computed value instead.
     181                 :             :      We can also eliminate stores on addresses that are overwritten
     182                 :             :      by later stores.  */
     183                 :             : 
     184                 :          13 :   sbitmap forwarded_bytes = sbitmap_alloc (load_size);
     185                 :          13 :   bitmap_clear (forwarded_bytes);
     186                 :             : 
     187                 :          13 :   unsigned int i;
     188                 :          13 :   store_fwd_info* it;
     189                 :          13 :   auto_vec<store_fwd_info> redundant_stores;
     190                 :          13 :   auto_vec<int> store_ind_to_remove;
     191                 :          92 :   FOR_EACH_VEC_ELT (stores, i, it)
     192                 :             :     {
     193                 :          79 :       HOST_WIDE_INT store_size = MEM_SIZE (it->store_mem).to_constant ();
     194                 :          79 :       if (bitmap_all_bits_in_range_p (forwarded_bytes, it->offset,
     195                 :          79 :                                       it->offset + store_size - 1))
     196                 :             :         {
     197                 :          16 :           redundant_stores.safe_push (*it);
     198                 :          16 :           store_ind_to_remove.safe_push (i);
     199                 :          16 :           continue;
     200                 :             :         }
     201                 :          63 :       bitmap_set_range (forwarded_bytes, it->offset, store_size);
     202                 :             :     }
     203                 :             : 
     204                 :          13 :   bitmap_not (forwarded_bytes, forwarded_bytes);
     205                 :          13 :   bool load_elim = bitmap_empty_p (forwarded_bytes);
     206                 :             : 
     207                 :          13 :   stats_sf_detected++;
     208                 :             : 
     209                 :          13 :   if (dump_file)
     210                 :             :     {
     211                 :           0 :       fprintf (dump_file, "Store forwarding detected:\n");
     212                 :             : 
     213                 :           0 :       FOR_EACH_VEC_ELT (stores, i, it)
     214                 :             :         {
     215                 :           0 :           fprintf (dump_file, "From: ");
     216                 :           0 :           print_rtl_single (dump_file, it->store_insn);
     217                 :             :         }
     218                 :             : 
     219                 :           0 :       fprintf (dump_file, "To: ");
     220                 :           0 :       print_rtl_single (dump_file, load_insn);
     221                 :             : 
     222                 :           0 :       if (load_elim)
     223                 :           0 :         fprintf (dump_file, "(Load elimination candidate)\n");
     224                 :             :     }
     225                 :             : 
     226                 :             :   /* Remove redundant stores from the vector.  Although this is quadratic,
     227                 :             :      there doesn't seem to be much point optimizing it.  The number of
     228                 :             :      redundant stores is expected to be low and the length of the list is
     229                 :             :      limited by a --param.  The dependence checking that we did earlier is
     230                 :             :      also quadratic in the size of this list.  */
     231                 :          13 :   store_ind_to_remove.reverse ();
     232                 :          35 :   for (int i : store_ind_to_remove)
     233                 :          16 :     stores.ordered_remove (i);
     234                 :             : 
     235                 :          13 :   rtx load = single_set (load_insn);
     236                 :          13 :   rtx dest;
     237                 :             : 
     238                 :          13 :   if (load_elim)
     239                 :          10 :     dest = gen_reg_rtx (load_mem_mode);
     240                 :             :   else
     241                 :           3 :     dest = SET_DEST (load);
     242                 :             : 
     243                 :          13 :   int move_to_front = -1;
     244                 :          13 :   int total_cost = 0;
     245                 :             : 
     246                 :             :   /* Check if we can emit bit insert instructions for all forwarded stores.  */
     247                 :          76 :   FOR_EACH_VEC_ELT (stores, i, it)
     248                 :             :     {
     249                 :          63 :       it->mov_reg = gen_reg_rtx (GET_MODE (it->store_mem));
     250                 :          63 :       rtx_insn *insns = NULL;
     251                 :          63 :       const bool has_zero_offset = it->offset == 0;
     252                 :             : 
     253                 :             :       /* If we're eliminating the load then find the store with zero offset
     254                 :             :          and use it as the base register to avoid a bit insert if possible.  */
     255                 :          63 :       if (load_elim && has_zero_offset)
     256                 :             :         {
     257                 :          10 :           start_sequence ();
     258                 :             : 
     259                 :          20 :           rtx base_reg = lowpart_subreg (GET_MODE (dest), it->mov_reg,
     260                 :          10 :                                          GET_MODE (it->mov_reg));
     261                 :             : 
     262                 :          10 :           if (base_reg)
     263                 :             :             {
     264                 :          10 :               rtx_insn *move0 = emit_move_insn (dest, base_reg);
     265                 :          10 :               if (recog_memoized (move0) >= 0)
     266                 :             :                 {
     267                 :          10 :                   insns = get_insns ();
     268                 :          10 :                   move_to_front = (int) i;
     269                 :             :                 }
     270                 :             :             }
     271                 :             : 
     272                 :          10 :           end_sequence ();
     273                 :             :         }
     274                 :             : 
     275                 :          10 :       if (!insns)
     276                 :          53 :         insns = generate_bit_insert_sequence (&(*it), dest);
     277                 :             : 
     278                 :          53 :       if (!insns)
     279                 :             :         {
     280                 :           0 :           if (dump_file)
     281                 :             :             {
     282                 :           0 :               fprintf (dump_file, "Failed due to: ");
     283                 :           0 :               print_rtl_single (dump_file, it->store_insn);
     284                 :             :             }
     285                 :           0 :           return false;
     286                 :             :         }
     287                 :             : 
     288                 :          63 :       total_cost += seq_cost (insns, true);
     289                 :          63 :       it->bits_insert_insns = insns;
     290                 :             : 
     291                 :          63 :       rtx store_set = single_set (it->store_insn);
     292                 :             : 
     293                 :             :       /* Create a register move at the store's original position to save the
     294                 :             :          stored value.  */
     295                 :          63 :       start_sequence ();
     296                 :          63 :       rtx_insn *insn1
     297                 :          63 :         = emit_insn (gen_rtx_SET (it->mov_reg, SET_SRC (store_set)));
     298                 :          63 :       end_sequence ();
     299                 :             : 
     300                 :          63 :       if (recog_memoized (insn1) < 0)
     301                 :             :         {
     302                 :           0 :           if (dump_file)
     303                 :             :             {
     304                 :           0 :               fprintf (dump_file, "Failed due to unrecognizable insn: ");
     305                 :           0 :               print_rtl_single (dump_file, insn1);
     306                 :             :             }
     307                 :           0 :           return false;
     308                 :             :         }
     309                 :             : 
     310                 :          63 :       it->save_store_value_insn = insn1;
     311                 :             : 
     312                 :             :       /* Create a new store after the load with the saved original value.
     313                 :             :          This avoids the forwarding stall.  */
     314                 :          63 :       start_sequence ();
     315                 :          63 :       rtx_insn *insn2
     316                 :          63 :         = emit_insn (gen_rtx_SET (SET_DEST (store_set), it->mov_reg));
     317                 :          63 :       end_sequence ();
     318                 :             : 
     319                 :          63 :       if (recog_memoized (insn2) < 0)
     320                 :             :         {
     321                 :           0 :           if (dump_file)
     322                 :             :             {
     323                 :           0 :               fprintf (dump_file, "Failed due to unrecognizable insn: ");
     324                 :           0 :               print_rtl_single (dump_file, insn2);
     325                 :             :             }
     326                 :           0 :           return false;
     327                 :             :         }
     328                 :             : 
     329                 :          63 :       it->store_saved_value_insn = insn2;
     330                 :             :     }
     331                 :             : 
     332                 :          13 :   if (load_elim)
     333                 :          10 :     total_cost -= insn_cost (load_insn, true);
     334                 :             : 
     335                 :             :   /* Let the target decide if transforming this store forwarding instance is
     336                 :             :      profitable.  */
     337                 :          13 :   if (!targetm.avoid_store_forwarding_p (stores, load_mem, total_cost,
     338                 :             :                                          load_elim))
     339                 :             :     {
     340                 :           1 :       if (dump_file)
     341                 :           0 :         fprintf (dump_file, "Not transformed due to target decision.\n");
     342                 :             : 
     343                 :           1 :       return false;
     344                 :             :     }
     345                 :             : 
     346                 :             :   /* If we have a move instead of bit insert, it needs to be emitted first in
     347                 :             :      the resulting sequence.  */
     348                 :          12 :   if (move_to_front != -1)
     349                 :             :     {
     350                 :          10 :       store_fwd_info copy = stores[move_to_front];
     351                 :          10 :       stores.safe_push (copy);
     352                 :          10 :       stores.ordered_remove (move_to_front);
     353                 :             :     }
     354                 :             : 
     355                 :          12 :   if (load_elim)
     356                 :             :     {
     357                 :          10 :       machine_mode outer_mode = GET_MODE (SET_DEST (load));
     358                 :          10 :       rtx load_move;
     359                 :          10 :       rtx load_value = dest;
     360                 :          10 :       if (outer_mode != load_mem_mode)
     361                 :             :         {
     362                 :           0 :           load_value = simplify_gen_unary (GET_CODE (SET_SRC (load)),
     363                 :             :                                            outer_mode, dest, load_mem_mode);
     364                 :             :         }
     365                 :          10 :       load_move = gen_rtx_SET (SET_DEST (load), load_value);
     366                 :             : 
     367                 :          10 :       start_sequence ();
     368                 :          10 :       rtx_insn *insn = emit_insn (load_move);
     369                 :          10 :       rtx_insn *seq = end_sequence ();
     370                 :             : 
     371                 :          10 :       if (recog_memoized (insn) < 0)
     372                 :             :         return false;
     373                 :             : 
     374                 :          10 :       emit_insn_after (seq, load_insn);
     375                 :             :     }
     376                 :             : 
     377                 :          12 :   if (dump_file)
     378                 :             :     {
     379                 :           0 :       fprintf (dump_file, "Store forwarding avoided with bit inserts:\n");
     380                 :             : 
     381                 :           0 :       FOR_EACH_VEC_ELT (stores, i, it)
     382                 :             :         {
     383                 :           0 :           if (stores.length () > 1)
     384                 :             :             {
     385                 :           0 :               fprintf (dump_file, "For: ");
     386                 :           0 :               print_rtl_single (dump_file, it->store_insn);
     387                 :             :             }
     388                 :             : 
     389                 :           0 :           fprintf (dump_file, "With sequence:\n");
     390                 :             : 
     391                 :           0 :           for (rtx_insn *insn = it->bits_insert_insns; insn;
     392                 :           0 :                insn = NEXT_INSN (insn))
     393                 :             :             {
     394                 :           0 :               fprintf (dump_file, "  ");
     395                 :           0 :               print_rtl_single (dump_file, insn);
     396                 :             :             }
     397                 :             :         }
     398                 :             : 
     399                 :           0 :       if (redundant_stores.length () > 0)
     400                 :             :         {
     401                 :           0 :           fprintf (dump_file, "\nRedundant stores that have been removed:\n");
     402                 :           0 :           FOR_EACH_VEC_ELT (redundant_stores, i, it)
     403                 :             :             {
     404                 :           0 :               fprintf (dump_file, "  ");
     405                 :           0 :               print_rtl_single (dump_file, it->store_insn);
     406                 :             :             }
     407                 :             :         }
     408                 :             :     }
     409                 :             : 
     410                 :          12 :   stats_sf_avoided++;
     411                 :             : 
     412                 :             :   /* Done, emit all the generated instructions and delete the stores.
     413                 :             :      Note that STORES are in reverse program order.  */
     414                 :             : 
     415                 :          74 :   FOR_EACH_VEC_ELT (stores, i, it)
     416                 :             :     {
     417                 :          62 :       emit_insn_after (it->bits_insert_insns, load_insn);
     418                 :          62 :       emit_insn_after (it->store_saved_value_insn, load_insn);
     419                 :             :     }
     420                 :             : 
     421                 :          74 :   FOR_EACH_VEC_ELT (stores, i, it)
     422                 :             :     {
     423                 :          62 :       emit_insn_before (it->save_store_value_insn, it->store_insn);
     424                 :          62 :       delete_insn (it->store_insn);
     425                 :             :     }
     426                 :             : 
     427                 :             :   /* Delete redundant stores.  */
     428                 :          28 :   FOR_EACH_VEC_ELT (redundant_stores, i, it)
     429                 :          16 :     delete_insn (it->store_insn);
     430                 :             : 
     431                 :          12 :   df_insn_rescan (load_insn);
     432                 :             : 
     433                 :          12 :   if (load_elim)
     434                 :          10 :     delete_insn (load_insn);
     435                 :             : 
     436                 :             :   return true;
     437                 :          13 : }
     438                 :             : 
     439                 :             : /* Try to modify BB so that expensive store forwarding cases are avoided.  */
     440                 :             : 
     441                 :             : void
     442                 :          51 : store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
     443                 :             : {
     444                 :          51 :   if (!optimize_bb_for_speed_p (bb))
     445                 :           9 :     return;
     446                 :             : 
     447                 :          42 :   auto_vec<store_fwd_info, 8> store_exprs;
     448                 :          42 :   rtx_insn *insn;
     449                 :          42 :   unsigned int insn_cnt = 0;
     450                 :             : 
     451                 :        1007 :   FOR_BB_INSNS (bb, insn)
     452                 :             :     {
     453                 :         965 :       if (!NONDEBUG_INSN_P (insn))
     454                 :         117 :         continue;
     455                 :             : 
     456                 :         883 :       vec_rtx_properties properties;
     457                 :         883 :       properties.add_insn (insn, false);
     458                 :             : 
     459                 :         883 :       rtx set = single_set (insn);
     460                 :             : 
     461                 :         883 :       if (!set || insn_could_throw_p (insn))
     462                 :             :         {
     463                 :          35 :           store_exprs.truncate (0);
     464                 :          35 :           continue;
     465                 :             :         }
     466                 :             : 
     467                 :             :       /* The inner mem RTX if INSN is a load, NULL_RTX otherwise.  */
     468                 :         848 :       rtx load_mem = SET_SRC (set);
     469                 :             : 
     470                 :         848 :       if (GET_CODE (load_mem) == ZERO_EXTEND
     471                 :         848 :           || GET_CODE (load_mem) == SIGN_EXTEND)
     472                 :          50 :         load_mem = XEXP (load_mem, 0);
     473                 :             : 
     474                 :         848 :       if (!MEM_P (load_mem))
     475                 :         782 :         load_mem = NULL_RTX;
     476                 :             : 
     477                 :             :       /* The mem RTX if INSN is a store, NULL_RTX otherwise.  */
     478                 :         848 :       rtx store_mem = MEM_P (SET_DEST (set)) ? SET_DEST (set) : NULL_RTX;
     479                 :             : 
     480                 :             :       /* We cannot analyze memory RTXs that have unknown size.  */
     481                 :         350 :       if ((store_mem && (!MEM_SIZE_KNOWN_P (store_mem)
     482                 :             :                          || !MEM_SIZE (store_mem).is_constant ()))
     483                 :         914 :           || (load_mem && (!MEM_SIZE_KNOWN_P (load_mem)
     484                 :             :                            || !MEM_SIZE (load_mem).is_constant ())))
     485                 :             :         {
     486                 :           0 :           store_exprs.truncate (0);
     487                 :           0 :           continue;
     488                 :             :         }
     489                 :             : 
     490                 :         848 :       bool is_simple = !properties.has_asm
     491                 :         848 :                        && !properties.has_side_effects ();
     492                 :         848 :       bool is_simple_store = is_simple
     493                 :         848 :                              && store_mem
     494                 :         848 :                              && !contains_mem_rtx_p (SET_SRC (set));
     495                 :         848 :       bool is_simple_load = is_simple
     496                 :         848 :                             && load_mem
     497                 :         848 :                             && !contains_mem_rtx_p (SET_DEST (set));
     498                 :             : 
     499                 :         848 :       int removed_count = 0;
     500                 :             : 
     501                 :         848 :       if (is_simple_store)
     502                 :             :         {
     503                 :             :           /* Record store forwarding candidate.  */
     504                 :         298 :           store_fwd_info info;
     505                 :         298 :           info.store_insn = insn;
     506                 :         298 :           info.store_mem = store_mem;
     507                 :         298 :           info.insn_cnt = insn_cnt;
     508                 :         298 :           info.remove = false;
     509                 :         298 :           info.forwarded = false;
     510                 :         298 :           store_exprs.safe_push (info);
     511                 :             :         }
     512                 :             : 
     513                 :         848 :       bool reads_mem = false;
     514                 :         848 :       bool writes_mem = false;
     515                 :        3037 :       for (auto ref : properties.refs ())
     516                 :        2189 :         if (ref.is_mem ())
     517                 :             :           {
     518                 :         408 :             reads_mem |= ref.is_read ();
     519                 :         408 :             writes_mem |= ref.is_write ();
     520                 :             :           }
     521                 :        1781 :         else if (ref.is_write ())
     522                 :             :           {
     523                 :             :             /* Drop store forwarding candidates when the address register is
     524                 :             :                overwritten.  */
     525                 :         681 :             bool remove_rest = false;
     526                 :         681 :             unsigned int i;
     527                 :         681 :             store_fwd_info *it;
     528                 :       18918 :             FOR_EACH_VEC_ELT_REVERSE (store_exprs, i, it)
     529                 :             :               {
     530                 :       15367 :                 if (remove_rest
     531                 :       30717 :                     || reg_overlap_mentioned_p (regno_reg_rtx[ref.regno],
     532                 :       15350 :                                                 it->store_mem))
     533                 :             :                   {
     534                 :          20 :                     it->remove = true;
     535                 :          20 :                     removed_count++;
     536                 :          20 :                     remove_rest = true;
     537                 :             :                   }
     538                 :             :               }
     539                 :             :           }
     540                 :             : 
     541                 :         848 :       if (is_simple_load)
     542                 :             :         {
     543                 :             :           /* Process load for possible store forwarding cases.
     544                 :             :              Possible newly created/moved stores, resulted from a successful
     545                 :             :              forwarding, will be processed in subsequent iterations.  */
     546                 :          62 :           auto_vec<store_fwd_info> forwardings;
     547                 :          62 :           bool partial_forwarding = false;
     548                 :          62 :           bool remove_rest = false;
     549                 :             : 
     550                 :          62 :           bool vector_load = VECTOR_MODE_P (GET_MODE (load_mem));
     551                 :             : 
     552                 :          62 :           unsigned int i;
     553                 :          62 :           store_fwd_info *it;
     554                 :         490 :           FOR_EACH_VEC_ELT_REVERSE (store_exprs, i, it)
     555                 :             :             {
     556                 :         366 :               rtx store_mem = it->store_mem;
     557                 :         366 :               HOST_WIDE_INT off_val;
     558                 :             : 
     559                 :         366 :               bool vector_store = VECTOR_MODE_P (GET_MODE (store_mem));
     560                 :             : 
     561                 :         366 :               if (remove_rest)
     562                 :             :                 {
     563                 :           9 :                   it->remove = true;
     564                 :           9 :                   removed_count++;
     565                 :             :                 }
     566                 :         357 :               else if (vector_load ^ vector_store)
     567                 :             :                 {
     568                 :             :                   /* Vector stores followed by a non-vector load or the
     569                 :             :                      opposite, cause store_bit_field to generate non-canonical
     570                 :             :                      expressions, like (subreg:V4SI (reg:DI ...) 0)).
     571                 :             :                      Cases like that should be handled using vec_duplicate,
     572                 :             :                      so we reject the transformation in those cases.  */
     573                 :           1 :                   it->remove = true;
     574                 :           1 :                   removed_count++;
     575                 :           1 :                   remove_rest = true;
     576                 :             :                 }
     577                 :         356 :               else if (is_store_forwarding (store_mem, load_mem, &off_val))
     578                 :             :                 {
     579                 :             :                   /* Check if moving this store after the load is legal.  */
     580                 :          79 :                   bool write_dep = false;
     581                 :        2250 :                   for (unsigned int j = store_exprs.length () - 1; j != i; j--)
     582                 :             :                     {
     583                 :        2092 :                       if (!store_exprs[j].forwarded
     584                 :        3810 :                           && output_dependence (store_mem,
     585                 :        1718 :                                                 store_exprs[j].store_mem))
     586                 :             :                         {
     587                 :             :                           write_dep = true;
     588                 :             :                           break;
     589                 :             :                         }
     590                 :             :                     }
     591                 :             : 
     592                 :          79 :                   if (!write_dep)
     593                 :             :                     {
     594                 :          79 :                       it->forwarded = true;
     595                 :          79 :                       it->offset = off_val;
     596                 :          79 :                       forwardings.safe_push (*it);
     597                 :             :                     }
     598                 :             :                   else
     599                 :             :                     partial_forwarding = true;
     600                 :             : 
     601                 :          79 :                   it->remove = true;
     602                 :          79 :                   removed_count++;
     603                 :             :                 }
     604                 :         277 :               else if (true_dependence (store_mem, GET_MODE (store_mem),
     605                 :             :                                         load_mem))
     606                 :             :                 {
     607                 :             :                   /* We cannot keep a store forwarding candidate if it possibly
     608                 :             :                      interferes with this load.  */
     609                 :           0 :                   it->remove = true;
     610                 :           0 :                   removed_count++;
     611                 :           0 :                   remove_rest = true;
     612                 :             :                 }
     613                 :             :             }
     614                 :             : 
     615                 :          88 :           if (!forwardings.is_empty () && !partial_forwarding)
     616                 :          13 :             process_store_forwarding (forwardings, insn, load_mem);
     617                 :          62 :         }
     618                 :             : 
     619                 :         848 :         if ((writes_mem && !is_simple_store)
     620                 :         818 :              || (reads_mem && !is_simple_load))
     621                 :          37 :            store_exprs.truncate (0);
     622                 :             : 
     623                 :         848 :         if (removed_count)
     624                 :             :         {
     625                 :          17 :           unsigned int i, j;
     626                 :          17 :           store_fwd_info *it;
     627                 :         310 :           VEC_ORDERED_REMOVE_IF (store_exprs, i, j, it, it->remove);
     628                 :             :         }
     629                 :             : 
     630                 :             :         /* Don't consider store forwarding if the RTL instruction distance is
     631                 :             :            more than PARAM_STORE_FORWARDING_MAX_DISTANCE and the cost checks
     632                 :             :            are not disabled.  */
     633                 :         848 :         const bool unlimited_cost = (param_store_forwarding_max_distance == 0);
     634                 :         233 :         if (!unlimited_cost && !store_exprs.is_empty ()
     635                 :         848 :             && (store_exprs[0].insn_cnt
     636                 :         233 :                 + param_store_forwarding_max_distance <= insn_cnt))
     637                 :          64 :           store_exprs.ordered_remove (0);
     638                 :             : 
     639                 :         848 :         insn_cnt++;
     640                 :         883 :     }
     641                 :          42 : }
     642                 :             : 
     643                 :             : /* Update pass statistics.  */
     644                 :             : 
     645                 :             : void
     646                 :          17 : store_forwarding_analyzer::update_stats (function *fn)
     647                 :             : {
     648                 :          17 :   statistics_counter_event (fn, "Cases of store forwarding detected: ",
     649                 :          17 :                             stats_sf_detected);
     650                 :          17 :   statistics_counter_event (fn, "Cases of store forwarding avoided: ",
     651                 :          17 :                             stats_sf_detected);
     652                 :          17 : }
     653                 :             : 
     654                 :             : unsigned int
     655                 :          17 : pass_rtl_avoid_store_forwarding::execute (function *fn)
     656                 :             : {
     657                 :          17 :   df_set_flags (DF_DEFER_INSN_RESCAN);
     658                 :             : 
     659                 :          17 :   init_alias_analysis ();
     660                 :             : 
     661                 :          17 :   store_forwarding_analyzer analyzer;
     662                 :             : 
     663                 :          17 :   basic_block bb;
     664                 :          68 :   FOR_EACH_BB_FN (bb, fn)
     665                 :          51 :     analyzer.avoid_store_forwarding (bb);
     666                 :             : 
     667                 :          17 :   end_alias_analysis ();
     668                 :             : 
     669                 :          17 :   analyzer.update_stats (fn);
     670                 :             : 
     671                 :          17 :   return 0;
     672                 :             : }
     673                 :             : 
     674                 :             : } // anon namespace.
     675                 :             : 
     676                 :             : rtl_opt_pass *
     677                 :      285081 : make_pass_rtl_avoid_store_forwarding (gcc::context *ctxt)
     678                 :             : {
     679                 :      285081 :   return new pass_rtl_avoid_store_forwarding (ctxt);
     680                 :             : }
        

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.