LCOV - code coverage report
Current view: top level - gcc - avoid-store-forwarding.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 84.1 % 277 233
Test Date: 2024-12-21 13:15:12 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 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                 :      280114 :   pass_rtl_avoid_store_forwarding (gcc::context *ctxt)
      79                 :      560228 :     : rtl_opt_pass (pass_data_avoid_store_forwarding, ctxt)
      80                 :             :   {}
      81                 :             : 
      82                 :             :   /* opt_pass methods: */
      83                 :     1415668 :   virtual bool gate (function *)
      84                 :             :     {
      85                 :     1415668 :       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                 :          15 : generate_bit_insert_sequence (store_fwd_info *store_info, rtx dest)
     112                 :             : {
     113                 :             :   /* Memory size should be a constant at this stage.  */
     114                 :          15 :   unsigned HOST_WIDE_INT store_size
     115                 :          15 :     = MEM_SIZE (store_info->store_mem).to_constant ();
     116                 :             : 
     117                 :          15 :   start_sequence ();
     118                 :             : 
     119                 :          15 :   unsigned HOST_WIDE_INT bitsize = store_size * BITS_PER_UNIT;
     120                 :          15 :   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                 :          15 :   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                 :          15 :   rtx mov_reg = store_info->mov_reg;
     134                 :          15 :   store_bit_field (dest, bitsize, start, 0, 0, GET_MODE (mov_reg), mov_reg,
     135                 :             :                    false, false);
     136                 :             : 
     137                 :          15 :   rtx_insn *insns = get_insns ();
     138                 :          15 :   unshare_all_rtl_in_chain (insns);
     139                 :          15 :   end_sequence ();
     140                 :             : 
     141                 :          95 :   for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
     142                 :          80 :     if (contains_mem_rtx_p (PATTERN (insn))
     143                 :          80 :         || 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                 :         106 : bool store_forwarding_analyzer::
     154                 :             : is_store_forwarding (rtx store_mem, rtx load_mem, HOST_WIDE_INT *off_val)
     155                 :             : {
     156                 :         106 :   poly_int64 load_offset, store_offset;
     157                 :         106 :   rtx load_base = strip_offset (XEXP (load_mem, 0), &load_offset);
     158                 :         106 :   rtx store_base = strip_offset (XEXP (store_mem, 0), &store_offset);
     159                 :         106 :   return (MEM_SIZE (load_mem).is_constant ()
     160                 :         106 :           && rtx_equal_p (load_base, store_base)
     161                 :          71 :           && known_subrange_p (store_offset, MEM_SIZE (store_mem),
     162                 :          71 :                                load_offset, MEM_SIZE (load_mem))
     163                 :          19 :           && (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                 :           7 : bool store_forwarding_analyzer::
     172                 :             : process_store_forwarding (vec<store_fwd_info> &stores, rtx_insn *load_insn,
     173                 :             :                           rtx load_mem)
     174                 :             : {
     175                 :           7 :   machine_mode load_mem_mode = GET_MODE (load_mem);
     176                 :             :   /* Memory sizes should be constants at this stage.  */
     177                 :           7 :   HOST_WIDE_INT load_size = MEM_SIZE (load_mem).to_constant ();
     178                 :             : 
     179                 :             :   /* If the stores cover all the bytes of the load without overlap then we can
     180                 :             :      eliminate the load entirely and use the computed value instead.  */
     181                 :             : 
     182                 :           7 :   sbitmap forwarded_bytes = sbitmap_alloc (load_size);
     183                 :           7 :   bitmap_clear (forwarded_bytes);
     184                 :             : 
     185                 :           7 :   unsigned int i;
     186                 :           7 :   store_fwd_info* it;
     187                 :          26 :   FOR_EACH_VEC_ELT (stores, i, it)
     188                 :             :     {
     189                 :          19 :       HOST_WIDE_INT store_size = MEM_SIZE (it->store_mem).to_constant ();
     190                 :          19 :       if (bitmap_bit_in_range_p (forwarded_bytes, it->offset,
     191                 :          19 :                                  it->offset + store_size - 1))
     192                 :             :         break;
     193                 :          19 :       bitmap_set_range (forwarded_bytes, it->offset, store_size);
     194                 :             :     }
     195                 :             : 
     196                 :           7 :   bitmap_not (forwarded_bytes, forwarded_bytes);
     197                 :           7 :   bool load_elim = bitmap_empty_p (forwarded_bytes);
     198                 :             : 
     199                 :           7 :   stats_sf_detected++;
     200                 :             : 
     201                 :           7 :   if (dump_file)
     202                 :             :     {
     203                 :           0 :       fprintf (dump_file, "Store forwarding detected:\n");
     204                 :             : 
     205                 :           0 :       FOR_EACH_VEC_ELT (stores, i, it)
     206                 :             :         {
     207                 :           0 :           fprintf (dump_file, "From: ");
     208                 :           0 :           print_rtl_single (dump_file, it->store_insn);
     209                 :             :         }
     210                 :             : 
     211                 :           0 :       fprintf (dump_file, "To: ");
     212                 :           0 :       print_rtl_single (dump_file, load_insn);
     213                 :             : 
     214                 :           0 :       if (load_elim)
     215                 :           0 :         fprintf (dump_file, "(Load elimination candidate)\n");
     216                 :             :     }
     217                 :             : 
     218                 :           7 :   rtx load = single_set (load_insn);
     219                 :           7 :   rtx dest;
     220                 :             : 
     221                 :           7 :   if (load_elim)
     222                 :           4 :     dest = gen_reg_rtx (load_mem_mode);
     223                 :             :   else
     224                 :           3 :     dest = SET_DEST (load);
     225                 :             : 
     226                 :           7 :   int move_to_front = -1;
     227                 :           7 :   int total_cost = 0;
     228                 :             : 
     229                 :             :   /* Check if we can emit bit insert instructions for all forwarded stores.  */
     230                 :          26 :   FOR_EACH_VEC_ELT (stores, i, it)
     231                 :             :     {
     232                 :          19 :       it->mov_reg = gen_reg_rtx (GET_MODE (it->store_mem));
     233                 :          19 :       rtx_insn *insns = NULL;
     234                 :             : 
     235                 :             :       /* If we're eliminating the load then find the store with zero offset
     236                 :             :          and use it as the base register to avoid a bit insert if possible.  */
     237                 :          19 :       if (load_elim && it->offset == 0)
     238                 :             :         {
     239                 :           4 :           start_sequence ();
     240                 :             : 
     241                 :             :           /* We can use a paradoxical subreg to force this to a wider mode, as
     242                 :             :              the only use will be inserting the bits (i.e., we don't care about
     243                 :             :              the value of the higher bits).  */
     244                 :           8 :           rtx ext0 = lowpart_subreg (GET_MODE (dest), it->mov_reg,
     245                 :           4 :                                      GET_MODE (it->mov_reg));
     246                 :           4 :           if (ext0)
     247                 :             :             {
     248                 :           4 :               rtx_insn *move0 = emit_move_insn (dest, ext0);
     249                 :           4 :               if (recog_memoized (move0) >= 0)
     250                 :             :                 {
     251                 :           4 :                   insns = get_insns ();
     252                 :           4 :                   move_to_front = (int) i;
     253                 :             :                 }
     254                 :             :             }
     255                 :             : 
     256                 :           4 :           end_sequence ();
     257                 :             :         }
     258                 :             : 
     259                 :           4 :       if (!insns)
     260                 :          15 :         insns = generate_bit_insert_sequence (&(*it), dest);
     261                 :             : 
     262                 :          15 :       if (!insns)
     263                 :             :         {
     264                 :           0 :           if (dump_file)
     265                 :             :             {
     266                 :           0 :               fprintf (dump_file, "Failed due to: ");
     267                 :           0 :               print_rtl_single (dump_file, it->store_insn);
     268                 :             :             }
     269                 :           0 :           return false;
     270                 :             :         }
     271                 :             : 
     272                 :          19 :       total_cost += seq_cost (insns, true);
     273                 :          19 :       it->bits_insert_insns = insns;
     274                 :             : 
     275                 :          19 :       rtx store_set = single_set (it->store_insn);
     276                 :             : 
     277                 :             :       /* Create a register move at the store's original position to save the
     278                 :             :          stored value.  */
     279                 :          19 :       start_sequence ();
     280                 :          19 :       rtx_insn *insn1
     281                 :          19 :         = emit_insn (gen_rtx_SET (it->mov_reg, SET_SRC (store_set)));
     282                 :          19 :       end_sequence ();
     283                 :             : 
     284                 :          19 :       if (recog_memoized (insn1) < 0)
     285                 :             :         {
     286                 :           0 :           if (dump_file)
     287                 :             :             {
     288                 :           0 :               fprintf (dump_file, "Failed due to unrecognizable insn: ");
     289                 :           0 :               print_rtl_single (dump_file, insn1);
     290                 :             :             }
     291                 :           0 :           return false;
     292                 :             :         }
     293                 :             : 
     294                 :          19 :       it->save_store_value_insn = insn1;
     295                 :             : 
     296                 :             :       /* Create a new store after the load with the saved original value.
     297                 :             :          This avoids the forwarding stall.  */
     298                 :          19 :       start_sequence ();
     299                 :          19 :       rtx_insn *insn2
     300                 :          19 :         = emit_insn (gen_rtx_SET (SET_DEST (store_set), it->mov_reg));
     301                 :          19 :       end_sequence ();
     302                 :             : 
     303                 :          19 :       if (recog_memoized (insn2) < 0)
     304                 :             :         {
     305                 :           0 :           if (dump_file)
     306                 :             :             {
     307                 :           0 :               fprintf (dump_file, "Failed due to unrecognizable insn: ");
     308                 :           0 :               print_rtl_single (dump_file, insn2);
     309                 :             :             }
     310                 :           0 :           return false;
     311                 :             :         }
     312                 :             : 
     313                 :          19 :       it->store_saved_value_insn = insn2;
     314                 :             :     }
     315                 :             : 
     316                 :           7 :   if (load_elim)
     317                 :           4 :     total_cost -= insn_cost (load_insn, true);
     318                 :             : 
     319                 :             :   /* Let the target decide if transforming this store forwarding instance is
     320                 :             :      profitable.  */
     321                 :           7 :   if (!targetm.avoid_store_forwarding_p (stores, load_mem, total_cost,
     322                 :             :                                          load_elim))
     323                 :             :     {
     324                 :           1 :       if (dump_file)
     325                 :           0 :         fprintf (dump_file, "Not transformed due to target decision.\n");
     326                 :             : 
     327                 :           1 :       return false;
     328                 :             :     }
     329                 :             : 
     330                 :             :   /* If we have a move instead of bit insert, it needs to be emitted first in
     331                 :             :      the resulting sequence.  */
     332                 :           6 :   if (move_to_front != -1)
     333                 :             :     {
     334                 :           4 :       store_fwd_info copy = stores[move_to_front];
     335                 :           4 :       stores.safe_push (copy);
     336                 :           4 :       stores.ordered_remove (move_to_front);
     337                 :             :     }
     338                 :             : 
     339                 :           6 :   if (load_elim)
     340                 :             :     {
     341                 :           4 :       machine_mode outer_mode = GET_MODE (SET_DEST (load));
     342                 :           4 :       rtx load_move;
     343                 :           4 :       rtx load_value = dest;
     344                 :           4 :       if (outer_mode != load_mem_mode)
     345                 :             :         {
     346                 :           0 :           load_value = simplify_gen_unary (GET_CODE (SET_SRC (load)),
     347                 :             :                                            outer_mode, dest, load_mem_mode);
     348                 :             :         }
     349                 :           4 :       load_move = gen_rtx_SET (SET_DEST (load), load_value);
     350                 :             : 
     351                 :           4 :       start_sequence ();
     352                 :           4 :       rtx_insn *insn = emit_insn (load_move);
     353                 :           4 :       rtx_insn *seq = get_insns ();
     354                 :           4 :       end_sequence ();
     355                 :             : 
     356                 :           4 :       if (recog_memoized (insn) < 0)
     357                 :             :         return false;
     358                 :             : 
     359                 :           4 :       emit_insn_after (seq, load_insn);
     360                 :             :     }
     361                 :             : 
     362                 :           6 :   if (dump_file)
     363                 :             :     {
     364                 :           0 :       fprintf (dump_file, "Store forwarding avoided with bit inserts:\n");
     365                 :             : 
     366                 :           0 :       FOR_EACH_VEC_ELT (stores, i, it)
     367                 :             :         {
     368                 :           0 :           if (stores.length () > 1)
     369                 :             :             {
     370                 :           0 :               fprintf (dump_file, "For: ");
     371                 :           0 :               print_rtl_single (dump_file, it->store_insn);
     372                 :             :             }
     373                 :             : 
     374                 :           0 :           fprintf (dump_file, "With sequence:\n");
     375                 :             : 
     376                 :           0 :           for (rtx_insn *insn = it->bits_insert_insns; insn;
     377                 :           0 :                insn = NEXT_INSN (insn))
     378                 :             :             {
     379                 :           0 :               fprintf (dump_file, "  ");
     380                 :           0 :               print_rtl_single (dump_file, insn);
     381                 :             :             }
     382                 :             :         }
     383                 :             :     }
     384                 :             : 
     385                 :           6 :   stats_sf_avoided++;
     386                 :             : 
     387                 :             :   /* Done, emit all the generated instructions and delete the stores.
     388                 :             :      Note that STORES are in reverse program order.  */
     389                 :             : 
     390                 :          24 :   FOR_EACH_VEC_ELT (stores, i, it)
     391                 :             :     {
     392                 :          18 :       emit_insn_after (it->bits_insert_insns, load_insn);
     393                 :          18 :       emit_insn_after (it->store_saved_value_insn, load_insn);
     394                 :             :     }
     395                 :             : 
     396                 :          24 :   FOR_EACH_VEC_ELT (stores, i, it)
     397                 :             :     {
     398                 :          18 :       emit_insn_before (it->save_store_value_insn, it->store_insn);
     399                 :          18 :       delete_insn (it->store_insn);
     400                 :             :     }
     401                 :             : 
     402                 :           6 :   df_insn_rescan (load_insn);
     403                 :             : 
     404                 :           6 :   if (load_elim)
     405                 :           4 :     delete_insn (load_insn);
     406                 :             : 
     407                 :             :   return true;
     408                 :             : }
     409                 :             : 
     410                 :             : /* Try to modify BB so that expensive store forwarding cases are avoided.  */
     411                 :             : 
     412                 :             : void
     413                 :          13 : store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
     414                 :             : {
     415                 :          13 :   if (!optimize_bb_for_speed_p (bb))
     416                 :           1 :     return;
     417                 :             : 
     418                 :          12 :   auto_vec<store_fwd_info, 8> store_exprs;
     419                 :          12 :   rtx_insn *insn;
     420                 :          12 :   unsigned int insn_cnt = 0;
     421                 :             : 
     422                 :         303 :   FOR_BB_INSNS (bb, insn)
     423                 :             :     {
     424                 :         291 :       if (!NONDEBUG_INSN_P (insn))
     425                 :          47 :         continue;
     426                 :             : 
     427                 :         259 :       vec_rtx_properties properties;
     428                 :         259 :       properties.add_insn (insn, false);
     429                 :             : 
     430                 :         259 :       rtx set = single_set (insn);
     431                 :             : 
     432                 :         259 :       if (!set || insn_could_throw_p (insn))
     433                 :             :         {
     434                 :          15 :           store_exprs.truncate (0);
     435                 :          15 :           continue;
     436                 :             :         }
     437                 :             : 
     438                 :             :       /* The inner mem RTX if INSN is a load, NULL_RTX otherwise.  */
     439                 :         244 :       rtx load_mem = SET_SRC (set);
     440                 :             : 
     441                 :         244 :       if (GET_CODE (load_mem) == ZERO_EXTEND
     442                 :         244 :           || GET_CODE (load_mem) == SIGN_EXTEND)
     443                 :          25 :         load_mem = XEXP (load_mem, 0);
     444                 :             : 
     445                 :         244 :       if (!MEM_P (load_mem))
     446                 :         219 :         load_mem = NULL_RTX;
     447                 :             : 
     448                 :             :       /* The mem RTX if INSN is a store, NULL_RTX otherwise.  */
     449                 :         244 :       rtx store_mem = MEM_P (SET_DEST (set)) ? SET_DEST (set) : NULL_RTX;
     450                 :             : 
     451                 :             :       /* We cannot analyze memory RTXs that have unknown size.  */
     452                 :          84 :       if ((store_mem && (!MEM_SIZE_KNOWN_P (store_mem)
     453                 :             :                          || !MEM_SIZE (store_mem).is_constant ()))
     454                 :         269 :           || (load_mem && (!MEM_SIZE_KNOWN_P (load_mem)
     455                 :             :                            || !MEM_SIZE (load_mem).is_constant ())))
     456                 :             :         {
     457                 :           0 :           store_exprs.truncate (0);
     458                 :           0 :           continue;
     459                 :             :         }
     460                 :             : 
     461                 :         244 :       bool is_simple = !properties.has_asm
     462                 :         244 :                        && !properties.has_side_effects ();
     463                 :         244 :       bool is_simple_store = is_simple
     464                 :         244 :                              && store_mem
     465                 :         244 :                              && !contains_mem_rtx_p (SET_SRC (set));
     466                 :         244 :       bool is_simple_load = is_simple
     467                 :         244 :                             && load_mem
     468                 :         244 :                             && !contains_mem_rtx_p (SET_DEST (set));
     469                 :             : 
     470                 :         244 :       int removed_count = 0;
     471                 :             : 
     472                 :         244 :       if (is_simple_store)
     473                 :             :         {
     474                 :             :           /* Record store forwarding candidate.  */
     475                 :          64 :           store_fwd_info info;
     476                 :          64 :           info.store_insn = insn;
     477                 :          64 :           info.store_mem = store_mem;
     478                 :          64 :           info.insn_cnt = insn_cnt;
     479                 :          64 :           info.remove = false;
     480                 :          64 :           info.forwarded = false;
     481                 :          64 :           store_exprs.safe_push (info);
     482                 :             :         }
     483                 :             : 
     484                 :         244 :       bool reads_mem = false;
     485                 :         244 :       bool writes_mem = false;
     486                 :         831 :       for (auto ref : properties.refs ())
     487                 :         587 :         if (ref.is_mem ())
     488                 :             :           {
     489                 :         101 :             reads_mem |= ref.is_read ();
     490                 :         101 :             writes_mem |= ref.is_write ();
     491                 :             :           }
     492                 :         486 :         else if (ref.is_write ())
     493                 :             :           {
     494                 :             :             /* Drop store forwarding candidates when the address register is
     495                 :             :                overwritten.  */
     496                 :         212 :             bool remove_rest = false;
     497                 :         212 :             unsigned int i;
     498                 :         212 :             store_fwd_info *it;
     499                 :        2935 :             FOR_EACH_VEC_ELT_REVERSE (store_exprs, i, it)
     500                 :             :               {
     501                 :        1924 :                 if (remove_rest
     502                 :        3815 :                     || reg_overlap_mentioned_p (regno_reg_rtx[ref.regno],
     503                 :        1891 :                                                 it->store_mem))
     504                 :             :                   {
     505                 :          36 :                     it->remove = true;
     506                 :          36 :                     removed_count++;
     507                 :          36 :                     remove_rest = true;
     508                 :             :                   }
     509                 :             :               }
     510                 :             :           }
     511                 :             : 
     512                 :         244 :       if (is_simple_load)
     513                 :             :         {
     514                 :             :           /* Process load for possible store forwarding cases.
     515                 :             :              Possible newly created/moved stores, resulted from a successful
     516                 :             :              forwarding, will be processed in subsequent iterations.  */
     517                 :          25 :           auto_vec<store_fwd_info> forwardings;
     518                 :          25 :           bool partial_forwarding = false;
     519                 :          25 :           bool remove_rest = false;
     520                 :             : 
     521                 :          25 :           bool vector_load = VECTOR_MODE_P (GET_MODE (load_mem));
     522                 :             : 
     523                 :          25 :           unsigned int i;
     524                 :          25 :           store_fwd_info *it;
     525                 :         156 :           FOR_EACH_VEC_ELT_REVERSE (store_exprs, i, it)
     526                 :             :             {
     527                 :         106 :               rtx store_mem = it->store_mem;
     528                 :         106 :               HOST_WIDE_INT off_val;
     529                 :             : 
     530                 :         106 :               bool vector_store = VECTOR_MODE_P (GET_MODE (store_mem));
     531                 :             : 
     532                 :         106 :               if (remove_rest)
     533                 :             :                 {
     534                 :           0 :                   it->remove = true;
     535                 :           0 :                   removed_count++;
     536                 :             :                 }
     537                 :         106 :               else if (vector_load ^ vector_store)
     538                 :             :                 {
     539                 :             :                   /* Vector stores followed by a non-vector load or the
     540                 :             :                      opposite, cause store_bit_field to generate non-canonical
     541                 :             :                      expressions, like (subreg:V4SI (reg:DI ...) 0)).
     542                 :             :                      Cases like that should be handled using vec_duplicate,
     543                 :             :                      so we reject the transformation in those cases.  */
     544                 :           0 :                   it->remove = true;
     545                 :           0 :                   removed_count++;
     546                 :           0 :                   remove_rest = true;
     547                 :             :                 }
     548                 :         106 :               else if (is_store_forwarding (store_mem, load_mem, &off_val))
     549                 :             :                 {
     550                 :             :                   /* Check if moving this store after the load is legal.  */
     551                 :          19 :                   bool write_dep = false;
     552                 :         278 :                   for (unsigned int j = store_exprs.length () - 1; j != i; j--)
     553                 :             :                     {
     554                 :         240 :                       if (!store_exprs[j].forwarded
     555                 :         456 :                           && output_dependence (store_mem,
     556                 :         216 :                                                 store_exprs[j].store_mem))
     557                 :             :                         {
     558                 :             :                           write_dep = true;
     559                 :             :                           break;
     560                 :             :                         }
     561                 :             :                     }
     562                 :             : 
     563                 :          19 :                   if (!write_dep)
     564                 :             :                     {
     565                 :          19 :                       it->forwarded = true;
     566                 :          19 :                       it->offset = off_val;
     567                 :          19 :                       forwardings.safe_push (*it);
     568                 :             :                     }
     569                 :             :                   else
     570                 :             :                     partial_forwarding = true;
     571                 :             : 
     572                 :          19 :                   it->remove = true;
     573                 :          19 :                   removed_count++;
     574                 :             :                 }
     575                 :          87 :               else if (true_dependence (store_mem, GET_MODE (store_mem),
     576                 :             :                                         load_mem))
     577                 :             :                 {
     578                 :             :                   /* We cannot keep a store forwarding candidate if it possibly
     579                 :             :                      interferes with this load.  */
     580                 :           0 :                   it->remove = true;
     581                 :           0 :                   removed_count++;
     582                 :           0 :                   remove_rest = true;
     583                 :             :                 }
     584                 :             :             }
     585                 :             : 
     586                 :          39 :           if (!forwardings.is_empty () && !partial_forwarding)
     587                 :           7 :             process_store_forwarding (forwardings, insn, load_mem);
     588                 :          25 :         }
     589                 :             : 
     590                 :         244 :         if ((writes_mem && !is_simple_store)
     591                 :         224 :              || (reads_mem && !is_simple_load))
     592                 :          22 :            store_exprs.truncate (0);
     593                 :             : 
     594                 :         244 :         if (removed_count)
     595                 :             :         {
     596                 :          10 :           unsigned int i, j;
     597                 :          10 :           store_fwd_info *it;
     598                 :         111 :           VEC_ORDERED_REMOVE_IF (store_exprs, i, j, it, it->remove);
     599                 :             :         }
     600                 :             : 
     601                 :             :         /* Don't consider store forwarding if the RTL instruction distance is
     602                 :             :            more than PARAM_STORE_FORWARDING_MAX_DISTANCE and the cost checks
     603                 :             :            are not disabled.  */
     604                 :         244 :         const bool unlimited_cost = (param_store_forwarding_max_distance == 0);
     605                 :         171 :         if (!unlimited_cost && !store_exprs.is_empty ()
     606                 :         244 :             && (store_exprs[0].insn_cnt
     607                 :         171 :                 + param_store_forwarding_max_distance <= insn_cnt))
     608                 :           0 :           store_exprs.ordered_remove (0);
     609                 :             : 
     610                 :         244 :         insn_cnt++;
     611                 :         259 :     }
     612                 :          12 : }
     613                 :             : 
     614                 :             : /* Update pass statistics.  */
     615                 :             : 
     616                 :             : void
     617                 :           9 : store_forwarding_analyzer::update_stats (function *fn)
     618                 :             : {
     619                 :           9 :   statistics_counter_event (fn, "Cases of store forwarding detected: ",
     620                 :           9 :                             stats_sf_detected);
     621                 :           9 :   statistics_counter_event (fn, "Cases of store forwarding avoided: ",
     622                 :           9 :                             stats_sf_detected);
     623                 :           9 : }
     624                 :             : 
     625                 :             : unsigned int
     626                 :           9 : pass_rtl_avoid_store_forwarding::execute (function *fn)
     627                 :             : {
     628                 :           9 :   df_set_flags (DF_DEFER_INSN_RESCAN);
     629                 :             : 
     630                 :           9 :   init_alias_analysis ();
     631                 :             : 
     632                 :           9 :   store_forwarding_analyzer analyzer;
     633                 :             : 
     634                 :           9 :   basic_block bb;
     635                 :          22 :   FOR_EACH_BB_FN (bb, fn)
     636                 :          13 :     analyzer.avoid_store_forwarding (bb);
     637                 :             : 
     638                 :           9 :   end_alias_analysis ();
     639                 :             : 
     640                 :           9 :   analyzer.update_stats (fn);
     641                 :             : 
     642                 :           9 :   return 0;
     643                 :             : }
     644                 :             : 
     645                 :             : } // anon namespace.
     646                 :             : 
     647                 :             : rtl_opt_pass *
     648                 :      280114 : make_pass_rtl_avoid_store_forwarding (gcc::context *ctxt)
     649                 :             : {
     650                 :      280114 :   return new pass_rtl_avoid_store_forwarding (ctxt);
     651                 :             : }
        

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.