LCOV - code coverage report
Current view: top level - gcc/config/i386 - i386-expand.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 9567 11013 86.9 %
Date: 2020-03-28 11:57:23 Functions: 195 209 93.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Copyright (C) 1988-2020 Free Software Foundation, Inc.
       2                 :            : 
       3                 :            : This file is part of GCC.
       4                 :            : 
       5                 :            : GCC is free software; you can redistribute it and/or modify
       6                 :            : it under the terms of the GNU General Public License as published by
       7                 :            : the Free Software Foundation; either version 3, or (at your option)
       8                 :            : any later version.
       9                 :            : 
      10                 :            : GCC is distributed in the hope that it will be useful,
      11                 :            : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13                 :            : GNU General Public License for more details.
      14                 :            : 
      15                 :            : You should have received a copy of the GNU General Public License
      16                 :            : along with GCC; see the file COPYING3.  If not see
      17                 :            : <http://www.gnu.org/licenses/>.  */
      18                 :            : 
      19                 :            : #define IN_TARGET_CODE 1
      20                 :            : 
      21                 :            : #include "config.h"
      22                 :            : #include "system.h"
      23                 :            : #include "coretypes.h"
      24                 :            : #include "backend.h"
      25                 :            : #include "rtl.h"
      26                 :            : #include "tree.h"
      27                 :            : #include "memmodel.h"
      28                 :            : #include "gimple.h"
      29                 :            : #include "cfghooks.h"
      30                 :            : #include "cfgloop.h"
      31                 :            : #include "df.h"
      32                 :            : #include "tm_p.h"
      33                 :            : #include "stringpool.h"
      34                 :            : #include "expmed.h"
      35                 :            : #include "optabs.h"
      36                 :            : #include "regs.h"
      37                 :            : #include "emit-rtl.h"
      38                 :            : #include "recog.h"
      39                 :            : #include "cgraph.h"
      40                 :            : #include "diagnostic.h"
      41                 :            : #include "cfgbuild.h"
      42                 :            : #include "alias.h"
      43                 :            : #include "fold-const.h"
      44                 :            : #include "attribs.h"
      45                 :            : #include "calls.h"
      46                 :            : #include "stor-layout.h"
      47                 :            : #include "varasm.h"
      48                 :            : #include "output.h"
      49                 :            : #include "insn-attr.h"
      50                 :            : #include "flags.h"
      51                 :            : #include "except.h"
      52                 :            : #include "explow.h"
      53                 :            : #include "expr.h"
      54                 :            : #include "cfgrtl.h"
      55                 :            : #include "common/common-target.h"
      56                 :            : #include "langhooks.h"
      57                 :            : #include "reload.h"
      58                 :            : #include "gimplify.h"
      59                 :            : #include "dwarf2.h"
      60                 :            : #include "tm-constrs.h"
      61                 :            : #include "cselib.h"
      62                 :            : #include "sched-int.h"
      63                 :            : #include "opts.h"
      64                 :            : #include "tree-pass.h"
      65                 :            : #include "context.h"
      66                 :            : #include "pass_manager.h"
      67                 :            : #include "target-globals.h"
      68                 :            : #include "gimple-iterator.h"
      69                 :            : #include "tree-vectorizer.h"
      70                 :            : #include "shrink-wrap.h"
      71                 :            : #include "builtins.h"
      72                 :            : #include "rtl-iter.h"
      73                 :            : #include "tree-iterator.h"
      74                 :            : #include "dbgcnt.h"
      75                 :            : #include "case-cfn-macros.h"
      76                 :            : #include "dojump.h"
      77                 :            : #include "fold-const-call.h"
      78                 :            : #include "tree-vrp.h"
      79                 :            : #include "tree-ssanames.h"
      80                 :            : #include "selftest.h"
      81                 :            : #include "selftest-rtl.h"
      82                 :            : #include "print-rtl.h"
      83                 :            : #include "intl.h"
      84                 :            : #include "ifcvt.h"
      85                 :            : #include "symbol-summary.h"
      86                 :            : #include "ipa-prop.h"
      87                 :            : #include "ipa-fnsummary.h"
      88                 :            : #include "wide-int-bitmask.h"
      89                 :            : #include "tree-vector-builder.h"
      90                 :            : #include "debug.h"
      91                 :            : #include "dwarf2out.h"
      92                 :            : #include "i386-options.h"
      93                 :            : #include "i386-builtins.h"
      94                 :            : #include "i386-expand.h"
      95                 :            : 
      96                 :            : /* Split one or more double-mode RTL references into pairs of half-mode
      97                 :            :    references.  The RTL can be REG, offsettable MEM, integer constant, or
      98                 :            :    CONST_DOUBLE.  "operands" is a pointer to an array of double-mode RTLs to
      99                 :            :    split and "num" is its length.  lo_half and hi_half are output arrays
     100                 :            :    that parallel "operands".  */
     101                 :            : 
     102                 :            : void
     103                 :    1880470 : split_double_mode (machine_mode mode, rtx operands[],
     104                 :            :                    int num, rtx lo_half[], rtx hi_half[])
     105                 :            : {
     106                 :    1880470 :   machine_mode half_mode;
     107                 :    1880470 :   unsigned int byte;
     108                 :    1880470 :   rtx mem_op = NULL_RTX;
     109                 :    1880470 :   int mem_num = 0;
     110                 :            : 
     111                 :    1880470 :   switch (mode)
     112                 :            :     {
     113                 :            :     case E_TImode:
     114                 :            :       half_mode = DImode;
     115                 :            :       break;
     116                 :     448431 :     case E_DImode:
     117                 :     448431 :       half_mode = SImode;
     118                 :     448431 :       break;
     119                 :          0 :     default:
     120                 :          0 :       gcc_unreachable ();
     121                 :            :     }
     122                 :            : 
     123                 :    3760930 :   byte = GET_MODE_SIZE (half_mode);
     124                 :            : 
     125                 :    3870530 :   while (num--)
     126                 :            :     {
     127                 :    1990060 :       rtx op = operands[num];
     128                 :            : 
     129                 :            :       /* simplify_subreg refuse to split volatile memory addresses,
     130                 :            :          but we still have to handle it.  */
     131                 :    1990060 :       if (MEM_P (op))
     132                 :            :         {
     133                 :     916481 :           if (mem_op && rtx_equal_p (op, mem_op))
     134                 :            :             {
     135                 :       2397 :               lo_half[num] = lo_half[mem_num];
     136                 :       2397 :               hi_half[num] = hi_half[mem_num];
     137                 :            :             }
     138                 :            :           else
     139                 :            :             {
     140                 :     914084 :               mem_op = op;
     141                 :     914084 :               mem_num = num;
     142                 :     914084 :               lo_half[num] = adjust_address (op, half_mode, 0);
     143                 :     914084 :               hi_half[num] = adjust_address (op, half_mode, byte);
     144                 :            :             }
     145                 :            :         }
     146                 :            :       else
     147                 :            :         {
     148                 :    1073580 :           lo_half[num] = simplify_gen_subreg (half_mode, op,
     149                 :    1073580 :                                               GET_MODE (op) == VOIDmode
     150                 :    1073580 :                                               ? mode : GET_MODE (op), 0);
     151                 :    1073580 :           hi_half[num] = simplify_gen_subreg (half_mode, op,
     152                 :    1073580 :                                               GET_MODE (op) == VOIDmode
     153                 :            :                                               ? mode : GET_MODE (op), byte);
     154                 :            :         }
     155                 :            :     }
     156                 :    1880470 : }
     157                 :            : 
     158                 :            : /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
     159                 :            :    for the target.  */
     160                 :            : 
     161                 :            : void
     162                 :      36540 : ix86_expand_clear (rtx dest)
     163                 :            : {
     164                 :      36540 :   rtx tmp;
     165                 :            : 
     166                 :            :   /* We play register width games, which are only valid after reload.  */
     167                 :      36540 :   gcc_assert (reload_completed);
     168                 :            : 
     169                 :            :   /* Avoid HImode and its attendant prefix byte.  */
     170                 :      73080 :   if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
     171                 :        231 :     dest = gen_rtx_REG (SImode, REGNO (dest));
     172                 :      36540 :   tmp = gen_rtx_SET (dest, const0_rtx);
     173                 :            : 
     174                 :      36540 :   if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
     175                 :            :     {
     176                 :      36540 :       rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
     177                 :      36540 :       tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
     178                 :            :     }
     179                 :            : 
     180                 :      36540 :   emit_insn (tmp);
     181                 :      36540 : }
     182                 :            : 
     183                 :            : void
     184                 :   48026000 : ix86_expand_move (machine_mode mode, rtx operands[])
     185                 :            : {
     186                 :   48026000 :   rtx op0, op1;
     187                 :   48026000 :   rtx tmp, addend = NULL_RTX;
     188                 :   48026000 :   enum tls_model model;
     189                 :            : 
     190                 :   48026000 :   op0 = operands[0];
     191                 :   48026000 :   op1 = operands[1];
     192                 :            : 
     193                 :   48026000 :   switch (GET_CODE (op1))
     194                 :            :     {
     195                 :     249571 :     case CONST:
     196                 :     249571 :       tmp = XEXP (op1, 0);
     197                 :            : 
     198                 :     249571 :       if (GET_CODE (tmp) != PLUS
     199                 :     239312 :           || GET_CODE (XEXP (tmp, 0)) != SYMBOL_REF)
     200                 :            :         break;
     201                 :            : 
     202                 :     236856 :       op1 = XEXP (tmp, 0);
     203                 :     236856 :       addend = XEXP (tmp, 1);
     204                 :            :       /* FALLTHRU */
     205                 :            : 
     206                 :    3096810 :     case SYMBOL_REF:
     207                 :    3096810 :       model = SYMBOL_REF_TLS_MODEL (op1);
     208                 :            : 
     209                 :    3096810 :       if (model)
     210                 :       9393 :         op1 = legitimize_tls_address (op1, model, true);
     211                 :    3087420 :       else if (ix86_force_load_from_GOT_p (op1))
     212                 :            :         {
     213                 :            :           /* Load the external function address via GOT slot to avoid PLT.  */
     214                 :          7 :           op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),
     215                 :            :                                 (TARGET_64BIT
     216                 :            :                                  ? UNSPEC_GOTPCREL
     217                 :            :                                  : UNSPEC_GOT));
     218                 :          7 :           op1 = gen_rtx_CONST (Pmode, op1);
     219                 :          7 :           op1 = gen_const_mem (Pmode, op1);
     220                 :          7 :           set_mem_alias_set (op1, ix86_GOT_alias_set ());
     221                 :            :         }
     222                 :            :       else
     223                 :            :         {
     224                 :    3087410 :           tmp = legitimize_pe_coff_symbol (op1, addend != NULL_RTX);
     225                 :    3087410 :           if (tmp)
     226                 :            :             {
     227                 :          0 :               op1 = tmp;
     228                 :          0 :               if (!addend)
     229                 :            :                 break;
     230                 :            :             }
     231                 :            :           else
     232                 :            :             {
     233                 :    3087410 :               op1 = operands[1];
     234                 :    3087410 :               break;
     235                 :            :             }
     236                 :            :         }
     237                 :            : 
     238                 :       9400 :       if (addend)
     239                 :            :         {
     240                 :       2768 :           op1 = force_operand (op1, NULL_RTX);
     241                 :       2777 :           op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
     242                 :            :                                      op0, 1, OPTAB_DIRECT);
     243                 :            :         }
     244                 :            :       else
     245                 :       6632 :         op1 = force_operand (op1, op0);
     246                 :            : 
     247                 :       9400 :       if (op1 == op0)
     248                 :            :         return;
     249                 :            : 
     250                 :       4505 :       op1 = convert_to_mode (mode, op1, 1);
     251                 :            : 
     252                 :            :     default:
     253                 :            :       break;
     254                 :            :     }
     255                 :            : 
     256                 :   48021100 :   if ((flag_pic || MACHOPIC_INDIRECT)
     257                 :   48021100 :       && symbolic_operand (op1, mode))
     258                 :            :     {
     259                 :     279236 :       if (TARGET_MACHO && !TARGET_64BIT)
     260                 :            :         {
     261                 :            : #if TARGET_MACHO
     262                 :            :           /* dynamic-no-pic */
     263                 :            :           if (MACHOPIC_INDIRECT)
     264                 :            :             {
     265                 :            :               rtx temp = (op0 && REG_P (op0) && mode == Pmode)
     266                 :            :                          ? op0 : gen_reg_rtx (Pmode);
     267                 :            :               op1 = machopic_indirect_data_reference (op1, temp);
     268                 :            :               if (MACHOPIC_PURE)
     269                 :            :                 op1 = machopic_legitimize_pic_address (op1, mode,
     270                 :            :                                                        temp == op1 ? 0 : temp);
     271                 :            :             }
     272                 :            :           if (op0 != op1 && GET_CODE (op0) != MEM)
     273                 :            :             {
     274                 :            :               rtx insn = gen_rtx_SET (op0, op1);
     275                 :            :               emit_insn (insn);
     276                 :            :               return;
     277                 :            :             }
     278                 :            :           if (GET_CODE (op0) == MEM)
     279                 :            :             op1 = force_reg (Pmode, op1);
     280                 :            :           else
     281                 :            :             {
     282                 :            :               rtx temp = op0;
     283                 :            :               if (GET_CODE (temp) != REG)
     284                 :            :                 temp = gen_reg_rtx (Pmode);
     285                 :            :               temp = legitimize_pic_address (op1, temp);
     286                 :            :               if (temp == op0)
     287                 :            :             return;
     288                 :            :               op1 = temp;
     289                 :            :             }
     290                 :            :       /* dynamic-no-pic */
     291                 :            : #endif
     292                 :            :         }
     293                 :            :       else
     294                 :            :         {
     295                 :     279236 :           if (MEM_P (op0))
     296                 :      75837 :             op1 = force_reg (mode, op1);
     297                 :     203399 :           else if (!(TARGET_64BIT && x86_64_movabs_operand (op1, DImode)))
     298                 :            :             {
     299                 :     203369 :               rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
     300                 :     203369 :               op1 = legitimize_pic_address (op1, reg);
     301                 :     203369 :               if (op0 == op1)
     302                 :            :                 return;
     303                 :     203369 :               op1 = convert_to_mode (mode, op1, 1);
     304                 :            :             }
     305                 :            :         }
     306                 :            :     }
     307                 :            :   else
     308                 :            :     {
     309                 :   47741800 :       if (MEM_P (op0)
     310                 :   68144700 :           && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
     311                 :    8541160 :               || !push_operand (op0, mode))
     312                 :   55371700 :           && MEM_P (op1))
     313                 :    1206820 :         op1 = force_reg (mode, op1);
     314                 :            : 
     315                 :   47741800 :       if (push_operand (op0, mode)
     316                 :   47741800 :           && ! general_no_elim_operand (op1, mode))
     317                 :        831 :         op1 = copy_to_mode_reg (mode, op1);
     318                 :            : 
     319                 :            :       /* Force large constants in 64bit compilation into register
     320                 :            :          to get them CSEed.  */
     321                 :   47741800 :       if (can_create_pseudo_p ()
     322                 :   44818100 :           && (mode == DImode) && TARGET_64BIT
     323                 :   22001100 :           && immediate_operand (op1, mode)
     324                 :    5554250 :           && !x86_64_zext_immediate_operand (op1, VOIDmode)
     325                 :     607813 :           && !register_operand (op0, mode)
     326                 :   47877800 :           && optimize)
     327                 :     101744 :         op1 = copy_to_mode_reg (mode, op1);
     328                 :            : 
     329                 :   47741800 :       if (can_create_pseudo_p ()
     330                 :   44818100 :           && CONST_DOUBLE_P (op1))
     331                 :            :         {
     332                 :            :           /* If we are loading a floating point constant to a register,
     333                 :            :              force the value to memory now, since we'll get better code
     334                 :            :              out the back end.  */
     335                 :            : 
     336                 :     637226 :           op1 = validize_mem (force_const_mem (mode, op1));
     337                 :     637226 :           if (!register_operand (op0, mode))
     338                 :            :             {
     339                 :      86545 :               rtx temp = gen_reg_rtx (mode);
     340                 :      86545 :               emit_insn (gen_rtx_SET (temp, op1));
     341                 :      86545 :               emit_move_insn (op0, temp);
     342                 :      86545 :               return;
     343                 :            :             }
     344                 :            :         }
     345                 :            :     }
     346                 :            : 
     347                 :   47934500 :   emit_insn (gen_rtx_SET (op0, op1));
     348                 :            : }
     349                 :            : 
     350                 :            : void
     351                 :    1710140 : ix86_expand_vector_move (machine_mode mode, rtx operands[])
     352                 :            : {
     353                 :    1710140 :   rtx op0 = operands[0], op1 = operands[1];
     354                 :            :   /* Use GET_MODE_BITSIZE instead of GET_MODE_ALIGNMENT for IA MCU
     355                 :            :      psABI since the biggest alignment is 4 byte for IA MCU psABI.  */
     356                 :    1710140 :   unsigned int align = (TARGET_IAMCU
     357                 :    1710140 :                         ? GET_MODE_BITSIZE (mode)
     358                 :    1710140 :                         : GET_MODE_ALIGNMENT (mode));
     359                 :            : 
     360                 :    1710140 :   if (push_operand (op0, VOIDmode))
     361                 :        864 :     op0 = emit_move_resolve_push (mode, op0);
     362                 :            : 
     363                 :            :   /* Force constants other than zero into memory.  We do not know how
     364                 :            :      the instructions used to build constants modify the upper 64 bits
     365                 :            :      of the register, once we have that information we may be able
     366                 :            :      to handle some of them more efficiently.  */
     367                 :    1710140 :   if (can_create_pseudo_p ()
     368                 :    1655930 :       && (CONSTANT_P (op1)
     369                 :    1614990 :           || (SUBREG_P (op1)
     370                 :     112468 :               && CONSTANT_P (SUBREG_REG (op1))))
     371                 :    1751090 :       && ((register_operand (op0, mode)
     372                 :      39590 :            && !standard_sse_constant_p (op1, mode))
     373                 :            :           /* ix86_expand_vector_move_misalign() does not like constants.  */
     374                 :      40936 :           || (SSE_REG_MODE_P (mode)
     375                 :      39858 :               && MEM_P (op0)
     376                 :       1166 :               && MEM_ALIGN (op0) < align)))
     377                 :            :     {
     378                 :         16 :       if (SUBREG_P (op1))
     379                 :            :         {
     380                 :         14 :           machine_mode imode = GET_MODE (SUBREG_REG (op1));
     381                 :         14 :           rtx r = force_const_mem (imode, SUBREG_REG (op1));
     382                 :         14 :           if (r)
     383                 :         14 :             r = validize_mem (r);
     384                 :            :           else
     385                 :          0 :             r = force_reg (imode, SUBREG_REG (op1));
     386                 :         14 :           op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
     387                 :            :         }
     388                 :            :       else
     389                 :          2 :         op1 = validize_mem (force_const_mem (mode, op1));
     390                 :            :     }
     391                 :            : 
     392                 :            :   /* We need to check memory alignment for SSE mode since attribute
     393                 :            :      can make operands unaligned.  */
     394                 :    1710140 :   if (can_create_pseudo_p ()
     395                 :    1655930 :       && SSE_REG_MODE_P (mode)
     396                 :    3762720 :       && ((MEM_P (op0) && (MEM_ALIGN (op0) < align))
     397                 :    1730280 :           || (MEM_P (op1) && (MEM_ALIGN (op1) < align))))
     398                 :            :     {
     399                 :     247179 :       rtx tmp[2];
     400                 :            : 
     401                 :            :       /* ix86_expand_vector_move_misalign() does not like both
     402                 :            :          arguments in memory.  */
     403                 :     247179 :       if (!register_operand (op0, mode)
     404                 :     247179 :           && !register_operand (op1, mode))
     405                 :         50 :         op1 = force_reg (mode, op1);
     406                 :            : 
     407                 :     247179 :       tmp[0] = op0; tmp[1] = op1;
     408                 :     247179 :       ix86_expand_vector_move_misalign (mode, tmp);
     409                 :     247179 :       return;
     410                 :            :     }
     411                 :            : 
     412                 :            :   /* Make operand1 a register if it isn't already.  */
     413                 :    1462960 :   if (can_create_pseudo_p ()
     414                 :    1408750 :       && !register_operand (op0, mode)
     415                 :    1781210 :       && !register_operand (op1, mode))
     416                 :            :     {
     417                 :      55193 :       emit_move_insn (op0, force_reg (GET_MODE (op0), op1));
     418                 :      55193 :       return;
     419                 :            :     }
     420                 :            : 
     421                 :    1407770 :   emit_insn (gen_rtx_SET (op0, op1));
     422                 :            : }
     423                 :            : 
     424                 :            : /* Split 32-byte AVX unaligned load and store if needed.  */
     425                 :            : 
     426                 :            : static void
     427                 :       7523 : ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
     428                 :            : {
     429                 :       7523 :   rtx m;
     430                 :       7523 :   rtx (*extract) (rtx, rtx, rtx);
     431                 :       7523 :   machine_mode mode;
     432                 :            : 
     433                 :       7523 :   if ((MEM_P (op1) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
     434                 :       7176 :       || (MEM_P (op0) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE))
     435                 :            :     {
     436                 :        425 :       emit_insn (gen_rtx_SET (op0, op1));
     437                 :        425 :       return;
     438                 :            :     }
     439                 :            : 
     440                 :       7098 :   rtx orig_op0 = NULL_RTX;
     441                 :       7098 :   mode = GET_MODE (op0);
     442                 :       7098 :   switch (GET_MODE_CLASS (mode))
     443                 :            :     {
     444                 :       2683 :     case MODE_VECTOR_INT:
     445                 :       2683 :     case MODE_INT:
     446                 :       2683 :       if (mode != V32QImode)
     447                 :            :         {
     448                 :       2300 :           if (!MEM_P (op0))
     449                 :            :             {
     450                 :       1309 :               orig_op0 = op0;
     451                 :       1309 :               op0 = gen_reg_rtx (V32QImode);
     452                 :            :             }
     453                 :            :           else
     454                 :        991 :             op0 = gen_lowpart (V32QImode, op0);
     455                 :       2300 :           op1 = gen_lowpart (V32QImode, op1);
     456                 :       2300 :           mode = V32QImode;
     457                 :            :         }
     458                 :            :       break;
     459                 :            :     case MODE_VECTOR_FLOAT:
     460                 :            :       break;
     461                 :          0 :     default:
     462                 :          0 :       gcc_unreachable ();
     463                 :            :     }
     464                 :            : 
     465                 :       7098 :   switch (mode)
     466                 :            :     {
     467                 :          0 :     default:
     468                 :          0 :       gcc_unreachable ();
     469                 :            :     case E_V32QImode:
     470                 :            :       extract = gen_avx_vextractf128v32qi;
     471                 :            :       mode = V16QImode;
     472                 :            :       break;
     473                 :       2147 :     case E_V8SFmode:
     474                 :       2147 :       extract = gen_avx_vextractf128v8sf;
     475                 :       2147 :       mode = V4SFmode;
     476                 :       2147 :       break;
     477                 :       2268 :     case E_V4DFmode:
     478                 :       2268 :       extract = gen_avx_vextractf128v4df;
     479                 :       2268 :       mode = V2DFmode;
     480                 :       2268 :       break;
     481                 :            :     }
     482                 :            : 
     483                 :       7098 :   if (MEM_P (op1))
     484                 :            :     {
     485                 :       5080 :       rtx r = gen_reg_rtx (mode);
     486                 :       5080 :       m = adjust_address (op1, mode, 0);
     487                 :       5080 :       emit_move_insn (r, m);
     488                 :       5080 :       m = adjust_address (op1, mode, 16);
     489                 :       5080 :       r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
     490                 :       5080 :       emit_move_insn (op0, r);
     491                 :            :     }
     492                 :       2018 :   else if (MEM_P (op0))
     493                 :            :     {
     494                 :       2018 :       m = adjust_address (op0, mode, 0);
     495                 :       2018 :       emit_insn (extract (m, op1, const0_rtx));
     496                 :       2018 :       m = adjust_address (op0, mode, 16);
     497                 :       2018 :       emit_insn (extract (m, copy_rtx (op1), const1_rtx));
     498                 :            :     }
     499                 :            :   else
     500                 :          0 :     gcc_unreachable ();
     501                 :            : 
     502                 :       7098 :   if (orig_op0)
     503                 :       1309 :     emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
     504                 :            : }
     505                 :            : 
     506                 :            : /* Implement the movmisalign patterns for SSE.  Non-SSE modes go
     507                 :            :    straight to ix86_expand_vector_move.  */
     508                 :            : /* Code generation for scalar reg-reg moves of single and double precision data:
     509                 :            :      if (x86_sse_partial_reg_dependency == true | x86_sse_split_regs == true)
     510                 :            :        movaps reg, reg
     511                 :            :      else
     512                 :            :        movss reg, reg
     513                 :            :      if (x86_sse_partial_reg_dependency == true)
     514                 :            :        movapd reg, reg
     515                 :            :      else
     516                 :            :        movsd reg, reg
     517                 :            : 
     518                 :            :    Code generation for scalar loads of double precision data:
     519                 :            :      if (x86_sse_split_regs == true)
     520                 :            :        movlpd mem, reg      (gas syntax)
     521                 :            :      else
     522                 :            :        movsd mem, reg
     523                 :            : 
     524                 :            :    Code generation for unaligned packed loads of single precision data
     525                 :            :    (x86_sse_unaligned_move_optimal overrides x86_sse_partial_reg_dependency):
     526                 :            :      if (x86_sse_unaligned_move_optimal)
     527                 :            :        movups mem, reg
     528                 :            : 
     529                 :            :      if (x86_sse_partial_reg_dependency == true)
     530                 :            :        {
     531                 :            :          xorps  reg, reg
     532                 :            :          movlps mem, reg
     533                 :            :          movhps mem+8, reg
     534                 :            :        }
     535                 :            :      else
     536                 :            :        {
     537                 :            :          movlps mem, reg
     538                 :            :          movhps mem+8, reg
     539                 :            :        }
     540                 :            : 
     541                 :            :    Code generation for unaligned packed loads of double precision data
     542                 :            :    (x86_sse_unaligned_move_optimal overrides x86_sse_split_regs):
     543                 :            :      if (x86_sse_unaligned_move_optimal)
     544                 :            :        movupd mem, reg
     545                 :            : 
     546                 :            :      if (x86_sse_split_regs == true)
     547                 :            :        {
     548                 :            :          movlpd mem, reg
     549                 :            :          movhpd mem+8, reg
     550                 :            :        }
     551                 :            :      else
     552                 :            :        {
     553                 :            :          movsd  mem, reg
     554                 :            :          movhpd mem+8, reg
     555                 :            :        }
     556                 :            :  */
     557                 :            : 
     558                 :            : void
     559                 :     300611 : ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
     560                 :            : {
     561                 :     300611 :   rtx op0, op1, m;
     562                 :            : 
     563                 :     300611 :   op0 = operands[0];
     564                 :     300611 :   op1 = operands[1];
     565                 :            : 
     566                 :            :   /* Use unaligned load/store for AVX512 or when optimizing for size.  */
     567                 :     601222 :   if (GET_MODE_SIZE (mode) == 64 || optimize_insn_for_size_p ())
     568                 :            :     {
     569                 :       4273 :       emit_insn (gen_rtx_SET (op0, op1));
     570                 :       4273 :       return;
     571                 :            :     }
     572                 :            : 
     573                 :     296338 :   if (TARGET_AVX)
     574                 :            :     {
     575                 :      64824 :       if (GET_MODE_SIZE (mode) == 32)
     576                 :       7523 :         ix86_avx256_split_vector_move_misalign (op0, op1);
     577                 :            :       else
     578                 :            :         /* Always use 128-bit mov<mode>_internal pattern for AVX.  */
     579                 :      24889 :         emit_insn (gen_rtx_SET (op0, op1));
     580                 :      32412 :       return;
     581                 :            :     }
     582                 :            : 
     583                 :     263926 :   if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
     584                 :         20 :       || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
     585                 :            :     {
     586                 :     263906 :       emit_insn (gen_rtx_SET (op0, op1));
     587                 :     263906 :       return;
     588                 :            :     }
     589                 :            : 
     590                 :            :   /* ??? If we have typed data, then it would appear that using
     591                 :            :      movdqu is the only way to get unaligned data loaded with
     592                 :            :      integer type.  */
     593                 :         20 :   if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
     594                 :            :     {
     595                 :          8 :       emit_insn (gen_rtx_SET (op0, op1));
     596                 :          8 :       return;
     597                 :            :     }
     598                 :            : 
     599                 :         12 :   if (MEM_P (op1))
     600                 :            :     {
     601                 :          4 :       if (TARGET_SSE2 && mode == V2DFmode)
     602                 :            :         {
     603                 :          2 :           rtx zero;
     604                 :            : 
     605                 :            :           /* When SSE registers are split into halves, we can avoid
     606                 :            :              writing to the top half twice.  */
     607                 :          2 :           if (TARGET_SSE_SPLIT_REGS)
     608                 :            :             {
     609                 :          2 :               emit_clobber (op0);
     610                 :          2 :               zero = op0;
     611                 :            :             }
     612                 :            :           else
     613                 :            :             {
     614                 :            :               /* ??? Not sure about the best option for the Intel chips.
     615                 :            :                  The following would seem to satisfy; the register is
     616                 :            :                  entirely cleared, breaking the dependency chain.  We
     617                 :            :                  then store to the upper half, with a dependency depth
     618                 :            :                  of one.  A rumor has it that Intel recommends two movsd
     619                 :            :                  followed by an unpacklpd, but this is unconfirmed.  And
     620                 :            :                  given that the dependency depth of the unpacklpd would
     621                 :            :                  still be one, I'm not sure why this would be better.  */
     622                 :          0 :               zero = CONST0_RTX (V2DFmode);
     623                 :            :             }
     624                 :            : 
     625                 :          2 :           m = adjust_address (op1, DFmode, 0);
     626                 :          2 :           emit_insn (gen_sse2_loadlpd (op0, zero, m));
     627                 :          2 :           m = adjust_address (op1, DFmode, 8);
     628                 :          2 :           emit_insn (gen_sse2_loadhpd (op0, op0, m));
     629                 :            :         }
     630                 :            :       else
     631                 :            :         {
     632                 :          2 :           rtx t;
     633                 :            : 
     634                 :          2 :           if (mode != V4SFmode)
     635                 :          0 :             t = gen_reg_rtx (V4SFmode);
     636                 :            :           else
     637                 :            :             t = op0;
     638                 :            :             
     639                 :          2 :           if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
     640                 :          0 :             emit_move_insn (t, CONST0_RTX (V4SFmode));
     641                 :            :           else
     642                 :          2 :             emit_clobber (t);
     643                 :            : 
     644                 :          2 :           m = adjust_address (op1, V2SFmode, 0);
     645                 :          2 :           emit_insn (gen_sse_loadlps (t, t, m));
     646                 :          2 :           m = adjust_address (op1, V2SFmode, 8);
     647                 :          2 :           emit_insn (gen_sse_loadhps (t, t, m));
     648                 :          2 :           if (mode != V4SFmode)
     649                 :          0 :             emit_move_insn (op0, gen_lowpart (mode, t));
     650                 :            :         }
     651                 :            :     }
     652                 :          8 :   else if (MEM_P (op0))
     653                 :            :     {
     654                 :          8 :       if (TARGET_SSE2 && mode == V2DFmode)
     655                 :            :         {
     656                 :          2 :           m = adjust_address (op0, DFmode, 0);
     657                 :          2 :           emit_insn (gen_sse2_storelpd (m, op1));
     658                 :          2 :           m = adjust_address (op0, DFmode, 8);
     659                 :          2 :           emit_insn (gen_sse2_storehpd (m, op1));
     660                 :            :         }
     661                 :            :       else
     662                 :            :         {
     663                 :          6 :           if (mode != V4SFmode)
     664                 :          0 :             op1 = gen_lowpart (V4SFmode, op1);
     665                 :            : 
     666                 :          6 :           m = adjust_address (op0, V2SFmode, 0);
     667                 :          6 :           emit_insn (gen_sse_storelps (m, op1));
     668                 :          6 :           m = adjust_address (op0, V2SFmode, 8);
     669                 :          6 :           emit_insn (gen_sse_storehps (m, copy_rtx (op1)));
     670                 :            :         }
     671                 :            :     }
     672                 :            :   else
     673                 :          0 :     gcc_unreachable ();
     674                 :            : }
     675                 :            : 
     676                 :            : /* Move bits 64:95 to bits 32:63.  */
     677                 :            : 
     678                 :            : void
     679                 :        223 : ix86_move_vector_high_sse_to_mmx (rtx op)
     680                 :            : {
     681                 :        223 :   rtx mask = gen_rtx_PARALLEL (VOIDmode,
     682                 :            :                                gen_rtvec (4, GEN_INT (0), GEN_INT (2),
     683                 :            :                                           GEN_INT (0), GEN_INT (0)));
     684                 :        223 :   rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
     685                 :        223 :   op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
     686                 :        223 :   rtx insn = gen_rtx_SET (dest, op);
     687                 :        223 :   emit_insn (insn);
     688                 :        223 : }
     689                 :            : 
     690                 :            : /* Split MMX pack with signed/unsigned saturation with SSE/SSE2.  */
     691                 :            : 
     692                 :            : void
     693                 :        133 : ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
     694                 :            : {
     695                 :        133 :   rtx op0 = operands[0];
     696                 :        133 :   rtx op1 = operands[1];
     697                 :        133 :   rtx op2 = operands[2];
     698                 :            : 
     699                 :        133 :   machine_mode dmode = GET_MODE (op0);
     700                 :        133 :   machine_mode smode = GET_MODE (op1);
     701                 :        266 :   machine_mode inner_dmode = GET_MODE_INNER (dmode);
     702                 :        266 :   machine_mode inner_smode = GET_MODE_INNER (smode);
     703                 :            : 
     704                 :            :   /* Get the corresponding SSE mode for destination.  */
     705                 :        133 :   int nunits = 16 / GET_MODE_SIZE (inner_dmode);
     706                 :        133 :   machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
     707                 :        266 :                                             nunits).require ();
     708                 :        266 :   machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
     709                 :        266 :                                                  nunits / 2).require ();
     710                 :            : 
     711                 :            :   /* Get the corresponding SSE mode for source.  */
     712                 :        133 :   nunits = 16 / GET_MODE_SIZE (inner_smode);
     713                 :        133 :   machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
     714                 :        266 :                                             nunits).require ();
     715                 :            : 
     716                 :            :   /* Generate SSE pack with signed/unsigned saturation.  */
     717                 :        133 :   rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
     718                 :        133 :   op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
     719                 :        133 :   op2 = lowpart_subreg (sse_smode, op2, GET_MODE (op2));
     720                 :            : 
     721                 :        133 :   op1 = gen_rtx_fmt_e (code, sse_half_dmode, op1);
     722                 :        133 :   op2 = gen_rtx_fmt_e (code, sse_half_dmode, op2);
     723                 :        133 :   rtx insn = gen_rtx_SET (dest, gen_rtx_VEC_CONCAT (sse_dmode,
     724                 :            :                                                     op1, op2));
     725                 :        133 :   emit_insn (insn);
     726                 :            : 
     727                 :        133 :   ix86_move_vector_high_sse_to_mmx (op0);
     728                 :        133 : }
     729                 :            : 
     730                 :            : /* Split MMX punpcklXX/punpckhXX with SSE punpcklXX.  */
     731                 :            : 
     732                 :            : void
     733                 :        323 : ix86_split_mmx_punpck (rtx operands[], bool high_p)
     734                 :            : {
     735                 :        323 :   rtx op0 = operands[0];
     736                 :        323 :   rtx op1 = operands[1];
     737                 :        323 :   rtx op2 = operands[2];
     738                 :        323 :   machine_mode mode = GET_MODE (op0);
     739                 :        323 :   rtx mask;
     740                 :            :   /* The corresponding SSE mode.  */
     741                 :        323 :   machine_mode sse_mode, double_sse_mode;
     742                 :            : 
     743                 :        323 :   switch (mode)
     744                 :            :     {
     745                 :         99 :     case E_V8QImode:
     746                 :         99 :       sse_mode = V16QImode;
     747                 :         99 :       double_sse_mode = V32QImode;
     748                 :         99 :       mask = gen_rtx_PARALLEL (VOIDmode,
     749                 :            :                                gen_rtvec (16,
     750                 :            :                                           GEN_INT (0), GEN_INT (16),
     751                 :            :                                           GEN_INT (1), GEN_INT (17),
     752                 :            :                                           GEN_INT (2), GEN_INT (18),
     753                 :            :                                           GEN_INT (3), GEN_INT (19),
     754                 :            :                                           GEN_INT (4), GEN_INT (20),
     755                 :            :                                           GEN_INT (5), GEN_INT (21),
     756                 :            :                                           GEN_INT (6), GEN_INT (22),
     757                 :            :                                           GEN_INT (7), GEN_INT (23)));
     758                 :         99 :       break;
     759                 :            : 
     760                 :        158 :     case E_V4HImode:
     761                 :        158 :       sse_mode = V8HImode;
     762                 :        158 :       double_sse_mode = V16HImode;
     763                 :        158 :       mask = gen_rtx_PARALLEL (VOIDmode,
     764                 :            :                                gen_rtvec (8,
     765                 :            :                                           GEN_INT (0), GEN_INT (8),
     766                 :            :                                           GEN_INT (1), GEN_INT (9),
     767                 :            :                                           GEN_INT (2), GEN_INT (10),
     768                 :            :                                           GEN_INT (3), GEN_INT (11)));
     769                 :        158 :       break;
     770                 :            : 
     771                 :         66 :     case E_V2SImode:
     772                 :         66 :       sse_mode = V4SImode;
     773                 :         66 :       double_sse_mode = V8SImode;
     774                 :         66 :       mask = gen_rtx_PARALLEL (VOIDmode,
     775                 :            :                                gen_rtvec (4,
     776                 :            :                                           GEN_INT (0), GEN_INT (4),
     777                 :            :                                           GEN_INT (1), GEN_INT (5)));
     778                 :         66 :       break;
     779                 :            : 
     780                 :          0 :     default:
     781                 :          0 :       gcc_unreachable ();
     782                 :            :     }
     783                 :            : 
     784                 :            :   /* Generate SSE punpcklXX.  */
     785                 :        323 :   rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
     786                 :        323 :   op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
     787                 :        323 :   op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
     788                 :            : 
     789                 :        323 :   op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
     790                 :        323 :   op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
     791                 :        323 :   rtx insn = gen_rtx_SET (dest, op2);
     792                 :        323 :   emit_insn (insn);
     793                 :            : 
     794                 :        323 :   if (high_p)
     795                 :            :     {
     796                 :            :       /* Move bits 64:127 to bits 0:63.  */
     797                 :        145 :       mask = gen_rtx_PARALLEL (VOIDmode,
     798                 :            :                                gen_rtvec (4, GEN_INT (2), GEN_INT (3),
     799                 :            :                                           GEN_INT (0), GEN_INT (0)));
     800                 :        145 :       dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
     801                 :        145 :       op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
     802                 :        145 :       insn = gen_rtx_SET (dest, op1);
     803                 :        145 :       emit_insn (insn);
     804                 :            :     }
     805                 :        323 : }
     806                 :            : 
     807                 :            : /* Helper function of ix86_fixup_binary_operands to canonicalize
     808                 :            :    operand order.  Returns true if the operands should be swapped.  */
     809                 :            : 
     810                 :            : static bool
     811                 :   34606700 : ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode,
     812                 :            :                              rtx operands[])
     813                 :            : {
     814                 :   34606700 :   rtx dst = operands[0];
     815                 :   34606700 :   rtx src1 = operands[1];
     816                 :   34606700 :   rtx src2 = operands[2];
     817                 :            : 
     818                 :            :   /* If the operation is not commutative, we can't do anything.  */
     819                 :   34606700 :   if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
     820                 :    5123400 :       && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
     821                 :            :     return false;
     822                 :            : 
     823                 :            :   /* Highest priority is that src1 should match dst.  */
     824                 :   29483900 :   if (rtx_equal_p (dst, src1))
     825                 :            :     return false;
     826                 :   23190500 :   if (rtx_equal_p (dst, src2))
     827                 :            :     return true;
     828                 :            : 
     829                 :            :   /* Next highest priority is that immediate constants come second.  */
     830                 :   23152100 :   if (immediate_operand (src2, mode))
     831                 :            :     return false;
     832                 :    4062180 :   if (immediate_operand (src1, mode))
     833                 :            :     return true;
     834                 :            : 
     835                 :            :   /* Lowest priority is that memory references should come second.  */
     836                 :    4062180 :   if (MEM_P (src2))
     837                 :            :     return false;
     838                 :    3702160 :   if (MEM_P (src1))
     839                 :     148667 :     return true;
     840                 :            : 
     841                 :            :   return false;
     842                 :            : }
     843                 :            : 
     844                 :            : 
     845                 :            : /* Fix up OPERANDS to satisfy ix86_binary_operator_ok.  Return the
     846                 :            :    destination to use for the operation.  If different from the true
     847                 :            :    destination in operands[0], a copy operation will be required.  */
     848                 :            : 
     849                 :            : rtx
     850                 :    8037660 : ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode,
     851                 :            :                             rtx operands[])
     852                 :            : {
     853                 :    8037660 :   rtx dst = operands[0];
     854                 :    8037660 :   rtx src1 = operands[1];
     855                 :    8037660 :   rtx src2 = operands[2];
     856                 :            : 
     857                 :            :   /* Canonicalize operand order.  */
     858                 :    8037660 :   if (ix86_swap_binary_operands_p (code, mode, operands))
     859                 :            :     {
     860                 :            :       /* It is invalid to swap operands of different modes.  */
     861                 :      57818 :       gcc_assert (GET_MODE (src1) == GET_MODE (src2));
     862                 :            : 
     863                 :    8037660 :       std::swap (src1, src2);
     864                 :            :     }
     865                 :            : 
     866                 :            :   /* Both source operands cannot be in memory.  */
     867                 :    8037660 :   if (MEM_P (src1) && MEM_P (src2))
     868                 :            :     {
     869                 :            :       /* Optimization: Only read from memory once.  */
     870                 :      38118 :       if (rtx_equal_p (src1, src2))
     871                 :            :         {
     872                 :          9 :           src2 = force_reg (mode, src2);
     873                 :          9 :           src1 = src2;
     874                 :            :         }
     875                 :      38109 :       else if (rtx_equal_p (dst, src1))
     876                 :       3243 :         src2 = force_reg (mode, src2);
     877                 :            :       else
     878                 :      34866 :         src1 = force_reg (mode, src1);
     879                 :            :     }
     880                 :            : 
     881                 :            :   /* If the destination is memory, and we do not have matching source
     882                 :            :      operands, do things in registers.  */
     883                 :    8037660 :   if (MEM_P (dst) && !rtx_equal_p (dst, src1))
     884                 :     288562 :     dst = gen_reg_rtx (mode);
     885                 :            : 
     886                 :            :   /* Source 1 cannot be a constant.  */
     887                 :    8037660 :   if (CONSTANT_P (src1))
     888                 :        376 :     src1 = force_reg (mode, src1);
     889                 :            : 
     890                 :            :   /* Source 1 cannot be a non-matching memory.  */
     891                 :    8037660 :   if (MEM_P (src1) && !rtx_equal_p (dst, src1))
     892                 :     286041 :     src1 = force_reg (mode, src1);
     893                 :            : 
     894                 :            :   /* Improve address combine.  */
     895                 :    8037660 :   if (code == PLUS
     896                 :    6035180 :       && GET_MODE_CLASS (mode) == MODE_INT
     897                 :    5980460 :       && MEM_P (src2))
     898                 :      87479 :     src2 = force_reg (mode, src2);
     899                 :            : 
     900                 :    8037660 :   operands[1] = src1;
     901                 :    8037660 :   operands[2] = src2;
     902                 :    8037660 :   return dst;
     903                 :            : }
     904                 :            : 
     905                 :            : /* Similarly, but assume that the destination has already been
     906                 :            :    set up properly.  */
     907                 :            : 
     908                 :            : void
     909                 :     136142 : ix86_fixup_binary_operands_no_copy (enum rtx_code code,
     910                 :            :                                     machine_mode mode, rtx operands[])
     911                 :            : {
     912                 :     136142 :   rtx dst = ix86_fixup_binary_operands (code, mode, operands);
     913                 :     136142 :   gcc_assert (dst == operands[0]);
     914                 :     136142 : }
     915                 :            : 
     916                 :            : /* Attempt to expand a binary operator.  Make the expansion closer to the
     917                 :            :    actual machine, then just general_operand, which will allow 3 separate
     918                 :            :    memory references (one output, two input) in a single insn.  */
     919                 :            : 
     920                 :            : void
     921                 :    7901360 : ix86_expand_binary_operator (enum rtx_code code, machine_mode mode,
     922                 :            :                              rtx operands[])
     923                 :            : {
     924                 :    7901360 :   rtx src1, src2, dst, op, clob;
     925                 :            : 
     926                 :    7901360 :   dst = ix86_fixup_binary_operands (code, mode, operands);
     927                 :    7901360 :   src1 = operands[1];
     928                 :    7901360 :   src2 = operands[2];
     929                 :            : 
     930                 :            :  /* Emit the instruction.  */
     931                 :            : 
     932                 :    7901360 :   op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
     933                 :            : 
     934                 :    7901360 :   if (reload_completed
     935                 :      32558 :       && code == PLUS
     936                 :    7902990 :       && !rtx_equal_p (dst, src1))
     937                 :            :     {
     938                 :            :       /* This is going to be an LEA; avoid splitting it later.  */
     939                 :          0 :       emit_insn (op);
     940                 :            :     }
     941                 :            :   else
     942                 :            :     {
     943                 :    7901360 :       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
     944                 :    7901360 :       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
     945                 :            :     }
     946                 :            : 
     947                 :            :   /* Fix up the destination if needed.  */
     948                 :    7901360 :   if (dst != operands[0])
     949                 :     288553 :     emit_move_insn (operands[0], dst);
     950                 :    7901360 : }
     951                 :            : 
     952                 :            : /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with
     953                 :            :    the given OPERANDS.  */
     954                 :            : 
     955                 :            : void
     956                 :      16027 : ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode,
     957                 :            :                                      rtx operands[])
     958                 :            : {
     959                 :      16027 :   rtx op1 = NULL_RTX, op2 = NULL_RTX;
     960                 :      16027 :   if (SUBREG_P (operands[1]))
     961                 :            :     {
     962                 :        183 :       op1 = operands[1];
     963                 :        183 :       op2 = operands[2];
     964                 :            :     }
     965                 :      15844 :   else if (SUBREG_P (operands[2]))
     966                 :            :     {
     967                 :            :       op1 = operands[2];
     968                 :            :       op2 = operands[1];
     969                 :            :     }
     970                 :            :   /* Optimize (__m128i) d | (__m128i) e and similar code
     971                 :            :      when d and e are float vectors into float vector logical
     972                 :            :      insn.  In C/C++ without using intrinsics there is no other way
     973                 :            :      to express vector logical operation on float vectors than
     974                 :            :      to cast them temporarily to integer vectors.  */
     975                 :       1528 :   if (op1
     976                 :       1528 :       && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
     977                 :       1528 :       && (SUBREG_P (op2) || GET_CODE (op2) == CONST_VECTOR)
     978                 :        183 :       && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op1))) == MODE_VECTOR_FLOAT
     979                 :         12 :       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) == GET_MODE_SIZE (mode)
     980                 :          4 :       && SUBREG_BYTE (op1) == 0
     981                 :          4 :       && (GET_CODE (op2) == CONST_VECTOR
     982                 :          1 :           || (GET_MODE (SUBREG_REG (op1)) == GET_MODE (SUBREG_REG (op2))
     983                 :          1 :               && SUBREG_BYTE (op2) == 0))
     984                 :       1532 :       && can_create_pseudo_p ())
     985                 :            :     {
     986                 :          4 :       rtx dst;
     987                 :          4 :       switch (GET_MODE (SUBREG_REG (op1)))
     988                 :            :         {
     989                 :          4 :         case E_V4SFmode:
     990                 :          4 :         case E_V8SFmode:
     991                 :          4 :         case E_V16SFmode:
     992                 :          4 :         case E_V2DFmode:
     993                 :          4 :         case E_V4DFmode:
     994                 :          4 :         case E_V8DFmode:
     995                 :          4 :           dst = gen_reg_rtx (GET_MODE (SUBREG_REG (op1)));
     996                 :          4 :           if (GET_CODE (op2) == CONST_VECTOR)
     997                 :            :             {
     998                 :          3 :               op2 = gen_lowpart (GET_MODE (dst), op2);
     999                 :          3 :               op2 = force_reg (GET_MODE (dst), op2);
    1000                 :            :             }
    1001                 :            :           else
    1002                 :            :             {
    1003                 :          1 :               op1 = operands[1];
    1004                 :          1 :               op2 = SUBREG_REG (operands[2]);
    1005                 :          1 :               if (!vector_operand (op2, GET_MODE (dst)))
    1006                 :          0 :                 op2 = force_reg (GET_MODE (dst), op2);
    1007                 :            :             }
    1008                 :          4 :           op1 = SUBREG_REG (op1);
    1009                 :          4 :           if (!vector_operand (op1, GET_MODE (dst)))
    1010                 :          0 :             op1 = force_reg (GET_MODE (dst), op1);
    1011                 :          4 :           emit_insn (gen_rtx_SET (dst,
    1012                 :            :                                   gen_rtx_fmt_ee (code, GET_MODE (dst),
    1013                 :            :                                                   op1, op2)));
    1014                 :          4 :           emit_move_insn (operands[0], gen_lowpart (mode, dst));
    1015                 :          4 :           return;
    1016                 :            :         default:
    1017                 :            :           break;
    1018                 :            :         }
    1019                 :            :     }
    1020                 :      16023 :   if (!vector_operand (operands[1], mode))
    1021                 :          0 :     operands[1] = force_reg (mode, operands[1]);
    1022                 :      16023 :   if (!vector_operand (operands[2], mode))
    1023                 :       1277 :     operands[2] = force_reg (mode, operands[2]);
    1024                 :      16023 :   ix86_fixup_binary_operands_no_copy (code, mode, operands);
    1025                 :      16023 :   emit_insn (gen_rtx_SET (operands[0],
    1026                 :            :                           gen_rtx_fmt_ee (code, mode, operands[1],
    1027                 :            :                                           operands[2])));
    1028                 :            : }
    1029                 :            : 
    1030                 :            : /* Return TRUE or FALSE depending on whether the binary operator meets the
    1031                 :            :    appropriate constraints.  */
    1032                 :            : 
    1033                 :            : bool
    1034                 :   26856200 : ix86_binary_operator_ok (enum rtx_code code, machine_mode mode,
    1035                 :            :                          rtx operands[3])
    1036                 :            : {
    1037                 :   26856200 :   rtx dst = operands[0];
    1038                 :   26856200 :   rtx src1 = operands[1];
    1039                 :   26856200 :   rtx src2 = operands[2];
    1040                 :            : 
    1041                 :            :   /* Both source operands cannot be in memory.  */
    1042                 :   26856200 :   if (MEM_P (src1) && MEM_P (src2))
    1043                 :            :     return false;
    1044                 :            : 
    1045                 :            :   /* Canonicalize operand order for commutative operators.  */
    1046                 :   26569000 :   if (ix86_swap_binary_operands_p (code, mode, operands))
    1047                 :     129274 :     std::swap (src1, src2);
    1048                 :            : 
    1049                 :            :   /* If the destination is memory, we must have a matching source operand.  */
    1050                 :   26569000 :   if (MEM_P (dst) && !rtx_equal_p (dst, src1))
    1051                 :            :     return false;
    1052                 :            : 
    1053                 :            :   /* Source 1 cannot be a constant.  */
    1054                 :   26012200 :   if (CONSTANT_P (src1))
    1055                 :            :     return false;
    1056                 :            : 
    1057                 :            :   /* Source 1 cannot be a non-matching memory.  */
    1058                 :   26012000 :   if (MEM_P (src1) && !rtx_equal_p (dst, src1))
    1059                 :            :     /* Support "andhi/andsi/anddi" as a zero-extending move.  */
    1060                 :     885136 :     return (code == AND
    1061                 :     100508 :             && (mode == HImode
    1062                 :     100508 :                 || mode == SImode
    1063                 :      47635 :                 || (TARGET_64BIT && mode == DImode))
    1064                 :     957389 :             && satisfies_constraint_L (src2));
    1065                 :            : 
    1066                 :            :   return true;
    1067                 :            : }
    1068                 :            : 
    1069                 :            : /* Attempt to expand a unary operator.  Make the expansion closer to the
    1070                 :            :    actual machine, then just general_operand, which will allow 2 separate
    1071                 :            :    memory references (one output, one input) in a single insn.  */
    1072                 :            : 
    1073                 :            : void
    1074                 :      76343 : ix86_expand_unary_operator (enum rtx_code code, machine_mode mode,
    1075                 :            :                             rtx operands[])
    1076                 :            : {
    1077                 :      76343 :   bool matching_memory = false;
    1078                 :      76343 :   rtx src, dst, op, clob;
    1079                 :            : 
    1080                 :      76343 :   dst = operands[0];
    1081                 :      76343 :   src = operands[1];
    1082                 :            : 
    1083                 :            :   /* If the destination is memory, and we do not have matching source
    1084                 :            :      operands, do things in registers.  */
    1085                 :      76343 :   if (MEM_P (dst))
    1086                 :            :     {
    1087                 :       1252 :       if (rtx_equal_p (dst, src))
    1088                 :            :         matching_memory = true;
    1089                 :            :       else
    1090                 :       1091 :         dst = gen_reg_rtx (mode);
    1091                 :            :     }
    1092                 :            : 
    1093                 :            :   /* When source operand is memory, destination must match.  */
    1094                 :      76343 :   if (MEM_P (src) && !matching_memory)
    1095                 :       1805 :     src = force_reg (mode, src);
    1096                 :            : 
    1097                 :            :   /* Emit the instruction.  */
    1098                 :            : 
    1099                 :      76343 :   op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src));
    1100                 :            : 
    1101                 :      76343 :   if (code == NOT)
    1102                 :      46026 :     emit_insn (op);
    1103                 :            :   else
    1104                 :            :     {
    1105                 :      30317 :       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
    1106                 :      30317 :       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
    1107                 :            :     }
    1108                 :            : 
    1109                 :            :   /* Fix up the destination if needed.  */
    1110                 :      76343 :   if (dst != operands[0])
    1111                 :       1091 :     emit_move_insn (operands[0], dst);
    1112                 :      76343 : }
    1113                 :            : 
    1114                 :            : /* Predict just emitted jump instruction to be taken with probability PROB.  */
    1115                 :            : 
    1116                 :            : static void
    1117                 :       7890 : predict_jump (int prob)
    1118                 :            : {
    1119                 :       7890 :   rtx_insn *insn = get_last_insn ();
    1120                 :       7890 :   gcc_assert (JUMP_P (insn));
    1121                 :       7890 :   add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
    1122                 :       7890 : }
    1123                 :            : 
    1124                 :            : /* Split 32bit/64bit divmod with 8bit unsigned divmod if dividend and
    1125                 :            :    divisor are within the range [0-255].  */
    1126                 :            : 
    1127                 :            : void
    1128                 :         25 : ix86_split_idivmod (machine_mode mode, rtx operands[],
    1129                 :            :                     bool unsigned_p)
    1130                 :            : {
    1131                 :         25 :   rtx_code_label *end_label, *qimode_label;
    1132                 :         25 :   rtx div, mod;
    1133                 :         25 :   rtx_insn *insn;
    1134                 :         25 :   rtx scratch, tmp0, tmp1, tmp2;
    1135                 :         25 :   rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx);
    1136                 :            : 
    1137                 :         25 :   switch (mode)
    1138                 :            :     {
    1139                 :         19 :     case E_SImode:
    1140                 :         19 :       if (GET_MODE (operands[0]) == SImode)
    1141                 :            :         {
    1142                 :         15 :           if (GET_MODE (operands[1]) == SImode)
    1143                 :         13 :             gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1;
    1144                 :            :           else
    1145                 :          2 :             gen_divmod4_1
    1146                 :          2 :               = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2;
    1147                 :            :         }
    1148                 :            :       else
    1149                 :          4 :         gen_divmod4_1
    1150                 :          4 :           = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1;
    1151                 :            :       break;
    1152                 :            : 
    1153                 :          6 :     case E_DImode:
    1154                 :          6 :       gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1;
    1155                 :            :       break;
    1156                 :            : 
    1157                 :          0 :     default:
    1158                 :          0 :       gcc_unreachable ();
    1159                 :            :     }
    1160                 :            : 
    1161                 :         25 :   end_label = gen_label_rtx ();
    1162                 :         25 :   qimode_label = gen_label_rtx ();
    1163                 :            : 
    1164                 :         25 :   scratch = gen_reg_rtx (mode);
    1165                 :            : 
    1166                 :            :   /* Use 8bit unsigned divimod if dividend and divisor are within
    1167                 :            :      the range [0-255].  */
    1168                 :         25 :   emit_move_insn (scratch, operands[2]);
    1169                 :         25 :   scratch = expand_simple_binop (mode, IOR, scratch, operands[3],
    1170                 :            :                                  scratch, 1, OPTAB_DIRECT);
    1171                 :         25 :   emit_insn (gen_test_ccno_1 (mode, scratch, GEN_INT (-0x100)));
    1172                 :         25 :   tmp0 = gen_rtx_REG (CCNOmode, FLAGS_REG);
    1173                 :         25 :   tmp0 = gen_rtx_EQ (VOIDmode, tmp0, const0_rtx);
    1174                 :         25 :   tmp0 = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp0,
    1175                 :            :                                gen_rtx_LABEL_REF (VOIDmode, qimode_label),
    1176                 :            :                                pc_rtx);
    1177                 :         25 :   insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp0));
    1178                 :         25 :   predict_jump (REG_BR_PROB_BASE * 50 / 100);
    1179                 :         25 :   JUMP_LABEL (insn) = qimode_label;
    1180                 :            : 
    1181                 :            :   /* Generate original signed/unsigned divimod.  */
    1182                 :         25 :   div = gen_divmod4_1 (operands[0], operands[1],
    1183                 :            :                        operands[2], operands[3]);
    1184                 :         25 :   emit_insn (div);
    1185                 :            : 
    1186                 :            :   /* Branch to the end.  */
    1187                 :         25 :   emit_jump_insn (gen_jump (end_label));
    1188                 :         25 :   emit_barrier ();
    1189                 :            : 
    1190                 :            :   /* Generate 8bit unsigned divide.  */
    1191                 :         25 :   emit_label (qimode_label);
    1192                 :            :   /* Don't use operands[0] for result of 8bit divide since not all
    1193                 :            :      registers support QImode ZERO_EXTRACT.  */
    1194                 :         25 :   tmp0 = lowpart_subreg (HImode, scratch, mode);
    1195                 :         25 :   tmp1 = lowpart_subreg (HImode, operands[2], mode);
    1196                 :         25 :   tmp2 = lowpart_subreg (QImode, operands[3], mode);
    1197                 :         25 :   emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2));
    1198                 :            : 
    1199                 :         25 :   if (unsigned_p)
    1200                 :            :     {
    1201                 :         11 :       div = gen_rtx_UDIV (mode, operands[2], operands[3]);
    1202                 :         11 :       mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
    1203                 :            :     }
    1204                 :            :   else
    1205                 :            :     {
    1206                 :         14 :       div = gen_rtx_DIV (mode, operands[2], operands[3]);
    1207                 :         14 :       mod = gen_rtx_MOD (mode, operands[2], operands[3]);
    1208                 :            :     }
    1209                 :         25 :   if (mode == SImode)
    1210                 :            :     {
    1211                 :         19 :       if (GET_MODE (operands[0]) != SImode)
    1212                 :          4 :         div = gen_rtx_ZERO_EXTEND (DImode, div);
    1213                 :         19 :       if (GET_MODE (operands[1]) != SImode)
    1214                 :          2 :         mod = gen_rtx_ZERO_EXTEND (DImode, mod);
    1215                 :            :     }
    1216                 :            : 
    1217                 :            :   /* Extract remainder from AH.  */
    1218                 :         25 :   tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]),
    1219                 :            :                                tmp0, GEN_INT (8), GEN_INT (8));
    1220                 :         25 :   if (REG_P (operands[1]))
    1221                 :         25 :     insn = emit_move_insn (operands[1], tmp1);
    1222                 :            :   else
    1223                 :            :     {
    1224                 :            :       /* Need a new scratch register since the old one has result
    1225                 :            :          of 8bit divide.  */
    1226                 :          0 :       scratch = gen_reg_rtx (GET_MODE (operands[1]));
    1227                 :          0 :       emit_move_insn (scratch, tmp1);
    1228                 :          0 :       insn = emit_move_insn (operands[1], scratch);
    1229                 :            :     }
    1230                 :         25 :   set_unique_reg_note (insn, REG_EQUAL, mod);
    1231                 :            : 
    1232                 :            :   /* Zero extend quotient from AL.  */
    1233                 :         25 :   tmp1 = gen_lowpart (QImode, tmp0);
    1234                 :         25 :   insn = emit_insn (gen_extend_insn
    1235                 :         25 :                     (operands[0], tmp1,
    1236                 :         25 :                      GET_MODE (operands[0]), QImode, 1));
    1237                 :         25 :   set_unique_reg_note (insn, REG_EQUAL, div);
    1238                 :            : 
    1239                 :         25 :   emit_label (end_label);
    1240                 :         25 : }
    1241                 :            : 
    1242                 :            : /* Emit x86 binary operand CODE in mode MODE, where the first operand
    1243                 :            :    matches destination.  RTX includes clobber of FLAGS_REG.  */
    1244                 :            : 
    1245                 :            : void
    1246                 :       5665 : ix86_emit_binop (enum rtx_code code, machine_mode mode,
    1247                 :            :                  rtx dst, rtx src)
    1248                 :            : {
    1249                 :       5665 :   rtx op, clob;
    1250                 :            : 
    1251                 :       5665 :   op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src));
    1252                 :       5665 :   clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
    1253                 :            :   
    1254                 :       5665 :   emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
    1255                 :       5665 : }
    1256                 :            : 
    1257                 :            : /* Return true if regno1 def is nearest to the insn.  */
    1258                 :            : 
    1259                 :            : static bool
    1260                 :          4 : find_nearest_reg_def (rtx_insn *insn, int regno1, int regno2)
    1261                 :            : {
    1262                 :          4 :   rtx_insn *prev = insn;
    1263                 :          4 :   rtx_insn *start = BB_HEAD (BLOCK_FOR_INSN (insn));
    1264                 :            : 
    1265                 :          4 :   if (insn == start)
    1266                 :            :     return false;
    1267                 :          8 :   while (prev && prev != start)
    1268                 :            :     {
    1269                 :          6 :       if (!INSN_P (prev) || !NONDEBUG_INSN_P (prev))
    1270                 :            :         {
    1271                 :          0 :           prev = PREV_INSN (prev);
    1272                 :          0 :           continue;
    1273                 :            :         }
    1274                 :          6 :       if (insn_defines_reg (regno1, INVALID_REGNUM, prev))
    1275                 :            :         return true;
    1276                 :          4 :       else if (insn_defines_reg (regno2, INVALID_REGNUM, prev))
    1277                 :            :         return false;
    1278                 :          4 :       prev = PREV_INSN (prev);
    1279                 :            :     }
    1280                 :            : 
    1281                 :            :   /* None of the regs is defined in the bb.  */
    1282                 :            :   return false;
    1283                 :            : }
    1284                 :            : 
    1285                 :            : /* Split lea instructions into a sequence of instructions
    1286                 :            :    which are executed on ALU to avoid AGU stalls.
    1287                 :            :    It is assumed that it is allowed to clobber flags register
    1288                 :            :    at lea position.  */
    1289                 :            : 
    1290                 :            : void
    1291                 :       3388 : ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
    1292                 :            : {
    1293                 :       3388 :   unsigned int regno0, regno1, regno2;
    1294                 :       3388 :   struct ix86_address parts;
    1295                 :       3388 :   rtx target, tmp;
    1296                 :       3388 :   int ok, adds;
    1297                 :            : 
    1298                 :       3388 :   ok = ix86_decompose_address (operands[1], &parts);
    1299                 :       3388 :   gcc_assert (ok);
    1300                 :            : 
    1301                 :       3388 :   target = gen_lowpart (mode, operands[0]);
    1302                 :            : 
    1303                 :       3388 :   regno0 = true_regnum (target);
    1304                 :       3388 :   regno1 = INVALID_REGNUM;
    1305                 :       3388 :   regno2 = INVALID_REGNUM;
    1306                 :            : 
    1307                 :       3388 :   if (parts.base)
    1308                 :            :     {
    1309                 :       3385 :       parts.base = gen_lowpart (mode, parts.base);
    1310                 :       3385 :       regno1 = true_regnum (parts.base);
    1311                 :            :     }
    1312                 :            : 
    1313                 :       3388 :   if (parts.index)
    1314                 :            :     {
    1315                 :       3383 :       parts.index = gen_lowpart (mode, parts.index);
    1316                 :       3383 :       regno2 = true_regnum (parts.index);
    1317                 :            :     }
    1318                 :            : 
    1319                 :       3388 :   if (parts.disp)
    1320                 :        147 :     parts.disp = gen_lowpart (mode, parts.disp);
    1321                 :            : 
    1322                 :       3388 :   if (parts.scale > 1)
    1323                 :            :     {
    1324                 :            :       /* Case r1 = r1 + ...  */
    1325                 :         13 :       if (regno1 == regno0)
    1326                 :            :         {
    1327                 :            :           /* If we have a case r1 = r1 + C * r2 then we
    1328                 :            :              should use multiplication which is very
    1329                 :            :              expensive.  Assume cost model is wrong if we
    1330                 :            :              have such case here.  */
    1331                 :          0 :           gcc_assert (regno2 != regno0);
    1332                 :            : 
    1333                 :          0 :           for (adds = parts.scale; adds > 0; adds--)
    1334                 :          0 :             ix86_emit_binop (PLUS, mode, target, parts.index);
    1335                 :            :         }
    1336                 :            :       else
    1337                 :            :         {
    1338                 :            :           /* r1 = r2 + r3 * C case.  Need to move r3 into r1.  */
    1339                 :         13 :           if (regno0 != regno2)
    1340                 :          6 :             emit_insn (gen_rtx_SET (target, parts.index));
    1341                 :            : 
    1342                 :            :           /* Use shift for scaling.  */
    1343                 :         13 :           ix86_emit_binop (ASHIFT, mode, target,
    1344                 :         26 :                            GEN_INT (exact_log2 (parts.scale)));
    1345                 :            : 
    1346                 :         13 :           if (parts.base)
    1347                 :         10 :             ix86_emit_binop (PLUS, mode, target, parts.base);
    1348                 :            : 
    1349                 :         13 :           if (parts.disp && parts.disp != const0_rtx)
    1350                 :          0 :             ix86_emit_binop (PLUS, mode, target, parts.disp);
    1351                 :            :         }
    1352                 :            :     }
    1353                 :       3375 :   else if (!parts.base && !parts.index)
    1354                 :            :     {
    1355                 :          0 :       gcc_assert(parts.disp);
    1356                 :          0 :       emit_insn (gen_rtx_SET (target, parts.disp));
    1357                 :            :     }
    1358                 :            :   else
    1359                 :            :     {
    1360                 :       3375 :       if (!parts.base)
    1361                 :            :         {
    1362                 :          0 :           if (regno0 != regno2)
    1363                 :          0 :             emit_insn (gen_rtx_SET (target, parts.index));
    1364                 :            :         }
    1365                 :       3375 :       else if (!parts.index)
    1366                 :            :         {
    1367                 :          5 :           if (regno0 != regno1)
    1368                 :          0 :             emit_insn (gen_rtx_SET (target, parts.base));
    1369                 :            :         }
    1370                 :            :       else
    1371                 :            :         {
    1372                 :       3370 :           if (regno0 == regno1)
    1373                 :            :             tmp = parts.index;
    1374                 :       1329 :           else if (regno0 == regno2)
    1375                 :            :             tmp = parts.base;
    1376                 :            :           else
    1377                 :            :             {
    1378                 :          4 :               rtx tmp1;
    1379                 :            : 
    1380                 :            :               /* Find better operand for SET instruction, depending
    1381                 :            :                  on which definition is farther from the insn.  */
    1382                 :          4 :               if (find_nearest_reg_def (insn, regno1, regno2))
    1383                 :          2 :                 tmp = parts.index, tmp1 = parts.base;
    1384                 :            :               else
    1385                 :          2 :                 tmp = parts.base, tmp1 = parts.index;
    1386                 :            : 
    1387                 :          4 :               emit_insn (gen_rtx_SET (target, tmp));
    1388                 :            : 
    1389                 :          4 :               if (parts.disp && parts.disp != const0_rtx)
    1390                 :          0 :                 ix86_emit_binop (PLUS, mode, target, parts.disp);
    1391                 :            : 
    1392                 :          4 :               ix86_emit_binop (PLUS, mode, target, tmp1);
    1393                 :          4 :               return;
    1394                 :            :             }
    1395                 :            : 
    1396                 :       3366 :           ix86_emit_binop (PLUS, mode, target, tmp);
    1397                 :            :         }
    1398                 :            : 
    1399                 :       3371 :       if (parts.disp && parts.disp != const0_rtx)
    1400                 :          6 :         ix86_emit_binop (PLUS, mode, target, parts.disp);
    1401                 :            :     }
    1402                 :            : }
    1403                 :            : 
    1404                 :            : /* Post-reload splitter for converting an SF or DFmode value in an
    1405                 :            :    SSE register into an unsigned SImode.  */
    1406                 :            : 
    1407                 :            : void
    1408                 :          0 : ix86_split_convert_uns_si_sse (rtx operands[])
    1409                 :            : {
    1410                 :          0 :   machine_mode vecmode;
    1411                 :          0 :   rtx value, large, zero_or_two31, input, two31, x;
    1412                 :            : 
    1413                 :          0 :   large = operands[1];
    1414                 :          0 :   zero_or_two31 = operands[2];
    1415                 :          0 :   input = operands[3];
    1416                 :          0 :   two31 = operands[4];
    1417                 :          0 :   vecmode = GET_MODE (large);
    1418                 :          0 :   value = gen_rtx_REG (vecmode, REGNO (operands[0]));
    1419                 :            : 
    1420                 :            :   /* Load up the value into the low element.  We must ensure that the other
    1421                 :            :      elements are valid floats -- zero is the easiest such value.  */
    1422                 :          0 :   if (MEM_P (input))
    1423                 :            :     {
    1424                 :          0 :       if (vecmode == V4SFmode)
    1425                 :          0 :         emit_insn (gen_vec_setv4sf_0 (value, CONST0_RTX (V4SFmode), input));
    1426                 :            :       else
    1427                 :          0 :         emit_insn (gen_sse2_loadlpd (value, CONST0_RTX (V2DFmode), input));
    1428                 :            :     }
    1429                 :            :   else
    1430                 :            :     {
    1431                 :          0 :       input = gen_rtx_REG (vecmode, REGNO (input));
    1432                 :          0 :       emit_move_insn (value, CONST0_RTX (vecmode));
    1433                 :          0 :       if (vecmode == V4SFmode)
    1434                 :          0 :         emit_insn (gen_sse_movss (value, value, input));
    1435                 :            :       else
    1436                 :          0 :         emit_insn (gen_sse2_movsd (value, value, input));
    1437                 :            :     }
    1438                 :            : 
    1439                 :          0 :   emit_move_insn (large, two31);
    1440                 :          0 :   emit_move_insn (zero_or_two31, MEM_P (two31) ? large : two31);
    1441                 :            : 
    1442                 :          0 :   x = gen_rtx_fmt_ee (LE, vecmode, large, value);
    1443                 :          0 :   emit_insn (gen_rtx_SET (large, x));
    1444                 :            : 
    1445                 :          0 :   x = gen_rtx_AND (vecmode, zero_or_two31, large);
    1446                 :          0 :   emit_insn (gen_rtx_SET (zero_or_two31, x));
    1447                 :            : 
    1448                 :          0 :   x = gen_rtx_MINUS (vecmode, value, zero_or_two31);
    1449                 :          0 :   emit_insn (gen_rtx_SET (value, x));
    1450                 :            : 
    1451                 :          0 :   large = gen_rtx_REG (V4SImode, REGNO (large));
    1452                 :          0 :   emit_insn (gen_ashlv4si3 (large, large, GEN_INT (31)));
    1453                 :            : 
    1454                 :          0 :   x = gen_rtx_REG (V4SImode, REGNO (value));
    1455                 :          0 :   if (vecmode == V4SFmode)
    1456                 :          0 :     emit_insn (gen_fix_truncv4sfv4si2 (x, value));
    1457                 :            :   else
    1458                 :          0 :     emit_insn (gen_sse2_cvttpd2dq (x, value));
    1459                 :          0 :   value = x;
    1460                 :            : 
    1461                 :          0 :   emit_insn (gen_xorv4si3 (value, value, large));
    1462                 :          0 : }
    1463                 :            : 
    1464                 :            : static bool ix86_expand_vector_init_one_nonzero (bool mmx_ok,
    1465                 :            :                                                  machine_mode mode, rtx target,
    1466                 :            :                                                  rtx var, int one_var);
    1467                 :            : 
    1468                 :            : /* Convert an unsigned DImode value into a DFmode, using only SSE.
    1469                 :            :    Expects the 64-bit DImode to be supplied in a pair of integral
    1470                 :            :    registers.  Requires SSE2; will use SSE3 if available.  For x86_32,
    1471                 :            :    -mfpmath=sse, !optimize_size only.  */
    1472                 :            : 
    1473                 :            : void
    1474                 :          0 : ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
    1475                 :            : {
    1476                 :          0 :   REAL_VALUE_TYPE bias_lo_rvt, bias_hi_rvt;
    1477                 :          0 :   rtx int_xmm, fp_xmm;
    1478                 :          0 :   rtx biases, exponents;
    1479                 :          0 :   rtx x;
    1480                 :            : 
    1481                 :          0 :   int_xmm = gen_reg_rtx (V4SImode);
    1482                 :          0 :   if (TARGET_INTER_UNIT_MOVES_TO_VEC)
    1483                 :          0 :     emit_insn (gen_movdi_to_sse (int_xmm, input));
    1484                 :          0 :   else if (TARGET_SSE_SPLIT_REGS)
    1485                 :            :     {
    1486                 :          0 :       emit_clobber (int_xmm);
    1487                 :          0 :       emit_move_insn (gen_lowpart (DImode, int_xmm), input);
    1488                 :            :     }
    1489                 :            :   else
    1490                 :            :     {
    1491                 :          0 :       x = gen_reg_rtx (V2DImode);
    1492                 :          0 :       ix86_expand_vector_init_one_nonzero (false, V2DImode, x, input, 0);
    1493                 :          0 :       emit_move_insn (int_xmm, gen_lowpart (V4SImode, x));
    1494                 :            :     }
    1495                 :            : 
    1496                 :          0 :   x = gen_rtx_CONST_VECTOR (V4SImode,
    1497                 :            :                             gen_rtvec (4, GEN_INT (0x43300000UL),
    1498                 :            :                                        GEN_INT (0x45300000UL),
    1499                 :            :                                        const0_rtx, const0_rtx));
    1500                 :          0 :   exponents = validize_mem (force_const_mem (V4SImode, x));
    1501                 :            : 
    1502                 :            :   /* int_xmm = {0x45300000UL, fp_xmm/hi, 0x43300000, fp_xmm/lo } */
    1503                 :          0 :   emit_insn (gen_vec_interleave_lowv4si (int_xmm, int_xmm, exponents));
    1504                 :            : 
    1505                 :            :   /* Concatenating (juxtaposing) (0x43300000UL ## fp_value_low_xmm)
    1506                 :            :      yields a valid DF value equal to (0x1.0p52 + double(fp_value_lo_xmm)).
    1507                 :            :      Similarly (0x45300000UL ## fp_value_hi_xmm) yields
    1508                 :            :      (0x1.0p84 + double(fp_value_hi_xmm)).
    1509                 :            :      Note these exponents differ by 32.  */
    1510                 :            : 
    1511                 :          0 :   fp_xmm = copy_to_mode_reg (V2DFmode, gen_lowpart (V2DFmode, int_xmm));
    1512                 :            : 
    1513                 :            :   /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
    1514                 :            :      in [0,2**32-1] and [0]+[2**32,2**64-1] respectively.  */
    1515                 :          0 :   real_ldexp (&bias_lo_rvt, &dconst1, 52);
    1516                 :          0 :   real_ldexp (&bias_hi_rvt, &dconst1, 84);
    1517                 :          0 :   biases = const_double_from_real_value (bias_lo_rvt, DFmode);
    1518                 :          0 :   x = const_double_from_real_value (bias_hi_rvt, DFmode);
    1519                 :          0 :   biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
    1520                 :          0 :   biases = validize_mem (force_const_mem (V2DFmode, biases));
    1521                 :          0 :   emit_insn (gen_subv2df3 (fp_xmm, fp_xmm, biases));
    1522                 :            : 
    1523                 :            :   /* Add the upper and lower DFmode values together.  */
    1524                 :          0 :   if (TARGET_SSE3)
    1525                 :          0 :     emit_insn (gen_sse3_haddv2df3 (fp_xmm, fp_xmm, fp_xmm));
    1526                 :            :   else
    1527                 :            :     {
    1528                 :          0 :       x = copy_to_mode_reg (V2DFmode, fp_xmm);
    1529                 :          0 :       emit_insn (gen_vec_interleave_highv2df (fp_xmm, fp_xmm, fp_xmm));
    1530                 :          0 :       emit_insn (gen_addv2df3 (fp_xmm, fp_xmm, x));
    1531                 :            :     }
    1532                 :            : 
    1533                 :          0 :   ix86_expand_vector_extract (false, target, fp_xmm, 0);
    1534                 :          0 : }
    1535                 :            : 
    1536                 :            : /* Not used, but eases macroization of patterns.  */
    1537                 :            : void
    1538                 :          0 : ix86_expand_convert_uns_sixf_sse (rtx, rtx)
    1539                 :            : {
    1540                 :          0 :   gcc_unreachable ();
    1541                 :            : }
    1542                 :            : 
    1543                 :            : /* Convert an unsigned SImode value into a DFmode.  Only currently used
    1544                 :            :    for SSE, but applicable anywhere.  */
    1545                 :            : 
    1546                 :            : void
    1547                 :          0 : ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
    1548                 :            : {
    1549                 :          0 :   REAL_VALUE_TYPE TWO31r;
    1550                 :          0 :   rtx x, fp;
    1551                 :            : 
    1552                 :          0 :   x = expand_simple_binop (SImode, PLUS, input, GEN_INT (-2147483647 - 1),
    1553                 :            :                            NULL, 1, OPTAB_DIRECT);
    1554                 :            : 
    1555                 :          0 :   fp = gen_reg_rtx (DFmode);
    1556                 :          0 :   emit_insn (gen_floatsidf2 (fp, x));
    1557                 :            : 
    1558                 :          0 :   real_ldexp (&TWO31r, &dconst1, 31);
    1559                 :          0 :   x = const_double_from_real_value (TWO31r, DFmode);
    1560                 :            : 
    1561                 :          0 :   x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
    1562                 :          0 :   if (x != target)
    1563                 :          0 :     emit_move_insn (target, x);
    1564                 :          0 : }
    1565                 :            : 
    1566                 :            : /* Convert a signed DImode value into a DFmode.  Only used for SSE in
    1567                 :            :    32-bit mode; otherwise we have a direct convert instruction.  */
    1568                 :            : 
    1569                 :            : void
    1570                 :          0 : ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
    1571                 :            : {
    1572                 :          0 :   REAL_VALUE_TYPE TWO32r;
    1573                 :          0 :   rtx fp_lo, fp_hi, x;
    1574                 :            : 
    1575                 :          0 :   fp_lo = gen_reg_rtx (DFmode);
    1576                 :          0 :   fp_hi = gen_reg_rtx (DFmode);
    1577                 :            : 
    1578                 :          0 :   emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
    1579                 :            : 
    1580                 :          0 :   real_ldexp (&TWO32r, &dconst1, 32);
    1581                 :          0 :   x = const_double_from_real_value (TWO32r, DFmode);
    1582                 :          0 :   fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
    1583                 :            : 
    1584                 :          0 :   ix86_expand_convert_uns_sidf_sse (fp_lo, gen_lowpart (SImode, input));
    1585                 :            : 
    1586                 :          0 :   x = expand_simple_binop (DFmode, PLUS, fp_hi, fp_lo, target,
    1587                 :            :                            0, OPTAB_DIRECT);
    1588                 :          0 :   if (x != target)
    1589                 :          0 :     emit_move_insn (target, x);
    1590                 :          0 : }
    1591                 :            : 
    1592                 :            : /* Convert an unsigned SImode value into a SFmode, using only SSE.
    1593                 :            :    For x86_32, -mfpmath=sse, !optimize_size only.  */
    1594                 :            : void
    1595                 :          0 : ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
    1596                 :            : {
    1597                 :          0 :   REAL_VALUE_TYPE ONE16r;
    1598                 :          0 :   rtx fp_hi, fp_lo, int_hi, int_lo, x;
    1599                 :            : 
    1600                 :          0 :   real_ldexp (&ONE16r, &dconst1, 16);
    1601                 :          0 :   x = const_double_from_real_value (ONE16r, SFmode);
    1602                 :          0 :   int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
    1603                 :            :                                       NULL, 0, OPTAB_DIRECT);
    1604                 :          0 :   int_hi = expand_simple_binop (SImode, LSHIFTRT, input, GEN_INT(16),
    1605                 :            :                                       NULL, 0, OPTAB_DIRECT);
    1606                 :          0 :   fp_hi = gen_reg_rtx (SFmode);
    1607                 :          0 :   fp_lo = gen_reg_rtx (SFmode);
    1608                 :          0 :   emit_insn (gen_floatsisf2 (fp_hi, int_hi));
    1609                 :          0 :   emit_insn (gen_floatsisf2 (fp_lo, int_lo));
    1610                 :          0 :   fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
    1611                 :            :                                0, OPTAB_DIRECT);
    1612                 :          0 :   fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
    1613                 :            :                                0, OPTAB_DIRECT);
    1614                 :          0 :   if (!rtx_equal_p (target, fp_hi))
    1615                 :          0 :     emit_move_insn (target, fp_hi);
    1616                 :          0 : }
    1617                 :            : 
    1618                 :            : /* floatunsv{4,8}siv{4,8}sf2 expander.  Expand code to convert
    1619                 :            :    a vector of unsigned ints VAL to vector of floats TARGET.  */
    1620                 :            : 
    1621                 :            : void
    1622                 :         40 : ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
    1623                 :            : {
    1624                 :         40 :   rtx tmp[8];
    1625                 :         40 :   REAL_VALUE_TYPE TWO16r;
    1626                 :         40 :   machine_mode intmode = GET_MODE (val);
    1627                 :         40 :   machine_mode fltmode = GET_MODE (target);
    1628                 :         40 :   rtx (*cvt) (rtx, rtx);
    1629                 :            : 
    1630                 :         40 :   if (intmode == V4SImode)
    1631                 :            :     cvt = gen_floatv4siv4sf2;
    1632                 :            :   else
    1633                 :          0 :     cvt = gen_floatv8siv8sf2;
    1634                 :         40 :   tmp[0] = ix86_build_const_vector (intmode, 1, GEN_INT (0xffff));
    1635                 :         40 :   tmp[0] = force_reg (intmode, tmp[0]);
    1636                 :         40 :   tmp[1] = expand_simple_binop (intmode, AND, val, tmp[0], NULL_RTX, 1,
    1637                 :            :                                 OPTAB_DIRECT);
    1638                 :         40 :   tmp[2] = expand_simple_binop (intmode, LSHIFTRT, val, GEN_INT (16),
    1639                 :            :                                 NULL_RTX, 1, OPTAB_DIRECT);
    1640                 :         40 :   tmp[3] = gen_reg_rtx (fltmode);
    1641                 :         40 :   emit_insn (cvt (tmp[3], tmp[1]));
    1642                 :         40 :   tmp[4] = gen_reg_rtx (fltmode);
    1643                 :         40 :   emit_insn (cvt (tmp[4], tmp[2]));
    1644                 :         40 :   real_ldexp (&TWO16r, &dconst1, 16);
    1645                 :         40 :   tmp[5] = const_double_from_real_value (TWO16r, SFmode);
    1646                 :         40 :   tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
    1647                 :         40 :   tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5], NULL_RTX, 1,
    1648                 :            :                                 OPTAB_DIRECT);
    1649                 :         40 :   tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6], target, 1,
    1650                 :            :                                 OPTAB_DIRECT);
    1651                 :         40 :   if (tmp[7] != target)
    1652                 :          0 :     emit_move_insn (target, tmp[7]);
    1653                 :         40 : }
    1654                 :            : 
    1655                 :            : /* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
    1656                 :            :    pattern can be used on it instead of *ufix_trunc* resp. fixuns_trunc*.
    1657                 :            :    This is done by doing just signed conversion if < 0x1p31, and otherwise by
    1658                 :            :    subtracting 0x1p31 first and xoring in 0x80000000 from *XORP afterwards.  */
    1659                 :            : 
    1660                 :            : rtx
    1661                 :         14 : ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
    1662                 :            : {
    1663                 :         14 :   REAL_VALUE_TYPE TWO31r;
    1664                 :         14 :   rtx two31r, tmp[4];
    1665                 :         14 :   machine_mode mode = GET_MODE (val);
    1666                 :         28 :   machine_mode scalarmode = GET_MODE_INNER (mode);
    1667                 :         28 :   machine_mode intmode = GET_MODE_SIZE (mode) == 32 ? V8SImode : V4SImode;
    1668                 :         14 :   rtx (*cmp) (rtx, rtx, rtx, rtx);
    1669                 :         14 :   int i;
    1670                 :            : 
    1671                 :         56 :   for (i = 0; i < 3; i++)
    1672                 :         42 :     tmp[i] = gen_reg_rtx (mode);
    1673                 :         14 :   real_ldexp (&TWO31r, &dconst1, 31);
    1674                 :         14 :   two31r = const_double_from_real_value (TWO31r, scalarmode);
    1675                 :         14 :   two31r = ix86_build_const_vector (mode, 1, two31r);
    1676                 :         14 :   two31r = force_reg (mode, two31r);
    1677                 :         14 :   switch (mode)
    1678                 :            :     {
    1679                 :            :     case E_V8SFmode: cmp = gen_avx_maskcmpv8sf3; break;
    1680                 :          4 :     case E_V4SFmode: cmp = gen_sse_maskcmpv4sf3; break;
    1681                 :          2 :     case E_V4DFmode: cmp = gen_avx_maskcmpv4df3; break;
    1682                 :          8 :     case E_V2DFmode: cmp = gen_sse2_maskcmpv2df3; break;
    1683                 :          0 :     default: gcc_unreachable ();
    1684                 :            :     }
    1685                 :         14 :   tmp[3] = gen_rtx_LE (mode, two31r, val);
    1686                 :         14 :   emit_insn (cmp (tmp[0], two31r, val, tmp[3]));
    1687                 :         14 :   tmp[1] = expand_simple_binop (mode, AND, tmp[0], two31r, tmp[1],
    1688                 :            :                                 0, OPTAB_DIRECT);
    1689                 :         14 :   if (intmode == V4SImode || TARGET_AVX2)
    1690                 :         24 :     *xorp = expand_simple_binop (intmode, ASHIFT,
    1691                 :         12 :                                  gen_lowpart (intmode, tmp[0]),
    1692                 :            :                                  GEN_INT (31), NULL_RTX, 0,
    1693                 :            :                                  OPTAB_DIRECT);
    1694                 :            :   else
    1695                 :            :     {
    1696                 :          2 :       rtx two31 = gen_int_mode (HOST_WIDE_INT_1U << 31, SImode);
    1697                 :          2 :       two31 = ix86_build_const_vector (intmode, 1, two31);
    1698                 :          2 :       *xorp = expand_simple_binop (intmode, AND,
    1699                 :          2 :                                    gen_lowpart (intmode, tmp[0]),
    1700                 :            :                                    two31, NULL_RTX, 0,
    1701                 :            :                                    OPTAB_DIRECT);
    1702                 :            :     }
    1703                 :         14 :   return expand_simple_binop (mode, MINUS, val, tmp[1], tmp[2],
    1704                 :         14 :                               0, OPTAB_DIRECT);
    1705                 :            : }
    1706                 :            : 
    1707                 :            : /* Generate code for floating point ABS or NEG.  */
    1708                 :            : 
    1709                 :            : void
    1710                 :      25917 : ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
    1711                 :            :                                 rtx operands[])
    1712                 :            : {
    1713                 :      25917 :   rtx set, dst, src;
    1714                 :      25917 :   bool use_sse = false;
    1715                 :      25917 :   bool vector_mode = VECTOR_MODE_P (mode);
    1716                 :      24015 :   machine_mode vmode = mode;
    1717                 :      24015 :   rtvec par;
    1718                 :            : 
    1719                 :      24015 :   if (vector_mode)
    1720                 :            :     use_sse = true;
    1721                 :      24015 :   else if (mode == TFmode)
    1722                 :            :     use_sse = true;
    1723                 :      22778 :   else if (TARGET_SSE_MATH)
    1724                 :            :     {
    1725                 :      21766 :       use_sse = SSE_FLOAT_MODE_P (mode);
    1726                 :      21766 :       if (mode == SFmode)
    1727                 :            :         vmode = V4SFmode;
    1728                 :      14911 :       else if (mode == DFmode)
    1729                 :      12128 :         vmode = V2DFmode;
    1730                 :            :     }
    1731                 :            : 
    1732                 :      25917 :   dst = operands[0];
    1733                 :      25917 :   src = operands[1];
    1734                 :            : 
    1735                 :      25917 :   set = gen_rtx_fmt_e (code, mode, src);
    1736                 :      25917 :   set = gen_rtx_SET (dst, set);
    1737                 :            : 
    1738                 :      25917 :   if (use_sse)
    1739                 :            :     {
    1740                 :      22118 :       rtx mask, use, clob;
    1741                 :            : 
    1742                 :            :       /* NEG and ABS performed with SSE use bitwise mask operations.
    1743                 :            :          Create the appropriate mask now.  */
    1744                 :      22118 :       mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
    1745                 :      22118 :       use = gen_rtx_USE (VOIDmode, mask);
    1746                 :      22118 :       if (vector_mode)
    1747                 :       1902 :         par = gen_rtvec (2, set, use);
    1748                 :            :       else
    1749                 :            :         {
    1750                 :      20216 :           clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
    1751                 :      20216 :           par = gen_rtvec (3, set, use, clob);
    1752                 :            :         }
    1753                 :            :     }
    1754                 :            :   else
    1755                 :            :     {
    1756                 :       3799 :       rtx clob;
    1757                 :            : 
    1758                 :            :       /* Changing of sign for FP values is doable using integer unit too.  */
    1759                 :       3799 :       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
    1760                 :       3799 :       par = gen_rtvec (2, set, clob);
    1761                 :            :     }
    1762                 :            : 
    1763                 :      25917 :   emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
    1764                 :      25917 : }
    1765                 :            : 
    1766                 :            : /* Deconstruct a floating point ABS or NEG operation
    1767                 :            :    with integer registers into integer operations.  */
    1768                 :            : 
    1769                 :            : void
    1770                 :         37 : ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
    1771                 :            :                                rtx operands[])
    1772                 :            : {
    1773                 :         37 :   enum rtx_code absneg_op;
    1774                 :         37 :   rtx dst, set;
    1775                 :            : 
    1776                 :         37 :   gcc_assert (operands_match_p (operands[0], operands[1]));
    1777                 :            : 
    1778                 :         37 :   switch (mode)
    1779                 :            :     {
    1780                 :          2 :     case E_SFmode:
    1781                 :          2 :       dst = gen_lowpart (SImode, operands[0]);
    1782                 :            : 
    1783                 :          2 :       if (code == ABS)
    1784                 :            :         {
    1785                 :          0 :           set = gen_int_mode (0x7fffffff, SImode);
    1786                 :          0 :           absneg_op = AND;
    1787                 :            :         }
    1788                 :            :       else
    1789                 :            :         {
    1790                 :          2 :           set = gen_int_mode (0x80000000, SImode);
    1791                 :          2 :           absneg_op = XOR;
    1792                 :            :         }
    1793                 :          2 :       set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
    1794                 :          2 :       break;
    1795                 :            : 
    1796                 :          4 :     case E_DFmode:
    1797                 :          4 :       if (TARGET_64BIT)
    1798                 :            :         {
    1799                 :          4 :           dst = gen_lowpart (DImode, operands[0]);
    1800                 :          4 :           dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
    1801                 :            : 
    1802                 :          4 :           if (code == ABS)
    1803                 :          0 :             set = const0_rtx;
    1804                 :            :           else
    1805                 :          4 :             set = gen_rtx_NOT (DImode, dst);
    1806                 :            :         }
    1807                 :            :       else
    1808                 :            :         {
    1809                 :          0 :           dst = gen_highpart (SImode, operands[0]);
    1810                 :            : 
    1811                 :          0 :           if (code == ABS)
    1812                 :            :             {
    1813                 :          0 :               set = gen_int_mode (0x7fffffff, SImode);
    1814                 :          0 :               absneg_op = AND;
    1815                 :            :             }
    1816                 :            :           else
    1817                 :            :             {
    1818                 :          0 :               set = gen_int_mode (0x80000000, SImode);
    1819                 :          0 :               absneg_op = XOR;
    1820                 :            :             }
    1821                 :          0 :           set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
    1822                 :            :         }
    1823                 :            :       break;
    1824                 :            : 
    1825                 :         31 :     case E_XFmode:
    1826                 :         31 :       dst = gen_rtx_REG (SImode,
    1827                 :         31 :                          REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
    1828                 :         31 :       if (code == ABS)
    1829                 :            :         {
    1830                 :          4 :           set = GEN_INT (0x7fff);
    1831                 :          4 :           absneg_op = AND;
    1832                 :            :         }
    1833                 :            :       else
    1834                 :            :         {
    1835                 :         27 :           set = GEN_INT (0x8000);
    1836                 :         27 :           absneg_op = XOR;
    1837                 :            :         }
    1838                 :         31 :       set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
    1839                 :         31 :       break;
    1840                 :            : 
    1841                 :          0 :     default:
    1842                 :          0 :       gcc_unreachable ();
    1843                 :            :     }
    1844                 :            : 
    1845                 :         37 :   set = gen_rtx_SET (dst, set);
    1846                 :            : 
    1847                 :         37 :   rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
    1848                 :         37 :   rtvec par = gen_rtvec (2, set, clob);
    1849                 :            : 
    1850                 :         37 :   emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
    1851                 :         37 : }
    1852                 :            : 
    1853                 :            : /* Expand a copysign operation.  Special case operand 0 being a constant.  */
    1854                 :            : 
    1855                 :            : void
    1856                 :      23680 : ix86_expand_copysign (rtx operands[])
    1857                 :            : {
    1858                 :      23680 :   machine_mode mode, vmode;
    1859                 :      23680 :   rtx dest, op0, op1, mask;
    1860                 :            : 
    1861                 :      23680 :   dest = operands[0];
    1862                 :      23680 :   op0 = operands[1];
    1863                 :      23680 :   op1 = operands[2];
    1864                 :            : 
    1865                 :      23680 :   mode = GET_MODE (dest);
    1866                 :            : 
    1867                 :      23680 :   if (mode == SFmode)
    1868                 :            :     vmode = V4SFmode;
    1869                 :      11870 :   else if (mode == DFmode)
    1870                 :            :     vmode = V2DFmode;
    1871                 :         97 :   else if (mode == TFmode)
    1872                 :            :     vmode = mode;
    1873                 :            :   else
    1874                 :          0 :     gcc_unreachable ();
    1875                 :            : 
    1876                 :      23680 :   mask = ix86_build_signbit_mask (vmode, 0, 0);
    1877                 :            : 
    1878                 :      23680 :   if (CONST_DOUBLE_P (op0))
    1879                 :            :     {
    1880                 :      23276 :       if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
    1881                 :          0 :         op0 = simplify_unary_operation (ABS, mode, op0, mode);
    1882                 :            : 
    1883                 :      23276 :       if (mode == SFmode || mode == DFmode)
    1884                 :            :         {
    1885                 :      23240 :           if (op0 == CONST0_RTX (mode))
    1886                 :         68 :             op0 = CONST0_RTX (vmode);
    1887                 :            :           else
    1888                 :            :             {
    1889                 :      23172 :               rtx v = ix86_build_const_vector (vmode, false, op0);
    1890                 :            : 
    1891                 :      23172 :               op0 = force_reg (vmode, v);
    1892                 :            :             }
    1893                 :            :         }
    1894                 :         36 :       else if (op0 != CONST0_RTX (mode))
    1895                 :          4 :         op0 = force_reg (mode, op0);
    1896                 :            : 
    1897                 :      23276 :       emit_insn (gen_copysign3_const (mode, dest, op0, op1, mask));
    1898                 :            :     }
    1899                 :            :   else
    1900                 :            :     {
    1901                 :        404 :       rtx nmask = ix86_build_signbit_mask (vmode, 0, 1);
    1902                 :            : 
    1903                 :        404 :       emit_insn (gen_copysign3_var
    1904                 :            :                  (mode, dest, NULL_RTX, op0, op1, nmask, mask));
    1905                 :            :     }
    1906                 :      23680 : }
    1907                 :            : 
    1908                 :            : /* Deconstruct a copysign operation into bit masks.  Operand 0 is known to
    1909                 :            :    be a constant, and so has already been expanded into a vector constant.  */
    1910                 :            : 
    1911                 :            : void
    1912                 :      23275 : ix86_split_copysign_const (rtx operands[])
    1913                 :            : {
    1914                 :      23275 :   machine_mode mode, vmode;
    1915                 :      23275 :   rtx dest, op0, mask, x;
    1916                 :            : 
    1917                 :      23275 :   dest = operands[0];
    1918                 :      23275 :   op0 = operands[1];
    1919                 :      23275 :   mask = operands[3];
    1920                 :            : 
    1921                 :      23275 :   mode = GET_MODE (dest);
    1922                 :      23275 :   vmode = GET_MODE (mask);
    1923                 :            : 
    1924                 :      23275 :   dest = lowpart_subreg (vmode, dest, mode);
    1925                 :      23275 :   x = gen_rtx_AND (vmode, dest, mask);
    1926                 :      23275 :   emit_insn (gen_rtx_SET (dest, x));
    1927                 :            : 
    1928                 :      23275 :   if (op0 != CONST0_RTX (vmode))
    1929                 :            :     {
    1930                 :      23175 :       x = gen_rtx_IOR (vmode, dest, op0);
    1931                 :      23175 :       emit_insn (gen_rtx_SET (dest, x));
    1932                 :            :     }
    1933                 :      23275 : }
    1934                 :            : 
    1935                 :            : /* Deconstruct a copysign operation into bit masks.  Operand 0 is variable,
    1936                 :            :    so we have to do two masks.  */
    1937                 :            : 
    1938                 :            : void
    1939                 :        404 : ix86_split_copysign_var (rtx operands[])
    1940                 :            : {
    1941                 :        404 :   machine_mode mode, vmode;
    1942                 :        404 :   rtx dest, scratch, op0, op1, mask, nmask, x;
    1943                 :            : 
    1944                 :        404 :   dest = operands[0];
    1945                 :        404 :   scratch = operands[1];
    1946                 :        404 :   op0 = operands[2];
    1947                 :        404 :   op1 = operands[3];
    1948                 :        404 :   nmask = operands[4];
    1949                 :        404 :   mask = operands[5];
    1950                 :            : 
    1951                 :        404 :   mode = GET_MODE (dest);
    1952                 :        404 :   vmode = GET_MODE (mask);
    1953                 :            : 
    1954                 :        404 :   if (rtx_equal_p (op0, op1))
    1955                 :            :     {
    1956                 :            :       /* Shouldn't happen often (it's useless, obviously), but when it does
    1957                 :            :          we'd generate incorrect code if we continue below.  */
    1958                 :          0 :       emit_move_insn (dest, op0);
    1959                 :          0 :       return;
    1960                 :            :     }
    1961                 :            : 
    1962                 :        404 :   if (REG_P (mask) && REGNO (dest) == REGNO (mask))     /* alternative 0 */
    1963                 :            :     {
    1964                 :         37 :       gcc_assert (REGNO (op1) == REGNO (scratch));
    1965                 :            : 
    1966                 :         37 :       x = gen_rtx_AND (vmode, scratch, mask);
    1967                 :         37 :       emit_insn (gen_rtx_SET (scratch, x));
    1968                 :            : 
    1969                 :         37 :       dest = mask;
    1970                 :         37 :       op0 = lowpart_subreg (vmode, op0, mode);
    1971                 :         37 :       x = gen_rtx_NOT (vmode, dest);
    1972                 :         37 :       x = gen_rtx_AND (vmode, x, op0);
    1973                 :         37 :       emit_insn (gen_rtx_SET (dest, x));
    1974                 :            :     }
    1975                 :            :   else
    1976                 :            :     {
    1977                 :        367 :       if (REGNO (op1) == REGNO (scratch))               /* alternative 1,3 */
    1978                 :            :         {
    1979                 :        308 :           x = gen_rtx_AND (vmode, scratch, mask);
    1980                 :            :         }
    1981                 :            :       else                                              /* alternative 2,4 */
    1982                 :            :         {
    1983                 :         59 :           gcc_assert (REGNO (mask) == REGNO (scratch));
    1984                 :         59 :           op1 = lowpart_subreg (vmode, op1, mode);
    1985                 :         59 :           x = gen_rtx_AND (vmode, scratch, op1);
    1986                 :            :         }
    1987                 :        367 :       emit_insn (gen_rtx_SET (scratch, x));
    1988                 :            : 
    1989                 :        367 :       if (REGNO (op0) == REGNO (dest))                  /* alternative 1,2 */
    1990                 :            :         {
    1991                 :        283 :           dest = lowpart_subreg (vmode, op0, mode);
    1992                 :        283 :           x = gen_rtx_AND (vmode, dest, nmask);
    1993                 :            :         }
    1994                 :            :       else                                              /* alternative 3,4 */
    1995                 :            :         {
    1996                 :         84 :           gcc_assert (REGNO (nmask) == REGNO (dest));
    1997                 :         84 :           dest = nmask;
    1998                 :         84 :           op0 = lowpart_subreg (vmode, op0, mode);
    1999                 :         84 :           x = gen_rtx_AND (vmode, dest, op0);
    2000                 :            :         }
    2001                 :        367 :       emit_insn (gen_rtx_SET (dest, x));
    2002                 :            :     }
    2003                 :            : 
    2004                 :        404 :   x = gen_rtx_IOR (vmode, dest, scratch);
    2005                 :        404 :   emit_insn (gen_rtx_SET (dest, x));
    2006                 :            : }
    2007                 :            : 
    2008                 :            : /* Expand an xorsign operation.  */
    2009                 :            : 
    2010                 :            : void
    2011                 :          2 : ix86_expand_xorsign (rtx operands[])
    2012                 :            : {
    2013                 :          2 :   machine_mode mode, vmode;
    2014                 :          2 :   rtx dest, op0, op1, mask;
    2015                 :            : 
    2016                 :          2 :   dest = operands[0];
    2017                 :          2 :   op0 = operands[1];
    2018                 :          2 :   op1 = operands[2];
    2019                 :            : 
    2020                 :          2 :   mode = GET_MODE (dest);
    2021                 :            : 
    2022                 :          2 :   if (mode == SFmode)
    2023                 :            :     vmode = V4SFmode;
    2024                 :          1 :   else if (mode == DFmode)
    2025                 :            :     vmode = V2DFmode;
    2026                 :            :   else
    2027                 :          0 :     gcc_unreachable ();
    2028                 :            : 
    2029                 :          2 :   mask = ix86_build_signbit_mask (vmode, 0, 0);
    2030                 :            : 
    2031                 :          2 :   emit_insn (gen_xorsign3_1 (mode, dest, op0, op1, mask));
    2032                 :          2 : }
    2033                 :            : 
    2034                 :            : /* Deconstruct an xorsign operation into bit masks.  */
    2035                 :            : 
    2036                 :            : void
    2037                 :          2 : ix86_split_xorsign (rtx operands[])
    2038                 :            : {
    2039                 :          2 :   machine_mode mode, vmode;
    2040                 :          2 :   rtx dest, op0, mask, x;
    2041                 :            : 
    2042                 :          2 :   dest = operands[0];
    2043                 :          2 :   op0 = operands[1];
    2044                 :          2 :   mask = operands[3];
    2045                 :            : 
    2046                 :          2 :   mode = GET_MODE (dest);
    2047                 :          2 :   vmode = GET_MODE (mask);
    2048                 :            : 
    2049                 :          2 :   dest = lowpart_subreg (vmode, dest, mode);
    2050                 :          2 :   x = gen_rtx_AND (vmode, dest, mask);
    2051                 :          2 :   emit_insn (gen_rtx_SET (dest, x));
    2052                 :            : 
    2053                 :          2 :   op0 = lowpart_subreg (vmode, op0, mode);
    2054                 :          2 :   x = gen_rtx_XOR (vmode, dest, op0);
    2055                 :          2 :   emit_insn (gen_rtx_SET (dest, x));
    2056                 :          2 : }
    2057                 :            : 
    2058                 :            : static rtx ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1);
    2059                 :            : 
    2060                 :            : void
    2061                 :    4131240 : ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
    2062                 :            : {
    2063                 :    4131240 :   machine_mode mode = GET_MODE (op0);
    2064                 :    4131240 :   rtx tmp;
    2065                 :            : 
    2066                 :            :   /* Handle special case - vector comparsion with boolean result, transform
    2067                 :            :      it using ptest instruction.  */
    2068                 :    4131240 :   if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
    2069                 :            :     {
    2070                 :         91 :       rtx flag = gen_rtx_REG (CCZmode, FLAGS_REG);
    2071                 :        182 :       machine_mode p_mode = GET_MODE_SIZE (mode) == 32 ? V4DImode : V2DImode;
    2072                 :            : 
    2073                 :         91 :       gcc_assert (code == EQ || code == NE);
    2074                 :            :       /* Generate XOR since we can't check that one operand is zero vector.  */
    2075                 :         91 :       tmp = gen_reg_rtx (mode);
    2076                 :         91 :       emit_insn (gen_rtx_SET (tmp, gen_rtx_XOR (mode, op0, op1)));
    2077                 :         91 :       tmp = gen_lowpart (p_mode, tmp);
    2078                 :         91 :       emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, FLAGS_REG),
    2079                 :            :                               gen_rtx_UNSPEC (CCmode,
    2080                 :            :                                               gen_rtvec (2, tmp, tmp),
    2081                 :            :                                               UNSPEC_PTEST)));
    2082                 :         91 :       tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx);
    2083                 :         91 :       tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
    2084                 :            :                                   gen_rtx_LABEL_REF (VOIDmode, label),
    2085                 :            :                                   pc_rtx);
    2086                 :         91 :       emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
    2087                 :         91 :       return;
    2088                 :            :     }
    2089                 :            : 
    2090                 :    4131150 :   switch (mode)
    2091                 :            :     {
    2092                 :    4077930 :     case E_SFmode:
    2093                 :    4077930 :     case E_DFmode:
    2094                 :    4077930 :     case E_XFmode:
    2095                 :    4077930 :     case E_QImode:
    2096                 :    4077930 :     case E_HImode:
    2097                 :    4077930 :     case E_SImode:
    2098                 :    4077930 :       simple:
    2099                 :    4077930 :       tmp = ix86_expand_compare (code, op0, op1);
    2100                 :    4077930 :       tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
    2101                 :            :                                   gen_rtx_LABEL_REF (VOIDmode, label),
    2102                 :            :                                   pc_rtx);
    2103                 :    4077930 :       emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
    2104                 :    4077930 :       return;
    2105                 :            : 
    2106                 :    1583360 :     case E_DImode:
    2107                 :    1583360 :       if (TARGET_64BIT)
    2108                 :    1564890 :         goto simple;
    2109                 :            :       /* For 32-bit target DI comparison may be performed on
    2110                 :            :          SSE registers.  To allow this we should avoid split
    2111                 :            :          to SI mode which is achieved by doing xor in DI mode
    2112                 :            :          and then comparing with zero (which is recognized by
    2113                 :            :          STV pass).  We don't compare using xor when optimizing
    2114                 :            :          for size.  */
    2115                 :      18470 :       if (!optimize_insn_for_size_p ()
    2116                 :      17703 :           && TARGET_STV
    2117                 :      36173 :           && (code == EQ || code == NE))
    2118                 :            :         {
    2119                 :       8513 :           op0 = force_reg (mode, gen_rtx_XOR (mode, op0, op1));
    2120                 :       8513 :           op1 = const0_rtx;
    2121                 :            :         }
    2122                 :            :       /* FALLTHRU */
    2123                 :      53220 :     case E_TImode:
    2124                 :            :       /* Expand DImode branch into multiple compare+branch.  */
    2125                 :      53220 :       {
    2126                 :      53220 :         rtx lo[2], hi[2];
    2127                 :      53220 :         rtx_code_label *label2;
    2128                 :      53220 :         enum rtx_code code1, code2, code3;
    2129                 :      53220 :         machine_mode submode;
    2130                 :            : 
    2131                 :      53220 :         if (CONSTANT_P (op0) && !CONSTANT_P (op1))
    2132                 :            :           {
    2133                 :          0 :             std::swap (op0, op1);
    2134                 :          0 :             code = swap_condition (code);
    2135                 :            :           }
    2136                 :            : 
    2137                 :      53220 :         split_double_mode (mode, &op0, 1, lo+0, hi+0);
    2138                 :      53220 :         split_double_mode (mode, &op1, 1, lo+1, hi+1);
    2139                 :            : 
    2140                 :      87970 :         submode = mode == DImode ? SImode : DImode;
    2141                 :            : 
    2142                 :            :         /* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to
    2143                 :            :            avoid two branches.  This costs one extra insn, so disable when
    2144                 :            :            optimizing for size.  */
    2145                 :            : 
    2146                 :      53220 :         if ((code == EQ || code == NE)
    2147                 :      53220 :             && (!optimize_insn_for_size_p ()
    2148                 :       1685 :                 || hi[1] == const0_rtx || lo[1] == const0_rtx))
    2149                 :            :           {
    2150                 :      30249 :             rtx xor0, xor1;
    2151                 :            : 
    2152                 :      30249 :             xor1 = hi[0];
    2153                 :      30249 :             if (hi[1] != const0_rtx)
    2154                 :      15539 :               xor1 = expand_binop (submode, xor_optab, xor1, hi[1],
    2155                 :            :                                    NULL_RTX, 0, OPTAB_WIDEN);
    2156                 :            : 
    2157                 :      30249 :             xor0 = lo[0];
    2158                 :      30249 :             if (lo[1] != const0_rtx)
    2159                 :      17207 :               xor0 = expand_binop (submode, xor_optab, xor0, lo[1],
    2160                 :            :                                    NULL_RTX, 0, OPTAB_WIDEN);
    2161                 :            : 
    2162                 :      30249 :             tmp = expand_binop (submode, ior_optab, xor1, xor0,
    2163                 :            :                                 NULL_RTX, 0, OPTAB_WIDEN);
    2164                 :            : 
    2165                 :      30249 :             ix86_expand_branch (code, tmp, const0_rtx, label);
    2166                 :      30249 :             return;
    2167                 :            :           }
    2168                 :            : 
    2169                 :            :         /* Otherwise, if we are doing less-than or greater-or-equal-than,
    2170                 :            :            op1 is a constant and the low word is zero, then we can just
    2171                 :            :            examine the high word.  Similarly for low word -1 and
    2172                 :            :            less-or-equal-than or greater-than.  */
    2173                 :            : 
    2174                 :      22971 :         if (CONST_INT_P (hi[1]))
    2175                 :      14803 :           switch (code)
    2176                 :            :             {
    2177                 :      10184 :             case LT: case LTU: case GE: case GEU:
    2178                 :      10184 :               if (lo[1] == const0_rtx)
    2179                 :            :                 {
    2180                 :       9779 :                   ix86_expand_branch (code, hi[0], hi[1], label);
    2181                 :       9779 :                   return;
    2182                 :            :                 }
    2183                 :            :               break;
    2184                 :       4535 :             case LE: case LEU: case GT: case GTU:
    2185                 :       4535 :               if (lo[1] == constm1_rtx)
    2186                 :            :                 {
    2187                 :        466 :                   ix86_expand_branch (code, hi[0], hi[1], label);
    2188                 :        466 :                   return;
    2189                 :            :                 }
    2190                 :            :               break;
    2191                 :            :             default:
    2192                 :            :               break;
    2193                 :            :             }
    2194                 :            : 
    2195                 :            :         /* Emulate comparisons that do not depend on Zero flag with
    2196                 :            :            double-word subtraction.  Note that only Overflow, Sign
    2197                 :            :            and Carry flags are valid, so swap arguments and condition
    2198                 :            :            of comparisons that would otherwise test Zero flag.  */
    2199                 :            : 
    2200                 :      12726 :         switch (code)
    2201                 :            :           {
    2202                 :       8020 :           case LE: case LEU: case GT: case GTU:
    2203                 :       8020 :             std::swap (lo[0], lo[1]);
    2204                 :       8020 :             std::swap (hi[0], hi[1]);
    2205                 :       8020 :             code = swap_condition (code);
    2206                 :            :             /* FALLTHRU */
    2207                 :            : 
    2208                 :      11752 :           case LT: case LTU: case GE: case GEU:
    2209                 :      11752 :             {
    2210                 :      11752 :               bool uns = (code == LTU || code == GEU);
    2211                 :      23504 :               rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
    2212                 :      11752 :                 = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
    2213                 :            : 
    2214                 :      11752 :               if (!nonimmediate_operand (lo[0], submode))
    2215                 :       4069 :                 lo[0] = force_reg (submode, lo[0]);
    2216                 :      11752 :               if (!x86_64_general_operand (lo[1], submode))
    2217                 :          0 :                 lo[1] = force_reg (submode, lo[1]);
    2218                 :            : 
    2219                 :      11752 :               if (!register_operand (hi[0], submode))
    2220                 :       4686 :                 hi[0] = force_reg (submode, hi[0]);
    2221                 :       7979 :               if ((uns && !nonimmediate_operand (hi[1], submode))
    2222                 :      19431 :                   || (!uns && !x86_64_general_operand (hi[1], submode)))
    2223                 :        300 :                 hi[1] = force_reg (submode, hi[1]);
    2224                 :            : 
    2225                 :      11752 :               emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
    2226                 :            : 
    2227                 :      11752 :               tmp = gen_rtx_SCRATCH (submode);
    2228                 :      11752 :               emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
    2229                 :            : 
    2230                 :      15525 :               tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
    2231                 :      11752 :               ix86_expand_branch (code, tmp, const0_rtx, label);
    2232                 :      11752 :               return;
    2233                 :            :             }
    2234                 :            : 
    2235                 :        974 :           default:
    2236                 :        974 :             break;
    2237                 :            :           }
    2238                 :            : 
    2239                 :            :         /* Otherwise, we need two or three jumps.  */
    2240                 :            : 
    2241                 :        974 :         label2 = gen_label_rtx ();
    2242                 :            : 
    2243                 :        974 :         code1 = code;
    2244                 :        974 :         code2 = swap_condition (code);
    2245                 :        974 :         code3 = unsigned_condition (code);
    2246                 :            : 
    2247                 :        974 :         switch (code)
    2248                 :            :           {
    2249                 :            :           case LT: case GT: case LTU: case GTU:
    2250                 :            :             break;
    2251                 :            : 
    2252                 :          0 :           case LE:   code1 = LT;  code2 = GT;  break;
    2253                 :          0 :           case GE:   code1 = GT;  code2 = LT;  break;
    2254                 :          0 :           case LEU:  code1 = LTU; code2 = GTU; break;
    2255                 :            :           case GEU:  code1 = GTU; code2 = LTU; break;
    2256                 :            : 
    2257                 :            :           case EQ:   code1 = UNKNOWN; code2 = NE;  break;
    2258                 :        924 :           case NE:   code2 = UNKNOWN; break;
    2259                 :            : 
    2260                 :          0 :           default:
    2261                 :          0 :             gcc_unreachable ();
    2262                 :            :           }
    2263                 :            : 
    2264                 :            :         /*
    2265                 :            :          * a < b =>
    2266                 :            :          *    if (hi(a) < hi(b)) goto true;
    2267                 :            :          *    if (hi(a) > hi(b)) goto false;
    2268                 :            :          *    if (lo(a) < lo(b)) goto true;
    2269                 :            :          *  false:
    2270                 :            :          */
    2271                 :            : 
    2272                 :        924 :         if (code1 != UNKNOWN)
    2273                 :        924 :           ix86_expand_branch (code1, hi[0], hi[1], label);
    2274                 :        974 :         if (code2 != UNKNOWN)
    2275                 :         50 :           ix86_expand_branch (code2, hi[0], hi[1], label2);
    2276                 :            : 
    2277                 :        974 :         ix86_expand_branch (code3, lo[0], lo[1], label);
    2278                 :            : 
    2279                 :        974 :         if (code2 != UNKNOWN)
    2280                 :         50 :           emit_label (label2);
    2281                 :            :         return;
    2282                 :            :       }
    2283                 :            : 
    2284                 :      11915 :     default:
    2285                 :      11915 :       gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC);
    2286                 :      11915 :       goto simple;
    2287                 :            :     }
    2288                 :            : }
    2289                 :            : 
    2290                 :            : /* Figure out whether to use unordered fp comparisons.  */
    2291                 :            : 
    2292                 :            : static bool
    2293                 :     949434 : ix86_unordered_fp_compare (enum rtx_code code)
    2294                 :            : {
    2295                 :     949434 :   if (!TARGET_IEEE_FP)
    2296                 :            :     return false;
    2297                 :            : 
    2298                 :     946228 :   switch (code)
    2299                 :            :     {
    2300                 :            :     case LT:
    2301                 :            :     case LE:
    2302                 :            :     case GT:
    2303                 :            :     case GE:
    2304                 :            :     case LTGT:
    2305                 :            :       return false;
    2306                 :            : 
    2307                 :     589374 :     case EQ:
    2308                 :     589374 :     case NE:
    2309                 :            : 
    2310                 :     589374 :     case UNORDERED:
    2311                 :     589374 :     case ORDERED:
    2312                 :     589374 :     case UNLT:
    2313                 :     589374 :     case UNLE:
    2314                 :     589374 :     case UNGT:
    2315                 :     589374 :     case UNGE:
    2316                 :     589374 :     case UNEQ:
    2317                 :     589374 :       return true;
    2318                 :            : 
    2319                 :          0 :     default:
    2320                 :          0 :       gcc_unreachable ();
    2321                 :            :     }
    2322                 :            : }
    2323                 :            : 
    2324                 :            : /* Return a comparison we can do and that it is equivalent to
    2325                 :            :    swap_condition (code) apart possibly from orderedness.
    2326                 :            :    But, never change orderedness if TARGET_IEEE_FP, returning
    2327                 :            :    UNKNOWN in that case if necessary.  */
    2328                 :            : 
    2329                 :            : static enum rtx_code
    2330                 :      35508 : ix86_fp_swap_condition (enum rtx_code code)
    2331                 :            : {
    2332                 :      35508 :   switch (code)
    2333                 :            :     {
    2334                 :       1594 :     case GT:                   /* GTU - CF=0 & ZF=0 */
    2335                 :       1594 :       return TARGET_IEEE_FP ? UNKNOWN : UNLT;
    2336                 :        463 :     case GE:                   /* GEU - CF=0 */
    2337                 :        463 :       return TARGET_IEEE_FP ? UNKNOWN : UNLE;
    2338                 :        366 :     case UNLT:                 /* LTU - CF=1 */
    2339                 :        366 :       return TARGET_IEEE_FP ? UNKNOWN : GT;
    2340                 :       9594 :     case UNLE:                 /* LEU - CF=1 | ZF=1 */
    2341                 :       9594 :       return TARGET_IEEE_FP ? UNKNOWN : GE;
    2342                 :      23491 :     default:
    2343                 :      23491 :       return swap_condition (code);
    2344                 :            :     }
    2345                 :            : }
    2346                 :            : 
    2347                 :            : /* Return cost of comparison CODE using the best strategy for performance.
    2348                 :            :    All following functions do use number of instructions as a cost metrics.
    2349                 :            :    In future this should be tweaked to compute bytes for optimize_size and
    2350                 :            :    take into account performance of various instructions on various CPUs.  */
    2351                 :            : 
    2352                 :            : static int
    2353                 :     948744 : ix86_fp_comparison_cost (enum rtx_code code)
    2354                 :            : {
    2355                 :     948744 :   int arith_cost;
    2356                 :            : 
    2357                 :            :   /* The cost of code using bit-twiddling on %ah.  */
    2358                 :     948744 :   switch (code)
    2359                 :            :     {
    2360                 :            :     case UNLE:
    2361                 :            :     case UNLT:
    2362                 :            :     case LTGT:
    2363                 :            :     case GT:
    2364                 :            :     case GE:
    2365                 :            :     case UNORDERED:
    2366                 :            :     case ORDERED:
    2367                 :            :     case UNEQ:
    2368                 :            :       arith_cost = 4;
    2369                 :            :       break;
    2370                 :      62004 :     case LT:
    2371                 :      62004 :     case NE:
    2372                 :      62004 :     case EQ:
    2373                 :      62004 :     case UNGE:
    2374                 :      62004 :       arith_cost = TARGET_IEEE_FP ? 5 : 4;
    2375                 :            :       break;
    2376                 :      15909 :     case LE:
    2377                 :      15909 :     case UNGT:
    2378                 :      15909 :       arith_cost = TARGET_IEEE_FP ? 6 : 4;
    2379                 :            :       break;
    2380                 :          0 :     default:
    2381                 :          0 :       gcc_unreachable ();
    2382                 :            :     }
    2383                 :            : 
    2384                 :     948744 :   switch (ix86_fp_comparison_strategy (code))
    2385                 :            :     {
    2386                 :     948744 :     case IX86_FPCMP_COMI:
    2387                 :     948744 :       return arith_cost > 4 ? 3 : 2;
    2388                 :          0 :     case IX86_FPCMP_SAHF:
    2389                 :          0 :       return arith_cost > 4 ? 4 : 3;
    2390                 :            :     default:
    2391                 :            :       return arith_cost;
    2392                 :            :     }
    2393                 :            : }
    2394                 :            : 
    2395                 :            : /* Swap, force into registers, or otherwise massage the two operands
    2396                 :            :    to a fp comparison.  The operands are updated in place; the new
    2397                 :            :    comparison code is returned.  */
    2398                 :            : 
    2399                 :            : static enum rtx_code
    2400                 :     474372 : ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
    2401                 :            : {
    2402                 :     474372 :   bool unordered_compare = ix86_unordered_fp_compare (code);
    2403                 :     474372 :   rtx op0 = *pop0, op1 = *pop1;
    2404                 :     474372 :   machine_mode op_mode = GET_MODE (op0);
    2405                 :     474372 :   bool is_sse = TARGET_SSE_MATH && SSE_FLOAT_MODE_P (op_mode);
    2406                 :            : 
    2407                 :            :   /* All of the unordered compare instructions only work on registers.
    2408                 :            :      The same is true of the fcomi compare instructions.  The XFmode
    2409                 :            :      compare instructions require registers except when comparing
    2410                 :            :      against zero or when converting operand 1 from fixed point to
    2411                 :            :      floating point.  */
    2412                 :            : 
    2413                 :     131612 :   if (!is_sse
    2414                 :     131612 :       && (unordered_compare
    2415                 :      46183 :           || (op_mode == XFmode
    2416                 :      84757 :               && ! (standard_80387_constant_p (op0) == 1
    2417                 :      42378 :                     || standard_80387_constant_p (op1) == 1)
    2418                 :      39794 :               && GET_CODE (op1) != FLOAT)
    2419                 :       6389 :           || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
    2420                 :            :     {
    2421                 :     131612 :       op0 = force_reg (op_mode, op0);
    2422                 :     131612 :       op1 = force_reg (op_mode, op1);
    2423                 :            :     }
    2424                 :            :   else
    2425                 :            :     {
    2426                 :            :       /* %%% We only allow op1 in memory; op0 must be st(0).  So swap
    2427                 :            :          things around if they appear profitable, otherwise force op0
    2428                 :            :          into a register.  */
    2429                 :            : 
    2430                 :     342760 :       if (standard_80387_constant_p (op0) == 0
    2431                 :     342760 :           || (MEM_P (op0)
    2432                 :      46506 :               && ! (standard_80387_constant_p (op1) == 0
    2433                 :      32761 :                     || MEM_P (op1))))
    2434                 :            :         {
    2435                 :      35508 :           enum rtx_code new_code = ix86_fp_swap_condition (code);
    2436                 :      35508 :           if (new_code != UNKNOWN)
    2437                 :            :             {
    2438                 :      23496 :               std::swap (op0, op1);
    2439                 :      23496 :               code = new_code;
    2440                 :            :             }
    2441                 :            :         }
    2442                 :            : 
    2443                 :     342760 :       if (!REG_P (op0))
    2444                 :      49164 :         op0 = force_reg (op_mode, op0);
    2445                 :            : 
    2446                 :     342760 :       if (CONSTANT_P (op1))
    2447                 :            :         {
    2448                 :     167654 :           int tmp = standard_80387_constant_p (op1);
    2449                 :     167654 :           if (tmp == 0)
    2450                 :      59952 :             op1 = validize_mem (force_const_mem (op_mode, op1));
    2451                 :     107702 :           else if (tmp == 1)
    2452                 :            :             {
    2453                 :      59394 :               if (TARGET_CMOVE)
    2454                 :      59394 :                 op1 = force_reg (op_mode, op1);
    2455                 :            :             }
    2456                 :            :           else
    2457                 :      48308 :             op1 = force_reg (op_mode, op1);
    2458                 :            :         }
    2459                 :            :     }
    2460                 :            : 
    2461                 :            :   /* Try to rearrange the comparison to make it cheaper.  */
    2462                 :     474372 :   if (ix86_fp_comparison_cost (code)
    2463                 :     474372 :       > ix86_fp_comparison_cost (swap_condition (code))
    2464                 :     474372 :       && (REG_P (op1) || can_create_pseudo_p ()))
    2465                 :            :     {
    2466                 :          0 :       std::swap (op0, op1);
    2467                 :          0 :       code = swap_condition (code);
    2468                 :          0 :       if (!REG_P (op0))
    2469                 :          0 :         op0 = force_reg (op_mode, op0);
    2470                 :            :     }
    2471                 :            : 
    2472                 :     474372 :   *pop0 = op0;
    2473                 :     474372 :   *pop1 = op1;
    2474                 :     474372 :   return code;
    2475                 :            : }
    2476                 :            : 
    2477                 :            : /* Generate insn patterns to do a floating point compare of OPERANDS.  */
    2478                 :            : 
    2479                 :            : static rtx
    2480                 :     474372 : ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
    2481                 :            : {
    2482                 :     474372 :   bool unordered_compare = ix86_unordered_fp_compare (code);
    2483                 :     474372 :   machine_mode cmp_mode;
    2484                 :     474372 :   rtx tmp, scratch;
    2485                 :            : 
    2486                 :     474372 :   code = ix86_prepare_fp_compare_args (code, &op0, &op1);
    2487                 :            : 
    2488                 :     474372 :   tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
    2489                 :     474372 :   if (unordered_compare)
    2490                 :     294416 :     tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
    2491                 :            : 
    2492                 :            :   /* Do fcomi/sahf based test when profitable.  */
    2493                 :     474372 :   switch (ix86_fp_comparison_strategy (code))
    2494                 :            :     {
    2495                 :     474372 :     case IX86_FPCMP_COMI:
    2496                 :     474372 :       cmp_mode = CCFPmode;
    2497                 :     474372 :       emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
    2498                 :     474372 :       break;
    2499                 :            : 
    2500                 :          0 :     case IX86_FPCMP_SAHF:
    2501                 :          0 :       cmp_mode = CCFPmode;
    2502                 :          0 :       tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
    2503                 :          0 :       scratch = gen_reg_rtx (HImode);
    2504                 :          0 :       emit_insn (gen_rtx_SET (scratch, tmp));
    2505                 :          0 :       emit_insn (gen_x86_sahf_1 (scratch));
    2506                 :          0 :       break;
    2507                 :            : 
    2508                 :          0 :     case IX86_FPCMP_ARITH:
    2509                 :          0 :       cmp_mode = CCNOmode;
    2510                 :          0 :       tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
    2511                 :          0 :       scratch = gen_reg_rtx (HImode);
    2512                 :          0 :       emit_insn (gen_rtx_SET (scratch, tmp));
    2513                 :            : 
    2514                 :            :       /* In the unordered case, we have to check C2 for NaN's, which
    2515                 :            :          doesn't happen to work out to anything nice combination-wise.
    2516                 :            :          So do some bit twiddling on the value we've got in AH to come
    2517                 :            :          up with an appropriate set of condition codes.  */
    2518                 :            : 
    2519                 :          0 :       switch (code)
    2520                 :            :         {
    2521                 :          0 :         case GT:
    2522                 :          0 :         case UNGT:
    2523                 :          0 :           if (code == GT || !TARGET_IEEE_FP)
    2524                 :            :             {
    2525                 :          0 :               emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
    2526                 :          0 :               code = EQ;
    2527                 :            :             }
    2528                 :            :           else
    2529                 :            :             {
    2530                 :          0 :               emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
    2531                 :          0 :               emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
    2532                 :          0 :               emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
    2533                 :          0 :               cmp_mode = CCmode;
    2534                 :          0 :               code = GEU;
    2535                 :            :             }
    2536                 :            :           break;
    2537                 :          0 :         case LT:
    2538                 :          0 :         case UNLT:
    2539                 :          0 :           if (code == LT && TARGET_IEEE_FP)
    2540                 :            :             {
    2541                 :          0 :               emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
    2542                 :          0 :               emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
    2543                 :          0 :               cmp_mode = CCmode;
    2544                 :          0 :               code = EQ;
    2545                 :            :             }
    2546                 :            :           else
    2547                 :            :             {
    2548                 :          0 :               emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx));
    2549                 :          0 :               code = NE;
    2550                 :            :             }
    2551                 :            :           break;
    2552                 :          0 :         case GE:
    2553                 :          0 :         case UNGE:
    2554                 :          0 :           if (code == GE || !TARGET_IEEE_FP)
    2555                 :            :             {
    2556                 :          0 :               emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)));
    2557                 :          0 :               code = EQ;
    2558                 :            :             }
    2559                 :            :           else
    2560                 :            :             {
    2561                 :          0 :               emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
    2562                 :          0 :               emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx));
    2563                 :          0 :               code = NE;
    2564                 :            :             }
    2565                 :            :           break;
    2566                 :          0 :         case LE:
    2567                 :          0 :         case UNLE:
    2568                 :          0 :           if (code == LE && TARGET_IEEE_FP)
    2569                 :            :             {
    2570                 :          0 :               emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
    2571                 :          0 :               emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
    2572                 :          0 :               emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
    2573                 :          0 :               cmp_mode = CCmode;
    2574                 :          0 :               code = LTU;
    2575                 :            :             }
    2576                 :            :           else
    2577                 :            :             {
    2578                 :          0 :               emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
    2579                 :          0 :               code = NE;
    2580                 :            :             }
    2581                 :            :           break;
    2582                 :          0 :         case EQ:
    2583                 :          0 :         case UNEQ:
    2584                 :          0 :           if (code == EQ && TARGET_IEEE_FP)
    2585                 :            :             {
    2586                 :          0 :               emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
    2587                 :          0 :               emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
    2588                 :          0 :               cmp_mode = CCmode;
    2589                 :          0 :               code = EQ;
    2590                 :            :             }
    2591                 :            :           else
    2592                 :            :             {
    2593                 :          0 :               emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
    2594                 :          0 :               code = NE;
    2595                 :            :             }
    2596                 :            :           break;
    2597                 :          0 :         case NE:
    2598                 :          0 :         case LTGT:
    2599                 :          0 :           if (code == NE && TARGET_IEEE_FP)
    2600                 :            :             {
    2601                 :          0 :               emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
    2602                 :          0 :               emit_insn (gen_xorqi_ext_1_cc (scratch, scratch,
    2603                 :            :                                              GEN_INT (0x40)));
    2604                 :          0 :               code = NE;
    2605                 :            :             }
    2606                 :            :           else
    2607                 :            :             {
    2608                 :          0 :               emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
    2609                 :          0 :               code = EQ;
    2610                 :            :             }
    2611                 :            :           break;
    2612                 :            : 
    2613                 :          0 :         case UNORDERED:
    2614                 :          0 :           emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
    2615                 :          0 :           code = NE;
    2616                 :          0 :           break;
    2617                 :          0 :         case ORDERED:
    2618                 :          0 :           emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
    2619                 :          0 :           code = EQ;
    2620                 :          0 :           break;
    2621                 :            : 
    2622                 :          0 :         default:
    2623                 :          0 :           gcc_unreachable ();
    2624                 :            :         }
    2625                 :            :         break;
    2626                 :            : 
    2627                 :          0 :     default:
    2628                 :          0 :       gcc_unreachable();
    2629                 :            :     }
    2630                 :            : 
    2631                 :            :   /* Return the test that should be put into the flags user, i.e.
    2632                 :            :      the bcc, scc, or cmov instruction.  */
    2633                 :     474372 :   return gen_rtx_fmt_ee (code, VOIDmode,
    2634                 :            :                          gen_rtx_REG (cmp_mode, FLAGS_REG),
    2635                 :            :                          const0_rtx);
    2636                 :            : }
    2637                 :            : 
    2638                 :            : /* Generate insn patterns to do an integer compare of OPERANDS.  */
    2639                 :            : 
    2640                 :            : static rtx
    2641                 :    4191350 : ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
    2642                 :            : {
    2643                 :    4191350 :   machine_mode cmpmode;
    2644                 :    4191350 :   rtx tmp, flags;
    2645                 :            : 
    2646                 :    4191350 :   cmpmode = SELECT_CC_MODE (code, op0, op1);
    2647                 :    4191350 :   flags = gen_rtx_REG (cmpmode, FLAGS_REG);
    2648                 :            : 
    2649                 :            :   /* This is very simple, but making the interface the same as in the
    2650                 :            :      FP case makes the rest of the code easier.  */
    2651                 :    4191350 :   tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
    2652                 :    4191350 :   emit_insn (gen_rtx_SET (flags, tmp));
    2653                 :            : 
    2654                 :            :   /* Return the test that should be put into the flags user, i.e.
    2655                 :            :      the bcc, scc, or cmov instruction.  */
    2656                 :    4191350 :   return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
    2657                 :            : }
    2658                 :            : 
    2659                 :            : static rtx
    2660                 :    4699180 : ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1)
    2661                 :            : {
    2662                 :    4699180 :   rtx ret;
    2663                 :            : 
    2664                 :    4699180 :   if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
    2665                 :      33787 :     ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
    2666                 :            : 
    2667                 :    4665400 :   else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
    2668                 :            :     {
    2669                 :     474044 :       gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
    2670                 :     474044 :       ret = ix86_expand_fp_compare (code, op0, op1);
    2671                 :            :     }
    2672                 :            :   else
    2673                 :    4191350 :     ret = ix86_expand_int_compare (code, op0, op1);
    2674                 :            : 
    2675                 :    4699180 :   return ret;
    2676                 :            : }
    2677                 :            : 
    2678                 :            : void
    2679                 :     319047 : ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1)
    2680                 :            : {
    2681                 :     319047 :   rtx ret;
    2682                 :            : 
    2683                 :     319047 :   gcc_assert (GET_MODE (dest) == QImode);
    2684                 :            : 
    2685                 :     319047 :   ret = ix86_expand_compare (code, op0, op1);
    2686                 :     319047 :   PUT_MODE (ret, QImode);
    2687                 :     319047 :   emit_insn (gen_rtx_SET (dest, ret));
    2688                 :     319047 : }
    2689                 :            : 
    2690                 :            : /* Expand comparison setting or clearing carry flag.  Return true when
    2691                 :            :    successful and set pop for the operation.  */
    2692                 :            : static bool
    2693                 :      16649 : ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
    2694                 :            : {
    2695                 :      33298 :   machine_mode mode
    2696                 :      16649 :     = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
    2697                 :            : 
    2698                 :            :   /* Do not handle double-mode compares that go through special path.  */
    2699                 :      17979 :   if (mode == (TARGET_64BIT ? TImode : DImode))
    2700                 :            :     return false;
    2701                 :            : 
    2702                 :      16649 :   if (SCALAR_FLOAT_MODE_P (mode))
    2703                 :            :     {
    2704                 :        332 :       rtx compare_op;
    2705                 :        332 :       rtx_insn *compare_seq;
    2706                 :            : 
    2707                 :        332 :       gcc_assert (!DECIMAL_FLOAT_MODE_P (mode));
    2708                 :            : 
    2709                 :            :       /* Shortcut:  following common codes never translate
    2710                 :            :          into carry flag compares.  */
    2711                 :        332 :       if (code == EQ || code == NE || code == UNEQ || code == LTGT
    2712                 :        330 :           || code == ORDERED || code == UNORDERED)
    2713                 :            :         return false;
    2714                 :            : 
    2715                 :            :       /* These comparisons require zero flag; swap operands so they won't.  */
    2716                 :        328 :       if ((code == GT || code == UNLE || code == LE || code == UNGT)
    2717                 :        242 :           && !TARGET_IEEE_FP)
    2718                 :            :         {
    2719                 :          4 :           std::swap (op0, op1);
    2720                 :          4 :           code = swap_condition (code);
    2721                 :            :         }
    2722                 :            : 
    2723                 :            :       /* Try to expand the comparison and verify that we end up with
    2724                 :            :          carry flag based comparison.  This fails to be true only when
    2725                 :            :          we decide to expand comparison using arithmetic that is not
    2726                 :            :          too common scenario.  */
    2727                 :        328 :       start_sequence ();
    2728                 :        328 :       compare_op = ix86_expand_fp_compare (code, op0, op1);
    2729                 :        328 :       compare_seq = get_insns ();
    2730                 :        328 :       end_sequence ();
    2731                 :            : 
    2732                 :        328 :       if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
    2733                 :        328 :         code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
    2734                 :            :       else
    2735                 :          0 :         code = GET_CODE (compare_op);
    2736                 :            : 
    2737                 :        328 :       if (code != LTU && code != GEU)
    2738                 :            :         return false;
    2739                 :            : 
    2740                 :         86 :       emit_insn (compare_seq);
    2741                 :         86 :       *pop = compare_op;
    2742                 :         86 :       return true;
    2743                 :            :     }
    2744                 :            : 
    2745                 :      16317 :   if (!INTEGRAL_MODE_P (mode))
    2746                 :            :     return false;
    2747                 :            : 
    2748                 :      16272 :   switch (code)
    2749                 :            :     {
    2750                 :            :     case LTU:
    2751                 :            :     case GEU:
    2752                 :            :       break;
    2753                 :            : 
    2754                 :            :     /* Convert a==0 into (unsigned)a<1.  */
    2755                 :      11794 :     case EQ:
    2756                 :      11794 :     case NE:
    2757                 :      11794 :       if (op1 != const0_rtx)
    2758                 :            :         return false;
    2759                 :       7354 :       op1 = const1_rtx;
    2760                 :       7354 :       code = (code == EQ ? LTU : GEU);
    2761                 :            :       break;
    2762                 :            : 
    2763                 :            :     /* Convert a>b into b<a or a>=b-1.  */
    2764                 :       1679 :     case GTU:
    2765                 :       1679 :     case LEU:
    2766                 :       1679 :       if (CONST_INT_P (op1))
    2767                 :            :         {
    2768                 :        135 :           op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
    2769                 :            :           /* Bail out on overflow.  We still can swap operands but that
    2770                 :            :              would force loading of the constant into register.  */
    2771                 :        135 :           if (op1 == const0_rtx
    2772                 :        135 :               || !x86_64_immediate_operand (op1, GET_MODE (op1)))
    2773                 :          0 :             return false;
    2774                 :        135 :           code = (code == GTU ? GEU : LTU);
    2775                 :            :         }
    2776                 :            :       else
    2777                 :            :         {
    2778                 :       1544 :           std::swap (op0, op1);
    2779                 :       1544 :           code = (code == GTU ? LTU : GEU);
    2780                 :            :         }
    2781                 :            :       break;
    2782                 :            : 
    2783                 :            :     /* Convert a>=0 into (unsigned)a<0x80000000.  */
    2784                 :        959 :     case LT:
    2785                 :        959 :     case GE:
    2786                 :        959 :       if (mode == DImode || op1 != const0_rtx)
    2787                 :            :         return false;
    2788                 :         84 :       op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
    2789                 :         42 :       code = (code == LT ? GEU : LTU);
    2790                 :            :       break;
    2791                 :       1205 :     case LE:
    2792                 :       1205 :     case GT:
    2793                 :       1205 :       if (mode == DImode || op1 != constm1_rtx)
    2794                 :            :         return false;
    2795                 :          0 :       op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
    2796                 :          0 :       code = (code == LE ? GEU : LTU);
    2797                 :            :       break;
    2798                 :            : 
    2799                 :            :     default:
    2800                 :            :       return false;
    2801                 :            :     }
    2802                 :            :   /* Swapping operands may cause constant to appear as first operand.  */
    2803                 :       9710 :   if (!nonimmediate_operand (op0, VOIDmode))
    2804                 :            :     {
    2805                 :        522 :       if (!can_create_pseudo_p ())
    2806                 :            :         return false;
    2807                 :        522 :       op0 = force_reg (mode, op0);
    2808                 :            :     }
    2809                 :       9710 :   *pop = ix86_expand_compare (code, op0, op1);
    2810                 :       9710 :   gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
    2811                 :            :   return true;
    2812                 :            : }
    2813                 :            : 
    2814                 :            : /* Expand conditional increment or decrement using adb/sbb instructions.
    2815                 :            :    The default case using setcc followed by the conditional move can be
    2816                 :            :    done by generic code.  */
    2817                 :            : bool
    2818                 :       7887 : ix86_expand_int_addcc (rtx operands[])
    2819                 :            : {
    2820                 :       7887 :   enum rtx_code code = GET_CODE (operands[1]);
    2821                 :       7887 :   rtx flags;
    2822                 :       7887 :   rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
    2823                 :       7887 :   rtx compare_op;
    2824                 :       7887 :   rtx val = const0_rtx;
    2825                 :       7887 :   bool fpcmp = false;
    2826                 :       7887 :   machine_mode mode;
    2827                 :       7887 :   rtx op0 = XEXP (operands[1], 0);
    2828                 :       7887 :   rtx op1 = XEXP (operands[1], 1);
    2829                 :            : 
    2830                 :       7887 :   if (operands[3] != const1_rtx
    2831                 :       4035 :       && operands[3] != constm1_rtx)
    2832                 :            :     return false;
    2833                 :       4286 :   if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
    2834                 :            :      return false;
    2835                 :       1384 :   code = GET_CODE (compare_op);
    2836                 :            : 
    2837                 :       1384 :   flags = XEXP (compare_op, 0);
    2838                 :            : 
    2839                 :       1384 :   if (GET_MODE (flags) == CCFPmode)
    2840                 :            :     {
    2841                 :          3 :       fpcmp = true;
    2842                 :          3 :       code = ix86_fp_compare_code_to_integer (code);
    2843                 :            :     }
    2844                 :            : 
    2845                 :       1384 :   if (code != LTU)
    2846                 :            :     {
    2847                 :       1027 :       val = constm1_rtx;
    2848                 :       1027 :       if (fpcmp)
    2849                 :          3 :         PUT_CODE (compare_op,
    2850                 :            :                   reverse_condition_maybe_unordered
    2851                 :            :                     (GET_CODE (compare_op)));
    2852                 :            :       else
    2853                 :       1024 :         PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
    2854                 :            :     }
    2855                 :            : 
    2856                 :       1384 :   mode = GET_MODE (operands[0]);
    2857                 :            : 
    2858                 :            :   /* Construct either adc or sbb insn.  */
    2859                 :       1384 :   if ((code == LTU) == (operands[3] == constm1_rtx))
    2860                 :            :     insn = gen_sub3_carry;
    2861                 :            :   else
    2862                 :        295 :     insn = gen_add3_carry;
    2863                 :            : 
    2864                 :       1384 :   emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
    2865                 :            : 
    2866                 :       1384 :   return true;
    2867                 :            : }
    2868                 :            : 
    2869                 :            : bool
    2870                 :     261148 : ix86_expand_int_movcc (rtx operands[])
    2871                 :            : {
    2872                 :     261148 :   enum rtx_code code = GET_CODE (operands[1]), compare_code;
    2873                 :     261148 :   rtx_insn *compare_seq;
    2874                 :     261148 :   rtx compare_op;
    2875                 :     261148 :   machine_mode mode = GET_MODE (operands[0]);
    2876                 :     261148 :   bool sign_bit_compare_p = false;
    2877                 :     261148 :   rtx op0 = XEXP (operands[1], 0);
    2878                 :     261148 :   rtx op1 = XEXP (operands[1], 1);
    2879                 :            : 
    2880                 :     261148 :   if (GET_MODE (op0) == TImode
    2881                 :     261144 :       || (GET_MODE (op0) == DImode
    2882                 :     102579 :           && !TARGET_64BIT))
    2883                 :            :     return false;
    2884                 :            : 
    2885                 :     261144 :   start_sequence ();
    2886                 :     261144 :   compare_op = ix86_expand_compare (code, op0, op1);
    2887                 :     261144 :   compare_seq = get_insns ();
    2888                 :     261144 :   end_sequence ();
    2889                 :            : 
    2890                 :     261144 :   compare_code = GET_CODE (compare_op);
    2891                 :            : 
    2892                 :     261144 :   if ((op1 == const0_rtx && (code == GE || code == LT))
    2893                 :     230102 :       || (op1 == constm1_rtx && (code == GT || code == LE)))
    2894                 :      31042 :     sign_bit_compare_p = true;
    2895                 :            : 
    2896                 :            :   /* Don't attempt mode expansion here -- if we had to expand 5 or 6
    2897                 :            :      HImode insns, we'd be swallowed in word prefix ops.  */
    2898                 :            : 
    2899                 :       3348 :   if ((mode != HImode || TARGET_FAST_PREFIX)
    2900                 :     293630 :       && (mode != (TARGET_64BIT ? TImode : DImode))
    2901                 :     261144 :       && CONST_INT_P (operands[2])
    2902                 :     274419 :       && CONST_INT_P (operands[3]))
    2903                 :            :     {
    2904                 :      12959 :       rtx out = operands[0];
    2905                 :      12959 :       HOST_WIDE_INT ct = INTVAL (operands[2]);
    2906                 :      12959 :       HOST_WIDE_INT cf = INTVAL (operands[3]);
    2907                 :      12959 :       HOST_WIDE_INT diff;
    2908                 :            : 
    2909                 :      12959 :       diff = ct - cf;
    2910                 :            :       /*  Sign bit compares are better done using shifts than we do by using
    2911                 :            :           sbb.  */
    2912                 :      12959 :       if (sign_bit_compare_p
    2913                 :      12959 :           || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
    2914                 :            :         {
    2915                 :            :           /* Detect overlap between destination and compare sources.  */
    2916                 :       9008 :           rtx tmp = out;
    2917                 :            : 
    2918                 :       9008 :           if (!sign_bit_compare_p)
    2919                 :            :             {
    2920                 :       8412 :               rtx flags;
    2921                 :       8412 :               bool fpcmp = false;
    2922                 :            : 
    2923                 :       8412 :               compare_code = GET_CODE (compare_op);
    2924                 :            : 
    2925                 :       8412 :               flags = XEXP (compare_op, 0);
    2926                 :            : 
    2927                 :       8412 :               if (GET_MODE (flags) == CCFPmode)
    2928                 :            :                 {
    2929                 :         83 :                   fpcmp = true;
    2930                 :         83 :                   compare_code
    2931                 :         83 :                     = ix86_fp_compare_code_to_integer (compare_code);
    2932                 :            :                 }
    2933                 :            : 
    2934                 :            :               /* To simplify rest of code, restrict to the GEU case.  */
    2935                 :       8412 :               if (compare_code == LTU)
    2936                 :            :                 {
    2937                 :       5899 :                   std::swap (ct, cf);
    2938                 :       5899 :                   compare_code = reverse_condition (compare_code);
    2939                 :       5899 :                   code = reverse_condition (code);
    2940                 :            :                 }
    2941                 :            :               else
    2942                 :            :                 {
    2943                 :       2513 :                   if (fpcmp)
    2944                 :         83 :                     PUT_CODE (compare_op,
    2945                 :            :                               reverse_condition_maybe_unordered
    2946                 :            :                                 (GET_CODE (compare_op)));
    2947                 :            :                   else
    2948                 :       2430 :                     PUT_CODE (compare_op,
    2949                 :            :                               reverse_condition (GET_CODE (compare_op)));
    2950                 :            :                 }
    2951                 :       8412 :               diff = ct - cf;
    2952                 :            : 
    2953                 :       8412 :               if (reg_overlap_mentioned_p (out, op0)
    2954                 :       8412 :                   || reg_overlap_mentioned_p (out, op1))
    2955                 :         32 :                 tmp = gen_reg_rtx (mode);
    2956                 :            : 
    2957                 :       8412 :               if (mode == DImode)
    2958                 :       1668 :                 emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
    2959                 :            :               else
    2960                 :       6744 :                 emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp),
    2961                 :            :                                                  flags, compare_op));
    2962                 :            :             }
    2963                 :            :           else
    2964                 :            :             {
    2965                 :        596 :               if (code == GT || code == GE)
    2966                 :        291 :                 code = reverse_condition (code);
    2967                 :            :               else
    2968                 :            :                 {
    2969                 :        305 :                   std::swap (ct, cf);
    2970                 :        305 :                   diff = ct - cf;
    2971                 :            :                 }
    2972                 :        596 :               tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
    2973                 :            :             }
    2974                 :            : 
    2975                 :       9008 :           if (diff == 1)
    2976                 :            :             {
    2977                 :            :               /*
    2978                 :            :                * cmpl op0,op1
    2979                 :            :                * sbbl dest,dest
    2980                 :            :                * [addl dest, ct]
    2981                 :            :                *
    2982                 :            :                * Size 5 - 8.
    2983                 :            :                */
    2984                 :       3532 :               if (ct)
    2985                 :        595 :                 tmp = expand_simple_binop (mode, PLUS,
    2986                 :            :                                            tmp, GEN_INT (ct),
    2987                 :            :                                            copy_rtx (tmp), 1, OPTAB_DIRECT);
    2988                 :            :             }
    2989                 :       5476 :           else if (cf == -1)
    2990                 :            :             {
    2991                 :            :               /*
    2992                 :            :                * cmpl op0,op1
    2993                 :            :                * sbbl dest,dest
    2994                 :            :                * orl $ct, dest
    2995                 :            :                *
    2996                 :            :                * Size 8.
    2997                 :            :                */
    2998                 :        440 :               tmp = expand_simple_binop (mode, IOR,
    2999                 :            :                                          tmp, GEN_INT (ct),
    3000                 :            :                                          copy_rtx (tmp), 1, OPTAB_DIRECT);
    3001                 :            :             }
    3002                 :       5036 :           else if (diff == -1 && ct)
    3003                 :            :             {
    3004                 :            :               /*
    3005                 :            :                * cmpl op0,op1
    3006                 :            :                * sbbl dest,dest
    3007                 :            :                * notl dest
    3008                 :            :                * [addl dest, cf]
    3009                 :            :                *
    3010                 :            :                * Size 8 - 11.
    3011                 :            :                */
    3012                 :        998 :               tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
    3013                 :        998 :               if (cf)
    3014                 :        297 :                 tmp = expand_simple_binop (mode, PLUS,
    3015                 :            :                                            copy_rtx (tmp), GEN_INT (cf),
    3016                 :            :                                            copy_rtx (tmp), 1, OPTAB_DIRECT);
    3017                 :            :             }
    3018                 :            :           else
    3019                 :            :             {
    3020                 :            :               /*
    3021                 :            :                * cmpl op0,op1
    3022                 :            :                * sbbl dest,dest
    3023                 :            :                * [notl dest]
    3024                 :            :                * andl cf - ct, dest
    3025                 :            :                * [addl dest, ct]
    3026                 :            :                *
    3027                 :            :                * Size 8 - 11.
    3028                 :            :                */
    3029                 :            : 
    3030                 :       4038 :               if (cf == 0)
    3031                 :            :                 {
    3032                 :       1265 :                   cf = ct;
    3033                 :       1265 :                   ct = 0;
    3034                 :       1265 :                   tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
    3035                 :            :                 }
    3036                 :            : 
    3037                 :       4038 :               tmp = expand_simple_binop (mode, AND,
    3038                 :            :                                          copy_rtx (tmp),
    3039                 :       4038 :                                          gen_int_mode (cf - ct, mode),
    3040                 :            :                                          copy_rtx (tmp), 1, OPTAB_DIRECT);
    3041                 :       4038 :               if (ct)
    3042                 :       2241 :                 tmp = expand_simple_binop (mode, PLUS,
    3043                 :            :                                            copy_rtx (tmp), GEN_INT (ct),
    3044                 :            :                                            copy_rtx (tmp), 1, OPTAB_DIRECT);
    3045                 :            :             }
    3046                 :            : 
    3047                 :       9008 :           if (!rtx_equal_p (tmp, out))
    3048                 :         97 :             emit_move_insn (copy_rtx (out), copy_rtx (tmp));
    3049                 :            : 
    3050                 :       9008 :           return true;
    3051                 :            :         }
    3052                 :            : 
    3053                 :       3951 :       if (diff < 0)
    3054                 :            :         {
    3055                 :       2699 :           machine_mode cmp_mode = GET_MODE (op0);
    3056                 :       2699 :           enum rtx_code new_code;
    3057                 :            : 
    3058                 :       2699 :           if (SCALAR_FLOAT_MODE_P (cmp_mode))
    3059                 :            :             {
    3060                 :         70 :               gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
    3061                 :            : 
    3062                 :            :               /* We may be reversing unordered compare to normal compare, that
    3063                 :            :                  is not valid in general (we may convert non-trapping condition
    3064                 :            :                  to trapping one), however on i386 we currently emit all
    3065                 :            :                  comparisons unordered.  */
    3066                 :         70 :               new_code = reverse_condition_maybe_unordered (code);
    3067                 :            :             }
    3068                 :            :           else
    3069                 :       2629 :             new_code = ix86_reverse_condition (code, cmp_mode);
    3070                 :       2699 :           if (new_code != UNKNOWN)
    3071                 :            :             {
    3072                 :       2699 :               std::swap (ct, cf);
    3073                 :       2699 :               diff = -diff;
    3074                 :       2699 :               code = new_code;
    3075                 :            :             }
    3076                 :            :         }
    3077                 :            : 
    3078                 :       3951 :       compare_code = UNKNOWN;
    3079                 :       3951 :       if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
    3080                 :       3814 :           && CONST_INT_P (op1))
    3081                 :            :         {
    3082                 :       1740 :           if (op1 == const0_rtx
    3083                 :        111 :               && (code == LT || code == GE))
    3084                 :            :             compare_code = code;
    3085                 :       1740 :           else if (op1 == constm1_rtx)
    3086                 :            :             {
    3087                 :        124 :               if (code == LE)
    3088                 :            :                 compare_code = LT;
    3089                 :        124 :               else if (code == GT)
    3090                 :            :                 compare_code = GE;
    3091                 :            :             }
    3092                 :            :         }
    3093                 :            : 
    3094                 :            :       /* Optimize dest = (op0 < 0) ? -1 : cf.  */
    3095                 :          0 :       if (compare_code != UNKNOWN
    3096                 :          0 :           && GET_MODE (op0) == GET_MODE (out)
    3097                 :          0 :           && (cf == -1 || ct == -1))
    3098                 :            :         {
    3099                 :            :           /* If lea code below could be used, only optimize
    3100                 :            :              if it results in a 2 insn sequence.  */
    3101                 :            : 
    3102                 :          0 :           if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
    3103                 :          0 :                  || diff == 3 || diff == 5 || diff == 9)
    3104                 :          0 :               || (compare_code == LT && ct == -1)
    3105                 :          0 :               || (compare_code == GE && cf == -1))
    3106                 :            :             {
    3107                 :            :               /*
    3108                 :            :                * notl op1       (if necessary)
    3109                 :            :                * sarl $31, op1
    3110                 :            :                * orl cf, op1
    3111                 :            :                */
    3112                 :          0 :               if (ct != -1)
    3113                 :            :                 {
    3114                 :          0 :                   cf = ct;
    3115                 :          0 :                   ct = -1;
    3116                 :          0 :                   code = reverse_condition (code);
    3117                 :            :                 }
    3118                 :            : 
    3119                 :          0 :               out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
    3120                 :            : 
    3121                 :          0 :               out = expand_simple_binop (mode, IOR,
    3122                 :            :                                          out, GEN_INT (cf),
    3123                 :            :                                          out, 1, OPTAB_DIRECT);
    3124                 :          0 :               if (out != operands[0])
    3125                 :          0 :                 emit_move_insn (operands[0], out);
    3126                 :            : 
    3127                 :          0 :               return true;
    3128                 :            :             }
    3129                 :            :         }
    3130                 :            : 
    3131                 :            : 
    3132                 :       4863 :       if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
    3133                 :        912 :            || diff == 3 || diff == 5 || diff == 9)
    3134                 :       3165 :           && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
    3135                 :       7116 :           && (mode != DImode
    3136                 :        468 :               || x86_64_immediate_operand (GEN_INT (cf), VOIDmode)))
    3137                 :            :         {
    3138                 :            :           /*
    3139                 :            :            * xorl dest,dest
    3140                 :            :            * cmpl op1,op2
    3141                 :            :            * setcc dest
    3142                 :            :            * lea cf(dest*(ct-cf)),dest
    3143                 :            :            *
    3144                 :            :            * Size 14.
    3145                 :            :            *
    3146                 :            :            * This also catches the degenerate setcc-only case.
    3147                 :            :            */
    3148                 :            : 
    3149                 :       3165 :           rtx tmp;
    3150                 :       3165 :           int nops;
    3151                 :            : 
    3152                 :       3165 :           out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
    3153                 :            : 
    3154                 :       3165 :           nops = 0;
    3155                 :            :           /* On x86_64 the lea instruction operates on Pmode, so we need
    3156                 :            :              to get arithmetics done in proper mode to match.  */
    3157                 :       3165 :           if (diff == 1)
    3158                 :       2473 :             tmp = copy_rtx (out);
    3159                 :            :           else
    3160                 :            :             {
    3161                 :        692 :               rtx out1;
    3162                 :        692 :               out1 = copy_rtx (out);
    3163                 :        692 :               tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
    3164                 :        692 :               nops++;
    3165                 :        692 :               if (diff & 1)
    3166                 :            :                 {
    3167                 :         98 :                   tmp = gen_rtx_PLUS (mode, tmp, out1);
    3168                 :         98 :                   nops++;
    3169                 :            :                 }
    3170                 :            :             }
    3171                 :       3165 :           if (cf != 0)
    3172                 :            :             {
    3173                 :       2284 :               tmp = gen_rtx_PLUS (mode, tmp, GEN_INT (cf));
    3174                 :       2284 :               nops++;
    3175                 :            :             }
    3176                 :       3165 :           if (!rtx_equal_p (tmp, out))
    3177                 :            :             {
    3178                 :       2408 :               if (nops == 1)
    3179                 :       1796 :                 out = force_operand (tmp, copy_rtx (out));
    3180                 :            :               else
    3181                 :        612 :                 emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp)));
    3182                 :            :             }
    3183                 :       3165 :           if (!rtx_equal_p (out, operands[0]))
    3184                 :        702 :             emit_move_insn (operands[0], copy_rtx (out));
    3185                 :            : 
    3186                 :       3165 :           return true;
    3187                 :            :         }
    3188                 :            : 
    3189                 :            :       /*
    3190                 :            :        * General case:                  Jumpful:
    3191                 :            :        *   xorl dest,dest               cmpl op1, op2
    3192                 :            :        *   cmpl op1, op2                movl ct, dest
    3193                 :            :        *   setcc dest                   jcc 1f
    3194                 :            :        *   decl dest                    movl cf, dest
    3195                 :            :        *   andl (cf-ct),dest            1:
    3196                 :            :        *   addl ct,dest
    3197                 :            :        *
    3198                 :            :        * Size 20.                       Size 14.
    3199                 :            :        *
    3200                 :            :        * This is reasonably steep, but branch mispredict costs are
    3201                 :            :        * high on modern cpus, so consider failing only if optimizing
    3202                 :            :        * for space.
    3203                 :            :        */
    3204                 :            : 
    3205                 :        786 :       if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
    3206                 :        786 :           && BRANCH_COST (optimize_insn_for_speed_p (),
    3207                 :            :                           false) >= 2)
    3208                 :            :         {
    3209                 :          0 :           if (cf == 0)
    3210                 :            :             {
    3211                 :          0 :               machine_mode cmp_mode = GET_MODE (op0);
    3212                 :          0 :               enum rtx_code new_code;
    3213                 :            : 
    3214                 :          0 :               if (SCALAR_FLOAT_MODE_P (cmp_mode))
    3215                 :            :                 {
    3216                 :          0 :                   gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
    3217                 :            : 
    3218                 :            :                   /* We may be reversing unordered compare to normal compare,
    3219                 :            :                      that is not valid in general (we may convert non-trapping
    3220                 :            :                      condition to trapping one), however on i386 we currently
    3221                 :            :                      emit all comparisons unordered.  */
    3222                 :          0 :                   new_code = reverse_condition_maybe_unordered (code);
    3223                 :            :                 }
    3224                 :            :               else
    3225                 :            :                 {
    3226                 :          0 :                   new_code = ix86_reverse_condition (code, cmp_mode);
    3227                 :          0 :                   if (compare_code != UNKNOWN && new_code != UNKNOWN)
    3228                 :          0 :                     compare_code = reverse_condition (compare_code);
    3229                 :            :                 }
    3230                 :            : 
    3231                 :          0 :               if (new_code != UNKNOWN)
    3232                 :            :                 {
    3233                 :          0 :                   cf = ct;
    3234                 :          0 :                   ct = 0;
    3235                 :          0 :                   code = new_code;
    3236                 :            :                 }
    3237                 :            :             }
    3238                 :            : 
    3239                 :          0 :           if (compare_code != UNKNOWN)
    3240                 :            :             {
    3241                 :            :               /* notl op1       (if needed)
    3242                 :            :                  sarl $31, op1
    3243                 :            :                  andl (cf-ct), op1
    3244                 :            :                  addl ct, op1
    3245                 :            : 
    3246                 :            :                  For x < 0 (resp. x <= -1) there will be no notl,
    3247                 :            :                  so if possible swap the constants to get rid of the
    3248                 :            :                  complement.
    3249                 :            :                  True/false will be -1/0 while code below (store flag
    3250                 :            :                  followed by decrement) is 0/-1, so the constants need
    3251                 :            :                  to be exchanged once more.  */
    3252                 :            : 
    3253                 :          0 :               if (compare_code == GE || !cf)
    3254                 :            :                 {
    3255                 :          0 :                   code = reverse_condition (code);
    3256                 :          0 :                   compare_code = LT;
    3257                 :            :                 }
    3258                 :            :               else
    3259                 :          0 :                 std::swap (ct, cf);
    3260                 :            : 
    3261                 :          0 :               out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
    3262                 :            :             }
    3263                 :            :           else
    3264                 :            :             {
    3265                 :          0 :               out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
    3266                 :            : 
    3267                 :          0 :               out = expand_simple_binop (mode, PLUS, copy_rtx (out),
    3268                 :            :                                          constm1_rtx,
    3269                 :            :                                          copy_rtx (out), 1, OPTAB_DIRECT);
    3270                 :            :             }
    3271                 :            : 
    3272                 :          0 :           out = expand_simple_binop (mode, AND, copy_rtx (out),
    3273                 :          0 :                                      gen_int_mode (cf - ct, mode),
    3274                 :            :                                      copy_rtx (out), 1, OPTAB_DIRECT);
    3275                 :          0 :           if (ct)
    3276                 :          0 :             out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
    3277                 :            :                                        copy_rtx (out), 1, OPTAB_DIRECT);
    3278                 :          0 :           if (!rtx_equal_p (out, operands[0]))
    3279                 :          0 :             emit_move_insn (operands[0], copy_rtx (out));
    3280                 :            : 
    3281                 :          0 :           return true;
    3282                 :            :         }
    3283                 :            :     }
    3284                 :            : 
    3285                 :     248971 :   if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
    3286                 :            :     {
    3287                 :            :       /* Try a few things more with specific constants and a variable.  */
    3288                 :            : 
    3289                 :       5628 :       optab op;
    3290                 :       5628 :       rtx var, orig_out, out, tmp;
    3291                 :            : 
    3292                 :       5628 :       if (BRANCH_COST (optimize_insn_for_speed_p (), false) <= 2)
    3293                 :            :         return false;
    3294                 :            : 
    3295                 :            :       /* If one of the two operands is an interesting constant, load a
    3296                 :            :          constant with the above and mask it in with a logical operation.  */
    3297                 :            : 
    3298                 :       5628 :       if (CONST_INT_P (operands[2]))
    3299                 :            :         {
    3300                 :        259 :           var = operands[3];
    3301                 :        259 :           if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
    3302                 :          0 :             operands[3] = constm1_rtx, op = and_optab;
    3303                 :        259 :           else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
    3304                 :          0 :             operands[3] = const0_rtx, op = ior_optab;
    3305                 :            :           else
    3306                 :            :             return false;
    3307                 :            :         }
    3308                 :       5369 :       else if (CONST_INT_P (operands[3]))
    3309                 :            :         {
    3310                 :        303 :           var = operands[2];
    3311                 :        303 :           if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
    3312                 :         34 :             operands[2] = constm1_rtx, op = and_optab;
    3313                 :        269 :           else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
    3314                 :         10 :             operands[2] = const0_rtx, op = ior_optab;
    3315                 :            :           else
    3316                 :            :             return false;
    3317                 :            :         }
    3318                 :            :       else
    3319                 :            :         return false;
    3320                 :            : 
    3321                 :         44 :       orig_out = operands[0];
    3322                 :         44 :       tmp = gen_reg_rtx (mode);
    3323                 :         44 :       operands[0] = tmp;
    3324                 :            : 
    3325                 :            :       /* Recurse to get the constant loaded.  */
    3326                 :         44 :       if (!ix86_expand_int_movcc (operands))
    3327                 :            :         return false;
    3328                 :            : 
    3329                 :            :       /* Mask in the interesting variable.  */
    3330                 :         44 :       out = expand_binop (mode, op, var, tmp, orig_out, 0,
    3331                 :            :                           OPTAB_WIDEN);
    3332                 :         44 :       if (!rtx_equal_p (out, orig_out))
    3333                 :          0 :         emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
    3334                 :            : 
    3335                 :         44 :       return true;
    3336                 :            :     }
    3337                 :            : 
    3338                 :            :   /*
    3339                 :            :    * For comparison with above,
    3340                 :            :    *
    3341                 :            :    * movl cf,dest
    3342                 :            :    * movl ct,tmp
    3343                 :            :    * cmpl op1,op2
    3344                 :            :    * cmovcc tmp,dest
    3345                 :            :    *
    3346                 :            :    * Size 15.
    3347                 :            :    */
    3348                 :            : 
    3349                 :     243343 :   if (! nonimmediate_operand (operands[2], mode))
    3350                 :       5259 :     operands[2] = force_reg (mode, operands[2]);
    3351                 :     243343 :   if (! nonimmediate_operand (operands[3], mode))
    3352                 :     131748 :     operands[3] = force_reg (mode, operands[3]);
    3353                 :            : 
    3354                 :     243343 :   if (! register_operand (operands[2], VOIDmode)
    3355                 :     243343 :       && (mode == QImode
    3356                 :       3322 :           || ! register_operand (operands[3], VOIDmode)))
    3357                 :       1561 :     operands[2] = force_reg (mode, operands[2]);
    3358                 :            : 
    3359                 :     243343 :   if (mode == QImode
    3360                 :     243343 :       && ! register_operand (operands[3], VOIDmode))
    3361                 :        592 :     operands[3] = force_reg (mode, operands[3]);
    3362                 :            : 
    3363                 :     243343 :   emit_insn (compare_seq);
    3364                 :     243343 :   emit_insn (gen_rtx_SET (operands[0],
    3365                 :            :                           gen_rtx_IF_THEN_ELSE (mode,
    3366                 :            :                                                 compare_op, operands[2],
    3367                 :            :                                                 operands[3])));
    3368                 :     243343 :   return true;
    3369                 :            : }
    3370                 :            : 
    3371                 :            : /* Detect conditional moves that exactly match min/max operational
    3372                 :            :    semantics.  Note that this is IEEE safe, as long as we don't
    3373                 :            :    interchange the operands.
    3374                 :            : 
    3375                 :            :    Returns FALSE if this conditional move doesn't match a MIN/MAX,
    3376                 :            :    and TRUE if the operation is successful and instructions are emitted.  */
    3377                 :            : 
    3378                 :            : static bool
    3379                 :       7599 : ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
    3380                 :            :                            rtx cmp_op1, rtx if_true, rtx if_false)
    3381                 :            : {
    3382                 :       7599 :   machine_mode mode;
    3383                 :       7599 :   bool is_min;
    3384                 :       7599 :   rtx tmp;
    3385                 :            : 
    3386                 :       7599 :   if (code == LT)
    3387                 :            :     ;
    3388                 :       3902 :   else if (code == UNGE)
    3389                 :       5246 :     std::swap (if_true, if_false);
    3390                 :            :   else
    3391                 :            :     return false;
    3392                 :            : 
    3393                 :       5246 :   if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
    3394                 :            :     is_min = true;
    3395                 :       3763 :   else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false))
    3396                 :            :     is_min = false;
    3397                 :            :   else
    3398                 :       1820 :     return false;
    3399                 :            : 
    3400                 :       3426 :   mode = GET_MODE (dest);
    3401                 :            : 
    3402                 :            :   /* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here,
    3403                 :            :      but MODE may be a vector mode and thus not appropriate.  */
    3404                 :       3426 :   if (!flag_finite_math_only || flag_signed_zeros)
    3405                 :            :     {
    3406                 :       3426 :       int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
    3407                 :       3426 :       rtvec v;
    3408                 :            : 
    3409                 :       3426 :       if_true = force_reg (mode, if_true);
    3410                 :       3426 :       v = gen_rtvec (2, if_true, if_false);
    3411                 :       3426 :       tmp = gen_rtx_UNSPEC (mode, v, u);
    3412                 :            :     }
    3413                 :            :   else
    3414                 :            :     {
    3415                 :          0 :       code = is_min ? SMIN : SMAX;
    3416                 :          0 :       if (MEM_P (if_true) && MEM_P (if_false))
    3417                 :          0 :         if_true = force_reg (mode, if_true);
    3418                 :          0 :       tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false);
    3419                 :            :     }
    3420                 :            : 
    3421                 :       3426 :   emit_insn (gen_rtx_SET (dest, tmp));
    3422                 :       3426 :   return true;
    3423                 :            : }
    3424                 :            : 
    3425                 :            : /* Return true if MODE is valid for vector compare to mask register,
    3426                 :            :    Same result for conditionl vector move with mask register.  */
    3427                 :            : static bool
    3428                 :      20013 : ix86_valid_mask_cmp_mode (machine_mode mode)
    3429                 :            : {
    3430                 :            :   /* XOP has its own vector conditional movement.  */
    3431                 :      20013 :   if (TARGET_XOP && !TARGET_AVX512F)
    3432                 :            :     return false;
    3433                 :            : 
    3434                 :            :   /* AVX512F is needed for mask operation.  */
    3435                 :      20001 :   if (!(TARGET_AVX512F && VECTOR_MODE_P (mode)))
    3436                 :            :     return false;
    3437                 :            : 
    3438                 :            :   /* AVX512BW is needed for vector QI/HImode,
    3439                 :            :      AVX512VL is needed for 128/256-bit vector.  */
    3440                 :       3738 :   machine_mode inner_mode = GET_MODE_INNER (mode);
    3441                 :       1869 :   int vector_size = GET_MODE_SIZE (mode);
    3442                 :       1869 :   if ((inner_mode == QImode || inner_mode == HImode) && !TARGET_AVX512BW)
    3443                 :            :     return false;
    3444                 :            : 
    3445                 :       1833 :   return vector_size == 64 || TARGET_AVX512VL;
    3446                 :            : }
    3447                 :            : 
    3448                 :            : /* Expand an SSE comparison.  Return the register with the result.  */
    3449                 :            : 
    3450                 :            : static rtx
    3451                 :      15076 : ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
    3452                 :            :                      rtx op_true, rtx op_false)
    3453                 :            : {
    3454                 :      15076 :   machine_mode mode = GET_MODE (dest);
    3455                 :      15076 :   machine_mode cmp_ops_mode = GET_MODE (cmp_op0);
    3456                 :            : 
    3457                 :            :   /* In general case result of comparison can differ from operands' type.  */
    3458                 :      15076 :   machine_mode cmp_mode;
    3459                 :            : 
    3460                 :            :   /* In AVX512F the result of comparison is an integer mask.  */
    3461                 :      15076 :   bool maskcmp = false;
    3462                 :      15076 :   rtx x;
    3463                 :            : 
    3464                 :      15076 :   if (ix86_valid_mask_cmp_mode (cmp_ops_mode))
    3465                 :            :     {
    3466                 :        567 :       unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
    3467                 :        567 :       maskcmp = true;
    3468                 :        893 :       cmp_mode = nbits > 8 ? int_mode_for_size (nbits, 0).require () : E_QImode;
    3469                 :            :     }
    3470                 :            :   else
    3471                 :            :     cmp_mode = cmp_ops_mode;
    3472                 :            : 
    3473                 :      15076 :   cmp_op0 = force_reg (cmp_ops_mode, cmp_op0);
    3474                 :            : 
    3475                 :      30152 :   int (*op1_predicate)(rtx, machine_mode)
    3476                 :      15076 :     = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand;
    3477                 :            : 
    3478                 :      15076 :   if (!op1_predicate (cmp_op1, cmp_ops_mode))
    3479                 :        490 :     cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
    3480                 :            : 
    3481                 :      15076 :   if (optimize
    3482                 :        336 :       || (maskcmp && cmp_mode != mode)
    3483                 :        274 :       || (op_true && reg_overlap_mentioned_p (dest, op_true))
    3484                 :      15350 :       || (op_false && reg_overlap_mentioned_p (dest, op_false)))
    3485                 :      29037 :     dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
    3486                 :            : 
    3487                 :      15076 :   x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
    3488                 :            : 
    3489                 :      15076 :   if (cmp_mode != mode && !maskcmp)
    3490                 :            :     {
    3491                 :       5004 :       x = force_reg (cmp_ops_mode, x);
    3492                 :       5004 :       convert_move (dest, x, false);
    3493                 :            :     }
    3494                 :            :   else
    3495                 :      10072 :     emit_insn (gen_rtx_SET (dest, x));
    3496                 :            : 
    3497                 :      15076 :   return dest;
    3498                 :            : }
    3499                 :            : 
    3500                 :            : /* Expand DEST = CMP ? OP_TRUE : OP_FALSE into a sequence of logical
    3501                 :            :    operations.  This is used for both scalar and vector conditional moves.  */
    3502                 :            : 
    3503                 :            : void
    3504                 :      10003 : ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
    3505                 :            : {
    3506                 :      10003 :   machine_mode mode = GET_MODE (dest);
    3507                 :      10003 :   machine_mode cmpmode = GET_MODE (cmp);
    3508                 :            : 
    3509                 :            :   /* In AVX512F the result of comparison is an integer mask.  */
    3510                 :      10003 :   bool maskcmp = mode != cmpmode && ix86_valid_mask_cmp_mode (mode);
    3511                 :            : 
    3512                 :      10003 :   rtx t2, t3, x;
    3513                 :            : 
    3514                 :            :   /* If we have an integer mask and FP value then we need
    3515                 :            :      to cast mask to FP mode.  */
    3516                 :      10003 :   if (mode != cmpmode && VECTOR_MODE_P (cmpmode))
    3517                 :            :     {
    3518                 :         58 :       cmp = force_reg (cmpmode, cmp);
    3519                 :         58 :       cmp = gen_rtx_SUBREG (mode, cmp, 0);
    3520                 :            :     }
    3521                 :            : 
    3522                 :      10003 :   if (maskcmp)
    3523                 :            :     {
    3524                 :            :       /* Using vector move with mask register.  */
    3525                 :        567 :       cmp = force_reg (cmpmode, cmp);
    3526                 :            :       /* Optimize for mask zero.  */
    3527                 :       1134 :       op_true = (op_true != CONST0_RTX (mode)
    3528                 :        567 :                  ? force_reg (mode, op_true) : op_true);
    3529                 :       1134 :       op_false = (op_false != CONST0_RTX (mode)
    3530                 :        567 :                   ? force_reg (mode, op_false) : op_false);
    3531                 :        567 :       if (op_true == CONST0_RTX (mode))
    3532                 :            :         {
    3533                 :          1 :           rtx (*gen_not) (rtx, rtx);
    3534                 :          1 :           switch (cmpmode)
    3535                 :            :             {
    3536                 :            :             case E_QImode: gen_not = gen_knotqi; break;
    3537                 :          0 :             case E_HImode: gen_not = gen_knothi; break;
    3538                 :          0 :             case E_SImode: gen_not = gen_knotsi; break;
    3539                 :          0 :             case E_DImode: gen_not = gen_knotdi; break;
    3540                 :          0 :             default: gcc_unreachable ();
    3541                 :            :             }
    3542                 :          1 :           rtx n = gen_reg_rtx (cmpmode);
    3543                 :          1 :           emit_insn (gen_not (n, cmp));
    3544                 :          1 :           cmp = n;
    3545                 :            :           /* Reverse op_true op_false.  */
    3546                 :          1 :           std::swap (op_true, op_false);
    3547                 :            :         }
    3548                 :            : 
    3549                 :        567 :       rtx vec_merge = gen_rtx_VEC_MERGE (mode, op_true, op_false, cmp);
    3550                 :        567 :       emit_insn (gen_rtx_SET (dest, vec_merge));
    3551                 :        567 :       return;
    3552                 :            :     }
    3553                 :       9436 :   else if (vector_all_ones_operand (op_true, mode)
    3554                 :       9436 :            && op_false == CONST0_RTX (mode))
    3555                 :            :     {
    3556                 :       1065 :       emit_insn (gen_rtx_SET (dest, cmp));
    3557                 :       1065 :       return;
    3558                 :            :     }
    3559                 :       8371 :   else if (op_false == CONST0_RTX (mode))
    3560                 :            :     {
    3561                 :       3012 :       op_true = force_reg (mode, op_true);
    3562                 :       3012 :       x = gen_rtx_AND (mode, cmp, op_true);
    3563                 :       3012 :       emit_insn (gen_rtx_SET (dest, x));
    3564                 :       3012 :       return;
    3565                 :            :     }
    3566                 :       5359 :   else if (op_true == CONST0_RTX (mode))
    3567                 :            :     {
    3568                 :        883 :       op_false = force_reg (mode, op_false);
    3569                 :        883 :       x = gen_rtx_NOT (mode, cmp);
    3570                 :        883 :       x = gen_rtx_AND (mode, x, op_false);
    3571                 :        883 :       emit_insn (gen_rtx_SET (dest, x));
    3572                 :        883 :       return;
    3573                 :            :     }
    3574                 :       4476 :   else if (INTEGRAL_MODE_P (mode) && op_true == CONSTM1_RTX (mode))
    3575                 :            :     {
    3576                 :          2 :       op_false = force_reg (mode, op_false);
    3577                 :          2 :       x = gen_rtx_IOR (mode, cmp, op_false);
    3578                 :          2 :       emit_insn (gen_rtx_SET (dest, x));
    3579                 :          2 :       return;
    3580                 :            :     }
    3581                 :       4474 :   else if (TARGET_XOP)
    3582                 :            :     {
    3583                 :          9 :       op_true = force_reg (mode, op_true);
    3584                 :            : 
    3585                 :          9 :       if (!nonimmediate_operand (op_false, mode))
    3586                 :          0 :         op_false = force_reg (mode, op_false);
    3587                 :            : 
    3588                 :          9 :       emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cmp,
    3589                 :            :                                                           op_true,
    3590                 :            :                                                           op_false)));
    3591                 :          9 :       return;
    3592                 :            :     }
    3593                 :            : 
    3594                 :       4465 :   rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
    3595                 :       4465 :   rtx d = dest;
    3596                 :            : 
    3597                 :       4465 :   if (!vector_operand (op_true, mode))
    3598                 :          0 :     op_true = force_reg (mode, op_true);
    3599                 :            : 
    3600                 :       4465 :   op_false = force_reg (mode, op_false);
    3601                 :            : 
    3602                 :       4465 :   switch (mode)
    3603                 :            :     {
    3604                 :        102 :     case E_V4SFmode:
    3605                 :        102 :       if (TARGET_SSE4_1)
    3606                 :         26 :         gen = gen_sse4_1_blendvps;
    3607                 :            :       break;
    3608                 :         39 :     case E_V2DFmode:
    3609                 :         39 :       if (TARGET_SSE4_1)
    3610                 :         17 :         gen = gen_sse4_1_blendvpd;
    3611                 :            :       break;
    3612                 :        984 :     case E_SFmode:
    3613                 :        984 :       if (TARGET_SSE4_1)
    3614                 :            :         {
    3615                 :         43 :           gen = gen_sse4_1_blendvss;
    3616                 :         43 :           op_true = force_reg (mode, op_true);
    3617                 :            :         }
    3618                 :            :       break;
    3619                 :       1659 :     case E_DFmode:
    3620                 :       1659 :       if (TARGET_SSE4_1)
    3621                 :            :         {
    3622                 :         42 :           gen = gen_sse4_1_blendvsd;
    3623                 :         42 :           op_true = force_reg (mode, op_true);
    3624                 :            :         }
    3625                 :            :       break;
    3626                 :       1556 :     case E_V16QImode:
    3627                 :       1556 :     case E_V8HImode:
    3628                 :       1556 :     case E_V4SImode:
    3629                 :       1556 :     case E_V2DImode:
    3630                 :       1556 :       if (TARGET_SSE4_1)
    3631                 :            :         {
    3632                 :        287 :           gen = gen_sse4_1_pblendvb;
    3633                 :        287 :           if (mode != V16QImode)
    3634                 :        263 :             d = gen_reg_rtx (V16QImode);
    3635                 :        287 :           op_false = gen_lowpart (V16QImode, op_false);
    3636                 :        287 :           op_true = gen_lowpart (V16QImode, op_true);
    3637                 :        287 :           cmp = gen_lowpart (V16QImode, cmp);
    3638                 :            :         }
    3639                 :            :       break;
    3640                 :         33 :     case E_V8SFmode:
    3641                 :         33 :       if (TARGET_AVX)
    3642                 :         33 :         gen = gen_avx_blendvps256;
    3643                 :            :       break;
    3644                 :         41 :     case E_V4DFmode:
    3645                 :         41 :       if (TARGET_AVX)
    3646                 :         41 :         gen = gen_avx_blendvpd256;
    3647                 :            :       break;
    3648                 :         51 :     case E_V32QImode:
    3649                 :         51 :     case E_V16HImode:
    3650                 :         51 :     case E_V8SImode:
    3651                 :         51 :     case E_V4DImode:
    3652                 :         51 :       if (TARGET_AVX2)
    3653                 :            :         {
    3654                 :         49 :           gen = gen_avx2_pblendvb;
    3655                 :         49 :           if (mode != V32QImode)
    3656                 :         43 :             d = gen_reg_rtx (V32QImode);
    3657                 :         49 :           op_false = gen_lowpart (V32QImode, op_false);
    3658                 :         49 :           op_true = gen_lowpart (V32QImode, op_true);
    3659                 :         49 :           cmp = gen_lowpart (V32QImode, cmp);
    3660                 :            :         }
    3661                 :            :       break;
    3662                 :            : 
    3663                 :          0 :     case E_V64QImode:
    3664                 :          0 :       gen = gen_avx512bw_blendmv64qi;
    3665                 :          0 :       break;
    3666                 :          0 :     case E_V32HImode:
    3667                 :          0 :       gen = gen_avx512bw_blendmv32hi;
    3668                 :          0 :       break;
    3669                 :          0 :     case E_V16SImode:
    3670                 :          0 :       gen = gen_avx512f_blendmv16si;
    3671                 :          0 :       break;
    3672                 :          0 :     case E_V8DImode:
    3673                 :          0 :       gen = gen_avx512f_blendmv8di;
    3674                 :          0 :       break;
    3675                 :          0 :     case E_V8DFmode:
    3676                 :          0 :       gen = gen_avx512f_blendmv8df;
    3677                 :          0 :       break;
    3678                 :          0 :     case E_V16SFmode:
    3679                 :          0 :       gen = gen_avx512f_blendmv16sf;
    3680                 :          0 :       break;
    3681                 :            : 
    3682                 :            :     default:
    3683                 :            :       break;
    3684                 :            :     }
    3685                 :            : 
    3686                 :       4465 :   if (gen != NULL)
    3687                 :            :     {
    3688                 :        538 :       emit_insn (gen (d, op_false, op_true, cmp));
    3689                 :        538 :       if (d != dest)
    3690                 :        306 :         emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
    3691                 :            :     }
    3692                 :            :   else
    3693                 :            :     {
    3694                 :       3927 :       op_true = force_reg (mode, op_true);
    3695                 :            : 
    3696                 :       3927 :       t2 = gen_reg_rtx (mode);
    3697                 :       3927 :       if (optimize)
    3698                 :       3911 :         t3 = gen_reg_rtx (mode);
    3699                 :            :       else
    3700                 :            :         t3 = dest;
    3701                 :            : 
    3702                 :       3927 :       x = gen_rtx_AND (mode, op_true, cmp);
    3703                 :       3927 :       emit_insn (gen_rtx_SET (t2, x));
    3704                 :            : 
    3705                 :       3927 :       x = gen_rtx_NOT (mode, cmp);
    3706                 :       3927 :       x = gen_rtx_AND (mode, x, op_false);
    3707                 :       3927 :       emit_insn (gen_rtx_SET (t3, x));
    3708                 :            : 
    3709                 :       3927 :       x = gen_rtx_IOR (mode, t3, t2);
    3710                 :       3927 :       emit_insn (gen_rtx_SET (dest, x));
    3711                 :            :     }
    3712                 :            : }
    3713                 :            : 
    3714                 :            : /* Swap, force into registers, or otherwise massage the two operands
    3715                 :            :    to an sse comparison with a mask result.  Thus we differ a bit from
    3716                 :            :    ix86_prepare_fp_compare_args which expects to produce a flags result.
    3717                 :            : 
    3718                 :            :    The DEST operand exists to help determine whether to commute commutative
    3719                 :            :    operators.  The POP0/POP1 operands are updated in place.  The new
    3720                 :            :    comparison code is returned, or UNKNOWN if not implementable.  */
    3721                 :            : 
    3722                 :            : static enum rtx_code
    3723                 :      11544 : ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
    3724                 :            :                                   rtx *pop0, rtx *pop1)
    3725                 :            : {
    3726                 :      11544 :   switch (code)
    3727                 :            :     {
    3728                 :        222 :     case LTGT:
    3729                 :        222 :     case UNEQ:
    3730                 :            :       /* AVX supports all the needed comparisons.  */
    3731                 :        222 :       if (TARGET_AVX)
    3732                 :            :         break;
    3733                 :            :       /* We have no LTGT as an operator.  We could implement it with
    3734                 :            :          NE & ORDERED, but this requires an extra temporary.  It's
    3735                 :            :          not clear that it's worth it.  */
    3736                 :            :       return UNKNOWN;
    3737                 :            : 
    3738                 :            :     case LT:
    3739                 :            :     case LE:
    3740                 :            :     case UNGT:
    3741                 :            :     case UNGE:
    3742                 :            :       /* These are supported directly.  */
    3743                 :            :       break;
    3744                 :            : 
    3745                 :       4245 :     case EQ:
    3746                 :       4245 :     case NE:
    3747                 :       4245 :     case UNORDERED:
    3748                 :       4245 :     case ORDERED:
    3749                 :            :       /* AVX has 3 operand comparisons, no need to swap anything.  */
    3750                 :       4245 :       if (TARGET_AVX)
    3751                 :            :         break;
    3752                 :            :       /* For commutative operators, try to canonicalize the destination
    3753                 :            :          operand to be first in the comparison - this helps reload to
    3754                 :            :          avoid extra moves.  */
    3755                 :        136 :       if (!dest || !rtx_equal_p (dest, *pop1))
    3756                 :            :         break;
    3757                 :            :       /* FALLTHRU */
    3758                 :            : 
    3759                 :       6422 :     case GE:
    3760                 :       6422 :     case GT:
    3761                 :       6422 :     case UNLE:
    3762                 :       6422 :     case UNLT:
    3763                 :            :       /* These are not supported directly before AVX, and furthermore
    3764                 :            :          ix86_expand_sse_fp_minmax only optimizes LT/UNGE.  Swap the
    3765                 :            :          comparison operands to transform into something that is
    3766                 :            :          supported.  */
    3767                 :       6422 :       std::swap (*pop0, *pop1);
    3768                 :       6422 :       code = swap_condition (code);
    3769                 :       6422 :       break;
    3770                 :            : 
    3771                 :          0 :     default:
    3772                 :          0 :       gcc_unreachable ();
    3773                 :            :     }
    3774                 :            : 
    3775                 :            :   return code;
    3776                 :            : }
    3777                 :            : 
    3778                 :            : /* Expand a floating-point conditional move.  Return true if successful.  */
    3779                 :            : 
    3780                 :            : bool
    3781                 :      43805 : ix86_expand_fp_movcc (rtx operands[])
    3782                 :            : {
    3783                 :      43805 :   machine_mode mode = GET_MODE (operands[0]);
    3784                 :      43805 :   enum rtx_code code = GET_CODE (operands[1]);
    3785                 :      43805 :   rtx tmp, compare_op;
    3786                 :      43805 :   rtx op0 = XEXP (operands[1], 0);
    3787                 :      43805 :   rtx op1 = XEXP (operands[1], 1);
    3788                 :            : 
    3789                 :      43805 :   if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
    3790                 :            :     {
    3791                 :      12564 :       machine_mode cmode;
    3792                 :            : 
    3793                 :            :       /* Since we've no cmove for sse registers, don't force bad register
    3794                 :            :          allocation just to gain access to it.  Deny movcc when the
    3795                 :            :          comparison mode doesn't match the move mode.  */
    3796                 :      12564 :       cmode = GET_MODE (op0);
    3797                 :      12564 :       if (cmode == VOIDmode)
    3798                 :          0 :         cmode = GET_MODE (op1);
    3799                 :      12564 :       if (cmode != mode)
    3800                 :            :         return false;
    3801                 :            : 
    3802                 :       6258 :       code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1);
    3803                 :       6258 :       if (code == UNKNOWN)
    3804                 :            :         return false;
    3805                 :            : 
    3806                 :       6048 :       if (ix86_expand_sse_fp_minmax (operands[0], code, op0, op1,
    3807                 :            :                                      operands[2], operands[3]))
    3808                 :            :         return true;
    3809                 :            : 
    3810                 :       2647 :       tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1,
    3811                 :            :                                  operands[2], operands[3]);
    3812                 :       2647 :       ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
    3813                 :       2647 :       return true;
    3814                 :            :     }
    3815                 :            : 
    3816                 :      31241 :   if (GET_MODE (op0) == TImode
    3817                 :      31241 :       || (GET_MODE (op0) == DImode
    3818                 :          0 :           && !TARGET_64BIT))
    3819                 :            :     return false;
    3820                 :            : 
    3821                 :            :   /* The floating point conditional move instructions don't directly
    3822                 :            :      support conditions resulting from a signed integer comparison.  */
    3823                 :            : 
    3824                 :      31241 :   compare_op = ix86_expand_compare (code, op0, op1);
    3825                 :      31241 :   if (!fcmov_comparison_operator (compare_op, VOIDmode))
    3826                 :            :     {
    3827                 :        114 :       tmp = gen_reg_rtx (QImode);
    3828                 :        114 :       ix86_expand_setcc (tmp, code, op0, op1);
    3829                 :            : 
    3830                 :        114 :       compare_op = ix86_expand_compare (NE, tmp, const0_rtx);
    3831                 :            :     }
    3832                 :            : 
    3833                 :      31241 :   emit_insn (gen_rtx_SET (operands[0],
    3834                 :            :                           gen_rtx_IF_THEN_ELSE (mode, compare_op,
    3835                 :            :                                                 operands[2], operands[3])));
    3836                 :            : 
    3837                 :      31241 :   return true;
    3838                 :            : }
    3839                 :            : 
    3840                 :            : /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes.  */
    3841                 :            : 
    3842                 :            : static int
    3843                 :        266 : ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
    3844                 :            : {
    3845                 :        266 :   switch (code)
    3846                 :            :     {
    3847                 :            :     case EQ:
    3848                 :            :       return 0;
    3849                 :          9 :     case LT:
    3850                 :          9 :     case LTU:
    3851                 :          9 :       return 1;
    3852                 :          9 :     case LE:
    3853                 :          9 :     case LEU:
    3854                 :          9 :       return 2;
    3855                 :         42 :     case NE:
    3856                 :         42 :       return 4;
    3857                 :         44 :     case GE:
    3858                 :         44 :     case GEU:
    3859                 :         44 :       return 5;
    3860                 :        131 :     case GT:
    3861                 :        131 :     case GTU:
    3862                 :        131 :       return 6;
    3863                 :          0 :     default:
    3864                 :          0 :       gcc_unreachable ();
    3865                 :            :     }
    3866                 :            : }
    3867                 :            : 
    3868                 :            : /* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes.  */
    3869                 :            : 
    3870                 :            : static int
    3871                 :        113 : ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
    3872                 :            : {
    3873                 :        113 :   switch (code)
    3874                 :            :     {
    3875                 :            :     case EQ:
    3876                 :            :       return 0x00;
    3877                 :          9 :     case NE:
    3878                 :          9 :       return 0x04;
    3879                 :         87 :     case GT:
    3880                 :         87 :       return 0x0e;
    3881                 :          1 :     case LE:
    3882                 :          1 :       return 0x02;
    3883                 :          1 :     case GE:
    3884                 :          1 :       return 0x0d;
    3885                 :          1 :     case LT:
    3886                 :          1 :       return 0x01;
    3887                 :          1 :     case UNLE:
    3888                 :          1 :       return 0x0a;
    3889                 :          1 :     case UNLT:
    3890                 :          1 :       return 0x09;
    3891                 :          1 :     case UNGE:
    3892                 :          1 :       return 0x05;
    3893                 :          1 :     case UNGT:
    3894                 :          1 :       return 0x06;
    3895                 :          1 :     case UNEQ:
    3896                 :          1 :       return 0x18;
    3897                 :          0 :     case LTGT:
    3898                 :          0 :       return 0x0c;
    3899                 :          1 :     case ORDERED:
    3900                 :          1 :       return 0x07;
    3901                 :          1 :     case UNORDERED:
    3902                 :          1 :       return 0x03;
    3903                 :          0 :     default:
    3904                 :          0 :       gcc_unreachable ();
    3905                 :            :     }
    3906                 :            : }
    3907                 :            : 
    3908                 :            : /* Return immediate value to be used in UNSPEC_PCMP
    3909                 :            :    for comparison CODE in MODE.  */
    3910                 :            : 
    3911                 :            : static int
    3912                 :        379 : ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
    3913                 :            : {
    3914                 :        379 :   if (FLOAT_MODE_P (mode))
    3915                 :        113 :     return ix86_fp_cmp_code_to_pcmp_immediate (code);
    3916                 :        266 :   return ix86_int_cmp_code_to_pcmp_immediate (code);
    3917                 :            : }
    3918                 :            : 
    3919                 :            : /* Expand AVX-512 vector comparison.  */
    3920                 :            : 
    3921                 :            : bool
    3922                 :        379 : ix86_expand_mask_vec_cmp (rtx operands[])
    3923                 :            : {
    3924                 :        379 :   machine_mode mask_mode = GET_MODE (operands[0]);
    3925                 :        379 :   machine_mode cmp_mode = GET_MODE (operands[2]);
    3926                 :        379 :   enum rtx_code code = GET_CODE (operands[1]);
    3927                 :        379 :   rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
    3928                 :        379 :   int unspec_code;
    3929                 :        379 :   rtx unspec;
    3930                 :            : 
    3931                 :        379 :   switch (code)
    3932                 :            :     {
    3933                 :            :     case LEU:
    3934                 :            :     case GTU:
    3935                 :            :     case GEU:
    3936                 :            :     case LTU:
    3937                 :            :       unspec_code = UNSPEC_UNSIGNED_PCMP;
    3938                 :            :       break;
    3939                 :            : 
    3940                 :        375 :     default:
    3941                 :        375 :       unspec_code = UNSPEC_PCMP;
    3942                 :            :     }
    3943                 :            : 
    3944                 :        379 :   unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, operands[2],
    3945                 :            :                                                  operands[3], imm),
    3946                 :            :                            unspec_code);
    3947                 :        379 :   emit_insn (gen_rtx_SET (operands[0], unspec));
    3948                 :            : 
    3949                 :        379 :   return true;
    3950                 :            : }
    3951                 :            : 
    3952                 :            : /* Expand fp vector comparison.  */
    3953                 :            : 
    3954                 :            : bool
    3955                 :       3727 : ix86_expand_fp_vec_cmp (rtx operands[])
    3956                 :            : {
    3957                 :       3727 :   enum rtx_code code = GET_CODE (operands[1]);
    3958                 :       3727 :   rtx cmp;
    3959                 :            : 
    3960                 :       3727 :   code = ix86_prepare_sse_fp_compare_args (operands[0], code,
    3961                 :            :                                            &operands[2], &operands[3]);
    3962                 :       3727 :   if (code == UNKNOWN)
    3963                 :            :     {
    3964                 :          1 :       rtx temp;
    3965                 :          1 :       switch (GET_CODE (operands[1]))
    3966                 :            :         {
    3967                 :          0 :         case LTGT:
    3968                 :          0 :           temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
    3969                 :            :                                       operands[3], NULL, NULL);
    3970                 :          0 :           cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
    3971                 :            :                                      operands[3], NULL, NULL);
    3972                 :          0 :           code = AND;
    3973                 :          0 :           break;
    3974                 :          1 :         case UNEQ:
    3975                 :          1 :           temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
    3976                 :            :                                       operands[3], NULL, NULL);
    3977                 :          1 :           cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2],
    3978                 :            :                                      operands[3], NULL, NULL);
    3979                 :          1 :           code = IOR;
    3980                 :          1 :           break;
    3981                 :          0 :         default:
    3982                 :          0 :           gcc_unreachable ();
    3983                 :            :         }
    3984                 :          1 :       cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
    3985                 :            :                                  OPTAB_DIRECT);
    3986                 :            :     }
    3987                 :            :   else
    3988                 :       3726 :     cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
    3989                 :            :                                operands[1], operands[2]);
    3990                 :            : 
    3991                 :       3727 :   if (operands[0] != cmp)
    3992                 :       3727 :     emit_move_insn (operands[0], cmp);
    3993                 :            : 
    3994                 :       3727 :   return true;
    3995                 :            : }
    3996                 :            : 
    3997                 :            : static rtx
    3998                 :       4382 : ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
    3999                 :            :                          rtx op_true, rtx op_false, bool *negate)
    4000                 :            : {
    4001                 :       4382 :   machine_mode data_mode = GET_MODE (dest);
    4002                 :       4382 :   machine_mode mode = GET_MODE (cop0);
    4003                 :       4382 :   rtx x;
    4004                 :            : 
    4005                 :       4382 :   *negate = false;
    4006                 :            : 
    4007                 :            :   /* XOP supports all of the comparisons on all 128-bit vector int types.  */
    4008                 :       4382 :   if (TARGET_XOP
    4009                 :        128 :       && (mode == V16QImode || mode == V8HImode
    4010                 :         92 :           || mode == V4SImode || mode == V2DImode))
    4011                 :            :     ;
    4012                 :            :   /* AVX512F supports all of the comparsions
    4013                 :            :      on all 128/256/512-bit vector int types.  */
    4014                 :       4312 :   else if (ix86_valid_mask_cmp_mode (mode))
    4015                 :            :     ;
    4016                 :            :   else
    4017                 :            :     {
    4018                 :            :       /* Canonicalize the comparison to EQ, GT, GTU.  */
    4019                 :       3841 :       switch (code)
    4020                 :            :         {
    4021                 :            :         case EQ:
    4022                 :            :         case GT:
    4023                 :            :         case GTU:
    4024                 :            :           break;
    4025                 :            : 
    4026                 :       1007 :         case NE:
    4027                 :       1007 :         case LE:
    4028                 :       1007 :         case LEU:
    4029                 :       1007 :           code = reverse_condition (code);
    4030                 :       1007 :           *negate = true;
    4031                 :       1007 :           break;
    4032                 :            : 
    4033                 :        258 :         case GE:
    4034                 :        258 :         case GEU:
    4035                 :        258 :           code = reverse_condition (code);
    4036                 :        258 :           *negate = true;
    4037                 :            :           /* FALLTHRU */
    4038                 :            : 
    4039                 :        656 :         case LT:
    4040                 :        656 :         case LTU:
    4041                 :        656 :           std::swap (cop0, cop1);
    4042                 :        656 :           code = swap_condition (code);
    4043                 :        656 :           break;
    4044                 :            : 
    4045                 :          0 :         default:
    4046                 :          0 :           gcc_unreachable ();
    4047                 :            :         }
    4048                 :            : 
    4049                 :            :       /* Only SSE4.1/SSE4.2 supports V2DImode.  */
    4050                 :       3841 :       if (mode == V2DImode)
    4051                 :            :         {
    4052                 :        249 :           switch (code)
    4053                 :            :             {
    4054                 :        140 :             case EQ:
    4055                 :            :               /* SSE4.1 supports EQ.  */
    4056                 :        140 :               if (!TARGET_SSE4_1)
    4057                 :       4382 :                 return NULL;
    4058                 :            :               break;
    4059                 :            : 
    4060                 :        109 :             case GT:
    4061                 :        109 :             case GTU:
    4062                 :            :               /* SSE4.2 supports GT/GTU.  */
    4063                 :        109 :               if (!TARGET_SSE4_2)
    4064                 :            :                 return NULL;
    4065                 :            :               break;
    4066                 :            : 
    4067                 :          0 :             default:
    4068                 :          0 :               gcc_unreachable ();
    4069                 :            :             }
    4070                 :            :         }
    4071                 :            : 
    4072                 :       3841 :       rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
    4073                 :       3841 :       rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
    4074                 :       3841 :       if (*negate)
    4075                 :       1265 :         std::swap (optrue, opfalse);
    4076                 :            : 
    4077                 :            :       /* Transform x > y ? 0 : -1 (i.e. x <= y ? -1 : 0 or x <= y) when
    4078                 :            :          not using integer masks into min (x, y) == x ? -1 : 0 (i.e.
    4079                 :            :          min (x, y) == x).  While we add one instruction (the minimum),
    4080                 :            :          we remove the need for two instructions in the negation, as the
    4081                 :            :          result is done this way.
    4082                 :            :          When using masks, do it for SI/DImode element types, as it is shorter
    4083                 :            :          than the two subtractions.  */
    4084                 :       3841 :       if ((code != EQ
    4085                 :       2232 :            && GET_MODE_SIZE (mode) != 64
    4086                 :       2232 :            && vector_all_ones_operand (opfalse, data_mode)
    4087                 :        469 :            && optrue == CONST0_RTX (data_mode))
    4088                 :       5604 :           || (code == GTU
    4089                 :        886 :               && GET_MODE_SIZE (GET_MODE_INNER (mode)) >= 4
    4090                 :            :               /* Don't do it if not using integer masks and we'd end up with
    4091                 :            :                  the right values in the registers though.  */
    4092                 :        231 :               && (GET_MODE_SIZE (mode) == 64
    4093                 :        231 :                   || !vector_all_ones_operand (optrue, data_mode)
    4094                 :         68 :                   || opfalse != CONST0_RTX (data_mode))))
    4095                 :            :         {
    4096                 :        632 :           rtx (*gen) (rtx, rtx, rtx) = NULL;
    4097                 :            : 
    4098                 :        632 :           switch (mode)
    4099                 :            :             {
    4100                 :          0 :             case E_V16SImode:
    4101                 :          0 :               gen = (code == GTU) ? gen_uminv16si3 : gen_sminv16si3;
    4102                 :            :               break;
    4103                 :          0 :             case E_V8DImode:
    4104                 :          0 :               gen = (code == GTU) ? gen_uminv8di3 : gen_sminv8di3;
    4105                 :          0 :               cop0 = force_reg (mode, cop0);
    4106                 :          0 :               cop1 = force_reg (mode, cop1);
    4107                 :          0 :               break;
    4108                 :         12 :             case E_V32QImode:
    4109                 :         12 :               if (TARGET_AVX2)
    4110                 :         12 :                 gen = (code == GTU) ? gen_uminv32qi3 : gen_sminv32qi3;
    4111                 :            :               break;
    4112                 :         12 :             case E_V16HImode:
    4113                 :         12 :               if (TARGET_AVX2)
    4114                 :         12 :                 gen = (code == GTU) ? gen_uminv16hi3 : gen_sminv16hi3;
    4115                 :            :               break;
    4116                 :         18 :             case E_V8SImode:
    4117                 :         18 :               if (TARGET_AVX2)
    4118                 :         18 :                 gen = (code == GTU) ? gen_uminv8si3 : gen_sminv8si3;
    4119                 :            :               break;
    4120                 :         14 :             case E_V4DImode:
    4121                 :         14 :               if (TARGET_AVX512VL)
    4122                 :            :                 {
    4123                 :          0 :                   gen = (code == GTU) ? gen_uminv4di3 : gen_sminv4di3;
    4124                 :          0 :                   cop0 = force_reg (mode, cop0);
    4125                 :          0 :                   cop1 = force_reg (mode, cop1);
    4126                 :            :                 }
    4127                 :            :               break;
    4128                 :         96 :             case E_V16QImode:
    4129                 :         96 :               if (code == GTU && TARGET_SSE2)
    4130                 :            :                 gen = gen_uminv16qi3;
    4131                 :         48 :               else if (code == GT && TARGET_SSE4_1)
    4132                 :          6 :                 gen = gen_sminv16qi3;
    4133                 :            :               break;
    4134                 :        100 :             case E_V8HImode:
    4135                 :        100 :               if (code == GTU && TARGET_SSE4_1)
    4136                 :            :                 gen = gen_uminv8hi3;
    4137                 :         94 :               else if (code == GT && TARGET_SSE2)
    4138                 :         52 :                 gen = gen_sminv8hi3;
    4139                 :            :               break;
    4140                 :        326 :             case E_V4SImode:
    4141                 :        326 :               if (TARGET_SSE4_1)
    4142                 :         47 :                 gen = (code == GTU) ? gen_uminv4si3 : gen_sminv4si3;
    4143                 :            :               break;
    4144                 :         54 :             case E_V2DImode:
    4145                 :         54 :               if (TARGET_AVX512VL)
    4146                 :            :                 {
    4147                 :          0 :                   gen = (code == GTU) ? gen_uminv2di3 : gen_sminv2di3;
    4148                 :          0 :                   cop0 = force_reg (mode, cop0);
    4149                 :          0 :                   cop1 = force_reg (mode, cop1);
    4150                 :            :                 }
    4151                 :            :               break;
    4152                 :            :             default:
    4153                 :            :               break;
    4154                 :            :             }
    4155                 :            : 
    4156                 :        632 :           if (gen)
    4157                 :            :             {
    4158                 :        201 :               rtx tem = gen_reg_rtx (mode);
    4159                 :        201 :               if (!vector_operand (cop0, mode))
    4160                 :          0 :                 cop0 = force_reg (mode, cop0);
    4161                 :        201 :               if (!vector_operand (cop1, mode))
    4162                 :          0 :                 cop1 = force_reg (mode, cop1);
    4163                 :        201 :               *negate = !*negate;
    4164                 :        201 :               emit_insn (gen (tem, cop0, cop1));
    4165                 :        201 :               cop1 = tem;
    4166                 :        201 :               code = EQ;
    4167                 :            :             }
    4168                 :            :         }
    4169                 :            : 
    4170                 :            :       /* Unsigned parallel compare is not supported by the hardware.
    4171                 :            :          Play some tricks to turn this into a signed comparison
    4172                 :            :          against 0.  */
    4173                 :       3841 :       if (code == GTU)
    4174                 :            :         {
    4175                 :        509 :           cop0 = force_reg (mode, cop0);
    4176                 :            : 
    4177                 :        509 :           switch (mode)
    4178                 :            :             {
    4179                 :        255 :             case E_V16SImode:
    4180                 :        255 :             case E_V8DImode:
    4181                 :        255 :             case E_V8SImode:
    4182                 :        255 :             case E_V4DImode:
    4183                 :        255 :             case E_V4SImode:
    4184                 :        255 :             case E_V2DImode:
    4185                 :        255 :                 {
    4186                 :        255 :                   rtx t1, t2, mask;
    4187                 :            : 
    4188                 :            :                   /* Subtract (-(INT MAX) - 1) from both operands to make
    4189                 :            :                      them signed.  */
    4190                 :        255 :                   mask = ix86_build_signbit_mask (mode, true, false);
    4191                 :        255 :                   t1 = gen_reg_rtx (mode);
    4192                 :        255 :                   emit_insn (gen_sub3_insn (t1, cop0, mask));
    4193                 :            : 
    4194                 :        255 :                   t2 = gen_reg_rtx (mode);
    4195                 :        255 :                   emit_insn (gen_sub3_insn (t2, cop1, mask));
    4196                 :            : 
    4197                 :        255 :                   cop0 = t1;
    4198                 :        255 :                   cop1 = t2;
    4199                 :        255 :                   code = GT;
    4200                 :            :                 }
    4201                 :        255 :               break;
    4202                 :            : 
    4203                 :        254 :             case E_V64QImode:
    4204                 :        254 :             case E_V32HImode:
    4205                 :        254 :             case E_V32QImode:
    4206                 :        254 :             case E_V16HImode:
    4207                 :        254 :             case E_V16QImode:
    4208                 :        254 :             case E_V8HImode:
    4209                 :            :               /* Perform a parallel unsigned saturating subtraction.  */
    4210                 :        254 :               x = gen_reg_rtx (mode);
    4211                 :        254 :               emit_insn (gen_rtx_SET
    4212                 :            :                          (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
    4213                 :        254 :               cop0 = x;
    4214                 :        254 :               cop1 = CONST0_RTX (mode);
    4215                 :        254 :               code = EQ;
    4216                 :        254 :               *negate = !*negate;
    4217                 :        254 :               break;
    4218                 :            : 
    4219                 :          0 :             default:
    4220                 :          0 :               gcc_unreachable ();
    4221                 :            :             }
    4222                 :            :         }
    4223                 :            :     }
    4224                 :            : 
    4225                 :       4382 :   if (*negate)
    4226                 :       1282 :     std::swap (op_true, op_false);
    4227                 :            : 
    4228                 :            :   /* Allow the comparison to be done in one mode, but the movcc to
    4229                 :            :      happen in another mode.  */
    4230                 :       4382 :   if (data_mode == mode)
    4231                 :            :     {
    4232                 :       4324 :       x = ix86_expand_sse_cmp (dest, code, cop0, cop1,
    4233                 :            :                                op_true, op_false);
    4234                 :            :     }
    4235                 :            :   else
    4236                 :            :     {
    4237                 :        174 :       gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
    4238                 :         58 :       x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
    4239                 :            :                                op_true, op_false);
    4240                 :         58 :       if (GET_MODE (x) == mode)
    4241                 :         53 :         x = gen_lowpart (data_mode, x);
    4242                 :            :     }
    4243                 :            : 
    4244                 :            :   return x;
    4245                 :            : }
    4246                 :            : 
    4247                 :            : /* Expand integer vector comparison.  */
    4248                 :            : 
    4249                 :            : bool
    4250                 :        531 : ix86_expand_int_vec_cmp (rtx operands[])
    4251                 :            : {
    4252                 :        531 :   rtx_code code = GET_CODE (operands[1]);
    4253                 :        531 :   bool negate = false;
    4254                 :        531 :   rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
    4255                 :            :                                      operands[3], NULL, NULL, &negate);
    4256                 :            : 
    4257                 :        531 :   if (!cmp)
    4258                 :            :     return false;
    4259                 :            : 
    4260                 :        531 :   if (negate)
    4261                 :        235 :     cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
    4262                 :        235 :                                    CONST0_RTX (GET_MODE (cmp)),
    4263                 :            :                                    NULL, NULL, &negate);
    4264                 :            : 
    4265                 :        531 :   gcc_assert (!negate);
    4266                 :            : 
    4267                 :        531 :   if (operands[0] != cmp)
    4268                 :        531 :     emit_move_insn (operands[0], cmp);
    4269                 :            : 
    4270                 :            :   return true;
    4271                 :            : }
    4272                 :            : 
    4273                 :            : /* Expand a floating-point vector conditional move; a vcond operation
    4274                 :            :    rather than a movcc operation.  */
    4275                 :            : 
    4276                 :            : bool
    4277                 :       1559 : ix86_expand_fp_vcond (rtx operands[])
    4278                 :            : {
    4279                 :       1559 :   enum rtx_code code = GET_CODE (operands[3]);
    4280                 :       1559 :   rtx cmp;
    4281                 :            : 
    4282                 :       1559 :   code = ix86_prepare_sse_fp_compare_args (operands[0], code,
    4283                 :            :                                            &operands[4], &operands[5]);
    4284                 :       1559 :   if (code == UNKNOWN)
    4285                 :            :     {
    4286                 :          8 :       rtx temp;
    4287                 :          8 :       switch (GET_CODE (operands[3]))
    4288                 :            :         {
    4289                 :          0 :         case LTGT:
    4290                 :          0 :           temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
    4291                 :            :                                       operands[5], operands[0], operands[0]);
    4292                 :          0 :           cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
    4293                 :            :                                      operands[5], operands[1], operands[2]);
    4294                 :          0 :           code = AND;
    4295                 :          0 :           break;
    4296                 :          8 :         case UNEQ:
    4297                 :          8 :           temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
    4298                 :            :                                       operands[5], operands[0], operands[0]);
    4299                 :          8 :           cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
    4300                 :            :                                      operands[5], operands[1], operands[2]);
    4301                 :          8 :           code = IOR;
    4302                 :          8 :           break;
    4303                 :          0 :         default:
    4304                 :          0 :           gcc_unreachable ();
    4305                 :            :         }
    4306                 :          8 :       cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
    4307                 :            :                                  OPTAB_DIRECT);
    4308                 :          8 :       ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
    4309                 :          8 :       return true;
    4310                 :            :     }
    4311                 :            : 
    4312                 :       1551 :   if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
    4313                 :            :                                  operands[5], operands[1], operands[2]))
    4314                 :            :     return true;
    4315                 :            : 
    4316                 :       1526 :   cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
    4317                 :            :                              operands[1], operands[2]);
    4318                 :       1526 :   ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
    4319                 :       1526 :   return true;
    4320                 :            : }
    4321                 :            : 
    4322                 :            : /* Expand a signed/unsigned integral vector conditional move.  */
    4323                 :            : 
    4324                 :            : bool
    4325                 :       3688 : ix86_expand_int_vcond (rtx operands[])
    4326                 :            : {
    4327                 :       3688 :   machine_mode data_mode = GET_MODE (operands[0]);
    4328                 :       3688 :   machine_mode mode = GET_MODE (operands[4]);
    4329                 :       3688 :   enum rtx_code code = GET_CODE (operands[3]);
    4330                 :       3688 :   bool negate = false;
    4331                 :       3688 :   rtx x, cop0, cop1;
    4332                 :            : 
    4333                 :       3688 :   cop0 = operands[4];
    4334                 :       3688 :   cop1 = operands[5];
    4335                 :            : 
    4336                 :            :   /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
    4337                 :            :      and x < 0 ? 1 : 0 into (unsigned) x >> 31.  */
    4338                 :       3688 :   if ((code == LT || code == GE)
    4339                 :        613 :       && data_mode == mode
    4340                 :        586 :       && cop1 == CONST0_RTX (mode)
    4341                 :        300 :       && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
    4342                 :        167 :       && GET_MODE_UNIT_SIZE (data_mode) > 1
    4343                 :        155 :       && GET_MODE_UNIT_SIZE (data_mode) <= 8
    4344                 :       3843 :       && (GET_MODE_SIZE (data_mode) == 16
    4345                 :         16 :           || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
    4346                 :            :     {
    4347                 :        155 :       rtx negop = operands[2 - (code == LT)];
    4348                 :        155 :       int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
    4349                 :        155 :       if (negop == CONST1_RTX (data_mode))
    4350                 :            :         {
    4351                 :          6 :           rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
    4352                 :            :                                          operands[0], 1, OPTAB_DIRECT);
    4353                 :          6 :           if (res != operands[0])
    4354                 :          0 :             emit_move_insn (operands[0], res);
    4355                 :          6 :           return true;
    4356                 :            :         }
    4357                 :        298 :       else if (GET_MODE_INNER (data_mode) != DImode
    4358                 :        149 :                && vector_all_ones_operand (negop, data_mode))
    4359                 :            :         {
    4360                 :         66 :           rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
    4361                 :            :                                          operands[0], 0, OPTAB_DIRECT);
    4362                 :         66 :           if (res != operands[0])
    4363                 :          0 :             emit_move_insn (operands[0], res);
    4364                 :         66 :           return true;
    4365                 :            :         }
    4366                 :            :     }
    4367                 :            : 
    4368                 :       3616 :   if (!nonimmediate_operand (cop1, mode))
    4369                 :        646 :     cop1 = force_reg (mode, cop1);
    4370                 :       3616 :   if (!general_operand (operands[1], data_mode))
    4371                 :        365 :     operands[1] = force_reg (data_mode, operands[1]);
    4372                 :       3616 :   if (!general_operand (operands[2], data_mode))
    4373                 :        261 :     operands[2] = force_reg (data_mode, operands[2]);
    4374                 :            : 
    4375                 :       3616 :   x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
    4376                 :            :                                operands[1], operands[2], &negate);
    4377                 :            : 
    4378                 :       3616 :   if (!x)
    4379                 :            :     return false;
    4380                 :            : 
    4381                 :       3616 :   ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
    4382                 :       3616 :                          operands[2-negate]);
    4383                 :       3616 :   return true;
    4384                 :            : }
    4385                 :            : 
    4386                 :            : static bool
    4387                 :      32210 : ix86_expand_vec_perm_vpermt2 (rtx target, rtx mask, rtx op0, rtx op1,
    4388                 :            :                               struct expand_vec_perm_d *d)
    4389                 :            : {
    4390                 :            :   /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
    4391                 :            :      expander, so args are either in d, or in op0, op1 etc.  */
    4392                 :      32210 :   machine_mode mode = GET_MODE (d ? d->op0 : op0);
    4393                 :      32210 :   machine_mode maskmode = mode;
    4394                 :      32210 :   rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
    4395                 :            : 
    4396                 :      32210 :   switch (mode)
    4397                 :            :     {
    4398                 :       5012 :     case E_V8HImode:
    4399                 :       5012 :       if (TARGET_AVX512VL && TARGET_AVX512BW)
    4400                 :            :         gen = gen_avx512vl_vpermt2varv8hi3;
    4401                 :            :       break;
    4402                 :        264 :     case E_V16HImode:
    4403                 :        264 :       if (TARGET_AVX512VL && TARGET_AVX512BW)
    4404                 :            :         gen = gen_avx512vl_vpermt2varv16hi3;
    4405                 :            :       break;
    4406                 :         61 :     case E_V64QImode:
    4407                 :         61 :       if (TARGET_AVX512VBMI)
    4408                 :            :         gen = gen_avx512bw_vpermt2varv64qi3;
    4409                 :            :       break;
    4410                 :         99 :     case E_V32HImode:
    4411                 :         99 :       if (TARGET_AVX512BW)
    4412                 :            :         gen = gen_avx512bw_vpermt2varv32hi3;
    4413                 :            :       break;
    4414                 :      10250 :     case E_V4SImode:
    4415                 :      10250 :       if (TARGET_AVX512VL)
    4416                 :            :         gen = gen_avx512vl_vpermt2varv4si3;
    4417                 :            :       break;
    4418                 :        980 :     case E_V8SImode:
    4419                 :        980 :       if (TARGET_AVX512VL)
    4420                 :            :         gen = gen_avx512vl_vpermt2varv8si3;
    4421                 :            :       break;
    4422                 :        105 :     case E_V16SImode:
    4423                 :        105 :       if (TARGET_AVX512F)
    4424                 :            :         gen = gen_avx512f_vpermt2varv16si3;
    4425                 :            :       break;
    4426                 :       3280 :     case E_V4SFmode:
    4427                 :       3280 :       if (TARGET_AVX512VL)
    4428                 :            :         {
    4429                 :            :           gen = gen_avx512vl_vpermt2varv4sf3;
    4430                 :            :           maskmode = V4SImode;
    4431                 :            :         }
    4432                 :            :       break;
    4433                 :       3027 :     case E_V8SFmode:
    4434                 :       3027 :       if (TARGET_AVX512VL)
    4435                 :            :         {
    4436                 :            :           gen = gen_avx512vl_vpermt2varv8sf3;
    4437                 :            :           maskmode = V8SImode;
    4438                 :            :         }
    4439                 :            :       break;
    4440                 :        167 :     case E_V16SFmode:
    4441                 :        167 :       if (TARGET_AVX512F)
    4442                 :            :         {
    4443                 :            :           gen = gen_avx512f_vpermt2varv16sf3;
    4444                 :            :           maskmode = V16SImode;
    4445                 :            :         }
    4446                 :            :       break;
    4447                 :          0 :     case E_V2DImode:
    4448                 :          0 :       if (TARGET_AVX512VL)
    4449                 :            :         gen = gen_avx512vl_vpermt2varv2di3;
    4450                 :            :       break;
    4451                 :        734 :     case E_V4DImode:
    4452                 :        734 :       if (TARGET_AVX512VL)
    4453                 :            :         gen = gen_avx512vl_vpermt2varv4di3;
    4454                 :            :       break;
    4455                 :          9 :     case E_V8DImode:
    4456                 :          9 :       if (TARGET_AVX512F)
    4457                 :            :         gen = gen_avx512f_vpermt2varv8di3;
    4458                 :            :       break;
    4459                 :          0 :     case E_V2DFmode:
    4460                 :          0 :       if (TARGET_AVX512VL)
    4461                 :            :         {
    4462                 :            :           gen = gen_avx512vl_vpermt2varv2df3;
    4463                 :            :           maskmode = V2DImode;
    4464                 :            :         }
    4465                 :            :       break;
    4466                 :       1624 :     case E_V4DFmode:
    4467                 :       1624 :       if (TARGET_AVX512VL)
    4468                 :            :         {
    4469                 :            :           gen = gen_avx512vl_vpermt2varv4df3;
    4470                 :            :           maskmode = V4DImode;
    4471                 :            :         }
    4472                 :            :       break;
    4473                 :        145 :     case E_V8DFmode:
    4474                 :        145 :       if (TARGET_AVX512F)
    4475                 :            :         {
    4476                 :            :           gen = gen_avx512f_vpermt2varv8df3;
    4477                 :            :           maskmode = V8DImode;
    4478                 :            :         }
    4479                 :            :       break;
    4480                 :            :     default:
    4481                 :            :       break;
    4482                 :            :     }
    4483                 :            : 
    4484                 :        541 :   if (gen == NULL)
    4485                 :            :     return false;
    4486                 :            : 
    4487                 :            :   /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
    4488                 :            :      expander, so args are either in d, or in op0, op1 etc.  */
    4489                 :        541 :   if (d)
    4490                 :            :     {
    4491                 :        541 :       rtx vec[64];
    4492                 :        541 :       target = d->target;
    4493                 :        541 :       op0 = d->op0;
    4494                 :        541 :       op1 = d->op1;
    4495                 :       9581 :       for (int i = 0; i < d->nelt; ++i)
    4496                 :       9040 :         vec[i] = GEN_INT (d->perm[i]);
    4497                 :        541 :       mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
    4498                 :            :     }
    4499                 :            : 
    4500                 :        541 :   emit_insn (gen (target, force_reg (maskmode, mask), op0, op1));
    4501                 :        541 :   return true;
    4502                 :            : }
    4503                 :            : 
    4504                 :            : /* Expand a variable vector permutation.  */
    4505                 :            : 
    4506                 :            : void
    4507                 :          2 : ix86_expand_vec_perm (rtx operands[])
    4508                 :            : {
    4509                 :          2 :   rtx target = operands[0];
    4510                 :          2 :   rtx op0 = operands[1];
    4511                 :          2 :   rtx op1 = operands[2];
    4512                 :          2 :   rtx mask = operands[3];
    4513                 :          2 :   rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
    4514                 :          2 :   machine_mode mode = GET_MODE (op0);
    4515                 :          2 :   machine_mode maskmode = GET_MODE (mask);
    4516                 :          2 :   int w, e, i;
    4517                 :          2 :   bool one_operand_shuffle = rtx_equal_p (op0, op1);
    4518                 :            : 
    4519                 :            :   /* Number of elements in the vector.  */
    4520                 :          2 :   w = GET_MODE_NUNITS (mode);
    4521                 :          2 :   e = GET_MODE_UNIT_SIZE (mode);
    4522                 :          2 :   gcc_assert (w <= 64);
    4523                 :            : 
    4524                 :          2 :   if (TARGET_AVX512F && one_operand_shuffle)
    4525                 :            :     {
    4526                 :          0 :       rtx (*gen) (rtx, rtx, rtx) = NULL;
    4527                 :          0 :       switch (mode)
    4528                 :            :         {
    4529                 :            :         case E_V16SImode:
    4530                 :            :           gen =gen_avx512f_permvarv16si;
    4531                 :            :           break;
    4532                 :          0 :         case E_V16SFmode:
    4533                 :          0 :           gen = gen_avx512f_permvarv16sf;
    4534                 :          0 :           break;
    4535                 :          0 :         case E_V8DImode:
    4536                 :          0 :           gen = gen_avx512f_permvarv8di;
    4537                 :          0 :           break;
    4538                 :          0 :         case E_V8DFmode:
    4539                 :          0 :           gen = gen_avx512f_permvarv8df;
    4540                 :          0 :           break;
    4541                 :            :         default:
    4542                 :            :           break;
    4543                 :            :         }
    4544                 :          0 :       if (gen != NULL)
    4545                 :            :         {
    4546                 :          0 :           emit_insn (gen (target, op0, mask));
    4547                 :          0 :           return;
    4548                 :            :         }
    4549                 :            :     }
    4550                 :            : 
    4551                 :          2 :   if (ix86_expand_vec_perm_vpermt2 (target, mask, op0, op1, NULL))
    4552                 :            :     return;
    4553                 :            : 
    4554                 :          2 :   if (TARGET_AVX2)
    4555                 :            :     {
    4556                 :          1 :       if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
    4557                 :            :         {
    4558                 :            :           /* Unfortunately, the VPERMQ and VPERMPD instructions only support
    4559                 :            :              an constant shuffle operand.  With a tiny bit of effort we can
    4560                 :            :              use VPERMD instead.  A re-interpretation stall for V4DFmode is
    4561                 :            :              unfortunate but there's no avoiding it.
    4562                 :            :              Similarly for V16HImode we don't have instructions for variable
    4563                 :            :              shuffling, while for V32QImode we can use after preparing suitable
    4564                 :            :              masks vpshufb; vpshufb; vpermq; vpor.  */
    4565                 :            : 
    4566                 :          0 :           if (mode == V16HImode)
    4567                 :            :             {
    4568                 :            :               maskmode = mode = V32QImode;
    4569                 :            :               w = 32;
    4570                 :            :               e = 1;
    4571                 :            :             }
    4572                 :            :           else
    4573                 :            :             {
    4574                 :          0 :               maskmode = mode = V8SImode;
    4575                 :          0 :               w = 8;
    4576                 :          0 :               e = 4;
    4577                 :            :             }
    4578                 :          0 :           t1 = gen_reg_rtx (maskmode);
    4579                 :            : 
    4580                 :            :           /* Replicate the low bits of the V4DImode mask into V8SImode:
    4581                 :            :                mask = { A B C D }
    4582                 :            :                t1 = { A A B B C C D D }.  */
    4583                 :          0 :           for (i = 0; i < w / 2; ++i)
    4584                 :          0 :             vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
    4585                 :          0 :           vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
    4586                 :          0 :           vt = force_reg (maskmode, vt);
    4587                 :          0 :           mask = gen_lowpart (maskmode, mask);
    4588                 :          0 :           if (maskmode == V8SImode)
    4589                 :          0 :             emit_insn (gen_avx2_permvarv8si (t1, mask, vt));
    4590                 :            :           else
    4591                 :          0 :             emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
    4592                 :            : 
    4593                 :            :           /* Multiply the shuffle indicies by two.  */
    4594                 :          0 :           t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
    4595                 :            :                                     OPTAB_DIRECT);
    4596                 :            : 
    4597                 :            :           /* Add one to the odd shuffle indicies:
    4598                 :            :                 t1 = { A*2, A*2+1, B*2, B*2+1, ... }.  */
    4599                 :          0 :           for (i = 0; i < w / 2; ++i)
    4600                 :            :             {
    4601                 :          0 :               vec[i * 2] = const0_rtx;
    4602                 :          0 :               vec[i * 2 + 1] = const1_rtx;
    4603                 :            :             }
    4604                 :          0 :           vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
    4605                 :          0 :           vt = validize_mem (force_const_mem (maskmode, vt));
    4606                 :          0 :           t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
    4607                 :            :                                     OPTAB_DIRECT);
    4608                 :            : 
    4609                 :            :           /* Continue as if V8SImode (resp. V32QImode) was used initially.  */
    4610                 :          0 :           operands[3] = mask = t1;
    4611                 :          0 :           target = gen_reg_rtx (mode);
    4612                 :          0 :           op0 = gen_lowpart (mode, op0);
    4613                 :          0 :           op1 = gen_lowpart (mode, op1);
    4614                 :            :         }
    4615                 :            : 
    4616                 :          1 :       switch (mode)
    4617                 :            :         {
    4618                 :          1 :         case E_V8SImode:
    4619                 :            :           /* The VPERMD and VPERMPS instructions already properly ignore
    4620                 :            :              the high bits of the shuffle elements.  No need for us to
    4621                 :            :              perform an AND ourselves.  */
    4622                 :          1 :           if (one_operand_shuffle)
    4623                 :            :             {
    4624                 :          0 :               emit_insn (gen_avx2_permvarv8si (target, op0, mask));
    4625                 :          0 :               if (target != operands[0])
    4626                 :          0 :                 emit_move_insn (operands[0],
    4627                 :          0 :                                 gen_lowpart (GET_MODE (operands[0]), target));
    4628                 :            :             }
    4629                 :            :           else
    4630                 :            :             {
    4631                 :          1 :               t1 = gen_reg_rtx (V8SImode);
    4632                 :          1 :               t2 = gen_reg_rtx (V8SImode);
    4633                 :          1 :               emit_insn (gen_avx2_permvarv8si (t1, op0, mask));
    4634                 :          1 :               emit_insn (gen_avx2_permvarv8si (t2, op1, mask));
    4635                 :          1 :               goto merge_two;
    4636                 :            :             }
    4637                 :          0 :           return;
    4638                 :            : 
    4639                 :          0 :         case E_V8SFmode:
    4640                 :          0 :           mask = gen_lowpart (V8SImode, mask);
    4641                 :          0 :           if (one_operand_shuffle)
    4642                 :          0 :             emit_insn (gen_avx2_permvarv8sf (target, op0, mask));
    4643                 :            :           else
    4644                 :            :             {
    4645                 :          0 :               t1 = gen_reg_rtx (V8SFmode);
    4646                 :          0 :               t2 = gen_reg_rtx (V8SFmode);
    4647                 :          0 :               emit_insn (gen_avx2_permvarv8sf (t1, op0, mask));
    4648                 :          0 :               emit_insn (gen_avx2_permvarv8sf (t2, op1, mask));
    4649                 :          0 :               goto merge_two;
    4650                 :            :             }
    4651                 :          0 :           return;
    4652                 :            : 
    4653                 :          0 :         case E_V4SImode:
    4654                 :            :           /* By combining the two 128-bit input vectors into one 256-bit
    4655                 :            :              input vector, we can use VPERMD and VPERMPS for the full
    4656                 :            :              two-operand shuffle.  */
    4657                 :          0 :           t1 = gen_reg_rtx (V8SImode);
    4658                 :          0 :           t2 = gen_reg_rtx (V8SImode);
    4659                 :          0 :           emit_insn (gen_avx_vec_concatv8si (t1, op0, op1));
    4660                 :          0 :           emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
    4661                 :          0 :           emit_insn (gen_avx2_permvarv8si (t1, t1, t2));
    4662                 :          0 :           emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx));
    4663                 :          0 :           return;
    4664                 :            : 
    4665                 :          0 :         case E_V4SFmode:
    4666                 :          0 :           t1 = gen_reg_rtx (V8SFmode);
    4667                 :          0 :           t2 = gen_reg_rtx (V8SImode);
    4668                 :          0 :           mask = gen_lowpart (V4SImode, mask);
    4669                 :          0 :           emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1));
    4670                 :          0 :           emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
    4671                 :          0 :           emit_insn (gen_avx2_permvarv8sf (t1, t1, t2));
    4672                 :          0 :           emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
    4673                 :          0 :           return;
    4674                 :            : 
    4675                 :          0 :         case E_V32QImode:
    4676                 :          0 :           t1 = gen_reg_rtx (V32QImode);
    4677                 :          0 :           t2 = gen_reg_rtx (V32QImode);
    4678                 :          0 :           t3 = gen_reg_rtx (V32QImode);
    4679                 :          0 :           vt2 = GEN_INT (-128);
    4680                 :          0 :           vt = gen_const_vec_duplicate (V32QImode, vt2);
    4681                 :          0 :           vt = force_reg (V32QImode, vt);
    4682                 :          0 :           for (i = 0; i < 32; i++)
    4683                 :          0 :             vec[i] = i < 16 ? vt2 : const0_rtx;
    4684                 :          0 :           vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
    4685                 :          0 :           vt2 = force_reg (V32QImode, vt2);
    4686                 :            :           /* From mask create two adjusted masks, which contain the same
    4687                 :            :              bits as mask in the low 7 bits of each vector element.
    4688                 :            :              The first mask will have the most significant bit clear
    4689                 :            :              if it requests element from the same 128-bit lane
    4690                 :            :              and MSB set if it requests element from the other 128-bit lane.
    4691                 :            :              The second mask will have the opposite values of the MSB,
    4692                 :            :              and additionally will have its 128-bit lanes swapped.
    4693                 :            :              E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
    4694                 :            :              t1   { 07 92 9e 09 ... | 17 19 85 1f ... } and
    4695                 :            :              t3   { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
    4696                 :            :              stands for other 12 bytes.  */
    4697                 :            :           /* The bit whether element is from the same lane or the other
    4698                 :            :              lane is bit 4, so shift it up by 3 to the MSB position.  */
    4699                 :          0 :           t5 = gen_reg_rtx (V4DImode);
    4700                 :          0 :           emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
    4701                 :            :                                     GEN_INT (3)));
    4702                 :            :           /* Clear MSB bits from the mask just in case it had them set.  */
    4703                 :          0 :           emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
    4704                 :            :           /* After this t1 will have MSB set for elements from other lane.  */
    4705                 :          0 :           emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
    4706                 :            :           /* Clear bits other than MSB.  */
    4707                 :          0 :           emit_insn (gen_andv32qi3 (t1, t1, vt));
    4708                 :            :           /* Or in the lower bits from mask into t3.  */
    4709                 :          0 :           emit_insn (gen_iorv32qi3 (t3, t1, t2));
    4710                 :            :           /* And invert MSB bits in t1, so MSB is set for elements from the same
    4711                 :            :              lane.  */
    4712                 :          0 :           emit_insn (gen_xorv32qi3 (t1, t1, vt));
    4713                 :            :           /* Swap 128-bit lanes in t3.  */
    4714                 :          0 :           t6 = gen_reg_rtx (V4DImode);
    4715                 :          0 :           emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
    4716                 :            :                                           const2_rtx, GEN_INT (3),
    4717                 :            :                                           const0_rtx, const1_rtx));
    4718                 :            :           /* And or in the lower bits from mask into t1.  */
    4719                 :          0 :           emit_insn (gen_iorv32qi3 (t1, t1, t2));
    4720                 :          0 :           if (one_operand_shuffle)
    4721                 :            :             {
    4722                 :            :               /* Each of these shuffles will put 0s in places where
    4723                 :            :                  element from the other 128-bit lane is needed, otherwise
    4724                 :            :                  will shuffle in the requested value.  */
    4725                 :          0 :               emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
    4726                 :          0 :                                                 gen_lowpart (V32QImode, t6)));
    4727                 :          0 :               emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
    4728                 :            :               /* For t3 the 128-bit lanes are swapped again.  */
    4729                 :          0 :               t7 = gen_reg_rtx (V4DImode);
    4730                 :          0 :               emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
    4731                 :            :                                               const2_rtx, GEN_INT (3),
    4732                 :            :                                               const0_rtx, const1_rtx));
    4733                 :            :               /* And oring both together leads to the result.  */
    4734                 :          0 :               emit_insn (gen_iorv32qi3 (target, t1,
    4735                 :          0 :                                         gen_lowpart (V32QImode, t7)));
    4736                 :          0 :               if (target != operands[0])
    4737                 :          0 :                 emit_move_insn (operands[0],
    4738                 :          0 :                                 gen_lowpart (GET_MODE (operands[0]), target));
    4739                 :          0 :               return;
    4740                 :            :             }
    4741                 :            : 
    4742                 :          0 :           t4 = gen_reg_rtx (V32QImode);
    4743                 :            :           /* Similarly to the above one_operand_shuffle code,
    4744                 :            :              just for repeated twice for each operand.  merge_two:
    4745                 :            :              code will merge the two results together.  */
    4746                 :          0 :           emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
    4747                 :          0 :                                             gen_lowpart (V32QImode, t6)));
    4748                 :          0 :           emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
    4749                 :          0 :                                             gen_lowpart (V32QImode, t6)));
    4750                 :          0 :           emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
    4751                 :          0 :           emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
    4752                 :          0 :           t7 = gen_reg_rtx (V4DImode);
    4753                 :          0 :           emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
    4754                 :            :                                           const2_rtx, GEN_INT (3),
    4755                 :            :                                           const0_rtx, const1_rtx));
    4756                 :          0 :           t8 = gen_reg_rtx (V4DImode);
    4757                 :          0 :           emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
    4758                 :            :                                           const2_rtx, GEN_INT (3),
    4759                 :            :                                           const0_rtx, const1_rtx));
    4760                 :          0 :           emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
    4761                 :          0 :           emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
    4762                 :          0 :           t1 = t4;
    4763                 :          0 :           t2 = t3;
    4764                 :          0 :           goto merge_two;
    4765                 :            : 
    4766                 :          0 :         default:
    4767                 :          0 :           gcc_assert (GET_MODE_SIZE (mode) <= 16);
    4768                 :            :           break;
    4769                 :            :         }
    4770                 :            :     }
    4771                 :            : 
    4772                 :          1 :   if (TARGET_XOP)
    4773                 :            :     {
    4774                 :            :       /* The XOP VPPERM insn supports three inputs.  By ignoring the 
    4775                 :            :          one_operand_shuffle special case, we avoid creating another
    4776                 :            :          set of constant vectors in memory.  */
    4777                 :          0 :       one_operand_shuffle = false;
    4778                 :            : 
    4779                 :            :       /* mask = mask & {2*w-1, ...} */
    4780                 :          0 :       vt = GEN_INT (2*w - 1);
    4781                 :            :     }
    4782                 :            :   else
    4783                 :            :     {
    4784                 :            :       /* mask = mask & {w-1, ...} */
    4785                 :          1 :       vt = GEN_INT (w - 1);
    4786                 :            :     }
    4787                 :            : 
    4788                 :          1 :   vt = gen_const_vec_duplicate (maskmode, vt);
    4789                 :          1 :   mask = expand_simple_binop (maskmode, AND, mask, vt,
    4790                 :            :                               NULL_RTX, 0, OPTAB_DIRECT);
    4791                 :            : 
    4792                 :            :   /* For non-QImode operations, convert the word permutation control
    4793                 :            :      into a byte permutation control.  */
    4794                 :          1 :   if (mode != V16QImode)
    4795                 :            :     {
    4796                 :          1 :       mask = expand_simple_binop (maskmode, ASHIFT, mask,
    4797                 :          2 :                                   GEN_INT (exact_log2 (e)),
    4798                 :            :                                   NULL_RTX, 0, OPTAB_DIRECT);
    4799                 :            : 
    4800                 :            :       /* Convert mask to vector of chars.  */
    4801                 :          1 :       mask = force_reg (V16QImode, gen_lowpart (V16QImode, mask));
    4802                 :            : 
    4803                 :            :       /* Replicate each of the input bytes into byte positions:
    4804                 :            :          (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}
    4805                 :            :          (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12}
    4806                 :            :          (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}.  */
    4807                 :         17 :       for (i = 0; i < 16; ++i)
    4808                 :         16 :         vec[i] = GEN_INT (i/e * e);
    4809                 :          1 :       vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
    4810                 :          1 :       vt = validize_mem (force_const_mem (V16QImode, vt));
    4811                 :          1 :       if (TARGET_XOP)
    4812                 :          0 :         emit_insn (gen_xop_pperm (mask, mask, mask, vt));
    4813                 :            :       else
    4814                 :          1 :         emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt));
    4815                 :            : 
    4816                 :            :       /* Convert it into the byte positions by doing
    4817                 :            :          mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...}  */
    4818                 :         17 :       for (i = 0; i < 16; ++i)
    4819                 :         16 :         vec[i] = GEN_INT (i % e);
    4820                 :          1 :       vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
    4821                 :          1 :       vt = validize_mem (force_const_mem (V16QImode, vt));
    4822                 :          1 :       emit_insn (gen_addv16qi3 (mask, mask, vt));
    4823                 :            :     }
    4824                 :            : 
    4825                 :            :   /* The actual shuffle operations all operate on V16QImode.  */
    4826                 :          1 :   op0 = gen_lowpart (V16QImode, op0);
    4827                 :          1 :   op1 = gen_lowpart (V16QImode, op1);
    4828                 :            : 
    4829                 :          1 :   if (TARGET_XOP)
    4830                 :            :     {
    4831                 :          0 :       if (GET_MODE (target) != V16QImode)
    4832                 :          0 :         target = gen_reg_rtx (V16QImode);
    4833                 :          0 :       emit_insn (gen_xop_pperm (target, op0, op1, mask));
    4834                 :          0 :       if (target != operands[0])
    4835                 :          0 :         emit_move_insn (operands[0],
    4836                 :          0 :                         gen_lowpart (GET_MODE (operands[0]), target));
    4837                 :            :     }
    4838                 :          1 :   else if (one_operand_shuffle)
    4839                 :            :     {
    4840                 :          1 :       if (GET_MODE (target) != V16QImode)
    4841                 :          1 :         target = gen_reg_rtx (V16QImode);
    4842                 :          1 :       emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
    4843                 :          1 :       if (target != operands[0])
    4844                 :          1 :         emit_move_insn (operands[0],
    4845                 :          1 :                         gen_lowpart (GET_MODE (operands[0]), target));
    4846                 :            :     }
    4847                 :            :   else
    4848                 :            :     {
    4849                 :          0 :       rtx xops[6];
    4850                 :          0 :       bool ok;
    4851                 :            : 
    4852                 :            :       /* Shuffle the two input vectors independently.  */
    4853                 :          0 :       t1 = gen_reg_rtx (V16QImode);
    4854                 :          0 :       t2 = gen_reg_rtx (V16QImode);
    4855                 :          0 :       emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask));
    4856                 :          0 :       emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask));
    4857                 :            : 
    4858                 :          1 :  merge_two:
    4859                 :            :       /* Then merge them together.  The key is whether any given control
    4860                 :            :          element contained a bit set that indicates the second word.  */
    4861                 :          1 :       mask = operands[3];
    4862                 :          1 :       vt = GEN_INT (w);
    4863                 :          1 :       if (maskmode == V2DImode && !TARGET_SSE4_1)
    4864                 :            :         {
    4865                 :            :           /* Without SSE4.1, we don't have V2DImode EQ.  Perform one
    4866                 :            :              more shuffle to convert the V2DI input mask into a V4SI
    4867                 :            :              input mask.  At which point the masking that expand_int_vcond
    4868                 :            :              will work as desired.  */
    4869                 :          0 :           rtx t3 = gen_reg_rtx (V4SImode);
    4870                 :          0 :           emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpart (V4SImode, mask),
    4871                 :            :                                         const0_rtx, const0_rtx,
    4872                 :            :                                         const2_rtx, const2_rtx));
    4873                 :          0 :           mask = t3;
    4874                 :          0 :           maskmode = V4SImode;
    4875                 :          0 :           e = w = 4;
    4876                 :            :         }
    4877                 :            : 
    4878                 :          1 :       vt = gen_const_vec_duplicate (maskmode, vt);
    4879                 :          1 :       vt = force_reg (maskmode, vt);
    4880                 :          1 :       mask = expand_simple_binop (maskmode, AND, mask, vt,
    4881                 :            :                                   NULL_RTX, 0, OPTAB_DIRECT);
    4882                 :            : 
    4883                 :          1 :       if (GET_MODE (target) != mode)
    4884                 :          0 :         target = gen_reg_rtx (mode);
    4885                 :          1 :       xops[0] = target;
    4886                 :          1 :       xops[1] = gen_lowpart (mode, t2);
    4887                 :          1 :       xops[2] = gen_lowpart (mode, t1);
    4888                 :          1 :       xops[3] = gen_rtx_EQ (maskmode, mask, vt);
    4889                 :          1 :       xops[4] = mask;
    4890                 :          1 :       xops[5] = vt;
    4891                 :          1 :       ok = ix86_expand_int_vcond (xops);
    4892                 :          1 :       gcc_assert (ok);
    4893                 :          1 :       if (target != operands[0])
    4894                 :          0 :         emit_move_insn (operands[0],
    4895                 :          0 :                         gen_lowpart (GET_MODE (operands[0]), target));
    4896                 :            :     }
    4897                 :            : }
    4898                 :            : 
    4899                 :            : /* Unpack OP[1] into the next wider integer vector type.  UNSIGNED_P is
    4900                 :            :    true if we should do zero extension, else sign extension.  HIGH_P is
    4901                 :            :    true if we want the N/2 high elements, else the low elements.  */
    4902                 :            : 
    4903                 :            : void
    4904                 :       5170 : ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
    4905                 :            : {
    4906                 :       5170 :   machine_mode imode = GET_MODE (src);
    4907                 :       5170 :   rtx tmp;
    4908                 :            : 
    4909                 :       5170 :   if (TARGET_SSE4_1)
    4910                 :            :     {
    4911                 :       1183 :       rtx (*unpack)(rtx, rtx);
    4912                 :       1183 :       rtx (*extract)(rtx, rtx) = NULL;
    4913                 :       1183 :       machine_mode halfmode = BLKmode;
    4914                 :            : 
    4915                 :       1183 :       switch (imode)
    4916                 :            :         {
    4917                 :         48 :         case E_V64QImode:
    4918                 :         48 :           if (unsigned_p)
    4919                 :            :             unpack = gen_avx512bw_zero_extendv32qiv32hi2;
    4920                 :            :           else
    4921                 :         38 :             unpack = gen_avx512bw_sign_extendv32qiv32hi2;
    4922                 :         48 :           halfmode = V32QImode;
    4923                 :         48 :           extract
    4924                 :         48 :             = high_p ? gen_vec_extract_hi_v64qi : gen_vec_extract_lo_v64qi;
    4925                 :            :           break;
    4926                 :         21 :         case E_V32QImode:
    4927                 :         21 :           if (unsigned_p)
    4928                 :            :             unpack = gen_avx2_zero_extendv16qiv16hi2;
    4929                 :            :           else
    4930                 :         14 :             unpack = gen_avx2_sign_extendv16qiv16hi2;
    4931                 :         21 :           halfmode = V16QImode;
    4932                 :         21 :           extract
    4933                 :         21 :             = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
    4934                 :            :           break;
    4935                 :         30 :         case E_V32HImode:
    4936                 :         30 :           if (unsigned_p)
    4937                 :            :             unpack = gen_avx512f_zero_extendv16hiv16si2;
    4938                 :            :           else
    4939                 :         18 :             unpack = gen_avx512f_sign_extendv16hiv16si2;
    4940                 :         30 :           halfmode = V16HImode;
    4941                 :         30 :           extract
    4942                 :         30 :             = high_p ? gen_vec_extract_hi_v32hi : gen_vec_extract_lo_v32hi;
    4943                 :            :           break;
    4944                 :         52 :         case E_V16HImode:
    4945                 :         52 :           if (unsigned_p)
    4946                 :            :             unpack = gen_avx2_zero_extendv8hiv8si2;
    4947                 :            :           else
    4948                 :         32 :             unpack = gen_avx2_sign_extendv8hiv8si2;
    4949                 :         52 :           halfmode = V8HImode;
    4950                 :         52 :           extract
    4951                 :         52 :             = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
    4952                 :            :           break;
    4953                 :         16 :         case E_V16SImode:
    4954                 :         16 :           if (unsigned_p)
    4955                 :            :             unpack = gen_avx512f_zero_extendv8siv8di2;
    4956                 :            :           else
    4957                 :         14 :             unpack = gen_avx512f_sign_extendv8siv8di2;
    4958                 :         16 :           halfmode = V8SImode;
    4959                 :         16 :           extract
    4960                 :         16 :             = high_p ? gen_vec_extract_hi_v16si : gen_vec_extract_lo_v16si;
    4961                 :            :           break;
    4962                 :        140 :         case E_V8SImode:
    4963                 :        140 :           if (unsigned_p)
    4964                 :            :             unpack = gen_avx2_zero_extendv4siv4di2;
    4965                 :            :           else
    4966                 :        136 :             unpack = gen_avx2_sign_extendv4siv4di2;
    4967                 :        140 :           halfmode = V4SImode;
    4968                 :        140 :           extract
    4969                 :        140 :             = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
    4970                 :            :           break;
    4971                 :        144 :         case E_V16QImode:
    4972                 :        144 :           if (unsigned_p)
    4973                 :            :             unpack = gen_sse4_1_zero_extendv8qiv8hi2;
    4974                 :            :           else
    4975                 :         82 :             unpack = gen_sse4_1_sign_extendv8qiv8hi2;
    4976                 :            :           break;
    4977                 :        384 :         case E_V8HImode:
    4978                 :        384 :           if (unsigned_p)
    4979                 :            :             unpack = gen_sse4_1_zero_extendv4hiv4si2;
    4980                 :            :           else
    4981                 :        296 :             unpack = gen_sse4_1_sign_extendv4hiv4si2;
    4982                 :            :           break;
    4983                 :        348 :         case E_V4SImode:
    4984                 :        348 :           if (unsigned_p)
    4985                 :            :             unpack = gen_sse4_1_zero_extendv2siv2di2;
    4986                 :            :           else
    4987                 :        348 :             unpack = gen_sse4_1_sign_extendv2siv2di2;
    4988                 :            :           break;
    4989                 :          0 :         default:
    4990                 :          0 :           gcc_unreachable ();
    4991                 :            :         }
    4992                 :            : 
    4993                 :       2366 :       if (GET_MODE_SIZE (imode) >= 32)
    4994                 :            :         {
    4995                 :        307 :           tmp = gen_reg_rtx (halfmode);
    4996                 :        307 :           emit_insn (extract (tmp, src));
    4997                 :            :         }
    4998                 :        876 :       else if (high_p)
    4999                 :            :         {
    5000                 :            :           /* Shift higher 8 bytes to lower 8 bytes.  */
    5001                 :        438 :           tmp = gen_reg_rtx (V1TImode);
    5002                 :        438 :           emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
    5003                 :            :                                          GEN_INT (64)));
    5004                 :        438 :           tmp = gen_lowpart (imode, tmp);
    5005                 :            :         }
    5006                 :            :       else
    5007                 :            :         tmp = src;
    5008                 :            : 
    5009                 :       1183 :       emit_insn (unpack (dest, tmp));
    5010                 :            :     }
    5011                 :            :   else
    5012                 :            :     {
    5013                 :       3987 :       rtx (*unpack)(rtx, rtx, rtx);
    5014                 :            : 
    5015                 :       3987 :       switch (imode)
    5016                 :            :         {
    5017                 :       1796 :         case E_V16QImode:
    5018                 :       1796 :           if (high_p)
    5019                 :            :             unpack = gen_vec_interleave_highv16qi;
    5020                 :            :           else
    5021                 :        898 :             unpack = gen_vec_interleave_lowv16qi;
    5022                 :            :           break;
    5023                 :       1703 :         case E_V8HImode:
    5024                 :       1703 :           if (high_p)
    5025                 :            :             unpack = gen_vec_interleave_highv8hi;
    5026                 :            :           else
    5027                 :        851 :             unpack = gen_vec_interleave_lowv8hi;
    5028                 :            :           break;
    5029                 :        488 :         case E_V4SImode:
    5030                 :        488 :           if (high_p)
    5031                 :            :             unpack = gen_vec_interleave_highv4si;
    5032                 :            :           else
    5033                 :        240 :             unpack = gen_vec_interleave_lowv4si;
    5034                 :            :           break;
    5035                 :          0 :         default:
    5036                 :          0 :           gcc_unreachable ();
    5037                 :            :         }
    5038                 :            : 
    5039                 :       3987 :       if (unsigned_p)
    5040                 :       1954 :         tmp = force_reg (imode, CONST0_RTX (imode));
    5041                 :            :       else
    5042                 :       2033 :         tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
    5043                 :            :                                    src, pc_rtx, pc_rtx);
    5044                 :            : 
    5045                 :       3987 :       rtx tmp2 = gen_reg_rtx (imode);
    5046                 :       3987 :       emit_insn (unpack (tmp2, src, tmp));
    5047                 :       3987 :       emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
    5048                 :            :     }
    5049                 :       5170 : }
    5050                 :            : 
    5051                 :            : /* Split operands 0 and 1 into half-mode parts.  Similar to split_double_mode,
    5052                 :            :    but works for floating pointer parameters and nonoffsetable memories.
    5053                 :            :    For pushes, it returns just stack offsets; the values will be saved
    5054                 :            :    in the right order.  Maximally three parts are generated.  */
    5055                 :            : 
    5056                 :            : static int
    5057                 :    2297860 : ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
    5058                 :            : {
    5059                 :    2297860 :   int size;
    5060                 :            : 
    5061                 :    2297860 :   if (!TARGET_64BIT)
    5062                 :     967044 :     size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
    5063                 :            :   else
    5064                 :    3628210 :     size = (GET_MODE_SIZE (mode) + 4) / 8;
    5065                 :            : 
    5066                 :    2297860 :   gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
    5067                 :    2297860 :   gcc_assert (size >= 2 && size <= 4);
    5068                 :            : 
    5069                 :            :   /* Optimize constant pool reference to immediates.  This is used by fp
    5070                 :            :      moves, that force all constants to memory to allow combining.  */
    5071                 :    2297860 :   if (MEM_P (operand) && MEM_READONLY_P (operand))
    5072                 :       5046 :     operand = avoid_constant_pool_reference (operand);
    5073                 :            : 
    5074                 :    2297860 :   if (MEM_P (operand) && !offsettable_memref_p (operand))
    5075                 :            :     {
    5076                 :            :       /* The only non-offsetable memories we handle are pushes.  */
    5077                 :     593530 :       int ok = push_operand (operand, VOIDmode);
    5078                 :            : 
    5079                 :     593530 :       gcc_assert (ok);
    5080                 :            : 
    5081                 :     593530 :       operand = copy_rtx (operand);
    5082                 :     593530 :       PUT_MODE (operand, word_mode);
    5083                 :     593530 :       parts[0] = parts[1] = parts[2] = parts[3] = operand;
    5084                 :     593530 :       return size;
    5085                 :            :     }
    5086                 :            : 
    5087                 :    1704330 :   if (GET_CODE (operand) == CONST_VECTOR)
    5088                 :            :     {
    5089                 :          0 :       scalar_int_mode imode = int_mode_for_mode (mode).require ();
    5090                 :            :       /* Caution: if we looked through a constant pool memory above,
    5091                 :            :          the operand may actually have a different mode now.  That's
    5092                 :            :          ok, since we want to pun this all the way back to an integer.  */
    5093                 :          0 :       operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
    5094                 :          0 :       gcc_assert (operand != NULL);
    5095                 :          0 :       mode = imode;
    5096                 :            :     }
    5097                 :            : 
    5098                 :    1704330 :   if (!TARGET_64BIT)
    5099                 :            :     {
    5100                 :     354361 :       if (mode == DImode)
    5101                 :     351769 :         split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
    5102                 :            :       else
    5103                 :            :         {
    5104                 :       2592 :           int i;
    5105                 :            : 
    5106                 :       2592 :           if (REG_P (operand))
    5107                 :            :             {
    5108                 :         89 :               gcc_assert (reload_completed);
    5109                 :        267 :               for (i = 0; i < size; i++)
    5110                 :        178 :                 parts[i] = gen_rtx_REG (SImode, REGNO (operand) + i);
    5111                 :            :             }
    5112                 :       2503 :           else if (offsettable_memref_p (operand))
    5113                 :            :             {
    5114                 :       1695 :               operand = adjust_address (operand, SImode, 0);
    5115                 :       1695 :               parts[0] = operand;
    5116                 :       3571 :               for (i = 1; i < size; i++)
    5117                 :       1876 :                 parts[i] = adjust_address (operand, SImode, 4 * i);
    5118                 :            :             }
    5119                 :        808 :           else if (CONST_DOUBLE_P (operand))
    5120                 :            :             {
    5121                 :        808 :               const REAL_VALUE_TYPE *r;
    5122                 :        808 :               long l[4];
    5123                 :            : 
    5124                 :        808 :               r = CONST_DOUBLE_REAL_VALUE (operand);
    5125                 :        808 :               switch (mode)
    5126                 :            :                 {
    5127                 :          0 :                 case E_TFmode:
    5128                 :          0 :                   real_to_target (l, r, mode);
    5129                 :          0 :                   parts[3] = gen_int_mode (l[3], SImode);
    5130                 :          0 :                   parts[2] = gen_int_mode (l[2], SImode);
    5131                 :          0 :                   break;
    5132                 :         61 :                 case E_XFmode:
    5133                 :            :                   /* We can't use REAL_VALUE_TO_TARGET_LONG_DOUBLE since
    5134                 :            :                      long double may not be 80-bit.  */
    5135                 :         61 :                   real_to_target (l, r, mode);
    5136                 :         61 :                   parts[2] = gen_int_mode (l[2], SImode);
    5137                 :         61 :                   break;
    5138                 :        747 :                 case E_DFmode:
    5139                 :        747 :                   REAL_VALUE_TO_TARGET_DOUBLE (*r, l);
    5140                 :        747 :                   break;
    5141                 :          0 :                 default:
    5142                 :          0 :                   gcc_unreachable ();
    5143                 :            :                 }
    5144                 :        808 :               parts[1] = gen_int_mode (l[1], SImode);
    5145                 :        808 :               parts[0] = gen_int_mode (l[0], SImode);
    5146                 :            :             }
    5147                 :            :           else
    5148                 :          0 :             gcc_unreachable ();
    5149                 :            :         }
    5150                 :            :     }
    5151                 :            :   else
    5152                 :            :     {
    5153                 :    1349970 :       if (mode == TImode)
    5154                 :    1334930 :         split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
    5155                 :    1349970 :       if (mode == XFmode || mode == TFmode)
    5156                 :            :         {
    5157                 :      16261 :           machine_mode upper_mode = mode==XFmode ? SImode : DImode;
    5158                 :      15039 :           if (REG_P (operand))
    5159                 :            :             {
    5160                 :       4760 :               gcc_assert (reload_completed);
    5161                 :       4760 :               parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
    5162                 :       4760 :               parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
    5163                 :            :             }
    5164                 :      10279 :           else if (offsettable_memref_p (operand))
    5165                 :            :             {
    5166                 :       8567 :               operand = adjust_address (operand, DImode, 0);
    5167                 :       8567 :               parts[0] = operand;
    5168                 :       8567 :               parts[1] = adjust_address (operand, upper_mode, 8);
    5169                 :            :             }
    5170                 :       1712 :           else if (CONST_DOUBLE_P (operand))
    5171                 :            :             {
    5172                 :       1712 :               long l[4];
    5173                 :            : 
    5174                 :       1712 :               real_to_target (l, CONST_DOUBLE_REAL_VALUE (operand), mode);
    5175                 :            : 
    5176                 :            :               /* real_to_target puts 32-bit pieces in each long.  */
    5177                 :       3424 :               parts[0] = gen_int_mode ((l[0] & HOST_WIDE_INT_C (0xffffffff))
    5178                 :       1712 :                                        | ((l[1] & HOST_WIDE_INT_C (0xffffffff))
    5179                 :       1712 :                                           << 32), DImode);
    5180                 :            : 
    5181                 :       1712 :               if (upper_mode == SImode)
    5182                 :       1140 :                 parts[1] = gen_int_mode (l[2], SImode);
    5183                 :            :               else
    5184                 :        572 :                 parts[1]
    5185                 :        572 :                   = gen_int_mode ((l[2] & HOST_WIDE_INT_C (0xffffffff))
    5186                 :        572 :                                   | ((l[3] & HOST_WIDE_INT_C (0xffffffff))
    5187                 :        572 :                                      << 32), DImode);
    5188                 :            :             }
    5189                 :            :           else
    5190                 :          0 :             gcc_unreachable ();
    5191                 :            :         }
    5192                 :            :     }
    5193                 :            : 
    5194                 :            :   return size;
    5195                 :            : }
    5196                 :            : 
    5197                 :            : /* Emit insns to perform a move or push of DI, DF, XF, and TF values.
    5198                 :            :    Return false when normal moves are needed; true when all required
    5199                 :            :    insns have been emitted.  Operands 2-4 contain the input values
    5200                 :            :    int the correct order; operands 5-7 contain the output values.  */
    5201                 :            : 
    5202                 :            : void
    5203                 :    1150130 : ix86_split_long_move (rtx operands[])
    5204                 :            : {
    5205                 :    1150130 :   rtx part[2][4];
    5206                 :    1150130 :   int nparts, i, j;
    5207                 :    1150130 :   int push = 0;
    5208                 :    1150130 :   int collisions = 0;
    5209                 :    1150130 :   machine_mode mode = GET_MODE (operands[0]);
    5210                 :    1150130 :   bool collisionparts[4];
    5211                 :            : 
    5212                 :            :   /* The DFmode expanders may ask us to move double.
    5213                 :            :      For 64bit target this is single move.  By hiding the fact
    5214                 :            :      here we simplify i386.md splitters.  */
    5215                 :    2058380 :   if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8)
    5216                 :            :     {
    5217                 :            :       /* Optimize constant pool reference to immediates.  This is used by
    5218                 :            :          fp moves, that force all constants to memory to allow combining.  */
    5219                 :            : 
    5220                 :       1201 :       if (MEM_P (operands[1])
    5221                 :        892 :           && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
    5222                 :       1567 :           && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
    5223                 :         93 :         operands[1] = get_pool_constant (XEXP (operands[1], 0));
    5224                 :       1201 :       if (push_operand (operands[0], VOIDmode))
    5225                 :            :         {
    5226                 :       1201 :           operands[0] = copy_rtx (operands[0]);
    5227                 :       1201 :           PUT_MODE (operands[0], word_mode);
    5228                 :            :         }
    5229                 :            :       else
    5230                 :          0 :         operands[0] = gen_lowpart (DImode, operands[0]);
    5231                 :       1201 :       operands[1] = gen_lowpart (DImode, operands[1]);
    5232                 :       1201 :       emit_move_insn (operands[0], operands[1]);
    5233                 :       1201 :       return;
    5234                 :            :     }
    5235                 :            : 
    5236                 :            :   /* The only non-offsettable memory we handle is push.  */
    5237                 :    1148930 :   if (push_operand (operands[0], VOIDmode))
    5238                 :            :     push = 1;
    5239                 :            :   else
    5240                 :     555401 :     gcc_assert (!MEM_P (operands[0])
    5241                 :            :                 || offsettable_memref_p (operands[0]));
    5242                 :            : 
    5243                 :    1148930 :   nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
    5244                 :    1148930 :   ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
    5245                 :            : 
    5246                 :            :   /* When emitting push, take care for source operands on the stack.  */
    5247                 :     593530 :   if (push && MEM_P (operands[1])
    5248                 :    1656440 :       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
    5249                 :            :     {
    5250                 :      90077 :       rtx src_base = XEXP (part[1][nparts - 1], 0);
    5251                 :            : 
    5252                 :            :       /* Compensate for the stack decrement by 4.  */
    5253                 :      90077 :       if (!TARGET_64BIT && nparts == 3
    5254                 :      33640 :           && mode == XFmode && TARGET_128BIT_LONG_DOUBLE)
    5255                 :          0 :         src_base = plus_constant (Pmode, src_base, 4);
    5256                 :            : 
    5257                 :            :       /* src_base refers to the stack pointer and is
    5258                 :            :          automatically decreased by emitted push.  */
    5259                 :     270284 :       for (i = 0; i < nparts; i++)
    5260                 :     180207 :         part[1][i] = change_address (part[1][i],
    5261                 :     180207 :                                      GET_MODE (part[1][i]), src_base);
    5262                 :            :     }
    5263                 :            : 
    5264                 :            :   /* We need to do copy in the right order in case an address register
    5265                 :            :      of the source overlaps the destination.  */
    5266                 :    1148930 :   if (REG_P (part[0][0]) && MEM_P (part[1][0]))
    5267                 :            :     {
    5268                 :            :       rtx tmp;
    5269                 :            : 
    5270                 :     580254 :       for (i = 0; i < nparts; i++)
    5271                 :            :         {
    5272                 :     386836 :           collisionparts[i]
    5273                 :     386836 :             = reg_overlap_mentioned_p (part[0][i], XEXP (part[1][0], 0));
    5274                 :     386836 :           if (collisionparts[i])
    5275                 :      10485 :             collisions++;
    5276                 :            :         }
    5277                 :            : 
    5278                 :            :       /* Collision in the middle part can be handled by reordering.  */
    5279                 :     193418 :       if (collisions == 1 && nparts == 3 && collisionparts [1])
    5280                 :            :         {
    5281                 :          0 :           std::swap (part[0][1], part[0][2]);
    5282                 :          0 :           std::swap (part[1][1], part[1][2]);
    5283                 :            :         }
    5284                 :     193418 :       else if (collisions == 1
    5285                 :     193418 :                && nparts == 4
    5286                 :          0 :                && (collisionparts [1] || collisionparts [2]))
    5287                 :            :         {
    5288                 :          0 :           if (collisionparts [1])
    5289                 :            :             {
    5290                 :          0 :               std::swap (part[0][1], part[0][2]);
    5291                 :          0 :               std::swap (part[1][1], part[1][2]);
    5292                 :            :             }
    5293                 :            :           else
    5294                 :            :             {
    5295                 :          0 :               std::swap (part[0][2], part[0][3]);
    5296                 :          0 :               std::swap (part[1][2], part[1][3]);
    5297                 :            :             }
    5298                 :            :         }
    5299                 :            : 
    5300                 :            :       /* If there are more collisions, we can't handle it by reordering.
    5301                 :            :          Do an lea to the last part and use only one colliding move.  */
    5302                 :     193418 :       else if (collisions > 1)
    5303                 :            :         {
    5304                 :         48 :           rtx base, addr;
    5305                 :            : 
    5306                 :         48 :           collisions = 1;
    5307                 :            : 
    5308                 :         48 :           base = part[0][nparts - 1];
    5309                 :            : 
    5310                 :            :           /* Handle the case when the last part isn't valid for lea.
    5311                 :            :              Happens in 64-bit mode storing the 12-byte XFmode.  */
    5312                 :         79 :           if (GET_MODE (base) != Pmode)
    5313                 :          0 :             base = gen_rtx_REG (Pmode, REGNO (base));
    5314                 :            : 
    5315                 :         48 :           addr = XEXP (part[1][0], 0);
    5316                 :         48 :           if (TARGET_TLS_DIRECT_SEG_REFS)
    5317                 :            :             {
    5318                 :         48 :               struct ix86_address parts;
    5319                 :         48 :               int ok = ix86_decompose_address (addr, &parts);
    5320                 :         48 :               gcc_assert (ok);
    5321                 :            :               /* It is not valid to use %gs: or %fs: in lea.  */
    5322                 :         48 :               gcc_assert (parts.seg == ADDR_SPACE_GENERIC);
    5323                 :            :             }
    5324                 :         48 :           emit_insn (gen_rtx_SET (base, addr));
    5325                 :         48 :           part[1][0] = replace_equiv_address (part[1][0], base);
    5326                 :         96 :           for (i = 1; i < nparts; i++)
    5327                 :            :             {
    5328                 :        110 :               tmp = plus_constant (Pmode, base, UNITS_PER_WORD * i);
    5329                 :         48 :               part[1][i] = replace_equiv_address (part[1][i], tmp);
    5330                 :            :             }
    5331                 :            :         }
    5332                 :            :     }
    5333                 :            : 
    5334                 :    1148930 :   if (push)
    5335                 :            :     {
    5336                 :     593530 :       if (!TARGET_64BIT)
    5337                 :            :         {
    5338                 :     129397 :           if (nparts == 3)
    5339                 :            :             {
    5340                 :        230 :               if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
    5341                 :          0 :                 emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4)));
    5342                 :        230 :               emit_move_insn (part[0][2], part[1][2]);
    5343                 :            :             }
    5344                 :     129167 :           else if (nparts == 4)
    5345                 :            :             {
    5346                 :          0 :               emit_move_insn (part[0][3], part[1][3]);
    5347                 :          0 :               emit_move_insn (part[0][2], part[1][2]);
    5348                 :            :             }
    5349                 :            :         }
    5350                 :            :       else
    5351                 :            :         {
    5352                 :            :           /* In 64bit mode we don't have 32bit push available.  In case this is
    5353                 :            :              register, it is OK - we will just use larger counterpart.  We also
    5354                 :            :              retype memory - these comes from attempt to avoid REX prefix on
    5355                 :            :              moving of second half of TFmode value.  */
    5356                 :     464133 :           if (GET_MODE (part[1][1]) == SImode)
    5357                 :            :             {
    5358                 :       8094 :               switch (GET_CODE (part[1][1]))
    5359                 :            :                 {
    5360                 :       5820 :                 case MEM:
    5361                 :       5820 :                   part[1][1] = adjust_address (part[1][1], DImode, 0);
    5362                 :       5820 :                   break;
    5363                 :            : 
    5364                 :       2274 :                 case REG:
    5365                 :       2274 :                   part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
    5366                 :       2274 :                   break;
    5367                 :            : 
    5368                 :          0 :                 default:
    5369                 :          0 :                   gcc_unreachable ();
    5370                 :            :                 }
    5371                 :            : 
    5372                 :       8094 :               if (GET_MODE (part[1][0]) == SImode)
    5373                 :          0 :                 part[1][0] = part[1][1];
    5374                 :            :             }
    5375                 :            :         }
    5376                 :     593530 :       emit_move_insn (part[0][1], part[1][1]);
    5377                 :     593530 :       emit_move_insn (part[0][0], part[1][0]);
    5378                 :     593530 :       return;
    5379                 :            :     }
    5380                 :            : 
    5381                 :            :   /* Choose correct order to not overwrite the source before it is copied.  */
    5382                 :     555401 :   if ((REG_P (part[0][0])
    5383                 :     353125 :        && REG_P (part[1][1])
    5384                 :      74945 :        && (REGNO (part[0][0]) == REGNO (part[1][1])
    5385                 :      68345 :            || (nparts == 3
    5386                 :          0 :                && REGNO (part[0][0]) == REGNO (part[1][2]))
    5387                 :      68345 :            || (nparts == 4
    5388                 :          0 :                && REGNO (part[0][0]) == REGNO (part[1][3]))))
    5389                 :     901926 :       || (collisions > 0
    5390                 :      10437 :           && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
    5391                 :            :     {
    5392                 :      50286 :       for (i = 0, j = nparts - 1; i < nparts; i++, j--)
    5393                 :            :         {
    5394                 :      33524 :           operands[2 + i] = part[0][j];
    5395                 :      33524 :           operands[6 + i] = part[1][j];
    5396                 :            :         }
    5397                 :            :     }
    5398                 :            :   else
    5399                 :            :     {
    5400                 :    1615920 :       for (i = 0; i < nparts; i++)
    5401                 :            :         {
    5402                 :    1077280 :           operands[2 + i] = part[0][i];
    5403                 :    1077280 :           operands[6 + i] = part[1][i];
    5404                 :            :         }
    5405                 :            :     }
    5406                 :            : 
    5407                 :            :   /* If optimizing for size, attempt to locally unCSE nonzero constants.  */
    5408                 :     555401 :   if (optimize_insn_for_size_p ())
    5409                 :            :     {
    5410                 :      34376 :       for (j = 0; j < nparts - 1; j++)
    5411                 :      17188 :         if (CONST_INT_P (operands[6 + j])
    5412                 :       7895 :             && operands[6 + j] != const0_rtx
    5413                 :       1664 :             && REG_P (operands[2 + j]))
    5414                 :       2946 :           for (i = j; i < nparts - 1; i++)
    5415                 :       1473 :             if (CONST_INT_P (operands[7 + i])
    5416                 :       1473 :                 && INTVAL (operands[7 + i]) == INTVAL (operands[6 + j]))
    5417                 :         54 :               operands[7 + i] = operands[2 + j];
    5418                 :            :     }
    5419                 :            : 
    5420                 :    1666210 :   for (i = 0; i < nparts; i++)
    5421                 :    1110810 :     emit_move_insn (operands[2 + i], operands[6 + i]);
    5422                 :            : 
    5423                 :            :   return;
    5424                 :            : }
    5425                 :            : 
    5426                 :            : /* Helper function of ix86_split_ashl used to generate an SImode/DImode
    5427                 :            :    left shift by a constant, either using a single shift or
    5428                 :            :    a sequence of add instructions.  */
    5429                 :            : 
    5430                 :            : static void
    5431                 :       2516 : ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
    5432                 :            : {
    5433                 :       2516 :   if (count == 1
    5434                 :       2516 :       || (count * ix86_cost->add <= ix86_cost->shift_const
    5435                 :          0 :           && !optimize_insn_for_size_p ()))
    5436                 :            :     {
    5437                 :       1828 :       while (count-- > 0)
    5438                 :        914 :         emit_insn (gen_add2_insn (operand, operand));
    5439                 :            :     }
    5440                 :            :   else
    5441                 :            :     {
    5442                 :       1602 :       rtx (*insn)(rtx, rtx, rtx);
    5443                 :            : 
    5444                 :       1602 :       insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
    5445                 :       1602 :       emit_insn (insn (operand, operand, GEN_INT (count)));
    5446                 :            :     }
    5447                 :       2516 : }
    5448                 :            : 
    5449                 :            : void
    5450                 :       6111 : ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
    5451                 :            : {
    5452                 :       6111 :   rtx (*gen_ashl3)(rtx, rtx, rtx);
    5453                 :       6111 :   rtx (*gen_shld)(rtx, rtx, rtx);
    5454                 :       6111 :   int half_width = GET_MODE_BITSIZE (mode) >> 1;
    5455                 :       6111 :   machine_mode half_mode;
    5456                 :            : 
    5457                 :       6111 :   rtx low[2], high[2];
    5458                 :       6111 :   int count;
    5459                 :            : 
    5460                 :       6111 :   if (CONST_INT_P (operands[2]))
    5461                 :            :     {
    5462                 :       5020 :       split_double_mode (mode, operands, 2, low, high);
    5463                 :       5020 :       count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
    5464                 :            : 
    5465                 :       5020 :       if (count >= half_width)
    5466                 :            :         {
    5467                 :       2616 :           emit_move_insn (high[0], low[1]);
    5468                 :       2616 :           emit_move_insn (low[0], const0_rtx);
    5469                 :            : 
    5470                 :       2616 :           if (count > half_width)
    5471                 :        112 :             ix86_expand_ashl_const (high[0], count - half_width, mode);
    5472                 :            :         }
    5473                 :            :       else
    5474                 :            :         {
    5475                 :       2404 :           gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
    5476                 :            : 
    5477                 :       2404 :           if (!rtx_equal_p (operands[0], operands[1]))
    5478                 :          0 :             emit_move_insn (operands[0], operands[1]);
    5479                 :            : 
    5480                 :       2404 :           emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
    5481                 :       2404 :           ix86_expand_ashl_const (low[0], count, mode);
    5482                 :            :         }
    5483                 :       5189 :       return;
    5484                 :            :     }
    5485                 :            : 
    5486                 :       1091 :   split_double_mode (mode, operands, 1, low, high);
    5487                 :       1218 :   half_mode = mode == DImode ? SImode : DImode;
    5488                 :            : 
    5489                 :       1091 :   gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
    5490                 :            : 
    5491                 :       1091 :   if (operands[1] == const1_rtx)
    5492                 :            :     {
    5493                 :            :       /* Assuming we've chosen a QImode capable registers, then 1 << N
    5494                 :            :          can be done with two 32/64-bit shifts, no branches, no cmoves.  */
    5495                 :        169 :       if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
    5496                 :            :         {
    5497                 :         83 :           rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
    5498                 :            : 
    5499                 :         83 :           ix86_expand_clear (low[0]);
    5500                 :         83 :           ix86_expand_clear (high[0]);
    5501                 :         83 :           emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width)));
    5502                 :            : 
    5503                 :         83 :           d = gen_lowpart (QImode, low[0]);
    5504                 :         83 :           d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
    5505                 :         83 :           s = gen_rtx_EQ (QImode, flags, const0_rtx);
    5506                 :         83 :           emit_insn (gen_rtx_SET (d, s));
    5507                 :            : 
    5508                 :         83 :           d = gen_lowpart (QImode, high[0]);
    5509                 :         83 :           d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
    5510                 :         83 :           s = gen_rtx_NE (QImode, flags, const0_rtx);
    5511                 :         83 :           emit_insn (gen_rtx_SET (d, s));
    5512                 :            :         }
    5513                 :            : 
    5514                 :            :       /* Otherwise, we can get the same results by manually performing
    5515                 :            :          a bit extract operation on bit 5/6, and then performing the two
    5516                 :            :          shifts.  The two methods of getting 0/1 into low/high are exactly
    5517                 :            :          the same size.  Avoiding the shift in the bit extract case helps
    5518                 :            :          pentium4 a bit; no one else seems to care much either way.  */
    5519                 :            :       else
    5520                 :            :         {
    5521                 :         86 :           rtx (*gen_lshr3)(rtx, rtx, rtx);
    5522                 :         86 :           rtx (*gen_and3)(rtx, rtx, rtx);
    5523                 :         86 :           rtx (*gen_xor3)(rtx, rtx, rtx);
    5524                 :         86 :           HOST_WIDE_INT bits;
    5525                 :         86 :           rtx x;
    5526                 :            : 
    5527                 :         86 :           if (mode == DImode)
    5528                 :            :             {
    5529                 :            :               gen_lshr3 = gen_lshrsi3;
    5530                 :            :               gen_and3 = gen_andsi3;
    5531                 :            :               gen_xor3 = gen_xorsi3;
    5532                 :            :               bits = 5;
    5533                 :            :             }
    5534                 :            :           else
    5535                 :            :             {
    5536                 :          0 :               gen_lshr3 = gen_lshrdi3;
    5537                 :          0 :               gen_and3 = gen_anddi3;
    5538                 :          0 :               gen_xor3 = gen_xordi3;
    5539                 :          0 :               bits = 6;
    5540                 :            :             }
    5541                 :            : 
    5542                 :         86 :           if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
    5543                 :          0 :             x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
    5544                 :            :           else
    5545                 :         86 :             x = gen_lowpart (half_mode, operands[2]);
    5546                 :         86 :           emit_insn (gen_rtx_SET (high[0], x));
    5547                 :            : 
    5548                 :         86 :           emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
    5549                 :         86 :           emit_insn (gen_and3 (high[0], high[0], const1_rtx));
    5550                 :         86 :           emit_move_insn (low[0], high[0]);
    5551                 :         86 :           emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
    5552                 :            :         }
    5553                 :            : 
    5554                 :        169 :       emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
    5555                 :        169 :       emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
    5556                 :        169 :       return;
    5557                 :            :     }
    5558                 :            : 
    5559                 :        922 :   if (operands[1] == constm1_rtx)
    5560                 :            :     {
    5561                 :            :       /* For -1 << N, we can avoid the shld instruction, because we
    5562                 :            :          know that we're shifting 0...31/63 ones into a -1.  */
    5563                 :         64 :       emit_move_insn (low[0], constm1_rtx);
    5564                 :         64 :       if (optimize_insn_for_size_p ())
    5565                 :          3 :         emit_move_insn (high[0], low[0]);
    5566                 :            :       else
    5567                 :         61 :         emit_move_insn (high[0], constm1_rtx);
    5568                 :            :     }
    5569                 :            :   else
    5570                 :            :     {
    5571                 :        858 :       gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
    5572                 :            : 
    5573                 :        858 :       if (!rtx_equal_p (operands[0], operands[1]))
    5574                 :          3 :         emit_move_insn (operands[0], operands[1]);
    5575                 :            : 
    5576                 :        858 :       split_double_mode (mode, operands, 1, low, high);
    5577                 :        858 :       emit_insn (gen_shld (high[0], low[0], operands[2]));
    5578                 :            :     }
    5579                 :            : 
    5580                 :        922 :   emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
    5581                 :            : 
    5582                 :        922 :   if (TARGET_CMOVE && scratch)
    5583                 :            :     {
    5584                 :        653 :       ix86_expand_clear (scratch);
    5585                 :        653 :       emit_insn (gen_x86_shift_adj_1
    5586                 :            :                  (half_mode, high[0], low[0], operands[2], scratch));
    5587                 :            :     }
    5588                 :            :   else
    5589                 :        269 :     emit_insn (gen_x86_shift_adj_2 (half_mode, high[0], low[0], operands[2]));
    5590                 :            : }
    5591                 :            : 
    5592                 :            : void
    5593                 :       2686 : ix86_split_ashr (rtx *operands, rtx scratch, machine_mode mode)
    5594                 :            : {
    5595                 :       5372 :   rtx (*gen_ashr3)(rtx, rtx, rtx)
    5596                 :       2686 :     = mode == DImode ? gen_ashrsi3 : gen_ashrdi3;
    5597                 :       2686 :   rtx (*gen_shrd)(rtx, rtx, rtx);
    5598                 :       2686 :   int half_width = GET_MODE_BITSIZE (mode) >> 1;
    5599                 :            : 
    5600                 :       2686 :   rtx low[2], high[2];
    5601                 :       2686 :   int count;
    5602                 :            : 
    5603                 :       2686 :   if (CONST_INT_P (operands[2]))
    5604                 :            :     {
    5605                 :       2592 :       split_double_mode (mode, operands, 2, low, high);
    5606                 :       2592 :       count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
    5607                 :            : 
    5608                 :       5184 :       if (count == GET_MODE_BITSIZE (mode) - 1)
    5609                 :            :         {
    5610                 :         25 :           emit_move_insn (high[0], high[1]);
    5611                 :         25 :           emit_insn (gen_ashr3 (high[0], high[0],
    5612                 :         25 :                                 GEN_INT (half_width - 1)));
    5613                 :         25 :           emit_move_insn (low[0], high[0]);
    5614                 :            : 
    5615                 :            :         }
    5616                 :       2567 :       else if (count >= half_width)
    5617                 :            :         {
    5618                 :       1657 :           emit_move_insn (low[0], high[1]);
    5619                 :       1657 :           emit_move_insn (high[0], low[0]);
    5620                 :       1657 :           emit_insn (gen_ashr3 (high[0], high[0],
    5621                 :       1657 :                                 GEN_INT (half_width - 1)));
    5622                 :            : 
    5623                 :       1657 :           if (count > half_width)
    5624                 :          0 :             emit_insn (gen_ashr3 (low[0], low[0],
    5625                 :          0 :                                   GEN_INT (count - half_width)));
    5626                 :            :         }
    5627                 :            :       else
    5628                 :            :         {
    5629                 :        910 :           gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
    5630                 :            : 
    5631                 :        910 :           if (!rtx_equal_p (operands[0], operands[1]))
    5632                 :          0 :             emit_move_insn (operands[0], operands[1]);
    5633                 :            : 
    5634                 :        910 :           emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
    5635                 :        910 :           emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count)));
    5636                 :            :         }
    5637                 :            :     }
    5638                 :            :   else
    5639                 :            :     {
    5640                 :         94 :       machine_mode half_mode;
    5641                 :            : 
    5642                 :         94 :       gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
    5643                 :            : 
    5644                 :         94 :      if (!rtx_equal_p (operands[0], operands[1]))
    5645                 :          0 :         emit_move_insn (operands[0], operands[1]);
    5646                 :            : 
    5647                 :         94 :       split_double_mode (mode, operands, 1, low, high);
    5648                 :        128 :       half_mode = mode == DImode ? SImode : DImode;
    5649                 :            : 
    5650                 :         94 :       emit_insn (gen_shrd (low[0], high[0], operands[2]));
    5651                 :         94 :       emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
    5652                 :            : 
    5653                 :         94 :       if (TARGET_CMOVE && scratch)
    5654                 :            :         {
    5655                 :         68 :           emit_move_insn (scratch, high[0]);
    5656                 :         68 :           emit_insn (gen_ashr3 (scratch, scratch,
    5657                 :         68 :                                 GEN_INT (half_width - 1)));
    5658                 :         68 :           emit_insn (gen_x86_shift_adj_1
    5659                 :            :                      (half_mode, low[0], high[0], operands[2], scratch));
    5660                 :            :         }
    5661                 :            :       else
    5662                 :         26 :         emit_insn (gen_x86_shift_adj_3
    5663                 :            :                    (half_mode, low[0], high[0], operands[2]));
    5664                 :            :     }
    5665                 :       2686 : }
    5666                 :            : 
    5667                 :            : void
    5668                 :      10070 : ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
    5669                 :            : {
    5670                 :      20140 :   rtx (*gen_lshr3)(rtx, rtx, rtx)
    5671                 :      10070 :     = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
    5672                 :      10070 :   rtx (*gen_shrd)(rtx, rtx, rtx);
    5673                 :      10070 :   int half_width = GET_MODE_BITSIZE (mode) >> 1;
    5674                 :            : 
    5675                 :      10070 :   rtx low[2], high[2];
    5676                 :      10070 :   int count;
    5677                 :            : 
    5678                 :      10070 :   if (CONST_INT_P (operands[2]))
    5679                 :            :     {
    5680                 :       9322 :       split_double_mode (mode, operands, 2, low, high);
    5681                 :       9322 :       count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
    5682                 :            : 
    5683                 :       9322 :       if (count >= half_width)
    5684                 :            :         {
    5685                 :       8492 :           emit_move_insn (low[0], high[1]);
    5686                 :       8492 :           ix86_expand_clear (high[0]);
    5687                 :            : 
    5688                 :       8492 :           if (count > half_width)
    5689                 :        312 :             emit_insn (gen_lshr3 (low[0], low[0],
    5690                 :        312 :                                   GEN_INT (count - half_width)));
    5691                 :            :         }
    5692                 :            :       else
    5693                 :            :         {
    5694                 :        830 :           gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
    5695                 :            : 
    5696                 :        830 :           if (!rtx_equal_p (operands[0], operands[1]))
    5697                 :          0 :             emit_move_insn (operands[0], operands[1]);
    5698                 :            : 
    5699                 :        830 :           emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
    5700                 :        830 :           emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count)));
    5701                 :            :         }
    5702                 :            :     }
    5703                 :            :   else
    5704                 :            :     {
    5705                 :        748 :       machine_mode half_mode;
    5706                 :            : 
    5707                 :        748 :       gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
    5708                 :            : 
    5709                 :        748 :       if (!rtx_equal_p (operands[0], operands[1]))
    5710                 :          0 :         emit_move_insn (operands[0], operands[1]);
    5711                 :            : 
    5712                 :        748 :       split_double_mode (mode, operands, 1, low, high);
    5713                 :        845 :       half_mode = mode == DImode ? SImode : DImode;
    5714                 :            : 
    5715                 :        748 :       emit_insn (gen_shrd (low[0], high[0], operands[2]));
    5716                 :        748 :       emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
    5717                 :            : 
    5718                 :        748 :       if (TARGET_CMOVE && scratch)
    5719                 :            :         {
    5720                 :        590 :           ix86_expand_clear (scratch);
    5721                 :        590 :           emit_insn (gen_x86_shift_adj_1
    5722                 :            :                      (half_mode, low[0], high[0], operands[2], scratch));
    5723                 :            :         }
    5724                 :            :       else
    5725                 :        158 :         emit_insn (gen_x86_shift_adj_2
    5726                 :            :                    (half_mode, low[0], high[0], operands[2]));
    5727                 :            :     }
    5728                 :      10070 : }
    5729                 :            : 
    5730                 :            : /* Return mode for the memcpy/memset loop counter.  Prefer SImode over
    5731                 :            :    DImode for constant loop counts.  */
    5732                 :            : 
    5733                 :            : static machine_mode
    5734                 :       5864 : counter_mode (rtx count_exp)
    5735                 :            : {
    5736                 :       5854 :   if (GET_MODE (count_exp) != VOIDmode)
    5737                 :       2565 :     return GET_MODE (count_exp);
    5738                 :       3299 :   if (!CONST_INT_P (count_exp))
    5739                 :          0 :     return Pmode;
    5740                 :            :   if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff))
    5741                 :            :     return DImode;
    5742                 :            :   return SImode;
    5743                 :            : }
    5744                 :            : 
    5745                 :            : /* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
    5746                 :            :    to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
    5747                 :            :    specified in bytes.  When ISSETMEM is TRUE, output the equivalent loop to set
    5748                 :            :    memory by VALUE (supposed to be in MODE).
    5749                 :            : 
    5750                 :            :    The size is rounded down to whole number of chunk size moved at once.
    5751                 :            :    SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info.  */
    5752                 :            : 
    5753                 :            : 
    5754                 :            : static void
    5755                 :       3465 : expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem,
    5756                 :            :                                rtx destptr, rtx srcptr, rtx value,
    5757                 :            :                                rtx count, machine_mode mode, int unroll,
    5758                 :            :                                int expected_size, bool issetmem)
    5759                 :            : {
    5760                 :       3465 :   rtx_code_label *out_label, *top_label;
    5761                 :       3465 :   rtx iter, tmp;
    5762                 :       3465 :   machine_mode iter_mode = counter_mode (count);
    5763                 :       3465 :   int piece_size_n = GET_MODE_SIZE (mode) * unroll;
    5764                 :       3465 :   rtx piece_size = GEN_INT (piece_size_n);
    5765                 :       6930 :   rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
    5766                 :       3465 :   rtx size;
    5767                 :       3465 :   int i;
    5768                 :            : 
    5769                 :       3465 :   top_label = gen_label_rtx ();
    5770                 :       3465 :   out_label = gen_label_rtx ();
    5771                 :       3465 :   iter = gen_reg_rtx (iter_mode);
    5772                 :            : 
    5773                 :       3465 :   size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
    5774                 :            :                               NULL, 1, OPTAB_DIRECT);
    5775                 :            :   /* Those two should combine.  */
    5776                 :       3465 :   if (piece_size == const1_rtx)
    5777                 :            :     {
    5778                 :        763 :       emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL_RTX, iter_mode,
    5779                 :            :                                true, out_label);
    5780                 :        763 :       predict_jump (REG_BR_PROB_BASE * 10 / 100);
    5781                 :            :     }
    5782                 :       3465 :   emit_move_insn (iter, const0_rtx);
    5783                 :            : 
    5784                 :       3465 :   emit_label (top_label);
    5785                 :            : 
    5786                 :       5392 :   tmp = convert_modes (Pmode, iter_mode, iter, true);
    5787                 :            : 
    5788                 :            :   /* This assert could be relaxed - in this case we'll need to compute
    5789                 :            :      smallest power of two, containing in PIECE_SIZE_N and pass it to
    5790                 :            :      offset_address.  */
    5791                 :       3465 :   gcc_assert ((piece_size_n & (piece_size_n - 1)) == 0);
    5792                 :       3465 :   destmem = offset_address (destmem, tmp, piece_size_n);
    5793                 :       3465 :   destmem = adjust_address (destmem, mode, 0);
    5794                 :            : 
    5795                 :       3465 :   if (!issetmem)
    5796                 :            :     {
    5797                 :       1255 :       srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
    5798                 :       1255 :       srcmem = adjust_address (srcmem, mode, 0);
    5799                 :            : 
    5800                 :            :       /* When unrolling for chips that reorder memory reads and writes,
    5801                 :            :          we can save registers by using single temporary.
    5802                 :            :          Also using 4 temporaries is overkill in 32bit mode.  */
    5803                 :       1255 :       if (!TARGET_64BIT && 0)
    5804                 :            :         {
    5805                 :            :           for (i = 0; i < unroll; i++)
    5806                 :            :             {
    5807                 :            :               if (i)
    5808                 :            :                 {
    5809                 :            :                   destmem = adjust_address (copy_rtx (destmem), mode,
    5810                 :            :                                             GET_MODE_SIZE (mode));
    5811                 :            :                   srcmem = adjust_address (copy_rtx (srcmem), mode,
    5812                 :            :                                            GET_MODE_SIZE (mode));
    5813                 :            :                 }
    5814                 :            :               emit_move_insn (destmem, srcmem);
    5815                 :            :             }
    5816                 :            :         }
    5817                 :            :       else
    5818                 :            :         {
    5819                 :       1255 :           rtx tmpreg[4];
    5820                 :       1255 :           gcc_assert (unroll <= 4);
    5821                 :       2534 :           for (i = 0; i < unroll; i++)
    5822                 :            :             {
    5823                 :       1279 :               tmpreg[i] = gen_reg_rtx (mode);
    5824                 :       1279 :               if (i)
    5825                 :         48 :                 srcmem = adjust_address (copy_rtx (srcmem), mode,
    5826                 :            :                                          GET_MODE_SIZE (mode));
    5827                 :       1279 :               emit_move_insn (tmpreg[i], srcmem);
    5828                 :            :             }
    5829                 :       2534 :           for (i = 0; i < unroll; i++)
    5830                 :            :             {
    5831                 :       1279 :               if (i)
    5832                 :         48 :                 destmem = adjust_address (copy_rtx (destmem), mode,
    5833                 :            :                                           GET_MODE_SIZE (mode));
    5834                 :       1279 :               emit_move_insn (destmem, tmpreg[i]);
    5835                 :            :             }
    5836                 :            :         }
    5837                 :            :     }
    5838                 :            :   else
    5839                 :       4435 :     for (i = 0; i < unroll; i++)
    5840                 :            :       {
    5841                 :       2225 :         if (i)
    5842                 :         30 :           destmem = adjust_address (copy_rtx (destmem), mode,
    5843                 :            :                                     GET_MODE_SIZE (mode));
    5844                 :       2225 :         emit_move_insn (destmem, value);
    5845                 :            :       }
    5846                 :            : 
    5847                 :       3465 :   tmp = expand_simple_binop (iter_mode, PLUS, iter, piece_size, iter,
    5848                 :            :                              true, OPTAB_LIB_WIDEN);
    5849                 :       3465 :   if (tmp != iter)
    5850                 :          0 :     emit_move_insn (iter, tmp);
    5851                 :            : 
    5852                 :       3465 :   emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
    5853                 :            :                            true, top_label);
    5854                 :       3465 :   if (expected_size != -1)
    5855                 :            :     {
    5856                 :       1828 :       expected_size /= GET_MODE_SIZE (mode) * unroll;
    5857                 :       1828 :       if (expected_size == 0)
    5858                 :          1 :         predict_jump (0);
    5859                 :       1827 :       else if (expected_size > REG_BR_PROB_BASE)
    5860                 :          0 :         predict_jump (REG_BR_PROB_BASE - 1);
    5861                 :            :       else
    5862                 :       1827 :         predict_jump (REG_BR_PROB_BASE - (REG_BR_PROB_BASE + expected_size / 2)
    5863                 :       1827 :                       / expected_size);
    5864                 :            :     }
    5865                 :            :   else
    5866                 :       1637 :     predict_jump (REG_BR_PROB_BASE * 80 / 100);
    5867                 :       3465 :   iter = ix86_zero_extend_to_Pmode (iter);
    5868                 :       5392 :   tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
    5869                 :            :                              true, OPTAB_LIB_WIDEN);
    5870                 :       3465 :   if (tmp != destptr)
    5871                 :          0 :     emit_move_insn (destptr, tmp);
    5872                 :       3465 :   if (!issetmem)
    5873                 :            :     {
    5874                 :       1401 :       tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
    5875                 :            :                                  true, OPTAB_LIB_WIDEN);
    5876                 :       1255 :       if (tmp != srcptr)
    5877                 :          0 :         emit_move_insn (srcptr, tmp);
    5878                 :            :     }
    5879                 :       3465 :   emit_label (out_label);
    5880                 :       3465 : }
    5881                 :            : 
    5882                 :            : /* Divide COUNTREG by SCALE.  */
    5883                 :            : static rtx
    5884                 :      44777 : scale_counter (rtx countreg, int scale)
    5885                 :            : {
    5886                 :      44777 :   rtx sc;
    5887                 :            : 
    5888                 :      44777 :   if (scale == 1)
    5889                 :            :     return countreg;
    5890                 :      41201 :   if (CONST_INT_P (countreg))
    5891                 :      38911 :     return GEN_INT (INTVAL (countreg) / scale);
    5892                 :       2290 :   gcc_assert (REG_P (countreg));
    5893                 :            : 
    5894                 :       6870 :   sc = expand_simple_binop (GET_MODE (countreg), LSHIFTRT, countreg,
    5895                 :       4580 :                             GEN_INT (exact_log2 (scale)),
    5896                 :            :                             NULL, 1, OPTAB_DIRECT);
    5897                 :       2290 :   return sc;
    5898                 :            : }
    5899                 :            : 
    5900                 :            : /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
    5901                 :            :    When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
    5902                 :            :    When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
    5903                 :            :    For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
    5904                 :            :    ORIG_VALUE is the original value passed to memset to fill the memory with.
    5905                 :            :    Other arguments have same meaning as for previous function.  */
    5906                 :            : 
    5907                 :            : static void
    5908                 :      44777 : expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
    5909                 :            :                            rtx destptr, rtx srcptr, rtx value, rtx orig_value,
    5910                 :            :                            rtx count,
    5911                 :            :                            machine_mode mode, bool issetmem)
    5912                 :            : {
    5913                 :      44777 :   rtx destexp;
    5914                 :      44777 :   rtx srcexp;
    5915                 :      44777 :   rtx countreg;
    5916                 :      44777 :   HOST_WIDE_INT rounded_count;
    5917                 :            : 
    5918                 :            :   /* If possible, it is shorter to use rep movs.
    5919                 :            :      TODO: Maybe it is better to move this logic to decide_alg.  */
    5920                 :      44777 :   if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
    5921                 :        218 :       && (!issetmem || orig_value == const0_rtx))
    5922                 :          0 :     mode = SImode;
    5923                 :            : 
    5924                 :      44777 :   if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
    5925                 :      42658 :     destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
    5926                 :            : 
    5927                 :      89554 :   countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
    5928                 :      44777 :                                                        GET_MODE_SIZE (mode)));
    5929                 :      44777 :   if (mode != QImode)
    5930                 :            :     {
    5931                 :      96356 :       destexp = gen_rtx_ASHIFT (Pmode, countreg,
    5932                 :            :                                 GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
    5933                 :      55155 :       destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
    5934                 :            :     }
    5935                 :            :   else
    5936                 :       3584 :     destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
    5937                 :      44777 :   if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
    5938                 :            :     {
    5939                 :      39711 :       rounded_count
    5940                 :      39711 :         = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
    5941                 :      39711 :       destmem = shallow_copy_rtx (destmem);
    5942                 :      39711 :       set_mem_size (destmem, rounded_count);
    5943                 :            :     }
    5944                 :       5066 :   else if (MEM_SIZE_KNOWN_P (destmem))
    5945                 :        659 :     clear_mem_size (destmem);
    5946                 :            : 
    5947                 :      44777 :   if (issetmem)
    5948                 :            :     {
    5949                 :      18223 :       value = force_reg (mode, gen_lowpart (mode, value));
    5950                 :      18223 :       emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
    5951                 :            :     }
    5952                 :            :   else
    5953                 :            :     {
    5954                 :      26554 :       if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
    5955                 :      25665 :         srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
    5956                 :      26554 :       if (mode != QImode)
    5957                 :            :         {
    5958                 :      57725 :           srcexp = gen_rtx_ASHIFT (Pmode, countreg,
    5959                 :            :                                    GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
    5960                 :      33403 :           srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
    5961                 :            :         }
    5962                 :            :       else
    5963                 :       2239 :         srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
    5964                 :      26554 :       if (CONST_INT_P (count))
    5965                 :            :         {
    5966                 :      24192 :           rounded_count
    5967                 :      24192 :             = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
    5968                 :      24192 :           srcmem = shallow_copy_rtx (srcmem);
    5969                 :      24192 :           set_mem_size (srcmem, rounded_count);
    5970                 :            :         }
    5971                 :            :       else
    5972                 :            :         {
    5973                 :       2362 :           if (MEM_SIZE_KNOWN_P (srcmem))
    5974                 :          0 :             clear_mem_size (srcmem);
    5975                 :            :         }
    5976                 :      26554 :       emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
    5977                 :            :                               destexp, srcexp));
    5978                 :            :     }
    5979                 :      44777 : }
    5980                 :            : 
    5981                 :            : /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
    5982                 :            :    DESTMEM.
    5983                 :            :    SRC is passed by pointer to be updated on return.
    5984                 :            :    Return value is updated DST.  */
    5985                 :            : static rtx
    5986                 :       3751 : emit_memmov (rtx destmem, rtx *srcmem, rtx destptr, rtx srcptr,
    5987                 :            :              HOST_WIDE_INT size_to_move)
    5988                 :            : {
    5989                 :       3751 :   rtx dst = destmem, src = *srcmem, adjust, tempreg;
    5990                 :       3751 :   enum insn_code code;
    5991                 :       3751 :   machine_mode move_mode;
    5992                 :       3751 :   int piece_size, i;
    5993                 :            : 
    5994                 :            :   /* Find the widest mode in which we could perform moves.
    5995                 :            :      Start with the biggest power of 2 less than SIZE_TO_MOVE and half
    5996                 :            :      it until move of such size is supported.  */
    5997                 :       3751 :   piece_size = 1 << floor_log2 (size_to_move);
    5998                 :       3751 :   while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
    5999                 :       7502 :          || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
    6000                 :            :     {
    6001                 :          0 :       gcc_assert (piece_size > 1);
    6002                 :          0 :       piece_size >>= 1;
    6003                 :            :     }
    6004                 :            : 
    6005                 :            :   /* Find the corresponding vector mode with the same size as MOVE_MODE.
    6006                 :            :      MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.).  */
    6007                 :      11253 :   if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
    6008                 :            :     {
    6009                 :          0 :       int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
    6010                 :          0 :       if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
    6011                 :          0 :           || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
    6012                 :            :         {
    6013                 :          0 :           move_mode = word_mode;
    6014                 :          0 :           piece_size = GET_MODE_SIZE (move_mode);
    6015                 :          0 :           code = optab_handler (mov_optab, move_mode);
    6016                 :            :         }
    6017                 :            :     }
    6018                 :       3751 :   gcc_assert (code != CODE_FOR_nothing);
    6019                 :            : 
    6020                 :       3751 :   dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
    6021                 :       3751 :   src = adjust_automodify_address_nv (src, move_mode, srcptr, 0);
    6022                 :            : 
    6023                 :            :   /* Emit moves.  We'll need SIZE_TO_MOVE/PIECE_SIZES moves.  */
    6024                 :       3751 :   gcc_assert (size_to_move % piece_size == 0);
    6025                 :       3751 :   adjust = GEN_INT (piece_size);
    6026                 :       7502 :   for (i = 0; i < size_to_move; i += piece_size)
    6027                 :            :     {
    6028                 :            :       /* We move from memory to memory, so we'll need to do it via
    6029                 :            :          a temporary register.  */
    6030                 :       3751 :       tempreg = gen_reg_rtx (move_mode);
    6031                 :       3751 :       emit_insn (GEN_FCN (code) (tempreg, src));
    6032                 :       3751 :       emit_insn (GEN_FCN (code) (dst, tempreg));
    6033                 :            : 
    6034                 :       7502 :       emit_move_insn (destptr,
    6035                 :       3816 :                       gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust));
    6036                 :       7502 :       emit_move_insn (srcptr,
    6037                 :       3816 :                       gen_rtx_PLUS (Pmode, copy_rtx (srcptr), adjust));
    6038                 :            : 
    6039                 :       3751 :       dst = adjust_automodify_address_nv (dst, move_mode, destptr,
    6040                 :            :                                           piece_size);
    6041                 :       3751 :       src = adjust_automodify_address_nv (src, move_mode, srcptr,
    6042                 :            :                                           piece_size);
    6043                 :            :     }
    6044                 :            : 
    6045                 :            :   /* Update DST and SRC rtx.  */
    6046                 :       3751 :   *srcmem = src;
    6047                 :       3751 :   return dst;
    6048                 :            : }
    6049                 :            : 
    6050                 :            : /* Helper function for the string operations below.  Dest VARIABLE whether
    6051                 :            :    it is aligned to VALUE bytes.  If true, jump to the label.  */
    6052                 :            : 
    6053                 :            : static rtx_code_label *
    6054                 :       2665 : ix86_expand_aligntest (rtx variable, int value, bool epilogue)
    6055                 :            : {
    6056                 :       2665 :   rtx_code_label *label = gen_label_rtx ();
    6057                 :       2665 :   rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
    6058                 :       2665 :   if (GET_MODE (variable) == DImode)
    6059                 :        344 :     emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
    6060                 :            :   else
    6061                 :       2321 :     emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
    6062                 :       2665 :   emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
    6063                 :            :                            1, label);
    6064                 :       2665 :   if (epilogue)
    6065                 :        606 :     predict_jump (REG_BR_PROB_BASE * 50 / 100);
    6066                 :            :   else
    6067                 :       2059 :     predict_jump (REG_BR_PROB_BASE * 90 / 100);
    6068                 :       2665 :   return label;
    6069                 :            : }
    6070                 :            : 
    6071                 :            : 
    6072                 :            : /* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST.  */
    6073                 :            : 
    6074                 :            : static void
    6075                 :      23519 : expand_cpymem_epilogue (rtx destmem, rtx srcmem,
    6076                 :            :                         rtx destptr, rtx srcptr, rtx count, int max_size)
    6077                 :            : {
    6078                 :      23519 :   rtx src, dest;
    6079                 :      23519 :   if (CONST_INT_P (count))
    6080                 :            :     {
    6081                 :      23472 :       HOST_WIDE_INT countval = INTVAL (count);
    6082                 :      23472 :       HOST_WIDE_INT epilogue_size = countval % max_size;
    6083                 :      23472 :       int i;
    6084                 :            : 
    6085                 :            :       /* For now MAX_SIZE should be a power of 2.  This assert could be
    6086                 :            :          relaxed, but it'll require a bit more complicated epilogue
    6087                 :            :          expanding.  */
    6088                 :      23472 :       gcc_assert ((max_size & (max_size - 1)) == 0);
    6089                 :     105673 :       for (i = max_size; i >= 1; i >>= 1)
    6090                 :            :         {
    6091                 :      82201 :           if (epilogue_size & i)
    6092                 :       3609 :             destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
    6093                 :            :         }
    6094                 :            :       return;
    6095                 :            :     }
    6096                 :         47 :   if (max_size > 8)
    6097                 :            :     {
    6098                 :          3 :       count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
    6099                 :            :                                     count, 1, OPTAB_DIRECT);
    6100                 :          3 :       expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
    6101                 :            :                                      count, QImode, 1, 4, false);
    6102                 :          3 :       return;
    6103                 :            :     }
    6104                 :            : 
    6105                 :            :   /* When there are stringops, we can cheaply increase dest and src pointers.
    6106                 :            :      Otherwise we save code size by maintaining offset (zero is readily
    6107                 :            :      available from preceding rep operation) and using x86 addressing modes.
    6108                 :            :    */
    6109                 :         44 :   if (TARGET_SINGLE_STRINGOP)
    6110                 :            :     {
    6111                 :          0 :       if (max_size > 4)
    6112                 :            :         {
    6113                 :          0 :           rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
    6114                 :          0 :           src = change_address (srcmem, SImode, srcptr);
    6115                 :          0 :           dest = change_address (destmem, SImode, destptr);
    6116                 :          0 :           emit_insn (gen_strmov (destptr, dest, srcptr, src));
    6117                 :          0 :           emit_label (label);
    6118                 :          0 :           LABEL_NUSES (label) = 1;
    6119                 :            :         }
    6120                 :          0 :       if (max_size > 2)
    6121                 :            :         {
    6122                 :          0 :           rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
    6123                 :          0 :           src = change_address (srcmem, HImode, srcptr);
    6124                 :          0 :           dest = change_address (destmem, HImode, destptr);
    6125                 :          0 :           emit_insn (gen_strmov (destptr, dest, srcptr, src));
    6126                 :          0 :           emit_label (label);
    6127                 :          0 :           LABEL_NUSES (label) = 1;
    6128                 :            :         }
    6129                 :          0 :       if (max_size > 1)
    6130                 :            :         {
    6131                 :          0 :           rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
    6132                 :          0 :           src = change_address (srcmem, QImode, srcptr);
    6133                 :          0 :           dest = change_address (destmem, QImode, destptr);
    6134                 :          0 :           emit_insn (gen_strmov (destptr, dest, srcptr, src));
    6135                 :          0 :           emit_label (label);
    6136                 :          0 :           LABEL_NUSES (label) = 1;
    6137                 :            :         }
    6138                 :            :     }
    6139                 :            :   else
    6140                 :            :     {
    6141                 :         56 :       rtx offset = force_reg (Pmode, const0_rtx);
    6142                 :         44 :       rtx tmp;
    6143                 :            : 
    6144                 :         44 :       if (max_size > 4)
    6145                 :            :         {
    6146                 :         32 :           rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
    6147                 :         32 :           src = change_address (srcmem, SImode, srcptr);
    6148                 :         32 :           dest = change_address (destmem, SImode, destptr);
    6149                 :         32 :           emit_move_insn (dest, src);
    6150                 :         32 :           tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (4), NULL,
    6151                 :            :                                      true, OPTAB_LIB_WIDEN);
    6152                 :         32 :           if (tmp != offset)
    6153                 :         32 :             emit_move_insn (offset, tmp);
    6154                 :         32 :           emit_label (label);
    6155                 :         32 :           LABEL_NUSES (label) = 1;
    6156                 :            :         }
    6157                 :         44 :       if (max_size > 2)
    6158                 :            :         {
    6159                 :         44 :           rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
    6160                 :         56 :           tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
    6161                 :         44 :           src = change_address (srcmem, HImode, tmp);
    6162                 :         56 :           tmp = gen_rtx_PLUS (Pmode, destptr, offset);
    6163                 :         44 :           dest = change_address (destmem, HImode, tmp);
    6164                 :         44 :           emit_move_insn (dest, src);
    6165                 :         56 :           tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (2), tmp,
    6166                 :            :                                      true, OPTAB_LIB_WIDEN);
    6167                 :         44 :           if (tmp != offset)
    6168                 :         44 :             emit_move_insn (offset, tmp);
    6169                 :         44 :           emit_label (label);
    6170                 :         44 :           LABEL_NUSES (label) = 1;
    6171                 :            :         }
    6172                 :         44 :       if (max_size > 1)
    6173                 :            :         {
    6174                 :         44 :           rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
    6175                 :         56 :           tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
    6176                 :         44 :           src = change_address (srcmem, QImode, tmp);
    6177                 :         56 :           tmp = gen_rtx_PLUS (Pmode, destptr, offset);
    6178                 :         44 :           dest = change_address (destmem, QImode, tmp);
    6179                 :         44 :           emit_move_insn (dest, src);
    6180                 :         44 :           emit_label (label);
    6181                 :         44 :           LABEL_NUSES (label) = 1;
    6182                 :            :         }
    6183                 :            :     }
    6184                 :            : }
    6185                 :            : 
    6186                 :            : /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
    6187                 :            :    with value PROMOTED_VAL.
    6188                 :            :    SRC is passed by pointer to be updated on return.
    6189                 :            :    Return value is updated DST.  */
    6190                 :            : static rtx
    6191                 :       5930 : emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
    6192                 :            :              HOST_WIDE_INT size_to_move)
    6193                 :            : {
    6194                 :       5930 :   rtx dst = destmem, adjust;
    6195                 :       5930 :   enum insn_code code;
    6196                 :       5930 :   machine_mode move_mode;
    6197                 :       5930 :   int piece_size, i;
    6198                 :            : 
    6199                 :            :   /* Find the widest mode in which we could perform moves.
    6200                 :            :      Start with the biggest power of 2 less than SIZE_TO_MOVE and half
    6201                 :            :      it until move of such size is supported.  */
    6202                 :       5930 :   move_mode = GET_MODE (promoted_val);
    6203                 :       5930 :   if (move_mode == VOIDmode)
    6204                 :          0 :     move_mode = QImode;
    6205                 :      11860 :   if (size_to_move < GET_MODE_SIZE (move_mode))
    6206                 :            :     {
    6207                 :       5927 :       unsigned int move_bits = size_to_move * BITS_PER_UNIT;
    6208                 :      11854 :       move_mode = int_mode_for_size (move_bits, 0).require ();
    6209                 :       5927 :       promoted_val = gen_lowpart (move_mode, promoted_val);
    6210                 :            :     }
    6211                 :       5930 :   piece_size = GET_MODE_SIZE (move_mode);
    6212                 :       5930 :   code = optab_handler (mov_optab, move_mode);
    6213                 :       5930 :   gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
    6214                 :            : 
    6215                 :       5930 :   dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
    6216                 :            : 
    6217                 :            :   /* Emit moves.  We'll need SIZE_TO_MOVE/PIECE_SIZES moves.  */
    6218                 :       5930 :   gcc_assert (size_to_move % piece_size == 0);
    6219                 :       5930 :   adjust = GEN_INT (piece_size);
    6220                 :      11861 :   for (i = 0; i < size_to_move; i += piece_size)
    6221                 :            :     {
    6222                 :      11862 :       if (piece_size <= GET_MODE_SIZE (word_mode))
    6223                 :            :         {
    6224                 :       5929 :           emit_insn (gen_strset (destptr, dst, promoted_val));
    6225                 :       5929 :           dst = adjust_automodify_address_nv (dst, move_mode, destptr,
    6226                 :            :                                               piece_size);
    6227                 :       5929 :           continue;
    6228                 :            :         }
    6229                 :            : 
    6230                 :          2 :       emit_insn (GEN_FCN (code) (dst, promoted_val));
    6231                 :            : 
    6232                 :          4 :       emit_move_insn (destptr,
    6233                 :          2 :                       gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust));
    6234                 :            : 
    6235                 :          2 :       dst = adjust_automodify_address_nv (dst, move_mode, destptr,
    6236                 :            :                                           piece_size);
    6237                 :            :     }
    6238                 :            : 
    6239                 :            :   /* Update DST rtx.  */
    6240                 :       5930 :   return dst;
    6241                 :            : }
    6242                 :            : /* Output code to set at most count & (max_size - 1) bytes starting by DEST.  */
    6243                 :            : static void
    6244                 :         10 : expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
    6245                 :            :                                  rtx count, int max_size)
    6246                 :            : {
    6247                 :         20 :   count = expand_simple_binop (counter_mode (count), AND, count,
    6248                 :         10 :                                GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
    6249                 :         10 :   expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
    6250                 :         10 :                                  gen_lowpart (QImode, value), count, QImode,
    6251                 :            :                                  1, max_size / 2, true);
    6252                 :         10 : }
    6253                 :            : 
    6254                 :            : /* Output code to set at most count & (max_size - 1) bytes starting by DEST.  */
    6255                 :            : static void
    6256                 :      17405 : expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
    6257                 :            :                         rtx count, int max_size)
    6258                 :            : {
    6259                 :      17405 :   rtx dest;
    6260                 :            : 
    6261                 :      17405 :   if (CONST_INT_P (count))
    6262                 :            :     {
    6263                 :      17213 :       HOST_WIDE_INT countval = INTVAL (count);
    6264                 :      17213 :       HOST_WIDE_INT epilogue_size = countval % max_size;
    6265                 :      17213 :       int i;
    6266                 :            : 
    6267                 :            :       /* For now MAX_SIZE should be a power of 2.  This assert could be
    6268                 :            :          relaxed, but it'll require a bit more complicated epilogue
    6269                 :            :          expanding.  */
    6270                 :      17213 :       gcc_assert ((max_size & (max_size - 1)) == 0);
    6271                 :      79043 :       for (i = max_size; i >= 1; i >>= 1)
    6272                 :            :         {
    6273                 :      61830 :           if (epilogue_size & i)
    6274                 :            :             {
    6275                 :       5925 :               if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
    6276                 :          0 :                 destmem = emit_memset (destmem, destptr, vec_value, i);
    6277                 :            :               else
    6278                 :       5923 :                 destmem = emit_memset (destmem, destptr, value, i);
    6279                 :            :             }
    6280                 :            :         }
    6281                 :            :       return;
    6282                 :            :     }
    6283                 :        192 :   if (max_size > 32)
    6284                 :            :     {
    6285                 :          2 :       expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
    6286                 :          2 :       return;
    6287                 :            :     }
    6288                 :        190 :   if (max_size > 16)
    6289                 :            :     {
    6290                 :          0 :       rtx_code_label *label = ix86_expand_aligntest (count, 16, true);
    6291                 :          0 :       if (TARGET_64BIT)
    6292                 :            :         {
    6293                 :          0 :           dest = change_address (destmem, DImode, destptr);
    6294                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6295                 :          0 :           dest = adjust_automodify_address_nv (dest, DImode, destptr, 8);
    6296                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6297                 :            :         }
    6298                 :            :       else
    6299                 :            :         {
    6300                 :          0 :           dest = change_address (destmem, SImode, destptr);
    6301                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6302                 :          0 :           dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
    6303                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6304                 :          0 :           dest = adjust_automodify_address_nv (dest, SImode, destptr, 8);
    6305                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6306                 :          0 :           dest = adjust_automodify_address_nv (dest, SImode, destptr, 12);
    6307                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6308                 :            :         }
    6309                 :          0 :       emit_label (label);
    6310                 :          0 :       LABEL_NUSES (label) = 1;
    6311                 :            :     }
    6312                 :        190 :   if (max_size > 8)
    6313                 :            :     {
    6314                 :          0 :       rtx_code_label *label = ix86_expand_aligntest (count, 8, true);
    6315                 :          0 :       if (TARGET_64BIT)
    6316                 :            :         {
    6317                 :          0 :           dest = change_address (destmem, DImode, destptr);
    6318                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6319                 :            :         }
    6320                 :            :       else
    6321                 :            :         {
    6322                 :          0 :           dest = change_address (destmem, SImode, destptr);
    6323                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6324                 :          0 :           dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
    6325                 :          0 :           emit_insn (gen_strset (destptr, dest, value));
    6326                 :            :         }
    6327                 :          0 :       emit_label (label);
    6328                 :          0 :       LABEL_NUSES (label) = 1;
    6329                 :            :     }
    6330                 :        190 :   if (max_size > 4)
    6331                 :            :     {
    6332                 :        106 :       rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
    6333                 :        106 :       dest = change_address (destmem, SImode, destptr);
    6334                 :        106 :       emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
    6335                 :        106 :       emit_label (label);
    6336                 :        106 :       LABEL_NUSES (label) = 1;
    6337                 :            :     }
    6338                 :        190 :   if (max_size > 2)
    6339                 :            :     {
    6340                 :        190 :       rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
    6341                 :        190 :       dest = change_address (destmem, HImode, destptr);
    6342                 :        190 :       emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
    6343                 :        190 :       emit_label (label);
    6344                 :        190 :       LABEL_NUSES (label) = 1;
    6345                 :            :     }
    6346                 :        190 :   if (max_size > 1)
    6347                 :            :     {
    6348                 :        190 :       rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
    6349                 :        190 :       dest = change_address (destmem, QImode, destptr);
    6350                 :        190 :       emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
    6351                 :        190 :       emit_label (label);
    6352                 :        190 :       LABEL_NUSES (label) = 1;
    6353                 :            :     }
    6354                 :            : }
    6355                 :            : 
    6356                 :            : /* Adjust COUNTER by the VALUE.  */
    6357                 :            : static void
    6358                 :         15 : ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
    6359                 :            : {
    6360                 :         15 :   emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
    6361                 :         15 : }
    6362                 :            : 
    6363                 :            : /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
    6364                 :            :    DESTMEM to align it to DESIRED_ALIGNMENT.  Original alignment is ALIGN.
    6365                 :            :    Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
    6366                 :            :    ignored.
    6367                 :            :    Return value is updated DESTMEM.  */
    6368                 :            : 
    6369                 :            : static rtx
    6370                 :          5 : expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
    6371                 :            :                                   rtx destptr, rtx srcptr, rtx value,
    6372                 :            :                                   rtx vec_value, rtx count, int align,
    6373                 :            :                                   int desired_alignment, bool issetmem)
    6374                 :            : {
    6375                 :          5 :   int i;
    6376                 :         26 :   for (i = 1; i < desired_alignment; i <<= 1)
    6377                 :            :     {
    6378                 :         21 :       if (align <= i)
    6379                 :            :         {
    6380                 :         15 :           rtx_code_label *label = ix86_expand_aligntest (destptr, i, false);
    6381                 :         15 :           if (issetmem)
    6382                 :            :             {
    6383                 :         14 :               if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
    6384                 :          2 :                 destmem = emit_memset (destmem, destptr, vec_value, i);
    6385                 :            :               else
    6386                 :          5 :                 destmem = emit_memset (destmem, destptr, value, i);
    6387                 :            :             }
    6388                 :            :           else
    6389                 :          8 :             destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
    6390                 :         15 :           ix86_adjust_counter (count, i);
    6391                 :         15 :           emit_label (label);
    6392                 :         15 :           LABEL_NUSES (label) = 1;
    6393                 :         15 :           set_mem_align (destmem, i * 2 * BITS_PER_UNIT);
    6394                 :            :         }
    6395                 :            :     }
    6396                 :          5 :   return destmem;
    6397                 :            : }
    6398                 :            : 
    6399                 :            : /* Test if COUNT&SIZE is nonzero and if so, expand movme
    6400                 :            :    or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
    6401                 :            :    and jump to DONE_LABEL.  */
    6402                 :            : static void
    6403                 :        953 : expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
    6404                 :            :                                rtx destptr, rtx srcptr,
    6405                 :            :                                rtx value, rtx vec_value,
    6406                 :            :                                rtx count, int size,
    6407                 :            :                                rtx done_label, bool issetmem)
    6408                 :            : {
    6409                 :        953 :   rtx_code_label *label = ix86_expand_aligntest (count, size, false);
    6410                 :        953 :   machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
    6411                 :        953 :   rtx modesize;
    6412                 :        953 :   int n;
    6413                 :            : 
    6414                 :            :   /* If we do not have vector value to copy, we must reduce size.  */
    6415                 :        953 :   if (issetmem)
    6416                 :            :     {
    6417                 :        428 :       if (!vec_value)
    6418                 :            :         {
    6419                 :        428 :           if (GET_MODE (value) == VOIDmode && size > 8)
    6420                 :          0 :             mode = Pmode;
    6421                 :       1284 :           else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
    6422                 :          1 :             mode = GET_MODE (value);
    6423                 :            :         }
    6424                 :            :       else
    6425                 :          0 :         mode = GET_MODE (vec_value), value = vec_value;
    6426                 :            :     }
    6427                 :            :   else
    6428                 :            :     {
    6429                 :            :       /* Choose appropriate vector mode.  */
    6430                 :        525 :       if (size >= 32)
    6431                 :          0 :         mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode;
    6432                 :        525 :       else if (size >= 16)
    6433                 :          0 :         mode = TARGET_SSE ? V16QImode : DImode;
    6434                 :        525 :       srcmem = change_address (srcmem, mode, srcptr);
    6435                 :            :     }
    6436                 :        953 :   destmem = change_address (destmem, mode, destptr);
    6437                 :       1906 :   modesize = GEN_INT (GET_MODE_SIZE (mode));
    6438                 :       1906 :   gcc_assert (GET_MODE_SIZE (mode) <= size);
    6439                 :       3814 :   for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
    6440                 :            :     {
    6441                 :        954 :       if (issetmem)
    6442                 :        429 :         emit_move_insn (destmem, gen_lowpart (mode, value));
    6443                 :            :       else
    6444                 :            :         {
    6445                 :        525 :           emit_move_insn (destmem, srcmem);
    6446                 :       1050 :           srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
    6447                 :            :         }
    6448                 :       1908 :       destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
    6449                 :            :     }
    6450                 :            : 
    6451                 :        953 :   destmem = offset_address (destmem, count, 1);
    6452                 :       1906 :   destmem = offset_address (destmem, GEN_INT (-2 * size),
    6453                 :        953 :                             GET_MODE_SIZE (mode));
    6454                 :        953 :   if (!issetmem)
    6455                 :            :     {
    6456                 :        525 :       srcmem = offset_address (srcmem, count, 1);
    6457                 :       1050 :       srcmem = offset_address (srcmem, GEN_INT (-2 * size),
    6458                 :        525 :                                GET_MODE_SIZE (mode));
    6459                 :            :     }
    6460                 :       3814 :   for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
    6461                 :            :     {
    6462                 :        954 :       if (issetmem)
    6463                 :        429 :         emit_move_insn (destmem, gen_lowpart (mode, value));
    6464                 :            :       else
    6465                 :            :         {
    6466                 :        525 :           emit_move_insn (destmem, srcmem);
    6467                 :       1050 :           srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
    6468                 :            :         }
    6469                 :       1908 :       destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
    6470                 :            :     }
    6471                 :        953 :   emit_jump_insn (gen_jump (done_label));
    6472                 :        953 :   emit_barrier ();
    6473                 :            : 
    6474                 :        953 :   emit_label (label);
    6475                 :        953 :   LABEL_NUSES (label) = 1;
    6476                 :        953 : }
    6477                 :            : 
    6478                 :            : /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
    6479                 :            :    and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
    6480                 :            :    bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
    6481                 :            :    proceed with an loop copying SIZE bytes at once. Do moves in MODE.
    6482                 :            :    DONE_LABEL is a label after the whole copying sequence. The label is created
    6483                 :            :    on demand if *DONE_LABEL is NULL.
    6484                 :            :    MIN_SIZE is minimal size of block copied.  This value gets adjusted for new
    6485                 :            :    bounds after the initial copies. 
    6486                 :            : 
    6487                 :            :    DESTMEM/SRCMEM are memory expressions pointing to the copies block,
    6488                 :            :    DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
    6489                 :            :    we will dispatch to a library call for large blocks.
    6490                 :            : 
    6491                 :            :    In pseudocode we do:
    6492                 :            : 
    6493                 :            :    if (COUNT < SIZE)
    6494                 :            :      {
    6495                 :            :        Assume that SIZE is 4. Bigger sizes are handled analogously
    6496                 :            :        if (COUNT & 4)
    6497                 :            :          {
    6498                 :            :             copy 4 bytes from SRCPTR to DESTPTR
    6499                 :            :             copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
    6500                 :            :             goto done_label
    6501                 :            :          }
    6502                 :            :        if (!COUNT)
    6503                 :            :          goto done_label;
    6504                 :            :        copy 1 byte from SRCPTR to DESTPTR
    6505                 :            :        if (COUNT & 2)
    6506                 :            :          {
    6507                 :            :             copy 2 bytes from SRCPTR to DESTPTR
    6508                 :            :             copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
    6509                 :            :          }
    6510                 :            :      }
    6511                 :            :    else
    6512                 :            :      {
    6513                 :            :        copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
    6514                 :            :        copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
    6515                 :            : 
    6516                 :            :        OLD_DESPTR = DESTPTR;
    6517                 :            :        Align DESTPTR up to DESIRED_ALIGN
    6518                 :            :        SRCPTR += DESTPTR - OLD_DESTPTR
    6519                 :            :        COUNT -= DEST_PTR - OLD_DESTPTR
    6520                 :            :        if (DYNAMIC_CHECK)
    6521                 :            :          Round COUNT down to multiple of SIZE
    6522                 :            :        << optional caller supplied zero size guard is here >>
    6523                 :            :        << optional caller supplied dynamic check is here >>
    6524                 :            :        << caller supplied main copy loop is here >>
    6525                 :            :      }
    6526                 :            :    done_label:
    6527                 :            :   */
    6528                 :            : static void
    6529                 :       2972 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
    6530                 :            :                                                             rtx *destptr, rtx *srcptr,
    6531                 :            :                                                             machine_mode mode,
    6532                 :            :                                                             rtx value, rtx vec_value,
    6533                 :            :                                                             rtx *count,
    6534                 :            :                                                             rtx_code_label **done_label,
    6535                 :            :                                                             int size,
    6536                 :            :                                                             int desired_align,
    6537                 :            :                                                             int align,
    6538                 :            :                                                             unsigned HOST_WIDE_INT *min_size,
    6539                 :            :                                                             bool dynamic_check,
    6540                 :            :                                                             bool issetmem)
    6541                 :            : {
    6542                 :       2972 :   rtx_code_label *loop_label = NULL, *label;
    6543                 :       2972 :   int n;
    6544                 :       2972 :   rtx modesize;
    6545                 :       2972 :   int prolog_size = 0;
    6546                 :       2972 :   rtx mode_value;
    6547                 :            : 
    6548                 :            :   /* Chose proper value to copy.  */
    6549                 :       2972 :   if (issetmem && VECTOR_MODE_P (mode))
    6550                 :            :     mode_value = vec_value;
    6551                 :            :   else
    6552                 :       2972 :     mode_value = value;
    6553                 :       5944 :   gcc_assert (GET_MODE_SIZE (mode) <= size);
    6554                 :            : 
    6555                 :            :   /* See if block is big or small, handle small blocks.  */
    6556                 :       2972 :   if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
    6557                 :            :     {
    6558                 :       1091 :       int size2 = size;
    6559                 :       1091 :       loop_label = gen_label_rtx ();
    6560                 :            : 
    6561                 :       1091 :       if (!*done_label)
    6562                 :       1091 :         *done_label = gen_label_rtx ();
    6563                 :            : 
    6564                 :       1091 :       emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
    6565                 :            :                                1, loop_label);
    6566                 :       1091 :       size2 >>= 1;
    6567                 :            : 
    6568                 :            :       /* Handle sizes > 3.  */
    6569                 :       2044 :       for (;size2 > 2; size2 >>= 1)
    6570                 :        953 :         expand_small_cpymem_or_setmem (destmem, srcmem,
    6571                 :            :                                        *destptr, *srcptr,
    6572                 :            :                                        value, vec_value,
    6573                 :            :                                        *count,
    6574                 :            :                                        size2, *done_label, issetmem);
    6575                 :            :       /* Nothing to copy?  Jump to DONE_LABEL if so */
    6576                 :       1091 :       emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
    6577                 :            :                                1, *done_label);
    6578                 :            : 
    6579                 :            :       /* Do a byte copy.  */
    6580                 :       1091 :       destmem = change_address (destmem, QImode, *destptr);
    6581                 :       1091 :       if (issetmem)
    6582                 :        498 :         emit_move_insn (destmem, gen_lowpart (QImode, value));
    6583                 :            :       else
    6584                 :            :         {
    6585                 :        593 :           srcmem = change_address (srcmem, QImode, *srcptr);
    6586                 :        593 :           emit_move_insn (destmem, srcmem);
    6587                 :            :         }
    6588                 :            : 
    6589                 :            :       /* Handle sizes 2 and 3.  */
    6590                 :       1091 :       label = ix86_expand_aligntest (*count, 2, false);
    6591                 :       1091 :       destmem = change_address (destmem, HImode, *destptr);
    6592                 :       1091 :       destmem = offset_address (destmem, *count, 1);
    6593                 :       1091 :       destmem = offset_address (destmem, GEN_INT (-2), 2);
    6594                 :       1091 :       if (issetmem)
    6595                 :        498 :         emit_move_insn (destmem, gen_lowpart (HImode, value));
    6596                 :            :       else
    6597                 :            :         {
    6598                 :        593 :           srcmem = change_address (srcmem, HImode, *srcptr);
    6599                 :        593 :           srcmem = offset_address (srcmem, *count, 1);
    6600                 :        593 :           srcmem = offset_address (srcmem, GEN_INT (-2), 2);
    6601                 :        593 :           emit_move_insn (destmem, srcmem);
    6602                 :            :         }
    6603                 :            : 
    6604                 :       1091 :       emit_label (label);
    6605                 :       1091 :       LABEL_NUSES (label) = 1;
    6606                 :       1091 :       emit_jump_insn (gen_jump (*done_label));
    6607                 :       1091 :       emit_barrier ();
    6608                 :            :     }
    6609                 :            :   else
    6610                 :       1881 :     gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
    6611                 :            :                 || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
    6612                 :            : 
    6613                 :            :   /* Start memcpy for COUNT >= SIZE.  */
    6614                 :       2972 :   if (loop_label)
    6615                 :            :     {
    6616                 :       1091 :        emit_label (loop_label);
    6617                 :       1091 :        LABEL_NUSES (loop_label) = 1;
    6618                 :            :     }
    6619                 :            : 
    6620                 :            :   /* Copy first desired_align bytes.  */
    6621                 :       2972 :   if (!issetmem)
    6622                 :       1419 :     srcmem = change_address (srcmem, mode, *srcptr);
    6623                 :       2972 :   destmem = change_address (destmem, mode, *destptr);
    6624                 :       2972 :   modesize = GEN_INT (GET_MODE_SIZE (mode));
    6625                 :       5393 :   for (n = 0; prolog_size < desired_align - align; n++)
    6626                 :            :     {
    6627                 :       2421 :       if (issetmem)
    6628                 :       1212 :         emit_move_insn (destmem, mode_value);
    6629                 :            :       else
    6630                 :            :         {
    6631                 :       1209 :           emit_move_insn (destmem, srcmem);
    6632                 :       2418 :           srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
    6633                 :            :         }
    6634                 :       4842 :       destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
    6635                 :       4842 :       prolog_size += GET_MODE_SIZE (mode);
    6636                 :            :     }
    6637                 :            : 
    6638                 :            : 
    6639                 :            :   /* Copy last SIZE bytes.  */
    6640                 :       2972 :   destmem = offset_address (destmem, *count, 1);
    6641                 :       2972 :   destmem = offset_address (destmem,
    6642                 :       2972 :                             GEN_INT (-size - prolog_size),
    6643                 :            :                             1);
    6644                 :       2972 :   if (issetmem)
    6645                 :       1553 :     emit_move_insn (destmem, mode_value);
    6646                 :            :   else
    6647                 :            :     {
    6648                 :       1419 :       srcmem = offset_address (srcmem, *count, 1);
    6649                 :       1419 :       srcmem = offset_address (srcmem,
    6650                 :            :                                GEN_INT (-size - prolog_size),
    6651                 :            :                                1);
    6652                 :       1419 :       emit_move_insn (destmem, srcmem);
    6653                 :            :     }
    6654                 :       5950 :   for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
    6655                 :            :     {
    6656                 :          3 :       destmem = offset_address (destmem, modesize, 1);
    6657                 :          3 :       if (issetmem)
    6658                 :          3 :         emit_move_insn (destmem, mode_value);
    6659                 :            :       else
    6660                 :            :         {
    6661                 :          0 :           srcmem = offset_address (srcmem, modesize, 1);
    6662                 :          0 :           emit_move_insn (destmem, srcmem);
    6663                 :            :         }
    6664                 :            :     }
    6665                 :            : 
    6666                 :            :   /* Align destination.  */
    6667                 :       2972 :   if (desired_align > 1 && desired_align > align)
    6668                 :            :     {
    6669                 :       2421 :       rtx saveddest = *destptr;
    6670                 :            : 
    6671                 :       2421 :       gcc_assert (desired_align <= size);
    6672                 :            :       /* Align destptr up, place it to new register.  */
    6673                 :       2421 :       *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
    6674                 :            :                                       GEN_INT (prolog_size),
    6675                 :            :                                       NULL_RTX, 1, OPTAB_DIRECT);
    6676                 :       2421 :       if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
    6677                 :       2421 :         REG_POINTER (*destptr) = 1;
    6678                 :       2421 :       *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
    6679                 :       2421 :                                       GEN_INT (-desired_align),
    6680                 :            :                                       *destptr, 1, OPTAB_DIRECT);
    6681                 :            :       /* See how many bytes we skipped.  */
    6682                 :       2421 :       saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
    6683                 :            :                                        *destptr,
    6684                 :            :                                        saveddest, 1, OPTAB_DIRECT);
    6685                 :            :       /* Adjust srcptr and count.  */
    6686                 :       2421 :       if (!issetmem)
    6687                 :       1209 :         *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
    6688                 :            :                                        saveddest, *srcptr, 1, OPTAB_DIRECT);
    6689                 :       2421 :       *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
    6690                 :            :                                     saveddest, *count, 1, OPTAB_DIRECT);
    6691                 :            :       /* We copied at most size + prolog_size.  */
    6692                 :       2421 :       if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
    6693                 :       1395 :         *min_size
    6694                 :       1395 :           = ROUND_DOWN (*min_size - size, (unsigned HOST_WIDE_INT)size);
    6695                 :            :       else
    6696                 :       1026 :         *min_size = 0;
    6697                 :            : 
    6698                 :            :       /* Our loops always round down the block size, but for dispatch to
    6699                 :            :          library we need precise value.  */
    6700                 :       2421 :       if (dynamic_check)
    6701                 :       2421 :         *count = expand_simple_binop (GET_MODE (*count), AND, *count,
    6702                 :            :                                       GEN_INT (-size), *count, 1, OPTAB_DIRECT);
    6703                 :            :     }
    6704                 :            :   else
    6705                 :            :     {
    6706                 :        551 :       gcc_assert (prolog_size == 0);
    6707                 :            :       /* Decrease count, so we won't end up copying last word twice.  */
    6708                 :        551 :       if (!CONST_INT_P (*count))
    6709                 :        551 :         *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
    6710                 :            :                                       constm1_rtx, *count, 1, OPTAB_DIRECT);
    6711                 :            :       else
    6712                 :          0 :         *count = GEN_INT (ROUND_DOWN (UINTVAL (*count) - 1,
    6713                 :            :                                       (unsigned HOST_WIDE_INT)size));
    6714                 :        551 :       if (*min_size)
    6715                 :        490 :         *min_size = ROUND_DOWN (*min_size - 1, (unsigned HOST_WIDE_INT)size);
    6716                 :            :     }
    6717                 :       2972 : }
    6718                 :            : 
    6719                 :            : 
    6720                 :            : /* This function is like the previous one, except here we know how many bytes
    6721                 :            :    need to be copied.  That allows us to update alignment not only of DST, which
    6722                 :            :    is returned, but also of SRC, which is passed as a pointer for that
    6723                 :            :    reason.  */
    6724                 :            : static rtx
    6725                 :        134 : expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
    6726                 :            :                                            rtx srcreg, rtx value, rtx vec_value,
    6727                 :            :                                            int desired_align, int align_bytes,
    6728                 :            :                                            bool issetmem)
    6729                 :            : {
    6730                 :        134 :   rtx src = NULL;
    6731                 :        134 :   rtx orig_dst = dst;
    6732                 :        134 :   rtx orig_src = NULL;
    6733                 :        134 :   int piece_size = 1;
    6734                 :        134 :   int copied_bytes = 0;
    6735                 :            : 
    6736                 :        134 :   if (!issetmem)
    6737                 :            :     {
    6738                 :        134 :       gcc_assert (srcp != NULL);
    6739                 :        134 :       src = *srcp;
    6740                 :        134 :       orig_src = src;
    6741                 :            :     }
    6742                 :            : 
    6743                 :        134 :   for (piece_size = 1;
    6744                 :        536 :        piece_size <= desired_align && copied_bytes < align_bytes;
    6745                 :        402 :        piece_size <<= 1)
    6746                 :            :     {
    6747                 :        402 :       if (align_bytes & piece_size)
    6748                 :            :         {
    6749                 :        134 :           if (issetmem)
    6750                 :            :             {
    6751                 :          0 :               if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
    6752                 :          0 :                 dst = emit_memset (dst, destreg, vec_value, piece_size);
    6753                 :            :               else
    6754                 :          0 :                 dst = emit_memset (dst, destreg, value, piece_size);
    6755                 :            :             }
    6756                 :            :           else
    6757                 :        134 :             dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
    6758                 :        134 :           copied_bytes += piece_size;
    6759                 :            :         }
    6760                 :            :     }
    6761                 :        134 :   if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
    6762                 :        134 :     set_mem_align (dst, desired_align * BITS_PER_UNIT);
    6763                 :        134 :   if (MEM_SIZE_KNOWN_P (orig_dst))
    6764                 :        134 :     set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
    6765                 :            : 
    6766                 :        134 :   if (!issetmem)
    6767                 :            :     {
    6768                 :        134 :       int src_align_bytes = get_mem_align_offset (src, desired_align
    6769                 :            :                                                        * BITS_PER_UNIT);
    6770                 :        134 :       if (src_align_bytes >= 0)
    6771                 :          0 :         src_align_bytes = desired_align - src_align_bytes;
    6772                 :        134 :       if (src_align_bytes >= 0)
    6773                 :            :         {
    6774                 :            :           unsigned int src_align;
    6775                 :          0 :           for (src_align = desired_align; src_align >= 2; src_align >>= 1)
    6776                 :            :             {
    6777                 :          0 :               if ((src_align_bytes & (src_align - 1))
    6778                 :          0 :                    == (align_bytes & (src_align - 1)))
    6779                 :            :                 break;
    6780                 :            :             }
    6781                 :          0 :           if (src_align > (unsigned int) desired_align)
    6782                 :            :             src_align = desired_align;
    6783                 :          0 :           if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
    6784                 :          0 :             set_mem_align (src, src_align * BITS_PER_UNIT);
    6785                 :            :         }
    6786                 :        134 :       if (MEM_SIZE_KNOWN_P (orig_src))
    6787                 :        134 :         set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
    6788                 :        134 :       *srcp = src;
    6789                 :            :     }
    6790                 :            : 
    6791                 :        134 :   return dst;
    6792                 :            : }
    6793                 :            : 
    6794                 :            : /* Return true if ALG can be used in current context.  
    6795                 :            :    Assume we expand memset if MEMSET is true.  */
    6796                 :            : static bool
    6797                 :     404366 : alg_usable_p (enum stringop_alg alg, bool memset, bool have_as)
    6798                 :            : {
    6799                 :     393657 :   if (alg == no_stringop)
    6800                 :            :     return false;
    6801                 :     296814 :   if (alg == vector_loop)
    6802                 :         15 :     return TARGET_SSE || TARGET_AVX;
    6803                 :            :   /* Algorithms using the rep prefix want at least edi and ecx;
    6804                 :            :      additionally, memset wants eax and memcpy wants esi.  Don't
    6805                 :            :      consider such algorithms if the user has appropriated those
    6806                 :            :      registers for their own purposes, or if we have a non-default
    6807                 :            :      address space, since some string insns cannot override the segment.  */
    6808                 :     307508 :   if (alg == rep_prefix_1_byte
    6809                 :            :       || alg == rep_prefix_4_byte
    6810                 :     296799 :       || alg == rep_prefix_8_byte)
    6811                 :            :     {
    6812                 :     136842 :       if (have_as)
    6813                 :            :         return false;
    6814                 :     147551 :       if (fixed_regs[CX_REG]
    6815                 :     147551 :           || fixed_regs[DI_REG]
    6816                 :     147535 :           || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG]))
    6817                 :         12 :         return false;
    6818                 :            :     }
    6819                 :            :   return true;
    6820                 :            : }
    6821                 :            : 
    6822                 :            : /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation.  */
    6823                 :            : static enum stringop_alg
    6824                 :      75207 : decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
    6825                 :            :             unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
    6826                 :            :             bool memset, bool zero_memset, bool have_as,
    6827                 :            :             int *dynamic_check, bool *noalign, bool recur)
    6828                 :            : {
    6829                 :      75207 :   const struct stringop_algs *algs;
    6830                 :      75207 :   bool optimize_for_speed;
    6831                 :      75207 :   int max = 0;
    6832                 :      75207 :   const struct processor_costs *cost;
    6833                 :      75207 :   int i;
    6834                 :      75207 :   bool any_alg_usable_p = false;
    6835                 :            : 
    6836                 :      75207 :   *noalign = false;
    6837                 :      75207 :   *dynamic_check = -1;
    6838                 :            : 
    6839                 :            :   /* Even if the string operation call is cold, we still might spend a lot
    6840                 :            :      of time processing large blocks.  */
    6841                 :      75207 :   if (optimize_function_for_size_p (cfun)
    6842                 :      75207 :       || (optimize_insn_for_size_p ()
    6843                 :       5580 :           && (max_size < 256
    6844                 :       1384 :               || (expected_size != -1 && expected_size < 256))))
    6845                 :            :     optimize_for_speed = false;
    6846                 :            :   else
    6847                 :      64382 :     optimize_for_speed = true;
    6848                 :            : 
    6849                 :      64382 :   cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
    6850                 :      75207 :   if (memset)
    6851                 :      36516 :     algs = &cost->memset[TARGET_64BIT != 0];
    6852                 :            :   else
    6853                 :      56496 :     algs = &cost->memcpy[TARGET_64BIT != 0];
    6854                 :            : 
    6855                 :            :   /* See maximal size for user defined algorithm.  */
    6856                 :     376035 :   for (i = 0; i < MAX_STRINGOP_ALGS; i++)
    6857                 :            :     {
    6858                 :     300828 :       enum stringop_alg candidate = algs->size[i].alg;
    6859                 :     300828 :       bool usable = alg_usable_p (candidate, memset, have_as);
    6860                 :     300828 :       any_alg_usable_p |= usable;
    6861                 :            : 
    6862                 :     300828 :       if (candidate != libcall && candidate && usable)
    6863                 :     139584 :         max = algs->size[i].max;
    6864                 :            :     }
    6865                 :            : 
    6866                 :            :   /* If expected size is not known but max size is small enough
    6867                 :            :      so inline version is a win, set expected size into
    6868                 :            :      the range.  */
    6869                 :      75207 :   if (((max > 1 && (unsigned HOST_WIDE_INT) max >= max_size) || max == -1)
    6870                 :      48024 :       && expected_size == -1)
    6871                 :       4510 :     expected_size = min_size / 2 + max_size / 2;
    6872                 :            : 
    6873                 :            :   /* If user specified the algorithm, honor it if possible.  */
    6874                 :      75207 :   if (ix86_stringop_alg != no_stringop
    6875                 :      75207 :       && alg_usable_p (ix86_stringop_alg, memset, have_as))
    6876                 :            :     return ix86_stringop_alg;
    6877                 :            :   /* rep; movq or rep; movl is the smallest variant.  */
    6878                 :      75084 :   else if (!optimize_for_speed)
    6879                 :            :     {
    6880                 :      10709 :       *noalign = true;
    6881                 :      10709 :       if (!count || (count & 3) || (memset && !zero_memset))
    6882                 :       3587 :         return alg_usable_p (rep_prefix_1_byte, memset, have_as)
    6883                 :            :                ? rep_prefix_1_byte : loop_1_byte;
    6884                 :            :       else
    6885                 :       7134 :         return alg_usable_p (rep_prefix_4_byte, memset, have_as)
    6886                 :            :                ? rep_prefix_4_byte : loop;
    6887                 :            :     }
    6888                 :            :   /* Very tiny blocks are best handled via the loop, REP is expensive to
    6889                 :            :      setup.  */
    6890                 :      64375 :   else if (expected_size != -1 && expected_size < 4)
    6891                 :            :     return loop_1_byte;
    6892                 :      63632 :   else if (expected_size != -1)
    6893                 :            :     {
    6894                 :            :       enum stringop_alg alg = libcall;
    6895                 :            :       bool alg_noalign = false;
    6896                 :      73866 :       for (i = 0; i < MAX_STRINGOP_ALGS; i++)
    6897                 :            :         {
    6898                 :            :           /* We get here if the algorithms that were not libcall-based
    6899                 :            :              were rep-prefix based and we are unable to use rep prefixes
    6900                 :            :              based on global register usage.  Break out of the loop and
    6901                 :            :              use the heuristic below.  */
    6902                 :      73866 :           if (algs->size[i].max == 0)
    6903                 :            :             break;
    6904                 :      73804 :           if (algs->size[i].max >= expected_size || algs->size[i].max == -1)
    6905                 :            :             {
    6906                 :      37709 :               enum stringop_alg candidate = algs->size[i].alg;
    6907                 :            : 
    6908                 :      37709 :               if (candidate != libcall
    6909                 :      37709 :                   && alg_usable_p (candidate, memset, have_as))
    6910                 :            :                 {
    6911                 :      36697 :                   alg = candidate;
    6912                 :      36697 :                   alg_noalign = algs->size[i].noalign;
    6913                 :            :                 }
    6914                 :            :               /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
    6915                 :            :                  last non-libcall inline algorithm.  */
    6916                 :      37709 :               if (TARGET_INLINE_ALL_STRINGOPS)
    6917                 :            :                 {
    6918                 :            :                   /* When the current size is best to be copied by a libcall,
    6919                 :            :                      but we are still forced to inline, run the heuristic below
    6920                 :            :                      that will pick code for medium sized blocks.  */
    6921                 :       7453 :                   if (alg != libcall)
    6922                 :            :                     {
    6923                 :       7390 :                       *noalign = alg_noalign;
    6924                 :       7390 :                       return alg;
    6925                 :            :                     }
    6926                 :         63 :                   else if (!any_alg_usable_p)
    6927                 :            :                     break;
    6928                 :            :                 }
    6929                 :      30256 :               else if (alg_usable_p (candidate, memset, have_as))
    6930                 :            :                 {
    6931                 :      30256 :                   *noalign = algs->size[i].noalign;
    6932                 :      30256 :                   return candidate;
    6933                 :            :                 }
    6934                 :            :             }
    6935                 :            :         }
    6936                 :            :     }
    6937                 :            :   /* When asked to inline the call anyway, try to pick meaningful choice.
    6938                 :            :      We look for maximal size of block that is faster to copy by hand and
    6939                 :            :      take blocks of at most of that size guessing that average size will
    6940                 :            :      be roughly half of the block.
    6941                 :            : 
    6942                 :            :      If this turns out to be bad, we might simply specify the preferred
    6943                 :            :      choice in ix86_costs.  */
    6944                 :      25986 :   if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
    6945                 :      25986 :       && (algs->unknown_size == libcall
    6946                 :          0 :           || !alg_usable_p (algs->unknown_size, memset, have_as)))
    6947                 :            :     {
    6948                 :        233 :       enum stringop_alg alg;
    6949                 :        233 :       HOST_WIDE_INT new_expected_size = (max > 0 ? max : 4096) / 2;
    6950                 :            : 
    6951                 :            :       /* If there aren't any usable algorithms or if recursing already,
    6952                 :            :          then recursing on smaller sizes or same size isn't going to
    6953                 :            :          find anything.  Just return the simple byte-at-a-time copy loop.  */
    6954                 :        233 :       if (!any_alg_usable_p || recur)
    6955                 :            :         {
    6956                 :            :           /* Pick something reasonable.  */
    6957                 :          0 :           if (TARGET_INLINE_STRINGOPS_DYNAMICALLY && !recur)
    6958                 :          0 :             *dynamic_check = 128;
    6959                 :          0 :           return loop_1_byte;
    6960                 :            :         }
    6961                 :        233 :       alg = decide_alg (count, new_expected_size, min_size, max_size, memset,
    6962                 :            :                         zero_memset, have_as, dynamic_check, noalign, true);
    6963                 :        233 :       gcc_assert (*dynamic_check == -1);
    6964                 :        233 :       if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
    6965                 :          9 :         *dynamic_check = max;
    6966                 :            :       else
    6967                 :        224 :         gcc_assert (alg != libcall);
    6968                 :        233 :       return alg;
    6969                 :            :     }
    6970                 :      25753 :   return (alg_usable_p (algs->unknown_size, memset, have_as)
    6971                 :      25753 :           ? algs->unknown_size : libcall);
    6972                 :            : }
    6973                 :            : 
    6974                 :            : /* Decide on alignment.  We know that the operand is already aligned to ALIGN
    6975                 :            :    (ALIGN can be based on profile feedback and thus it is not 100% guaranteed).  */
    6976                 :            : static int
    6977                 :      48230 : decide_alignment (int align,
    6978                 :            :                   enum stringop_alg alg,
    6979                 :            :                   int expected_size,
    6980                 :            :                   machine_mode move_mode)
    6981                 :            : {
    6982                 :      48230 :   int desired_align = 0;
    6983                 :            : 
    6984                 :      48230 :   gcc_assert (alg != no_stringop);
    6985                 :            : 
    6986                 :      48230 :   if (alg == libcall)
    6987                 :            :     return 0;
    6988                 :      48230 :   if (move_mode == VOIDmode)
    6989                 :            :     return 0;
    6990                 :            : 
    6991                 :      48230 :   desired_align = GET_MODE_SIZE (move_mode);
    6992                 :            :   /* PentiumPro has special logic triggering for 8 byte aligned blocks.
    6993                 :            :      copying whole cacheline at once.  */
    6994                 :      48230 :   if (TARGET_PENTIUMPRO
    6995                 :          0 :       && (alg == rep_prefix_4_byte || alg == rep_prefix_1_byte))
    6996                 :          0 :     desired_align = 8;
    6997                 :            : 
    6998                 :      48230 :   if (optimize_size)
    6999                 :       6567 :     desired_align = 1;
    7000                 :      48230 :   if (desired_align < align)
    7001                 :            :     desired_align = align;
    7002                 :      48230 :   if (expected_size != -1 && expected_size < 4)
    7003                 :         13 :     desired_align = align;
    7004                 :            : 
    7005                 :            :   return desired_align;
    7006                 :            : }
    7007                 :            : 
    7008                 :            : 
    7009                 :            : /* Helper function for memcpy.  For QImode value 0xXY produce
    7010                 :            :    0xXYXYXYXY of wide specified by MODE.  This is essentially
    7011                 :            :    a * 0x10101010, but we can do slightly better than
    7012                 :            :    synth_mult by unwinding the sequence by hand on CPUs with
    7013                 :            :    slow multiply.  */
    7014                 :            : static rtx
    7015                 :      19064 : promote_duplicated_reg (machine_mode mode, rtx val)
    7016                 :            : {
    7017                 :      19064 :   machine_mode valmode = GET_MODE (val);
    7018                 :      19064 :   rtx tmp;
    7019                 :      19064 :   int nops = mode == DImode ? 3 : 2;
    7020                 :            : 
    7021                 :      19064 :   gcc_assert (mode == SImode || mode == DImode || val == const0_rtx);
    7022                 :      19064 :   if (val == const0_rtx)
    7023                 :      18348 :     return copy_to_mode_reg (mode, CONST0_RTX (mode));
    7024                 :        716 :   if (CONST_INT_P (val))
    7025                 :            :     {
    7026                 :        622 :       HOST_WIDE_INT v = INTVAL (val) & 255;
    7027                 :            : 
    7028                 :        622 :       v |= v << 8;
    7029                 :        622 :       v |= v << 16;
    7030                 :        622 :       if (mode == DImode)
    7031                 :        592 :         v |= (v << 16) << 16;
    7032                 :        622 :       return copy_to_mode_reg (mode, gen_int_mode (v, mode));
    7033                 :            :     }
    7034                 :            : 
    7035                 :         94 :   if (valmode == VOIDmode)
    7036                 :            :     valmode = QImode;
    7037                 :         94 :   if (valmode != QImode)
    7038                 :          0 :     val = gen_lowpart (QImode, val);
    7039                 :         94 :   if (mode == QImode)
    7040                 :            :     return val;
    7041                 :         94 :   if (!TARGET_PARTIAL_REG_STALL)
    7042                 :         94 :     nops--;
    7043                 :        188 :   if (ix86_cost->mult_init[mode == DImode ? 3 : 2]
    7044                 :         94 :       + ix86_cost->mult_bit * (mode == DImode ? 8 : 4)
    7045                 :         94 :       <= (ix86_cost->shift_const + ix86_cost->add) * nops
    7046                 :         94 :           + (COSTS_N_INSNS (TARGET_PARTIAL_REG_STALL == 0)))
    7047                 :            :     {
    7048                 :         94 :       rtx reg = convert_modes (mode, QImode, val, true);
    7049                 :         94 :       tmp = promote_duplicated_reg (mode, const1_rtx);
    7050                 :         94 :       return expand_simple_binop (mode, MULT, reg, tmp, NULL, 1,
    7051                 :         94 :                                   OPTAB_DIRECT);
    7052                 :            :     }
    7053                 :            :   else
    7054                 :            :     {
    7055                 :          0 :       rtx reg = convert_modes (mode, QImode, val, true);
    7056                 :            : 
    7057                 :          0 :       if (!TARGET_PARTIAL_REG_STALL)
    7058                 :          0 :         if (mode == SImode)
    7059                 :          0 :           emit_insn (gen_insvsi_1 (reg, reg));
    7060                 :            :         else
    7061                 :          0 :           emit_insn (gen_insvdi_1 (reg, reg));
    7062                 :            :       else
    7063                 :            :         {
    7064                 :          0 :           tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
    7065                 :            :                                      NULL, 1, OPTAB_DIRECT);
    7066                 :          0 :           reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1,
    7067                 :            :                                      OPTAB_DIRECT);
    7068                 :            :         }
    7069                 :          0 :       tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (16),
    7070                 :            :                                  NULL, 1, OPTAB_DIRECT);
    7071                 :          0 :       reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
    7072                 :          0 :       if (mode == SImode)
    7073                 :            :         return reg;
    7074                 :          0 :       tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (32),
    7075                 :            :                                  NULL, 1, OPTAB_DIRECT);
    7076                 :          0 :       reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
    7077                 :          0 :       return reg;
    7078                 :            :     }
    7079                 :            : }
    7080                 :            : 
    7081                 :            : /* Duplicate value VAL using promote_duplicated_reg into maximal size that will
    7082                 :            :    be needed by main loop copying SIZE_NEEDED chunks and prologue getting
    7083                 :            :    alignment from ALIGN to DESIRED_ALIGN.  */
    7084                 :            : static rtx
    7085                 :      20424 : promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
    7086                 :            :                                 int align)
    7087                 :            : {
    7088                 :      20424 :   rtx promoted_val;
    7089                 :            : 
    7090                 :      20424 :   if (TARGET_64BIT
    7091                 :      13771 :       && (size_needed > 4 || (desired_align > align && desired_align > 4)))
    7092                 :      11372 :     promoted_val = promote_duplicated_reg (DImode, val);
    7093                 :       9052 :   else if (size_needed > 2 || (desired_align > align && desired_align > 2))
    7094                 :       7594 :     promoted_val = promote_duplicated_reg (SImode, val);
    7095                 :       1458 :   else if (size_needed > 1 || (desired_align > align && desired_align > 1))
    7096                 :          0 :     promoted_val = promote_duplicated_reg (HImode, val);
    7097                 :            :   else
    7098                 :            :     promoted_val = val;
    7099                 :            : 
    7100                 :      20424 :   return promoted_val;
    7101                 :            : }
    7102                 :            : 
    7103                 :            : /* Copy the address to a Pmode register.  This is used for x32 to
    7104                 :            :    truncate DImode TLS address to a SImode register. */
    7105                 :            : 
    7106                 :            : static rtx
    7107                 :      76036 : ix86_copy_addr_to_reg (rtx addr)
    7108                 :            : {
    7109                 :      76036 :   rtx reg;
    7110                 :     101157 :   if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
    7111                 :            :     {
    7112                 :      76036 :       reg = copy_addr_to_reg (addr);
    7113                 :      76036 :       REG_POINTER (reg) = 1;
    7114                 :      76036 :       return reg;
    7115                 :            :     }
    7116                 :            :   else
    7117                 :            :     {
    7118                 :          0 :       gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
    7119                 :          0 :       reg = copy_to_mode_reg (DImode, addr);
    7120                 :          0 :       REG_POINTER (reg) = 1;
    7121                 :          0 :       return gen_rtx_SUBREG (SImode, reg, 0);
    7122                 :            :     }
    7123                 :            : }
    7124                 :            : 
    7125                 :            : /* Expand string move (memcpy) ot store (memset) operation.  Use i386 string
    7126                 :            :    operations when profitable.  The code depends upon architecture, block size
    7127                 :            :    and alignment, but always has one of the following overall structures:
    7128                 :            : 
    7129                 :            :    Aligned move sequence:
    7130                 :            : 
    7131                 :            :      1) Prologue guard: Conditional that jumps up to epilogues for small
    7132                 :            :         blocks that can be handled by epilogue alone.  This is faster
    7133                 :            :         but also needed for correctness, since prologue assume the block
    7134                 :            :         is larger than the desired alignment.
    7135                 :            : 
    7136                 :            :         Optional dynamic check for size and libcall for large
    7137                 :            :         blocks is emitted here too, with -minline-stringops-dynamically.
    7138                 :            : 
    7139                 :            :      2) Prologue: copy first few bytes in order to get destination
    7140                 :            :         aligned to DESIRED_ALIGN.  It is emitted only when ALIGN is less
    7141                 :            :         than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
    7142                 :            :         copied.  We emit either a jump tree on power of two sized
    7143                 :            :         blocks, or a byte loop.
    7144                 :            : 
    7145                 :            :      3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
    7146                 :            :         with specified algorithm.
    7147                 :            : 
    7148                 :            :      4) Epilogue: code copying tail of the block that is too small to be
    7149                 :            :         handled by main body (or up to size guarded by prologue guard). 
    7150                 :            : 
    7151                 :            :   Misaligned move sequence
    7152                 :            : 
    7153                 :            :      1) missaligned move prologue/epilogue containing:
    7154                 :            :         a) Prologue handling small memory blocks and jumping to done_label
    7155                 :            :            (skipped if blocks are known to be large enough)
    7156                 :            :         b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
    7157                 :            :            needed by single possibly misaligned move
    7158                 :            :            (skipped if alignment is not needed)
    7159                 :            :         c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
    7160                 :            : 
    7161                 :            :      2) Zero size guard dispatching to done_label, if needed
    7162                 :            : 
    7163                 :            :      3) dispatch to library call, if needed,
    7164                 :            : 
    7165                 :            :      3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
    7166                 :            :         with specified algorithm.  */
    7167                 :            : bool
    7168                 :      75122 : ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
    7169                 :            :                            rtx align_exp, rtx expected_align_exp,
    7170                 :            :                            rtx expected_size_exp, rtx min_size_exp,
    7171                 :            :                            rtx max_size_exp, rtx probable_max_size_exp,
    7172                 :            :                            bool issetmem)
    7173                 :            : {
    7174                 :      75122 :   rtx destreg;
    7175                 :      75122 :   rtx srcreg = NULL;
    7176                 :      75122 :   rtx_code_label *label = NULL;
    7177                 :      75122 :   rtx tmp;
    7178                 :      75122 :   rtx_code_label *jump_around_label = NULL;
    7179                 :      75122 :   HOST_WIDE_INT align = 1;
    7180                 :      75122 :   unsigned HOST_WIDE_INT count = 0;
    7181                 :      75122 :   HOST_WIDE_INT expected_size = -1;
    7182                 :      75122 :   int size_needed = 0, epilogue_size_needed;
    7183                 :      75122 :   int desired_align = 0, align_bytes = 0;
    7184                 :      75122 :   enum stringop_alg alg;
    7185                 :      75122 :   rtx promoted_val = NULL;
    7186                 :      75122 :   rtx vec_promoted_val = NULL;
    7187                 :      75122 :   bool force_loopy_epilogue = false;
    7188                 :      75122 :   int dynamic_check;
    7189                 :      75122 :   bool need_zero_guard = false;
    7190                 :      75122 :   bool noalign;
    7191                 :      75122 :   machine_mode move_mode = VOIDmode;
    7192                 :      75122 :   machine_mode wider_mode;
    7193                 :      75122 :   int unroll_factor = 1;
    7194                 :            :   /* TODO: Once value ranges are available, fill in proper data.  */
    7195                 :      75122 :   unsigned HOST_WIDE_INT min_size = 0;
    7196                 :      75122 :   unsigned HOST_WIDE_INT max_size = -1;
    7197                 :      75122 :   unsigned HOST_WIDE_INT probable_max_size = -1;
    7198                 :      75122 :   bool misaligned_prologue_used = false;
    7199                 :      75122 :   bool have_as;
    7200                 :            : 
    7201                 :      75122 :   if (CONST_INT_P (align_exp))
    7202                 :      75122 :     align = INTVAL (align_exp);
    7203                 :            :   /* i386 can do misaligned access on reasonably increased cost.  */
    7204                 :      75122 :   if (CONST_INT_P (expected_align_exp)
    7205                 :      75122 :       && INTVAL (expected_align_exp) > align)
    7206                 :            :     align = INTVAL (expected_align_exp);
    7207                 :            :   /* ALIGN is the minimum of destination and source alignment, but we care here
    7208                 :            :      just about destination alignment.  */
    7209                 :      71467 :   else if (!issetmem
    7210                 :      71467 :            && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
    7211                 :       1122 :     align = MEM_ALIGN (dst) / BITS_PER_UNIT;
    7212                 :            : 
    7213                 :      75122 :   if (CONST_INT_P (count_exp))
    7214                 :            :     {
    7215                 :      44673 :       min_size = max_size = probable_max_size = count = expected_size
    7216                 :      44673 :         = INTVAL (count_exp);
    7217                 :            :       /* When COUNT is 0, there is nothing to do.  */
    7218                 :      44673 :       if (!count)
    7219                 :            :         return true;
    7220                 :            :     }
    7221                 :            :   else
    7222                 :            :     {
    7223                 :      30449 :       if (min_size_exp)
    7224                 :      30449 :         min_size = INTVAL (min_size_exp);
    7225                 :      30449 :       if (max_size_exp)
    7226                 :      12484 :         max_size = INTVAL (max_size_exp);
    7227                 :      30449 :       if (probable_max_size_exp)
    7228                 :      14705 :         probable_max_size = INTVAL (probable_max_size_exp);
    7229                 :      30449 :       if (CONST_INT_P (expected_size_exp))
    7230                 :      30449 :         expected_size = INTVAL (expected_size_exp);
    7231                 :            :      }
    7232                 :            : 
    7233                 :            :   /* Make sure we don't need to care about overflow later on.  */
    7234                 :      75120 :   if (count > (HOST_WIDE_INT_1U << 30))
    7235                 :            :     return false;
    7236                 :            : 
    7237                 :      74974 :   have_as = !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (dst));
    7238                 :      74974 :   if (!issetmem)
    7239                 :      46178 :     have_as |= !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src));
    7240                 :            : 
    7241                 :            :   /* Step 0: Decide on preferred algorithm, desired alignment and
    7242                 :            :      size of chunks to be copied by main loop.  */
    7243                 :      74974 :   alg = decide_alg (count, expected_size, min_size, probable_max_size,
    7244                 :            :                     issetmem,
    7245                 :      74974 :                     issetmem && val_exp == const0_rtx, have_as,
    7246                 :            :                     &dynamic_check, &noalign, false);
    7247                 :            : 
    7248                 :      74974 :   if (dump_file)
    7249                 :          2 :     fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
    7250                 :          2 :              stringop_alg_names[alg]);
    7251                 :            : 
    7252                 :      74974 :   if (alg == libcall)
    7253                 :            :     return false;
    7254                 :      48230 :   gcc_assert (alg != no_stringop);
    7255                 :            : 
    7256                 :            :   /* For now vector-version of memset is generated only for memory zeroing, as
    7257                 :            :      creating of promoted vector value is very cheap in this case.  */
    7258                 :      48230 :   if (issetmem && alg == vector_loop && val_exp != const0_rtx)
    7259                 :          0 :     alg = unrolled_loop;
    7260                 :            : 
    7261                 :      48230 :   if (!count)
    7262                 :       4693 :     count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
    7263                 :      48230 :   destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
    7264                 :      48230 :   if (!issetmem)
    7265                 :      27806 :     srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
    7266                 :            : 
    7267                 :      48230 :   unroll_factor = 1;
    7268                 :      48230 :   move_mode = word_mode;
    7269                 :      48230 :   switch (alg)
    7270                 :            :     {
    7271                 :          0 :     case libcall:
    7272                 :          0 :     case no_stringop:
    7273                 :          0 :     case last_alg:
    7274                 :          0 :       gcc_unreachable ();
    7275                 :        750 :     case loop_1_byte:
    7276                 :        750 :       need_zero_guard = true;
    7277                 :        750 :       move_mode = QImode;
    7278                 :        750 :       break;
    7279                 :       2689 :     case loop:
    7280                 :       2689 :       need_zero_guard = true;
    7281                 :       2689 :       break;
    7282                 :          5 :     case unrolled_loop:
    7283                 :          5 :       need_zero_guard = true;
    7284                 :          5 :       unroll_factor = (TARGET_64BIT ? 4 : 2);
    7285                 :            :       break;
    7286                 :            :     case vector_loop:
    7287                 :         21 :       need_zero_guard = true;
    7288                 :         21 :       unroll_factor = 4;
    7289                 :            :       /* Find the widest supported mode.  */
    7290                 :         21 :       move_mode = word_mode;
    7291                 :         50 :       while (GET_MODE_WIDER_MODE (move_mode).exists (&wider_mode)
    7292                 :         21 :              && optab_handler (mov_optab, wider_mode) != CODE_FOR_nothing)
    7293                 :            :         move_mode = wider_mode;
    7294                 :            : 
    7295                 :          9 :       if (TARGET_AVX256_SPLIT_REGS && GET_MODE_BITSIZE (move_mode) > 128)
    7296                 :            :         move_mode = TImode;
    7297                 :            : 
    7298                 :            :       /* Find the corresponding vector mode with the same size as MOVE_MODE.
    7299                 :            :          MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.).  */
    7300                 :         27 :       if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
    7301                 :            :         {
    7302                 :         18 :           int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
    7303                 :         18 :           if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
    7304                 :          9 :               || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
    7305                 :          0 :             move_mode = word_mode;
    7306                 :            :         }
    7307                 :          9 :       gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
    7308                 :            :       break;
    7309                 :      23328 :     case rep_prefix_8_byte:
    7310                 :      23328 :       move_mode = DImode;
    7311                 :      23328 :       break;
    7312                 :      17873 :     case rep_prefix_4_byte:
    7313                 :      17873 :       move_mode = SImode;
    7314                 :      17873 :       break;
    7315                 :       3576 :     case rep_prefix_1_byte:
    7316                 :       3576 :       move_mode = QImode;
    7317                 :       3576 :       break;
    7318                 :            :     }
    7319                 :      48230 :   size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
    7320                 :      48230 :   epilogue_size_needed = size_needed;
    7321                 :            : 
    7322                 :            :   /* If we are going to call any library calls conditionally, make sure any
    7323                 :            :      pending stack adjustment happen before the first conditional branch,
    7324                 :            :      otherwise they will be emitted before the library call only and won't
    7325                 :            :      happen from the other branches.  */
    7326                 :      48230 :   if (dynamic_check != -1)
    7327                 :          8 :     do_pending_stack_adjust ();
    7328                 :            : 
    7329                 :      48230 :   desired_align = decide_alignment (align, alg, expected_size, move_mode);
    7330                 :      48230 :   if (!TARGET_ALIGN_STRINGOPS || noalign)
    7331                 :      10714 :     align = desired_align;
    7332                 :            : 
    7333                 :            :   /* Step 1: Prologue guard.  */
    7334                 :            : 
    7335                 :            :   /* Alignment code needs count to be in register.  */
    7336                 :      48230 :   if (CONST_INT_P (count_exp) && desired_align > align)
    7337                 :            :     {
    7338                 :       1514 :       if (INTVAL (count_exp) > desired_align
    7339                 :       1514 :           && INTVAL (count_exp) > size_needed)
    7340                 :            :         {
    7341                 :       1514 :           align_bytes
    7342                 :       1514 :             = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
    7343                 :       1514 :           if (align_bytes <= 0)
    7344                 :            :             align_bytes = 0;
    7345                 :            :           else
    7346                 :        134 :             align_bytes = desired_align - align_bytes;
    7347                 :            :         }
    7348                 :        134 :       if (align_bytes == 0)
    7349                 :       1380 :         count_exp = force_reg (counter_mode (count_exp), count_exp);
    7350                 :            :     }
    7351                 :      48230 :   gcc_assert (desired_align >= 1 && align >= 1);
    7352                 :            : 
    7353                 :            :   /* Misaligned move sequences handle both prologue and epilogue at once.
    7354                 :            :      Default code generation results in a smaller code for large alignments
    7355                 :            :      and also avoids redundant job when sizes are known precisely.  */
    7356                 :      48230 :   misaligned_prologue_used
    7357                 :      96460 :     = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
    7358                 :      48222 :        && MAX (desired_align, epilogue_size_needed) <= 32
    7359                 :      47506 :        && desired_align <= epilogue_size_needed
    7360                 :      81768 :        && ((desired_align > align && !align_bytes)
    7361                 :      31117 :            || (!count && epilogue_size_needed > 1)));
    7362                 :            : 
    7363                 :            :   /* Do the cheap promotion to allow better CSE across the
    7364                 :            :      main loop and epilogue (ie one load of the big constant in the
    7365                 :            :      front of all code.  
    7366                 :            :      For now the misaligned move sequences do not have fast path
    7367                 :            :      without broadcasting.  */
    7368                 :      48230 :   if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used)))
    7369                 :            :     {
    7370                 :      20362 :       if (alg == vector_loop)
    7371                 :            :         {
    7372                 :          4 :           gcc_assert (val_exp == const0_rtx);
    7373                 :          4 :           vec_promoted_val = promote_duplicated_reg (move_mode, val_exp);
    7374                 :          4 :           promoted_val = promote_duplicated_reg_to_size (val_exp,
    7375                 :          8 :                                                          GET_MODE_SIZE (word_mode),
    7376                 :            :                                                          desired_align, align);
    7377                 :            :         }
    7378                 :            :       else
    7379                 :            :         {
    7380                 :      20358 :           promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
    7381                 :            :                                                          desired_align, align);
    7382                 :            :         }
    7383                 :            :     }
    7384                 :            :   /* Misaligned move sequences handles both prologues and epilogues at once.
    7385                 :            :      Default code generation results in smaller code for large alignments and
    7386                 :            :      also avoids redundant job when sizes are known precisely.  */
    7387                 :      48230 :   if (misaligned_prologue_used)
    7388                 :            :     {
    7389                 :            :       /* Misaligned move prologue handled small blocks by itself.  */
    7390                 :       2972 :       expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
    7391                 :       2972 :            (dst, src, &destreg, &srcreg,
    7392                 :            :             move_mode, promoted_val, vec_promoted_val,
    7393                 :            :             &count_exp,
    7394                 :            :             &jump_around_label,
    7395                 :       2972 :             desired_align < align
    7396                 :            :             ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
    7397                 :            :             desired_align, align, &min_size, dynamic_check, issetmem);
    7398                 :       2972 :       if (!issetmem)
    7399                 :       1419 :         src = change_address (src, BLKmode, srcreg);
    7400                 :       2972 :       dst = change_address (dst, BLKmode, destreg);
    7401                 :       2972 :       set_mem_align (dst, desired_align * BITS_PER_UNIT);
    7402                 :       2972 :       epilogue_size_needed = 0;
    7403                 :       2972 :       if (need_zero_guard
    7404                 :        853 :           && min_size < (unsigned HOST_WIDE_INT) size_needed)
    7405                 :            :         {
    7406                 :            :           /* It is possible that we copied enough so the main loop will not
    7407                 :            :              execute.  */
    7408                 :        819 :           gcc_assert (size_needed > 1);
    7409                 :        819 :           if (jump_around_label == NULL_RTX)
    7410                 :        110 :             jump_around_label = gen_label_rtx ();
    7411                 :        819 :           emit_cmp_and_jump_insns (count_exp,
    7412                 :            :                                    GEN_INT (size_needed),
    7413                 :            :                                    LTU, 0, counter_mode (count_exp), 1, jump_around_label);
    7414                 :        819 :           if (expected_size == -1
    7415                 :          1 :               || expected_size < (desired_align - align) / 2 + size_needed)
    7416                 :        819 :             predict_jump (REG_BR_PROB_BASE * 20 / 100);
    7417                 :            :           else
    7418                 :          0 :             predict_jump (REG_BR_PROB_BASE * 60 / 100);
    7419                 :            :         }
    7420                 :            :     }
    7421                 :            :   /* Ensure that alignment prologue won't copy past end of block.  */
    7422                 :      45258 :   else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
    7423                 :            :     {
    7424                 :      40932 :       epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
    7425                 :            :       /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
    7426                 :            :          Make sure it is power of 2.  */
    7427                 :      40932 :       epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
    7428                 :            : 
    7429                 :            :       /* To improve performance of small blocks, we jump around the VAL
    7430                 :            :          promoting mode.  This mean that if the promoted VAL is not constant,
    7431                 :            :          we might not use it in the epilogue and have to use byte
    7432                 :            :          loop variant.  */
    7433                 :      40932 :       if (issetmem && epilogue_size_needed > 2 && !promoted_val)
    7434                 :          8 :         force_loopy_epilogue = true;
    7435                 :      40932 :       if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed)
    7436                 :      40931 :           || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
    7437                 :            :         {
    7438                 :            :           /* If main algorithm works on QImode, no epilogue is needed.
    7439                 :            :              For small sizes just don't align anything.  */
    7440                 :          1 :           if (size_needed == 1)
    7441                 :          0 :             desired_align = align;
    7442                 :            :           else
    7443                 :          1 :             goto epilogue;
    7444                 :            :         }
    7445                 :      40931 :       else if (!count
    7446                 :        241 :                && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
    7447                 :            :         {
    7448                 :         47 :           label = gen_label_rtx ();
    7449                 :         47 :           emit_cmp_and_jump_insns (count_exp,
    7450                 :            :                                    GEN_INT (epilogue_size_needed),
    7451                 :            :                                    LTU, 0, counter_mode (count_exp), 1, label);
    7452                 :         47 :           if (expected_size == -1 || expected_size < epilogue_size_needed)
    7453                 :         42 :             predict_jump (REG_BR_PROB_BASE * 60 / 100);
    7454                 :            :           else
    7455                 :          5 :             predict_jump (REG_BR_PROB_BASE * 20 / 100);
    7456                 :            :         }
    7457                 :            :     }
    7458                 :            : 
    7459                 :            :   /* Emit code to decide on runtime whether library call or inline should be
    7460                 :            :      used.  */
    7461                 :      48229 :   if (dynamic_check != -1)
    7462                 :            :     {
    7463                 :          8 :       if (!issetmem && CONST_INT_P (count_exp))
    7464                 :            :         {
    7465                 :          0 :           if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
    7466                 :            :             {
    7467                 :          0 :               emit_block_copy_via_libcall (dst, src, count_exp);
    7468                 :          0 :               count_exp = const0_rtx;
    7469                 :          0 :               goto epilogue;
    7470                 :            :             }
    7471                 :            :         }
    7472                 :            :       else
    7473                 :            :         {
    7474                 :          8 :           rtx_code_label *hot_label = gen_label_rtx ();
    7475                 :          8 :           if (jump_around_label == NULL_RTX)
    7476                 :          2 :             jump_around_label = gen_label_rtx ();
    7477                 :          8 :           emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
    7478                 :            :                                    LEU, 0, counter_mode (count_exp),
    7479                 :            :                                    1, hot_label);
    7480                 :          8 :           predict_jump (REG_BR_PROB_BASE * 90 / 100);
    7481                 :          8 :           if (issetmem)
    7482                 :          5 :             set_storage_via_libcall (dst, count_exp, val_exp);
    7483                 :            :           else
    7484                 :          3 :             emit_block_copy_via_libcall (dst, src, count_exp);
    7485                 :          8 :           emit_jump (jump_around_label);
    7486                 :          8 :           emit_label (hot_label);
    7487                 :            :         }
    7488                 :            :     }
    7489                 :            : 
    7490                 :            :   /* Step 2: Alignment prologue.  */
    7491                 :            :   /* Do the expensive promotion once we branched off the small blocks.  */
    7492                 :      48229 :   if (issetmem && !promoted_val)
    7493                 :         62 :     promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
    7494                 :            :                                                    desired_align, align);
    7495                 :            : 
    7496                 :      48229 :   if (desired_align > align && !misaligned_prologue_used)
    7497                 :            :     {
    7498                 :        139 :       if (align_bytes == 0)
    7499                 :            :         {
    7500                 :            :           /* Except for the first move in prologue, we no longer know
    7501                 :            :              constant offset in aliasing info.  It don't seems to worth
    7502                 :            :              the pain to maintain it for the first move, so throw away
    7503                 :            :              the info early.  */
    7504                 :          5 :           dst = change_address (dst, BLKmode, destreg);
    7505                 :          5 :           if (!issetmem)
    7506                 :          3 :             src = change_address (src, BLKmode, srcreg);
    7507                 :          5 :           dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
    7508                 :            :                                             promoted_val, vec_promoted_val,
    7509                 :            :                                             count_exp, align, desired_align,
    7510                 :            :                                             issetmem);
    7511                 :            :           /* At most desired_align - align bytes are copied.  */
    7512                 :          5 :           if (min_size < (unsigned)(desired_align - align))
    7513                 :          0 :             min_size = 0;
    7514                 :            :           else
    7515                 :          5 :             min_size -= desired_align - align;
    7516                 :            :         }
    7517                 :            :       else
    7518                 :            :         {
    7519                 :            :           /* If we know how many bytes need to be stored before dst is
    7520                 :            :              sufficiently aligned, maintain aliasing info accurately.  */
    7521                 :        134 :           dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
    7522                 :            :                                                            srcreg,
    7523                 :            :                                                            promoted_val,
    7524                 :            :                                                            vec_promoted_val,
    7525                 :            :                                                            desired_align,
    7526                 :            :                                                            align_bytes,
    7527                 :            :                                                            issetmem);
    7528                 :            : 
    7529                 :        268 :           count_exp = plus_constant (counter_mode (count_exp),
    7530                 :        134 :                                      count_exp, -align_bytes);
    7531                 :        134 :           count -= align_bytes;
    7532                 :        134 :           min_size -= align_bytes;
    7533                 :        134 :           max_size -= align_bytes;
    7534                 :            :         }
    7535                 :        139 :       if (need_zero_guard
    7536                 :          5 :           && min_size < (unsigned HOST_WIDE_INT) size_needed
    7537                 :          1 :           && (count < (unsigned HOST_WIDE_INT) size_needed
    7538                 :          0 :               || (align_bytes == 0
    7539                 :          0 :                   && count < ((unsigned HOST_WIDE_INT) size_needed
    7540                 :          0 :                               + desired_align - align))))
    7541                 :            :         {
    7542                 :            :           /* It is possible that we copied enough so the main loop will not
    7543                 :            :              execute.  */
    7544                 :          1 :           gcc_assert (size_needed > 1);
    7545                 :          1 :           if (label == NULL_RTX)
    7546                 :          0 :             label = gen_label_rtx ();
    7547                 :          1 :           emit_cmp_and_jump_insns (count_exp,
    7548                 :            :                                    GEN_INT (size_needed),
    7549                 :            :                                    LTU, 0, counter_mode (count_exp), 1, label);
    7550                 :          1 :           if (expected_size == -1
    7551                 :          0 :               || expected_size < (desired_align - align) / 2 + size_needed)
    7552                 :          1 :             predict_jump (REG_BR_PROB_BASE * 20 / 100);
    7553                 :            :           else
    7554                 :          0 :             predict_jump (REG_BR_PROB_BASE * 60 / 100);
    7555                 :            :         }
    7556                 :            :     }
    7557                 :      48229 :   if (label && size_needed == 1)
    7558                 :            :     {
    7559                 :          0 :       emit_label (label);
    7560                 :          0 :       LABEL_NUSES (label) = 1;
    7561                 :          0 :       label = NULL;
    7562                 :          0 :       epilogue_size_needed = 1;
    7563                 :          0 :       if (issetmem)
    7564                 :          0 :         promoted_val = val_exp;
    7565                 :            :     }
    7566                 :      48229 :   else if (label == NULL_RTX && !misaligned_prologue_used)
    7567                 :      45210 :     epilogue_size_needed = size_needed;
    7568                 :            : 
    7569                 :            :   /* Step 3: Main loop.  */
    7570                 :            : 
    7571                 :      48229 :   switch (alg)
    7572                 :            :     {
    7573                 :          0 :     case libcall:
    7574                 :          0 :     case no_stringop:
    7575                 :          0 :     case last_alg:
    7576                 :          0 :       gcc_unreachable ();
    7577                 :       3444 :     case loop_1_byte:
    7578                 :       3444 :     case loop:
    7579                 :       3444 :     case unrolled_loop:
    7580                 :       3444 :       expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
    7581                 :            :                                      count_exp, move_mode, unroll_factor,
    7582                 :            :                                      expected_size, issetmem);
    7583                 :       3444 :       break;
    7584                 :          8 :     case vector_loop:
    7585                 :          8 :       expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
    7586                 :            :                                      vec_promoted_val, count_exp, move_mode,
    7587                 :            :                                      unroll_factor, expected_size, issetmem);
    7588                 :          8 :       break;
    7589                 :      44777 :     case rep_prefix_8_byte:
    7590                 :      44777 :     case rep_prefix_4_byte:
    7591                 :      44777 :     case rep_prefix_1_byte:
    7592                 :      44777 :       expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
    7593                 :            :                                        val_exp, count_exp, move_mode, issetmem);
    7594                 :      44777 :       break;
    7595                 :            :     }
    7596                 :            :   /* Adjust properly the offset of src and dest memory for aliasing.  */
    7597                 :      48229 :   if (CONST_INT_P (count_exp))
    7598                 :            :     {
    7599                 :      42156 :       if (!issetmem)
    7600                 :      24258 :         src = adjust_automodify_address_nv (src, BLKmode, srcreg,
    7601                 :            :                                             (count / size_needed) * size_needed);
    7602                 :      42156 :       dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
    7603                 :            :                                           (count / size_needed) * size_needed);
    7604                 :            :     }
    7605                 :            :   else
    7606                 :            :     {
    7607                 :       6073 :       if (!issetmem)
    7608                 :       3548 :         src = change_address (src, BLKmode, srcreg);
    7609                 :       6073 :       dst = change_address (dst, BLKmode, destreg);
    7610                 :            :     }
    7611                 :            : 
    7612                 :            :   /* Step 4: Epilogue to copy the remaining bytes.  */
    7613                 :      48230 :  epilogue:
    7614                 :      48230 :   if (label)
    7615                 :            :     {
    7616                 :            :       /* When the main loop is done, COUNT_EXP might hold original count,
    7617                 :            :          while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
    7618                 :            :          Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
    7619                 :            :          bytes. Compensate if needed.  */
    7620                 :            : 
    7621                 :         47 :       if (size_needed < epilogue_size_needed)
    7622                 :            :         {
    7623                 :          0 :           tmp = expand_simple_binop (counter_mode (count_exp), AND, count_exp,
    7624                 :          0 :                                      GEN_INT (size_needed - 1), count_exp, 1,
    7625                 :            :                                      OPTAB_DIRECT);
    7626                 :          0 :           if (tmp != count_exp)
    7627                 :          0 :             emit_move_insn (count_exp, tmp);
    7628                 :            :         }
    7629                 :         47 :       emit_label (label);
    7630                 :         47 :       LABEL_NUSES (label) = 1;
    7631                 :            :     }
    7632                 :            : 
    7633                 :      48230 :   if (count_exp != const0_rtx && epilogue_size_needed > 1)
    7634                 :            :     {
    7635                 :      40932 :       if (force_loopy_epilogue)
    7636                 :          8 :         expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
    7637                 :            :                                          epilogue_size_needed);
    7638                 :            :       else
    7639                 :            :         {
    7640                 :      40924 :           if (issetmem)
    7641                 :      17405 :             expand_setmem_epilogue (dst, destreg, promoted_val,
    7642                 :            :                                     vec_promoted_val, count_exp,
    7643                 :            :                                     epilogue_size_needed);
    7644                 :            :           else
    7645                 :      23519 :             expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
    7646                 :            :                                     epilogue_size_needed);
    7647                 :            :         }
    7648                 :            :     }
    7649                 :      48230 :   if (jump_around_label)
    7650                 :       1203 :     emit_label (jump_around_label);
    7651                 :            :   return true;
    7652                 :            : }
    7653                 :            : 
    7654                 :            : 
    7655                 :            : /* Expand the appropriate insns for doing strlen if not just doing
    7656                 :            :    repnz; scasb
    7657                 :            : 
    7658                 :            :    out = result, initialized with the start address
    7659                 :            :    align_rtx = alignment of the address.
    7660                 :            :    scratch = scratch register, initialized with the startaddress when
    7661                 :            :         not aligned, otherwise undefined
    7662                 :            : 
    7663                 :            :    This is just the body. It needs the initializations mentioned above and
    7664                 :            :    some address computing at the end.  These things are done in i386.md.  */
    7665                 :            : 
    7666                 :            : static void
    7667                 :         10 : ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
    7668                 :            : {
    7669                 :         10 :   int align;
    7670                 :         10 :   rtx tmp;
    7671                 :         10 :   rtx_code_label *align_2_label = NULL;
    7672                 :         10 :   rtx_code_label *align_3_label = NULL;
    7673                 :         10 :   rtx_code_label *align_4_label = gen_label_rtx ();
    7674                 :         10 :   rtx_code_label *end_0_label = gen_label_rtx ();
    7675                 :         10 :   rtx mem;
    7676                 :         10 :   rtx tmpreg = gen_reg_rtx (SImode);
    7677                 :         10 :   rtx scratch = gen_reg_rtx (SImode);
    7678                 :         10 :   rtx cmp;
    7679                 :            : 
    7680                 :         10 :   align = 0;
    7681                 :         10 :   if (CONST_INT_P (align_rtx))
    7682                 :         10 :     align = INTVAL (align_rtx);
    7683                 :            : 
    7684                 :            :   /* Loop to check 1..3 bytes for null to get an aligned pointer.  */
    7685                 :            : 
    7686                 :            :   /* Is there a known alignment and is it less than 4?  */
    7687                 :         10 :   if (align < 4)
    7688                 :            :     {
    7689                 :         14 :       rtx scratch1 = gen_reg_rtx (Pmode);
    7690                 :         10 :       emit_move_insn (scratch1, out);
    7691                 :            :       /* Is there a known alignment and is it not 2? */
    7692                 :         10 :       if (align != 2)
    7693                 :            :         {
    7694                 :         10 :           align_3_label = gen_label_rtx (); /* Label when aligned to 3-byte */
    7695                 :         10 :           align_2_label = gen_label_rtx (); /* Label when aligned to 2-byte */
    7696                 :            : 
    7697                 :            :           /* Leave just the 3 lower bits.  */
    7698                 :         14 :           align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
    7699                 :            :                                     NULL_RTX, 0, OPTAB_WIDEN);
    7700                 :            : 
    7701                 :         14 :           emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
    7702                 :         14 :                                    Pmode, 1, align_4_label);
    7703                 :         14 :           emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
    7704                 :         14 :                                    Pmode, 1, align_2_label);
    7705                 :         14 :           emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
    7706                 :         14 :                                    Pmode, 1, align_3_label);
    7707                 :            :         }
    7708                 :            :       else
    7709                 :            :         {
    7710                 :            :           /* Since the alignment is 2, we have to check 2 or 0 bytes;
    7711                 :            :              check if is aligned to 4 - byte.  */
    7712                 :            : 
    7713                 :          0 :           align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
    7714                 :            :                                     NULL_RTX, 0, OPTAB_WIDEN);
    7715                 :            : 
    7716                 :          0 :           emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
    7717                 :          0 :                                    Pmode, 1, align_4_label);
    7718                 :            :         }
    7719                 :            : 
    7720                 :         10 :       mem = change_address (src, QImode, out);
    7721                 :            : 
    7722                 :            :       /* Now compare the bytes.  */
    7723                 :            : 
    7724                 :            :       /* Compare the first n unaligned byte on a byte per byte basis.  */
    7725                 :         10 :       emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
    7726                 :            :                                QImode, 1, end_0_label);
    7727                 :            : 
    7728                 :            :       /* Increment the address.  */
    7729                 :         10 :       emit_insn (gen_add2_insn (out, const1_rtx));
    7730                 :            : 
    7731                 :            :       /* Not needed with an alignment of 2 */
    7732                 :         10 :       if (align != 2)
    7733                 :            :         {
    7734                 :         10 :           emit_label (align_2_label);
    7735                 :            : 
    7736                 :         10 :           emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
    7737                 :            :                                    end_0_label);
    7738                 :            : 
    7739                 :         10 :