Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Redundant Extension Elimination pass for the GNU compiler.
      2  1.1  mrg    Copyright (C) 2010-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Ilya Enkovich (ilya.enkovich (at) intel.com)
      4  1.1  mrg 
      5  1.1  mrg    Based on the Redundant Zero-extension elimination pass contributed by
      6  1.1  mrg    Sriraman Tallam (tmsriram (at) google.com) and Silvius Rus (rus (at) google.com).
      7  1.1  mrg 
      8  1.1  mrg This file is part of GCC.
      9  1.1  mrg 
     10  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
     11  1.1  mrg the terms of the GNU General Public License as published by the Free
     12  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     13  1.1  mrg version.
     14  1.1  mrg 
     15  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     16  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     17  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     18  1.1  mrg for more details.
     19  1.1  mrg 
     20  1.1  mrg You should have received a copy of the GNU General Public License
     21  1.1  mrg along with GCC; see the file COPYING3.  If not see
     22  1.1  mrg <http://www.gnu.org/licenses/>.  */
     23  1.1  mrg 
     24  1.1  mrg 
     25  1.1  mrg /* Problem Description :
     26  1.1  mrg    --------------------
     27  1.1  mrg    This pass is intended to remove redundant extension instructions.
     28  1.1  mrg    Such instructions appear for different reasons.  We expect some of
     29  1.1  mrg    them due to implicit zero-extension in 64-bit registers after writing
     30  1.1  mrg    to their lower 32-bit half (e.g. for the x86-64 architecture).
     31  1.1  mrg    Another possible reason is a type cast which follows a load (for
     32  1.1  mrg    instance a register restore) and which can be combined into a single
     33  1.1  mrg    instruction, and for which earlier local passes, e.g. the combiner,
     34  1.1  mrg    weren't able to optimize.
     35  1.1  mrg 
     36  1.1  mrg    How does this pass work  ?
     37  1.1  mrg    --------------------------
     38  1.1  mrg 
     39  1.1  mrg    This pass is run after register allocation.  Hence, all registers that
     40  1.1  mrg    this pass deals with are hard registers.  This pass first looks for an
     41  1.1  mrg    extension instruction that could possibly be redundant.  Such extension
     42  1.1  mrg    instructions show up in RTL with the pattern  :
     43  1.1  mrg    (set (reg:<SWI248> x) (any_extend:<SWI248> (reg:<SWI124> x))),
     44  1.1  mrg    where x can be any hard register.
     45  1.1  mrg    Now, this pass tries to eliminate this instruction by merging the
     46  1.1  mrg    extension with the definitions of register x.  For instance, if
     47  1.1  mrg    one of the definitions of register x was  :
     48  1.1  mrg    (set (reg:SI x) (plus:SI (reg:SI z1) (reg:SI z2))),
     49  1.1  mrg    followed by extension  :
     50  1.1  mrg    (set (reg:DI x) (zero_extend:DI (reg:SI x)))
     51  1.1  mrg    then the combination converts this into :
     52  1.1  mrg    (set (reg:DI x) (zero_extend:DI (plus:SI (reg:SI z1) (reg:SI z2)))).
     53  1.1  mrg    If all the merged definitions are recognizable assembly instructions,
     54  1.1  mrg    the extension is effectively eliminated.
     55  1.1  mrg 
     56  1.1  mrg    For example, for the x86-64 architecture, implicit zero-extensions
     57  1.1  mrg    are captured with appropriate patterns in the i386.md file.  Hence,
     58  1.1  mrg    these merged definition can be matched to a single assembly instruction.
     59  1.1  mrg    The original extension instruction is then deleted if all the
     60  1.1  mrg    definitions can be merged.
     61  1.1  mrg 
     62  1.1  mrg    However, there are cases where the definition instruction cannot be
     63  1.1  mrg    merged with an extension.  Examples are CALL instructions.  In such
     64  1.1  mrg    cases, the original extension is not redundant and this pass does
     65  1.1  mrg    not delete it.
     66  1.1  mrg 
     67  1.1  mrg    Handling conditional moves :
     68  1.1  mrg    ----------------------------
     69  1.1  mrg 
     70  1.1  mrg    Architectures like x86-64 support conditional moves whose semantics for
     71  1.1  mrg    extension differ from the other instructions.  For instance, the
     72  1.1  mrg    instruction *cmov ebx, eax*
     73  1.1  mrg    zero-extends eax onto rax only when the move from ebx to eax happens.
     74  1.1  mrg    Otherwise, eax may not be zero-extended.  Consider conditional moves as
     75  1.1  mrg    RTL instructions of the form
     76  1.1  mrg    (set (reg:SI x) (if_then_else (cond) (reg:SI y) (reg:SI z))).
     77  1.1  mrg    This pass tries to merge an extension with a conditional move by
     78  1.1  mrg    actually merging the definitions of y and z with an extension and then
     79  1.1  mrg    converting the conditional move into :
     80  1.1  mrg    (set (reg:DI x) (if_then_else (cond) (reg:DI y) (reg:DI z))).
     81  1.1  mrg    Since registers y and z are extended, register x will also be extended
     82  1.1  mrg    after the conditional move.  Note that this step has to be done
     83  1.1  mrg    transitively since the definition of a conditional copy can be
     84  1.1  mrg    another conditional copy.
     85  1.1  mrg 
     86  1.1  mrg    Motivating Example I :
     87  1.1  mrg    ---------------------
     88  1.1  mrg    For this program :
     89  1.1  mrg    **********************************************
     90  1.1  mrg    bad_code.c
     91  1.1  mrg 
     92  1.1  mrg    int mask[1000];
     93  1.1  mrg 
     94  1.1  mrg    int foo(unsigned x)
     95  1.1  mrg    {
     96  1.1  mrg      if (x < 10)
     97  1.1  mrg        x = x * 45;
     98  1.1  mrg      else
     99  1.1  mrg        x = x * 78;
    100  1.1  mrg      return mask[x];
    101  1.1  mrg    }
    102  1.1  mrg    **********************************************
    103  1.1  mrg 
    104  1.1  mrg    $ gcc -O2 bad_code.c
    105  1.1  mrg      ........
    106  1.1  mrg      400315:       b8 4e 00 00 00          mov    $0x4e,%eax
    107  1.1  mrg      40031a:       0f af f8                imul   %eax,%edi
    108  1.1  mrg      40031d:       89 ff                   mov    %edi,%edi - useless extension
    109  1.1  mrg      40031f:       8b 04 bd 60 19 40 00    mov    0x401960(,%rdi,4),%eax
    110  1.1  mrg      400326:       c3                      retq
    111  1.1  mrg      ......
    112  1.1  mrg      400330:       ba 2d 00 00 00          mov    $0x2d,%edx
    113  1.1  mrg      400335:       0f af fa                imul   %edx,%edi
    114  1.1  mrg      400338:       89 ff                   mov    %edi,%edi - useless extension
    115  1.1  mrg      40033a:       8b 04 bd 60 19 40 00    mov    0x401960(,%rdi,4),%eax
    116  1.1  mrg      400341:       c3                      retq
    117  1.1  mrg 
    118  1.1  mrg    $ gcc -O2 -free bad_code.c
    119  1.1  mrg      ......
    120  1.1  mrg      400315:       6b ff 4e                imul   $0x4e,%edi,%edi
    121  1.1  mrg      400318:       8b 04 bd 40 19 40 00    mov    0x401940(,%rdi,4),%eax
    122  1.1  mrg      40031f:       c3                      retq
    123  1.1  mrg      400320:       6b ff 2d                imul   $0x2d,%edi,%edi
    124  1.1  mrg      400323:       8b 04 bd 40 19 40 00    mov    0x401940(,%rdi,4),%eax
    125  1.1  mrg      40032a:       c3                      retq
    126  1.1  mrg 
    127  1.1  mrg    Motivating Example II :
    128  1.1  mrg    ---------------------
    129  1.1  mrg 
    130  1.1  mrg    Here is an example with a conditional move.
    131  1.1  mrg 
    132  1.1  mrg    For this program :
    133  1.1  mrg    **********************************************
    134  1.1  mrg 
    135  1.1  mrg    unsigned long long foo(unsigned x , unsigned y)
    136  1.1  mrg    {
    137  1.1  mrg      unsigned z;
    138  1.1  mrg      if (x > 100)
    139  1.1  mrg        z = x + y;
    140  1.1  mrg      else
    141  1.1  mrg        z = x - y;
    142  1.1  mrg      return (unsigned long long)(z);
    143  1.1  mrg    }
    144  1.1  mrg 
    145  1.1  mrg    $ gcc -O2 bad_code.c
    146  1.1  mrg      ............
    147  1.1  mrg      400360:       8d 14 3e                lea    (%rsi,%rdi,1),%edx
    148  1.1  mrg      400363:       89 f8                   mov    %edi,%eax
    149  1.1  mrg      400365:       29 f0                   sub    %esi,%eax
    150  1.1  mrg      400367:       83 ff 65                cmp    $0x65,%edi
    151  1.1  mrg      40036a:       0f 43 c2                cmovae %edx,%eax
    152  1.1  mrg      40036d:       89 c0                   mov    %eax,%eax - useless extension
    153  1.1  mrg      40036f:       c3                      retq
    154  1.1  mrg 
    155  1.1  mrg    $ gcc -O2 -free bad_code.c
    156  1.1  mrg      .............
    157  1.1  mrg      400360:       89 fa                   mov    %edi,%edx
    158  1.1  mrg      400362:       8d 04 3e                lea    (%rsi,%rdi,1),%eax
    159  1.1  mrg      400365:       29 f2                   sub    %esi,%edx
    160  1.1  mrg      400367:       83 ff 65                cmp    $0x65,%edi
    161  1.1  mrg      40036a:       89 d6                   mov    %edx,%esi
    162  1.1  mrg      40036c:       48 0f 42 c6             cmovb  %rsi,%rax
    163  1.1  mrg      400370:       c3                      retq
    164  1.1  mrg 
    165  1.1  mrg   Motivating Example III :
    166  1.1  mrg   ---------------------
    167  1.1  mrg 
    168  1.1  mrg   Here is an example with a type cast.
    169  1.1  mrg 
    170  1.1  mrg   For this program :
    171  1.1  mrg   **********************************************
    172  1.1  mrg 
    173  1.1  mrg   void test(int size, unsigned char *in, unsigned char *out)
    174  1.1  mrg   {
    175  1.1  mrg     int i;
    176  1.1  mrg     unsigned char xr, xg, xy=0;
    177  1.1  mrg 
    178  1.1  mrg     for (i = 0; i < size; i++) {
    179  1.1  mrg       xr = *in++;
    180  1.1  mrg       xg = *in++;
    181  1.1  mrg       xy = (unsigned char) ((19595*xr + 38470*xg) >> 16);
    182  1.1  mrg       *out++ = xy;
    183  1.1  mrg     }
    184  1.1  mrg   }
    185  1.1  mrg 
    186  1.1  mrg   $ gcc -O2 bad_code.c
    187  1.1  mrg     ............
    188  1.1  mrg     10:   0f b6 0e                movzbl (%rsi),%ecx
    189  1.1  mrg     13:   0f b6 46 01             movzbl 0x1(%rsi),%eax
    190  1.1  mrg     17:   48 83 c6 02             add    $0x2,%rsi
    191  1.1  mrg     1b:   0f b6 c9                movzbl %cl,%ecx - useless extension
    192  1.1  mrg     1e:   0f b6 c0                movzbl %al,%eax - useless extension
    193  1.1  mrg     21:   69 c9 8b 4c 00 00       imul   $0x4c8b,%ecx,%ecx
    194  1.1  mrg     27:   69 c0 46 96 00 00       imul   $0x9646,%eax,%eax
    195  1.1  mrg 
    196  1.1  mrg    $ gcc -O2 -free bad_code.c
    197  1.1  mrg      .............
    198  1.1  mrg     10:   0f b6 0e                movzbl (%rsi),%ecx
    199  1.1  mrg     13:   0f b6 46 01             movzbl 0x1(%rsi),%eax
    200  1.1  mrg     17:   48 83 c6 02             add    $0x2,%rsi
    201  1.1  mrg     1b:   69 c9 8b 4c 00 00       imul   $0x4c8b,%ecx,%ecx
    202  1.1  mrg     21:   69 c0 46 96 00 00       imul   $0x9646,%eax,%eax
    203  1.1  mrg 
    204  1.1  mrg    Usefulness :
    205  1.1  mrg    ----------
    206  1.1  mrg 
    207  1.1  mrg    The original redundant zero-extension elimination pass reported reduction
    208  1.1  mrg    of the dynamic instruction count of a compression benchmark by 2.8% and
    209  1.1  mrg    improvement of its run time by about 1%.
    210  1.1  mrg 
    211  1.1  mrg    The additional performance gain with the enhanced pass is mostly expected
    212  1.1  mrg    on in-order architectures where redundancy cannot be compensated by out of
    213  1.1  mrg    order execution.  Measurements showed up to 10% performance gain (reduced
    214  1.1  mrg    run time) on EEMBC 2.0 benchmarks on Atom processor with geomean performance
    215  1.1  mrg    gain 1%.  */
    216  1.1  mrg 
    217  1.1  mrg 
    218  1.1  mrg #include "config.h"
    219  1.1  mrg #include "system.h"
    220  1.1  mrg #include "coretypes.h"
    221  1.1  mrg #include "backend.h"
    222  1.1  mrg #include "target.h"
    223  1.1  mrg #include "rtl.h"
    224  1.1  mrg #include "tree.h"
    225  1.1  mrg #include "df.h"
    226  1.1  mrg #include "memmodel.h"
    227  1.1  mrg #include "tm_p.h"
    228  1.1  mrg #include "optabs.h"
    229  1.1  mrg #include "regs.h"
    230  1.1  mrg #include "emit-rtl.h"
    231  1.1  mrg #include "recog.h"
    232  1.1  mrg #include "cfgrtl.h"
    233  1.1  mrg #include "expr.h"
    234  1.1  mrg #include "tree-pass.h"
    235  1.1  mrg 
    236  1.1  mrg /* This structure represents a candidate for elimination.  */
    237  1.1  mrg 
    238  1.1  mrg struct ext_cand
    239  1.1  mrg {
    240  1.1  mrg   /* The expression.  */
    241  1.1  mrg   const_rtx expr;
    242  1.1  mrg 
    243  1.1  mrg   /* The kind of extension.  */
    244  1.1  mrg   enum rtx_code code;
    245  1.1  mrg 
    246  1.1  mrg   /* The destination mode.  */
    247  1.1  mrg   machine_mode mode;
    248  1.1  mrg 
    249  1.1  mrg   /* The instruction where it lives.  */
    250  1.1  mrg   rtx_insn *insn;
    251  1.1  mrg };
    252  1.1  mrg 
    253  1.1  mrg 
    254  1.1  mrg static int max_insn_uid;
    255  1.1  mrg 
    256  1.1  mrg /* Update or remove REG_EQUAL or REG_EQUIV notes for INSN.  */
    257  1.1  mrg 
    258  1.1  mrg static bool
    259  1.1  mrg update_reg_equal_equiv_notes (rtx_insn *insn, machine_mode new_mode,
    260  1.1  mrg 			      machine_mode old_mode, enum rtx_code code)
    261  1.1  mrg {
    262  1.1  mrg   rtx *loc = &REG_NOTES (insn);
    263  1.1  mrg   while (*loc)
    264  1.1  mrg     {
    265  1.1  mrg       enum reg_note kind = REG_NOTE_KIND (*loc);
    266  1.1  mrg       if (kind == REG_EQUAL || kind == REG_EQUIV)
    267  1.1  mrg 	{
    268  1.1  mrg 	  rtx orig_src = XEXP (*loc, 0);
    269  1.1  mrg 	  /* Update equivalency constants.  Recall that RTL constants are
    270  1.1  mrg 	     sign-extended.  */
    271  1.1  mrg 	  if (GET_CODE (orig_src) == CONST_INT
    272  1.1  mrg 	      && HWI_COMPUTABLE_MODE_P (new_mode))
    273  1.1  mrg 	    {
    274  1.1  mrg 	      if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
    275  1.1  mrg 		/* Nothing needed.  */;
    276  1.1  mrg 	      else
    277  1.1  mrg 		{
    278  1.1  mrg 		  /* Zero-extend the negative constant by masking out the
    279  1.1  mrg 		     bits outside the source mode.  */
    280  1.1  mrg 		  rtx new_const_int
    281  1.1  mrg 		    = gen_int_mode (INTVAL (orig_src)
    282  1.1  mrg 				    & GET_MODE_MASK (old_mode),
    283  1.1  mrg 				    new_mode);
    284  1.1  mrg 		  if (!validate_change (insn, &XEXP (*loc, 0),
    285  1.1  mrg 					new_const_int, true))
    286  1.1  mrg 		    return false;
    287  1.1  mrg 		}
    288  1.1  mrg 	      loc = &XEXP (*loc, 1);
    289  1.1  mrg 	    }
    290  1.1  mrg 	  /* Drop all other notes, they assume a wrong mode.  */
    291  1.1  mrg 	  else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
    292  1.1  mrg 	    return false;
    293  1.1  mrg 	}
    294  1.1  mrg       else
    295  1.1  mrg 	loc = &XEXP (*loc, 1);
    296  1.1  mrg     }
    297  1.1  mrg   return true;
    298  1.1  mrg }
    299  1.1  mrg 
    300  1.1  mrg /* Given a insn (CURR_INSN), an extension candidate for removal (CAND)
    301  1.1  mrg    and a pointer to the SET rtx (ORIG_SET) that needs to be modified,
    302  1.1  mrg    this code modifies the SET rtx to a new SET rtx that extends the
    303  1.1  mrg    right hand expression into a register on the left hand side.  Note
    304  1.1  mrg    that multiple assumptions are made about the nature of the set that
    305  1.1  mrg    needs to be true for this to work and is called from merge_def_and_ext.
    306  1.1  mrg 
    307  1.1  mrg    Original :
    308  1.1  mrg    (set (reg a) (expression))
    309  1.1  mrg 
    310  1.1  mrg    Transform :
    311  1.1  mrg    (set (reg a) (any_extend (expression)))
    312  1.1  mrg 
    313  1.1  mrg    Special Cases :
    314  1.1  mrg    If the expression is a constant or another extension, then directly
    315  1.1  mrg    assign it to the register.  */
    316  1.1  mrg 
    317  1.1  mrg static bool
    318  1.1  mrg combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
    319  1.1  mrg {
    320  1.1  mrg   rtx orig_src = SET_SRC (*orig_set);
    321  1.1  mrg   machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
    322  1.1  mrg   rtx new_set;
    323  1.1  mrg   rtx cand_pat = single_set (cand->insn);
    324  1.1  mrg 
    325  1.1  mrg   /* If the extension's source/destination registers are not the same
    326  1.1  mrg      then we need to change the original load to reference the destination
    327  1.1  mrg      of the extension.  Then we need to emit a copy from that destination
    328  1.1  mrg      to the original destination of the load.  */
    329  1.1  mrg   rtx new_reg;
    330  1.1  mrg   bool copy_needed
    331  1.1  mrg     = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0)));
    332  1.1  mrg   if (copy_needed)
    333  1.1  mrg     new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat)));
    334  1.1  mrg   else
    335  1.1  mrg     new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
    336  1.1  mrg 
    337  1.1  mrg   /* Merge constants by directly moving the constant into the register under
    338  1.1  mrg      some conditions.  Recall that RTL constants are sign-extended.  */
    339  1.1  mrg   if (GET_CODE (orig_src) == CONST_INT
    340  1.1  mrg       && HWI_COMPUTABLE_MODE_P (cand->mode))
    341  1.1  mrg     {
    342  1.1  mrg       if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND)
    343  1.1  mrg 	new_set = gen_rtx_SET (new_reg, orig_src);
    344  1.1  mrg       else
    345  1.1  mrg 	{
    346  1.1  mrg 	  /* Zero-extend the negative constant by masking out the bits outside
    347  1.1  mrg 	     the source mode.  */
    348  1.1  mrg 	  rtx new_const_int
    349  1.1  mrg 	    = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode),
    350  1.1  mrg 			    GET_MODE (new_reg));
    351  1.1  mrg 	  new_set = gen_rtx_SET (new_reg, new_const_int);
    352  1.1  mrg 	}
    353  1.1  mrg     }
    354  1.1  mrg   else if (GET_MODE (orig_src) == VOIDmode)
    355  1.1  mrg     {
    356  1.1  mrg       /* This is mostly due to a call insn that should not be optimized.  */
    357  1.1  mrg       return false;
    358  1.1  mrg     }
    359  1.1  mrg   else if (GET_CODE (orig_src) == cand->code)
    360  1.1  mrg     {
    361  1.1  mrg       /* Here is a sequence of two extensions.  Try to merge them.  */
    362  1.1  mrg       rtx temp_extension
    363  1.1  mrg 	= gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0));
    364  1.1  mrg       rtx simplified_temp_extension = simplify_rtx (temp_extension);
    365  1.1  mrg       if (simplified_temp_extension)
    366  1.1  mrg         temp_extension = simplified_temp_extension;
    367  1.1  mrg       new_set = gen_rtx_SET (new_reg, temp_extension);
    368  1.1  mrg     }
    369  1.1  mrg   else if (GET_CODE (orig_src) == IF_THEN_ELSE)
    370  1.1  mrg     {
    371  1.1  mrg       /* Only IF_THEN_ELSE of phi-type copies are combined.  Otherwise,
    372  1.1  mrg          in general, IF_THEN_ELSE should not be combined.  */
    373  1.1  mrg       return false;
    374  1.1  mrg     }
    375  1.1  mrg   else
    376  1.1  mrg     {
    377  1.1  mrg       /* This is the normal case.  */
    378  1.1  mrg       rtx temp_extension
    379  1.1  mrg 	= gen_rtx_fmt_e (cand->code, cand->mode, orig_src);
    380  1.1  mrg       rtx simplified_temp_extension = simplify_rtx (temp_extension);
    381  1.1  mrg       if (simplified_temp_extension)
    382  1.1  mrg         temp_extension = simplified_temp_extension;
    383  1.1  mrg       new_set = gen_rtx_SET (new_reg, temp_extension);
    384  1.1  mrg     }
    385  1.1  mrg 
    386  1.1  mrg   /* This change is a part of a group of changes.  Hence,
    387  1.1  mrg      validate_change will not try to commit the change.  */
    388  1.1  mrg   if (validate_change (curr_insn, orig_set, new_set, true)
    389  1.1  mrg       && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
    390  1.1  mrg 				       cand->code))
    391  1.1  mrg     {
    392  1.1  mrg       if (dump_file)
    393  1.1  mrg         {
    394  1.1  mrg           fprintf (dump_file,
    395  1.1  mrg 		   "Tentatively merged extension with definition %s:\n",
    396  1.1  mrg 		   (copy_needed) ? "(copy needed)" : "");
    397  1.1  mrg           print_rtl_single (dump_file, curr_insn);
    398  1.1  mrg         }
    399  1.1  mrg       return true;
    400  1.1  mrg     }
    401  1.1  mrg 
    402  1.1  mrg   return false;
    403  1.1  mrg }
    404  1.1  mrg 
    405  1.1  mrg /* Treat if_then_else insns, where the operands of both branches
    406  1.1  mrg    are registers, as copies.  For instance,
    407  1.1  mrg    Original :
    408  1.1  mrg    (set (reg:SI a) (if_then_else (cond) (reg:SI b) (reg:SI c)))
    409  1.1  mrg    Transformed :
    410  1.1  mrg    (set (reg:DI a) (if_then_else (cond) (reg:DI b) (reg:DI c)))
    411  1.1  mrg    DEF_INSN is the if_then_else insn.  */
    412  1.1  mrg 
    413  1.1  mrg static bool
    414  1.1  mrg transform_ifelse (ext_cand *cand, rtx_insn *def_insn)
    415  1.1  mrg {
    416  1.1  mrg   rtx set_insn = PATTERN (def_insn);
    417  1.1  mrg   rtx srcreg, dstreg, srcreg2;
    418  1.1  mrg   rtx map_srcreg, map_dstreg, map_srcreg2;
    419  1.1  mrg   rtx ifexpr;
    420  1.1  mrg   rtx cond;
    421  1.1  mrg   rtx new_set;
    422  1.1  mrg 
    423  1.1  mrg   gcc_assert (GET_CODE (set_insn) == SET);
    424  1.1  mrg 
    425  1.1  mrg   cond = XEXP (SET_SRC (set_insn), 0);
    426  1.1  mrg   dstreg = SET_DEST (set_insn);
    427  1.1  mrg   srcreg = XEXP (SET_SRC (set_insn), 1);
    428  1.1  mrg   srcreg2 = XEXP (SET_SRC (set_insn), 2);
    429  1.1  mrg   /* If the conditional move already has the right or wider mode,
    430  1.1  mrg      there is nothing to do.  */
    431  1.1  mrg   if (GET_MODE_UNIT_SIZE (GET_MODE (dstreg))
    432  1.1  mrg       >= GET_MODE_UNIT_SIZE (cand->mode))
    433  1.1  mrg     return true;
    434  1.1  mrg 
    435  1.1  mrg   map_srcreg = gen_rtx_REG (cand->mode, REGNO (srcreg));
    436  1.1  mrg   map_srcreg2 = gen_rtx_REG (cand->mode, REGNO (srcreg2));
    437  1.1  mrg   map_dstreg = gen_rtx_REG (cand->mode, REGNO (dstreg));
    438  1.1  mrg   ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2);
    439  1.1  mrg   new_set = gen_rtx_SET (map_dstreg, ifexpr);
    440  1.1  mrg 
    441  1.1  mrg   if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)
    442  1.1  mrg       && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg),
    443  1.1  mrg 				       cand->code))
    444  1.1  mrg     {
    445  1.1  mrg       if (dump_file)
    446  1.1  mrg         {
    447  1.1  mrg           fprintf (dump_file,
    448  1.1  mrg 		   "Mode of conditional move instruction extended:\n");
    449  1.1  mrg           print_rtl_single (dump_file, def_insn);
    450  1.1  mrg         }
    451  1.1  mrg       return true;
    452  1.1  mrg     }
    453  1.1  mrg 
    454  1.1  mrg   return false;
    455  1.1  mrg }
    456  1.1  mrg 
    457  1.1  mrg /* Get all the reaching definitions of an instruction.  The definitions are
    458  1.1  mrg    desired for REG used in INSN.  Return the definition list or NULL if a
    459  1.1  mrg    definition is missing.  If DEST is non-NULL, additionally push the INSN
    460  1.1  mrg    of the definitions onto DEST.  */
    461  1.1  mrg 
    462  1.1  mrg static struct df_link *
    463  1.1  mrg get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest)
    464  1.1  mrg {
    465  1.1  mrg   df_ref use;
    466  1.1  mrg   struct df_link *ref_chain, *ref_link;
    467  1.1  mrg 
    468  1.1  mrg   FOR_EACH_INSN_USE (use, insn)
    469  1.1  mrg     {
    470  1.1  mrg       if (GET_CODE (DF_REF_REG (use)) == SUBREG)
    471  1.1  mrg         return NULL;
    472  1.1  mrg       if (REGNO (DF_REF_REG (use)) == REGNO (reg))
    473  1.1  mrg 	break;
    474  1.1  mrg     }
    475  1.1  mrg 
    476  1.1  mrg   gcc_assert (use != NULL);
    477  1.1  mrg 
    478  1.1  mrg   ref_chain = DF_REF_CHAIN (use);
    479  1.1  mrg 
    480  1.1  mrg   for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
    481  1.1  mrg     {
    482  1.1  mrg       /* Problem getting some definition for this instruction.  */
    483  1.1  mrg       if (ref_link->ref == NULL)
    484  1.1  mrg         return NULL;
    485  1.1  mrg       if (DF_REF_INSN_INFO (ref_link->ref) == NULL)
    486  1.1  mrg         return NULL;
    487  1.1  mrg       /* As global regs are assumed to be defined at each function call
    488  1.1  mrg 	 dataflow can report a call_insn as being a definition of REG.
    489  1.1  mrg 	 But we can't do anything with that in this pass so proceed only
    490  1.1  mrg 	 if the instruction really sets REG in a way that can be deduced
    491  1.1  mrg 	 from the RTL structure.  */
    492  1.1  mrg       if (global_regs[REGNO (reg)]
    493  1.1  mrg 	  && !set_of (reg, DF_REF_INSN (ref_link->ref)))
    494  1.1  mrg 	return NULL;
    495  1.1  mrg     }
    496  1.1  mrg 
    497  1.1  mrg   if (dest)
    498  1.1  mrg     for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
    499  1.1  mrg       dest->safe_push (DF_REF_INSN (ref_link->ref));
    500  1.1  mrg 
    501  1.1  mrg   return ref_chain;
    502  1.1  mrg }
    503  1.1  mrg 
    504  1.1  mrg /* Get all the reaching uses of an instruction.  The uses are desired for REG
    505  1.1  mrg    set in INSN.  Return use list or NULL if a use is missing or irregular.  */
    506  1.1  mrg 
    507  1.1  mrg static struct df_link *
    508  1.1  mrg get_uses (rtx_insn *insn, rtx reg)
    509  1.1  mrg {
    510  1.1  mrg   df_ref def;
    511  1.1  mrg   struct df_link *ref_chain, *ref_link;
    512  1.1  mrg 
    513  1.1  mrg   FOR_EACH_INSN_DEF (def, insn)
    514  1.1  mrg     if (REGNO (DF_REF_REG (def)) == REGNO (reg))
    515  1.1  mrg       break;
    516  1.1  mrg 
    517  1.1  mrg   gcc_assert (def != NULL);
    518  1.1  mrg 
    519  1.1  mrg   ref_chain = DF_REF_CHAIN (def);
    520  1.1  mrg 
    521  1.1  mrg   for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
    522  1.1  mrg     {
    523  1.1  mrg       /* Problem getting some use for this instruction.  */
    524  1.1  mrg       if (ref_link->ref == NULL)
    525  1.1  mrg         return NULL;
    526  1.1  mrg       if (DF_REF_CLASS (ref_link->ref) != DF_REF_REGULAR)
    527  1.1  mrg 	return NULL;
    528  1.1  mrg     }
    529  1.1  mrg 
    530  1.1  mrg   return ref_chain;
    531  1.1  mrg }
    532  1.1  mrg 
    533  1.1  mrg /* Return true if INSN is
    534  1.1  mrg      (SET (reg REGNO (def_reg)) (if_then_else (cond) (REG x1) (REG x2)))
    535  1.1  mrg    and store x1 and x2 in REG_1 and REG_2.  */
    536  1.1  mrg 
    537  1.1  mrg static bool
    538  1.1  mrg is_cond_copy_insn (rtx_insn *insn, rtx *reg1, rtx *reg2)
    539  1.1  mrg {
    540  1.1  mrg   rtx expr = single_set (insn);
    541  1.1  mrg 
    542  1.1  mrg   if (expr != NULL_RTX
    543  1.1  mrg       && GET_CODE (expr) == SET
    544  1.1  mrg       && GET_CODE (SET_DEST (expr)) == REG
    545  1.1  mrg       && GET_CODE (SET_SRC (expr))  == IF_THEN_ELSE
    546  1.1  mrg       && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG
    547  1.1  mrg       && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG)
    548  1.1  mrg     {
    549  1.1  mrg       *reg1 = XEXP (SET_SRC (expr), 1);
    550  1.1  mrg       *reg2 = XEXP (SET_SRC (expr), 2);
    551  1.1  mrg       return true;
    552  1.1  mrg     }
    553  1.1  mrg 
    554  1.1  mrg   return false;
    555  1.1  mrg }
    556  1.1  mrg 
    557  1.1  mrg enum ext_modified_kind
    558  1.1  mrg {
    559  1.1  mrg   /* The insn hasn't been modified by ree pass yet.  */
    560  1.1  mrg   EXT_MODIFIED_NONE,
    561  1.1  mrg   /* Changed into zero extension.  */
    562  1.1  mrg   EXT_MODIFIED_ZEXT,
    563  1.1  mrg   /* Changed into sign extension.  */
    564  1.1  mrg   EXT_MODIFIED_SEXT
    565  1.1  mrg };
    566  1.1  mrg 
    567  1.1  mrg struct ATTRIBUTE_PACKED ext_modified
    568  1.1  mrg {
    569  1.1  mrg   /* Mode from which ree has zero or sign extended the destination.  */
    570  1.1  mrg   ENUM_BITFIELD(machine_mode) mode : 8;
    571  1.1  mrg 
    572  1.1  mrg   /* Kind of modification of the insn.  */
    573  1.1  mrg   ENUM_BITFIELD(ext_modified_kind) kind : 2;
    574  1.1  mrg 
    575  1.1  mrg   unsigned int do_not_reextend : 1;
    576  1.1  mrg 
    577  1.1  mrg   /* True if the insn is scheduled to be deleted.  */
    578  1.1  mrg   unsigned int deleted : 1;
    579  1.1  mrg };
    580  1.1  mrg 
    581  1.1  mrg /* Vectors used by combine_reaching_defs and its helpers.  */
    582  1.1  mrg class ext_state
    583  1.1  mrg {
    584  1.1  mrg public:
    585  1.1  mrg   /* In order to avoid constant alloc/free, we keep these
    586  1.1  mrg      4 vectors live through the entire find_and_remove_re and just
    587  1.1  mrg      truncate them each time.  */
    588  1.1  mrg   auto_vec<rtx_insn *> defs_list;
    589  1.1  mrg   auto_vec<rtx_insn *> copies_list;
    590  1.1  mrg   auto_vec<rtx_insn *> modified_list;
    591  1.1  mrg   auto_vec<rtx_insn *> work_list;
    592  1.1  mrg 
    593  1.1  mrg   /* For instructions that have been successfully modified, this is
    594  1.1  mrg      the original mode from which the insn is extending and
    595  1.1  mrg      kind of extension.  */
    596  1.1  mrg   struct ext_modified *modified;
    597  1.1  mrg };
    598  1.1  mrg 
    599  1.1  mrg /* Reaching Definitions of the extended register could be conditional copies
    600  1.1  mrg    or regular definitions.  This function separates the two types into two
    601  1.1  mrg    lists, STATE->DEFS_LIST and STATE->COPIES_LIST.  This is necessary because,
    602  1.1  mrg    if a reaching definition is a conditional copy, merging the extension with
    603  1.1  mrg    this definition is wrong.  Conditional copies are merged by transitively
    604  1.1  mrg    merging their definitions.  The defs_list is populated with all the reaching
    605  1.1  mrg    definitions of the extension instruction (EXTEND_INSN) which must be merged
    606  1.1  mrg    with an extension.  The copies_list contains all the conditional moves that
    607  1.1  mrg    will later be extended into a wider mode conditional move if all the merges
    608  1.1  mrg    are successful.  The function returns false upon failure, true upon
    609  1.1  mrg    success.  */
    610  1.1  mrg 
    611  1.1  mrg static bool
    612  1.1  mrg make_defs_and_copies_lists (rtx_insn *extend_insn, const_rtx set_pat,
    613  1.1  mrg 			    ext_state *state)
    614  1.1  mrg {
    615  1.1  mrg   rtx src_reg = XEXP (SET_SRC (set_pat), 0);
    616  1.1  mrg   bool *is_insn_visited;
    617  1.1  mrg   bool ret = true;
    618  1.1  mrg 
    619  1.1  mrg   state->work_list.truncate (0);
    620  1.1  mrg 
    621  1.1  mrg   /* Initialize the work list.  */
    622  1.1  mrg   if (!get_defs (extend_insn, src_reg, &state->work_list))
    623  1.1  mrg     return false;
    624  1.1  mrg 
    625  1.1  mrg   is_insn_visited = XCNEWVEC (bool, max_insn_uid);
    626  1.1  mrg 
    627  1.1  mrg   /* Perform transitive closure for conditional copies.  */
    628  1.1  mrg   while (!state->work_list.is_empty ())
    629  1.1  mrg     {
    630  1.1  mrg       rtx_insn *def_insn = state->work_list.pop ();
    631  1.1  mrg       rtx reg1, reg2;
    632  1.1  mrg 
    633  1.1  mrg       gcc_assert (INSN_UID (def_insn) < max_insn_uid);
    634  1.1  mrg 
    635  1.1  mrg       if (is_insn_visited[INSN_UID (def_insn)])
    636  1.1  mrg 	continue;
    637  1.1  mrg       is_insn_visited[INSN_UID (def_insn)] = true;
    638  1.1  mrg 
    639  1.1  mrg       if (is_cond_copy_insn (def_insn, &reg1, &reg2))
    640  1.1  mrg 	{
    641  1.1  mrg 	  /* Push it onto the copy list first.  */
    642  1.1  mrg 	  state->copies_list.safe_push (def_insn);
    643  1.1  mrg 
    644  1.1  mrg 	  /* Now perform the transitive closure.  */
    645  1.1  mrg 	  if (!get_defs (def_insn, reg1, &state->work_list)
    646  1.1  mrg 	      || !get_defs (def_insn, reg2, &state->work_list))
    647  1.1  mrg 	    {
    648  1.1  mrg 	      ret = false;
    649  1.1  mrg 	      break;
    650  1.1  mrg 	    }
    651  1.1  mrg         }
    652  1.1  mrg       else
    653  1.1  mrg 	state->defs_list.safe_push (def_insn);
    654  1.1  mrg     }
    655  1.1  mrg 
    656  1.1  mrg   XDELETEVEC (is_insn_visited);
    657  1.1  mrg 
    658  1.1  mrg   return ret;
    659  1.1  mrg }
    660  1.1  mrg 
    661  1.1  mrg /* If DEF_INSN has single SET expression with a register
    662  1.1  mrg    destination, possibly buried inside a PARALLEL, return
    663  1.1  mrg    the address of the SET expression, else return NULL.
    664  1.1  mrg    This is similar to single_set, except that single_set
    665  1.1  mrg    allows multiple SETs when all but one is dead.  */
    666  1.1  mrg static rtx *
    667  1.1  mrg get_sub_rtx (rtx_insn *def_insn)
    668  1.1  mrg {
    669  1.1  mrg   enum rtx_code code = GET_CODE (PATTERN (def_insn));
    670  1.1  mrg   rtx *sub_rtx = NULL;
    671  1.1  mrg 
    672  1.1  mrg   if (code == PARALLEL)
    673  1.1  mrg     {
    674  1.1  mrg       for (int i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++)
    675  1.1  mrg         {
    676  1.1  mrg           rtx s_expr = XVECEXP (PATTERN (def_insn), 0, i);
    677  1.1  mrg           if (GET_CODE (s_expr) != SET)
    678  1.1  mrg             continue;
    679  1.1  mrg 	  if (!REG_P (SET_DEST (s_expr)))
    680  1.1  mrg 	    continue;
    681  1.1  mrg 
    682  1.1  mrg           if (sub_rtx == NULL)
    683  1.1  mrg             sub_rtx = &XVECEXP (PATTERN (def_insn), 0, i);
    684  1.1  mrg           else
    685  1.1  mrg             {
    686  1.1  mrg               /* PARALLEL with multiple SETs.  */
    687  1.1  mrg               return NULL;
    688  1.1  mrg             }
    689  1.1  mrg         }
    690  1.1  mrg     }
    691  1.1  mrg   else if (code == SET)
    692  1.1  mrg     {
    693  1.1  mrg 	rtx s_expr = PATTERN (def_insn);
    694  1.1  mrg 	if (REG_P (SET_DEST (s_expr)))
    695  1.1  mrg 	  sub_rtx = &PATTERN (def_insn);
    696  1.1  mrg     }
    697  1.1  mrg 
    698  1.1  mrg   return sub_rtx;
    699  1.1  mrg }
    700  1.1  mrg 
    701  1.1  mrg /* Merge the DEF_INSN with an extension.  Calls combine_set_extension
    702  1.1  mrg    on the SET pattern.  */
    703  1.1  mrg 
    704  1.1  mrg static bool
    705  1.1  mrg merge_def_and_ext (ext_cand *cand, rtx_insn *def_insn, ext_state *state)
    706  1.1  mrg {
    707  1.1  mrg   machine_mode ext_src_mode;
    708  1.1  mrg   rtx *sub_rtx;
    709  1.1  mrg 
    710  1.1  mrg   ext_src_mode = GET_MODE (XEXP (SET_SRC (cand->expr), 0));
    711  1.1  mrg   sub_rtx = get_sub_rtx (def_insn);
    712  1.1  mrg 
    713  1.1  mrg   if (sub_rtx == NULL)
    714  1.1  mrg     return false;
    715  1.1  mrg 
    716  1.1  mrg   if (GET_MODE (SET_DEST (*sub_rtx)) == ext_src_mode
    717  1.1  mrg 	  || ((state->modified[INSN_UID (def_insn)].kind
    718  1.1  mrg 	       == (cand->code == ZERO_EXTEND
    719  1.1  mrg 		   ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT))
    720  1.1  mrg 	      && state->modified[INSN_UID (def_insn)].mode
    721  1.1  mrg 		 == ext_src_mode))
    722  1.1  mrg     {
    723  1.1  mrg       if (GET_MODE_UNIT_SIZE (GET_MODE (SET_DEST (*sub_rtx)))
    724  1.1  mrg 	  >= GET_MODE_UNIT_SIZE (cand->mode))
    725  1.1  mrg 	return true;
    726  1.1  mrg       /* If def_insn is already scheduled to be deleted, don't attempt
    727  1.1  mrg 	 to modify it.  */
    728  1.1  mrg       if (state->modified[INSN_UID (def_insn)].deleted)
    729  1.1  mrg 	return false;
    730  1.1  mrg       if (combine_set_extension (cand, def_insn, sub_rtx))
    731  1.1  mrg 	{
    732  1.1  mrg 	  if (state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)
    733  1.1  mrg 	    state->modified[INSN_UID (def_insn)].mode = ext_src_mode;
    734  1.1  mrg 	  return true;
    735  1.1  mrg 	}
    736  1.1  mrg     }
    737  1.1  mrg 
    738  1.1  mrg   return false;
    739  1.1  mrg }
    740  1.1  mrg 
    741  1.1  mrg /* Given SRC, which should be one or more extensions of a REG, strip
    742  1.1  mrg    away the extensions and return the REG.  */
    743  1.1  mrg 
    744  1.1  mrg static inline rtx
    745  1.1  mrg get_extended_src_reg (rtx src)
    746  1.1  mrg {
    747  1.1  mrg   while (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND)
    748  1.1  mrg     src = XEXP (src, 0);
    749  1.1  mrg   gcc_assert (REG_P (src));
    750  1.1  mrg   return src;
    751  1.1  mrg }
    752  1.1  mrg 
    753  1.1  mrg /* This function goes through all reaching defs of the source
    754  1.1  mrg    of the candidate for elimination (CAND) and tries to combine
    755  1.1  mrg    the extension with the definition instruction.  The changes
    756  1.1  mrg    are made as a group so that even if one definition cannot be
    757  1.1  mrg    merged, all reaching definitions end up not being merged.
    758  1.1  mrg    When a conditional copy is encountered, merging is attempted
    759  1.1  mrg    transitively on its definitions.  It returns true upon success
    760  1.1  mrg    and false upon failure.  */
    761  1.1  mrg 
    762  1.1  mrg static bool
    763  1.1  mrg combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
    764  1.1  mrg {
    765  1.1  mrg   rtx_insn *def_insn;
    766  1.1  mrg   bool merge_successful = true;
    767  1.1  mrg   int i;
    768  1.1  mrg   int defs_ix;
    769  1.1  mrg   bool outcome;
    770  1.1  mrg 
    771  1.1  mrg   state->defs_list.truncate (0);
    772  1.1  mrg   state->copies_list.truncate (0);
    773  1.1  mrg 
    774  1.1  mrg   outcome = make_defs_and_copies_lists (cand->insn, set_pat, state);
    775  1.1  mrg 
    776  1.1  mrg   if (!outcome)
    777  1.1  mrg     return false;
    778  1.1  mrg 
    779  1.1  mrg   /* If the destination operand of the extension is a different
    780  1.1  mrg      register than the source operand, then additional restrictions
    781  1.1  mrg      are needed.  Note we have to handle cases where we have nested
    782  1.1  mrg      extensions in the source operand.
    783  1.1  mrg 
    784  1.1  mrg      Candidate insns are known to be single_sets, via the test in
    785  1.1  mrg      find_removable_extensions.  So we continue to use single_set here
    786  1.1  mrg      rather than get_sub_rtx.  */
    787  1.1  mrg   rtx set = single_set (cand->insn);
    788  1.1  mrg   bool copy_needed
    789  1.1  mrg     = (REGNO (SET_DEST (set)) != REGNO (get_extended_src_reg (SET_SRC (set))));
    790  1.1  mrg   if (copy_needed)
    791  1.1  mrg     {
    792  1.1  mrg       /* Considering transformation of
    793  1.1  mrg 	 (set (reg1) (expression))
    794  1.1  mrg 	 ...
    795  1.1  mrg 	 (set (reg2) (any_extend (reg1)))
    796  1.1  mrg 
    797  1.1  mrg 	 into
    798  1.1  mrg 
    799  1.1  mrg 	 (set (reg2) (any_extend (expression)))
    800  1.1  mrg 	 (set (reg1) (reg2))
    801  1.1  mrg 	 ...  */
    802  1.1  mrg 
    803  1.1  mrg       /* In theory we could handle more than one reaching def, it
    804  1.1  mrg 	 just makes the code to update the insn stream more complex.  */
    805  1.1  mrg       if (state->defs_list.length () != 1)
    806  1.1  mrg 	return false;
    807  1.1  mrg 
    808  1.1  mrg       /* We don't have the structure described above if there are
    809  1.1  mrg 	 conditional moves in between the def and the candidate,
    810  1.1  mrg 	 and we will not handle them correctly.  See PR68194.  */
    811  1.1  mrg       if (state->copies_list.length () > 0)
    812  1.1  mrg 	return false;
    813  1.1  mrg 
    814  1.1  mrg       /* We require the candidate not already be modified.  It may,
    815  1.1  mrg 	 for example have been changed from a (sign_extend (reg))
    816  1.1  mrg 	 into (zero_extend (sign_extend (reg))).
    817  1.1  mrg 
    818  1.1  mrg 	 Handling that case shouldn't be terribly difficult, but the code
    819  1.1  mrg 	 here and the code to emit copies would need auditing.  Until
    820  1.1  mrg 	 we see a need, this is the safe thing to do.  */
    821  1.1  mrg       if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
    822  1.1  mrg 	return false;
    823  1.1  mrg 
    824  1.1  mrg       machine_mode dst_mode = GET_MODE (SET_DEST (set));
    825  1.1  mrg       rtx src_reg = get_extended_src_reg (SET_SRC (set));
    826  1.1  mrg 
    827  1.1  mrg       /* Ensure we can use the src_reg in dst_mode (needed for
    828  1.1  mrg 	 the (set (reg1) (reg2)) insn mentioned above).  */
    829  1.1  mrg       if (!targetm.hard_regno_mode_ok (REGNO (src_reg), dst_mode))
    830  1.1  mrg 	return false;
    831  1.1  mrg 
    832  1.1  mrg       /* Ensure the number of hard registers of the copy match.  */
    833  1.1  mrg       if (hard_regno_nregs (REGNO (src_reg), dst_mode) != REG_NREGS (src_reg))
    834  1.1  mrg 	return false;
    835  1.1  mrg 
    836  1.1  mrg       /* There's only one reaching def.  */
    837  1.1  mrg       rtx_insn *def_insn = state->defs_list[0];
    838  1.1  mrg 
    839  1.1  mrg       /* The defining statement must not have been modified either.  */
    840  1.1  mrg       if (state->modified[INSN_UID (def_insn)].kind != EXT_MODIFIED_NONE)
    841  1.1  mrg 	return false;
    842  1.1  mrg 
    843  1.1  mrg       /* The defining statement and candidate insn must be in the same block.
    844  1.1  mrg 	 This is merely to keep the test for safety and updating the insn
    845  1.1  mrg 	 stream simple.  Also ensure that within the block the candidate
    846  1.1  mrg 	 follows the defining insn.  */
    847  1.1  mrg       basic_block bb = BLOCK_FOR_INSN (cand->insn);
    848  1.1  mrg       if (bb != BLOCK_FOR_INSN (def_insn)
    849  1.1  mrg 	  || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))
    850  1.1  mrg 	return false;
    851  1.1  mrg 
    852  1.1  mrg       /* If there is an overlap between the destination of DEF_INSN and
    853  1.1  mrg 	 CAND->insn, then this transformation is not safe.  Note we have
    854  1.1  mrg 	 to test in the widened mode.  */
    855  1.1  mrg       rtx *dest_sub_rtx = get_sub_rtx (def_insn);
    856  1.1  mrg       if (dest_sub_rtx == NULL)
    857  1.1  mrg 	return false;
    858  1.1  mrg 
    859  1.1  mrg       rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (set)),
    860  1.1  mrg 				 REGNO (SET_DEST (*dest_sub_rtx)));
    861  1.1  mrg       if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (set)))
    862  1.1  mrg 	return false;
    863  1.1  mrg 
    864  1.1  mrg       /* On RISC machines we must make sure that changing the mode of SRC_REG
    865  1.1  mrg 	 as destination register will not affect its reaching uses, which may
    866  1.1  mrg 	 read its value in a larger mode because DEF_INSN implicitly sets it
    867  1.1  mrg 	 in word mode.  */
    868  1.1  mrg       poly_int64 prec
    869  1.1  mrg 	= GET_MODE_PRECISION (GET_MODE (SET_DEST (*dest_sub_rtx)));
    870  1.1  mrg       if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
    871  1.1  mrg 	{
    872  1.1  mrg 	  struct df_link *uses = get_uses (def_insn, src_reg);
    873  1.1  mrg 	  if (!uses)
    874  1.1  mrg 	    return false;
    875  1.1  mrg 
    876  1.1  mrg 	  for (df_link *use = uses; use; use = use->next)
    877  1.1  mrg 	    if (paradoxical_subreg_p (GET_MODE (*DF_REF_LOC (use->ref)),
    878  1.1  mrg 				      GET_MODE (SET_DEST (*dest_sub_rtx)))
    879  1.1  mrg 		&& !DEBUG_INSN_P (DF_REF_INSN (use->ref)))
    880  1.1  mrg 	      return false;
    881  1.1  mrg 	}
    882  1.1  mrg 
    883  1.1  mrg       /* The destination register of the extension insn must not be
    884  1.1  mrg 	 used or set between the def_insn and cand->insn exclusive.  */
    885  1.1  mrg       if (reg_used_between_p (SET_DEST (set), def_insn, cand->insn)
    886  1.1  mrg 	  || reg_set_between_p (SET_DEST (set), def_insn, cand->insn))
    887  1.1  mrg 	return false;
    888  1.1  mrg 
    889  1.1  mrg       /* We must be able to copy between the two registers.   Generate,
    890  1.1  mrg 	 recognize and verify constraints of the copy.  Also fail if this
    891  1.1  mrg 	 generated more than one insn.
    892  1.1  mrg 
    893  1.1  mrg          This generates garbage since we throw away the insn when we're
    894  1.1  mrg 	 done, only to recreate it later if this test was successful.
    895  1.1  mrg 
    896  1.1  mrg 	 Make sure to get the mode from the extension (cand->insn).  This
    897  1.1  mrg 	 is different than in the code to emit the copy as we have not
    898  1.1  mrg 	 modified the defining insn yet.  */
    899  1.1  mrg       start_sequence ();
    900  1.1  mrg       rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (set)),
    901  1.1  mrg                                  REGNO (get_extended_src_reg (SET_SRC (set))));
    902  1.1  mrg       rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (set)),
    903  1.1  mrg                                  REGNO (SET_DEST (set)));
    904  1.1  mrg       emit_move_insn (new_dst, new_src);
    905  1.1  mrg 
    906  1.1  mrg       rtx_insn *insn = get_insns ();
    907  1.1  mrg       end_sequence ();
    908  1.1  mrg       if (NEXT_INSN (insn))
    909  1.1  mrg 	return false;
    910  1.1  mrg       if (recog_memoized (insn) == -1)
    911  1.1  mrg 	return false;
    912  1.1  mrg       extract_insn (insn);
    913  1.1  mrg       if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
    914  1.1  mrg 	return false;
    915  1.1  mrg 
    916  1.1  mrg       while (REG_P (SET_SRC (*dest_sub_rtx))
    917  1.1  mrg 	     && (REGNO (SET_SRC (*dest_sub_rtx)) == REGNO (SET_DEST (set))))
    918  1.1  mrg 	{
    919  1.1  mrg 	  /* Considering transformation of
    920  1.1  mrg 	     (set (reg2) (expression))
    921  1.1  mrg 	     ...
    922  1.1  mrg 	     (set (reg1) (reg2))
    923  1.1  mrg 	     ...
    924  1.1  mrg 	     (set (reg2) (any_extend (reg1)))
    925  1.1  mrg 
    926  1.1  mrg 	     into
    927  1.1  mrg 
    928  1.1  mrg 	     (set (reg2) (any_extend (expression)))
    929  1.1  mrg 	     (set (reg1) (reg2))
    930  1.1  mrg 	     ...  */
    931  1.1  mrg 	  struct df_link *defs
    932  1.1  mrg 	    = get_defs (def_insn, SET_SRC (*dest_sub_rtx), NULL);
    933  1.1  mrg 	  if (defs == NULL || defs->next)
    934  1.1  mrg 	    break;
    935  1.1  mrg 
    936  1.1  mrg 	  /* There is only one reaching def.  */
    937  1.1  mrg 	  rtx_insn *def_insn2 = DF_REF_INSN (defs->ref);
    938  1.1  mrg 
    939  1.1  mrg 	  /* The defining statement must not have been modified either.  */
    940  1.1  mrg 	  if (state->modified[INSN_UID (def_insn2)].kind != EXT_MODIFIED_NONE)
    941  1.1  mrg 	    break;
    942  1.1  mrg 
    943  1.1  mrg 	  /* The def_insn2 and candidate insn must be in the same
    944  1.1  mrg 	     block and def_insn follows def_insn2.  */
    945  1.1  mrg 	  if (bb != BLOCK_FOR_INSN (def_insn2)
    946  1.1  mrg 	      || DF_INSN_LUID (def_insn2) > DF_INSN_LUID (def_insn))
    947  1.1  mrg 	    break;
    948  1.1  mrg 
    949  1.1  mrg 	  rtx *dest_sub_rtx2 = get_sub_rtx (def_insn2);
    950  1.1  mrg 	  if (dest_sub_rtx2 == NULL)
    951  1.1  mrg 	    break;
    952  1.1  mrg 
    953  1.1  mrg 	  /* On RISC machines we must make sure that changing the mode of
    954  1.1  mrg 	     SRC_REG as destination register will not affect its reaching
    955  1.1  mrg 	     uses, which may read its value in a larger mode because DEF_INSN
    956  1.1  mrg 	     implicitly sets it in word mode.  */
    957  1.1  mrg 	  if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
    958  1.1  mrg 	    {
    959  1.1  mrg 	      struct df_link *uses = get_uses (def_insn2, SET_DEST (set));
    960  1.1  mrg 	      if (!uses)
    961  1.1  mrg 		break;
    962  1.1  mrg 
    963  1.1  mrg 	      df_link *use;
    964  1.1  mrg 	      rtx dest2 = SET_DEST (*dest_sub_rtx2);
    965  1.1  mrg 	      for (use = uses; use; use = use->next)
    966  1.1  mrg 		if (paradoxical_subreg_p (GET_MODE (*DF_REF_LOC (use->ref)),
    967  1.1  mrg 					  GET_MODE (dest2))
    968  1.1  mrg 		    && !DEBUG_INSN_P (DF_REF_INSN (use->ref)))
    969  1.1  mrg 		  break;
    970  1.1  mrg 	      if (use)
    971  1.1  mrg 		break;
    972  1.1  mrg 	    }
    973  1.1  mrg 
    974  1.1  mrg 	  /* The destination register of the extension insn must not be
    975  1.1  mrg 	     used or set between the def_insn2 and def_insn exclusive.
    976  1.1  mrg 	     Likewise for the other reg, i.e. check both reg1 and reg2
    977  1.1  mrg 	     in the above comment.  */
    978  1.1  mrg 	  if (reg_used_between_p (SET_DEST (set), def_insn2, def_insn)
    979  1.1  mrg 	      || reg_set_between_p (SET_DEST (set), def_insn2, def_insn)
    980  1.1  mrg 	      || reg_used_between_p (src_reg, def_insn2, def_insn)
    981  1.1  mrg 	      || reg_set_between_p (src_reg, def_insn2, def_insn))
    982  1.1  mrg 	    break;
    983  1.1  mrg 
    984  1.1  mrg 	  state->defs_list[0] = def_insn2;
    985  1.1  mrg 	  break;
    986  1.1  mrg 	}
    987  1.1  mrg     }
    988  1.1  mrg 
    989  1.1  mrg   /* If cand->insn has been already modified, update cand->mode to a wider
    990  1.1  mrg      mode if possible, or punt.  */
    991  1.1  mrg   if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
    992  1.1  mrg     {
    993  1.1  mrg       machine_mode mode;
    994  1.1  mrg 
    995  1.1  mrg       if (state->modified[INSN_UID (cand->insn)].kind
    996  1.1  mrg 	  != (cand->code == ZERO_EXTEND
    997  1.1  mrg 	      ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)
    998  1.1  mrg 	  || state->modified[INSN_UID (cand->insn)].mode != cand->mode
    999  1.1  mrg 	  || (set == NULL_RTX))
   1000  1.1  mrg 	return false;
   1001  1.1  mrg       mode = GET_MODE (SET_DEST (set));
   1002  1.1  mrg       gcc_assert (GET_MODE_UNIT_SIZE (mode)
   1003  1.1  mrg 		  >= GET_MODE_UNIT_SIZE (cand->mode));
   1004  1.1  mrg       cand->mode = mode;
   1005  1.1  mrg     }
   1006  1.1  mrg 
   1007  1.1  mrg   merge_successful = true;
   1008  1.1  mrg 
   1009  1.1  mrg   /* Go through the defs vector and try to merge all the definitions
   1010  1.1  mrg      in this vector.  */
   1011  1.1  mrg   state->modified_list.truncate (0);
   1012  1.1  mrg   FOR_EACH_VEC_ELT (state->defs_list, defs_ix, def_insn)
   1013  1.1  mrg     {
   1014  1.1  mrg       if (merge_def_and_ext (cand, def_insn, state))
   1015  1.1  mrg 	state->modified_list.safe_push (def_insn);
   1016  1.1  mrg       else
   1017  1.1  mrg         {
   1018  1.1  mrg           merge_successful = false;
   1019  1.1  mrg           break;
   1020  1.1  mrg         }
   1021  1.1  mrg     }
   1022  1.1  mrg 
   1023  1.1  mrg   /* Now go through the conditional copies vector and try to merge all
   1024  1.1  mrg      the copies in this vector.  */
   1025  1.1  mrg   if (merge_successful)
   1026  1.1  mrg     {
   1027  1.1  mrg       FOR_EACH_VEC_ELT (state->copies_list, i, def_insn)
   1028  1.1  mrg         {
   1029  1.1  mrg           if (transform_ifelse (cand, def_insn))
   1030  1.1  mrg 	    state->modified_list.safe_push (def_insn);
   1031  1.1  mrg           else
   1032  1.1  mrg             {
   1033  1.1  mrg               merge_successful = false;
   1034  1.1  mrg               break;
   1035  1.1  mrg             }
   1036  1.1  mrg         }
   1037  1.1  mrg     }
   1038  1.1  mrg 
   1039  1.1  mrg   if (merge_successful)
   1040  1.1  mrg     {
   1041  1.1  mrg       /* Commit the changes here if possible
   1042  1.1  mrg 	 FIXME: It's an all-or-nothing scenario.  Even if only one definition
   1043  1.1  mrg 	 cannot be merged, we entirely give up.  In the future, we should allow
   1044  1.1  mrg 	 extensions to be partially eliminated along those paths where the
   1045  1.1  mrg 	 definitions could be merged.  */
   1046  1.1  mrg       if (apply_change_group ())
   1047  1.1  mrg         {
   1048  1.1  mrg           if (dump_file)
   1049  1.1  mrg             fprintf (dump_file, "All merges were successful.\n");
   1050  1.1  mrg 
   1051  1.1  mrg 	  FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
   1052  1.1  mrg 	    {
   1053  1.1  mrg 	      ext_modified *modified = &state->modified[INSN_UID (def_insn)];
   1054  1.1  mrg 	      if (modified->kind == EXT_MODIFIED_NONE)
   1055  1.1  mrg 		modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT
   1056  1.1  mrg 						            : EXT_MODIFIED_SEXT);
   1057  1.1  mrg 
   1058  1.1  mrg 	      if (copy_needed)
   1059  1.1  mrg 		modified->do_not_reextend = 1;
   1060  1.1  mrg 	    }
   1061  1.1  mrg           return true;
   1062  1.1  mrg         }
   1063  1.1  mrg       else
   1064  1.1  mrg         {
   1065  1.1  mrg           /* Changes need not be cancelled explicitly as apply_change_group
   1066  1.1  mrg              does it.  Print list of definitions in the dump_file for debug
   1067  1.1  mrg              purposes.  This extension cannot be deleted.  */
   1068  1.1  mrg           if (dump_file)
   1069  1.1  mrg             {
   1070  1.1  mrg 	      fprintf (dump_file,
   1071  1.1  mrg 		       "Merge cancelled, non-mergeable definitions:\n");
   1072  1.1  mrg 	      FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
   1073  1.1  mrg 	        print_rtl_single (dump_file, def_insn);
   1074  1.1  mrg             }
   1075  1.1  mrg         }
   1076  1.1  mrg     }
   1077  1.1  mrg   else
   1078  1.1  mrg     {
   1079  1.1  mrg       /* Cancel any changes that have been made so far.  */
   1080  1.1  mrg       cancel_changes (0);
   1081  1.1  mrg     }
   1082  1.1  mrg 
   1083  1.1  mrg   return false;
   1084  1.1  mrg }
   1085  1.1  mrg 
   1086  1.1  mrg /* Add an extension pattern that could be eliminated.  */
   1087  1.1  mrg 
   1088  1.1  mrg static void
   1089  1.1  mrg add_removable_extension (const_rtx expr, rtx_insn *insn,
   1090  1.1  mrg 			 vec<ext_cand> *insn_list,
   1091  1.1  mrg 			 unsigned *def_map,
   1092  1.1  mrg 			 bitmap init_regs)
   1093  1.1  mrg {
   1094  1.1  mrg   enum rtx_code code;
   1095  1.1  mrg   machine_mode mode;
   1096  1.1  mrg   unsigned int idx;
   1097  1.1  mrg   rtx src, dest;
   1098  1.1  mrg 
   1099  1.1  mrg   /* We are looking for SET (REG N) (ANY_EXTEND (REG N)).  */
   1100  1.1  mrg   if (GET_CODE (expr) != SET)
   1101  1.1  mrg     return;
   1102  1.1  mrg 
   1103  1.1  mrg   src = SET_SRC (expr);
   1104  1.1  mrg   code = GET_CODE (src);
   1105  1.1  mrg   dest = SET_DEST (expr);
   1106  1.1  mrg   mode = GET_MODE (dest);
   1107  1.1  mrg 
   1108  1.1  mrg   if (REG_P (dest)
   1109  1.1  mrg       && (code == SIGN_EXTEND || code == ZERO_EXTEND)
   1110  1.1  mrg       && REG_P (XEXP (src, 0)))
   1111  1.1  mrg     {
   1112  1.1  mrg       rtx reg = XEXP (src, 0);
   1113  1.1  mrg       struct df_link *defs, *def;
   1114  1.1  mrg       ext_cand *cand;
   1115  1.1  mrg 
   1116  1.1  mrg       /* Zero-extension of an undefined value is partly defined (it's
   1117  1.1  mrg 	 completely undefined for sign-extension, though).  So if there exists
   1118  1.1  mrg 	 a path from the entry to this zero-extension that leaves this register
   1119  1.1  mrg 	 uninitialized, removing the extension could change the behavior of
   1120  1.1  mrg 	 correct programs.  So first, check it is not the case.  */
   1121  1.1  mrg       if (code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg)))
   1122  1.1  mrg 	{
   1123  1.1  mrg 	  if (dump_file)
   1124  1.1  mrg 	    {
   1125  1.1  mrg 	      fprintf (dump_file, "Cannot eliminate extension:\n");
   1126  1.1  mrg 	      print_rtl_single (dump_file, insn);
   1127  1.1  mrg 	      fprintf (dump_file, " because it can operate on uninitialized"
   1128  1.1  mrg 			          " data\n");
   1129  1.1  mrg 	    }
   1130  1.1  mrg 	  return;
   1131  1.1  mrg 	}
   1132  1.1  mrg 
   1133  1.1  mrg       /* Second, make sure we can get all the reaching definitions.  */
   1134  1.1  mrg       defs = get_defs (insn, reg, NULL);
   1135  1.1  mrg       if (!defs)
   1136  1.1  mrg 	{
   1137  1.1  mrg 	  if (dump_file)
   1138  1.1  mrg 	    {
   1139  1.1  mrg 	      fprintf (dump_file, "Cannot eliminate extension:\n");
   1140  1.1  mrg 	      print_rtl_single (dump_file, insn);
   1141  1.1  mrg 	      fprintf (dump_file, " because of missing definition(s)\n");
   1142  1.1  mrg 	    }
   1143  1.1  mrg 	  return;
   1144  1.1  mrg 	}
   1145  1.1  mrg 
   1146  1.1  mrg       /* Third, make sure the reaching definitions don't feed another and
   1147  1.1  mrg 	 different extension.  FIXME: this obviously can be improved.  */
   1148  1.1  mrg       for (def = defs; def; def = def->next)
   1149  1.1  mrg 	if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))])
   1150  1.1  mrg 	    && idx != -1U
   1151  1.1  mrg 	    && (cand = &(*insn_list)[idx - 1])
   1152  1.1  mrg 	    && cand->code != code)
   1153  1.1  mrg 	  {
   1154  1.1  mrg 	    if (dump_file)
   1155  1.1  mrg 	      {
   1156  1.1  mrg 	        fprintf (dump_file, "Cannot eliminate extension:\n");
   1157  1.1  mrg 		print_rtl_single (dump_file, insn);
   1158  1.1  mrg 	        fprintf (dump_file, " because of other extension\n");
   1159  1.1  mrg 	      }
   1160  1.1  mrg 	    return;
   1161  1.1  mrg 	  }
   1162  1.1  mrg 	/* For vector mode extensions, ensure that all uses of the
   1163  1.1  mrg 	   XEXP (src, 0) register are in insn or debug insns, as unlike
   1164  1.1  mrg 	   integral extensions lowpart subreg of the sign/zero extended
   1165  1.1  mrg 	   register are not equal to the original register, so we have
   1166  1.1  mrg 	   to change all uses or none and the current code isn't able
   1167  1.1  mrg 	   to change them all at once in one transaction.  */
   1168  1.1  mrg 	else if (VECTOR_MODE_P (GET_MODE (XEXP (src, 0))))
   1169  1.1  mrg 	  {
   1170  1.1  mrg 	    struct df_link *ref_chain, *ref_link;
   1171  1.1  mrg 
   1172  1.1  mrg 	    ref_chain = DF_REF_CHAIN (def->ref);
   1173  1.1  mrg 	    for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
   1174  1.1  mrg 	      {
   1175  1.1  mrg 		if (ref_link->ref == NULL
   1176  1.1  mrg 		    || DF_REF_INSN_INFO (ref_link->ref) == NULL)
   1177  1.1  mrg 		  {
   1178  1.1  mrg 		    idx = -1U;
   1179  1.1  mrg 		    break;
   1180  1.1  mrg 		  }
   1181  1.1  mrg 		rtx_insn *use_insn = DF_REF_INSN (ref_link->ref);
   1182  1.1  mrg 		if (use_insn != insn && !DEBUG_INSN_P (use_insn))
   1183  1.1  mrg 		  {
   1184  1.1  mrg 		    idx = -1U;
   1185  1.1  mrg 		    break;
   1186  1.1  mrg 		  }
   1187  1.1  mrg 	      }
   1188  1.1  mrg 
   1189  1.1  mrg 	    if (idx == -1U)
   1190  1.1  mrg 	      {
   1191  1.1  mrg 		def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
   1192  1.1  mrg 		if (dump_file)
   1193  1.1  mrg 		  {
   1194  1.1  mrg 		    fprintf (dump_file, "Cannot eliminate extension:\n");
   1195  1.1  mrg 		    print_rtl_single (dump_file, insn);
   1196  1.1  mrg 		    fprintf (dump_file,
   1197  1.1  mrg 			     " because some vector uses aren't extension\n");
   1198  1.1  mrg 		  }
   1199  1.1  mrg 		return;
   1200  1.1  mrg 	      }
   1201  1.1  mrg 	  }
   1202  1.1  mrg 
   1203  1.1  mrg       /* Fourth, if the extended version occupies more registers than the
   1204  1.1  mrg 	 original and the source of the extension is the same hard register
   1205  1.1  mrg 	 as the destination of the extension, then we cannot eliminate
   1206  1.1  mrg 	 the extension without deep analysis, so just punt.
   1207  1.1  mrg 
   1208  1.1  mrg 	 We allow this when the registers are different because the
   1209  1.1  mrg 	 code in combine_reaching_defs will handle that case correctly.  */
   1210  1.1  mrg       if (hard_regno_nregs (REGNO (dest), mode) != REG_NREGS (reg)
   1211  1.1  mrg 	  && reg_overlap_mentioned_p (dest, reg))
   1212  1.1  mrg 	return;
   1213  1.1  mrg 
   1214  1.1  mrg       /* Then add the candidate to the list and insert the reaching definitions
   1215  1.1  mrg          into the definition map.  */
   1216  1.1  mrg       ext_cand e = {expr, code, mode, insn};
   1217  1.1  mrg       insn_list->safe_push (e);
   1218  1.1  mrg       idx = insn_list->length ();
   1219  1.1  mrg 
   1220  1.1  mrg       for (def = defs; def; def = def->next)
   1221  1.1  mrg 	def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
   1222  1.1  mrg     }
   1223  1.1  mrg }
   1224  1.1  mrg 
   1225  1.1  mrg /* Traverse the instruction stream looking for extensions and return the
   1226  1.1  mrg    list of candidates.  */
   1227  1.1  mrg 
   1228  1.1  mrg static vec<ext_cand>
   1229  1.1  mrg find_removable_extensions (void)
   1230  1.1  mrg {
   1231  1.1  mrg   vec<ext_cand> insn_list = vNULL;
   1232  1.1  mrg   basic_block bb;
   1233  1.1  mrg   rtx_insn *insn;
   1234  1.1  mrg   rtx set;
   1235  1.1  mrg   unsigned *def_map = XCNEWVEC (unsigned, max_insn_uid);
   1236  1.1  mrg   bitmap_head init, kill, gen, tmp;
   1237  1.1  mrg 
   1238  1.1  mrg   bitmap_initialize (&init, NULL);
   1239  1.1  mrg   bitmap_initialize (&kill, NULL);
   1240  1.1  mrg   bitmap_initialize (&gen, NULL);
   1241  1.1  mrg   bitmap_initialize (&tmp, NULL);
   1242  1.1  mrg 
   1243  1.1  mrg   FOR_EACH_BB_FN (bb, cfun)
   1244  1.1  mrg     {
   1245  1.1  mrg       bitmap_copy (&init, DF_MIR_IN (bb));
   1246  1.1  mrg       bitmap_clear (&kill);
   1247  1.1  mrg       bitmap_clear (&gen);
   1248  1.1  mrg 
   1249  1.1  mrg       FOR_BB_INSNS (bb, insn)
   1250  1.1  mrg 	{
   1251  1.1  mrg 	  if (NONDEBUG_INSN_P (insn))
   1252  1.1  mrg 	    {
   1253  1.1  mrg 	      set = single_set (insn);
   1254  1.1  mrg 	      if (set != NULL_RTX)
   1255  1.1  mrg 		add_removable_extension (set, insn, &insn_list, def_map,
   1256  1.1  mrg 					 &init);
   1257  1.1  mrg 	      df_mir_simulate_one_insn (bb, insn, &kill, &gen);
   1258  1.1  mrg 	      bitmap_ior_and_compl (&tmp, &gen, &init, &kill);
   1259  1.1  mrg 	      bitmap_copy (&init, &tmp);
   1260  1.1  mrg 	    }
   1261  1.1  mrg 	}
   1262  1.1  mrg     }
   1263  1.1  mrg 
   1264  1.1  mrg   XDELETEVEC (def_map);
   1265  1.1  mrg 
   1266  1.1  mrg   return insn_list;
   1267  1.1  mrg }
   1268  1.1  mrg 
   1269  1.1  mrg /* This is the main function that checks the insn stream for redundant
   1270  1.1  mrg    extensions and tries to remove them if possible.  */
   1271  1.1  mrg 
   1272  1.1  mrg static void
   1273  1.1  mrg find_and_remove_re (void)
   1274  1.1  mrg {
   1275  1.1  mrg   ext_cand *curr_cand;
   1276  1.1  mrg   rtx_insn *curr_insn = NULL;
   1277  1.1  mrg   int num_re_opportunities = 0, num_realized = 0, i;
   1278  1.1  mrg   vec<ext_cand> reinsn_list;
   1279  1.1  mrg   auto_vec<rtx_insn *> reinsn_del_list;
   1280  1.1  mrg   auto_vec<rtx_insn *> reinsn_copy_list;
   1281  1.1  mrg 
   1282  1.1  mrg   /* Construct DU chain to get all reaching definitions of each
   1283  1.1  mrg      extension instruction.  */
   1284  1.1  mrg   df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
   1285  1.1  mrg   df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
   1286  1.1  mrg   df_mir_add_problem ();
   1287  1.1  mrg   df_analyze ();
   1288  1.1  mrg   df_set_flags (DF_DEFER_INSN_RESCAN);
   1289  1.1  mrg 
   1290  1.1  mrg   max_insn_uid = get_max_uid ();
   1291  1.1  mrg   reinsn_list = find_removable_extensions ();
   1292  1.1  mrg 
   1293  1.1  mrg   ext_state state;
   1294  1.1  mrg   if (reinsn_list.is_empty ())
   1295  1.1  mrg     state.modified = NULL;
   1296  1.1  mrg   else
   1297  1.1  mrg     state.modified = XCNEWVEC (struct ext_modified, max_insn_uid);
   1298  1.1  mrg 
   1299  1.1  mrg   FOR_EACH_VEC_ELT (reinsn_list, i, curr_cand)
   1300  1.1  mrg     {
   1301  1.1  mrg       num_re_opportunities++;
   1302  1.1  mrg 
   1303  1.1  mrg       /* Try to combine the extension with the definition.  */
   1304  1.1  mrg       if (dump_file)
   1305  1.1  mrg         {
   1306  1.1  mrg           fprintf (dump_file, "Trying to eliminate extension:\n");
   1307  1.1  mrg           print_rtl_single (dump_file, curr_cand->insn);
   1308  1.1  mrg         }
   1309  1.1  mrg 
   1310  1.1  mrg       if (combine_reaching_defs (curr_cand, curr_cand->expr, &state))
   1311  1.1  mrg         {
   1312  1.1  mrg           if (dump_file)
   1313  1.1  mrg             fprintf (dump_file, "Eliminated the extension.\n");
   1314  1.1  mrg           num_realized++;
   1315  1.1  mrg 	  /* If the RHS of the current candidate is not (extend (reg)), then
   1316  1.1  mrg 	     we do not allow the optimization of extensions where
   1317  1.1  mrg 	     the source and destination registers do not match.  Thus
   1318  1.1  mrg 	     checking REG_P here is correct.  */
   1319  1.1  mrg 	  rtx set = single_set (curr_cand->insn);
   1320  1.1  mrg 	  if (REG_P (XEXP (SET_SRC (set), 0))
   1321  1.1  mrg 	      && (REGNO (SET_DEST (set)) != REGNO (XEXP (SET_SRC (set), 0))))
   1322  1.1  mrg 	    {
   1323  1.1  mrg               reinsn_copy_list.safe_push (curr_cand->insn);
   1324  1.1  mrg               reinsn_copy_list.safe_push (state.defs_list[0]);
   1325  1.1  mrg 	    }
   1326  1.1  mrg 	  reinsn_del_list.safe_push (curr_cand->insn);
   1327  1.1  mrg 	  state.modified[INSN_UID (curr_cand->insn)].deleted = 1;
   1328  1.1  mrg         }
   1329  1.1  mrg     }
   1330  1.1  mrg 
   1331  1.1  mrg   /* The copy list contains pairs of insns which describe copies we
   1332  1.1  mrg      need to insert into the INSN stream.
   1333  1.1  mrg 
   1334  1.1  mrg      The first insn in each pair is the extension insn, from which
   1335  1.1  mrg      we derive the source and destination of the copy.
   1336  1.1  mrg 
   1337  1.1  mrg      The second insn in each pair is the memory reference where the
   1338  1.1  mrg      extension will ultimately happen.  We emit the new copy
   1339  1.1  mrg      immediately after this insn.
   1340  1.1  mrg 
   1341  1.1  mrg      It may first appear that the arguments for the copy are reversed.
   1342  1.1  mrg      Remember that the memory reference will be changed to refer to the
   1343  1.1  mrg      destination of the extention.  So we're actually emitting a copy
   1344  1.1  mrg      from the new destination to the old destination.  */
   1345  1.1  mrg   for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
   1346  1.1  mrg     {
   1347  1.1  mrg       rtx_insn *curr_insn = reinsn_copy_list[i];
   1348  1.1  mrg       rtx_insn *def_insn = reinsn_copy_list[i + 1];
   1349  1.1  mrg 
   1350  1.1  mrg       /* Use the mode of the destination of the defining insn
   1351  1.1  mrg 	 for the mode of the copy.  This is necessary if the
   1352  1.1  mrg 	 defining insn was used to eliminate a second extension
   1353  1.1  mrg 	 that was wider than the first.  */
   1354  1.1  mrg       rtx sub_rtx = *get_sub_rtx (def_insn);
   1355  1.1  mrg       rtx set = single_set (curr_insn);
   1356  1.1  mrg       rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
   1357  1.1  mrg 				 REGNO (XEXP (SET_SRC (set), 0)));
   1358  1.1  mrg       rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
   1359  1.1  mrg 				 REGNO (SET_DEST (set)));
   1360  1.1  mrg       rtx new_set = gen_rtx_SET (new_dst, new_src);
   1361  1.1  mrg       emit_insn_after (new_set, def_insn);
   1362  1.1  mrg     }
   1363  1.1  mrg 
   1364  1.1  mrg   /* Delete all useless extensions here in one sweep.  */
   1365  1.1  mrg   FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn)
   1366  1.1  mrg     delete_insn (curr_insn);
   1367  1.1  mrg 
   1368  1.1  mrg   reinsn_list.release ();
   1369  1.1  mrg   XDELETEVEC (state.modified);
   1370  1.1  mrg 
   1371  1.1  mrg   if (dump_file && num_re_opportunities > 0)
   1372  1.1  mrg     fprintf (dump_file, "Elimination opportunities = %d realized = %d\n",
   1373  1.1  mrg 	     num_re_opportunities, num_realized);
   1374  1.1  mrg }
   1375  1.1  mrg 
   1376  1.1  mrg /* Find and remove redundant extensions.  */
   1377  1.1  mrg 
   1378  1.1  mrg static unsigned int
   1379  1.1  mrg rest_of_handle_ree (void)
   1380  1.1  mrg {
   1381  1.1  mrg   find_and_remove_re ();
   1382  1.1  mrg   return 0;
   1383  1.1  mrg }
   1384  1.1  mrg 
   1385  1.1  mrg namespace {
   1386  1.1  mrg 
   1387  1.1  mrg const pass_data pass_data_ree =
   1388  1.1  mrg {
   1389  1.1  mrg   RTL_PASS, /* type */
   1390  1.1  mrg   "ree", /* name */
   1391  1.1  mrg   OPTGROUP_NONE, /* optinfo_flags */
   1392  1.1  mrg   TV_REE, /* tv_id */
   1393  1.1  mrg   0, /* properties_required */
   1394  1.1  mrg   0, /* properties_provided */
   1395  1.1  mrg   0, /* properties_destroyed */
   1396  1.1  mrg   0, /* todo_flags_start */
   1397  1.1  mrg   TODO_df_finish, /* todo_flags_finish */
   1398  1.1  mrg };
   1399  1.1  mrg 
   1400  1.1  mrg class pass_ree : public rtl_opt_pass
   1401  1.1  mrg {
   1402  1.1  mrg public:
   1403  1.1  mrg   pass_ree (gcc::context *ctxt)
   1404  1.1  mrg     : rtl_opt_pass (pass_data_ree, ctxt)
   1405  1.1  mrg   {}
   1406  1.1  mrg 
   1407  1.1  mrg   /* opt_pass methods: */
   1408  1.1  mrg   virtual bool gate (function *) { return (optimize > 0 && flag_ree); }
   1409  1.1  mrg   virtual unsigned int execute (function *) { return rest_of_handle_ree (); }
   1410  1.1  mrg 
   1411  1.1  mrg }; // class pass_ree
   1412  1.1  mrg 
   1413  1.1  mrg } // anon namespace
   1414  1.1  mrg 
   1415  1.1  mrg rtl_opt_pass *
   1416  1.1  mrg make_pass_ree (gcc::context *ctxt)
   1417  1.1  mrg {
   1418  1.1  mrg   return new pass_ree (ctxt);
   1419  1.1  mrg }
   1420