Home | History | Annotate | Line # | Download | only in loongarch
      1 /* Subroutines used for LoongArch code generation.
      2    Copyright (C) 2021-2024 Free Software Foundation, Inc.
      3    Contributed by Loongson Ltd.
      4    Based on MIPS and RISC-V target for GNU compiler.
      5 
      6 This file is part of GCC.
      7 
      8 GCC is free software; you can redistribute it and/or modify
      9 it under the terms of the GNU General Public License as published by
     10 the Free Software Foundation; either version 3, or (at your option)
     11 any later version.
     12 
     13 GCC is distributed in the hope that it will be useful,
     14 but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 GNU General Public License for more details.
     17 
     18 You should have received a copy of the GNU General Public License
     19 along with GCC; see the file COPYING3.  If not see
     20 <http://www.gnu.org/licenses/>.  */
     21 
     22 #define IN_TARGET_CODE 1
     23 
     24 #include "config.h"
     25 #include "system.h"
     26 #include "coretypes.h"
     27 #include "backend.h"
     28 #include "target.h"
     29 #include "rtl.h"
     30 #include "tree.h"
     31 #include "memmodel.h"
     32 #include "gimple.h"
     33 #include "cfghooks.h"
     34 #include "df.h"
     35 #include "tm_p.h"
     36 #include "stringpool.h"
     37 #include "attribs.h"
     38 #include "optabs.h"
     39 #include "regs.h"
     40 #include "emit-rtl.h"
     41 #include "recog.h"
     42 #include "cgraph.h"
     43 #include "diagnostic.h"
     44 #include "insn-attr.h"
     45 #include "output.h"
     46 #include "alias.h"
     47 #include "fold-const.h"
     48 #include "varasm.h"
     49 #include "stor-layout.h"
     50 #include "calls.h"
     51 #include "explow.h"
     52 #include "expr.h"
     53 #include "libfuncs.h"
     54 #include "reload.h"
     55 #include "common/common-target.h"
     56 #include "langhooks.h"
     57 #include "cfgrtl.h"
     58 #include "cfganal.h"
     59 #include "sched-int.h"
     60 #include "gimplify.h"
     61 #include "target-globals.h"
     62 #include "tree-pass.h"
     63 #include "context.h"
     64 #include "builtins.h"
     65 #include "rtl-iter.h"
     66 #include "opts.h"
     67 #include "function-abi.h"
     68 #include "cfgloop.h"
     69 #include "tree-vectorizer.h"
     70 
     71 /* This file should be included last.  */
     72 #include "target-def.h"
     73 
     74 /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF.  */
     75 #define UNSPEC_ADDRESS_P(X)					\
     76   (GET_CODE (X) == UNSPEC					\
     77    && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST			\
     78    && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
     79 
     80 /* Extract the symbol or label from UNSPEC wrapper X.  */
     81 #define UNSPEC_ADDRESS(X) XVECEXP (X, 0, 0)
     82 
     83 /* Extract the symbol type from UNSPEC wrapper X.  */
     84 #define UNSPEC_ADDRESS_TYPE(X) \
     85   ((enum loongarch_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
     86 
     87 /* True if INSN is a loongarch.md pattern or asm statement.  */
     88 /* ???	This test exists through the compiler, perhaps it should be
     89    moved to rtl.h.  */
     90 #define USEFUL_INSN_P(INSN)						\
     91   (NONDEBUG_INSN_P (INSN)						\
     92    && GET_CODE (PATTERN (INSN)) != USE					\
     93    && GET_CODE (PATTERN (INSN)) != CLOBBER)
     94 
     95 /* True if bit BIT is set in VALUE.  */
     96 #define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0)
     97 
     98 /* Classifies an address.
     99 
    100    ADDRESS_REG
    101        A natural register + offset address.  The register satisfies
    102        loongarch_valid_base_register_p and the offset is a const_arith_operand.
    103 
    104    ADDRESS_REG_REG
    105        A base register indexed by (optionally scaled) register.
    106 
    107    ADDRESS_LO_SUM
    108        A LO_SUM rtx.  The first operand is a valid base register and the second
    109        operand is a symbolic address.
    110 
    111    ADDRESS_CONST_INT
    112        A signed 16-bit constant address.
    113 
    114    ADDRESS_SYMBOLIC:
    115        A constant symbolic address.  */
    116 enum loongarch_address_type
    117 {
    118   ADDRESS_REG,
    119   ADDRESS_REG_REG,
    120   ADDRESS_LO_SUM,
    121   ADDRESS_CONST_INT,
    122   ADDRESS_SYMBOLIC
    123 };
    124 
    125 
    126 /* Information about an address described by loongarch_address_type.  */
    127 struct loongarch_address_info
    128 {
    129   enum loongarch_address_type type;
    130   rtx reg;
    131   rtx offset;
    132   enum loongarch_symbol_type symbol_type;
    133 };
    134 
    135 /* Method of loading instant numbers:
    136 
    137    METHOD_NORMAL:
    138      Load 0-31 bit of the immediate number.
    139 
    140    METHOD_LU32I:
    141      Load 32-51 bit of the immediate number.
    142 
    143    METHOD_LU52I:
    144      Load 52-63 bit of the immediate number.
    145 
    146    METHOD_MIRROR:
    147      Copy 0-31 bit of the immediate number to 32-63bit.
    148 */
    149 enum loongarch_load_imm_method
    150 {
    151   METHOD_NORMAL,
    152   METHOD_LU32I,
    153   METHOD_LU52I,
    154   METHOD_MIRROR
    155 };
    156 
    157 struct loongarch_integer_op
    158 {
    159   enum rtx_code code;
    160   HOST_WIDE_INT value;
    161   /* Represent the result of the immediate count of the load instruction at
    162      each step.  */
    163   HOST_WIDE_INT curr_value;
    164   enum loongarch_load_imm_method method;
    165 };
    166 
    167 /* The largest number of operations needed to load an integer constant.
    168    The worst accepted case for 64-bit constants is LU12I.W,LU32I.D,LU52I.D,ORI
    169    or LU12I.W,LU32I.D,LU52I.D,ADDI.D DECL_ASSEMBLER_NAME.  */
    170 #define LARCH_MAX_INTEGER_OPS 4
    171 
    172 /* Arrays that map GCC register numbers to debugger register numbers.  */
    173 int loongarch_dwarf_regno[FIRST_PSEUDO_REGISTER];
    174 
    175 /* Index [M][R] is true if register R is allowed to hold a value of mode M.  */
    176 static bool loongarch_hard_regno_mode_ok_p[MAX_MACHINE_MODE]
    177 					  [FIRST_PSEUDO_REGISTER];
    178 
    179 /* Index C is true if character C is a valid PRINT_OPERAND punctation
    180    character.  */
    181 static bool loongarch_print_operand_punct[256];
    182 
    183 /* Cached value of can_issue_more.  This is cached in loongarch_variable_issue
    184    hook and returned from loongarch_sched_reorder2.  */
    185 static int cached_can_issue_more;
    186 
    187 /* Index R is the smallest register class that contains register R.  */
    188 const enum reg_class loongarch_regno_to_class[FIRST_PSEUDO_REGISTER] = {
    189     GR_REGS,	     GR_REGS,	      GR_REGS,	       GR_REGS,
    190     JIRL_REGS,       JIRL_REGS,       JIRL_REGS,       JIRL_REGS,
    191     JIRL_REGS,       JIRL_REGS,       JIRL_REGS,       JIRL_REGS,
    192     SIBCALL_REGS,    JIRL_REGS,       SIBCALL_REGS,    SIBCALL_REGS,
    193     SIBCALL_REGS,    SIBCALL_REGS,    SIBCALL_REGS,    SIBCALL_REGS,
    194     SIBCALL_REGS,    GR_REGS,	      GR_REGS,	       JIRL_REGS,
    195     JIRL_REGS,       JIRL_REGS,       JIRL_REGS,       JIRL_REGS,
    196     JIRL_REGS,       JIRL_REGS,       JIRL_REGS,       JIRL_REGS,
    197 
    198     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    199     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    200     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    201     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    202     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    203     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    204     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    205     FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
    206     FCC_REGS,	FCC_REGS,	FCC_REGS,	FCC_REGS,
    207     FCC_REGS,	FCC_REGS,	FCC_REGS,	FCC_REGS,
    208     FRAME_REGS,	FRAME_REGS
    209 };
    210 
    211 /* Information about a single argument.  */
    212 struct loongarch_arg_info
    213 {
    214   /* True if the argument is at least partially passed on the stack.  */
    215   bool stack_p;
    216 
    217   /* The number of integer registers allocated to this argument.  */
    218   unsigned int num_gprs;
    219 
    220   /* The offset of the first register used, provided num_gprs is nonzero.
    221      If passed entirely on the stack, the value is MAX_ARGS_IN_REGISTERS.  */
    222   unsigned int gpr_offset;
    223 
    224   /* The number of floating-point registers allocated to this argument.  */
    225   unsigned int num_fprs;
    226 
    227   /* The offset of the first register used, provided num_fprs is nonzero.  */
    228   unsigned int fpr_offset;
    229 };
    230 
    231 /* Invoke MACRO (COND) for each fcmp.cond.{s/d} condition.  */
    232 #define LARCH_FP_CONDITIONS(MACRO) \
    233   MACRO (f),	\
    234   MACRO (un),	\
    235   MACRO (eq),	\
    236   MACRO (ueq),	\
    237   MACRO (olt),	\
    238   MACRO (ult),	\
    239   MACRO (ole),	\
    240   MACRO (ule),	\
    241   MACRO (sf),	\
    242   MACRO (ngle),	\
    243   MACRO (seq),	\
    244   MACRO (ngl),	\
    245   MACRO (lt),	\
    246   MACRO (nge),	\
    247   MACRO (le),	\
    248   MACRO (ngt)
    249 
    250 /* Enumerates the codes above as LARCH_FP_COND_<X>.  */
    251 #define DECLARE_LARCH_COND(X) LARCH_FP_COND_##X
    252 enum loongarch_fp_condition
    253 {
    254   LARCH_FP_CONDITIONS (DECLARE_LARCH_COND)
    255 };
    256 #undef DECLARE_LARCH_COND
    257 
    258 /* Index X provides the string representation of LARCH_FP_COND_<X>.  */
    259 #define STRINGIFY(X) #X
    260 const char *const
    261 loongarch_fp_conditions[16]= {LARCH_FP_CONDITIONS (STRINGIFY)};
    262 #undef STRINGIFY
    263 
    264 /* Size of guard page.  */
    265 #define STACK_CLASH_PROTECTION_GUARD_SIZE \
    266   (1 << param_stack_clash_protection_guard_size)
    267 
    268 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  Every parameter gets at
    269    least PARM_BOUNDARY bits of alignment, but will be given anything up
    270    to PREFERRED_STACK_BOUNDARY bits if the type requires it.  */
    271 
    272 static unsigned int
    273 loongarch_function_arg_boundary (machine_mode mode, const_tree type)
    274 {
    275   unsigned int alignment;
    276 
    277   /* Use natural alignment if the type is not aggregate data.  */
    278   if (type && !AGGREGATE_TYPE_P (type))
    279     alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type));
    280   else
    281     alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
    282 
    283   return MIN (PREFERRED_STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment));
    284 }
    285 
    286 /* If MODE represents an argument that can be passed or returned in
    287    floating-point registers, return the number of registers, else 0.  */
    288 
    289 static unsigned
    290 loongarch_pass_mode_in_fpr_p (machine_mode mode)
    291 {
    292   if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG)
    293     {
    294       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
    295 	return 1;
    296 
    297       if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
    298 	return 2;
    299     }
    300 
    301   return 0;
    302 }
    303 
    304 typedef struct
    305 {
    306   const_tree type;
    307   HOST_WIDE_INT offset;
    308 } loongarch_aggregate_field;
    309 
    310 /* Identify subfields of aggregates that are candidates for passing in
    311    floating-point registers.  */
    312 
    313 static int
    314 loongarch_flatten_aggregate_field (const_tree type,
    315 				   loongarch_aggregate_field fields[2], int n,
    316 				   HOST_WIDE_INT offset)
    317 {
    318   switch (TREE_CODE (type))
    319     {
    320     case RECORD_TYPE:
    321       /* Can't handle incomplete types nor sizes that are not fixed.  */
    322       if (!COMPLETE_TYPE_P (type)
    323 	  || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
    324 	  || !tree_fits_uhwi_p (TYPE_SIZE (type)))
    325 	return -1;
    326 
    327       for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
    328 	if (TREE_CODE (f) == FIELD_DECL)
    329 	  {
    330 	    if (!TYPE_P (TREE_TYPE (f)))
    331 	      return -1;
    332 
    333 	    if (DECL_SIZE (f) && integer_zerop (DECL_SIZE (f)))
    334 	      continue;
    335 
    336 	    HOST_WIDE_INT pos = offset + int_byte_position (f);
    337 	    n = loongarch_flatten_aggregate_field (TREE_TYPE (f), fields, n,
    338 						   pos);
    339 	    if (n < 0)
    340 	      return -1;
    341 	  }
    342       return n;
    343 
    344     case ARRAY_TYPE:
    345       {
    346 	HOST_WIDE_INT n_elts;
    347 	loongarch_aggregate_field subfields[2];
    348 	tree index = TYPE_DOMAIN (type);
    349 	tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type));
    350 	int n_subfields = loongarch_flatten_aggregate_field (TREE_TYPE (type),
    351 							     subfields, 0,
    352 							     offset);
    353 
    354 	/* Can't handle incomplete types nor sizes that are not fixed.  */
    355 	if (n_subfields <= 0
    356 	    || !COMPLETE_TYPE_P (type)
    357 	    || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
    358 	    || !index
    359 	    || !TYPE_MAX_VALUE (index)
    360 	    || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index))
    361 	    || !TYPE_MIN_VALUE (index)
    362 	    || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index))
    363 	    || !tree_fits_uhwi_p (elt_size))
    364 	  return -1;
    365 
    366 	n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index))
    367 		 - tree_to_uhwi (TYPE_MIN_VALUE (index));
    368 	gcc_assert (n_elts >= 0);
    369 
    370 	for (HOST_WIDE_INT i = 0; i < n_elts; i++)
    371 	  for (int j = 0; j < n_subfields; j++)
    372 	    {
    373 	      if (n >= 2)
    374 		return -1;
    375 
    376 	      fields[n] = subfields[j];
    377 	      fields[n++].offset += i * tree_to_uhwi (elt_size);
    378 	    }
    379 
    380 	return n;
    381       }
    382 
    383     case COMPLEX_TYPE:
    384       {
    385 	/* Complex type need consume 2 field, so n must be 0.  */
    386 	if (n != 0)
    387 	  return -1;
    388 
    389 	HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)));
    390 
    391 	if (elt_size <= UNITS_PER_FP_ARG)
    392 	  {
    393 	    fields[0].type = TREE_TYPE (type);
    394 	    fields[0].offset = offset;
    395 	    fields[1].type = TREE_TYPE (type);
    396 	    fields[1].offset = offset + elt_size;
    397 
    398 	    return 2;
    399 	  }
    400 
    401 	return -1;
    402       }
    403 
    404     default:
    405       if (n < 2
    406 	  && ((SCALAR_FLOAT_TYPE_P (type)
    407 	       && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG)
    408 	      || (INTEGRAL_TYPE_P (type)
    409 		  && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD)))
    410 	{
    411 	  fields[n].type = type;
    412 	  fields[n].offset = offset;
    413 	  return n + 1;
    414 	}
    415       else
    416 	return -1;
    417     }
    418 }
    419 
    420 /* Identify candidate aggregates for passing in floating-point registers.
    421    Candidates have at most two fields after flattening.  */
    422 
    423 static int
    424 loongarch_flatten_aggregate_argument (const_tree type,
    425 				      loongarch_aggregate_field fields[2])
    426 {
    427   if (!type || TREE_CODE (type) != RECORD_TYPE)
    428     return -1;
    429 
    430   return loongarch_flatten_aggregate_field (type, fields, 0, 0);
    431 }
    432 
    433 /* See whether TYPE is a record whose fields should be returned in one or
    434    two floating-point registers.  If so, populate FIELDS accordingly.  */
    435 
    436 static unsigned
    437 loongarch_pass_aggregate_num_fpr (const_tree type,
    438 				  loongarch_aggregate_field fields[2])
    439 {
    440   int n = loongarch_flatten_aggregate_argument (type, fields);
    441 
    442   for (int i = 0; i < n; i++)
    443     if (!SCALAR_FLOAT_TYPE_P (fields[i].type))
    444       return 0;
    445 
    446   return n > 0 ? n : 0;
    447 }
    448 
    449 /* See whether TYPE is a record whose fields should be returned in one
    450    floating-point register and one integer register.  If so, populate
    451    FIELDS accordingly.  */
    452 
    453 static bool
    454 loongarch_pass_aggregate_in_fpr_and_gpr_p (const_tree type,
    455 					   loongarch_aggregate_field fields[2])
    456 {
    457   unsigned num_int = 0, num_float = 0;
    458   int n = loongarch_flatten_aggregate_argument (type, fields);
    459 
    460   for (int i = 0; i < n; i++)
    461     {
    462       num_float += SCALAR_FLOAT_TYPE_P (fields[i].type);
    463       num_int += INTEGRAL_TYPE_P (fields[i].type);
    464     }
    465 
    466   return num_int == 1 && num_float == 1;
    467 }
    468 
    469 /* Return the representation of an argument passed or returned in an FPR
    470    when the value has mode VALUE_MODE and the type has TYPE_MODE.  The
    471    two modes may be different for structures like:
    472 
    473    struct __attribute__((packed)) foo { float f; }
    474 
    475    where the SFmode value "f" is passed in REGNO but the struct itself
    476    has mode BLKmode.  */
    477 
    478 static rtx
    479 loongarch_pass_fpr_single (machine_mode type_mode, unsigned regno,
    480 			   machine_mode value_mode,
    481 			   HOST_WIDE_INT offset)
    482 {
    483   rtx x = gen_rtx_REG (value_mode, regno);
    484 
    485   if (type_mode != value_mode)
    486     {
    487       x = gen_rtx_EXPR_LIST (VOIDmode, x, GEN_INT (offset));
    488       x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x));
    489     }
    490   return x;
    491 }
    492 
    493 /* Pass or return a composite value in the FPR pair REGNO and REGNO + 1.
    494    MODE is the mode of the composite.  MODE1 and OFFSET1 are the mode and
    495    byte offset for the first value, likewise MODE2 and OFFSET2 for the
    496    second value.  */
    497 
    498 static rtx
    499 loongarch_pass_fpr_pair (machine_mode mode, unsigned regno1,
    500 			 machine_mode mode1, HOST_WIDE_INT offset1,
    501 			 unsigned regno2, machine_mode mode2,
    502 			 HOST_WIDE_INT offset2)
    503 {
    504   return gen_rtx_PARALLEL (
    505     mode, gen_rtvec (2,
    506 		     gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode1, regno1),
    507 					GEN_INT (offset1)),
    508 		     gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode2, regno2),
    509 					GEN_INT (offset2))));
    510 }
    511 
    512 /* Fill INFO with information about a single argument, and return an
    513    RTL pattern to pass or return the argument.  CUM is the cumulative
    514    state for earlier arguments.  MODE is the mode of this argument and
    515    TYPE is its type (if known).  NAMED is true if this is a named
    516    (fixed) argument rather than a variable one.  RETURN_P is true if
    517    returning the argument, or false if passing the argument.  */
    518 
    519 static rtx
    520 loongarch_get_arg_info (struct loongarch_arg_info *info,
    521 			const CUMULATIVE_ARGS *cum, machine_mode mode,
    522 			const_tree type, bool named, bool return_p)
    523 {
    524   unsigned num_bytes, num_words;
    525   unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST;
    526   unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST;
    527   unsigned alignment = loongarch_function_arg_boundary (mode, type);
    528 
    529   memset (info, 0, sizeof (*info));
    530   info->gpr_offset = cum->num_gprs;
    531   info->fpr_offset = cum->num_fprs;
    532 
    533   if (named)
    534     {
    535       loongarch_aggregate_field fields[2];
    536       unsigned fregno = fpr_base + info->fpr_offset;
    537       unsigned gregno = gpr_base + info->gpr_offset;
    538 
    539       /* Pass one- or two-element floating-point aggregates in FPRs.  */
    540       if ((info->num_fprs
    541 	   = loongarch_pass_aggregate_num_fpr (type, fields))
    542 	  && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS)
    543 	switch (info->num_fprs)
    544 	  {
    545 	  case 1:
    546 	    return loongarch_pass_fpr_single (mode, fregno,
    547 					      TYPE_MODE (fields[0].type),
    548 					      fields[0].offset);
    549 
    550 	  case 2:
    551 	    return loongarch_pass_fpr_pair (mode, fregno,
    552 					    TYPE_MODE (fields[0].type),
    553 					    fields[0].offset,
    554 					    fregno + 1,
    555 					    TYPE_MODE (fields[1].type),
    556 					    fields[1].offset);
    557 
    558 	  default:
    559 	    gcc_unreachable ();
    560 	  }
    561 
    562       /* Pass real and complex floating-point numbers in FPRs.  */
    563       if ((info->num_fprs = loongarch_pass_mode_in_fpr_p (mode))
    564 	  && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS)
    565 	switch (GET_MODE_CLASS (mode))
    566 	  {
    567 	  case MODE_FLOAT:
    568 	    return gen_rtx_REG (mode, fregno);
    569 
    570 	  case MODE_COMPLEX_FLOAT:
    571 	    return loongarch_pass_fpr_pair (mode, fregno,
    572 					    GET_MODE_INNER (mode), 0,
    573 					    fregno + 1, GET_MODE_INNER (mode),
    574 					    GET_MODE_UNIT_SIZE (mode));
    575 
    576 	  default:
    577 	    gcc_unreachable ();
    578 	  }
    579 
    580       /* Pass structs with one float and one integer in an FPR and a GPR.  */
    581       if (loongarch_pass_aggregate_in_fpr_and_gpr_p (type, fields)
    582 	  && info->gpr_offset < MAX_ARGS_IN_REGISTERS
    583 	  && info->fpr_offset < MAX_ARGS_IN_REGISTERS)
    584 	{
    585 	  info->num_gprs = 1;
    586 	  info->num_fprs = 1;
    587 
    588 	  if (!SCALAR_FLOAT_TYPE_P (fields[0].type))
    589 	    std::swap (fregno, gregno);
    590 
    591 	  return loongarch_pass_fpr_pair (mode, fregno,
    592 					  TYPE_MODE (fields[0].type),
    593 					  fields[0].offset, gregno,
    594 					  TYPE_MODE (fields[1].type),
    595 					  fields[1].offset);
    596 	}
    597     }
    598 
    599   /* Work out the size of the argument.  */
    600   num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
    601   num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
    602 
    603   /* Doubleword-aligned varargs start on an even register boundary.  */
    604   if (!named && num_bytes != 0 && alignment > BITS_PER_WORD)
    605     info->gpr_offset += info->gpr_offset & 1;
    606 
    607   /* Partition the argument between registers and stack.  */
    608   info->num_fprs = 0;
    609   info->num_gprs = MIN (num_words, MAX_ARGS_IN_REGISTERS - info->gpr_offset);
    610   info->stack_p = (num_words - info->num_gprs) != 0;
    611 
    612   if (info->num_gprs || return_p)
    613     return gen_rtx_REG (mode, gpr_base + info->gpr_offset);
    614 
    615   return NULL_RTX;
    616 }
    617 
    618 /* Implement TARGET_FUNCTION_ARG.  */
    619 
    620 static rtx
    621 loongarch_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
    622 {
    623   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
    624   struct loongarch_arg_info info;
    625 
    626   if (arg.end_marker_p ())
    627     return NULL;
    628 
    629   return loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named,
    630 				 false);
    631 }
    632 
    633 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
    634 
    635 static void
    636 loongarch_function_arg_advance (cumulative_args_t cum_v,
    637 				const function_arg_info &arg)
    638 {
    639   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
    640   struct loongarch_arg_info info;
    641 
    642   loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
    643 
    644   /* Advance the register count.  This has the effect of setting
    645      num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned
    646      argument required us to skip the final GPR and pass the whole
    647      argument on the stack.  */
    648   cum->num_fprs = info.fpr_offset + info.num_fprs;
    649   cum->num_gprs = info.gpr_offset + info.num_gprs;
    650 }
    651 
    652 /* Implement TARGET_ARG_PARTIAL_BYTES.  */
    653 
    654 static int
    655 loongarch_arg_partial_bytes (cumulative_args_t cum,
    656 			     const function_arg_info &generic_arg)
    657 {
    658   struct loongarch_arg_info arg;
    659 
    660   loongarch_get_arg_info (&arg, get_cumulative_args (cum), generic_arg.mode,
    661 			  generic_arg.type, generic_arg.named, false);
    662   return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0;
    663 }
    664 
    665 /* Implement FUNCTION_VALUE and LIBCALL_VALUE.  For normal calls,
    666    VALTYPE is the return type and MODE is VOIDmode.  For libcalls,
    667    VALTYPE is null and MODE is the mode of the return value.  */
    668 
    669 static rtx
    670 loongarch_function_value_1 (const_tree type, const_tree func,
    671 			    machine_mode mode)
    672 {
    673   struct loongarch_arg_info info;
    674   CUMULATIVE_ARGS args;
    675 
    676   if (type)
    677     {
    678       int unsigned_p = TYPE_UNSIGNED (type);
    679 
    680       mode = TYPE_MODE (type);
    681 
    682       /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes,
    683 	 return values, promote the mode here too.  */
    684       mode = promote_function_mode (type, mode, &unsigned_p, func, 1);
    685     }
    686 
    687   memset (&args, 0, sizeof (args));
    688   return loongarch_get_arg_info (&info, &args, mode, type, true, true);
    689 }
    690 
    691 
    692 /* Implement TARGET_FUNCTION_VALUE.  */
    693 
    694 static rtx
    695 loongarch_function_value (const_tree valtype, const_tree fn_decl_or_type,
    696 			  bool outgoing ATTRIBUTE_UNUSED)
    697 {
    698   return loongarch_function_value_1 (valtype, fn_decl_or_type, VOIDmode);
    699 }
    700 
    701 /* Implement TARGET_LIBCALL_VALUE.  */
    702 
    703 static rtx
    704 loongarch_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
    705 {
    706   return loongarch_function_value_1 (NULL_TREE, NULL_TREE, mode);
    707 }
    708 
    709 
    710 /* Implement TARGET_PASS_BY_REFERENCE.  */
    711 
    712 static bool
    713 loongarch_pass_by_reference (cumulative_args_t cum_v,
    714 			     const function_arg_info &arg)
    715 {
    716   HOST_WIDE_INT size = arg.type_size_in_bytes ();
    717   struct loongarch_arg_info info;
    718   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
    719 
    720   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  Fortunately, we
    721      never pass variadic arguments in floating-point registers, so we can
    722      avoid the call to loongarch_get_arg_info in this case.  */
    723   if (cum != NULL)
    724     {
    725       /* Don't pass by reference if we can use a floating-point register.  */
    726       loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named,
    727 			      false);
    728       if (info.num_fprs)
    729 	return false;
    730     }
    731 
    732   /* Pass by reference if the data do not fit in two integer registers.  */
    733   return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD);
    734 }
    735 
    736 /* Implement TARGET_RETURN_IN_MEMORY.  */
    737 
    738 static bool
    739 loongarch_return_in_memory (const_tree type,
    740 			    const_tree fndecl ATTRIBUTE_UNUSED)
    741 {
    742   CUMULATIVE_ARGS args;
    743   cumulative_args_t cum = pack_cumulative_args (&args);
    744 
    745   /* The rules for returning in memory are the same as for passing the
    746      first named argument by reference.  */
    747   memset (&args, 0, sizeof (args));
    748   function_arg_info arg (const_cast<tree> (type), /*named=*/true);
    749   return loongarch_pass_by_reference (cum, arg);
    750 }
    751 
    752 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
    753 
    754 static void
    755 loongarch_setup_incoming_varargs (cumulative_args_t cum,
    756 				  const function_arg_info &arg,
    757 				  int *pretend_size ATTRIBUTE_UNUSED,
    758 				  int no_rtl)
    759 {
    760   CUMULATIVE_ARGS local_cum;
    761   int gp_saved;
    762 
    763   /* The caller has advanced CUM up to, but not beyond, the last named
    764      argument.  Advance a local copy of CUM past the last "real" named
    765      argument, to find out how many registers are left over.  */
    766   local_cum = *get_cumulative_args (cum);
    767 
    768   /* For a C23 variadic function w/o any named argument, and w/o an
    769      artifical argument for large return value, skip advancing args.
    770      There is such an artifical argument iff. arg.type is non-NULL
    771      (PR 114175).  */
    772   if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))
    773       || arg.type != NULL_TREE)
    774     loongarch_function_arg_advance (pack_cumulative_args (&local_cum), arg);
    775 
    776   /* Found out how many registers we need to save.  */
    777   gp_saved = cfun->va_list_gpr_size / UNITS_PER_WORD;
    778   if (gp_saved > (int) (MAX_ARGS_IN_REGISTERS - local_cum.num_gprs))
    779     gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
    780 
    781   if (!no_rtl && gp_saved > 0)
    782     {
    783       rtx ptr = plus_constant (Pmode, virtual_incoming_args_rtx,
    784 			       REG_PARM_STACK_SPACE (cfun->decl)
    785 			       - gp_saved * UNITS_PER_WORD);
    786       rtx mem = gen_frame_mem (BLKmode, ptr);
    787       set_mem_alias_set (mem, get_varargs_alias_set ());
    788 
    789       move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, mem, gp_saved);
    790     }
    791   if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
    792     cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD;
    793 }
    794 
    795 /* Make the last instruction frame-related and note that it performs
    796    the operation described by FRAME_PATTERN.  */
    797 
    798 static void
    799 loongarch_set_frame_expr (rtx frame_pattern)
    800 {
    801   rtx insn;
    802 
    803   insn = get_last_insn ();
    804   RTX_FRAME_RELATED_P (insn) = 1;
    805   REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, frame_pattern,
    806 				      REG_NOTES (insn));
    807 }
    808 
    809 /* Return a frame-related rtx that stores REG at MEM.
    810    REG must be a single register.  */
    811 
    812 static rtx
    813 loongarch_frame_set (rtx mem, rtx reg)
    814 {
    815   rtx set = gen_rtx_SET (mem, reg);
    816   RTX_FRAME_RELATED_P (set) = 1;
    817   return set;
    818 }
    819 
    820 /* Return true if the current function must save register REGNO.  */
    821 
    822 static bool
    823 loongarch_save_reg_p (unsigned int regno)
    824 {
    825   bool call_saved = !global_regs[regno] && !call_used_regs[regno];
    826   bool might_clobber
    827     = crtl->saves_all_registers || df_regs_ever_live_p (regno);
    828 
    829   if (call_saved && might_clobber)
    830     return true;
    831 
    832   if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
    833     return true;
    834 
    835   if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
    836     return true;
    837 
    838   return false;
    839 }
    840 
    841 /* Determine which GPR save/restore routine to call.  */
    842 
    843 static unsigned
    844 loongarch_save_libcall_count (unsigned mask)
    845 {
    846   for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--)
    847     if (BITSET_P (mask, n))
    848       return CALLEE_SAVED_REG_NUMBER (n) + 1;
    849   abort ();
    850 }
    851 
    852 /* Populate the current function's loongarch_frame_info structure.
    853 
    854    LoongArch stack frames grown downward.  High addresses are at the top.
    855 
    856      +-------------------------------+
    857      |				     |
    858      |  incoming stack arguments     |
    859      |				     |
    860      +-------------------------------+ <-- incoming stack pointer
    861      |				     |
    862      |  callee-allocated save area   |
    863      |  for arguments that are       |
    864      |  split between registers and  |
    865      |  the stack		     |
    866      |				     |
    867      +-------------------------------+ <-- arg_pointer_rtx (virtual)
    868      |				     |
    869      |  callee-allocated save area   |
    870      |  for register varargs	     |
    871      |				     |
    872      +-------------------------------+ <-- hard_frame_pointer_rtx;
    873      |				     |     stack_pointer_rtx + gp_sp_offset
    874      |  GPR save area		     |       + UNITS_PER_WORD
    875      |				     |
    876      +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
    877      |				     |       + UNITS_PER_HWVALUE
    878      |  FPR save area		     |
    879      |				     |
    880      +-------------------------------+ <-- frame_pointer_rtx (virtual)
    881      |				     |
    882      |  local variables		     |
    883      |				     |
    884    P +-------------------------------+
    885      |				     |
    886      |  outgoing stack arguments     |
    887      |				     |
    888      +-------------------------------+ <-- stack_pointer_rtx
    889 
    890    Dynamic stack allocations such as alloca insert data at point P.
    891    They decrease stack_pointer_rtx but leave frame_pointer_rtx and
    892    hard_frame_pointer_rtx unchanged.  */
    893 
    894 static void
    895 loongarch_compute_frame_info (void)
    896 {
    897   struct loongarch_frame_info *frame;
    898   HOST_WIDE_INT offset;
    899   unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
    900 
    901   frame = &cfun->machine->frame;
    902   memset (frame, 0, sizeof (*frame));
    903 
    904   /* Find out which GPRs we need to save.  */
    905   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
    906     if (loongarch_save_reg_p (regno))
    907       frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
    908 
    909   /* If this function calls eh_return, we must also save and restore the
    910      EH data registers.  */
    911   if (crtl->calls_eh_return)
    912     for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
    913       frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
    914 
    915   /* Find out which FPRs we need to save.  This loop must iterate over
    916      the same space as its companion in loongarch_for_each_saved_reg.  */
    917   if (TARGET_HARD_FLOAT)
    918     for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
    919       if (loongarch_save_reg_p (regno))
    920 	frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
    921 
    922   /* At the bottom of the frame are any outgoing stack arguments.  */
    923   offset = LARCH_STACK_ALIGN (crtl->outgoing_args_size);
    924   /* Next are local stack variables.  */
    925   offset += LARCH_STACK_ALIGN (get_frame_size ());
    926   /* The virtual frame pointer points above the local variables.  */
    927   frame->frame_pointer_offset = offset;
    928   /* Next are the callee-saved FPRs.  */
    929   if (frame->fmask)
    930     {
    931       offset += LARCH_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG);
    932       frame->fp_sp_offset = offset - UNITS_PER_FP_REG;
    933     }
    934   else
    935     frame->fp_sp_offset = offset;
    936   /* Next are the callee-saved GPRs.  */
    937   if (frame->mask)
    938     {
    939       unsigned x_save_size = LARCH_STACK_ALIGN (num_x_saved * UNITS_PER_WORD);
    940       unsigned num_save_restore
    941 	= 1 + loongarch_save_libcall_count (frame->mask);
    942 
    943       /* Only use save/restore routines if they don't alter the stack size.  */
    944       if (LARCH_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size)
    945 	frame->save_libcall_adjustment = x_save_size;
    946 
    947       offset += x_save_size;
    948       frame->gp_sp_offset = offset - UNITS_PER_WORD;
    949     }
    950   else
    951     frame->gp_sp_offset = offset;
    952   /* The hard frame pointer points above the callee-saved GPRs.  */
    953   frame->hard_frame_pointer_offset = offset;
    954   /* Above the hard frame pointer is the callee-allocated varags save area.  */
    955   offset += LARCH_STACK_ALIGN (cfun->machine->varargs_size);
    956   /* Next is the callee-allocated area for pretend stack arguments.  */
    957   offset += LARCH_STACK_ALIGN (crtl->args.pretend_args_size);
    958   /* Arg pointer must be below pretend args, but must be above alignment
    959      padding.  */
    960   frame->arg_pointer_offset = offset - crtl->args.pretend_args_size;
    961   frame->total_size = offset;
    962   /* Next points the incoming stack pointer and any incoming arguments.  */
    963 
    964   /* Only use save/restore routines when the GPRs are atop the frame.  */
    965   if (frame->hard_frame_pointer_offset != frame->total_size)
    966     frame->save_libcall_adjustment = 0;
    967 }
    968 
    969 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame pointer
    970    or argument pointer.  TO is either the stack pointer or hard frame
    971    pointer.  */
    972 
    973 HOST_WIDE_INT
    974 loongarch_initial_elimination_offset (int from, int to)
    975 {
    976   HOST_WIDE_INT src, dest;
    977 
    978   loongarch_compute_frame_info ();
    979 
    980   if (to == HARD_FRAME_POINTER_REGNUM)
    981     dest = cfun->machine->frame.hard_frame_pointer_offset;
    982   else if (to == STACK_POINTER_REGNUM)
    983     dest = 0; /* The stack pointer is the base of all offsets, hence 0.  */
    984   else
    985     gcc_unreachable ();
    986 
    987   if (from == FRAME_POINTER_REGNUM)
    988     src = cfun->machine->frame.frame_pointer_offset;
    989   else if (from == ARG_POINTER_REGNUM)
    990     src = cfun->machine->frame.arg_pointer_offset;
    991   else
    992     gcc_unreachable ();
    993 
    994   return src - dest;
    995 }
    996 
    997 /* A function to save or store a register.  The first argument is the
    998    register and the second is the stack slot.  */
    999 typedef void (*loongarch_save_restore_fn) (rtx, rtx);
   1000 
   1001 /* Use FN to save or restore register REGNO.  MODE is the register's
   1002    mode and OFFSET is the offset of its save slot from the current
   1003    stack pointer.  */
   1004 
   1005 static void
   1006 loongarch_save_restore_reg (machine_mode mode, int regno, HOST_WIDE_INT offset,
   1007 			    loongarch_save_restore_fn fn)
   1008 {
   1009   rtx mem;
   1010 
   1011   mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset));
   1012   fn (gen_rtx_REG (mode, regno), mem);
   1013 }
   1014 
   1015 /* Call FN for each register that is saved by the current function.
   1016    SP_OFFSET is the offset of the current stack pointer from the start
   1017    of the frame.  */
   1018 
   1019 static void
   1020 loongarch_for_each_saved_reg (HOST_WIDE_INT sp_offset,
   1021 			      loongarch_save_restore_fn fn,
   1022 			      bool skip_eh_data_regs_p)
   1023 {
   1024   HOST_WIDE_INT offset;
   1025 
   1026   /* Save the link register and s-registers.  */
   1027   offset = cfun->machine->frame.gp_sp_offset - sp_offset;
   1028   for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
   1029     if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
   1030       {
   1031 	/* Special care needs to be taken for $r4-$r7 (EH_RETURN_DATA_REGNO)
   1032 	   when returning normally from a function that calls
   1033 	   __builtin_eh_return.  In this case, these registers are saved but
   1034 	   should not be restored, or the return value may be clobbered.  */
   1035 
   1036 	if (!(cfun->machine->reg_is_wrapped_separately[regno]
   1037 	      || (skip_eh_data_regs_p
   1038 	      && GP_ARG_FIRST <= regno && regno < GP_ARG_FIRST + 4)))
   1039 	  loongarch_save_restore_reg (word_mode, regno, offset, fn);
   1040 
   1041 	offset -= UNITS_PER_WORD;
   1042       }
   1043 
   1044   /* This loop must iterate over the same space as its companion in
   1045      loongarch_compute_frame_info.  */
   1046   offset = cfun->machine->frame.fp_sp_offset - sp_offset;
   1047   machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
   1048 
   1049   for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
   1050     if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
   1051       {
   1052 	if (!cfun->machine->reg_is_wrapped_separately[regno])
   1053 	  loongarch_save_restore_reg (word_mode, regno, offset, fn);
   1054 
   1055 	offset -= GET_MODE_SIZE (mode);
   1056       }
   1057 }
   1058 
   1059 /* Emit a move from SRC to DEST.  Assume that the move expanders can
   1060    handle all moves if !can_create_pseudo_p ().  The distinction is
   1061    important because, unlike emit_move_insn, the move expanders know
   1062    how to force Pmode objects into the constant pool even when the
   1063    constant pool address is not itself legitimate.  */
   1064 
   1065 rtx
   1066 loongarch_emit_move (rtx dest, rtx src)
   1067 {
   1068   return (can_create_pseudo_p () ? emit_move_insn (dest, src)
   1069 	  : emit_move_insn_1 (dest, src));
   1070 }
   1071 
   1072 /* Save register REG to MEM.  Make the instruction frame-related.  */
   1073 
   1074 static void
   1075 loongarch_save_reg (rtx reg, rtx mem)
   1076 {
   1077   loongarch_emit_move (mem, reg);
   1078   loongarch_set_frame_expr (loongarch_frame_set (mem, reg));
   1079 }
   1080 
   1081 /* Restore register REG from MEM.  */
   1082 
   1083 static void
   1084 loongarch_restore_reg (rtx reg, rtx mem)
   1085 {
   1086   rtx insn = loongarch_emit_move (reg, mem);
   1087   rtx dwarf = NULL_RTX;
   1088   dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
   1089   REG_NOTES (insn) = dwarf;
   1090 
   1091   RTX_FRAME_RELATED_P (insn) = 1;
   1092 }
   1093 
   1094 /* For stack frames that can't be allocated with a single ADDI instruction,
   1095    compute the best value to initially allocate.  It must at a minimum
   1096    allocate enough space to spill the callee-saved registers.  */
   1097 
   1098 static HOST_WIDE_INT
   1099 loongarch_first_stack_step (struct loongarch_frame_info *frame)
   1100 {
   1101   HOST_WIDE_INT min_first_step
   1102     = LARCH_STACK_ALIGN (frame->total_size - frame->fp_sp_offset);
   1103 
   1104   /* When stack checking is required, if the sum of frame->total_size
   1105      and stack_check_protect is greater than stack clash protection guard
   1106      size, then return min_first_step.  */
   1107   if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
   1108       || (flag_stack_clash_protection
   1109 	  && frame->total_size > STACK_CLASH_PROTECTION_GUARD_SIZE))
   1110     return min_first_step;
   1111 
   1112   if (IMM12_OPERAND (frame->total_size))
   1113     return frame->total_size;
   1114 
   1115   HOST_WIDE_INT max_first_step = IMM_REACH / 2 - PREFERRED_STACK_BOUNDARY / 8;
   1116   HOST_WIDE_INT min_second_step = frame->total_size - max_first_step;
   1117   gcc_assert (min_first_step <= max_first_step);
   1118 
   1119   /* As an optimization, use the least-significant bits of the total frame
   1120      size, so that the second adjustment step is just LU12I + ADD.  */
   1121   if (!IMM12_OPERAND (min_second_step)
   1122       && frame->total_size % IMM_REACH < IMM_REACH / 2
   1123       && frame->total_size % IMM_REACH >= min_first_step)
   1124     return frame->total_size % IMM_REACH;
   1125 
   1126   return max_first_step;
   1127 }
   1128 
   1129 static void
   1130 loongarch_emit_stack_tie (void)
   1131 {
   1132   emit_insn (gen_stack_tie (Pmode, stack_pointer_rtx,
   1133 			    frame_pointer_needed ? hard_frame_pointer_rtx
   1134 			    : stack_pointer_rtx));
   1135 }
   1136 
   1137 #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
   1138 
   1139 #if PROBE_INTERVAL > 16384
   1140 #error Cannot use indexed addressing mode for stack probing
   1141 #endif
   1142 
   1143 /* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
   1144    inclusive.  These are offsets from the current stack pointer.  */
   1145 
   1146 static void
   1147 loongarch_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
   1148 {
   1149   HOST_WIDE_INT rounded_size;
   1150   HOST_WIDE_INT interval;
   1151 
   1152   if (flag_stack_clash_protection)
   1153     interval = STACK_CLASH_PROTECTION_GUARD_SIZE;
   1154   else
   1155     interval = PROBE_INTERVAL;
   1156 
   1157   rtx r12 = LARCH_PROLOGUE_TEMP2 (Pmode);
   1158   rtx r14 = LARCH_PROLOGUE_TEMP3 (Pmode);
   1159 
   1160   size = size + first;
   1161 
   1162   /* Sanity check for the addressing mode we're going to use.  */
   1163   gcc_assert (first <= 16384);
   1164 
   1165   /* Step 1: round SIZE to the previous multiple of the interval.  */
   1166 
   1167   rounded_size = ROUND_DOWN (size, interval);
   1168 
   1169   /* Step 2: compute initial and final value of the loop counter.  */
   1170 
   1171   emit_move_insn (r14, GEN_INT (interval));
   1172 
   1173   /* If rounded_size is zero, it means that the space requested by
   1174      the local variable is less than the interval, and there is no
   1175      need to display and detect the allocated space.  */
   1176   if (rounded_size != 0)
   1177     {
   1178       /* Step 3: the loop
   1179 
   1180 	 do
   1181 	 {
   1182 	 TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
   1183 	 probe at TEST_ADDR
   1184 	 }
   1185 	 while (TEST_ADDR != LAST_ADDR)
   1186 
   1187 	 probes at FIRST + N * PROBE_INTERVAL for values of N from 1
   1188 	 until it is equal to ROUNDED_SIZE.  */
   1189 
   1190       if (rounded_size <= STACK_CLASH_MAX_UNROLL_PAGES * interval)
   1191 	{
   1192 	  for (HOST_WIDE_INT i = 0; i < rounded_size; i += interval)
   1193 	    {
   1194 	      emit_insn (gen_rtx_SET (stack_pointer_rtx,
   1195 				      gen_rtx_MINUS (Pmode,
   1196 						     stack_pointer_rtx,
   1197 						     r14)));
   1198 	      emit_move_insn (gen_rtx_MEM (Pmode,
   1199 					   gen_rtx_PLUS (Pmode,
   1200 							 stack_pointer_rtx,
   1201 							 const0_rtx)),
   1202 			      const0_rtx);
   1203 	      emit_insn (gen_blockage ());
   1204 	    }
   1205 	  dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
   1206 	}
   1207       else
   1208 	{
   1209 	  emit_move_insn (r12, GEN_INT (rounded_size));
   1210 	  emit_insn (gen_rtx_SET (r12,
   1211 				  gen_rtx_MINUS (Pmode,
   1212 						 stack_pointer_rtx,
   1213 						 r12)));
   1214 
   1215 	  emit_insn (gen_probe_stack_range (Pmode, stack_pointer_rtx,
   1216 					    stack_pointer_rtx, r12, r14));
   1217 	  emit_insn (gen_blockage ());
   1218 	  dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size);
   1219 	}
   1220     }
   1221   else
   1222     dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
   1223 
   1224 
   1225   /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
   1226      that SIZE is equal to ROUNDED_SIZE.  */
   1227 
   1228   if (size != rounded_size)
   1229     {
   1230       if (size - rounded_size >= 2048)
   1231 	{
   1232 	  emit_move_insn (r14, GEN_INT (size - rounded_size));
   1233 	  emit_insn (gen_rtx_SET (stack_pointer_rtx,
   1234 				  gen_rtx_MINUS (Pmode,
   1235 						 stack_pointer_rtx,
   1236 						 r14)));
   1237 	}
   1238       else
   1239 	emit_insn (gen_rtx_SET (stack_pointer_rtx,
   1240 				gen_rtx_PLUS (Pmode,
   1241 					      stack_pointer_rtx,
   1242 					      GEN_INT (rounded_size - size))));
   1243     }
   1244 
   1245   if (first)
   1246     {
   1247       emit_move_insn (r12, GEN_INT (first));
   1248       emit_insn (gen_rtx_SET (stack_pointer_rtx,
   1249 			      gen_rtx_PLUS (Pmode,
   1250 					    stack_pointer_rtx, r12)));
   1251     }
   1252   /* Make sure nothing is scheduled before we are done.  */
   1253   emit_insn (gen_blockage ());
   1254 }
   1255 
   1256 /* Probe a range of stack addresses from REG1 to REG2 inclusive.  These are
   1257    absolute addresses.  */
   1258 const char *
   1259 loongarch_output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3)
   1260 {
   1261   static int labelno = 0;
   1262   char loop_lab[32], tmp[64];
   1263   rtx xops[3];
   1264 
   1265   ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
   1266 
   1267   /* Loop.  */
   1268   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
   1269 
   1270   /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL.  */
   1271   xops[0] = reg1;
   1272   xops[2] = reg3;
   1273   if (TARGET_64BIT)
   1274     output_asm_insn ("sub.d\t%0,%0,%2", xops);
   1275   else
   1276     output_asm_insn ("sub.w\t%0,%0,%2", xops);
   1277 
   1278   /* Probe at TEST_ADDR, test if TEST_ADDR == LAST_ADDR and branch.  */
   1279   xops[1] = reg2;
   1280   strcpy (tmp, "bne\t%0,%1,");
   1281   if (TARGET_64BIT)
   1282     output_asm_insn ("st.d\t$r0,%0,0", xops);
   1283   else
   1284     output_asm_insn ("st.w\t$r0,%0,0", xops);
   1285   output_asm_insn (strcat (tmp, &loop_lab[1]), xops);
   1286 
   1287   return "";
   1288 }
   1289 
   1290 /* Expand the "prologue" pattern.  */
   1291 
   1292 void
   1293 loongarch_expand_prologue (void)
   1294 {
   1295   struct loongarch_frame_info *frame = &cfun->machine->frame;
   1296   HOST_WIDE_INT size = frame->total_size;
   1297   rtx insn;
   1298 
   1299   if (flag_stack_usage_info)
   1300     current_function_static_stack_size = size;
   1301 
   1302   /* Save the registers.  */
   1303   if ((frame->mask | frame->fmask) != 0)
   1304     {
   1305       HOST_WIDE_INT step1 = MIN (size, loongarch_first_stack_step (frame));
   1306 
   1307       insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
   1308 			    GEN_INT (-step1));
   1309       RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
   1310       size -= step1;
   1311       loongarch_for_each_saved_reg (size, loongarch_save_reg, false);
   1312     }
   1313 
   1314   /* Set up the frame pointer, if we're using one.  */
   1315   if (frame_pointer_needed)
   1316     {
   1317       insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
   1318 			    GEN_INT (frame->hard_frame_pointer_offset - size));
   1319       RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
   1320 
   1321       loongarch_emit_stack_tie ();
   1322     }
   1323 
   1324   if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
   1325        || flag_stack_clash_protection)
   1326     {
   1327       HOST_WIDE_INT first = get_stack_check_protect ();
   1328 
   1329       if (frame->total_size == 0)
   1330 	{
   1331 	  /* do nothing.  */
   1332 	  dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
   1333 	  return;
   1334 	}
   1335 
   1336       if (crtl->is_leaf && !cfun->calls_alloca)
   1337 	{
   1338 	  HOST_WIDE_INT interval;
   1339 
   1340 	  if (flag_stack_clash_protection)
   1341 	    interval = STACK_CLASH_PROTECTION_GUARD_SIZE;
   1342 	  else
   1343 	    interval = PROBE_INTERVAL;
   1344 
   1345 	  if (size > interval && size > first)
   1346 	    loongarch_emit_probe_stack_range (first, size - first);
   1347 	  else
   1348 	    loongarch_emit_probe_stack_range (first, size);
   1349 	}
   1350       else
   1351 	loongarch_emit_probe_stack_range (first, size);
   1352 
   1353       if (size > 0)
   1354 	{
   1355 	  /* Describe the effect of the previous instructions.  */
   1356 	  insn = plus_constant (Pmode, stack_pointer_rtx, -size);
   1357 	  insn = gen_rtx_SET (stack_pointer_rtx, insn);
   1358 	  loongarch_set_frame_expr (insn);
   1359 	}
   1360       return;
   1361     }
   1362 
   1363   if (size > 0)
   1364     {
   1365       if (IMM12_OPERAND (-size))
   1366 	{
   1367 	  insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
   1368 				GEN_INT (-size));
   1369 	  RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
   1370 	}
   1371       else
   1372 	{
   1373 	  loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode),
   1374 			       GEN_INT (-size));
   1375 	  emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
   1376 				    LARCH_PROLOGUE_TEMP (Pmode)));
   1377 
   1378 	  /* Describe the effect of the previous instructions.  */
   1379 	  insn = plus_constant (Pmode, stack_pointer_rtx, -size);
   1380 	  insn = gen_rtx_SET (stack_pointer_rtx, insn);
   1381 	  loongarch_set_frame_expr (insn);
   1382 	}
   1383     }
   1384 }
   1385 
   1386 /* Return nonzero if this function is known to have a null epilogue.
   1387    This allows the optimizer to omit jumps to jumps if no stack
   1388    was created.  */
   1389 
   1390 bool
   1391 loongarch_can_use_return_insn (void)
   1392 {
   1393   return reload_completed && cfun->machine->frame.total_size == 0;
   1394 }
   1395 
   1396 /* Expand function epilogue using the following insn patterns:
   1397    "epilogue"	      (style == NORMAL_RETURN)
   1398    "sibcall_epilogue" (style == SIBCALL_RETURN)
   1399    "eh_return"	      (style == EXCEPTION_RETURN) */
   1400 
   1401 void
   1402 loongarch_expand_epilogue (int style)
   1403 {
   1404   /* Split the frame into two.  STEP1 is the amount of stack we should
   1405      deallocate before restoring the registers.  STEP2 is the amount we
   1406      should deallocate afterwards.
   1407 
   1408      Start off by assuming that no registers need to be restored.  */
   1409   struct loongarch_frame_info *frame = &cfun->machine->frame;
   1410   HOST_WIDE_INT step1 = frame->total_size;
   1411   HOST_WIDE_INT step2 = 0;
   1412   rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
   1413   rtx insn;
   1414 
   1415   /* We need to add memory barrier to prevent read from deallocated stack.  */
   1416   bool need_barrier_p
   1417     = (get_frame_size () + cfun->machine->frame.arg_pointer_offset) != 0;
   1418 
   1419   /* Handle simple returns.  */
   1420   if (style == NORMAL_RETURN && loongarch_can_use_return_insn ())
   1421     {
   1422       emit_jump_insn (gen_return ());
   1423       return;
   1424     }
   1425 
   1426   /* Move past any dynamic stack allocations.  */
   1427   if (cfun->calls_alloca)
   1428     {
   1429       /* Emit a barrier to prevent loads from a deallocated stack.  */
   1430       loongarch_emit_stack_tie ();
   1431       need_barrier_p = false;
   1432 
   1433       rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset);
   1434       if (!IMM12_OPERAND (INTVAL (adjust)))
   1435 	{
   1436 	  loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust);
   1437 	  adjust = LARCH_PROLOGUE_TEMP (Pmode);
   1438 	}
   1439 
   1440       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
   1441 				       hard_frame_pointer_rtx,
   1442 				       adjust));
   1443 
   1444       rtx dwarf = NULL_RTX;
   1445       rtx minus_offset = GEN_INT (-frame->hard_frame_pointer_offset);
   1446       rtx cfa_adjust_value = gen_rtx_PLUS (Pmode,
   1447 					   hard_frame_pointer_rtx,
   1448 					   minus_offset);
   1449 
   1450       rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value);
   1451       dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf);
   1452       RTX_FRAME_RELATED_P (insn) = 1;
   1453 
   1454       REG_NOTES (insn) = dwarf;
   1455     }
   1456 
   1457   /* If we need to restore registers, deallocate as much stack as
   1458      possible in the second step without going out of range.  */
   1459   if ((frame->mask | frame->fmask) != 0)
   1460     {
   1461       step2 = loongarch_first_stack_step (frame);
   1462       step1 -= step2;
   1463     }
   1464 
   1465   /* Set TARGET to BASE + STEP1.  */
   1466   if (step1 > 0)
   1467     {
   1468       /* Emit a barrier to prevent loads from a deallocated stack.  */
   1469       loongarch_emit_stack_tie ();
   1470       need_barrier_p = false;
   1471 
   1472       /* Get an rtx for STEP1 that we can add to BASE.  */
   1473       rtx adjust = GEN_INT (step1);
   1474       if (!IMM12_OPERAND (step1))
   1475 	{
   1476 	  loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust);
   1477 	  adjust = LARCH_PROLOGUE_TEMP (Pmode);
   1478 	}
   1479 
   1480       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
   1481 				       stack_pointer_rtx,
   1482 				       adjust));
   1483 
   1484       rtx dwarf = NULL_RTX;
   1485       rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   1486 					 GEN_INT (step2));
   1487 
   1488       dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
   1489       RTX_FRAME_RELATED_P (insn) = 1;
   1490 
   1491       REG_NOTES (insn) = dwarf;
   1492     }
   1493 
   1494   /* Restore the registers.  */
   1495   loongarch_for_each_saved_reg (frame->total_size - step2,
   1496 				loongarch_restore_reg,
   1497 				crtl->calls_eh_return
   1498 				&& style != EXCEPTION_RETURN);
   1499 
   1500   if (need_barrier_p)
   1501     loongarch_emit_stack_tie ();
   1502 
   1503   /* Deallocate the final bit of the frame.  */
   1504   if (step2 > 0)
   1505     {
   1506       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
   1507 				       stack_pointer_rtx,
   1508 				       GEN_INT (step2)));
   1509 
   1510       rtx dwarf = NULL_RTX;
   1511       rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx);
   1512       dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
   1513       RTX_FRAME_RELATED_P (insn) = 1;
   1514 
   1515       REG_NOTES (insn) = dwarf;
   1516     }
   1517 
   1518   /* Add in the __builtin_eh_return stack adjustment.  */
   1519   if (crtl->calls_eh_return && style == EXCEPTION_RETURN)
   1520     emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
   1521 			      EH_RETURN_STACKADJ_RTX));
   1522 
   1523   /* Emit return unless doing sibcall.  */
   1524   if (style != SIBCALL_RETURN)
   1525     emit_jump_insn (gen_simple_return_internal (ra));
   1526 }
   1527 
   1528 #define LU32I_B (0xfffffULL << 32)
   1529 #define LU52I_B (0xfffULL << 52)
   1530 
   1531 /* Fill CODES with a sequence of rtl operations to load VALUE.
   1532    Return the number of operations needed.  */
   1533 
   1534 static unsigned int
   1535 loongarch_build_integer (struct loongarch_integer_op *codes,
   1536 			 HOST_WIDE_INT value)
   1537 
   1538 {
   1539   unsigned int cost = 0;
   1540 
   1541   /* Get the lower 32 bits of the value.  */
   1542   HOST_WIDE_INT low_part = (int32_t)value;
   1543 
   1544   if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part))
   1545     {
   1546       /* The value of the lower 32 bit be loaded with one instruction.
   1547 	 lu12i.w.  */
   1548       codes[cost].code = UNKNOWN;
   1549       codes[cost].method = METHOD_NORMAL;
   1550       codes[cost].value = low_part;
   1551       codes[cost].curr_value = low_part;
   1552       cost++;
   1553     }
   1554   else
   1555     {
   1556       /* lu12i.w + ior.  */
   1557       codes[cost].code = UNKNOWN;
   1558       codes[cost].method = METHOD_NORMAL;
   1559       codes[cost].value = low_part & ~(IMM_REACH - 1);
   1560       codes[cost].curr_value = codes[cost].value;
   1561       cost++;
   1562       HOST_WIDE_INT iorv = low_part & (IMM_REACH - 1);
   1563       if (iorv != 0)
   1564 	{
   1565 	  codes[cost].code = IOR;
   1566 	  codes[cost].method = METHOD_NORMAL;
   1567 	  codes[cost].value = iorv;
   1568 	  codes[cost].curr_value = low_part;
   1569 	  cost++;
   1570 	}
   1571     }
   1572 
   1573   if (TARGET_64BIT)
   1574     {
   1575       bool lu32i[2] = {(value & LU32I_B) == 0, (value & LU32I_B) == LU32I_B};
   1576       bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B};
   1577 
   1578       int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31;
   1579       int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51;
   1580 
   1581       uint32_t hival = (uint32_t) (value >> 32);
   1582       uint32_t loval = (uint32_t) value;
   1583 
   1584       /* Determine whether the upper 32 bits are sign-extended from the lower
   1585 	 32 bits. If it is, the instructions to load the high order can be
   1586 	 ommitted.  */
   1587       if (lu32i[sign31] && lu52i[sign31])
   1588 	return cost;
   1589       /* If the lower 32 bits are the same as the upper 32 bits, just copy
   1590 	 the lower 32 bits to the upper 32 bits.  */
   1591       else if (loval == hival)
   1592 	{
   1593 	  codes[cost].method = METHOD_MIRROR;
   1594 	  codes[cost].curr_value = value;
   1595 	  return cost + 1;
   1596 	}
   1597       /* Determine whether bits 32-51 are sign-extended from the lower 32
   1598 	 bits. If so, directly load 52-63 bits.  */
   1599       else if (lu32i[sign31])
   1600 	{
   1601 	  codes[cost].method = METHOD_LU52I;
   1602 	  codes[cost].value = value & LU52I_B;
   1603 	  codes[cost].curr_value = value;
   1604 	  return cost + 1;
   1605 	}
   1606 
   1607       codes[cost].method = METHOD_LU32I;
   1608       codes[cost].value = (value & LU32I_B) | (sign51 ? LU52I_B : 0);
   1609       codes[cost].curr_value = (value & 0xfffffffffffff)
   1610 	| (sign51 ? LU52I_B : 0);
   1611       cost++;
   1612 
   1613       /* Determine whether the 52-61 bits are sign-extended from the low order,
   1614 	 and if not, load the 52-61 bits.  */
   1615       if (!lu52i[(value & (HOST_WIDE_INT_1U << 51)) >> 51])
   1616 	{
   1617 	  codes[cost].method = METHOD_LU52I;
   1618 	  codes[cost].value = value & LU52I_B;
   1619 	  codes[cost].curr_value = value;
   1620 	  cost++;
   1621 	}
   1622     }
   1623 
   1624   gcc_assert (cost <= LARCH_MAX_INTEGER_OPS);
   1625 
   1626   return cost;
   1627 }
   1628 
   1629 /* Fill CODES with a sequence of rtl operations to load VALUE.
   1630    Return the number of operations needed.
   1631    Split interger in loongarch_output_move.  */
   1632 
   1633 static unsigned int
   1634 loongarch_integer_cost (HOST_WIDE_INT value)
   1635 {
   1636   struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS];
   1637   return loongarch_build_integer (codes, value);
   1638 }
   1639 
   1640 /* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
   1641 
   1642 static bool
   1643 loongarch_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
   1644 {
   1645   return loongarch_const_insns (x) > 0;
   1646 }
   1647 
   1648 /* Return true if X is a thread-local symbol.  */
   1649 
   1650 static bool
   1651 loongarch_tls_symbol_p (rtx x)
   1652 {
   1653   return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0;
   1654 }
   1655 
   1656 /* Return true if SYMBOL_REF X is associated with a global symbol
   1657    (in the STB_GLOBAL sense).  */
   1658 
   1659 bool
   1660 loongarch_global_symbol_p (const_rtx x)
   1661 {
   1662   if (LABEL_REF_P (x))
   1663     return false;
   1664 
   1665   const_tree decl = SYMBOL_REF_DECL (x);
   1666 
   1667   if (!decl)
   1668     return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x);
   1669 
   1670   /* Weakref symbols are not TREE_PUBLIC, but their targets are global
   1671      or weak symbols.  Relocations in the object file will be against
   1672      the target symbol, so it's that symbol's binding that matters here.  */
   1673   return DECL_P (decl) && (TREE_PUBLIC (decl) || DECL_WEAK (decl));
   1674 }
   1675 
   1676 bool
   1677 loongarch_global_symbol_noweak_p (const_rtx x)
   1678 {
   1679   if (LABEL_REF_P (x))
   1680     return false;
   1681 
   1682   const_tree decl = SYMBOL_REF_DECL (x);
   1683 
   1684   if (!decl)
   1685     return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x);
   1686 
   1687   return DECL_P (decl) && TREE_PUBLIC (decl);
   1688 }
   1689 
   1690 bool
   1691 loongarch_weak_symbol_p (const_rtx x)
   1692 {
   1693   const_tree decl;
   1694   if (LABEL_REF_P (x) || !(decl = SYMBOL_REF_DECL (x)))
   1695     return false;
   1696   return DECL_P (decl) && DECL_WEAK (decl);
   1697 }
   1698 
   1699 /* Return true if SYMBOL_REF X binds locally.  */
   1700 
   1701 bool
   1702 loongarch_symbol_binds_local_p (const_rtx x)
   1703 {
   1704   if (TARGET_DIRECT_EXTERN_ACCESS)
   1705     return true;
   1706 
   1707   if (SYMBOL_REF_P (x))
   1708     return (SYMBOL_REF_DECL (x)
   1709 	    ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
   1710 	    : SYMBOL_REF_LOCAL_P (x));
   1711   else
   1712     return false;
   1713 }
   1714 
   1715 /* Return true if OP is a constant vector with the number of units in MODE,
   1716    and each unit has the same bit set.  */
   1717 
   1718 bool
   1719 loongarch_const_vector_bitimm_set_p (rtx op, machine_mode mode)
   1720 {
   1721   if (GET_CODE (op) == CONST_VECTOR && op != CONST0_RTX (mode))
   1722     {
   1723       unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0));
   1724       int vlog2 = exact_log2 (val & GET_MODE_MASK (GET_MODE_INNER (mode)));
   1725 
   1726       if (vlog2 != -1)
   1727 	{
   1728 	  gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
   1729 	  gcc_assert (vlog2 >= 0 && vlog2 <= GET_MODE_UNIT_BITSIZE (mode) - 1);
   1730 	  return loongarch_const_vector_same_val_p (op, mode);
   1731 	}
   1732     }
   1733 
   1734   return false;
   1735 }
   1736 
   1737 /* Return true if OP is a constant vector with the number of units in MODE,
   1738    and each unit has the same bit clear.  */
   1739 
   1740 bool
   1741 loongarch_const_vector_bitimm_clr_p (rtx op, machine_mode mode)
   1742 {
   1743   if (GET_CODE (op) == CONST_VECTOR && op != CONSTM1_RTX (mode))
   1744     {
   1745       unsigned HOST_WIDE_INT val = ~UINTVAL (CONST_VECTOR_ELT (op, 0));
   1746       int vlog2 = exact_log2 (val & GET_MODE_MASK (GET_MODE_INNER (mode)));
   1747 
   1748       if (vlog2 != -1)
   1749 	{
   1750 	  gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
   1751 	  gcc_assert (vlog2 >= 0 && vlog2 <= GET_MODE_UNIT_BITSIZE (mode) - 1);
   1752 	  return loongarch_const_vector_same_val_p (op, mode);
   1753 	}
   1754     }
   1755 
   1756   return false;
   1757 }
   1758 
   1759 /* Return true if OP is a constant vector with the number of units in MODE,
   1760    and each unit has the same value.  */
   1761 
   1762 bool
   1763 loongarch_const_vector_same_val_p (rtx op, machine_mode mode)
   1764 {
   1765   int i, nunits = GET_MODE_NUNITS (mode);
   1766   rtx first;
   1767 
   1768   if (GET_CODE (op) != CONST_VECTOR || GET_MODE (op) != mode)
   1769     return false;
   1770 
   1771   first = CONST_VECTOR_ELT (op, 0);
   1772   for (i = 1; i < nunits; i++)
   1773     if (!rtx_equal_p (first, CONST_VECTOR_ELT (op, i)))
   1774       return false;
   1775 
   1776   return true;
   1777 }
   1778 
   1779 /* Return true if OP is a constant vector with the number of units in MODE,
   1780    and each unit has the same value as well as replicated bytes in the value.
   1781 */
   1782 
   1783 bool
   1784 loongarch_const_vector_same_bytes_p (rtx op, machine_mode mode)
   1785 {
   1786   int i, bytes;
   1787   HOST_WIDE_INT val, first_byte;
   1788   rtx first;
   1789 
   1790   if (!loongarch_const_vector_same_val_p (op, mode))
   1791     return false;
   1792 
   1793   first = CONST_VECTOR_ELT (op, 0);
   1794   bytes = GET_MODE_UNIT_SIZE (mode);
   1795   val = INTVAL (first);
   1796   first_byte = val & 0xff;
   1797   for (i = 1; i < bytes; i++)
   1798     {
   1799       val >>= 8;
   1800       if ((val & 0xff) != first_byte)
   1801 	return false;
   1802     }
   1803 
   1804   return true;
   1805 }
   1806 
   1807 /* Return true if OP is a constant vector with the number of units in MODE,
   1808    and each unit has the same integer value in the range [LOW, HIGH].  */
   1809 
   1810 bool
   1811 loongarch_const_vector_same_int_p (rtx op, machine_mode mode, HOST_WIDE_INT low,
   1812 				   HOST_WIDE_INT high)
   1813 {
   1814   HOST_WIDE_INT value;
   1815   rtx elem0;
   1816 
   1817   if (!loongarch_const_vector_same_val_p (op, mode))
   1818     return false;
   1819 
   1820   elem0 = CONST_VECTOR_ELT (op, 0);
   1821   if (!CONST_INT_P (elem0))
   1822     return false;
   1823 
   1824   value = INTVAL (elem0);
   1825   return (value >= low && value <= high);
   1826 }
   1827 
   1828 /* Return true if OP is a constant vector with repeated 4-element sets
   1829    in mode MODE.  */
   1830 
   1831 bool
   1832 loongarch_const_vector_shuffle_set_p (rtx op, machine_mode mode)
   1833 {
   1834   int nunits = GET_MODE_NUNITS (mode);
   1835   int nsets = nunits / 4;
   1836   int set = 0;
   1837   int i, j;
   1838 
   1839   /* Check if we have the same 4-element sets.  */
   1840   for (j = 0; j < nsets; j++, set = 4 * j)
   1841     for (i = 0; i < 4; i++)
   1842       if ((INTVAL (XVECEXP (op, 0, i))
   1843 	   != (INTVAL (XVECEXP (op, 0, set + i)) - set))
   1844 	  || !IN_RANGE (INTVAL (XVECEXP (op, 0, set + i)), 0, set + 3))
   1845 	return false;
   1846   return true;
   1847 }
   1848 
   1849 /* Return true if rtx constants of mode MODE should be put into a small
   1850    data section.  */
   1851 
   1852 static bool
   1853 loongarch_rtx_constant_in_small_data_p (machine_mode mode)
   1854 {
   1855   return (GET_MODE_SIZE (mode) <= g_switch_value);
   1856 }
   1857 
   1858 /* Return the method that should be used to access SYMBOL_REF or
   1859    LABEL_REF X.  */
   1860 
   1861 static enum loongarch_symbol_type
   1862 loongarch_classify_symbol (const_rtx x)
   1863 {
   1864   enum loongarch_symbol_type pcrel =
   1865     TARGET_CMODEL_EXTREME ? SYMBOL_PCREL64 : SYMBOL_PCREL;
   1866 
   1867   if (!SYMBOL_REF_P (x))
   1868     return pcrel;
   1869 
   1870   if (SYMBOL_REF_TLS_MODEL (x))
   1871     return SYMBOL_TLS;
   1872 
   1873   if (!loongarch_symbol_binds_local_p (x))
   1874     return SYMBOL_GOT_DISP;
   1875 
   1876   tree t = SYMBOL_REF_DECL (x);
   1877   if (!t)
   1878     return pcrel;
   1879 
   1880   t = lookup_attribute ("model", DECL_ATTRIBUTES (t));
   1881   if (!t)
   1882     return pcrel;
   1883 
   1884   t = TREE_VALUE (TREE_VALUE (t));
   1885 
   1886   /* loongarch_handle_model_attribute should reject other values.  */
   1887   gcc_assert (TREE_CODE (t) == STRING_CST);
   1888 
   1889   const char *model = TREE_STRING_POINTER (t);
   1890   if (strcmp (model, "normal") == 0)
   1891     return SYMBOL_PCREL;
   1892   if (strcmp (model, "extreme") == 0)
   1893     return SYMBOL_PCREL64;
   1894 
   1895   /* loongarch_handle_model_attribute should reject unknown model
   1896      name.  */
   1897   gcc_unreachable ();
   1898 }
   1899 
   1900 /* Classify the base of symbolic expression X, given that X appears in
   1901    context CONTEXT.  */
   1902 
   1903 static enum loongarch_symbol_type
   1904 loongarch_classify_symbolic_expression (rtx x)
   1905 {
   1906   rtx offset;
   1907 
   1908   split_const (x, &x, &offset);
   1909   if (UNSPEC_ADDRESS_P (x))
   1910     return UNSPEC_ADDRESS_TYPE (x);
   1911 
   1912   return loongarch_classify_symbol (x);
   1913 }
   1914 
   1915 /* Return true if X is a symbolic constant.  If it is,
   1916    store the type of the symbol in *SYMBOL_TYPE.  */
   1917 
   1918 bool
   1919 loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type)
   1920 {
   1921   rtx offset;
   1922 
   1923   split_const (x, &x, &offset);
   1924   if (UNSPEC_ADDRESS_P (x))
   1925     {
   1926       *symbol_type = UNSPEC_ADDRESS_TYPE (x);
   1927       x = UNSPEC_ADDRESS (x);
   1928     }
   1929   else if (SYMBOL_REF_P (x) || LABEL_REF_P (x))
   1930     *symbol_type = loongarch_classify_symbol (x);
   1931   else
   1932     return false;
   1933 
   1934   if (offset == const0_rtx)
   1935     return true;
   1936 
   1937   /* Check whether a nonzero offset is valid for the underlying
   1938      relocations.  */
   1939   switch (*symbol_type)
   1940     {
   1941     case SYMBOL_PCREL64:
   1942       /* When the code model is extreme, the non-zero offset situation
   1943 	 has not been handled well, so it is disabled here now.  */
   1944       if (!loongarch_explicit_relocs_p (SYMBOL_PCREL64))
   1945 	return false;
   1946     /* fall through */
   1947     case SYMBOL_PCREL:
   1948       /* GAS rejects offsets outside the range [-2^31, 2^31-1].  */
   1949       return sext_hwi (INTVAL (offset), 32) == INTVAL (offset);
   1950 
   1951     /* The following symbol types do not allow non-zero offsets.  */
   1952     case SYMBOL_GOT_DISP:
   1953     case SYMBOL_TLS_IE:
   1954     case SYMBOL_TLSGD:
   1955     case SYMBOL_TLSLDM:
   1956     case SYMBOL_TLS:
   1957     /* From an implementation perspective, tls_le symbols are allowed to
   1958        have non-zero offsets, but currently binutils has not added support,
   1959        so the generation of non-zero offsets is prohibited here.  */
   1960     case SYMBOL_TLS_LE:
   1961       return false;
   1962     }
   1963   gcc_unreachable ();
   1964 }
   1965 
   1966 /* If -mexplicit-relocs=auto, we use machine operations with reloc hints
   1967    for cases where the linker is unable to relax so we can schedule the
   1968    machine operations, otherwise use an assembler pseudo-op so the
   1969    assembler will generate R_LARCH_RELAX.  */
   1970 
   1971 bool
   1972 loongarch_explicit_relocs_p (enum loongarch_symbol_type type)
   1973 {
   1974   if (la_opt_explicit_relocs != EXPLICIT_RELOCS_AUTO)
   1975     return la_opt_explicit_relocs == EXPLICIT_RELOCS_ALWAYS;
   1976 
   1977   /* The linker don't know how to relax accesses in extreme code model.  */
   1978   if (loongarch_symbol_extreme_p (type))
   1979     return true;
   1980 
   1981   switch (type)
   1982     {
   1983       case SYMBOL_TLS_IE:
   1984       case SYMBOL_TLS_LE:
   1985       case SYMBOL_PCREL64:
   1986 	/* TLS IE cannot be relaxed.  TLS LE relaxation is different from
   1987 	   the normal R_LARCH_RELAX-based relaxation and it **requires**
   1988 	   using the explicit %le_{lo12,hi20,add}_r relocs.  The linker
   1989 	   does not relax 64-bit pc-relative accesses as at now.  */
   1990 	return true;
   1991       case SYMBOL_GOT_DISP:
   1992 	/* If we are performing LTO for a final link, and we have the
   1993 	   linker plugin so we know the resolution of the symbols, then
   1994 	   all GOT references are binding to external symbols or
   1995 	   preemptable symbols.  So the linker cannot relax them.  */
   1996 	return (in_lto_p
   1997 		&& !flag_incremental_link
   1998 		&& HAVE_LTO_PLUGIN == 2
   1999 		&& (!global_options_set.x_flag_use_linker_plugin
   2000 		    || global_options.x_flag_use_linker_plugin));
   2001       default:
   2002 	return false;
   2003     }
   2004 }
   2005 
   2006 /* Returns the number of instructions necessary to reference a symbol.  */
   2007 
   2008 static int
   2009 loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
   2010 {
   2011   /* LSX LD.* and ST.* cannot support loading symbols via an immediate
   2012      operand.  */
   2013   if (mode != MAX_MACHINE_MODE
   2014       && (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode)))
   2015     return 0;
   2016 
   2017   switch (type)
   2018     {
   2019     case SYMBOL_GOT_DISP:
   2020       /* The constant will have to be loaded from the GOT before it
   2021 	 is used in an address.  */
   2022       if (!loongarch_explicit_relocs_p (type) && mode != MAX_MACHINE_MODE)
   2023 	return 0;
   2024 
   2025       return 3;
   2026 
   2027     case SYMBOL_PCREL:
   2028     case SYMBOL_TLS_IE:
   2029     case SYMBOL_TLS_LE:
   2030       return 2;
   2031 
   2032     case SYMBOL_TLSGD:
   2033     case SYMBOL_TLSLDM:
   2034       return TARGET_TLS_DESC ? 4 : 3;
   2035 
   2036     case SYMBOL_PCREL64:
   2037       return 5;
   2038 
   2039     case SYMBOL_TLS:
   2040       /* We don't treat a bare TLS symbol as a constant.  */
   2041       return 0;
   2042     }
   2043   gcc_unreachable ();
   2044 }
   2045 
   2046 /* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
   2047 
   2048 static bool
   2049 loongarch_cannot_force_const_mem (machine_mode mode, rtx x)
   2050 {
   2051   enum loongarch_symbol_type type;
   2052   rtx base, offset;
   2053 
   2054   /* As an optimization, reject constants that loongarch_legitimize_move
   2055      can expand inline.
   2056 
   2057      Suppose we have a multi-instruction sequence that loads constant C
   2058      into register R.  If R does not get allocated a hard register, and
   2059      R is used in an operand that allows both registers and memory
   2060      references, reload will consider forcing C into memory and using
   2061      one of the instruction's memory alternatives.  Returning false
   2062      here will force it to use an input reload instead.  */
   2063   if ((CONST_INT_P (x) || GET_CODE (x) == CONST_VECTOR)
   2064       && loongarch_legitimate_constant_p (mode, x))
   2065     return true;
   2066 
   2067   split_const (x, &base, &offset);
   2068   if (loongarch_symbolic_constant_p (base, &type))
   2069     {
   2070       /* The same optimization as for CONST_INT.  */
   2071       if (IMM12_INT (offset)
   2072 	  && loongarch_symbol_insns (type, MAX_MACHINE_MODE) > 0)
   2073 	return true;
   2074     }
   2075 
   2076   /* TLS symbols must be computed by loongarch_legitimize_move.  */
   2077   if (tls_referenced_p (x))
   2078     return true;
   2079 
   2080   return false;
   2081 }
   2082 
   2083 /* Return true if register REGNO is a valid base register for mode MODE.
   2084    STRICT_P is true if REG_OK_STRICT is in effect.  */
   2085 
   2086 int
   2087 loongarch_regno_mode_ok_for_base_p (int regno,
   2088 				    machine_mode mode ATTRIBUTE_UNUSED,
   2089 				    bool strict_p)
   2090 {
   2091   if (!HARD_REGISTER_NUM_P (regno))
   2092     {
   2093       if (!strict_p)
   2094 	return true;
   2095       regno = reg_renumber[regno];
   2096     }
   2097 
   2098   /* These fake registers will be eliminated to either the stack or
   2099      hard frame pointer, both of which are usually valid base registers.
   2100      Reload deals with the cases where the eliminated form isn't valid.  */
   2101   if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
   2102     return true;
   2103 
   2104   return GP_REG_P (regno);
   2105 }
   2106 
   2107 /* Return true if X is a valid base register for mode MODE.
   2108    STRICT_P is true if REG_OK_STRICT is in effect.  */
   2109 
   2110 static bool
   2111 loongarch_valid_base_register_p (rtx x, machine_mode mode, bool strict_p)
   2112 {
   2113   if (!strict_p && SUBREG_P (x))
   2114     x = SUBREG_REG (x);
   2115 
   2116   return (REG_P (x)
   2117 	  && loongarch_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p));
   2118 }
   2119 
   2120 /* Return true if, for every base register BASE_REG, (plus BASE_REG X)
   2121    can address a value of mode MODE.  */
   2122 
   2123 static bool
   2124 loongarch_valid_offset_p (rtx x, machine_mode mode)
   2125 {
   2126   /* Check that X is a signed 12-bit number,
   2127      or check that X is a signed 16-bit number
   2128      and offset 4 byte aligned.  */
   2129   if (!(const_arith_operand (x, Pmode)
   2130 	|| ((mode == E_SImode || mode == E_DImode)
   2131 	    && const_imm16_operand (x, Pmode)
   2132 	    && (loongarch_signed_immediate_p (INTVAL (x), 14, 2)))))
   2133     return false;
   2134 
   2135   /* We may need to split multiword moves, so make sure that every word
   2136      is accessible.  */
   2137   if (!(LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))
   2138       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
   2139       && !IMM12_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD))
   2140     return false;
   2141 
   2142   return true;
   2143 }
   2144 
   2145 /* Should a symbol of type SYMBOL_TYPE should be split in two or more?  */
   2146 
   2147 bool
   2148 loongarch_split_symbol_type (enum loongarch_symbol_type symbol_type)
   2149 {
   2150   switch (symbol_type)
   2151     {
   2152     case SYMBOL_PCREL:
   2153     case SYMBOL_PCREL64:
   2154     case SYMBOL_GOT_DISP:
   2155     case SYMBOL_TLS_IE:
   2156     case SYMBOL_TLS_LE:
   2157     case SYMBOL_TLSGD:
   2158     case SYMBOL_TLSLDM:
   2159       return true;
   2160 
   2161     case SYMBOL_TLS:
   2162       return false;
   2163 
   2164     default:
   2165       gcc_unreachable ();
   2166     }
   2167 }
   2168 
   2169 /* Return true if a LO_SUM can address a value of mode MODE when the
   2170    LO_SUM symbol has type SYMBOL_TYPE.  */
   2171 
   2172 static bool
   2173 loongarch_valid_lo_sum_p (enum loongarch_symbol_type symbol_type,
   2174 			  machine_mode mode, rtx x)
   2175 {
   2176   int align, size;
   2177 
   2178   /* Check that symbols of type SYMBOL_TYPE can be used to access values
   2179      of mode MODE.  */
   2180   if (loongarch_symbol_insns (symbol_type, mode) == 0)
   2181     return false;
   2182 
   2183   /* Check that there is a known low-part relocation.  */
   2184   if (!loongarch_split_symbol_type (symbol_type))
   2185     return false;
   2186 
   2187   /* We can't tell size or alignment when we have BLKmode, so try extracing a
   2188      decl from the symbol if possible.  */
   2189   if (mode == BLKmode)
   2190     {
   2191       rtx offset;
   2192 
   2193       /* Extract the symbol from the LO_SUM operand, if any.  */
   2194       split_const (x, &x, &offset);
   2195 
   2196       /* Might be a CODE_LABEL.  We can compute align but not size for that,
   2197 	 so don't bother trying to handle it.  */
   2198       if (!SYMBOL_REF_P (x))
   2199 	return false;
   2200 
   2201       /* Use worst case assumptions if we don't have a SYMBOL_REF_DECL.  */
   2202       align = (SYMBOL_REF_DECL (x)
   2203 	       ? DECL_ALIGN (SYMBOL_REF_DECL (x))
   2204 	       : 1);
   2205       size = (SYMBOL_REF_DECL (x) && DECL_SIZE (SYMBOL_REF_DECL (x))
   2206 	      ? tree_to_uhwi (DECL_SIZE (SYMBOL_REF_DECL (x)))
   2207 	      : 2*BITS_PER_WORD);
   2208     }
   2209   else
   2210     {
   2211       align = GET_MODE_ALIGNMENT (mode);
   2212       size = GET_MODE_BITSIZE (mode);
   2213     }
   2214 
   2215   /* We may need to split multiword moves, so make sure that each word
   2216      can be accessed without inducing a carry.  */
   2217   if (size > BITS_PER_WORD
   2218       && (!TARGET_STRICT_ALIGN || size > align))
   2219     return false;
   2220 
   2221   return true;
   2222 }
   2223 
   2224 static bool
   2225 loongarch_valid_index_p (struct loongarch_address_info *info, rtx x,
   2226 			 machine_mode mode, bool strict_p)
   2227 {
   2228   rtx index;
   2229 
   2230   if ((REG_P (x) || SUBREG_P (x))
   2231       && GET_MODE (x) == Pmode)
   2232     {
   2233       index = x;
   2234     }
   2235   else
   2236     return false;
   2237 
   2238   if (!strict_p
   2239       && SUBREG_P (index)
   2240       && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))])
   2241     index = SUBREG_REG (index);
   2242 
   2243   if (loongarch_valid_base_register_p (index, mode, strict_p))
   2244     {
   2245       info->type = ADDRESS_REG_REG;
   2246       info->offset = index;
   2247       return true;
   2248     }
   2249 
   2250   return false;
   2251 }
   2252 
   2253 /* Return true if X is a valid address for machine mode MODE.  If it is,
   2254    fill in INFO appropriately.  STRICT_P is true if REG_OK_STRICT is in
   2255    effect.  */
   2256 
   2257 static bool
   2258 loongarch_classify_address (struct loongarch_address_info *info, rtx x,
   2259 			    machine_mode mode, bool strict_p)
   2260 {
   2261   switch (GET_CODE (x))
   2262     {
   2263     case REG:
   2264     case SUBREG:
   2265       info->type = ADDRESS_REG;
   2266       info->reg = x;
   2267       info->offset = const0_rtx;
   2268       return loongarch_valid_base_register_p (info->reg, mode, strict_p);
   2269 
   2270     case PLUS:
   2271       if (loongarch_valid_base_register_p (XEXP (x, 0), mode, strict_p)
   2272 	  && loongarch_valid_index_p (info, XEXP (x, 1), mode, strict_p))
   2273 	{
   2274 	  info->reg = XEXP (x, 0);
   2275 	  return true;
   2276 	}
   2277 
   2278       if (loongarch_valid_base_register_p (XEXP (x, 1), mode, strict_p)
   2279 	  && loongarch_valid_index_p (info, XEXP (x, 0), mode, strict_p))
   2280 	{
   2281 	  info->reg = XEXP (x, 1);
   2282 	  return true;
   2283 	}
   2284 
   2285       info->type = ADDRESS_REG;
   2286       info->reg = XEXP (x, 0);
   2287       info->offset = XEXP (x, 1);
   2288       return (loongarch_valid_base_register_p (info->reg, mode, strict_p)
   2289 	      && loongarch_valid_offset_p (info->offset, mode));
   2290 
   2291     case LO_SUM:
   2292       info->type = ADDRESS_LO_SUM;
   2293       info->reg = XEXP (x, 0);
   2294       info->offset = XEXP (x, 1);
   2295       /* We have to trust the creator of the LO_SUM to do something vaguely
   2296 	 sane.  Target-independent code that creates a LO_SUM should also
   2297 	 create and verify the matching HIGH.  Target-independent code that
   2298 	 adds an offset to a LO_SUM must prove that the offset will not
   2299 	 induce a carry.  Failure to do either of these things would be
   2300 	 a bug, and we are not required to check for it here.  The MIPS
   2301 	 backend itself should only create LO_SUMs for valid symbolic
   2302 	 constants, with the high part being either a HIGH or a copy
   2303 	 of _gp. */
   2304       info->symbol_type
   2305 	= loongarch_classify_symbolic_expression (info->offset);
   2306       return (loongarch_valid_base_register_p (info->reg, mode, strict_p)
   2307 	      && loongarch_valid_lo_sum_p (info->symbol_type, mode,
   2308 					   info->offset));
   2309     case CONST_INT:
   2310       /* Small-integer addresses don't occur very often, but they
   2311 	 are legitimate if $r0 is a valid base register.  */
   2312       info->type = ADDRESS_CONST_INT;
   2313       return IMM12_OPERAND (INTVAL (x));
   2314 
   2315     default:
   2316       return false;
   2317     }
   2318 }
   2319 
   2320 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
   2321 
   2322 static bool
   2323 loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
   2324 				code_helper = ERROR_MARK)
   2325 {
   2326   struct loongarch_address_info addr;
   2327 
   2328   return loongarch_classify_address (&addr, x, mode, strict_p);
   2329 }
   2330 
   2331 /* Return true if ADDR matches the pattern for the indexed address
   2332    instruction.  */
   2333 
   2334 static bool
   2335 loongarch_index_address_p (rtx addr, machine_mode mode ATTRIBUTE_UNUSED)
   2336 {
   2337   if (GET_CODE (addr) != PLUS
   2338       || !REG_P (XEXP (addr, 0))
   2339       || !REG_P (XEXP (addr, 1)))
   2340     return false;
   2341   return true;
   2342 }
   2343 
   2344 /* Return the number of instructions needed to load or store a value
   2345    of mode MODE at address X.  Return 0 if X isn't valid for MODE.
   2346    Assume that multiword moves may need to be split into word moves
   2347    if MIGHT_SPLIT_P, otherwise assume that a single load or store is
   2348    enough.  */
   2349 
   2350 int
   2351 loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
   2352 {
   2353   struct loongarch_address_info addr;
   2354   int factor;
   2355   bool lsx_p = (!might_split_p
   2356 		&& (LSX_SUPPORTED_MODE_P (mode)
   2357 		    || LASX_SUPPORTED_MODE_P (mode)));
   2358 
   2359   if (!loongarch_classify_address (&addr, x, mode, false))
   2360     return 0;
   2361 
   2362   /* BLKmode is used for single unaligned loads and stores and should
   2363      not count as a multiword mode.  (GET_MODE_SIZE (BLKmode) is pretty
   2364      meaningless, so we have to single it out as a special case one way
   2365      or the other.)  */
   2366   if (mode != BLKmode && might_split_p)
   2367     factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   2368   else
   2369     factor = 1;
   2370 
   2371   if (loongarch_classify_address (&addr, x, mode, false))
   2372     switch (addr.type)
   2373       {
   2374       case ADDRESS_REG:
   2375 	if (lsx_p)
   2376 	  {
   2377 	    /* LSX LD.* and ST.* supports 12-bit signed offsets.  */
   2378 	    if (IMM12_OPERAND (INTVAL (addr.offset)))
   2379 	      return 1;
   2380 	    else
   2381 	      return 0;
   2382 	  }
   2383 	return factor;
   2384 
   2385       case ADDRESS_REG_REG:
   2386 	return factor;
   2387 
   2388       case ADDRESS_CONST_INT:
   2389 	return lsx_p ? 0 : factor;
   2390 
   2391       case ADDRESS_LO_SUM:
   2392 	return factor + 1;
   2393 
   2394       case ADDRESS_SYMBOLIC:
   2395 	return lsx_p ? 0
   2396 	  : factor * loongarch_symbol_insns (addr.symbol_type, mode);
   2397       }
   2398   return 0;
   2399 }
   2400 
   2401 /* Return true if X fits within an unsigned field of BITS bits that is
   2402    shifted left SHIFT bits before being used.  */
   2403 
   2404 bool
   2405 loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits,
   2406 				int shift = 0)
   2407 {
   2408   return (x & ((1 << shift) - 1)) == 0 && x < ((unsigned) 1 << (shift + bits));
   2409 }
   2410 
   2411 /* Return true if X fits within a signed field of BITS bits that is
   2412    shifted left SHIFT bits before being used.  */
   2413 
   2414 bool
   2415 loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits,
   2416 			      int shift = 0)
   2417 {
   2418   x += 1 << (bits + shift - 1);
   2419   return loongarch_unsigned_immediate_p (x, bits, shift);
   2420 }
   2421 
   2422 /* Return the scale shift that applied to LSX LD/ST address offset.  */
   2423 
   2424 int
   2425 loongarch_ldst_scaled_shift (machine_mode mode)
   2426 {
   2427   int shift = exact_log2 (GET_MODE_UNIT_SIZE (mode));
   2428 
   2429   if (shift < 0 || shift > 8)
   2430     gcc_unreachable ();
   2431 
   2432   return shift;
   2433 }
   2434 
   2435 /* Return true if X is a legitimate address with a 12-bit offset
   2436    or addr.type is ADDRESS_LO_SUM.
   2437    MODE is the mode of the value being accessed.  */
   2438 
   2439 bool
   2440 loongarch_12bit_offset_address_p (rtx x, machine_mode mode)
   2441 {
   2442   struct loongarch_address_info addr;
   2443 
   2444   return (loongarch_classify_address (&addr, x, mode, false)
   2445 	  && ((addr.type == ADDRESS_REG
   2446 	       && CONST_INT_P (addr.offset)
   2447 	       && LARCH_12BIT_OFFSET_P (INTVAL (addr.offset)))
   2448 	      || addr.type == ADDRESS_LO_SUM));
   2449 }
   2450 
   2451 /* Return true if X is a legitimate address with a 14-bit offset shifted 2.
   2452    MODE is the mode of the value being accessed.  */
   2453 
   2454 bool
   2455 loongarch_14bit_shifted_offset_address_p (rtx x, machine_mode mode)
   2456 {
   2457   struct loongarch_address_info addr;
   2458 
   2459   return (loongarch_classify_address (&addr, x, mode, false)
   2460 	  && addr.type == ADDRESS_REG
   2461 	  && CONST_INT_P (addr.offset)
   2462 	  && LARCH_16BIT_OFFSET_P (INTVAL (addr.offset))
   2463 	  && LARCH_SHIFT_2_OFFSET_P (INTVAL (addr.offset)));
   2464 }
   2465 
   2466 /* Return true if X is a legitimate address with base and index.
   2467    MODE is the mode of the value being accessed.  */
   2468 
   2469 bool
   2470 loongarch_base_index_address_p (rtx x, machine_mode mode)
   2471 {
   2472   struct loongarch_address_info addr;
   2473 
   2474   return (loongarch_classify_address (&addr, x, mode, false)
   2475 	  && addr.type == ADDRESS_REG_REG
   2476 	  && REG_P (addr.offset));
   2477 }
   2478 
   2479 /* Return the number of instructions needed to load constant X,
   2480    Return 0 if X isn't a valid constant.  */
   2481 
   2482 int
   2483 loongarch_const_insns (rtx x)
   2484 {
   2485   enum loongarch_symbol_type symbol_type;
   2486   rtx offset;
   2487 
   2488   switch (GET_CODE (x))
   2489     {
   2490     case HIGH:
   2491       if (!loongarch_symbolic_constant_p (XEXP (x, 0), &symbol_type)
   2492 	  || !loongarch_split_symbol_type (symbol_type))
   2493 	return 0;
   2494 
   2495       /* This is simply a PCALAU12I.  */
   2496       return 1;
   2497 
   2498     case CONST_INT:
   2499       return loongarch_integer_cost (INTVAL (x));
   2500 
   2501     case CONST_VECTOR:
   2502       if ((LSX_SUPPORTED_MODE_P (GET_MODE (x))
   2503 	   || LASX_SUPPORTED_MODE_P (GET_MODE (x)))
   2504 	  && loongarch_const_vector_same_int_p (x, GET_MODE (x), -512, 511))
   2505 	return 1;
   2506       /* Fall through.  */
   2507     case CONST_DOUBLE:
   2508       return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0;
   2509 
   2510     case CONST:
   2511       /* See if we can refer to X directly.  */
   2512       if (loongarch_symbolic_constant_p (x, &symbol_type))
   2513 	return loongarch_symbol_insns (symbol_type, MAX_MACHINE_MODE);
   2514 
   2515       /* Otherwise try splitting the constant into a base and offset.
   2516 	 If the offset is a 12-bit value, we can load the base address
   2517 	 into a register and then use ADDI.{W/D} to add in the offset.
   2518 	 If the offset is larger, we can load the base and offset
   2519 	 into separate registers and add them together with ADD.{W/D}.
   2520 	 However, the latter is only possible before reload; during
   2521 	 and after reload, we must have the option of forcing the
   2522 	 constant into the pool instead.  */
   2523       split_const (x, &x, &offset);
   2524       if (offset != 0)
   2525 	{
   2526 	  int n = loongarch_const_insns (x);
   2527 	  if (n != 0)
   2528 	    {
   2529 	      if (IMM12_INT (offset))
   2530 		return n + 1;
   2531 	      else if (!targetm.cannot_force_const_mem (GET_MODE (x), x))
   2532 		return n + 1 + loongarch_integer_cost (INTVAL (offset));
   2533 	    }
   2534 	}
   2535       return 0;
   2536 
   2537     case SYMBOL_REF:
   2538     case LABEL_REF:
   2539       return loongarch_symbol_insns (
   2540 		loongarch_classify_symbol (x), MAX_MACHINE_MODE);
   2541 
   2542     default:
   2543       return 0;
   2544     }
   2545 }
   2546 
   2547 /* X is a doubleword constant that can be handled by splitting it into
   2548    two words and loading each word separately.  Return the number of
   2549    instructions required to do this.  */
   2550 
   2551 int
   2552 loongarch_split_const_insns (rtx x)
   2553 {
   2554   unsigned int low, high;
   2555 
   2556   low = loongarch_const_insns (loongarch_subword (x, false));
   2557   high = loongarch_const_insns (loongarch_subword (x, true));
   2558   gcc_assert (low > 0 && high > 0);
   2559   return low + high;
   2560 }
   2561 
   2562 /* Return one word of 128-bit value OP, taking into account the fixed
   2563    endianness of certain registers.  BYTE selects from the byte address.  */
   2564 
   2565 rtx
   2566 loongarch_subword_at_byte (rtx op, unsigned int byte)
   2567 {
   2568   machine_mode mode;
   2569 
   2570   mode = GET_MODE (op);
   2571   if (mode == VOIDmode)
   2572     mode = TImode;
   2573 
   2574   gcc_assert (!FP_REG_RTX_P (op));
   2575 
   2576   if (MEM_P (op))
   2577     return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte));
   2578 
   2579   return simplify_gen_subreg (word_mode, op, mode, byte);
   2580 }
   2581 
   2582 /* Return the number of instructions needed to implement INSN,
   2583    given that it loads from or stores to MEM.  */
   2584 
   2585 int
   2586 loongarch_load_store_insns (rtx mem, rtx_insn *insn)
   2587 {
   2588   machine_mode mode;
   2589   bool might_split_p;
   2590   rtx set;
   2591 
   2592   gcc_assert (MEM_P (mem));
   2593   mode = GET_MODE (mem);
   2594 
   2595   /* Try to prove that INSN does not need to be split.  */
   2596   might_split_p = GET_MODE_SIZE (mode) > UNITS_PER_WORD;
   2597   if (might_split_p)
   2598     {
   2599       set = single_set (insn);
   2600       if (set
   2601 	  && !loongarch_split_move_p (SET_DEST (set), SET_SRC (set)))
   2602 	might_split_p = false;
   2603     }
   2604 
   2605   return loongarch_address_insns (XEXP (mem, 0), mode, might_split_p);
   2606 }
   2607 
   2608 /* Return true if we need to trap on division by zero.  */
   2609 
   2610 bool
   2611 loongarch_check_zero_div_p (void)
   2612 {
   2613   /* if -m[no-]check-zero-division is given explicitly.  */
   2614   if (target_flags_explicit & MASK_CHECK_ZERO_DIV)
   2615     return TARGET_CHECK_ZERO_DIV;
   2616 
   2617   /* if not, don't trap for optimized code except -Og.  */
   2618   return !optimize || optimize_debug;
   2619 }
   2620 
   2621 /* Return the number of instructions needed for an integer division.  */
   2622 
   2623 int
   2624 loongarch_idiv_insns (machine_mode mode ATTRIBUTE_UNUSED)
   2625 {
   2626   int count;
   2627 
   2628   count = 1;
   2629   if (loongarch_check_zero_div_p ())
   2630     count += 2;
   2631 
   2632   return count;
   2633 }
   2634 
   2635 /* Emit an instruction of the form (set TARGET (CODE OP0 OP1)).  */
   2636 
   2637 void
   2638 loongarch_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
   2639 {
   2640   emit_insn (gen_rtx_SET (target, gen_rtx_fmt_ee (code, GET_MODE (target),
   2641 						  op0, op1)));
   2642 }
   2643 
   2644 /* Compute (CODE OP0 OP1) and store the result in a new register
   2645    of mode MODE.  Return that new register.  */
   2646 
   2647 static rtx
   2648 loongarch_force_binary (machine_mode mode, enum rtx_code code, rtx op0,
   2649 			rtx op1)
   2650 {
   2651   rtx reg;
   2652 
   2653   reg = gen_reg_rtx (mode);
   2654   loongarch_emit_binary (code, reg, op0, op1);
   2655   return reg;
   2656 }
   2657 
   2658 /* Copy VALUE to a register and return that register.  If new pseudos
   2659    are allowed, copy it into a new register, otherwise use DEST.  */
   2660 
   2661 static rtx
   2662 loongarch_force_temporary (rtx dest, rtx value)
   2663 {
   2664   if (can_create_pseudo_p ())
   2665     return force_reg (Pmode, value);
   2666   else
   2667     {
   2668       loongarch_emit_move (dest, value);
   2669       return dest;
   2670     }
   2671 }
   2672 
   2673 /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
   2674    then add CONST_INT OFFSET to the result.  */
   2675 
   2676 static rtx
   2677 loongarch_unspec_address_offset (rtx base, rtx offset,
   2678 				 enum loongarch_symbol_type symbol_type)
   2679 {
   2680   base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
   2681 			 UNSPEC_ADDRESS_FIRST + symbol_type);
   2682   if (offset != const0_rtx)
   2683     base = gen_rtx_PLUS (Pmode, base, offset);
   2684   return gen_rtx_CONST (Pmode, base);
   2685 }
   2686 
   2687 /* Return an UNSPEC address with underlying address ADDRESS and symbol
   2688    type SYMBOL_TYPE.  */
   2689 
   2690 rtx
   2691 loongarch_unspec_address (rtx address, enum loongarch_symbol_type symbol_type)
   2692 {
   2693   rtx base, offset;
   2694 
   2695   split_const (address, &base, &offset);
   2696   return loongarch_unspec_address_offset (base, offset, symbol_type);
   2697 }
   2698 
   2699 /* Emit an instruction of the form (set TARGET SRC).  */
   2700 
   2701 static rtx
   2702 loongarch_emit_set (rtx target, rtx src)
   2703 {
   2704   emit_insn (gen_rtx_SET (target, src));
   2705   return target;
   2706 }
   2707 
   2708 /* If OP is an UNSPEC address, return the address to which it refers,
   2709    otherwise return OP itself.  */
   2710 
   2711 rtx
   2712 loongarch_strip_unspec_address (rtx op)
   2713 {
   2714   rtx base, offset;
   2715 
   2716   split_const (op, &base, &offset);
   2717   if (UNSPEC_ADDRESS_P (base))
   2718     op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset));
   2719   return op;
   2720 }
   2721 
   2722 /* Return a legitimate address for REG + OFFSET.  TEMP is as for
   2723    loongarch_force_temporary; it is only needed when OFFSET is not a
   2724    IMM12_OPERAND.  */
   2725 
   2726 static rtx
   2727 loongarch_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
   2728 {
   2729   if (!IMM12_OPERAND (offset))
   2730     {
   2731       rtx high;
   2732 
   2733       /* Leave OFFSET as a 12-bit offset and put the excess in HIGH.
   2734 	 The addition inside the macro CONST_HIGH_PART may cause an
   2735 	 overflow, so we need to force a sign-extension check.  */
   2736       high = gen_int_mode (CONST_HIGH_PART (offset), Pmode);
   2737       offset = CONST_LOW_PART (offset);
   2738       high = loongarch_force_temporary (temp, high);
   2739       reg = loongarch_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
   2740     }
   2741   return plus_constant (Pmode, reg, offset);
   2742 }
   2743 
   2744 /* The __tls_get_addr symbol.  */
   2745 static GTY (()) rtx loongarch_tls_symbol;
   2746 
   2747 /* Load an entry for a TLS access.  */
   2748 
   2749 static rtx
   2750 loongarch_load_tls (rtx dest, rtx sym, enum loongarch_symbol_type type)
   2751 {
   2752   /* TLS LE gets a 32 or 64 bit offset here, so one register can do it.  */
   2753   if (type == SYMBOL_TLS_LE)
   2754     return gen_load_tls (Pmode, dest, sym);
   2755 
   2756   return loongarch_symbol_extreme_p (type)
   2757     ? gen_movdi_symbolic_off64 (dest, sym, gen_reg_rtx (DImode))
   2758     : gen_load_tls (Pmode, dest, sym);
   2759 }
   2760 
   2761 /* Return an instruction sequence that calls __tls_get_addr.  SYM is
   2762    the TLS symbol we are referencing and TYPE is the symbol type to use
   2763    (either global dynamic or local dynamic).  V0 is an RTX for the
   2764    return value location.  */
   2765 
   2766 static rtx_insn *
   2767 loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
   2768 {
   2769   rtx loc, a0;
   2770   rtx_insn *insn;
   2771   rtx tmp = gen_reg_rtx (Pmode);
   2772 
   2773   a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
   2774 
   2775   if (!loongarch_tls_symbol)
   2776     loongarch_tls_symbol = init_one_libfunc ("__tls_get_addr");
   2777 
   2778   loc = loongarch_unspec_address (sym, type);
   2779 
   2780   start_sequence ();
   2781 
   2782   if (loongarch_explicit_relocs_p (type))
   2783     {
   2784       if (TARGET_CMODEL_EXTREME)
   2785 	{
   2786 	  rtx part1 = gen_reg_rtx (Pmode);
   2787 	  rtx part2 = gen_reg_rtx (Pmode);
   2788 
   2789 	  emit_insn (gen_la_pcrel64_two_parts (part1, part2, loc));
   2790 	  emit_move_insn (a0, gen_rtx_PLUS (Pmode, part1, part2));
   2791 	}
   2792       else
   2793 	{
   2794 	  /* Split tls symbol to high and low.  */
   2795 	  rtx high = gen_rtx_HIGH (Pmode, copy_rtx (loc));
   2796 
   2797 	  high = loongarch_force_temporary (tmp, high);
   2798 	  emit_insn (gen_tls_low (Pmode, a0, high, loc));
   2799 	}
   2800     }
   2801   else
   2802     emit_insn (loongarch_load_tls (a0, loc, type));
   2803 
   2804   if (flag_plt)
   2805     {
   2806       switch (la_target.cmodel)
   2807 	{
   2808 	case CMODEL_NORMAL:
   2809 	  insn = emit_call_insn (gen_call_value_internal (v0,
   2810 							  loongarch_tls_symbol,
   2811 							  const0_rtx));
   2812 	  break;
   2813 
   2814 	case CMODEL_MEDIUM:
   2815 	    {
   2816 	      if (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE)
   2817 		{
   2818 		  rtx call;
   2819 
   2820 		 if (HAVE_AS_SUPPORT_CALL36)
   2821 		   call = gen_call_value_internal (v0, loongarch_tls_symbol,
   2822 						   const0_rtx);
   2823 		 else
   2824 		   {
   2825 		     rtx reg = gen_reg_rtx (Pmode);
   2826 		     emit_insn (gen_pcalau12i (Pmode, reg,
   2827 					       loongarch_tls_symbol));
   2828 		     call = gen_call_value_internal_1 (Pmode, v0, reg,
   2829 						       loongarch_tls_symbol,
   2830 						       const0_rtx);
   2831 		   }
   2832 		 insn = emit_call_insn (call);
   2833 		}
   2834 	      else
   2835 		{
   2836 		  rtx reg = gen_reg_rtx (Pmode);
   2837 		  emit_move_insn (reg, loongarch_tls_symbol);
   2838 		  insn = emit_call_insn (gen_call_value_internal (v0,
   2839 								  reg,
   2840 								  const0_rtx));
   2841 		}
   2842 	      break;
   2843 	    }
   2844 
   2845 	/* code model extreme not support plt.  */
   2846 	case CMODEL_EXTREME:
   2847 	case CMODEL_LARGE:
   2848 	case CMODEL_TINY:
   2849 	case CMODEL_TINY_STATIC:
   2850 	default:
   2851 	  gcc_unreachable ();
   2852 	}
   2853     }
   2854   else
   2855     {
   2856       rtx dest = gen_reg_rtx (Pmode);
   2857 
   2858       switch (la_target.cmodel)
   2859 	{
   2860 	case CMODEL_NORMAL:
   2861 	case CMODEL_MEDIUM:
   2862 	    {
   2863 	      if (loongarch_explicit_relocs_p (SYMBOL_GOT_DISP))
   2864 		{
   2865 		  rtx high = gen_reg_rtx (Pmode);
   2866 		  loongarch_emit_move (high,
   2867 				       gen_rtx_HIGH (Pmode,
   2868 						     loongarch_tls_symbol));
   2869 		  emit_insn (gen_ld_from_got (Pmode, dest, high,
   2870 					      loongarch_tls_symbol));
   2871 		}
   2872 	      else
   2873 		loongarch_emit_move (dest, loongarch_tls_symbol);
   2874 	      break;
   2875 	    }
   2876 
   2877 	case CMODEL_EXTREME:
   2878 	    {
   2879 	      if (loongarch_explicit_relocs_p (SYMBOL_GOT_DISP))
   2880 		{
   2881 		  gcc_assert (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE);
   2882 
   2883 		  rtx part1 = gen_reg_rtx (Pmode);
   2884 		  rtx part2 = gen_reg_rtx (Pmode);
   2885 
   2886 		  emit_insn (gen_la_pcrel64_two_parts (part1, part2,
   2887 						       loongarch_tls_symbol));
   2888 		  loongarch_emit_move (
   2889 		    dest,
   2890 		    gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode,
   2891 						      part1,
   2892 						      part2)));
   2893 
   2894 		  /* Put an REG_EQUAL note here to allow CSE (storing
   2895 		     part1 + part2, i.e. the address of tls_get_addr into
   2896 		     a saved register and use it for multiple TLS
   2897 		     accesses).  */
   2898 		  rtx sum = gen_rtx_UNSPEC (
   2899 		    Pmode, gen_rtvec (1, loongarch_tls_symbol),
   2900 		    UNSPEC_ADDRESS_FIRST
   2901 		    + loongarch_classify_symbol (loongarch_tls_symbol));
   2902 		  set_unique_reg_note (get_last_insn (), REG_EQUAL, sum);
   2903 		}
   2904 	      else
   2905 	       emit_insn (gen_movdi_symbolic_off64 (dest, loongarch_tls_symbol,
   2906 						    gen_reg_rtx (DImode)));
   2907 	    }
   2908 	  break;
   2909 
   2910 	case CMODEL_LARGE:
   2911 	case CMODEL_TINY:
   2912 	case CMODEL_TINY_STATIC:
   2913 	default:
   2914 	  gcc_unreachable ();
   2915 	}
   2916 
   2917       insn = emit_call_insn (gen_call_value_internal (v0, dest, const0_rtx));
   2918     }
   2919 
   2920   RTL_CONST_CALL_P (insn) = 1;
   2921   use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
   2922   insn = get_insns ();
   2923 
   2924   end_sequence ();
   2925 
   2926   return insn;
   2927 }
   2928 
   2929 /* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
   2930    its address.  The return value will be both a valid address and a valid
   2931    SET_SRC (either a REG or a LO_SUM).  */
   2932 
   2933 static rtx
   2934 loongarch_legitimize_tls_address (rtx loc)
   2935 {
   2936   rtx dest, tp, tmp, tmp1, tmp2, tmp3, a0;
   2937   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
   2938   rtx_insn *insn;
   2939 
   2940   switch (model)
   2941     {
   2942     case TLS_MODEL_LOCAL_DYNAMIC:
   2943       if (!TARGET_TLS_DESC)
   2944 	{
   2945 	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
   2946 	  dest = gen_reg_rtx (Pmode);
   2947 	  insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
   2948 	  emit_libcall_block (insn, dest, tmp, loc);
   2949 	  break;
   2950 	}
   2951       /* Fall through.  */
   2952     case TLS_MODEL_GLOBAL_DYNAMIC:
   2953       if (TARGET_TLS_DESC)
   2954 	{
   2955 	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
   2956 	  dest = gen_reg_rtx (Pmode);
   2957 	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
   2958 
   2959 	  if (TARGET_CMODEL_EXTREME)
   2960 	    emit_insn (gen_got_load_tls_desc_off64 (loc, gen_reg_rtx (DImode)));
   2961 	  else
   2962 	    emit_insn (gen_got_load_tls_desc (Pmode, loc));
   2963 
   2964 	  emit_insn (gen_add3_insn (dest, a0, tp));
   2965 	}
   2966       else
   2967 	{
   2968 	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
   2969 	  dest = gen_reg_rtx (Pmode);
   2970 	  insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
   2971 	  emit_libcall_block (insn, dest, tmp, loc);
   2972 	}
   2973       break;
   2974 
   2975     case TLS_MODEL_INITIAL_EXEC:
   2976 	{
   2977 	  /* la.tls.ie; tp-relative add.  */
   2978 	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
   2979 	  tmp1 = gen_reg_rtx (Pmode);
   2980 	  tmp2 = loongarch_unspec_address (loc, SYMBOL_TLS_IE);
   2981 	  dest = gen_reg_rtx (Pmode);
   2982 	  if (loongarch_explicit_relocs_p (SYMBOL_TLS_IE))
   2983 	    {
   2984 	      if (TARGET_CMODEL_EXTREME)
   2985 		{
   2986 		  gcc_assert (la_opt_explicit_relocs
   2987 			      != EXPLICIT_RELOCS_NONE);
   2988 
   2989 		  rtx part1 = gen_reg_rtx (Pmode);
   2990 		  rtx part2 = gen_reg_rtx (Pmode);
   2991 
   2992 		  emit_insn (gen_la_pcrel64_two_parts (part1, part2,
   2993 						       tmp2));
   2994 		  emit_move_insn (tmp1,
   2995 				  gen_rtx_MEM (Pmode,
   2996 					       gen_rtx_PLUS (Pmode,
   2997 							     part1,
   2998 							     part2)));
   2999 		}
   3000 	      else
   3001 		{
   3002 		  tmp3 = gen_reg_rtx (Pmode);
   3003 		  rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
   3004 
   3005 		  high = loongarch_force_temporary (tmp3, high);
   3006 		  emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2));
   3007 		}
   3008 	    }
   3009 	  else
   3010 	    emit_insn (loongarch_load_tls (tmp1, tmp2, SYMBOL_TLS_IE));
   3011 	  emit_insn (gen_add3_insn (dest, tmp1, tp));
   3012 	}
   3013       break;
   3014 
   3015     case TLS_MODEL_LOCAL_EXEC:
   3016 	{
   3017 	  /* la.tls.le; tp-relative add.
   3018 
   3019 	     normal:
   3020 	      lu12i.w $rd, %le_hi20(sym)
   3021 	      ori $rd, $rd, %le_lo12(sym)
   3022 	      add.{w/d} $rd, $rd, $tp
   3023 	      (st.{w/d}/ld.{w/d} $rs, $rd, 0)
   3024 
   3025 	     tls le relax:
   3026 	      lu12i.w $rd, %le_hi20_r(sym)
   3027 	      add.{w/d} $rd,$rd,$tp
   3028 	      addi.{w/d} $rd,$rd,%le_lo12_r(sym)
   3029 	      (st.{w/d}/ld.{w/d} $rs, $rd, 0)
   3030 
   3031 	     extreme (When the code model is set to extreme, the TLS le Relax
   3032 	     instruction sequence is not generated):
   3033 	      lu12i.w $rd, %le_hi20(sym)
   3034 	      ori $rd, $rd, %le_lo12(sym)
   3035 	      lu32i.d $rd, %le64_lo20(sym)
   3036 	      lu52i.d $rd, $rd, %le64_hi12(sym)
   3037 	      add.d $rd, $rd, $tp
   3038 	      (st.{w/d}/ld.{w/d} $rs, $rd, 0)  */
   3039 
   3040 	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
   3041 	  tmp1 = gen_reg_rtx (Pmode);
   3042 	  tmp2 = loongarch_unspec_address (loc, SYMBOL_TLS_LE);
   3043 	  dest = gen_reg_rtx (Pmode);
   3044 
   3045 	  if (loongarch_explicit_relocs_p (SYMBOL_TLS_LE))
   3046 	    {
   3047 	      tmp3 = gen_reg_rtx (Pmode);
   3048 	      rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
   3049 	      high = loongarch_force_temporary (tmp3, high);
   3050 
   3051 	      /* The assembler does not implement tls le relax support when the
   3052 		 code model is extreme, so when the code model is extreme, the
   3053 		 old symbol address acquisition method is still used.  */
   3054 	      if (HAVE_AS_TLS_LE_RELAXATION && !TARGET_CMODEL_EXTREME)
   3055 		{
   3056 		  emit_insn (gen_add_tls_le_relax (Pmode, dest, high,
   3057 						   tp, loc));
   3058 		  loongarch_emit_move (dest,
   3059 				       gen_rtx_LO_SUM (Pmode, dest, tmp2));
   3060 		  return dest;
   3061 		}
   3062 	      else
   3063 		emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2));
   3064 
   3065 	      if (TARGET_CMODEL_EXTREME)
   3066 		{
   3067 		  emit_insn (gen_lui_h_lo20 (tmp1, tmp1, tmp2));
   3068 		  emit_insn (gen_lui_h_hi12 (tmp1, tmp1, tmp2));
   3069 		}
   3070 	    }
   3071 	  else
   3072 	    emit_insn (loongarch_load_tls (tmp1, tmp2, SYMBOL_TLS_LE));
   3073 	  emit_insn (gen_add3_insn (dest, tmp1, tp));
   3074 	}
   3075       break;
   3076 
   3077     default:
   3078       gcc_unreachable ();
   3079     }
   3080   return dest;
   3081 }
   3082 
   3083 rtx
   3084 loongarch_legitimize_call_address (rtx addr)
   3085 {
   3086   if (!call_insn_operand (addr, VOIDmode))
   3087     {
   3088       rtx reg = gen_reg_rtx (Pmode);
   3089       loongarch_emit_move (reg, addr);
   3090       return reg;
   3091     }
   3092 
   3093   enum loongarch_symbol_type symbol_type = loongarch_classify_symbol (addr);
   3094 
   3095   /* If add the compilation option '-cmodel=medium', and the assembler does
   3096      not support call36.  The following sequence of instructions will be
   3097      used for the function call:
   3098 	pcalau12i $rd, %pc_hi20(sym)
   3099 	jr $rd, %pc_lo12(sym)
   3100   */
   3101 
   3102   if (TARGET_CMODEL_MEDIUM
   3103       && !HAVE_AS_SUPPORT_CALL36
   3104       && (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE)
   3105       && (SYMBOL_REF_P (addr) || LABEL_REF_P (addr))
   3106       && (symbol_type == SYMBOL_PCREL
   3107 	  || (symbol_type == SYMBOL_GOT_DISP && flag_plt)))
   3108     {
   3109       rtx reg = gen_reg_rtx (Pmode);
   3110       emit_insn (gen_pcalau12i (Pmode, reg, addr));
   3111       return gen_rtx_LO_SUM (Pmode, reg, addr);
   3112     }
   3113 
   3114   return addr;
   3115 }
   3116 
   3117 /* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR
   3118    and *OFFSET_PTR.  Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise.  */
   3119 
   3120 static void
   3121 loongarch_split_plus (rtx x, rtx *base_ptr, HOST_WIDE_INT *offset_ptr)
   3122 {
   3123   if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
   3124     {
   3125       *base_ptr = XEXP (x, 0);
   3126       *offset_ptr = INTVAL (XEXP (x, 1));
   3127     }
   3128   else
   3129     {
   3130       *base_ptr = x;
   3131       *offset_ptr = 0;
   3132     }
   3133 }
   3134 
   3135 /* If X is not a valid address for mode MODE, force it into a register.  */
   3136 
   3137 static rtx
   3138 loongarch_force_address (rtx x, machine_mode mode)
   3139 {
   3140   if (!loongarch_legitimate_address_p (mode, x, false))
   3141     x = force_reg (Pmode, x);
   3142   return x;
   3143 }
   3144 
   3145 bool
   3146 loongarch_symbol_extreme_p (enum loongarch_symbol_type type)
   3147 {
   3148   switch (type)
   3149     {
   3150       case SYMBOL_PCREL:
   3151 	return false;
   3152       case SYMBOL_PCREL64:
   3153 	return true;
   3154       default:
   3155 	return TARGET_CMODEL_EXTREME;
   3156     }
   3157 }
   3158 
   3159 /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise
   3160    it appears in a MEM of that mode.  Return true if ADDR is a legitimate
   3161    constant in that context and can be split into high and low parts.
   3162    If so, and if LOW_OUT is nonnull, emit the high part and store the
   3163    low part in *LOW_OUT.  Leave *LOW_OUT unchanged otherwise.
   3164 
   3165    Return false if build with '-mexplicit-relocs=none'.
   3166 
   3167    TEMP is as for loongarch_force_temporary and is used to load the high
   3168    part into a register.
   3169 
   3170    When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be
   3171    a legitimize SET_SRC for an .md pattern, otherwise the low part
   3172    is guaranteed to be a legitimate address for mode MODE.  */
   3173 
   3174 bool
   3175 loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
   3176 {
   3177   enum loongarch_symbol_type symbol_type;
   3178 
   3179   if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE)
   3180       || !loongarch_symbolic_constant_p (addr, &symbol_type)
   3181       || !loongarch_explicit_relocs_p (symbol_type)
   3182       || loongarch_symbol_insns (symbol_type, mode) == 0
   3183       || !loongarch_split_symbol_type (symbol_type))
   3184     return false;
   3185 
   3186   rtx high;
   3187 
   3188   if (temp == NULL)
   3189     temp = gen_reg_rtx (Pmode);
   3190 
   3191   if (loongarch_symbol_extreme_p (symbol_type) && can_create_pseudo_p ())
   3192     {
   3193       gcc_assert (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE);
   3194 
   3195       high = gen_reg_rtx (Pmode);
   3196       emit_insn (gen_la_pcrel64_two_parts (high, temp, addr));
   3197     }
   3198   else
   3199     {
   3200       /* Get the 12-31 bits of the address.  */
   3201       high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
   3202       high = loongarch_force_temporary (temp, high);
   3203     }
   3204 
   3205   if (low_out)
   3206     switch (symbol_type)
   3207       {
   3208       case SYMBOL_PCREL64:
   3209 	if (can_create_pseudo_p ())
   3210 	  {
   3211 	    *low_out = gen_rtx_PLUS (Pmode, high, temp);
   3212 	    break;
   3213 	  }
   3214 	/* fall through */
   3215       case SYMBOL_PCREL:
   3216 	*low_out = gen_rtx_LO_SUM (Pmode, high, addr);
   3217 	break;
   3218 
   3219       case SYMBOL_GOT_DISP:
   3220 	/* SYMBOL_GOT_DISP symbols are loaded from the GOT.  */
   3221 	{
   3222 	  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
   3223 	    *low_out = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, high,
   3224 							 temp));
   3225 	  else
   3226 	    {
   3227 	      rtx low = gen_rtx_LO_SUM (Pmode, high, addr);
   3228 	      rtx mem = gen_rtx_MEM (Pmode, low);
   3229 	      *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem),
   3230 					 UNSPEC_LOAD_FROM_GOT);
   3231 
   3232 	      /* Nonzero in a mem, if the memory is statically allocated and
   3233 		 read-only.  A common example of the later is a shared librarys
   3234 		 global offset table.  */
   3235 	      MEM_READONLY_P (mem) = 1;
   3236 	    }
   3237 
   3238 	  break;
   3239 	}
   3240 
   3241       default:
   3242 	gcc_unreachable ();
   3243       }
   3244 
   3245   return true;
   3246 }
   3247 
   3248 /* Helper loongarch_legitimize_address.  Given X, return true if it
   3249    is a left shift by 1, 2 or 3 positions or a multiply by 2, 4 or 8.
   3250 
   3251    This respectively represent canonical shift-add rtxs or scaled
   3252    memory addresses.  */
   3253 static bool
   3254 mem_shadd_or_shadd_rtx_p (rtx x)
   3255 {
   3256   return ((GET_CODE (x) == ASHIFT
   3257 	   || GET_CODE (x) == MULT)
   3258 	  && CONST_INT_P (XEXP (x, 1))
   3259 	  && ((GET_CODE (x) == ASHIFT && IN_RANGE (INTVAL (XEXP (x, 1)), 1, 3))
   3260 	      || (GET_CODE (x) == MULT
   3261 		  && IN_RANGE (exact_log2 (INTVAL (XEXP (x, 1))), 1, 3))));
   3262 }
   3263 
   3264 /* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
   3265    be legitimized in a way that the generic machinery might not expect,
   3266    return a new address, otherwise return NULL.  MODE is the mode of
   3267    the memory being accessed.  */
   3268 
   3269 static rtx
   3270 loongarch_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   3271 			      machine_mode mode)
   3272 {
   3273   rtx base, addr;
   3274   HOST_WIDE_INT offset;
   3275 
   3276   if (loongarch_tls_symbol_p (x))
   3277     return loongarch_legitimize_tls_address (x);
   3278 
   3279   /* See if the address can split into a high part and a LO_SUM.  */
   3280   if (loongarch_split_symbol (NULL, x, mode, &addr))
   3281     return loongarch_force_address (addr, mode);
   3282 
   3283   /* Handle BASE + OFFSET using loongarch_add_offset.  */
   3284   loongarch_split_plus (x, &base, &offset);
   3285   if (offset != 0)
   3286     {
   3287       /* Handle (plus (plus (mult (a) (mem_shadd_constant)) (fp)) (C)) case.  */
   3288       if (GET_CODE (base) == PLUS && mem_shadd_or_shadd_rtx_p (XEXP (base, 0))
   3289 	  && IMM12_OPERAND (offset))
   3290 	{
   3291 	  rtx index = XEXP (base, 0);
   3292 	  rtx fp = XEXP (base, 1);
   3293 
   3294 	  if (REG_P (fp) && REGNO (fp) == VIRTUAL_STACK_VARS_REGNUM)
   3295 	    {
   3296 	      /* If we were given a MULT, we must fix the constant
   3297 		 as we're going to create the ASHIFT form.  */
   3298 	      int shift_val = INTVAL (XEXP (index, 1));
   3299 	      if (GET_CODE (index) == MULT)
   3300 		shift_val = exact_log2 (shift_val);
   3301 
   3302 	      rtx reg1 = gen_reg_rtx (Pmode);
   3303 	      rtx reg3 = gen_reg_rtx (Pmode);
   3304 	      loongarch_emit_binary (PLUS, reg1, fp, GEN_INT (offset));
   3305 	      loongarch_emit_binary (PLUS, reg3,
   3306 				     gen_rtx_ASHIFT (Pmode, XEXP (index, 0),
   3307 						     GEN_INT (shift_val)),
   3308 				     reg1);
   3309 
   3310 	      return reg3;
   3311 	    }
   3312 	}
   3313 
   3314       if (!loongarch_valid_base_register_p (base, mode, false))
   3315 	base = copy_to_mode_reg (Pmode, base);
   3316       addr = loongarch_add_offset (NULL, base, offset);
   3317       return loongarch_force_address (addr, mode);
   3318     }
   3319 
   3320   return x;
   3321 }
   3322 
   3323 /* Load VALUE into DEST.  TEMP is as for loongarch_force_temporary.  */
   3324 
   3325 void
   3326 loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value)
   3327 {
   3328   struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS];
   3329   machine_mode mode;
   3330   unsigned int i, num_ops;
   3331   rtx x;
   3332 
   3333   mode = GET_MODE (dest);
   3334   num_ops = loongarch_build_integer (codes, value);
   3335 
   3336   /* Apply each binary operation to X.  Invariant: X is a legitimate
   3337      source operand for a SET pattern.  */
   3338   x = GEN_INT (codes[0].value);
   3339   for (i = 1; i < num_ops; i++)
   3340     {
   3341       if (!can_create_pseudo_p ())
   3342 	{
   3343 	  emit_insn (gen_rtx_SET (temp, x));
   3344 	  x = temp;
   3345 	}
   3346       else
   3347 	x = force_reg (mode, x);
   3348 
   3349       set_unique_reg_note (get_last_insn (), REG_EQUAL,
   3350 			   GEN_INT (codes[i-1].curr_value));
   3351 
   3352       switch (codes[i].method)
   3353 	{
   3354 	case METHOD_NORMAL:
   3355 	  x = gen_rtx_fmt_ee (codes[i].code, mode, x,
   3356 			      GEN_INT (codes[i].value));
   3357 	  break;
   3358 	case METHOD_LU32I:
   3359 	  gcc_assert (mode == DImode);
   3360 	  x = gen_rtx_IOR (DImode,
   3361 			   gen_rtx_ZERO_EXTEND (DImode,
   3362 						gen_rtx_SUBREG (SImode, x, 0)),
   3363 			   GEN_INT (codes[i].value));
   3364 	  break;
   3365 	case METHOD_LU52I:
   3366 	  gcc_assert (mode == DImode);
   3367 	  x = gen_rtx_IOR (DImode,
   3368 			   gen_rtx_AND (DImode, x, GEN_INT (0xfffffffffffff)),
   3369 			   GEN_INT (codes[i].value));
   3370 	  break;
   3371 	case METHOD_MIRROR:
   3372 	  gcc_assert (mode == DImode);
   3373 	  emit_insn (gen_insvdi (x, GEN_INT (32), GEN_INT (32), x));
   3374 	  break;
   3375 	default:
   3376 	  gcc_unreachable ();
   3377 	}
   3378     }
   3379 
   3380   emit_insn (gen_rtx_SET (dest, x));
   3381 }
   3382 
   3383 /* Subroutine of loongarch_legitimize_move.  Move constant SRC into register
   3384    DEST given that SRC satisfies immediate_operand but doesn't satisfy
   3385    move_operand.  */
   3386 
   3387 static void
   3388 loongarch_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
   3389 {
   3390   rtx base, offset;
   3391 
   3392   /* Split moves of big integers into smaller pieces.  */
   3393   if (splittable_const_int_operand (src, mode))
   3394     {
   3395       loongarch_move_integer (dest, dest, INTVAL (src));
   3396       return;
   3397     }
   3398 
   3399   /* Split moves of symbolic constants into high and low.  */
   3400   if (loongarch_split_symbol (dest, src, MAX_MACHINE_MODE, &src))
   3401     {
   3402       loongarch_emit_set (dest, src);
   3403       return;
   3404     }
   3405 
   3406   /* Generate the appropriate access sequences for TLS symbols.  */
   3407   if (loongarch_tls_symbol_p (src))
   3408     {
   3409       loongarch_emit_move (dest, loongarch_legitimize_tls_address (src));
   3410       return;
   3411     }
   3412 
   3413   /* If we have (const (plus symbol offset)), and that expression cannot
   3414      be forced into memory, load the symbol first and add in the offset.
   3415      prefer to do this even if the constant _can_ be forced into memory,
   3416      as it usually produces better code.  */
   3417   split_const (src, &base, &offset);
   3418   if (offset != const0_rtx
   3419       && (targetm.cannot_force_const_mem (mode, src)
   3420 	  || (can_create_pseudo_p ())))
   3421     {
   3422       base = loongarch_force_temporary (dest, base);
   3423       loongarch_emit_move (dest,
   3424 			   loongarch_add_offset (NULL, base, INTVAL (offset)));
   3425       return;
   3426     }
   3427 
   3428   src = force_const_mem (mode, src);
   3429 
   3430   loongarch_emit_move (dest, src);
   3431 }
   3432 
   3433 /* If (set DEST SRC) is not a valid move instruction, emit an equivalent
   3434    sequence that is valid.  */
   3435 
   3436 bool
   3437 loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src)
   3438 {
   3439   if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
   3440     {
   3441       loongarch_emit_move (dest, force_reg (mode, src));
   3442       return true;
   3443     }
   3444 
   3445   /* Both src and dest are non-registers;  one special case is supported where
   3446      the source is (const_int 0) and the store can source the zero register.
   3447      LSX and LASX are never able to source the zero register directly in
   3448      memory operations.  */
   3449   if (!register_operand (dest, mode) && !register_operand (src, mode)
   3450       && (!const_0_operand (src, mode)
   3451 	  || LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode)))
   3452     {
   3453       loongarch_emit_move (dest, force_reg (mode, src));
   3454       return true;
   3455     }
   3456 
   3457   /* We need to deal with constants that would be legitimate
   3458      immediate_operands but aren't legitimate move_operands.  */
   3459   if (CONSTANT_P (src) && !move_operand (src, mode))
   3460     {
   3461       loongarch_legitimize_const_move (mode, dest, src);
   3462       set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
   3463       return true;
   3464     }
   3465 
   3466   /* Obtain the address of the symbol through the macro instruction
   3467      of two registers.  */
   3468   enum loongarch_symbol_type symbol_type;
   3469   if (TARGET_64BIT && register_operand (dest, mode)
   3470       && loongarch_symbolic_constant_p (src, &symbol_type)
   3471       && loongarch_symbol_extreme_p (symbol_type))
   3472     {
   3473       gcc_assert (can_create_pseudo_p ());
   3474       rtx tmp_reg = gen_reg_rtx (DImode);
   3475       emit_insn (gen_movdi_symbolic_off64 (dest, src, tmp_reg));
   3476       set_unique_reg_note (get_last_insn (), REG_UNUSED, tmp_reg);
   3477       set_unique_reg_note (get_last_insn (), REG_EQUAL, src);
   3478       return true;
   3479     }
   3480 
   3481   return false;
   3482 }
   3483 
   3484 /* Return true if OP refers to small data symbols directly.  */
   3485 
   3486 static int
   3487 loongarch_small_data_pattern_1 (rtx x)
   3488 {
   3489   subrtx_var_iterator::array_type array;
   3490   FOR_EACH_SUBRTX_VAR (iter, array, x, ALL)
   3491     {
   3492       rtx x = *iter;
   3493 
   3494       /* We make no particular guarantee about which symbolic constants are
   3495 	 acceptable as asm operands versus which must be forced into a GPR.  */
   3496       if (GET_CODE (x) == ASM_OPERANDS)
   3497 	iter.skip_subrtxes ();
   3498       else if (MEM_P (x))
   3499 	{
   3500 	  if (loongarch_small_data_pattern_1 (XEXP (x, 0)))
   3501 	    return true;
   3502 	  iter.skip_subrtxes ();
   3503 	}
   3504     }
   3505   return false;
   3506 }
   3507 
   3508 /* Return true if OP refers to small data symbols directly.  */
   3509 
   3510 bool
   3511 loongarch_small_data_pattern_p (rtx op)
   3512 {
   3513   return loongarch_small_data_pattern_1 (op);
   3514 }
   3515 
   3516 /* Rewrite *LOC so that it refers to small data using explicit
   3517    relocations.  */
   3518 
   3519 static void
   3520 loongarch_rewrite_small_data_1 (rtx *loc)
   3521 {
   3522   subrtx_ptr_iterator::array_type array;
   3523   FOR_EACH_SUBRTX_PTR (iter, array, loc, ALL)
   3524     {
   3525       rtx *loc = *iter;
   3526       if (MEM_P (*loc))
   3527 	{
   3528 	  loongarch_rewrite_small_data_1 (&XEXP (*loc, 0));
   3529 	  iter.skip_subrtxes ();
   3530 	}
   3531     }
   3532 }
   3533 
   3534 /* Rewrite instruction pattern PATTERN so that it refers to small data
   3535    using explicit relocations.  */
   3536 
   3537 rtx
   3538 loongarch_rewrite_small_data (rtx pattern)
   3539 {
   3540   pattern = copy_insn (pattern);
   3541   loongarch_rewrite_small_data_1 (&pattern);
   3542   return pattern;
   3543 }
   3544 
   3545 /* The cost of loading values from the constant pool.  It should be
   3546    larger than the cost of any constant we want to synthesize inline.  */
   3547 #define CONSTANT_POOL_COST COSTS_N_INSNS (8)
   3548 
   3549 /* Return true if there is a instruction that implements CODE
   3550    and if that instruction accepts X as an immediate operand.  */
   3551 
   3552 static int
   3553 loongarch_immediate_operand_p (int code, HOST_WIDE_INT x)
   3554 {
   3555   switch (code)
   3556     {
   3557     case ASHIFT:
   3558     case ASHIFTRT:
   3559     case LSHIFTRT:
   3560       /* All shift counts are truncated to a valid constant.  */
   3561       return true;
   3562 
   3563     case ROTATE:
   3564     case ROTATERT:
   3565       return true;
   3566 
   3567     case AND:
   3568     case IOR:
   3569     case XOR:
   3570       /* These instructions take 12-bit unsigned immediates.  */
   3571       return IMM12_OPERAND_UNSIGNED (x);
   3572 
   3573     case PLUS:
   3574     case LT:
   3575     case LTU:
   3576       /* These instructions take 12-bit signed immediates.  */
   3577       return IMM12_OPERAND (x);
   3578 
   3579     case EQ:
   3580     case NE:
   3581     case GT:
   3582     case GTU:
   3583       /* The "immediate" forms of these instructions are really
   3584 	 implemented as comparisons with register 0.  */
   3585       return x == 0;
   3586 
   3587     case GE:
   3588     case GEU:
   3589       /* Likewise, meaning that the only valid immediate operand is 1.  */
   3590       return x == 1;
   3591 
   3592     case LE:
   3593       /* We add 1 to the immediate and use SLT.  */
   3594       return IMM12_OPERAND (x + 1);
   3595 
   3596     case LEU:
   3597       /* Likewise SLTU, but reject the always-true case.  */
   3598       return IMM12_OPERAND (x + 1) && x + 1 != 0;
   3599 
   3600     case SIGN_EXTRACT:
   3601     case ZERO_EXTRACT:
   3602       /* The bit position and size are immediate operands.  */
   3603       return 1;
   3604 
   3605     default:
   3606       /* By default assume that $0 can be used for 0.  */
   3607       return x == 0;
   3608     }
   3609 }
   3610 
   3611 /* Return the cost of binary operation X, given that the instruction
   3612    sequence for a word-sized or smaller operation has cost SINGLE_COST
   3613    and that the sequence of a double-word operation has cost DOUBLE_COST.
   3614    If SPEED is true, optimize for speed otherwise optimize for size.  */
   3615 
   3616 static int
   3617 loongarch_binary_cost (rtx x, int single_cost, int double_cost, bool speed)
   3618 {
   3619   int cost;
   3620 
   3621   if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2)
   3622     cost = double_cost;
   3623   else
   3624     cost = single_cost;
   3625   return (cost
   3626 	  + set_src_cost (XEXP (x, 0), GET_MODE (x), speed)
   3627 	  + rtx_cost (XEXP (x, 1), GET_MODE (x), GET_CODE (x), 1, speed));
   3628 }
   3629 
   3630 /* Return the cost of floating-point multiplications of mode MODE.  */
   3631 
   3632 static int
   3633 loongarch_fp_mult_cost (machine_mode mode)
   3634 {
   3635   return mode == DFmode ? loongarch_cost->fp_mult_df
   3636 			: loongarch_cost->fp_mult_sf;
   3637 }
   3638 
   3639 /* Return the cost of floating-point divisions of mode MODE.  */
   3640 
   3641 static int
   3642 loongarch_fp_div_cost (machine_mode mode)
   3643 {
   3644   return mode == DFmode ? loongarch_cost->fp_div_df
   3645 			: loongarch_cost->fp_div_sf;
   3646 }
   3647 
   3648 /* Return the cost of sign-extending OP to mode MODE, not including the
   3649    cost of OP itself.  */
   3650 
   3651 static int
   3652 loongarch_sign_extend_cost (rtx op)
   3653 {
   3654   if (MEM_P (op))
   3655     /* Extended loads are as cheap as unextended ones.  */
   3656     return 0;
   3657 
   3658   return COSTS_N_INSNS (1);
   3659 }
   3660 
   3661 /* Return the cost of zero-extending OP to mode MODE, not including the
   3662    cost of OP itself.  */
   3663 
   3664 static int
   3665 loongarch_zero_extend_cost (rtx op)
   3666 {
   3667   if (MEM_P (op))
   3668     /* Extended loads are as cheap as unextended ones.  */
   3669     return 0;
   3670 
   3671   /* We can use ANDI.  */
   3672   return COSTS_N_INSNS (1);
   3673 }
   3674 
   3675 /* Return the cost of moving between two registers of mode MODE,
   3676    assuming that the move will be in pieces of at most UNITS bytes.  */
   3677 
   3678 static int
   3679 loongarch_set_reg_reg_piece_cost (machine_mode mode, unsigned int units)
   3680 {
   3681   return COSTS_N_INSNS ((GET_MODE_SIZE (mode) + units - 1) / units);
   3682 }
   3683 
   3684 /* Return the cost of moving between two registers of mode MODE.  */
   3685 
   3686 static int
   3687 loongarch_set_reg_reg_cost (machine_mode mode)
   3688 {
   3689   switch (GET_MODE_CLASS (mode))
   3690     {
   3691     case MODE_CC:
   3692       return loongarch_set_reg_reg_piece_cost (mode, GET_MODE_SIZE (CCmode));
   3693 
   3694     case MODE_FLOAT:
   3695     case MODE_COMPLEX_FLOAT:
   3696     case MODE_VECTOR_FLOAT:
   3697       if (TARGET_HARD_FLOAT)
   3698 	return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_HWFPVALUE);
   3699       /* Fall through.  */
   3700 
   3701     default:
   3702       return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_WORD);
   3703     }
   3704 }
   3705 
   3706 /* Implement TARGET_RTX_COSTS.  */
   3707 
   3708 static bool
   3709 loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code,
   3710 		     int opno ATTRIBUTE_UNUSED, int *total, bool speed)
   3711 {
   3712   int code = GET_CODE (x);
   3713   bool float_mode_p = FLOAT_MODE_P (mode);
   3714   int cost;
   3715   rtx addr;
   3716 
   3717   if (outer_code == COMPARE)
   3718     {
   3719       gcc_assert (CONSTANT_P (x));
   3720       *total = 0;
   3721       return true;
   3722     }
   3723 
   3724   switch (code)
   3725     {
   3726     case CONST_INT:
   3727       if (TARGET_64BIT && outer_code == AND && UINTVAL (x) == 0xffffffff)
   3728 	{
   3729 	  *total = 0;
   3730 	  return true;
   3731 	}
   3732 
   3733       /* When not optimizing for size, we care more about the cost
   3734 	 of hot code, and hot code is often in a loop.  If a constant
   3735 	 operand needs to be forced into a register, we will often be
   3736 	 able to hoist the constant load out of the loop, so the load
   3737 	 should not contribute to the cost.  */
   3738       if (speed || loongarch_immediate_operand_p (outer_code, INTVAL (x)))
   3739 	{
   3740 	  *total = 0;
   3741 	  return true;
   3742 	}
   3743       /* Fall through.  */
   3744 
   3745     case CONST:
   3746     case SYMBOL_REF:
   3747     case LABEL_REF:
   3748     case CONST_DOUBLE:
   3749       cost = loongarch_const_insns (x);
   3750       if (cost > 0)
   3751 	{
   3752 	  if (cost == 1 && outer_code == SET
   3753 	      && !(float_mode_p && TARGET_HARD_FLOAT))
   3754 	    cost = 0;
   3755 	  else if ((outer_code == SET || GET_MODE (x) == VOIDmode))
   3756 	    cost = 1;
   3757 	  *total = COSTS_N_INSNS (cost);
   3758 	  return true;
   3759 	}
   3760       /* The value will need to be fetched from the constant pool.  */
   3761       *total = CONSTANT_POOL_COST;
   3762       return true;
   3763 
   3764     case MEM:
   3765       /* If the address is legitimate, return the number of
   3766 	 instructions it needs.  */
   3767       addr = XEXP (x, 0);
   3768       /* Check for a scaled indexed address.  */
   3769       if (loongarch_index_address_p (addr, mode))
   3770 	{
   3771 	  *total = COSTS_N_INSNS (2);
   3772 	  return true;
   3773 	}
   3774       cost = loongarch_address_insns (addr, mode, true);
   3775       if (cost > 0)
   3776 	{
   3777 	  *total = COSTS_N_INSNS (cost + 1);
   3778 	  return true;
   3779 	}
   3780       /* Otherwise use the default handling.  */
   3781       return false;
   3782 
   3783     case FFS:
   3784       *total = COSTS_N_INSNS (6);
   3785       return false;
   3786 
   3787     case NOT:
   3788       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
   3789       return false;
   3790 
   3791     case AND:
   3792       /* Check for a *clear_upper32 pattern and treat it like a zero
   3793 	 extension.  See the pattern's comment for details.  */
   3794       if (TARGET_64BIT && mode == DImode && CONST_INT_P (XEXP (x, 1))
   3795 	  && UINTVAL (XEXP (x, 1)) == 0xffffffff)
   3796 	{
   3797 	  *total = (loongarch_zero_extend_cost (XEXP (x, 0))
   3798 		    + set_src_cost (XEXP (x, 0), mode, speed));
   3799 	  return true;
   3800 	}
   3801       /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in
   3802 	 a single instruction.  */
   3803       if (GET_CODE (XEXP (x, 0)) == NOT && GET_CODE (XEXP (x, 1)) == NOT)
   3804 	{
   3805 	  cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
   3806 	  *total = (COSTS_N_INSNS (cost)
   3807 		    + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
   3808 		    + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed));
   3809 	  return true;
   3810 	}
   3811 
   3812       /* Fall through.  */
   3813 
   3814     case IOR:
   3815     case XOR:
   3816       /* Double-word operations use two single-word operations.  */
   3817       *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (2),
   3818 				      speed);
   3819       return true;
   3820 
   3821     case ASHIFT:
   3822     case ASHIFTRT:
   3823     case LSHIFTRT:
   3824     case ROTATE:
   3825     case ROTATERT:
   3826       if (CONSTANT_P (XEXP (x, 1)))
   3827 	*total = loongarch_binary_cost (x, COSTS_N_INSNS (1),
   3828 					COSTS_N_INSNS (4), speed);
   3829       else
   3830 	*total = loongarch_binary_cost (x, COSTS_N_INSNS (1),
   3831 					COSTS_N_INSNS (12), speed);
   3832       return true;
   3833 
   3834     case ABS:
   3835       if (float_mode_p)
   3836 	*total = loongarch_cost->fp_add;
   3837       else
   3838 	*total = COSTS_N_INSNS (4);
   3839       return false;
   3840 
   3841     case LT:
   3842     case LTU:
   3843     case LE:
   3844     case LEU:
   3845     case GT:
   3846     case GTU:
   3847     case GE:
   3848     case GEU:
   3849     case EQ:
   3850     case NE:
   3851     case UNORDERED:
   3852     case LTGT:
   3853     case UNGE:
   3854     case UNGT:
   3855     case UNLE:
   3856     case UNLT:
   3857       /* Branch comparisons have VOIDmode, so use the first operand's
   3858 	 mode instead.  */
   3859       mode = GET_MODE (XEXP (x, 0));
   3860       if (FLOAT_MODE_P (mode))
   3861 	{
   3862 	  *total = loongarch_cost->fp_add;
   3863 	  return false;
   3864 	}
   3865       *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
   3866 				      speed);
   3867       return true;
   3868 
   3869     case MINUS:
   3870     case PLUS:
   3871       if (float_mode_p)
   3872 	{
   3873 	  *total = loongarch_cost->fp_add;
   3874 	  return false;
   3875 	}
   3876 
   3877       /* If it's an add + mult (which is equivalent to shift left) and
   3878 	 it's immediate operand satisfies const_immalsl_operand predicate.  */
   3879       if ((mode == SImode || (TARGET_64BIT && mode == DImode))
   3880 	  && GET_CODE (XEXP (x, 0)) == MULT)
   3881 	{
   3882 	  rtx op2 = XEXP (XEXP (x, 0), 1);
   3883 	  if (const_immalsl_operand (op2, mode))
   3884 	    {
   3885 	      *total = (COSTS_N_INSNS (1)
   3886 			+ set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
   3887 			+ set_src_cost (XEXP (x, 1), mode, speed));
   3888 	      return true;
   3889 	    }
   3890 	}
   3891 
   3892       /* Double-word operations require three single-word operations and
   3893 	 an SLTU.  */
   3894       *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
   3895 				      speed);
   3896       return true;
   3897 
   3898     case NEG:
   3899       if (float_mode_p)
   3900 	*total = loongarch_cost->fp_add;
   3901       else
   3902 	*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
   3903       return false;
   3904 
   3905     case FMA:
   3906       *total = loongarch_fp_mult_cost (mode);
   3907       return false;
   3908 
   3909     case MULT:
   3910       if (float_mode_p)
   3911 	*total = loongarch_fp_mult_cost (mode);
   3912       else if (mode == DImode && !TARGET_64BIT)
   3913 	*total = (speed
   3914 		  ? loongarch_cost->int_mult_si * 3 + 6
   3915 		  : COSTS_N_INSNS (7));
   3916       else if (mode == DImode)
   3917 	*total = loongarch_cost->int_mult_di;
   3918       else
   3919 	*total = loongarch_cost->int_mult_si;
   3920       return false;
   3921 
   3922     case DIV:
   3923       /* Check for a reciprocal.  */
   3924       if (float_mode_p
   3925 	  && flag_unsafe_math_optimizations
   3926 	  && XEXP (x, 0) == CONST1_RTX (mode))
   3927 	{
   3928 	  if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT)
   3929 	    /* An rsqrt<mode>a or rsqrt<mode>b pattern.  Count the
   3930 	       division as being free.  */
   3931 	    *total = set_src_cost (XEXP (x, 1), mode, speed);
   3932 	  else
   3933 	    *total = (loongarch_fp_div_cost (mode)
   3934 		      + set_src_cost (XEXP (x, 1), mode, speed));
   3935 	  return true;
   3936 	}
   3937       /* Fall through.  */
   3938 
   3939     case SQRT:
   3940     case MOD:
   3941       if (float_mode_p)
   3942 	{
   3943 	  *total = loongarch_fp_div_cost (mode);
   3944 	  return false;
   3945 	}
   3946       /* Fall through.  */
   3947 
   3948     case UDIV:
   3949     case UMOD:
   3950       if (mode == DImode)
   3951 	*total = loongarch_cost->int_div_di;
   3952       else
   3953 	{
   3954 	  *total = loongarch_cost->int_div_si;
   3955 	  if (TARGET_64BIT && !ISA_HAS_DIV32)
   3956 	    *total += COSTS_N_INSNS (2);
   3957 	}
   3958 
   3959       if (TARGET_CHECK_ZERO_DIV)
   3960 	*total += COSTS_N_INSNS (2);
   3961 
   3962       return false;
   3963 
   3964     case SIGN_EXTEND:
   3965       *total = loongarch_sign_extend_cost (XEXP (x, 0));
   3966       return false;
   3967 
   3968     case ZERO_EXTEND:
   3969       *total = loongarch_zero_extend_cost (XEXP (x, 0));
   3970       return false;
   3971     case TRUNCATE:
   3972       /* Costings for highpart multiplies.  Matching patterns of the form:
   3973 
   3974 	 (lshiftrt:DI (mult:DI (sign_extend:DI (...)
   3975 			       (sign_extend:DI (...))
   3976 		      (const_int 32)
   3977       */
   3978       if ((GET_CODE (XEXP (x, 0)) == ASHIFTRT
   3979 	   || GET_CODE (XEXP (x, 0)) == LSHIFTRT)
   3980 	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
   3981 	  && ((INTVAL (XEXP (XEXP (x, 0), 1)) == 32
   3982 	       && GET_MODE (XEXP (x, 0)) == DImode)
   3983 	      || (TARGET_64BIT
   3984 		  && INTVAL (XEXP (XEXP (x, 0), 1)) == 64
   3985 		  && GET_MODE (XEXP (x, 0)) == TImode))
   3986 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
   3987 	  && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND
   3988 	       && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND)
   3989 	      || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
   3990 		  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1))
   3991 		      == ZERO_EXTEND))))
   3992 	{
   3993 	  if (mode == DImode)
   3994 	    *total = loongarch_cost->int_mult_di;
   3995 	  else
   3996 	    *total = loongarch_cost->int_mult_si;
   3997 
   3998 	  /* Sign extension is free, zero extension costs for DImode when
   3999 	     on a 64bit core / when DMUL is present.  */
   4000 	  for (int i = 0; i < 2; ++i)
   4001 	    {
   4002 	      rtx op = XEXP (XEXP (XEXP (x, 0), 0), i);
   4003 	      if (TARGET_64BIT
   4004 		  && GET_CODE (op) == ZERO_EXTEND
   4005 		  && GET_MODE (op) == DImode)
   4006 		*total += rtx_cost (op, DImode, MULT, i, speed);
   4007 	      else
   4008 		*total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op), 0,
   4009 				    speed);
   4010 	    }
   4011 
   4012 	  return true;
   4013 	}
   4014       return false;
   4015 
   4016     case FLOAT:
   4017     case UNSIGNED_FLOAT:
   4018     case FIX:
   4019     case FLOAT_EXTEND:
   4020     case FLOAT_TRUNCATE:
   4021       *total = loongarch_cost->fp_add;
   4022       return false;
   4023 
   4024     case SET:
   4025       if (register_operand (SET_DEST (x), VOIDmode)
   4026 	  && reg_or_0_operand (SET_SRC (x), VOIDmode))
   4027 	{
   4028 	  *total = loongarch_set_reg_reg_cost (GET_MODE (SET_DEST (x)));
   4029 	  return true;
   4030 	}
   4031       return false;
   4032 
   4033     default:
   4034       return false;
   4035     }
   4036 }
   4037 
   4038 /* Implement targetm.vectorize.builtin_vectorization_cost.  */
   4039 
   4040 static int
   4041 loongarch_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
   4042 				      tree vectype,
   4043 				      int misalign ATTRIBUTE_UNUSED)
   4044 {
   4045   unsigned elements;
   4046   machine_mode mode = vectype != NULL ? TYPE_MODE (vectype) : DImode;
   4047 
   4048   switch (type_of_cost)
   4049     {
   4050       case scalar_stmt:
   4051       case scalar_load:
   4052       case vector_stmt:
   4053       case vec_to_scalar:
   4054       case scalar_to_vec:
   4055       case scalar_store:
   4056 	return 1;
   4057 
   4058       case vec_promote_demote:
   4059       case vec_perm:
   4060 	return LASX_SUPPORTED_MODE_P (mode)
   4061 	  && !LSX_SUPPORTED_MODE_P (mode) ? 2 : 1;
   4062 
   4063       case vector_load:
   4064       case vector_store:
   4065       case unaligned_load:
   4066       case unaligned_store:
   4067 	return 2;
   4068 
   4069       case cond_branch_taken:
   4070 	return 4;
   4071 
   4072       case cond_branch_not_taken:
   4073 	return 2;
   4074 
   4075       case vec_construct:
   4076 	elements = TYPE_VECTOR_SUBPARTS (vectype);
   4077 	if (ISA_HAS_LASX)
   4078 	  return elements + 1;
   4079 	else
   4080 	  return elements;
   4081 
   4082       default:
   4083 	gcc_unreachable ();
   4084     }
   4085 }
   4086 
   4087 class loongarch_vector_costs : public vector_costs
   4088 {
   4089 public:
   4090   using vector_costs::vector_costs;
   4091 
   4092   unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind,
   4093 			      stmt_vec_info stmt_info, slp_tree, tree vectype,
   4094 			      int misalign,
   4095 			      vect_cost_model_location where) override;
   4096   void finish_cost (const vector_costs *) override;
   4097 
   4098 protected:
   4099   void count_operations (vect_cost_for_stmt, stmt_vec_info,
   4100 			 vect_cost_model_location, unsigned int);
   4101   unsigned int determine_suggested_unroll_factor (loop_vec_info);
   4102   /* The number of vectorized stmts in loop.  */
   4103   unsigned m_stmts = 0;
   4104   /* The number of load and store operations in loop.  */
   4105   unsigned m_loads = 0;
   4106   unsigned m_stores = 0;
   4107   /* Reduction factor for suggesting unroll factor.  */
   4108   unsigned m_reduc_factor = 0;
   4109   /* True if the loop contains an average operation. */
   4110   bool m_has_avg = false;
   4111   /* True if the loop uses approximation instruction sequence.  */
   4112   bool m_has_recip = false;
   4113 };
   4114 
   4115 /* Implement TARGET_VECTORIZE_CREATE_COSTS.  */
   4116 static vector_costs *
   4117 loongarch_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar)
   4118 {
   4119   return new loongarch_vector_costs (vinfo, costing_for_scalar);
   4120 }
   4121 
   4122 void
   4123 loongarch_vector_costs::count_operations (vect_cost_for_stmt kind,
   4124 					  stmt_vec_info stmt_info,
   4125 					  vect_cost_model_location where,
   4126 					  unsigned int count)
   4127 {
   4128   if (!m_costing_for_scalar
   4129       && is_a<loop_vec_info> (m_vinfo)
   4130       && where == vect_body)
   4131     {
   4132       m_stmts += count;
   4133 
   4134       if (kind == scalar_load
   4135 	  || kind == vector_load
   4136 	  || kind == unaligned_load)
   4137 	m_loads += count;
   4138       else if (kind == scalar_store
   4139 	       || kind == vector_store
   4140 	       || kind == unaligned_store)
   4141 	m_stores += count;
   4142       else if ((kind == scalar_stmt
   4143 		|| kind == vector_stmt
   4144 		|| kind == vec_to_scalar)
   4145 	       && stmt_info && vect_is_reduction (stmt_info))
   4146 	{
   4147 	  tree lhs = gimple_get_lhs (stmt_info->stmt);
   4148 	  unsigned int base = FLOAT_TYPE_P (TREE_TYPE (lhs)) ? 2 : 1;
   4149 	  m_reduc_factor = MAX (base * count, m_reduc_factor);
   4150 	}
   4151     }
   4152 }
   4153 
   4154 unsigned int
   4155 loongarch_vector_costs::determine_suggested_unroll_factor (loop_vec_info loop_vinfo)
   4156 {
   4157   class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   4158 
   4159   if (m_has_avg || m_has_recip)
   4160     return 1;
   4161 
   4162   /* Don't unroll if it's specified explicitly not to be unrolled.  */
   4163   if (loop->unroll == 1
   4164       || (OPTION_SET_P (flag_unroll_loops) && !flag_unroll_loops)
   4165       || (OPTION_SET_P (flag_unroll_all_loops) && !flag_unroll_all_loops))
   4166     return 1;
   4167 
   4168   unsigned int nstmts_nonldst = m_stmts - m_loads - m_stores;
   4169   /* Don't unroll if no vector instructions excepting for memory access.  */
   4170   if (nstmts_nonldst == 0)
   4171     return 1;
   4172 
   4173   /* Use this simple hardware resource model that how many non vld/vst
   4174      vector instructions can be issued per cycle.  */
   4175   unsigned int issue_info = la_vect_issue_info;
   4176   unsigned int reduc_factor = m_reduc_factor > 1 ? m_reduc_factor : 1;
   4177   unsigned int uf = CEIL (reduc_factor * issue_info, nstmts_nonldst);
   4178   uf = MIN ((unsigned int) la_vect_unroll_limit, uf);
   4179 
   4180   return 1 << ceil_log2 (uf);
   4181 }
   4182 
   4183 /* Check if assign stmt rhs op comes from a multiply-add operation.  */
   4184 static bool
   4185 loongarch_multiply_add_p (vec_info *vinfo, stmt_vec_info stmt_info)
   4186 {
   4187   gassign *assign = dyn_cast<gassign *> (stmt_info->stmt);
   4188   if (!assign)
   4189     return false;
   4190   tree_code code = gimple_assign_rhs_code (assign);
   4191   if (code != PLUS_EXPR && code != MINUS_EXPR)
   4192     return false;
   4193 
   4194   auto is_mul_result = [&](int i)
   4195     {
   4196       tree rhs = gimple_op (assign, i);
   4197       if (TREE_CODE (rhs) != SSA_NAME)
   4198 	return false;
   4199 
   4200       stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
   4201       if (!def_stmt_info
   4202 	  || STMT_VINFO_DEF_TYPE (def_stmt_info) != vect_internal_def)
   4203 	return false;
   4204       gassign *rhs_assign = dyn_cast<gassign *> (def_stmt_info->stmt);
   4205       if (!rhs_assign || gimple_assign_rhs_code (rhs_assign) != MULT_EXPR)
   4206 	return false;
   4207 
   4208       return true;
   4209     };
   4210 
   4211   return is_mul_result (1) || is_mul_result (2);
   4212 }
   4213 
   4214 unsigned
   4215 loongarch_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
   4216 				       stmt_vec_info stmt_info, slp_tree,
   4217 				       tree vectype, int misalign,
   4218 				       vect_cost_model_location where)
   4219 {
   4220   unsigned retval = 0;
   4221 
   4222   if (flag_vect_cost_model)
   4223     {
   4224       int stmt_cost = loongarch_builtin_vectorization_cost (kind, vectype,
   4225 							    misalign);
   4226       if (vectype && stmt_info)
   4227 	{
   4228 	  gassign *assign = dyn_cast<gassign *> (STMT_VINFO_STMT (stmt_info));
   4229 	  machine_mode mode = TYPE_MODE (vectype);
   4230 
   4231 	  /* We found through testing that this strategy (the stmt that
   4232 	     matches the multiply-add pattern) has positive returns only
   4233 	     when applied to the 128-bit vector stmt, so this restriction
   4234 	     is currently made.  */
   4235 	  if (kind == vector_stmt && GET_MODE_SIZE (mode) == 16 && assign)
   4236 	    {
   4237 	      if (!vect_is_reduction (stmt_info)
   4238 		  && loongarch_multiply_add_p (m_vinfo, stmt_info))
   4239 		stmt_cost = 0;
   4240 	    }
   4241 	}
   4242 
   4243       retval = adjust_cost_for_freq (stmt_info, where, count * stmt_cost);
   4244       m_costs[where] += retval;
   4245 
   4246       count_operations (kind, stmt_info, where, count);
   4247     }
   4248 
   4249   if (stmt_info)
   4250     {
   4251       /* Detect the use of an averaging operation.  */
   4252       gimple *stmt = stmt_info->stmt;
   4253       if (is_gimple_call (stmt)
   4254 	  && gimple_call_internal_p (stmt))
   4255 	{
   4256 	  switch (gimple_call_internal_fn (stmt))
   4257 	    {
   4258 	    case IFN_AVG_FLOOR:
   4259 	    case IFN_AVG_CEIL:
   4260 	      m_has_avg = true;
   4261 	    default:
   4262 	      break;
   4263 	    }
   4264 	}
   4265     }
   4266 
   4267   combined_fn cfn;
   4268   if (kind == vector_stmt
   4269       && stmt_info
   4270       && stmt_info->stmt)
   4271     {
   4272       /* Detect the use of approximate instruction sequence.  */
   4273       if ((TARGET_RECIP_VEC_SQRT || TARGET_RECIP_VEC_RSQRT)
   4274 	  && (cfn = gimple_call_combined_fn (stmt_info->stmt)) != CFN_LAST)
   4275 	switch (cfn)
   4276 	  {
   4277 	  case CFN_BUILT_IN_SQRTF:
   4278 	    m_has_recip = true;
   4279 	  default:
   4280 	    break;
   4281 	  }
   4282       else if (TARGET_RECIP_VEC_DIV
   4283 	       && gimple_code (stmt_info->stmt) == GIMPLE_ASSIGN)
   4284 	{
   4285 	  machine_mode mode = TYPE_MODE (vectype);
   4286 	  switch (gimple_assign_rhs_code (stmt_info->stmt))
   4287 	    {
   4288 	    case RDIV_EXPR:
   4289 	      if (GET_MODE_INNER (mode) == SFmode)
   4290 		m_has_recip = true;
   4291 	    default:
   4292 	      break;
   4293 	    }
   4294 	}
   4295     }
   4296 
   4297   return retval;
   4298 }
   4299 
   4300 void
   4301 loongarch_vector_costs::finish_cost (const vector_costs *scalar_costs)
   4302 {
   4303   loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo);
   4304   if (loop_vinfo)
   4305     {
   4306       m_suggested_unroll_factor = determine_suggested_unroll_factor (loop_vinfo);
   4307     }
   4308 
   4309   vector_costs::finish_cost (scalar_costs);
   4310 }
   4311 
   4312 /* Implement TARGET_ADDRESS_COST.  */
   4313 
   4314 static int
   4315 loongarch_address_cost (rtx addr, machine_mode mode,
   4316 			addr_space_t as ATTRIBUTE_UNUSED,
   4317 			bool speed ATTRIBUTE_UNUSED)
   4318 {
   4319   return loongarch_address_insns (addr, mode, false);
   4320 }
   4321 
   4322 /* Return one word of double-word value OP, taking into account the fixed
   4323    endianness of certain registers.  HIGH_P is true to select the high part,
   4324    false to select the low part.  */
   4325 
   4326 rtx
   4327 loongarch_subword (rtx op, bool high_p)
   4328 {
   4329   unsigned int byte;
   4330   machine_mode mode;
   4331 
   4332   byte = high_p ? UNITS_PER_WORD : 0;
   4333   mode = GET_MODE (op);
   4334   if (mode == VOIDmode)
   4335     mode = TARGET_64BIT ? TImode : DImode;
   4336 
   4337   if (FP_REG_RTX_P (op))
   4338     return gen_rtx_REG (word_mode, REGNO (op) + high_p);
   4339 
   4340   if (MEM_P (op))
   4341     return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte));
   4342 
   4343   return simplify_gen_subreg (word_mode, op, mode, byte);
   4344 }
   4345 
   4346 /* Return true if a move from SRC to DEST should be split into two.
   4347    SPLIT_TYPE describes the split condition.  */
   4348 
   4349 bool
   4350 loongarch_split_move_p (rtx dest, rtx src)
   4351 {
   4352   /* FPR-to-FPR moves can be done in a single instruction, if they're
   4353      allowed at all.  */
   4354   unsigned int size = GET_MODE_SIZE (GET_MODE (dest));
   4355   if (size == 8 && FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
   4356     return false;
   4357 
   4358   /* Check for floating-point loads and stores.  */
   4359   if (size == 8)
   4360     {
   4361       if (FP_REG_RTX_P (dest) && MEM_P (src))
   4362 	return false;
   4363       if (FP_REG_RTX_P (src) && MEM_P (dest))
   4364 	return false;
   4365     }
   4366 
   4367   /* Check if LSX moves need splitting.  */
   4368   if (LSX_SUPPORTED_MODE_P (GET_MODE (dest)))
   4369     return loongarch_split_128bit_move_p (dest, src);
   4370 
   4371   /* Check if LASX moves need splitting.  */
   4372   if (LASX_SUPPORTED_MODE_P (GET_MODE (dest)))
   4373     return loongarch_split_256bit_move_p (dest, src);
   4374 
   4375   /* Otherwise split all multiword moves.  */
   4376   return size > UNITS_PER_WORD;
   4377 }
   4378 
   4379 /* Split a move from SRC to DEST, given that loongarch_split_move_p holds.
   4380    SPLIT_TYPE describes the split condition.  */
   4381 
   4382 void
   4383 loongarch_split_move (rtx dest, rtx src)
   4384 {
   4385   rtx low_dest;
   4386 
   4387   gcc_checking_assert (loongarch_split_move_p (dest, src));
   4388   if (LSX_SUPPORTED_MODE_P (GET_MODE (dest)))
   4389     loongarch_split_128bit_move (dest, src);
   4390   else if (LASX_SUPPORTED_MODE_P (GET_MODE (dest)))
   4391     loongarch_split_256bit_move (dest, src);
   4392   else if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
   4393     {
   4394       if (!TARGET_64BIT && GET_MODE (dest) == DImode)
   4395 	emit_insn (gen_move_doubleword_fprdi (dest, src));
   4396       else if (!TARGET_64BIT && GET_MODE (dest) == DFmode)
   4397 	emit_insn (gen_move_doubleword_fprdf (dest, src));
   4398       else if (TARGET_64BIT && GET_MODE (dest) == TFmode)
   4399 	emit_insn (gen_move_doubleword_fprtf (dest, src));
   4400       else
   4401 	gcc_unreachable ();
   4402     }
   4403   else
   4404     {
   4405       /* The operation can be split into two normal moves.  Decide in
   4406 	 which order to do them.  */
   4407       low_dest = loongarch_subword (dest, false);
   4408       if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src))
   4409 	{
   4410 	  loongarch_emit_move (loongarch_subword (dest, true),
   4411 			       loongarch_subword (src, true));
   4412 	  loongarch_emit_move (low_dest, loongarch_subword (src, false));
   4413 	}
   4414       else
   4415 	{
   4416 	  loongarch_emit_move (low_dest, loongarch_subword (src, false));
   4417 	  loongarch_emit_move (loongarch_subword (dest, true),
   4418 			       loongarch_subword (src, true));
   4419 	}
   4420     }
   4421 }
   4422 
   4423 /* Check if adding an integer constant value for a specific mode can be
   4424    performed with an addu16i.d instruction and an addi.{w/d}
   4425    instruction.  */
   4426 
   4427 bool
   4428 loongarch_addu16i_imm12_operand_p (HOST_WIDE_INT value, machine_mode mode)
   4429 {
   4430   /* Not necessary, but avoid unnecessary calculation if !TARGET_64BIT.  */
   4431   if (!TARGET_64BIT)
   4432     return false;
   4433 
   4434   if ((value & 0xffff) == 0)
   4435     return false;
   4436 
   4437   if (IMM12_OPERAND (value))
   4438     return false;
   4439 
   4440   value = (value & ~HWIT_UC_0xFFF) + ((value & 0x800) << 1);
   4441   return ADDU16I_OPERAND (trunc_int_for_mode (value, mode));
   4442 }
   4443 
   4444 /* Split one integer constant op[0] into two (op[1] and op[2]) for constant
   4445    plus operation in a specific mode.  The splitted constants can be added
   4446    onto a register with a single instruction (addi.{d/w} or addu16i.d).  */
   4447 
   4448 void
   4449 loongarch_split_plus_constant (rtx *op, machine_mode mode)
   4450 {
   4451   HOST_WIDE_INT v = INTVAL (op[0]), a;
   4452 
   4453   if (DUAL_IMM12_OPERAND (v))
   4454     a = (v > 0 ? 2047 : -2048);
   4455   else if (loongarch_addu16i_imm12_operand_p (v, mode))
   4456     a = (v & ~HWIT_UC_0xFFF) + ((v & 0x800) << 1);
   4457   else if (mode == DImode && DUAL_ADDU16I_OPERAND (v))
   4458     a = (v > 0 ? 0x7fff0000 : ~0x7fffffff);
   4459   else
   4460     gcc_unreachable ();
   4461 
   4462   op[1] = gen_int_mode (a, mode);
   4463   v = v - (unsigned HOST_WIDE_INT) a;
   4464   op[2] = gen_int_mode (v, mode);
   4465 }
   4466 
   4467 /* Implement TARGET_CONSTANT_ALIGNMENT.  */
   4468 
   4469 static HOST_WIDE_INT
   4470 loongarch_constant_alignment (const_tree exp, HOST_WIDE_INT align)
   4471 {
   4472   if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR)
   4473     return MAX (align, BITS_PER_WORD);
   4474   return align;
   4475 }
   4476 
   4477 const char *
   4478 loongarch_output_move_index (rtx x, machine_mode mode, bool ldr)
   4479 {
   4480   int index = exact_log2 (GET_MODE_SIZE (mode));
   4481   if (!IN_RANGE (index, 0, 3))
   4482     return NULL;
   4483 
   4484   struct loongarch_address_info info;
   4485   if ((loongarch_classify_address (&info, x, mode, false)
   4486        && !(info.type == ADDRESS_REG_REG))
   4487       || !loongarch_legitimate_address_p (mode, x, false))
   4488     return NULL;
   4489 
   4490   const char *const insn[][4] =
   4491     {
   4492       {
   4493 	"stx.b\t%z1,%0",
   4494 	"stx.h\t%z1,%0",
   4495 	"stx.w\t%z1,%0",
   4496 	"stx.d\t%z1,%0",
   4497       },
   4498       {
   4499 	"ldx.bu\t%0,%1",
   4500 	"ldx.hu\t%0,%1",
   4501 	"ldx.w\t%0,%1",
   4502 	"ldx.d\t%0,%1",
   4503       }
   4504     };
   4505 
   4506   return insn[ldr][index];
   4507 }
   4508 
   4509 const char *
   4510 loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr)
   4511 {
   4512   int index = exact_log2 (GET_MODE_SIZE (mode));
   4513   if (!IN_RANGE (index, 2, 5))
   4514     return NULL;
   4515 
   4516   struct loongarch_address_info info;
   4517   if ((loongarch_classify_address (&info, x, mode, false)
   4518        && !(info.type == ADDRESS_REG_REG))
   4519       || !loongarch_legitimate_address_p (mode, x, false))
   4520     return NULL;
   4521 
   4522   const char *const insn[][4] =
   4523     {
   4524 	{
   4525 	  "fstx.s\t%1,%0",
   4526 	  "fstx.d\t%1,%0",
   4527 	  "vstx\t%w1,%0",
   4528 	  "xvstx\t%u1,%0"
   4529 	},
   4530 	{
   4531 	  "fldx.s\t%0,%1",
   4532 	  "fldx.d\t%0,%1",
   4533 	  "vldx\t%w0,%1",
   4534 	  "xvldx\t%u0,%1"
   4535 	}
   4536     };
   4537 
   4538   return insn[ldr][index-2];
   4539 }
   4540 /* Return true if a 128-bit move from SRC to DEST should be split.  */
   4541 
   4542 bool
   4543 loongarch_split_128bit_move_p (rtx dest, rtx src)
   4544 {
   4545   /* LSX-to-LSX moves can be done in a single instruction.  */
   4546   if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
   4547     return false;
   4548 
   4549   /* Check for LSX loads and stores.  */
   4550   if (FP_REG_RTX_P (dest) && MEM_P (src))
   4551     return false;
   4552   if (FP_REG_RTX_P (src) && MEM_P (dest))
   4553     return false;
   4554 
   4555   /* Check for LSX set to an immediate const vector with valid replicated
   4556      element.  */
   4557   if (FP_REG_RTX_P (dest)
   4558       && loongarch_const_vector_same_int_p (src, GET_MODE (src), -512, 511))
   4559     return false;
   4560 
   4561   /* Check for LSX load zero immediate.  */
   4562   if (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src)))
   4563     return false;
   4564 
   4565   return true;
   4566 }
   4567 
   4568 /* Return true if a 256-bit move from SRC to DEST should be split.  */
   4569 
   4570 bool
   4571 loongarch_split_256bit_move_p (rtx dest, rtx src)
   4572 {
   4573   /* LSX-to-LSX moves can be done in a single instruction.  */
   4574   if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
   4575     return false;
   4576 
   4577   /* Check for LSX loads and stores.  */
   4578   if (FP_REG_RTX_P (dest) && MEM_P (src))
   4579     return false;
   4580   if (FP_REG_RTX_P (src) && MEM_P (dest))
   4581     return false;
   4582 
   4583   /* Check for LSX set to an immediate const vector with valid replicated
   4584      element.  */
   4585   if (FP_REG_RTX_P (dest)
   4586       && loongarch_const_vector_same_int_p (src, GET_MODE (src), -512, 511))
   4587     return false;
   4588 
   4589   /* Check for LSX load zero immediate.  */
   4590   if (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src)))
   4591     return false;
   4592 
   4593   return true;
   4594 }
   4595 
   4596 /* Split a 128-bit move from SRC to DEST.  */
   4597 
   4598 void
   4599 loongarch_split_128bit_move (rtx dest, rtx src)
   4600 {
   4601   int byte, index;
   4602   rtx low_dest, low_src, d, s;
   4603 
   4604   if (FP_REG_RTX_P (dest))
   4605     {
   4606       gcc_assert (!MEM_P (src));
   4607 
   4608       rtx new_dest = dest;
   4609       if (!TARGET_64BIT)
   4610 	{
   4611 	  if (GET_MODE (dest) != V4SImode)
   4612 	    new_dest = simplify_gen_subreg (V4SImode, dest, GET_MODE (dest), 0);
   4613 	}
   4614       else
   4615 	{
   4616 	  if (GET_MODE (dest) != V2DImode)
   4617 	    new_dest = simplify_gen_subreg (V2DImode, dest, GET_MODE (dest), 0);
   4618 	}
   4619 
   4620       for (byte = 0, index = 0; byte < GET_MODE_SIZE (TImode);
   4621 	   byte += UNITS_PER_WORD, index++)
   4622 	{
   4623 	  s = loongarch_subword_at_byte (src, byte);
   4624 	  if (!TARGET_64BIT)
   4625 	    emit_insn (gen_lsx_vinsgr2vr_w (new_dest, s, new_dest,
   4626 					    GEN_INT (1 << index)));
   4627 	  else
   4628 	    emit_insn (gen_lsx_vinsgr2vr_d (new_dest, s, new_dest,
   4629 					    GEN_INT (1 << index)));
   4630 	}
   4631     }
   4632   else if (FP_REG_RTX_P (src))
   4633     {
   4634       gcc_assert (!MEM_P (dest));
   4635 
   4636       rtx new_src = src;
   4637       if (!TARGET_64BIT)
   4638 	{
   4639 	  if (GET_MODE (src) != V4SImode)
   4640 	    new_src = simplify_gen_subreg (V4SImode, src, GET_MODE (src), 0);
   4641 	}
   4642       else
   4643 	{
   4644 	  if (GET_MODE (src) != V2DImode)
   4645 	    new_src = simplify_gen_subreg (V2DImode, src, GET_MODE (src), 0);
   4646 	}
   4647 
   4648       for (byte = 0, index = 0; byte < GET_MODE_SIZE (TImode);
   4649 	   byte += UNITS_PER_WORD, index++)
   4650 	{
   4651 	  d = loongarch_subword_at_byte (dest, byte);
   4652 	  if (!TARGET_64BIT)
   4653 	    emit_insn (gen_lsx_vpickve2gr_w (d, new_src, GEN_INT (index)));
   4654 	  else
   4655 	    emit_insn (gen_lsx_vpickve2gr_d (d, new_src, GEN_INT (index)));
   4656 	}
   4657     }
   4658   else
   4659     {
   4660       low_dest = loongarch_subword_at_byte (dest, 0);
   4661       low_src = loongarch_subword_at_byte (src, 0);
   4662       gcc_assert (REG_P (low_dest) && REG_P (low_src));
   4663       /* Make sure the source register is not written before reading.  */
   4664       if (REGNO (low_dest) <= REGNO (low_src))
   4665 	{
   4666 	  for (byte = 0; byte < GET_MODE_SIZE (TImode);
   4667 	       byte += UNITS_PER_WORD)
   4668 	    {
   4669 	      d = loongarch_subword_at_byte (dest, byte);
   4670 	      s = loongarch_subword_at_byte (src, byte);
   4671 	      loongarch_emit_move (d, s);
   4672 	    }
   4673 	}
   4674       else
   4675 	{
   4676 	  for (byte = GET_MODE_SIZE (TImode) - UNITS_PER_WORD; byte >= 0;
   4677 	       byte -= UNITS_PER_WORD)
   4678 	    {
   4679 	      d = loongarch_subword_at_byte (dest, byte);
   4680 	      s = loongarch_subword_at_byte (src, byte);
   4681 	      loongarch_emit_move (d, s);
   4682 	    }
   4683 	}
   4684     }
   4685 }
   4686 
   4687 /* Split a 256-bit move from SRC to DEST.  */
   4688 
   4689 void
   4690 loongarch_split_256bit_move (rtx dest, rtx src)
   4691 {
   4692   int byte, index;
   4693   rtx low_dest, low_src, d, s;
   4694 
   4695   if (FP_REG_RTX_P (dest))
   4696     {
   4697       gcc_assert (!MEM_P (src));
   4698 
   4699       rtx new_dest = dest;
   4700       if (!TARGET_64BIT)
   4701 	{
   4702 	  if (GET_MODE (dest) != V8SImode)
   4703 	    new_dest = simplify_gen_subreg (V8SImode, dest, GET_MODE (dest), 0);
   4704 	}
   4705       else
   4706 	{
   4707 	  if (GET_MODE (dest) != V4DImode)
   4708 	    new_dest = simplify_gen_subreg (V4DImode, dest, GET_MODE (dest), 0);
   4709 	}
   4710 
   4711       for (byte = 0, index = 0; byte < GET_MODE_SIZE (GET_MODE (dest));
   4712 	   byte += UNITS_PER_WORD, index++)
   4713 	{
   4714 	  s = loongarch_subword_at_byte (src, byte);
   4715 	  if (!TARGET_64BIT)
   4716 	    emit_insn (gen_lasx_xvinsgr2vr_w (new_dest, s, new_dest,
   4717 					      GEN_INT (1 << index)));
   4718 	  else
   4719 	    emit_insn (gen_lasx_xvinsgr2vr_d (new_dest, s, new_dest,
   4720 					      GEN_INT (1 << index)));
   4721 	}
   4722     }
   4723   else if (FP_REG_RTX_P (src))
   4724     {
   4725       gcc_assert (!MEM_P (dest));
   4726 
   4727       rtx new_src = src;
   4728       if (!TARGET_64BIT)
   4729 	{
   4730 	  if (GET_MODE (src) != V8SImode)
   4731 	    new_src = simplify_gen_subreg (V8SImode, src, GET_MODE (src), 0);
   4732 	}
   4733       else
   4734 	{
   4735 	  if (GET_MODE (src) != V4DImode)
   4736 	    new_src = simplify_gen_subreg (V4DImode, src, GET_MODE (src), 0);
   4737 	}
   4738 
   4739       for (byte = 0, index = 0; byte < GET_MODE_SIZE (GET_MODE (src));
   4740 	   byte += UNITS_PER_WORD, index++)
   4741 	{
   4742 	  d = loongarch_subword_at_byte (dest, byte);
   4743 	  if (!TARGET_64BIT)
   4744 	    emit_insn (gen_lsx_vpickve2gr_w (d, new_src, GEN_INT (index)));
   4745 	  else
   4746 	    emit_insn (gen_lsx_vpickve2gr_d (d, new_src, GEN_INT (index)));
   4747 	}
   4748     }
   4749   else
   4750     {
   4751       low_dest = loongarch_subword_at_byte (dest, 0);
   4752       low_src = loongarch_subword_at_byte (src, 0);
   4753       gcc_assert (REG_P (low_dest) && REG_P (low_src));
   4754       /* Make sure the source register is not written before reading.  */
   4755       if (REGNO (low_dest) <= REGNO (low_src))
   4756 	{
   4757 	  for (byte = 0; byte < GET_MODE_SIZE (TImode);
   4758 	       byte += UNITS_PER_WORD)
   4759 	    {
   4760 	      d = loongarch_subword_at_byte (dest, byte);
   4761 	      s = loongarch_subword_at_byte (src, byte);
   4762 	      loongarch_emit_move (d, s);
   4763 	    }
   4764 	}
   4765       else
   4766 	{
   4767 	  for (byte = GET_MODE_SIZE (TImode) - UNITS_PER_WORD; byte >= 0;
   4768 	       byte -= UNITS_PER_WORD)
   4769 	    {
   4770 	      d = loongarch_subword_at_byte (dest, byte);
   4771 	      s = loongarch_subword_at_byte (src, byte);
   4772 	      loongarch_emit_move (d, s);
   4773 	    }
   4774 	}
   4775     }
   4776 }
   4777 
   4778 /* Return the appropriate instructions to move SRC into DEST.  Assume
   4779    that SRC is operand 1 and DEST is operand 0.  */
   4780 
   4781 const char *
   4782 loongarch_output_move (rtx dest, rtx src)
   4783 {
   4784   enum rtx_code dest_code = GET_CODE (dest);
   4785   enum rtx_code src_code = GET_CODE (src);
   4786   machine_mode mode = GET_MODE (dest);
   4787   bool dbl_p = (GET_MODE_SIZE (mode) == 8);
   4788   bool lsx_p = LSX_SUPPORTED_MODE_P (mode);
   4789   bool lasx_p = LASX_SUPPORTED_MODE_P (mode);
   4790 
   4791   if (loongarch_split_move_p (dest, src))
   4792     return "#";
   4793 
   4794   if ((lsx_p || lasx_p)
   4795       && dest_code == REG && FP_REG_P (REGNO (dest))
   4796       && src_code == CONST_VECTOR
   4797       && CONST_INT_P (CONST_VECTOR_ELT (src, 0)))
   4798     {
   4799       gcc_assert (loongarch_const_vector_same_int_p (src, mode, -512, 511));
   4800       switch (GET_MODE_SIZE (mode))
   4801 	{
   4802 	case 16:
   4803 	  return "vrepli.%v0\t%w0,%E1";
   4804 	case 32:
   4805 	  return "xvrepli.%v0\t%u0,%E1";
   4806 	default: gcc_unreachable ();
   4807 	}
   4808     }
   4809 
   4810   if ((src_code == REG && GP_REG_P (REGNO (src)))
   4811       || (src == CONST0_RTX (mode)))
   4812     {
   4813       if (dest_code == REG)
   4814 	{
   4815 	  if (GP_REG_P (REGNO (dest)))
   4816 	    return "or\t%0,%z1,$r0";
   4817 
   4818 	  if (FP_REG_P (REGNO (dest)))
   4819 	    {
   4820 	      if (lsx_p || lasx_p)
   4821 		{
   4822 		  gcc_assert (src == CONST0_RTX (GET_MODE (src)));
   4823 		  switch (GET_MODE_SIZE (mode))
   4824 		    {
   4825 		    case 16:
   4826 		      return "vrepli.b\t%w0,0";
   4827 		    case 32:
   4828 		      return "xvrepli.b\t%u0,0";
   4829 		    default:
   4830 		      gcc_unreachable ();
   4831 		    }
   4832 		}
   4833 
   4834 	      return dbl_p ? "movgr2fr.d\t%0,%z1" : "movgr2fr.w\t%0,%z1";
   4835 	    }
   4836 	}
   4837       if (dest_code == MEM)
   4838 	{
   4839 	  const char *insn = NULL;
   4840 	  insn = loongarch_output_move_index (XEXP (dest, 0), GET_MODE (dest),
   4841 					      false);
   4842 	  if (insn)
   4843 	    return insn;
   4844 
   4845 	  rtx offset = XEXP (dest, 0);
   4846 	  if (GET_CODE (offset) == PLUS)
   4847 	    offset = XEXP (offset, 1);
   4848 	  switch (GET_MODE_SIZE (mode))
   4849 	    {
   4850 	    case 1:
   4851 	      return "st.b\t%z1,%0";
   4852 	    case 2:
   4853 	      return "st.h\t%z1,%0";
   4854 	    case 4:
   4855 	      /* Matching address type with a 12bit offset and
   4856 		 ADDRESS_LO_SUM.  */
   4857 	      if (const_arith_operand (offset, Pmode)
   4858 		  || GET_CODE (offset) == LO_SUM)
   4859 		return "st.w\t%z1,%0";
   4860 	      else
   4861 		return "stptr.w\t%z1,%0";
   4862 	    case 8:
   4863 	      if (const_arith_operand (offset, Pmode)
   4864 		  || GET_CODE (offset) == LO_SUM)
   4865 		return "st.d\t%z1,%0";
   4866 	      else
   4867 		return "stptr.d\t%z1,%0";
   4868 	    default:
   4869 	      gcc_unreachable ();
   4870 	    }
   4871 	}
   4872     }
   4873   if (dest_code == REG && GP_REG_P (REGNO (dest)))
   4874     {
   4875       if (src_code == REG)
   4876 	if (FP_REG_P (REGNO (src)))
   4877 	  {
   4878 	    gcc_assert (!lsx_p);
   4879 	    return dbl_p ? "movfr2gr.d\t%0,%1" : "movfr2gr.s\t%0,%1";
   4880 	  }
   4881 
   4882       if (src_code == MEM)
   4883 	{
   4884 	  const char *insn = NULL;
   4885 	  insn = loongarch_output_move_index (XEXP (src, 0), GET_MODE (src),
   4886 					      true);
   4887 	  if (insn)
   4888 	    return insn;
   4889 
   4890 	  rtx offset = XEXP (src, 0);
   4891 	  if (GET_CODE (offset) == PLUS)
   4892 	    offset = XEXP (offset, 1);
   4893 	  switch (GET_MODE_SIZE (mode))
   4894 	    {
   4895 	    case 1:
   4896 	      return "ld.bu\t%0,%1";
   4897 	    case 2:
   4898 	      return "ld.hu\t%0,%1";
   4899 	    case 4:
   4900 	      /* Matching address type with a 12bit offset and
   4901 		 ADDRESS_LO_SUM.  */
   4902 	      if (const_arith_operand (offset, Pmode)
   4903 		  || GET_CODE (offset) == LO_SUM)
   4904 		return "ld.w\t%0,%1";
   4905 	      else
   4906 		return "ldptr.w\t%0,%1";
   4907 	    case 8:
   4908 	      if (const_arith_operand (offset, Pmode)
   4909 		  || GET_CODE (offset) == LO_SUM)
   4910 		return "ld.d\t%0,%1";
   4911 	      else
   4912 		return "ldptr.d\t%0,%1";
   4913 	    default:
   4914 	      gcc_unreachable ();
   4915 	    }
   4916 	}
   4917 
   4918       if (src_code == HIGH)
   4919 	{
   4920 	  rtx offset, x;
   4921 	  split_const (XEXP (src, 0), &x, &offset);
   4922 	  enum loongarch_symbol_type type = SYMBOL_PCREL;
   4923 
   4924 	  if (UNSPEC_ADDRESS_P (x))
   4925 	    type = UNSPEC_ADDRESS_TYPE (x);
   4926 
   4927 	  if (type == SYMBOL_TLS_LE)
   4928 	    return "lu12i.w\t%0,%h1";
   4929 	  else
   4930 	    return "%Q1pcalau12i\t%0,%h1";
   4931 	}
   4932 
   4933       if (src_code == CONST_INT)
   4934 	{
   4935 	  if (LU12I_INT (src))
   4936 	    return "lu12i.w\t%0,%1>>12\t\t\t# %X1";
   4937 	  else if (IMM12_INT (src))
   4938 	    return "addi.w\t%0,$r0,%1\t\t\t# %X1";
   4939 	  else if (IMM12_INT_UNSIGNED (src))
   4940 	    return "ori\t%0,$r0,%1\t\t\t# %X1";
   4941 	  else if (LU52I_INT (src))
   4942 	    return "lu52i.d\t%0,$r0,%X1>>52\t\t\t# %1";
   4943 	  else
   4944 	    gcc_unreachable ();
   4945 	}
   4946     }
   4947 
   4948   if (!loongarch_explicit_relocs_p (loongarch_classify_symbol (src))
   4949       && dest_code == REG && symbolic_operand (src, VOIDmode))
   4950     {
   4951       if (loongarch_classify_symbol (src) == SYMBOL_PCREL)
   4952 	return "la.local\t%0,%1";
   4953       else
   4954 	return "la.global\t%0,%1";
   4955     }
   4956 
   4957   if (src_code == REG && FP_REG_P (REGNO (src)))
   4958     {
   4959       if (dest_code == REG && FP_REG_P (REGNO (dest)))
   4960 	{
   4961 	  if (lsx_p || lasx_p)
   4962 	    {
   4963 	      switch (GET_MODE_SIZE (mode))
   4964 		{
   4965 		case 16:
   4966 		  return "vori.b\t%w0,%w1,0";
   4967 		case 32:
   4968 		  return "xvori.b\t%u0,%u1,0";
   4969 		default:
   4970 		  gcc_unreachable ();
   4971 		}
   4972 	    }
   4973 
   4974 	  return dbl_p ? "fmov.d\t%0,%1" : "fmov.s\t%0,%1";
   4975 	}
   4976 
   4977       if (dest_code == MEM)
   4978 	{
   4979 	  const char *insn = NULL;
   4980 	  insn = loongarch_output_move_index_float (XEXP (dest, 0),
   4981 						    GET_MODE (dest),
   4982 						    false);
   4983 	  if (insn)
   4984 	    return insn;
   4985 
   4986 	  if (lsx_p || lasx_p)
   4987 	    {
   4988 	      switch (GET_MODE_SIZE (mode))
   4989 		{
   4990 		case 16:
   4991 		  return "vst\t%w1,%0";
   4992 		case 32:
   4993 		  return "xvst\t%u1,%0";
   4994 		default:
   4995 		  gcc_unreachable ();
   4996 		}
   4997 	    }
   4998 
   4999 	  return dbl_p ? "fst.d\t%1,%0" : "fst.s\t%1,%0";
   5000 	}
   5001     }
   5002 
   5003   if (dest_code == REG && FP_REG_P (REGNO (dest)))
   5004     {
   5005       if (src_code == MEM)
   5006 	{
   5007 	  const char *insn = NULL;
   5008 	  insn = loongarch_output_move_index_float (XEXP (src, 0),
   5009 						    GET_MODE (src),
   5010 						    true);
   5011 	  if (insn)
   5012 	    return insn;
   5013 
   5014 	  if (lsx_p || lasx_p)
   5015 	    {
   5016 	      switch (GET_MODE_SIZE (mode))
   5017 		{
   5018 		case 16:
   5019 		  return "vld\t%w0,%1";
   5020 		case 32:
   5021 		  return "xvld\t%u0,%1";
   5022 		default:
   5023 		  gcc_unreachable ();
   5024 		}
   5025 	    }
   5026 	  return dbl_p ? "fld.d\t%0,%1" : "fld.s\t%0,%1";
   5027 	}
   5028     }
   5029 
   5030   gcc_unreachable ();
   5031 }
   5032 
   5033 /* Return true if CMP1 is a suitable second operand for integer ordering
   5034    test CODE.  */
   5035 
   5036 static bool
   5037 loongarch_int_order_operand_ok_p (enum rtx_code code, rtx cmp1)
   5038 {
   5039   switch (code)
   5040     {
   5041     case GT:
   5042     case GTU:
   5043       return reg_or_0_operand (cmp1, VOIDmode);
   5044 
   5045     case GE:
   5046     case GEU:
   5047       return cmp1 == const1_rtx;
   5048 
   5049     case LT:
   5050     case LTU:
   5051       return arith_operand (cmp1, VOIDmode);
   5052 
   5053     case LE:
   5054       return sle_operand (cmp1, VOIDmode);
   5055 
   5056     case LEU:
   5057       return sleu_operand (cmp1, VOIDmode);
   5058 
   5059     default:
   5060       gcc_unreachable ();
   5061     }
   5062 }
   5063 
   5064 /* Return true if *CMP1 (of mode MODE) is a valid second operand for
   5065    integer ordering test *CODE, or if an equivalent combination can
   5066    be formed by adjusting *CODE and *CMP1.  When returning true, update
   5067    *CODE and *CMP1 with the chosen code and operand, otherwise leave
   5068    them alone.  */
   5069 
   5070 static bool
   5071 loongarch_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1,
   5072 				       machine_mode mode)
   5073 {
   5074   HOST_WIDE_INT plus_one;
   5075 
   5076   if (loongarch_int_order_operand_ok_p (*code, *cmp1))
   5077     return true;
   5078 
   5079   if (CONST_INT_P (*cmp1))
   5080     switch (*code)
   5081       {
   5082       case LE:
   5083 	plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
   5084 	if (INTVAL (*cmp1) < plus_one)
   5085 	  {
   5086 	    *code = LT;
   5087 	    *cmp1 = force_reg (mode, GEN_INT (plus_one));
   5088 	    return true;
   5089 	  }
   5090 	break;
   5091 
   5092       case LEU:
   5093 	plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
   5094 	if (plus_one != 0)
   5095 	  {
   5096 	    *code = LTU;
   5097 	    *cmp1 = force_reg (mode, GEN_INT (plus_one));
   5098 	    return true;
   5099 	  }
   5100 	break;
   5101 
   5102       default:
   5103 	break;
   5104       }
   5105   return false;
   5106 }
   5107 
   5108 /* Compare CMP0 and CMP1 using ordering test CODE and store the result
   5109    in TARGET.  CMP0 and TARGET are register_operands.  If INVERT_PTR
   5110    is nonnull, it's OK to set TARGET to the inverse of the result and
   5111    flip *INVERT_PTR instead.  */
   5112 
   5113 static void
   5114 loongarch_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
   5115 			       rtx target, rtx cmp0, rtx cmp1)
   5116 {
   5117   machine_mode mode;
   5118 
   5119   /* First see if there is a LoongArch instruction that can do this operation.
   5120      If not, try doing the same for the inverse operation.  If that also
   5121      fails, force CMP1 into a register and try again.  */
   5122   mode = GET_MODE (cmp0);
   5123   if (loongarch_canonicalize_int_order_test (&code, &cmp1, mode))
   5124     loongarch_emit_binary (code, target, cmp0, cmp1);
   5125   else
   5126     {
   5127       enum rtx_code inv_code = reverse_condition (code);
   5128       if (!loongarch_canonicalize_int_order_test (&inv_code, &cmp1, mode))
   5129 	{
   5130 	  cmp1 = force_reg (mode, cmp1);
   5131 	  loongarch_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1);
   5132 	}
   5133       else if (invert_ptr == 0)
   5134 	{
   5135 	  rtx inv_target;
   5136 
   5137 	  inv_target = loongarch_force_binary (GET_MODE (target),
   5138 					       inv_code, cmp0, cmp1);
   5139 	  loongarch_emit_binary (XOR, target, inv_target, const1_rtx);
   5140 	}
   5141       else
   5142 	{
   5143 	  *invert_ptr = !*invert_ptr;
   5144 	  loongarch_emit_binary (inv_code, target, cmp0, cmp1);
   5145 	}
   5146     }
   5147 }
   5148 
   5149 /* Return a register that is zero if CMP0 and CMP1 are equal.
   5150    The register will have the same mode as CMP0.  */
   5151 
   5152 static rtx
   5153 loongarch_zero_if_equal (rtx cmp0, rtx cmp1)
   5154 {
   5155   if (cmp1 == const0_rtx)
   5156     return cmp0;
   5157 
   5158   if (uns_arith_operand (cmp1, VOIDmode))
   5159     return expand_binop (GET_MODE (cmp0), xor_optab, cmp0, cmp1, 0, 0,
   5160 			 OPTAB_DIRECT);
   5161 
   5162   return expand_binop (GET_MODE (cmp0), sub_optab, cmp0, cmp1, 0, 0,
   5163 		       OPTAB_DIRECT);
   5164 }
   5165 
   5166 /* Sign- or zero-extend OP0 and OP1 for integer comparisons.  */
   5167 
   5168 static void
   5169 loongarch_extend_comparands (rtx_code code, rtx *op0, rtx *op1)
   5170 {
   5171   /* Comparisons consider all GRLEN bits, so extend sub-GRLEN values.  */
   5172   if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0)))
   5173     {
   5174       /* It is more profitable to zero-extend QImode values.  But not if the
   5175 	 first operand has already been sign-extended, and the second one is
   5176 	 is a constant or has already been sign-extended also.  */
   5177       if (unsigned_condition (code) == code
   5178 	  && (GET_MODE (*op0) == QImode
   5179 	      && ! (GET_CODE (*op0) == SUBREG
   5180 		    && SUBREG_PROMOTED_VAR_P (*op0)
   5181 		    && SUBREG_PROMOTED_SIGNED_P (*op0)
   5182 		    && (CONST_INT_P (*op1)
   5183 			|| (GET_CODE (*op1) == SUBREG
   5184 			    && SUBREG_PROMOTED_VAR_P (*op1)
   5185 			    && SUBREG_PROMOTED_SIGNED_P (*op1))))))
   5186 	{
   5187 	  *op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0);
   5188 	  if (CONST_INT_P (*op1))
   5189 	    *op1 = GEN_INT ((uint8_t) INTVAL (*op1));
   5190 	  else
   5191 	    *op1 = gen_rtx_ZERO_EXTEND (word_mode, *op1);
   5192 	}
   5193       else
   5194 	{
   5195 	  *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0);
   5196 	  if (*op1 != const0_rtx)
   5197 	    *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1);
   5198 	}
   5199     }
   5200 }
   5201 
   5202 
   5203 /* Convert a comparison into something that can be used in a branch.  On
   5204    entry, *OP0 and *OP1 are the values being compared and *CODE is the code
   5205    used to compare them.  Update them to describe the final comparison.  */
   5206 
   5207 static void
   5208 loongarch_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1)
   5209 {
   5210   static const enum rtx_code
   5211   mag_comparisons[][2] = {{LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE}};
   5212 
   5213   if (splittable_const_int_operand (*op1, VOIDmode))
   5214     {
   5215       HOST_WIDE_INT rhs = INTVAL (*op1);
   5216 
   5217       if (*code == EQ || *code == NE)
   5218 	{
   5219 	  /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0.  */
   5220 	  if (IMM12_OPERAND (-rhs))
   5221 	    {
   5222 	      *op0 = loongarch_force_binary (GET_MODE (*op0), PLUS, *op0,
   5223 					     GEN_INT (-rhs));
   5224 	      *op1 = const0_rtx;
   5225 	    }
   5226 	}
   5227       else
   5228 	{
   5229 	  /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000).  */
   5230 	  for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++)
   5231 	    {
   5232 	      HOST_WIDE_INT new_rhs;
   5233 	      bool increment = *code == mag_comparisons[i][0];
   5234 	      bool decrement = *code == mag_comparisons[i][1];
   5235 	      if (!increment && !decrement)
   5236 		continue;
   5237 
   5238 	      if ((increment && rhs == HOST_WIDE_INT_MAX)
   5239 		  || (decrement && rhs == HOST_WIDE_INT_MIN))
   5240 		break;
   5241 
   5242 	      new_rhs = rhs + (increment ? 1 : -1);
   5243 	      if (loongarch_integer_cost (new_rhs)
   5244 		    < loongarch_integer_cost (rhs))
   5245 		{
   5246 		  *op1 = GEN_INT (new_rhs);
   5247 		  *code = mag_comparisons[i][increment];
   5248 		}
   5249 	      break;
   5250 	    }
   5251 	}
   5252     }
   5253 
   5254   loongarch_extend_comparands (*code, op0, op1);
   5255 
   5256   *op0 = force_reg (word_mode, *op0);
   5257   if (*op1 != const0_rtx)
   5258     *op1 = force_reg (word_mode, *op1);
   5259 }
   5260 
   5261 /* Like loongarch_emit_int_compare, but for floating-point comparisons.  */
   5262 
   5263 static void
   5264 loongarch_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
   5265 {
   5266   rtx cmp_op0 = *op0;
   5267   rtx cmp_op1 = *op1;
   5268 
   5269   /* Floating-point tests use a separate FCMP.cond.fmt
   5270      comparison to set a register.  The branch or conditional move will
   5271      then compare that register against zero.
   5272 
   5273      Set CMP_CODE to the code of the comparison instruction and
   5274      *CODE to the code that the branch or move should use.  */
   5275   enum rtx_code cmp_code = *code;
   5276   /* Three FP conditions cannot be implemented by reversing the
   5277      operands for FCMP.cond.fmt, instead a reversed condition code is
   5278      required and a test for false.  */
   5279   *code = NE;
   5280   *op0 = gen_reg_rtx (FCCmode);
   5281 
   5282   *op1 = const0_rtx;
   5283   loongarch_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
   5284 }
   5285 
   5286 /* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
   5287    and OPERAND[3].  Store the result in OPERANDS[0].
   5288 
   5289    On 64-bit targets, the mode of the comparison and target will always be
   5290    SImode, thus possibly narrower than that of the comparison's operands.  */
   5291 
   5292 void
   5293 loongarch_expand_scc (rtx operands[])
   5294 {
   5295   rtx target = operands[0];
   5296   enum rtx_code code = GET_CODE (operands[1]);
   5297   rtx op0 = operands[2];
   5298   rtx op1 = operands[3];
   5299 
   5300   loongarch_extend_comparands (code, &op0, &op1);
   5301   op0 = force_reg (word_mode, op0);
   5302 
   5303   gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT);
   5304 
   5305   if (code == EQ || code == NE)
   5306     {
   5307       rtx zie = loongarch_zero_if_equal (op0, op1);
   5308       loongarch_emit_binary (code, target, zie, const0_rtx);
   5309     }
   5310   else
   5311     loongarch_emit_int_order_test (code, 0, target, op0, op1);
   5312 }
   5313 
   5314 /* Compare OPERANDS[1] with OPERANDS[2] using comparison code
   5315    CODE and jump to OPERANDS[3] if the condition holds.  */
   5316 
   5317 void
   5318 loongarch_expand_conditional_branch (rtx *operands)
   5319 {
   5320   enum rtx_code code = GET_CODE (operands[0]);
   5321   rtx op0 = operands[1];
   5322   rtx op1 = operands[2];
   5323   rtx condition;
   5324 
   5325   if (FLOAT_MODE_P (GET_MODE (op1)))
   5326     loongarch_emit_float_compare (&code, &op0, &op1);
   5327   else
   5328     loongarch_emit_int_compare (&code, &op0, &op1);
   5329 
   5330   condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
   5331   emit_jump_insn (gen_condjump (condition, operands[3]));
   5332 }
   5333 
   5334 /* Perform the comparison in OPERANDS[1].  Move OPERANDS[2] into OPERANDS[0]
   5335    if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0].  */
   5336 
   5337 void
   5338 loongarch_expand_conditional_move (rtx *operands)
   5339 {
   5340   enum rtx_code code = GET_CODE (operands[1]);
   5341   rtx op0 = XEXP (operands[1], 0);
   5342   rtx op1 = XEXP (operands[1], 1);
   5343   rtx op0_extend = op0;
   5344   rtx op1_extend = op1;
   5345 
   5346   /* Record whether operands[2] and operands[3] modes are promoted to word_mode.  */
   5347   bool promote_op[2] = {false, false};
   5348   bool promote_p = false;
   5349   machine_mode mode = GET_MODE (operands[0]);
   5350 
   5351   if (FLOAT_MODE_P (GET_MODE (op1)))
   5352     loongarch_emit_float_compare (&code, &op0, &op1);
   5353   else
   5354     {
   5355       if (GET_MODE_SIZE (GET_MODE (op0)) < word_mode)
   5356 	{
   5357 	  promote_op[0] = (REG_P (op0) && REG_P (operands[2]) &&
   5358 			   REGNO (op0) == REGNO (operands[2]));
   5359 	  promote_op[1] = (REG_P (op1) && REG_P (operands[3]) &&
   5360 			   REGNO (op1) == REGNO (operands[3]));
   5361 	}
   5362 
   5363       if (promote_op[0] || promote_op[1])
   5364 	{
   5365 	  mode = word_mode;
   5366 	  promote_p = true;
   5367 	}
   5368 
   5369       loongarch_extend_comparands (code, &op0, &op1);
   5370 
   5371       op0 = force_reg (word_mode, op0);
   5372       op0_extend = op0;
   5373       op1_extend = force_reg (word_mode, op1);
   5374 
   5375       if (code == EQ || code == NE)
   5376 	{
   5377 	  op0 = loongarch_zero_if_equal (op0, op1);
   5378 	  op1 = const0_rtx;
   5379 	}
   5380       else
   5381 	{
   5382 	  /* The comparison needs a separate scc instruction.  Store the
   5383 	     result of the scc in *OP0 and compare it against zero.  */
   5384 	  bool invert = false;
   5385 	  rtx target = gen_reg_rtx (GET_MODE (op0));
   5386 	  loongarch_emit_int_order_test (code, &invert, target, op0, op1);
   5387 	  code = invert ? EQ : NE;
   5388 	  op0 = target;
   5389 	  op1 = const0_rtx;
   5390 	}
   5391     }
   5392 
   5393   rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
   5394   /* There is no direct support for general conditional GP move involving
   5395      two registers using SEL.  */
   5396   if (INTEGRAL_MODE_P (GET_MODE (operands[2]))
   5397       && register_operand (operands[2], VOIDmode)
   5398       && register_operand (operands[3], VOIDmode))
   5399     {
   5400       rtx op2 = operands[2];
   5401       rtx op3 = operands[3];
   5402 
   5403       if (promote_p)
   5404 	{
   5405 	  if (promote_op[0])
   5406 	    op2 = op0_extend;
   5407 	  else
   5408 	    {
   5409 	      loongarch_extend_comparands (code, &op2, &const0_rtx);
   5410 	      op2 = force_reg (mode, op2);
   5411 	    }
   5412 
   5413 	  if (promote_op[1])
   5414 	    op3 = op1_extend;
   5415 	  else
   5416 	    {
   5417 	      loongarch_extend_comparands (code, &op3, &const0_rtx);
   5418 	      op3 = force_reg (mode, op3);
   5419 	    }
   5420 	}
   5421 
   5422       rtx temp = gen_reg_rtx (mode);
   5423       rtx temp2 = gen_reg_rtx (mode);
   5424 
   5425       emit_insn (gen_rtx_SET (temp,
   5426 			      gen_rtx_IF_THEN_ELSE (mode, cond,
   5427 						    op2, const0_rtx)));
   5428 
   5429       /* Flip the test for the second operand.  */
   5430       cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, GET_MODE (op0), op0, op1);
   5431 
   5432       emit_insn (gen_rtx_SET (temp2,
   5433 			      gen_rtx_IF_THEN_ELSE (mode, cond,
   5434 						    op3, const0_rtx)));
   5435 
   5436       /* Merge the two results, at least one is guaranteed to be zero.  */
   5437       if (promote_p)
   5438 	{
   5439 	  rtx temp3 = gen_reg_rtx (mode);
   5440 	  emit_insn (gen_rtx_SET (temp3, gen_rtx_IOR (mode, temp, temp2)));
   5441 	  temp3 = gen_lowpart (GET_MODE (operands[0]), temp3);
   5442 	  /* Nonzero in a subreg if it was made when accessing an object that
   5443 	     was promoted to a wider mode in accord with the PROMOTED_MODE
   5444 	     machine description macro.  */
   5445 	  SUBREG_PROMOTED_VAR_P (temp3) = 1;
   5446 	  /* Sets promoted mode for SUBREG_PROMOTED_VAR_P.  */
   5447 	  SUBREG_PROMOTED_SET (temp3, SRP_SIGNED);
   5448 	  loongarch_emit_move (operands[0], temp3);
   5449 	}
   5450       else
   5451 	emit_insn (gen_rtx_SET (operands[0], gen_rtx_IOR (mode, temp, temp2)));
   5452     }
   5453   else
   5454     emit_insn (gen_rtx_SET (operands[0],
   5455 			    gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond,
   5456 						  operands[2], operands[3])));
   5457 }
   5458 
   5459 /* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
   5460 
   5461 static void
   5462 loongarch_va_start (tree valist, rtx nextarg)
   5463 {
   5464   nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size);
   5465   std_expand_builtin_va_start (valist, nextarg);
   5466 }
   5467 
   5468 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
   5469 
   5470 static bool
   5471 loongarch_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
   5472 				   tree exp ATTRIBUTE_UNUSED)
   5473 {
   5474   /* Always OK.  */
   5475   return true;
   5476 }
   5477 
   5478 static machine_mode
   5479 loongarch_mode_for_move_size (HOST_WIDE_INT size)
   5480 {
   5481   switch (size)
   5482     {
   5483     case 32:
   5484       return V32QImode;
   5485     case 16:
   5486       return V16QImode;
   5487     }
   5488 
   5489   return int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
   5490 }
   5491 
   5492 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
   5493    Assume that the areas do not overlap.  */
   5494 
   5495 static void
   5496 loongarch_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length,
   5497 			       HOST_WIDE_INT delta)
   5498 {
   5499   HOST_WIDE_INT offs, delta_cur;
   5500   int i;
   5501   machine_mode mode;
   5502   rtx *regs;
   5503 
   5504   /* Calculate how many registers we'll need for the block move.
   5505      We'll emit length / delta move operations with delta as the size
   5506      first.  Then we may still have length % delta bytes not copied.
   5507      We handle these remaining bytes by move operations with smaller
   5508      (halfed) sizes.  For example, if length = 21 and delta = 8, we'll
   5509      emit two ld.d/st.d pairs, one ld.w/st.w pair, and one ld.b/st.b
   5510      pair.  For each load/store pair we use a dedicated register to keep
   5511      the pipeline as populated as possible.  */
   5512   gcc_assert (pow2p_hwi (delta));
   5513   HOST_WIDE_INT num_reg = length / delta + popcount_hwi (length % delta);
   5514 
   5515   /* Allocate a buffer for the temporary registers.  */
   5516   regs = XALLOCAVEC (rtx, num_reg);
   5517 
   5518   for (delta_cur = delta, i = 0, offs = 0; offs < length; delta_cur /= 2)
   5519     {
   5520       mode = loongarch_mode_for_move_size (delta_cur);
   5521 
   5522       for (; offs + delta_cur <= length; offs += delta_cur, i++)
   5523 	{
   5524 	  regs[i] = gen_reg_rtx (mode);
   5525 	  loongarch_emit_move (regs[i], adjust_address (src, mode, offs));
   5526 	}
   5527     }
   5528 
   5529   for (delta_cur = delta, i = 0, offs = 0; offs < length; delta_cur /= 2)
   5530     {
   5531       mode = loongarch_mode_for_move_size (delta_cur);
   5532 
   5533       for (; offs + delta_cur <= length; offs += delta_cur, i++)
   5534 	loongarch_emit_move (adjust_address (dest, mode, offs), regs[i]);
   5535     }
   5536 }
   5537 
   5538 /* Helper function for doing a loop-based block operation on memory
   5539    reference MEM.  Each iteration of the loop will operate on LENGTH
   5540    bytes of MEM.
   5541 
   5542    Create a new base register for use within the loop and point it to
   5543    the start of MEM.  Create a new memory reference that uses this
   5544    register.  Store them in *LOOP_REG and *LOOP_MEM respectively.  */
   5545 
   5546 static void
   5547 loongarch_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg,
   5548 			    rtx *loop_mem)
   5549 {
   5550   *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
   5551 
   5552   /* Although the new mem does not refer to a known location,
   5553      it does keep up to LENGTH bytes of alignment.  */
   5554   *loop_mem = change_address (mem, BLKmode, *loop_reg);
   5555   set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
   5556 }
   5557 
   5558 /* Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER
   5559    bytes at a time.  LENGTH must be at least BYTES_PER_ITER.  Assume that
   5560    the memory regions do not overlap.  */
   5561 
   5562 static void
   5563 loongarch_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
   5564 			   HOST_WIDE_INT align)
   5565 {
   5566   rtx_code_label *label;
   5567   rtx src_reg, dest_reg, final_src, test;
   5568   HOST_WIDE_INT bytes_per_iter = align * LARCH_MAX_MOVE_OPS_PER_LOOP_ITER;
   5569   HOST_WIDE_INT leftover;
   5570 
   5571   leftover = length % bytes_per_iter;
   5572   length -= leftover;
   5573 
   5574   /* Create registers and memory references for use within the loop.  */
   5575   loongarch_adjust_block_mem (src, bytes_per_iter, &src_reg, &src);
   5576   loongarch_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest);
   5577 
   5578   /* Calculate the value that SRC_REG should have after the last iteration
   5579      of the loop.  */
   5580   final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), 0,
   5581 				   0, OPTAB_WIDEN);
   5582 
   5583   /* Emit the start of the loop.  */
   5584   label = gen_label_rtx ();
   5585   emit_label (label);
   5586 
   5587   /* Emit the loop body.  */
   5588   loongarch_block_move_straight (dest, src, bytes_per_iter, align);
   5589 
   5590   /* Move on to the next block.  */
   5591   loongarch_emit_move (src_reg,
   5592 		       plus_constant (Pmode, src_reg, bytes_per_iter));
   5593   loongarch_emit_move (dest_reg,
   5594 		       plus_constant (Pmode, dest_reg, bytes_per_iter));
   5595 
   5596   /* Emit the loop condition.  */
   5597   test = gen_rtx_NE (VOIDmode, src_reg, final_src);
   5598   if (Pmode == DImode)
   5599     emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label));
   5600   else
   5601     emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
   5602 
   5603   /* Mop up any left-over bytes.  */
   5604   if (leftover)
   5605     loongarch_block_move_straight (dest, src, leftover, align);
   5606   else
   5607     /* Temporary fix for PR79150.  */
   5608     emit_insn (gen_nop ());
   5609 }
   5610 
   5611 /* Expand a cpymemsi instruction, which copies LENGTH bytes from
   5612    memory reference SRC to memory reference DEST.  */
   5613 
   5614 bool
   5615 loongarch_expand_block_move (rtx dest, rtx src, rtx r_length, rtx r_align)
   5616 {
   5617   if (!CONST_INT_P (r_length))
   5618     return false;
   5619 
   5620   HOST_WIDE_INT length = INTVAL (r_length);
   5621   if (length > la_max_inline_memcpy_size)
   5622     return false;
   5623 
   5624   HOST_WIDE_INT align = INTVAL (r_align);
   5625 
   5626   if (!TARGET_STRICT_ALIGN || align > LARCH_MAX_MOVE_PER_INSN)
   5627     align = LARCH_MAX_MOVE_PER_INSN;
   5628 
   5629   if (length <= align * LARCH_MAX_MOVE_OPS_STRAIGHT)
   5630     {
   5631       loongarch_block_move_straight (dest, src, length, align);
   5632       return true;
   5633     }
   5634 
   5635   if (optimize)
   5636     {
   5637       loongarch_block_move_loop (dest, src, length, align);
   5638       return true;
   5639     }
   5640 
   5641   return false;
   5642 }
   5643 
   5644 /* Return true if loongarch_expand_block_move is the preferred
   5645    implementation of the 'cpymemsi' template.  */
   5646 
   5647 bool
   5648 loongarch_do_optimize_block_move_p (void)
   5649 {
   5650   /* if -m[no-]memcpy is given explicitly.  */
   5651   if (target_flags_explicit & MASK_MEMCPY)
   5652     return !TARGET_MEMCPY;
   5653 
   5654   /* if not, don't optimize under -Os.  */
   5655   return !optimize_size;
   5656 }
   5657 
   5658 /* Expand a QI or HI mode atomic memory operation.
   5659 
   5660    GENERATOR contains a pointer to the gen_* function that generates
   5661    the SI mode underlying atomic operation using masks that we
   5662    calculate.
   5663 
   5664    RESULT is the return register for the operation.  Its value is NULL
   5665    if unused.
   5666 
   5667    MEM is the location of the atomic access.
   5668 
   5669    OLDVAL is the first operand for the operation.
   5670 
   5671    NEWVAL is the optional second operand for the operation.  Its value
   5672    is NULL if unused.  */
   5673 
   5674 void
   5675 loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs generator,
   5676 			      rtx result, rtx mem, rtx oldval, rtx newval,
   5677 			      rtx model)
   5678 {
   5679   rtx orig_addr, memsi_addr, memsi, shift, shiftsi, unshifted_mask;
   5680   rtx unshifted_mask_reg, mask, inverted_mask, si_op;
   5681   rtx res = NULL;
   5682   machine_mode mode;
   5683 
   5684   mode = GET_MODE (mem);
   5685 
   5686   /* Compute the address of the containing SImode value.  */
   5687   orig_addr = force_reg (Pmode, XEXP (mem, 0));
   5688   memsi_addr = loongarch_force_binary (Pmode, AND, orig_addr,
   5689 				       force_reg (Pmode, GEN_INT (-4)));
   5690 
   5691   /* Create a memory reference for it.  */
   5692   memsi = gen_rtx_MEM (SImode, memsi_addr);
   5693   set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
   5694   MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
   5695 
   5696   /* Work out the byte offset of the QImode or HImode value,
   5697      counting from the least significant byte.  */
   5698   shift = loongarch_force_binary (Pmode, AND, orig_addr, GEN_INT (3));
   5699   /* Multiply by eight to convert the shift value from bytes to bits.  */
   5700   loongarch_emit_binary (ASHIFT, shift, shift, GEN_INT (3));
   5701 
   5702   /* Make the final shift an SImode value, so that it can be used in
   5703      SImode operations.  */
   5704   shiftsi = force_reg (SImode, gen_lowpart (SImode, shift));
   5705 
   5706   /* Set MASK to an inclusive mask of the QImode or HImode value.  */
   5707   unshifted_mask = GEN_INT (GET_MODE_MASK (mode));
   5708   unshifted_mask_reg = force_reg (SImode, unshifted_mask);
   5709   mask = loongarch_force_binary (SImode, ASHIFT, unshifted_mask_reg, shiftsi);
   5710 
   5711   /* Compute the equivalent exclusive mask.  */
   5712   inverted_mask = gen_reg_rtx (SImode);
   5713   emit_insn (gen_rtx_SET (inverted_mask, gen_rtx_NOT (SImode, mask)));
   5714 
   5715   /* Shift the old value into place.  */
   5716   if (oldval != const0_rtx)
   5717     {
   5718       oldval = convert_modes (SImode, mode, oldval, true);
   5719       oldval = force_reg (SImode, oldval);
   5720       oldval = loongarch_force_binary (SImode, ASHIFT, oldval, shiftsi);
   5721     }
   5722 
   5723   /* Do the same for the new value.  */
   5724   if (newval && newval != const0_rtx)
   5725     {
   5726       newval = convert_modes (SImode, mode, newval, true);
   5727       newval = force_reg (SImode, newval);
   5728       newval = loongarch_force_binary (SImode, ASHIFT, newval, shiftsi);
   5729     }
   5730 
   5731   /* Do the SImode atomic access.  */
   5732   if (result)
   5733     res = gen_reg_rtx (SImode);
   5734 
   5735   if (newval)
   5736     si_op = generator.fn_7 (res, memsi, mask, inverted_mask, oldval, newval,
   5737 			    model);
   5738   else if (result)
   5739     si_op = generator.fn_6 (res, memsi, mask, inverted_mask, oldval, model);
   5740   else
   5741     si_op = generator.fn_5 (memsi, mask, inverted_mask, oldval, model);
   5742 
   5743   emit_insn (si_op);
   5744 
   5745   if (result)
   5746     {
   5747       /* Shift and convert the result.  */
   5748       loongarch_emit_binary (AND, res, res, mask);
   5749       loongarch_emit_binary (LSHIFTRT, res, res, shiftsi);
   5750       loongarch_emit_move (result, gen_lowpart (GET_MODE (result), res));
   5751     }
   5752 }
   5753 
   5754 /* Return true if (zero_extract OP WIDTH BITPOS) can be used as the
   5755    source of an "ext" instruction or the destination of an "ins"
   5756    instruction.  OP must be a register operand and the following
   5757    conditions must hold:
   5758 
   5759    0 <= BITPOS < GET_MODE_BITSIZE (GET_MODE (op))
   5760    0 < WIDTH <= GET_MODE_BITSIZE (GET_MODE (op))
   5761    0 < BITPOS + WIDTH <= GET_MODE_BITSIZE (GET_MODE (op))
   5762 
   5763    Also reject lengths equal to a word as they are better handled
   5764    by the move patterns.  */
   5765 
   5766 bool
   5767 loongarch_use_ins_ext_p (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos)
   5768 {
   5769   if (!register_operand (op, VOIDmode)
   5770       || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
   5771     return false;
   5772 
   5773   if (!IN_RANGE (width, 1, GET_MODE_BITSIZE (GET_MODE (op)) - 1))
   5774     return false;
   5775 
   5776   if (bitpos < 0 || bitpos + width > GET_MODE_BITSIZE (GET_MODE (op)))
   5777     return false;
   5778 
   5779   return true;
   5780 }
   5781 
   5782 /* Predicate for pre-reload splitters with associated instructions,
   5783    which can match any time before the split1 pass (usually combine),
   5784    then are unconditionally split in that pass and should not be
   5785    matched again afterwards.  */
   5786 
   5787 bool loongarch_pre_reload_split (void)
   5788 {
   5789   return (can_create_pseudo_p ()
   5790 	  && !(cfun->curr_properties & PROP_rtl_split_insns));
   5791 }
   5792 
   5793 /* Check if we can use bstrins.<d> for
   5794    op0 = (op1 & op2) | (op3 & op4)
   5795    where op0, op1, op3 are regs, and op2, op4 are integer constants.  */
   5796 int
   5797 loongarch_use_bstrins_for_ior_with_mask (machine_mode mode, rtx *op)
   5798 {
   5799   unsigned HOST_WIDE_INT mask1 = UINTVAL (op[2]);
   5800   unsigned HOST_WIDE_INT mask2 = UINTVAL (op[4]);
   5801 
   5802   if (mask1 != ~mask2 || !mask1 || !mask2)
   5803     return 0;
   5804 
   5805   /* Try to avoid a right-shift.  */
   5806   if (low_bitmask_len (mode, mask1) != -1)
   5807     return -1;
   5808 
   5809   if (low_bitmask_len (mode, mask2 >> (ffs_hwi (mask2) - 1)) != -1)
   5810     return 1;
   5811 
   5812   if (low_bitmask_len (mode, mask1 >> (ffs_hwi (mask1) - 1)) != -1)
   5813     return -1;
   5814 
   5815   return 0;
   5816 }
   5817 
   5818 /* Rewrite a MEM for simple load/store under -mexplicit-relocs=auto
   5819    -mcmodel={normal/medium}.  */
   5820 rtx
   5821 loongarch_rewrite_mem_for_simple_ldst (rtx mem)
   5822 {
   5823   rtx addr = XEXP (mem, 0);
   5824   rtx hi = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
   5825 			   UNSPEC_PCALAU12I_GR);
   5826   rtx new_mem;
   5827 
   5828   addr = gen_rtx_LO_SUM (Pmode, force_reg (Pmode, hi), addr);
   5829   new_mem = gen_rtx_MEM (GET_MODE (mem), addr);
   5830   MEM_COPY_ATTRIBUTES (new_mem, mem);
   5831   return new_mem;
   5832 }
   5833 
   5834 /* Print the text for PRINT_OPERAND punctation character CH to FILE.
   5835    The punctuation characters are:
   5836 
   5837    '.'	Print the name of the register with a hard-wired zero (zero or $r0).
   5838    '$'	Print the name of the stack pointer register (sp or $r3).
   5839 
   5840    See also loongarch_init_print_operand_punct.  */
   5841 
   5842 static void
   5843 loongarch_print_operand_punctuation (FILE *file, int ch)
   5844 {
   5845   switch (ch)
   5846     {
   5847     case '.':
   5848       fputs (reg_names[GP_REG_FIRST + 0], file);
   5849       break;
   5850 
   5851     case '$':
   5852       fputs (reg_names[STACK_POINTER_REGNUM], file);
   5853       break;
   5854 
   5855     default:
   5856       gcc_unreachable ();
   5857       break;
   5858     }
   5859 }
   5860 
   5861 /* PRINT_OPERAND prefix LETTER refers to the integer branch instruction
   5862    associated with condition CODE.  Print the condition part of the
   5863    opcode to FILE.  */
   5864 
   5865 static void
   5866 loongarch_print_int_branch_condition (FILE *file, enum rtx_code code,
   5867 				      int letter)
   5868 {
   5869   switch (code)
   5870     {
   5871     case EQ:
   5872     case NE:
   5873     case GT:
   5874     case GE:
   5875     case LT:
   5876     case LE:
   5877     case GTU:
   5878     case GEU:
   5879     case LTU:
   5880     case LEU:
   5881       /* Conveniently, the LoongArch names for these conditions are the same
   5882 	 as their RTL equivalents.  */
   5883       fputs (GET_RTX_NAME (code), file);
   5884       break;
   5885 
   5886     default:
   5887       output_operand_lossage ("'%%%c' is not a valid operand prefix", letter);
   5888       break;
   5889     }
   5890 }
   5891 
   5892 /* Likewise floating-point branches.  */
   5893 
   5894 static void
   5895 loongarch_print_float_branch_condition (FILE *file, enum rtx_code code,
   5896 					int letter)
   5897 {
   5898   switch (code)
   5899     {
   5900     case EQ:
   5901       fputs ("ceqz", file);
   5902       break;
   5903 
   5904     case NE:
   5905       fputs ("cnez", file);
   5906       break;
   5907 
   5908     default:
   5909       output_operand_lossage ("'%%%c' is not a valid operand prefix", letter);
   5910       break;
   5911     }
   5912 }
   5913 
   5914 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P.  */
   5915 
   5916 static bool
   5917 loongarch_print_operand_punct_valid_p (unsigned char code)
   5918 {
   5919   return loongarch_print_operand_punct[code];
   5920 }
   5921 
   5922 /* Return true if a FENCE should be emitted to before a memory access to
   5923    implement the release portion of memory model MODEL.  */
   5924 
   5925 static bool
   5926 loongarch_memmodel_needs_rel_acq_fence (enum memmodel model)
   5927 {
   5928   switch (memmodel_base (model))
   5929     {
   5930       case MEMMODEL_ACQ_REL:
   5931       case MEMMODEL_SEQ_CST:
   5932       case MEMMODEL_RELEASE:
   5933       case MEMMODEL_ACQUIRE:
   5934 	return true;
   5935 
   5936       case MEMMODEL_RELAXED:
   5937 	return false;
   5938 
   5939       default:
   5940 	gcc_unreachable ();
   5941     }
   5942 }
   5943 
   5944 /* Return true if a FENCE should be emitted after a failed CAS to
   5945    implement the acquire semantic of failure_memorder.  */
   5946 
   5947 static bool
   5948 loongarch_cas_failure_memorder_needs_acquire (enum memmodel model)
   5949 {
   5950   switch (memmodel_base (model))
   5951     {
   5952     case MEMMODEL_ACQUIRE:
   5953     case MEMMODEL_ACQ_REL:
   5954     case MEMMODEL_SEQ_CST:
   5955       return true;
   5956 
   5957     case MEMMODEL_RELAXED:
   5958     case MEMMODEL_RELEASE:
   5959       return false;
   5960 
   5961     /* MEMMODEL_CONSUME is deliberately not handled because it's always
   5962        replaced by MEMMODEL_ACQUIRE as at now.  If you see an ICE caused by
   5963        MEMMODEL_CONSUME, read the change (re)introducing it carefully and
   5964        decide what to do.  See PR 59448 and get_memmodel in builtins.cc.  */
   5965     default:
   5966       gcc_unreachable ();
   5967     }
   5968 }
   5969 
   5970 /* Print symbolic operand OP, which is part of a HIGH or LO_SUM
   5971    in context CONTEXT.  HI_RELOC indicates a high-part reloc.  */
   5972 
   5973 static void
   5974 loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part,
   5975 			       bool hi_reloc)
   5976 {
   5977   const char *reloc;
   5978   enum loongarch_symbol_type symbol_type =
   5979     loongarch_classify_symbolic_expression (op);
   5980 
   5981   if (loongarch_symbol_extreme_p (symbol_type))
   5982     gcc_assert (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE);
   5983 
   5984   switch (symbol_type)
   5985     {
   5986     case SYMBOL_PCREL64:
   5987       if (hi64_part)
   5988 	{
   5989 	  reloc = hi_reloc ? "%pc64_hi12" : "%pc64_lo20";
   5990 	  break;
   5991 	}
   5992       /* fall through */
   5993     case SYMBOL_PCREL:
   5994       reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12";
   5995       break;
   5996 
   5997     case SYMBOL_GOT_DISP:
   5998       if (hi64_part)
   5999 	{
   6000 	  if (TARGET_CMODEL_EXTREME)
   6001 	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
   6002 	  else
   6003 	    gcc_unreachable ();
   6004 	}
   6005       else
   6006 	reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12";
   6007       break;
   6008 
   6009     case SYMBOL_TLS_IE:
   6010       if (hi64_part)
   6011 	{
   6012 	  if (TARGET_CMODEL_EXTREME)
   6013 	    reloc = hi_reloc ? "%ie64_pc_hi12" : "%ie64_pc_lo20";
   6014 	  else
   6015 	    gcc_unreachable ();
   6016 	}
   6017       else
   6018 	reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12";
   6019       break;
   6020 
   6021     case SYMBOL_TLS_LE:
   6022       if (hi64_part)
   6023 	{
   6024 	  if (TARGET_CMODEL_EXTREME)
   6025 	    reloc = hi_reloc ? "%le64_hi12" : "%le64_lo20";
   6026 	  else
   6027 	    gcc_unreachable ();
   6028 	}
   6029       else
   6030 	{
   6031 	  if (HAVE_AS_TLS_LE_RELAXATION && !TARGET_CMODEL_EXTREME)
   6032 	    reloc = hi_reloc ? "%le_hi20_r" : "%le_lo12_r";
   6033 	  else
   6034 	    reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
   6035 	}
   6036       break;
   6037 
   6038     case SYMBOL_TLSGD:
   6039       if (hi64_part)
   6040 	{
   6041 	  if (TARGET_CMODEL_EXTREME)
   6042 	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
   6043 	  else
   6044 	    gcc_unreachable ();
   6045 	}
   6046       else
   6047 	reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12";
   6048       break;
   6049 
   6050     case SYMBOL_TLSLDM:
   6051       if (hi64_part)
   6052 	{
   6053 	  if (TARGET_CMODEL_EXTREME)
   6054 	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
   6055 	  else
   6056 	    gcc_unreachable ();
   6057 	}
   6058       else
   6059 	reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12";
   6060       break;
   6061 
   6062     default:
   6063       gcc_unreachable ();
   6064     }
   6065 
   6066   fprintf (file, "%s(", reloc);
   6067   output_addr_const (file, loongarch_strip_unspec_address (op));
   6068   fputc (')', file);
   6069 }
   6070 
   6071 /* Implement TARGET_PRINT_OPERAND.  The LoongArch-specific operand codes are:
   6072 
   6073    'A'	Print a _DB suffix if the memory model requires a release.
   6074    'b'	Print the address of a memory operand, without offset.
   6075    'B'	Print CONST_INT OP element 0 of a replicated CONST_VECTOR
   6076 	  as an unsigned byte [0..255].
   6077    'c'  Print an integer.
   6078    'C'	Print the integer branch condition for comparison OP.
   6079    'd'	Print CONST_INT OP in decimal.
   6080    'E'	Print CONST_INT OP element 0 of a replicated CONST_VECTOR in decimal.
   6081    'F'	Print the FPU branch condition for comparison OP.
   6082    'G'	Print a DBAR insn for CAS failure (with an acquire semantic if
   6083 	needed, otherwise a simple load-load barrier).
   6084    'H'  Print address 52-61bit relocation associated with OP.
   6085    'h'  Print the high-part relocation associated with OP.
   6086    'i'	Print i if the operand is not a register.
   6087    'L'  Print the low-part relocation associated with OP.
   6088    'm'	Print one less than CONST_INT OP in decimal.
   6089    'N'	Print the inverse of the integer branch condition for comparison OP.
   6090    'Q'  Print R_LARCH_RELAX for TLS IE.
   6091    'r'  Print address 12-31bit relocation associated with OP.
   6092    'R'  Print address 32-51bit relocation associated with OP.
   6093    'T'	Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
   6094 	      'z' for (eq:?I ...), 'n' for (ne:?I ...).
   6095    't'	Like 'T', but with the EQ/NE cases reversed
   6096    'F'	Print the FPU branch condition for comparison OP.
   6097    'W'	Print the inverse of the FPU branch condition for comparison OP.
   6098    'w'	Print a LSX register.
   6099    'u'	Print a LASX register.
   6100    'T'	Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
   6101 	      'z' for (eq:?I ...), 'n' for (ne:?I ...).
   6102    't'	Like 'T', but with the EQ/NE cases reversed
   6103    'Y'	Print loongarch_fp_conditions[INTVAL (OP)]
   6104    'Z'	Print OP and a comma for 8CC, otherwise print nothing.
   6105    'z'	Print $0 if OP is zero, otherwise print OP normally.
   6106    'v'	Print the insn size suffix b, h, w or d for vector modes V16QI, V8HI,
   6107 	  V4SI, V2SI, and w, d for vector modes V4SF, V2DF respectively.
   6108    'V'	Print exact log2 of CONST_INT OP element 0 of a replicated
   6109 	  CONST_VECTOR in decimal.
   6110    'W'	Print the inverse of the FPU branch condition for comparison OP.
   6111    'X'	Print CONST_INT OP in hexadecimal format.
   6112    'x'	Print the low 16 bits of CONST_INT OP in hexadecimal format.
   6113    'Y'	Print loongarch_fp_conditions[INTVAL (OP)]
   6114    'y'	Print exact log2 of CONST_INT OP in decimal.
   6115    'Z'	Print OP and a comma for 8CC, otherwise print nothing.
   6116    'z'	Print $0 if OP is zero, otherwise print OP normally.  */
   6117 
   6118 static void
   6119 loongarch_print_operand (FILE *file, rtx op, int letter)
   6120 {
   6121   enum rtx_code code;
   6122 
   6123   if (loongarch_print_operand_punct_valid_p (letter))
   6124     {
   6125       loongarch_print_operand_punctuation (file, letter);
   6126       return;
   6127     }
   6128 
   6129   gcc_assert (op);
   6130   code = GET_CODE (op);
   6131 
   6132   switch (letter)
   6133     {
   6134     case 'A':
   6135       if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op)))
   6136        fputs ("_db", file);
   6137       break;
   6138     case 'E':
   6139       if (GET_CODE (op) == CONST_VECTOR)
   6140 	{
   6141 	  gcc_assert (loongarch_const_vector_same_val_p (op, GET_MODE (op)));
   6142 	  op = CONST_VECTOR_ELT (op, 0);
   6143 	  gcc_assert (CONST_INT_P (op));
   6144 	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
   6145 	}
   6146       else
   6147 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6148       break;
   6149 
   6150 
   6151     case 'c':
   6152       if (CONST_INT_P (op))
   6153 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
   6154       else
   6155 	output_operand_lossage ("unsupported operand for code '%c'", letter);
   6156 
   6157       break;
   6158 
   6159     case 'C':
   6160       loongarch_print_int_branch_condition (file, code, letter);
   6161       break;
   6162 
   6163     case 'd':
   6164       if (CONST_INT_P (op))
   6165 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
   6166       else
   6167 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6168       break;
   6169 
   6170     case 'F':
   6171       loongarch_print_float_branch_condition (file, code, letter);
   6172       break;
   6173 
   6174     case 'G':
   6175       if (loongarch_cas_failure_memorder_needs_acquire (
   6176 	    memmodel_from_int (INTVAL (op))))
   6177 	fputs ("dbar\t0b10100", file);
   6178       else if (!ISA_HAS_LD_SEQ_SA)
   6179 	fputs ("dbar\t0x700", file);
   6180       break;
   6181 
   6182     case 'h':
   6183       if (code == HIGH)
   6184 	op = XEXP (op, 0);
   6185       loongarch_print_operand_reloc (file, op, false /* hi64_part */,
   6186 				     true /* hi_reloc */);
   6187       break;
   6188 
   6189     case 'H':
   6190       loongarch_print_operand_reloc (file, op, true /* hi64_part */,
   6191 				     true /* hi_reloc */);
   6192       break;
   6193 
   6194     case 'i':
   6195       if (code != REG)
   6196 	fputs ("i", file);
   6197       break;
   6198 
   6199     case 'L':
   6200       loongarch_print_operand_reloc (file, op, false /* hi64_part*/,
   6201 				     false /* lo_reloc */);
   6202       break;
   6203     case 'B':
   6204       if (GET_CODE (op) == CONST_VECTOR)
   6205 	{
   6206 	  gcc_assert (loongarch_const_vector_same_val_p (op, GET_MODE (op)));
   6207 	  op = CONST_VECTOR_ELT (op, 0);
   6208 	  gcc_assert (CONST_INT_P (op));
   6209 	  unsigned HOST_WIDE_INT val8 = UINTVAL (op) & GET_MODE_MASK (QImode);
   6210 	  fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, val8);
   6211 	}
   6212       else
   6213 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6214       break;
   6215 
   6216     case 'm':
   6217       if (CONST_INT_P (op))
   6218 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1);
   6219       else
   6220 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6221       break;
   6222 
   6223     case 'N':
   6224       loongarch_print_int_branch_condition (file, reverse_condition (code),
   6225 					    letter);
   6226       break;
   6227 
   6228     case 'Q':
   6229       if (!TARGET_LINKER_RELAXATION)
   6230 	break;
   6231 
   6232       if (code == HIGH)
   6233 	op = XEXP (op, 0);
   6234 
   6235       if (loongarch_classify_symbolic_expression (op) == SYMBOL_TLS_IE)
   6236 	fprintf (file, ".reloc\t.,R_LARCH_RELAX\n\t");
   6237 
   6238       break;
   6239 
   6240     case 'r':
   6241       loongarch_print_operand_reloc (file, op, false /* hi64_part */,
   6242 				     true /* lo_reloc */);
   6243       break;
   6244 
   6245     case 'R':
   6246       loongarch_print_operand_reloc (file, op, true /* hi64_part */,
   6247 				     false /* lo_reloc */);
   6248       break;
   6249 
   6250     case 't':
   6251     case 'T':
   6252       {
   6253 	int truth = (code == NE) == (letter == 'T');
   6254 	fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file);
   6255       }
   6256       break;
   6257 
   6258     case 'V':
   6259       if (CONST_VECTOR_P (op))
   6260 	{
   6261 	  machine_mode mode = GET_MODE_INNER (GET_MODE (op));
   6262 	  unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0));
   6263 	  int vlog2 = exact_log2 (val & GET_MODE_MASK (mode));
   6264 	  if (vlog2 != -1)
   6265 	    fprintf (file, "%d", vlog2);
   6266 	  else
   6267 	    output_operand_lossage ("invalid use of '%%%c'", letter);
   6268 	}
   6269       else
   6270 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6271       break;
   6272 
   6273     case 'W':
   6274       loongarch_print_float_branch_condition (file, reverse_condition (code),
   6275 					      letter);
   6276       break;
   6277 
   6278     case 'x':
   6279       if (CONST_INT_P (op))
   6280 	fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff);
   6281       else
   6282 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6283       break;
   6284 
   6285     case 'X':
   6286       if (CONST_INT_P (op))
   6287 	fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
   6288       else
   6289 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6290       break;
   6291 
   6292     case 'y':
   6293       if (CONST_INT_P (op))
   6294 	{
   6295 	  int val = exact_log2 (INTVAL (op));
   6296 	  if (val != -1)
   6297 	    fprintf (file, "%d", val);
   6298 	  else
   6299 	    output_operand_lossage ("invalid use of '%%%c'", letter);
   6300 	}
   6301       else
   6302 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6303       break;
   6304 
   6305     case 'Y':
   6306       if (code == CONST_INT
   6307 	  && UINTVAL (op) < ARRAY_SIZE (loongarch_fp_conditions))
   6308 	fputs (loongarch_fp_conditions[UINTVAL (op)], file);
   6309       else
   6310 	output_operand_lossage ("'%%%c' is not a valid operand prefix",
   6311 				letter);
   6312       break;
   6313 
   6314     case 'Z':
   6315       loongarch_print_operand (file, op, 0);
   6316       fputc (',', file);
   6317       break;
   6318 
   6319     case 'w':
   6320       if (code == REG && LSX_REG_P (REGNO (op)))
   6321 	fprintf (file, "$vr%s", &reg_names[REGNO (op)][2]);
   6322       else
   6323 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6324       break;
   6325 
   6326     case 'u':
   6327       if (code == REG && LASX_REG_P (REGNO (op)))
   6328 	fprintf (file, "$xr%s", &reg_names[REGNO (op)][2]);
   6329       else
   6330 	output_operand_lossage ("invalid use of '%%%c'", letter);
   6331       break;
   6332 
   6333     case 'v':
   6334       switch (GET_MODE (op))
   6335 	{
   6336 	case E_V16QImode:
   6337 	case E_V32QImode:
   6338 	  fprintf (file, "b");
   6339 	  break;
   6340 	case E_V8HImode:
   6341 	case E_V16HImode:
   6342 	  fprintf (file, "h");
   6343 	  break;
   6344 	case E_V4SImode:
   6345 	case E_V4SFmode:
   6346 	case E_V8SImode:
   6347 	case E_V8SFmode:
   6348 	  fprintf (file, "w");
   6349 	  break;
   6350 	case E_V2DImode:
   6351 	case E_V2DFmode:
   6352 	case E_V4DImode:
   6353 	case E_V4DFmode:
   6354 	  fprintf (file, "d");
   6355 	  break;
   6356 	default:
   6357 	  output_operand_lossage ("invalid use of '%%%c'", letter);
   6358 	}
   6359       break;
   6360 
   6361     default:
   6362       switch (code)
   6363 	{
   6364 	case REG:
   6365 	  {
   6366 	    unsigned int regno = REGNO (op);
   6367 	    if (letter && letter != 'z')
   6368 	      output_operand_lossage ("invalid use of '%%%c'", letter);
   6369 	    fprintf (file, "%s", reg_names[regno]);
   6370 	  }
   6371 	  break;
   6372 
   6373 	case MEM:
   6374 	  if (letter == 'D')
   6375 	    output_address (GET_MODE (op),
   6376 			    plus_constant (Pmode, XEXP (op, 0), 4));
   6377 	  else if (letter == 'b')
   6378 	    {
   6379 	      gcc_assert (REG_P (XEXP (op, 0)));
   6380 	      loongarch_print_operand (file, XEXP (op, 0), 0);
   6381 	    }
   6382 	  else if (letter && letter != 'z')
   6383 	    output_operand_lossage ("invalid use of '%%%c'", letter);
   6384 	  else
   6385 	    output_address (GET_MODE (op), XEXP (op, 0));
   6386 	  break;
   6387 
   6388 	default:
   6389 	  if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
   6390 	    fputs (reg_names[GP_REG_FIRST], file);
   6391 	  else if (letter && letter != 'z')
   6392 	    output_operand_lossage ("invalid use of '%%%c'", letter);
   6393 	  else
   6394 	    output_addr_const (file, loongarch_strip_unspec_address (op));
   6395 	  break;
   6396 	}
   6397     }
   6398 }
   6399 
   6400 /* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
   6401 
   6402 static void
   6403 loongarch_print_operand_address (FILE *file, machine_mode /* mode  */, rtx x)
   6404 {
   6405   struct loongarch_address_info addr;
   6406 
   6407   if (loongarch_classify_address (&addr, x, word_mode, true))
   6408     switch (addr.type)
   6409       {
   6410       case ADDRESS_REG:
   6411 	fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
   6412 	loongarch_print_operand (file, addr.offset, 0);
   6413 	return;
   6414 
   6415       case ADDRESS_REG_REG:
   6416 	fprintf (file, "%s,%s", reg_names[REGNO (addr.reg)],
   6417 				reg_names[REGNO (addr.offset)]);
   6418 	return;
   6419 
   6420       case ADDRESS_LO_SUM:
   6421 	fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
   6422 	loongarch_print_operand_reloc (file, addr.offset, false /* hi64_part */,
   6423 				       false /* hi_reloc */);
   6424 	return;
   6425 
   6426       case ADDRESS_CONST_INT:
   6427 	fprintf (file, "%s,", reg_names[GP_REG_FIRST]);
   6428 	output_addr_const (file, x);
   6429 	return;
   6430 
   6431       case ADDRESS_SYMBOLIC:
   6432 	output_addr_const (file, loongarch_strip_unspec_address (x));
   6433 	return;
   6434       }
   6435   if (CONST_INT_P (x))
   6436     output_addr_const (file, x);
   6437   else
   6438     gcc_unreachable ();
   6439 }
   6440 
   6441 /* Implement TARGET_ASM_SELECT_RTX_SECTION.  */
   6442 
   6443 static section *
   6444 loongarch_select_rtx_section (machine_mode mode, rtx x,
   6445 			      unsigned HOST_WIDE_INT align)
   6446 {
   6447   /* ??? Consider using mergeable small data sections.  */
   6448   if (loongarch_rtx_constant_in_small_data_p (mode))
   6449     return get_named_section (NULL, ".sdata", 0);
   6450 
   6451   return default_elf_select_rtx_section (mode, x, align);
   6452 }
   6453 
   6454 /* Implement TARGET_ASM_FUNCTION_RODATA_SECTION.
   6455 
   6456    The complication here is that jump tables will use absolute addresses,
   6457    and should therefore not be included in the read-only part of a DSO.
   6458    Handle such cases by selecting a normal data section instead of a
   6459    read-only one.  The logic apes that in default_function_rodata_section.  */
   6460 
   6461 static section *
   6462 loongarch_function_rodata_section (tree decl, bool)
   6463 {
   6464   return default_function_rodata_section (decl, false);
   6465 }
   6466 
   6467 /* Implement TARGET_IN_SMALL_DATA_P.  */
   6468 
   6469 static bool
   6470 loongarch_in_small_data_p (const_tree decl)
   6471 {
   6472   int size;
   6473 
   6474   if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
   6475     return false;
   6476 
   6477   if (VAR_P (decl) && DECL_SECTION_NAME (decl) != 0)
   6478     {
   6479       const char *name;
   6480 
   6481       /* Reject anything that isn't in a known small-data section.  */
   6482       name = DECL_SECTION_NAME (decl);
   6483       if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
   6484 	return false;
   6485 
   6486       /* If a symbol is defined externally, the assembler will use the
   6487 	 usual -G rules when deciding how to implement macros.  */
   6488       if (!DECL_EXTERNAL (decl))
   6489 	return true;
   6490     }
   6491 
   6492   /* We have traditionally not treated zero-sized objects as small data,
   6493      so this is now effectively part of the ABI.  */
   6494   size = int_size_in_bytes (TREE_TYPE (decl));
   6495   return size > 0 && size <= g_switch_value;
   6496 }
   6497 
   6498 /* The LoongArch debug format wants all automatic variables and arguments
   6499    to be in terms of the virtual frame pointer (stack pointer before
   6500    any adjustment in the function), while the LoongArch linker wants
   6501    the frame pointer to be the stack pointer after the initial
   6502    adjustment.  So, we do the adjustment here.  The arg pointer (which
   6503    is eliminated) points to the virtual frame pointer, while the frame
   6504    pointer (which may be eliminated) points to the stack pointer after
   6505    the initial adjustments.  */
   6506 
   6507 HOST_WIDE_INT
   6508 loongarch_debugger_offset (rtx addr, HOST_WIDE_INT offset)
   6509 {
   6510   rtx offset2 = const0_rtx;
   6511   rtx reg = eliminate_constant_term (addr, &offset2);
   6512 
   6513   if (offset == 0)
   6514     offset = INTVAL (offset2);
   6515 
   6516   if (reg == stack_pointer_rtx
   6517       || reg == frame_pointer_rtx
   6518       || reg == hard_frame_pointer_rtx)
   6519     {
   6520       offset -= cfun->machine->frame.total_size;
   6521       if (reg == hard_frame_pointer_rtx)
   6522 	offset += cfun->machine->frame.hard_frame_pointer_offset;
   6523     }
   6524 
   6525   return offset;
   6526 }
   6527 
   6528 /* Implement ASM_OUTPUT_EXTERNAL.  */
   6529 
   6530 void
   6531 loongarch_output_external (FILE *file, tree decl, const char *name)
   6532 {
   6533   default_elf_asm_output_external (file, decl, name);
   6534 
   6535   /* We output the name if and only if TREE_SYMBOL_REFERENCED is
   6536      set in order to avoid putting out names that are never really
   6537      used.  */
   6538   if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
   6539     {
   6540       if (loongarch_in_small_data_p (decl))
   6541 	{
   6542 	  /* When using assembler macros, emit .extern directives for
   6543 	     all small-data externs so that the assembler knows how
   6544 	     big they are.
   6545 
   6546 	     In most cases it would be safe (though pointless) to emit
   6547 	     .externs for other symbols too.  One exception is when an
   6548 	     object is within the -G limit but declared by the user to
   6549 	     be in a section other than .sbss or .sdata.  */
   6550 	  fputs ("\t.extern\t", file);
   6551 	  assemble_name (file, name);
   6552 	  fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC "\n",
   6553 		   int_size_in_bytes (TREE_TYPE (decl)));
   6554 	}
   6555     }
   6556 }
   6557 
   6558 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL.  */
   6559 
   6560 static void ATTRIBUTE_UNUSED
   6561 loongarch_output_dwarf_dtprel (FILE *file, int size, rtx x)
   6562 {
   6563   switch (size)
   6564     {
   6565     case 4:
   6566       fputs ("\t.dtprelword\t", file);
   6567       break;
   6568 
   6569     case 8:
   6570       fputs ("\t.dtpreldword\t", file);
   6571       break;
   6572 
   6573     default:
   6574       gcc_unreachable ();
   6575     }
   6576   output_addr_const (file, x);
   6577   fputs ("+0x8000", file);
   6578 }
   6579 
   6580 /* Implement ASM_OUTPUT_ASCII.  */
   6581 
   6582 void
   6583 loongarch_output_ascii (FILE *stream, const char *string, size_t len)
   6584 {
   6585   size_t i;
   6586   int cur_pos;
   6587 
   6588   cur_pos = 17;
   6589   fprintf (stream, "\t.ascii\t\"");
   6590   for (i = 0; i < len; i++)
   6591     {
   6592       int c;
   6593 
   6594       c = (unsigned char) string[i];
   6595       if (ISPRINT (c))
   6596 	{
   6597 	  if (c == '\\' || c == '\"')
   6598 	    {
   6599 	      putc ('\\', stream);
   6600 	      cur_pos++;
   6601 	    }
   6602 	  putc (c, stream);
   6603 	  cur_pos++;
   6604 	}
   6605       else
   6606 	{
   6607 	  fprintf (stream, "\\%03o", c);
   6608 	  cur_pos += 4;
   6609 	}
   6610 
   6611       if (cur_pos > 72 && i + 1 < len)
   6612 	{
   6613 	  cur_pos = 17;
   6614 	  fprintf (stream, "\"\n\t.ascii\t\"");
   6615 	}
   6616     }
   6617   fprintf (stream, "\"\n");
   6618 }
   6619 
   6620 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
   6621 
   6622 static bool
   6623 loongarch_frame_pointer_required (void)
   6624 {
   6625   /* If the function contains dynamic stack allocations, we need to
   6626      use the frame pointer to access the static parts of the frame.  */
   6627   if (cfun->calls_alloca)
   6628     return true;
   6629 
   6630   return false;
   6631 }
   6632 
   6633 /* Implement TARGET_CAN_ELIMINATE.  Make sure that we're not trying
   6634    to eliminate to the wrong hard frame pointer.  */
   6635 
   6636 static bool
   6637 loongarch_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
   6638 {
   6639   return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
   6640 }
   6641 
   6642 /* Implement RETURN_ADDR_RTX.  We do not support moving back to a
   6643    previous frame.  */
   6644 
   6645 rtx
   6646 loongarch_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
   6647 {
   6648   if (count != 0)
   6649     return const0_rtx;
   6650 
   6651   return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
   6652 }
   6653 
   6654 /* Emit code to change the current function's return address to
   6655    ADDRESS.  SCRATCH is available as a scratch register, if needed.
   6656    ADDRESS and SCRATCH are both word-mode GPRs.  */
   6657 
   6658 void
   6659 loongarch_set_return_address (rtx address, rtx scratch)
   6660 {
   6661   rtx slot_address;
   6662 
   6663   gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM));
   6664 
   6665   if (frame_pointer_needed)
   6666     slot_address = loongarch_add_offset (scratch, hard_frame_pointer_rtx,
   6667 					 -UNITS_PER_WORD);
   6668   else
   6669     slot_address = loongarch_add_offset (scratch, stack_pointer_rtx,
   6670 					 cfun->machine->frame.gp_sp_offset);
   6671 
   6672   loongarch_emit_move (gen_frame_mem (GET_MODE (address), slot_address),
   6673 		       address);
   6674 }
   6675 
   6676 /* Return true if register REGNO can store a value of mode MODE.
   6677    The result of this function is cached in loongarch_hard_regno_mode_ok.  */
   6678 
   6679 static bool
   6680 loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode)
   6681 {
   6682   unsigned int size;
   6683   enum mode_class mclass;
   6684 
   6685   if (mode == FCCmode)
   6686     return FCC_REG_P (regno) || GP_REG_P (regno) || FP_REG_P (regno);
   6687 
   6688   size = GET_MODE_SIZE (mode);
   6689   mclass = GET_MODE_CLASS (mode);
   6690 
   6691   if (GP_REG_P (regno) && !LSX_SUPPORTED_MODE_P (mode)
   6692       && !LASX_SUPPORTED_MODE_P (mode))
   6693     return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD;
   6694 
   6695   /* For LSX, allow TImode and 128-bit vector modes in all FPR.  */
   6696   if (FP_REG_P (regno) && LSX_SUPPORTED_MODE_P (mode))
   6697     return true;
   6698 
   6699   /* FIXED ME: For LASX, allow TImode and 256-bit vector modes in all FPR.  */
   6700   if (FP_REG_P (regno) && LASX_SUPPORTED_MODE_P (mode))
   6701     return true;
   6702 
   6703   if (FP_REG_P (regno))
   6704     {
   6705       if (mclass == MODE_FLOAT
   6706 	  || mclass == MODE_COMPLEX_FLOAT
   6707 	  || mclass == MODE_VECTOR_FLOAT)
   6708 	return size <= UNITS_PER_HWFPVALUE;
   6709 
   6710       /* Allow integer modes that fit into a single register.  We need
   6711 	 to put integers into FPRs when using instructions like CVT
   6712 	 and TRUNC.  There's no point allowing sizes smaller than a word,
   6713 	 because the FPU has no appropriate load/store instructions.  */
   6714       if (mclass == MODE_INT)
   6715 	return size >= MIN_UNITS_PER_WORD && size <= UNITS_PER_FP_REG;
   6716     }
   6717 
   6718   return false;
   6719 }
   6720 
   6721 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
   6722 
   6723 static bool
   6724 loongarch_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
   6725 {
   6726   return loongarch_hard_regno_mode_ok_p[mode][regno];
   6727 }
   6728 
   6729 
   6730 static bool
   6731 loongarch_hard_regno_call_part_clobbered (unsigned int,
   6732 					  unsigned int regno, machine_mode mode)
   6733 {
   6734   if (ISA_HAS_LSX && FP_REG_P (regno) && GET_MODE_SIZE (mode) > 8)
   6735     return true;
   6736 
   6737   return false;
   6738 }
   6739 
   6740 /* Implement TARGET_HARD_REGNO_NREGS.  */
   6741 
   6742 static unsigned int
   6743 loongarch_hard_regno_nregs (unsigned int regno, machine_mode mode)
   6744 {
   6745   if (FCC_REG_P (regno))
   6746     /* The size of FP status registers is always 4, because they only hold
   6747        FCCmode values, and FCCmode is always considered to be 4 bytes wide.  */
   6748     return (GET_MODE_SIZE (mode) + 3) / 4;
   6749 
   6750   if (FP_REG_P (regno))
   6751     {
   6752       if (LSX_SUPPORTED_MODE_P (mode))
   6753 	return 1;
   6754 
   6755       if (LASX_SUPPORTED_MODE_P (mode))
   6756 	return 1;
   6757 
   6758       return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
   6759     }
   6760 
   6761   /* All other registers are word-sized.  */
   6762   return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   6763 }
   6764 
   6765 /* Implement CLASS_MAX_NREGS, taking the maximum of the cases
   6766    in loongarch_hard_regno_nregs.  */
   6767 
   6768 int
   6769 loongarch_class_max_nregs (enum reg_class rclass, machine_mode mode)
   6770 {
   6771   int size;
   6772   HARD_REG_SET left;
   6773 
   6774   size = 0x8000;
   6775   left = reg_class_contents[rclass];
   6776   if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FCC_REGS]))
   6777     {
   6778       if (loongarch_hard_regno_mode_ok (FCC_REG_FIRST, mode))
   6779 	size = MIN (size, 4);
   6780 
   6781       left &= ~reg_class_contents[FCC_REGS];
   6782     }
   6783   if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS]))
   6784     {
   6785       if (loongarch_hard_regno_mode_ok (FP_REG_FIRST, mode))
   6786 	{
   6787 	  /* Fixed me.  */
   6788 	  if (LASX_SUPPORTED_MODE_P (mode))
   6789 	    size = MIN (size, UNITS_PER_LASX_REG);
   6790 	  else if (LSX_SUPPORTED_MODE_P (mode))
   6791 	    size = MIN (size, UNITS_PER_LSX_REG);
   6792 	  else
   6793 	    size = MIN (size, UNITS_PER_FP_REG);
   6794 	}
   6795       left &= ~reg_class_contents[FP_REGS];
   6796     }
   6797   if (!hard_reg_set_empty_p (left))
   6798     size = MIN (size, UNITS_PER_WORD);
   6799   return (GET_MODE_SIZE (mode) + size - 1) / size;
   6800 }
   6801 
   6802 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
   6803 
   6804 static bool
   6805 loongarch_can_change_mode_class (machine_mode from, machine_mode to,
   6806 				 reg_class_t rclass)
   6807 {
   6808   /* Allow conversions between different LSX/LASX vector modes.  */
   6809   if (LASX_SUPPORTED_MODE_P (from) && LASX_SUPPORTED_MODE_P (to))
   6810     return true;
   6811 
   6812   /* Allow conversions between different LSX vector modes.  */
   6813   if (LSX_SUPPORTED_MODE_P (from) && LSX_SUPPORTED_MODE_P (to))
   6814     return true;
   6815 
   6816   /* Allow conversion between LSX vector mode and scalar fp mode. */
   6817   if ((LSX_SUPPORTED_MODE_P (from) && SCALAR_FLOAT_MODE_P (to))
   6818       || ((SCALAR_FLOAT_MODE_P (from) && LSX_SUPPORTED_MODE_P (to))))
   6819     return true;
   6820 
   6821   return !reg_classes_intersect_p (FP_REGS, rclass);
   6822 }
   6823 
   6824 /* Return true if moves in mode MODE can use the FPU's fmov.fmt instruction,
   6825 */
   6826 
   6827 static bool
   6828 loongarch_mode_ok_for_mov_fmt_p (machine_mode mode)
   6829 {
   6830   switch (mode)
   6831     {
   6832     case E_FCCmode:
   6833     case E_SFmode:
   6834       return TARGET_HARD_FLOAT;
   6835 
   6836     case E_DFmode:
   6837       return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT;
   6838 
   6839     default:
   6840       return ISA_HAS_LASX ? LASX_SUPPORTED_MODE_P (mode)
   6841 	: LSX_SUPPORTED_MODE_P (mode);
   6842     }
   6843 }
   6844 
   6845 /* Implement TARGET_MODES_TIEABLE_P.  */
   6846 
   6847 static bool
   6848 loongarch_modes_tieable_p (machine_mode mode1, machine_mode mode2)
   6849 {
   6850   /* FPRs allow no mode punning, so it's not worth tying modes if we'd
   6851      prefer to put one of them in FPRs.  */
   6852   return (mode1 == mode2
   6853 	  || (!loongarch_mode_ok_for_mov_fmt_p (mode1)
   6854 	      && !loongarch_mode_ok_for_mov_fmt_p (mode2)));
   6855 }
   6856 
   6857 /* Implement TARGET_PREFERRED_RELOAD_CLASS.  */
   6858 
   6859 static reg_class_t
   6860 loongarch_preferred_reload_class (rtx x, reg_class_t rclass)
   6861 {
   6862   if (reg_class_subset_p (FP_REGS, rclass)
   6863       && loongarch_mode_ok_for_mov_fmt_p (GET_MODE (x)))
   6864     return FP_REGS;
   6865 
   6866   if (reg_class_subset_p (GR_REGS, rclass))
   6867     rclass = GR_REGS;
   6868 
   6869   return rclass;
   6870 }
   6871 
   6872 /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation.
   6873    Return a "canonical" class to represent it in later calculations.  */
   6874 
   6875 static reg_class_t
   6876 loongarch_canonicalize_move_class (reg_class_t rclass)
   6877 {
   6878   if (reg_class_subset_p (rclass, GENERAL_REGS))
   6879     rclass = GENERAL_REGS;
   6880 
   6881   return rclass;
   6882 }
   6883 
   6884 /* Return the cost of moving a value from a register of class FROM to a GPR.
   6885    Return 0 for classes that are unions of other classes handled by this
   6886    function.  */
   6887 
   6888 static int
   6889 loongarch_move_to_gpr_cost (reg_class_t from)
   6890 {
   6891   switch (from)
   6892     {
   6893     case GENERAL_REGS:
   6894       /* MOVE macro.  */
   6895       return 2;
   6896 
   6897     case FP_REGS:
   6898       /* MOVFR2GR, etc.  */
   6899       return 4;
   6900 
   6901     case FCC_REGS:
   6902       return loongarch_cost->movcf2gr;
   6903 
   6904     default:
   6905       return 0;
   6906     }
   6907 }
   6908 
   6909 /* Return the cost of moving a value from a GPR to a register of class TO.
   6910    Return 0 for classes that are unions of other classes handled by this
   6911    function.  */
   6912 
   6913 static int
   6914 loongarch_move_from_gpr_cost (reg_class_t to)
   6915 {
   6916   switch (to)
   6917     {
   6918     case GENERAL_REGS:
   6919       /*MOVE macro.  */
   6920       return 2;
   6921 
   6922     case FP_REGS:
   6923       /* MOVGR2FR, etc.  */
   6924       return 4;
   6925 
   6926     case FCC_REGS:
   6927       return loongarch_cost->movgr2cf;
   6928 
   6929     default:
   6930       return 0;
   6931     }
   6932 }
   6933 
   6934 /* Implement TARGET_REGISTER_MOVE_COST.  Return 0 for classes that are the
   6935    maximum of the move costs for subclasses; regclass will work out
   6936    the maximum for us.  */
   6937 
   6938 static int
   6939 loongarch_register_move_cost (machine_mode mode, reg_class_t from,
   6940 			      reg_class_t to)
   6941 {
   6942   reg_class_t dregs;
   6943   int cost1, cost2;
   6944 
   6945   from = loongarch_canonicalize_move_class (from);
   6946   to = loongarch_canonicalize_move_class (to);
   6947 
   6948   /* Handle moves that can be done without using general-purpose registers.  */
   6949   if (from == FP_REGS)
   6950     {
   6951       if (to == FP_REGS && loongarch_mode_ok_for_mov_fmt_p (mode))
   6952 	/* FMOV.FMT.  */
   6953 	return 4;
   6954     }
   6955 
   6956   /* Handle cases in which only one class deviates from the ideal.  */
   6957   dregs = GENERAL_REGS;
   6958   if (from == dregs)
   6959     return loongarch_move_from_gpr_cost (to);
   6960   if (to == dregs)
   6961     return loongarch_move_to_gpr_cost (from);
   6962 
   6963   /* fcc -> fcc, fcc -> fpr, or fpr -> fcc. */
   6964   if (from == FCC_REGS || to == FCC_REGS)
   6965     return COSTS_N_INSNS (from == to ? 2 : 1);
   6966 
   6967   /* Handles cases that require a GPR temporary.  */
   6968   cost1 = loongarch_move_to_gpr_cost (from);
   6969   if (cost1 != 0)
   6970     {
   6971       cost2 = loongarch_move_from_gpr_cost (to);
   6972       if (cost2 != 0)
   6973 	return cost1 + cost2;
   6974     }
   6975 
   6976   return 0;
   6977 }
   6978 
   6979 /* Implement TARGET_MEMORY_MOVE_COST.  */
   6980 
   6981 static int
   6982 loongarch_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in)
   6983 {
   6984   return (loongarch_cost->memory_latency
   6985 	  + memory_move_secondary_cost (mode, rclass, in));
   6986 }
   6987 
   6988 /* Return the register class required for a secondary register when
   6989    copying between one of the registers in RCLASS and value X, which
   6990    has mode MODE.  X is the source of the move if IN_P, otherwise it
   6991    is the destination.  Return NO_REGS if no secondary register is
   6992    needed.  */
   6993 
   6994 static reg_class_t
   6995 loongarch_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
   6996 			    reg_class_t rclass, machine_mode mode,
   6997 			    secondary_reload_info *sri ATTRIBUTE_UNUSED)
   6998 {
   6999   int regno;
   7000 
   7001   regno = true_regnum (x);
   7002 
   7003   if (mode == FCCmode)
   7004     {
   7005       if (reg_class_subset_p (rclass, FCC_REGS) && !FP_REG_P (regno))
   7006 	{
   7007 	  if (FCC_REG_P (regno))
   7008 	    return FP_REGS;
   7009 
   7010 	  auto fn = in_p ? loongarch_move_from_gpr_cost
   7011 			 : loongarch_move_to_gpr_cost;
   7012 
   7013 	  if (fn (FCC_REGS) > fn (FP_REGS) + COSTS_N_INSNS (1))
   7014 	    return FP_REGS;
   7015 
   7016 	  return GP_REG_P (regno) ? NO_REGS : GR_REGS;
   7017 	}
   7018 
   7019       if (reg_class_subset_p (rclass, GR_REGS) && FCC_REG_P (regno))
   7020 	{
   7021 	  auto fn = in_p ? loongarch_move_to_gpr_cost
   7022 			 : loongarch_move_from_gpr_cost;
   7023 
   7024 	  if (fn (FCC_REGS) > fn (FP_REGS) + COSTS_N_INSNS (1))
   7025 	    return FP_REGS;
   7026 
   7027 	  return NO_REGS;
   7028 	}
   7029 
   7030       if (reg_class_subset_p (rclass, FP_REGS)
   7031 	  && (regno == -1 || MEM_P (x)))
   7032 	return GR_REGS;
   7033 
   7034       return NO_REGS;
   7035     }
   7036 
   7037   if (reg_class_subset_p (rclass, FP_REGS))
   7038     {
   7039       if (regno < 0
   7040 	  || (MEM_P (x)
   7041 	      && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)))
   7042 	/* In this case we can use lwc1, swc1, ldc1 or sdc1.  We'll use
   7043 	   pairs of lwc1s and swc1s if ldc1 and sdc1 are not supported.  */
   7044 	return NO_REGS;
   7045 
   7046       if (MEM_P (x) && LSX_SUPPORTED_MODE_P (mode))
   7047 	/* In this case we can use LSX LD.* and ST.*.  */
   7048 	return NO_REGS;
   7049 
   7050       if (GP_REG_P (regno) || x == CONST0_RTX (mode))
   7051 	/* In this case we can use movgr2fr.s, movfr2gr.s, movgr2fr.d or
   7052 	 * movfr2gr.d.  */
   7053 	return NO_REGS;
   7054 
   7055       if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (mode, x))
   7056 	/* We can force the constant to memory and use fld.s
   7057 	   and fld.d.  As above, we will use pairs of lwc1s if
   7058 	   ldc1 is not supported.  */
   7059 	return NO_REGS;
   7060 
   7061       if (FP_REG_P (regno) && loongarch_mode_ok_for_mov_fmt_p (mode))
   7062 	/* In this case we can use fmov.{s/d}.  */
   7063 	return NO_REGS;
   7064 
   7065       /* Otherwise, we need to reload through an integer register.  */
   7066       return GR_REGS;
   7067     }
   7068   if (FP_REG_P (regno))
   7069     return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS;
   7070 
   7071   return NO_REGS;
   7072 }
   7073 
   7074 /* Implement TARGET_VALID_POINTER_MODE.  */
   7075 
   7076 static bool
   7077 loongarch_valid_pointer_mode (scalar_int_mode mode)
   7078 {
   7079   return mode == SImode || (TARGET_64BIT && mode == DImode);
   7080 }
   7081 
   7082 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P.  */
   7083 
   7084 static bool
   7085 loongarch_vector_mode_supported_p (machine_mode mode)
   7086 {
   7087   return ISA_HAS_LASX ? LASX_SUPPORTED_MODE_P (mode)
   7088     : LSX_SUPPORTED_MODE_P (mode);
   7089 }
   7090 
   7091 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
   7092 
   7093 static bool
   7094 loongarch_scalar_mode_supported_p (scalar_mode mode)
   7095 {
   7096   if (ALL_FIXED_POINT_MODE_P (mode)
   7097       && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
   7098     return true;
   7099 
   7100   return default_scalar_mode_supported_p (mode);
   7101 }
   7102 
   7103 /* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
   7104 
   7105 static machine_mode
   7106 loongarch_preferred_simd_mode (scalar_mode mode)
   7107 {
   7108   if (!ISA_HAS_LSX)
   7109     return word_mode;
   7110 
   7111   switch (mode)
   7112     {
   7113     case E_QImode:
   7114       return ISA_HAS_LASX ? E_V32QImode : E_V16QImode;
   7115     case E_HImode:
   7116       return ISA_HAS_LASX ? E_V16HImode : E_V8HImode;
   7117     case E_SImode:
   7118       return ISA_HAS_LASX ? E_V8SImode : E_V4SImode;
   7119     case E_DImode:
   7120       return ISA_HAS_LASX ? E_V4DImode : E_V2DImode;
   7121 
   7122     case E_SFmode:
   7123       return ISA_HAS_LASX ? E_V8SFmode : E_V4SFmode;
   7124 
   7125     case E_DFmode:
   7126       return ISA_HAS_LASX ? E_V4DFmode : E_V2DFmode;
   7127 
   7128     default:
   7129       break;
   7130     }
   7131   return word_mode;
   7132 }
   7133 
   7134 static unsigned int
   7135 loongarch_autovectorize_vector_modes (vector_modes *modes, bool)
   7136 {
   7137   if (ISA_HAS_LASX)
   7138     {
   7139       modes->safe_push (V32QImode);
   7140       modes->safe_push (V16QImode);
   7141     }
   7142   else if (ISA_HAS_LSX)
   7143     {
   7144       modes->safe_push (V16QImode);
   7145     }
   7146 
   7147   return 0;
   7148 }
   7149 
   7150 /* Return the assembly code for INSN, which has the operands given by
   7151    OPERANDS, and which branches to OPERANDS[0] if some condition is true.
   7152    BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0]
   7153    is in range of a direct branch.  BRANCH_IF_FALSE is an inverted
   7154    version of BRANCH_IF_TRUE.  */
   7155 
   7156 const char *
   7157 loongarch_output_conditional_branch (rtx_insn *insn, rtx *operands,
   7158 				     const char *branch_if_true,
   7159 				     const char *branch_if_false)
   7160 {
   7161   unsigned int length;
   7162   rtx taken;
   7163 
   7164   gcc_assert (LABEL_P (operands[0]));
   7165 
   7166   length = get_attr_length (insn);
   7167   if (length <= 4)
   7168     {
   7169       return branch_if_true;
   7170     }
   7171 
   7172   /* Generate a reversed branch around a direct jump.  */
   7173   rtx_code_label *not_taken = gen_label_rtx ();
   7174   taken = operands[0];
   7175 
   7176   /* Generate the reversed branch to NOT_TAKEN.  */
   7177   operands[0] = not_taken;
   7178   output_asm_insn (branch_if_false, operands);
   7179 
   7180   output_asm_insn ("b\t%0", &taken);
   7181 
   7182   /* Output NOT_TAKEN.  */
   7183   targetm.asm_out.internal_label (asm_out_file, "L",
   7184 				  CODE_LABEL_NUMBER (not_taken));
   7185   return "";
   7186 }
   7187 
   7188 /* Return the assembly code for INSN, which branches to OPERANDS[0]
   7189    if some equality condition is true.  The condition is given by
   7190    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of
   7191    OPERANDS[1].  OPERANDS[2] is the comparison's first operand;
   7192    OPERANDS[3] is the second operand and may be zero or a register.  */
   7193 
   7194 const char *
   7195 loongarch_output_equal_conditional_branch (rtx_insn *insn, rtx *operands,
   7196 					   bool inverted_p)
   7197 {
   7198   const char *branch[2];
   7199   if (operands[3] == const0_rtx)
   7200     {
   7201       branch[!inverted_p] = LARCH_BRANCH ("b%C1z", "%2,%0");
   7202       branch[inverted_p] = LARCH_BRANCH ("b%N1z", "%2,%0");
   7203     }
   7204   else
   7205     {
   7206       branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%z3,%0");
   7207       branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%z3,%0");
   7208     }
   7209 
   7210   return loongarch_output_conditional_branch (insn, operands, branch[1],
   7211 					      branch[0]);
   7212 }
   7213 
   7214 /* Return the assembly code for INSN, which branches to OPERANDS[0]
   7215    if some ordering condition is true.  The condition is given by
   7216    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of
   7217    OPERANDS[1].  OPERANDS[2] is the comparison's first operand;
   7218    OPERANDS[3] is the second operand and may be zero or a register.  */
   7219 
   7220 const char *
   7221 loongarch_output_order_conditional_branch (rtx_insn *insn, rtx *operands,
   7222 					   bool inverted_p)
   7223 {
   7224   const char *branch[2];
   7225 
   7226   /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true.
   7227      Make BRANCH[0] branch on the inverse condition.  */
   7228   if (operands[3] != const0_rtx)
   7229     {
   7230       /* Handle degenerate cases that should not, but do, occur.  */
   7231       if (REGNO (operands[2]) == REGNO (operands[3]))
   7232 	{
   7233 	  switch (GET_CODE (operands[1]))
   7234 	    {
   7235 	    case LT:
   7236 	    case LTU:
   7237 	    case GT:
   7238 	    case GTU:
   7239 	      inverted_p = !inverted_p;
   7240 	      /* Fall through.  */
   7241 	    case LE:
   7242 	    case LEU:
   7243 	    case GE:
   7244 	    case GEU:
   7245 	      branch[!inverted_p] = LARCH_BRANCH ("b", "%0");
   7246 	      branch[inverted_p] = "\t# branch never";
   7247 	      break;
   7248 	    default:
   7249 	      gcc_unreachable ();
   7250 	    }
   7251 	}
   7252       else
   7253 	{
   7254 	  switch (GET_CODE (operands[1]))
   7255 	    {
   7256 	    case LE:
   7257 	    case LEU:
   7258 	    case GT:
   7259 	    case GTU:
   7260 	    case LT:
   7261 	    case LTU:
   7262 	    case GE:
   7263 	    case GEU:
   7264 	      branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%3,%0");
   7265 	      branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%3,%0");
   7266 	      break;
   7267 	    default:
   7268 	      gcc_unreachable ();
   7269 	    }
   7270 	}
   7271     }
   7272   else
   7273     {
   7274       switch (GET_CODE (operands[1]))
   7275 	{
   7276 	  /* These cases are equivalent to comparisons against zero.  */
   7277 	case LEU:
   7278 	case GTU:
   7279 	case LTU:
   7280 	case GEU:
   7281 	case LE:
   7282 	case GT:
   7283 	case LT:
   7284 	case GE:
   7285 	  branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,$r0,%0");
   7286 	  branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,$r0,%0");
   7287 	  break;
   7288 	default:
   7289 	  gcc_unreachable ();
   7290 	}
   7291     }
   7292   return loongarch_output_conditional_branch (insn, operands, branch[1],
   7293 					      branch[0]);
   7294 }
   7295 
   7296 /* Return the assembly code for DIV.{W/D} instruction DIVISION, which has
   7297    the operands given by OPERANDS.  Add in a divide-by-zero check if needed.
   7298    */
   7299 
   7300 const char *
   7301 loongarch_output_division (const char *division, rtx *operands)
   7302 {
   7303   const char *s;
   7304 
   7305   s = division;
   7306   if (loongarch_check_zero_div_p ())
   7307     {
   7308       output_asm_insn (s, operands);
   7309       s = "bne\t%2,%.,1f\n\tbreak\t7\n1:";
   7310     }
   7311   return s;
   7312 }
   7313 
   7314 /* Return the assembly code for LSX DIV_{S,U}.DF or MOD_{S,U}.DF instructions,
   7315    which has the operands given by OPERANDS.  Add in a divide-by-zero check
   7316    if needed.  */
   7317 
   7318 const char *
   7319 loongarch_lsx_output_division (const char *division, rtx *operands)
   7320 {
   7321   const char *s;
   7322   machine_mode mode = GET_MODE (*operands);
   7323 
   7324   s = division;
   7325   if (TARGET_CHECK_ZERO_DIV)
   7326     {
   7327       if (ISA_HAS_LASX && GET_MODE_SIZE (mode) == 32)
   7328 	{
   7329 	  output_asm_insn ("xvsetallnez.%v0\t$fcc7,%u2",operands);
   7330 	  output_asm_insn (s, operands);
   7331 	  output_asm_insn ("bcnez\t$fcc7,1f", operands);
   7332 	}
   7333       else if (ISA_HAS_LSX)
   7334 	{
   7335 	  output_asm_insn ("vsetallnez.%v0\t$fcc7,%w2",operands);
   7336 	  output_asm_insn (s, operands);
   7337 	  output_asm_insn ("bcnez\t$fcc7,1f", operands);
   7338 	}
   7339       s = "break\t7\n1:";
   7340     }
   7341   return s;
   7342 }
   7343 
   7344 /* Implement TARGET_SCHED_ADJUST_COST.  We assume that anti and output
   7345    dependencies have no cost.  */
   7346 
   7347 static int
   7348 loongarch_adjust_cost (rtx_insn *, int dep_type, rtx_insn *, int cost,
   7349 		       unsigned int)
   7350 {
   7351   if (dep_type != 0 && (dep_type != REG_DEP_OUTPUT))
   7352     return 0;
   7353   return cost;
   7354 }
   7355 
   7356 /* Return the number of instructions that can be issued per cycle.  */
   7357 
   7358 static int
   7359 loongarch_issue_rate (void)
   7360 {
   7361   if ((unsigned long) la_target.cpu_tune < N_TUNE_TYPES)
   7362     return loongarch_cpu_issue_rate[la_target.cpu_tune];
   7363   else
   7364     return 1;
   7365 }
   7366 
   7367 /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD.  This should
   7368    be as wide as the scheduling freedom in the DFA.  */
   7369 
   7370 static int
   7371 loongarch_multipass_dfa_lookahead (void)
   7372 {
   7373   if ((unsigned long) la_target.cpu_tune < N_ARCH_TYPES)
   7374     return loongarch_cpu_multipass_dfa_lookahead[la_target.cpu_tune];
   7375   else
   7376     return 0;
   7377 }
   7378 
   7379 /* Implement TARGET_SCHED_REORDER.  */
   7380 
   7381 static int
   7382 loongarch_sched_reorder (FILE *file ATTRIBUTE_UNUSED,
   7383 			 int verbose ATTRIBUTE_UNUSED,
   7384 			 rtx_insn **ready ATTRIBUTE_UNUSED,
   7385 			 int *nreadyp ATTRIBUTE_UNUSED,
   7386 			 int cycle ATTRIBUTE_UNUSED)
   7387 {
   7388   return loongarch_issue_rate ();
   7389 }
   7390 
   7391 /* Implement TARGET_SCHED_REORDER2.  */
   7392 
   7393 static int
   7394 loongarch_sched_reorder2 (FILE *file ATTRIBUTE_UNUSED,
   7395 			  int verbose ATTRIBUTE_UNUSED,
   7396 			  rtx_insn **ready ATTRIBUTE_UNUSED,
   7397 			  int *nreadyp ATTRIBUTE_UNUSED,
   7398 			  int cycle ATTRIBUTE_UNUSED)
   7399 {
   7400   return cached_can_issue_more;
   7401 }
   7402 
   7403 /* Implement TARGET_SCHED_INIT.  */
   7404 
   7405 static void
   7406 loongarch_sched_init (FILE *file ATTRIBUTE_UNUSED,
   7407 		      int verbose ATTRIBUTE_UNUSED,
   7408 		      int max_ready ATTRIBUTE_UNUSED)
   7409 {}
   7410 
   7411 /* Implement TARGET_SCHED_VARIABLE_ISSUE.  */
   7412 
   7413 static int
   7414 loongarch_variable_issue (FILE *file ATTRIBUTE_UNUSED,
   7415 			  int verbose ATTRIBUTE_UNUSED, rtx_insn *insn,
   7416 			  int more)
   7417 {
   7418   /* Ignore USEs and CLOBBERs; don't count them against the issue rate.  */
   7419   if (USEFUL_INSN_P (insn))
   7420     {
   7421       if (get_attr_type (insn) != TYPE_GHOST)
   7422 	more--;
   7423     }
   7424 
   7425   /* Instructions of type 'multi' should all be split before
   7426      the second scheduling pass.  */
   7427   gcc_assert (!reload_completed
   7428 	      || recog_memoized (insn) < 0
   7429 	      || get_attr_type (insn) != TYPE_MULTI);
   7430 
   7431   cached_can_issue_more = more;
   7432   return more;
   7433 }
   7434 
   7435 /* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY),
   7436    return the first operand of the associated PREF or PREFX insn.  */
   7437 
   7438 rtx
   7439 loongarch_prefetch_cookie (rtx write, rtx locality)
   7440 {
   7441   /* store_streamed / load_streamed.  */
   7442   if (INTVAL (locality) <= 0)
   7443     return GEN_INT (INTVAL (write) + 4);
   7444 
   7445   /* store / load.  */
   7446   if (INTVAL (locality) <= 2)
   7447     return write;
   7448 
   7449   /* store_retained / load_retained.  */
   7450   return GEN_INT (INTVAL (write) + 6);
   7451 }
   7452 
   7453 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
   7454    in order to avoid duplicating too much logic from elsewhere.  */
   7455 
   7456 static void
   7457 loongarch_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   7458 			   HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
   7459 			   tree function)
   7460 {
   7461   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
   7462   rtx this_rtx, temp1, temp2, fnaddr;
   7463   rtx_insn *insn;
   7464   bool use_sibcall_p;
   7465 
   7466   /* Pretend to be a post-reload pass while generating rtl.  */
   7467   reload_completed = 1;
   7468 
   7469   /* Mark the end of the (empty) prologue.  */
   7470   emit_note (NOTE_INSN_PROLOGUE_END);
   7471 
   7472   /* Determine if we can use a sibcall to call FUNCTION directly.  */
   7473   fnaddr = XEXP (DECL_RTL (function), 0);
   7474   use_sibcall_p = const_call_insn_operand (fnaddr, Pmode);
   7475 
   7476   /* We need two temporary registers in some cases.  */
   7477   temp1 = gen_rtx_REG (Pmode, 12);
   7478   temp2 = gen_rtx_REG (Pmode, 13);
   7479 
   7480   /* Find out which register contains the "this" pointer.  */
   7481   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
   7482     this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
   7483   else
   7484     this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST);
   7485 
   7486   /* Add DELTA to THIS_RTX.  */
   7487   if (delta != 0)
   7488     {
   7489       rtx offset = GEN_INT (delta);
   7490       if (!IMM12_OPERAND (delta))
   7491 	{
   7492 	  loongarch_emit_move (temp1, offset);
   7493 	  offset = temp1;
   7494 	}
   7495       emit_insn (gen_add3_insn (this_rtx, this_rtx, offset));
   7496     }
   7497 
   7498   /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
   7499   if (vcall_offset != 0)
   7500     {
   7501       rtx addr;
   7502 
   7503       /* Set TEMP1 to *THIS_RTX.  */
   7504       loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx));
   7505 
   7506       /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET.  */
   7507       addr = loongarch_add_offset (temp2, temp1, vcall_offset);
   7508 
   7509       /* Load the offset and add it to THIS_RTX.  */
   7510       loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, addr));
   7511       emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1));
   7512     }
   7513 
   7514   /* Jump to the target function.  Use a sibcall if direct jumps are
   7515      allowed, otherwise load the address into a register first.  */
   7516   if (use_sibcall_p)
   7517     {
   7518       /* If TARGET_CMODEL_EXTREME, we cannot do a direct jump at all
   7519 	 and const_call_insn_operand should have returned false.  */
   7520       gcc_assert (!TARGET_CMODEL_EXTREME);
   7521 
   7522       insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
   7523       SIBLING_CALL_P (insn) = 1;
   7524     }
   7525   else
   7526     {
   7527       if (!TARGET_CMODEL_EXTREME)
   7528 	loongarch_emit_move (temp1, fnaddr);
   7529       else if (la_opt_explicit_relocs == EXPLICIT_RELOCS_NONE)
   7530 	emit_insn (gen_movdi_symbolic_off64 (temp1, fnaddr, temp2));
   7531       else
   7532 	{
   7533 	  emit_insn (gen_la_pcrel64_two_parts (temp1, temp2, fnaddr));
   7534 	  emit_move_insn (temp1, gen_rtx_PLUS (Pmode, temp1, temp2));
   7535 	}
   7536 
   7537       emit_jump_insn (gen_indirect_jump (temp1));
   7538     }
   7539 
   7540   /* Run just enough of rest_of_compilation.  This sequence was
   7541      "borrowed" from alpha.c.  */
   7542   insn = get_insns ();
   7543   split_all_insns_noflow ();
   7544   shorten_branches (insn);
   7545   assemble_start_function (thunk_fndecl, fnname);
   7546   final_start_function (insn, file, 1);
   7547   final (insn, file, 1);
   7548   final_end_function ();
   7549   assemble_end_function (thunk_fndecl, fnname);
   7550 
   7551   /* Stop pretending to be a post-reload pass.  */
   7552   reload_completed = 0;
   7553 }
   7554 
   7555 /* Allocate a chunk of memory for per-function machine-dependent data.  */
   7556 
   7557 static struct machine_function *
   7558 loongarch_init_machine_status (void)
   7559 {
   7560   return ggc_cleared_alloc<machine_function> ();
   7561 }
   7562 
   7563 static void
   7564 loongarch_global_init (void)
   7565 {
   7566   /* Initialize loongarch_print_operand_punct.  */
   7567   for (const char *p = ".$"; *p; p++)
   7568     loongarch_print_operand_punct[(unsigned char) *p] = true;
   7569 
   7570   /* Set up array to map GCC register number to debug register number.
   7571      Ignore the special purpose register numbers.  */
   7572   for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
   7573     {
   7574       if (GP_REG_P (i) || FP_REG_P (i))
   7575 	loongarch_dwarf_regno[i] = i;
   7576       else
   7577 	loongarch_dwarf_regno[i] = INVALID_REGNUM;
   7578     }
   7579 
   7580   /* Function to allocate machine-dependent function status.  */
   7581   init_machine_status = &loongarch_init_machine_status;
   7582 };
   7583 
   7584 static void
   7585 loongarch_reg_init (void)
   7586 {
   7587   /* Set up loongarch_hard_regno_mode_ok.  */
   7588   for (int mode = 0; mode < MAX_MACHINE_MODE; mode++)
   7589     for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   7590       loongarch_hard_regno_mode_ok_p[mode][regno]
   7591 	= loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode);
   7592 }
   7593 
   7594 static void
   7595 loongarch_option_override_internal (struct loongarch_target *target,
   7596 				    struct gcc_options *opts,
   7597 				    struct gcc_options *opts_set)
   7598 {
   7599   /* Handle options not covered by struct loongarch_target.  */
   7600   loongarch_init_misc_options (opts, opts_set);
   7601 
   7602   /* Resolve the target struct.  */
   7603   loongarch_init_target (target,
   7604 			 opts->x_la_opt_cpu_arch,
   7605 			 opts->x_la_opt_cpu_tune,
   7606 			 opts->x_la_opt_fpu,
   7607 			 opts->x_la_opt_simd,
   7608 			 opts->x_la_opt_abi_base,
   7609 			 opts->x_la_opt_abi_ext,
   7610 			 opts->x_la_opt_cmodel,
   7611 			 opts->x_la_opt_tls_dialect,
   7612 			 opts->x_la_isa_evolution,
   7613 			 opts_set->x_la_isa_evolution);
   7614 
   7615   loongarch_config_target (target, NULL, 0);
   7616 
   7617   /* Override some options according to the resolved target.  */
   7618   loongarch_target_option_override (target, opts, opts_set);
   7619 
   7620   target_option_default_node = target_option_current_node
   7621     = build_target_option_node (opts, opts_set);
   7622 
   7623   loongarch_reg_init ();
   7624 }
   7625 
   7626 /* Remember the last target of loongarch_set_current_function.  */
   7627 
   7628 static GTY(()) tree loongarch_previous_fndecl;
   7629 
   7630 /* Restore or save the TREE_TARGET_GLOBALS from or to new_tree.
   7631    Used by loongarch_set_current_function to
   7632    make sure optab availability predicates are recomputed when necessary.  */
   7633 
   7634 static void
   7635 loongarch_save_restore_target_globals (tree new_tree)
   7636 {
   7637   if (TREE_TARGET_GLOBALS (new_tree))
   7638     restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
   7639   else if (new_tree == target_option_default_node)
   7640     restore_target_globals (&default_target_globals);
   7641   else
   7642     TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
   7643 }
   7644 
   7645 /* Implement TARGET_SET_CURRENT_FUNCTION.  */
   7646 
   7647 static void
   7648 loongarch_set_current_function (tree fndecl)
   7649 {
   7650   if (fndecl == loongarch_previous_fndecl)
   7651     return;
   7652 
   7653   tree old_tree;
   7654   if (loongarch_previous_fndecl == NULL_TREE)
   7655     old_tree = target_option_current_node;
   7656   else if (DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl))
   7657     old_tree = DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl);
   7658   else
   7659     old_tree = target_option_default_node;
   7660 
   7661   if (fndecl == NULL_TREE)
   7662     {
   7663       if (old_tree != target_option_current_node)
   7664 	{
   7665 	  loongarch_previous_fndecl = NULL_TREE;
   7666 	  cl_target_option_restore (&global_options, &global_options_set,
   7667 				    TREE_TARGET_OPTION
   7668 				    (target_option_current_node));
   7669 	}
   7670       return;
   7671     }
   7672 
   7673   tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
   7674   if (new_tree == NULL_TREE)
   7675     new_tree = target_option_default_node;
   7676 
   7677   loongarch_previous_fndecl = fndecl;
   7678 
   7679   if (new_tree == old_tree)
   7680     return;
   7681 
   7682   cl_target_option_restore (&global_options, &global_options_set,
   7683 			    TREE_TARGET_OPTION (new_tree));
   7684 
   7685   loongarch_reg_init ();
   7686 
   7687   loongarch_save_restore_target_globals (new_tree);
   7688 }
   7689 
   7690 
   7691 
   7692 /* Implement TARGET_OPTION_OVERRIDE.  */
   7693 
   7694 static void
   7695 loongarch_option_override (void)
   7696 {
   7697   /* Global initializations.  */
   7698   loongarch_global_init ();
   7699 
   7700   /* Setting up the target configuration.  */
   7701   loongarch_option_override_internal (&la_target,
   7702 				      &global_options,
   7703 				      &global_options_set);
   7704 
   7705 }
   7706 
   7707 /* Implement TARGET_OPTION_SAVE.  */
   7708 static void
   7709 loongarch_option_save (struct cl_target_option *,
   7710 		       struct gcc_options *opts,
   7711 		       struct gcc_options *opts_set)
   7712 {
   7713   loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
   7714 }
   7715 
   7716 /* Implement TARGET_OPTION_RESTORE.  */
   7717 static void
   7718 loongarch_option_restore (struct gcc_options *,
   7719 			  struct gcc_options *,
   7720 			  struct cl_target_option *ptr)
   7721 {
   7722   la_target.cpu_arch = ptr->x_la_opt_cpu_arch;
   7723   la_target.cpu_tune = ptr->x_la_opt_cpu_tune;
   7724 
   7725   la_target.isa.fpu = ptr->x_la_opt_fpu;
   7726   la_target.isa.simd = ptr->x_la_opt_simd;
   7727   la_target.isa.evolution = ptr->x_la_isa_evolution;
   7728 
   7729   la_target.cmodel = ptr->x_la_opt_cmodel;
   7730   la_target.tls_dialect = ptr->x_la_opt_tls_dialect;
   7731 }
   7732 
   7733 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
   7734 
   7735 static void
   7736 loongarch_conditional_register_usage (void)
   7737 {
   7738   if (!TARGET_HARD_FLOAT)
   7739     accessible_reg_set &= ~(reg_class_contents[FP_REGS]
   7740 			    | reg_class_contents[FCC_REGS]);
   7741 }
   7742 
   7743 /* Implement EH_USES.  */
   7744 
   7745 bool
   7746 loongarch_eh_uses (unsigned int regno ATTRIBUTE_UNUSED)
   7747 {
   7748   return false;
   7749 }
   7750 
   7751 /* Implement EPILOGUE_USES.  */
   7752 
   7753 bool
   7754 loongarch_epilogue_uses (unsigned int regno)
   7755 {
   7756   /* Say that the epilogue uses the return address register.  Note that
   7757      in the case of sibcalls, the values "used by the epilogue" are
   7758      considered live at the start of the called function.  */
   7759   if (regno == RETURN_ADDR_REGNUM)
   7760     return true;
   7761 
   7762   return false;
   7763 }
   7764 
   7765 bool
   7766 loongarch_load_store_bonding_p (rtx *operands, machine_mode mode, bool load_p)
   7767 {
   7768   rtx reg1, reg2, mem1, mem2, base1, base2;
   7769   enum reg_class rc1, rc2;
   7770   HOST_WIDE_INT offset1, offset2;
   7771 
   7772   if (load_p)
   7773     {
   7774       reg1 = operands[0];
   7775       reg2 = operands[2];
   7776       mem1 = operands[1];
   7777       mem2 = operands[3];
   7778     }
   7779   else
   7780     {
   7781       reg1 = operands[1];
   7782       reg2 = operands[3];
   7783       mem1 = operands[0];
   7784       mem2 = operands[2];
   7785     }
   7786 
   7787   if (loongarch_address_insns (XEXP (mem1, 0), mode, false) == 0
   7788       || loongarch_address_insns (XEXP (mem2, 0), mode, false) == 0)
   7789     return false;
   7790 
   7791   loongarch_split_plus (XEXP (mem1, 0), &base1, &offset1);
   7792   loongarch_split_plus (XEXP (mem2, 0), &base2, &offset2);
   7793 
   7794   /* Base regs do not match.  */
   7795   if (!REG_P (base1) || !rtx_equal_p (base1, base2))
   7796     return false;
   7797 
   7798   /* Either of the loads is clobbering base register.  It is legitimate to bond
   7799      loads if second load clobbers base register.  However, hardware does not
   7800      support such bonding.  */
   7801   if (load_p
   7802       && (REGNO (reg1) == REGNO (base1) || (REGNO (reg2) == REGNO (base1))))
   7803     return false;
   7804 
   7805   /* Loading in same registers.  */
   7806   if (load_p && REGNO (reg1) == REGNO (reg2))
   7807     return false;
   7808 
   7809   /* The loads/stores are not of same type.  */
   7810   rc1 = REGNO_REG_CLASS (REGNO (reg1));
   7811   rc2 = REGNO_REG_CLASS (REGNO (reg2));
   7812   if (rc1 != rc2 && !reg_class_subset_p (rc1, rc2)
   7813       && !reg_class_subset_p (rc2, rc1))
   7814     return false;
   7815 
   7816   if (abs (offset1 - offset2) != GET_MODE_SIZE (mode))
   7817     return false;
   7818 
   7819   return true;
   7820 }
   7821 
   7822 /* Implement TARGET_TRAMPOLINE_INIT.  */
   7823 
   7824 static void
   7825 loongarch_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
   7826 {
   7827   rtx addr, end_addr, mem;
   7828   rtx trampoline[8];
   7829   unsigned int i, j;
   7830   HOST_WIDE_INT end_addr_offset, static_chain_offset, target_function_offset;
   7831 
   7832   /* Work out the offsets of the pointers from the start of the
   7833      trampoline code.  */
   7834   end_addr_offset = TRAMPOLINE_CODE_SIZE;
   7835   static_chain_offset = end_addr_offset;
   7836   target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode);
   7837 
   7838   /* Get pointers to the beginning and end of the code block.  */
   7839   addr = force_reg (Pmode, XEXP (m_tramp, 0));
   7840   end_addr
   7841     = loongarch_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset));
   7842 
   7843 #define OP(X) gen_int_mode (X, SImode)
   7844 
   7845   /* Build up the code in TRAMPOLINE.  */
   7846   i = 0;
   7847   /*pcaddi $static_chain,0
   7848     ld.[dw] $tmp,$static_chain,target_function_offset
   7849     ld.[dw] $static_chain,$static_chain,static_chain_offset
   7850     jirl $r0,$tmp,0  */
   7851   trampoline[i++] = OP (0x18000000 | (STATIC_CHAIN_REGNUM - GP_REG_FIRST));
   7852   trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000)
   7853 			| 19 /* $t7  */
   7854 			| ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5)
   7855 			| ((target_function_offset & 0xfff) << 10));
   7856   trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000)
   7857 			| (STATIC_CHAIN_REGNUM - GP_REG_FIRST)
   7858 			| ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5)
   7859 			| ((static_chain_offset & 0xfff) << 10));
   7860   trampoline[i++] = OP (0x4c000000 | (19 << 5));
   7861 #undef OP
   7862 
   7863   for (j = 0; j < i; j++)
   7864    {
   7865      mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode));
   7866      loongarch_emit_move (mem, trampoline[j]);
   7867    }
   7868 
   7869   /* Set up the static chain pointer field.  */
   7870   mem = adjust_address (m_tramp, ptr_mode, static_chain_offset);
   7871   loongarch_emit_move (mem, chain_value);
   7872 
   7873   /* Set up the target function field.  */
   7874   mem = adjust_address (m_tramp, ptr_mode, target_function_offset);
   7875   loongarch_emit_move (mem, XEXP (DECL_RTL (fndecl), 0));
   7876 
   7877   /* Flush the code part of the trampoline.  */
   7878   emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE)));
   7879   emit_insn (gen_clear_cache (addr, end_addr));
   7880 }
   7881 
   7882 /* Generate or test for an insn that supports a constant permutation.  */
   7883 
   7884 #define MAX_VECT_LEN 32
   7885 
   7886 struct expand_vec_perm_d
   7887 {
   7888   rtx target, op0, op1;
   7889   unsigned char perm[MAX_VECT_LEN];
   7890   machine_mode vmode;
   7891   unsigned char nelt;
   7892   bool one_vector_p;
   7893   bool testing_p;
   7894 };
   7895 
   7896 /* Construct (set target (vec_select op0 (parallel perm))) and
   7897    return true if that's a valid instruction in the active ISA.  */
   7898 
   7899 static bool
   7900 loongarch_expand_vselect (rtx target, rtx op0,
   7901 			  const unsigned char *perm, unsigned nelt,
   7902 			  bool testing_p)
   7903 {
   7904   rtx rperm[MAX_VECT_LEN], x;
   7905   rtx_insn *insn;
   7906   unsigned i;
   7907 
   7908   for (i = 0; i < nelt; ++i)
   7909     rperm[i] = GEN_INT (perm[i]);
   7910 
   7911   x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelt, rperm));
   7912   x = gen_rtx_VEC_SELECT (GET_MODE (target), op0, x);
   7913   x = gen_rtx_SET (target, x);
   7914 
   7915   insn = emit_insn (x);
   7916   if (recog_memoized (insn) < 0)
   7917     {
   7918       remove_insn (insn);
   7919       return false;
   7920     }
   7921 
   7922   if (testing_p)
   7923       remove_insn (insn);
   7924   return true;
   7925 }
   7926 
   7927 /* Similar, but generate a vec_concat from op0 and op1 as well.  */
   7928 
   7929 static bool
   7930 loongarch_expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   7931 				  const unsigned char *perm, unsigned nelt,
   7932 				  bool testing_p)
   7933 {
   7934   machine_mode v2mode;
   7935   rtx x;
   7936 
   7937   if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
   7938     return false;
   7939   x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
   7940   return loongarch_expand_vselect (target, x, perm, nelt, testing_p);
   7941 }
   7942 
   7943 static tree
   7944 loongarch_handle_model_attribute (tree *node, tree name, tree arg, int,
   7945 				  bool *no_add_attrs)
   7946 {
   7947   tree decl = *node;
   7948   if (VAR_P (decl))
   7949     {
   7950       if (DECL_THREAD_LOCAL_P (decl))
   7951 	{
   7952 	  error_at (DECL_SOURCE_LOCATION (decl),
   7953 		    "%qE attribute cannot be specified for thread-local "
   7954 		    "variables", name);
   7955 	  *no_add_attrs = true;
   7956 	  return NULL_TREE;
   7957 	}
   7958       if (DECL_CONTEXT (decl)
   7959 	  && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL
   7960 	  && !TREE_STATIC (decl))
   7961 	{
   7962 	  error_at (DECL_SOURCE_LOCATION (decl),
   7963 		    "%qE attribute cannot be specified for local "
   7964 		    "variables", name);
   7965 	  *no_add_attrs = true;
   7966 	  return NULL_TREE;
   7967 	}
   7968       if (DECL_REGISTER (decl))
   7969 	{
   7970 	  error_at (DECL_SOURCE_LOCATION (decl),
   7971 		    "%qE attribute cannot be specified for register "
   7972 		    "variables", name);
   7973 	  *no_add_attrs = true;
   7974 	  return NULL_TREE;
   7975 	}
   7976 
   7977       arg = TREE_VALUE (arg);
   7978       if (TREE_CODE (arg) != STRING_CST)
   7979 	{
   7980 	  error_at (DECL_SOURCE_LOCATION (decl),
   7981 		    "invalid argument of %qE attribute", name);
   7982 	  *no_add_attrs = true;
   7983 	  return NULL_TREE;
   7984 	}
   7985 
   7986       const char *model = TREE_STRING_POINTER (arg);
   7987       if (strcmp (model, "normal") != 0
   7988 	  && strcmp (model, "extreme") != 0)
   7989 	{
   7990 	  error_at (DECL_SOURCE_LOCATION (decl),
   7991 		    "invalid argument of %qE attribute", name);
   7992 	  *no_add_attrs = true;
   7993 	  return NULL_TREE;
   7994 	}
   7995 
   7996       if (lookup_attribute ("model", DECL_ATTRIBUTES (decl)))
   7997 	{
   7998 	  error_at (DECL_SOURCE_LOCATION (decl),
   7999 		    "multiple %qE attribute", name);
   8000 	  *no_add_attrs = true;
   8001 	  return NULL_TREE;
   8002 	}
   8003     }
   8004   else
   8005     {
   8006       warning (OPT_Wattributes, "%qE attribute ignored", name);
   8007       *no_add_attrs = true;
   8008     }
   8009   return NULL_TREE;
   8010 }
   8011 
   8012 TARGET_GNU_ATTRIBUTES (loongarch_attribute_table,
   8013 {
   8014   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
   8015        affects_type_identity, handler, exclude } */
   8016   { "model", 1, 1, true, false, false, false,
   8017     loongarch_handle_model_attribute, NULL }
   8018 });
   8019 
   8020 bool
   8021 loongarch_use_anchors_for_symbol_p (const_rtx symbol)
   8022 {
   8023   tree decl = SYMBOL_REF_DECL (symbol);
   8024 
   8025   /* The section anchor optimization may break custom address model.  */
   8026   if (decl && lookup_attribute ("model", DECL_ATTRIBUTES (decl)))
   8027     return false;
   8028 
   8029   return default_use_anchors_for_symbol_p (symbol);
   8030 }
   8031 
   8032 /* Implement the TARGET_ASAN_SHADOW_OFFSET hook.  */
   8033 
   8034 static unsigned HOST_WIDE_INT
   8035 loongarch_asan_shadow_offset (void)
   8036 {
   8037   /* We only have libsanitizer support for LOONGARCH64 at present.
   8038      This value is taken from the file libsanitizer/asan/asan_mapping.h.  */
   8039   return TARGET_64BIT ? (HOST_WIDE_INT_1 << 46) : 0;
   8040 }
   8041 
   8042 static sbitmap
   8043 loongarch_get_separate_components (void)
   8044 {
   8045   HOST_WIDE_INT offset;
   8046   sbitmap components = sbitmap_alloc (FIRST_PSEUDO_REGISTER);
   8047   bitmap_clear (components);
   8048   offset = cfun->machine->frame.gp_sp_offset;
   8049 
   8050   /* The stack should be aligned to 16-bytes boundary, so we can make the use
   8051      of ldptr instructions.  */
   8052   gcc_assert (offset % UNITS_PER_WORD == 0);
   8053 
   8054   for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
   8055     if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
   8056       {
   8057 	/* We can wrap general registers saved at [sp, sp + 32768) using the
   8058 	   ldptr/stptr instructions.  For large offsets a pseudo register
   8059 	   might be needed which cannot be created during the shrink
   8060 	   wrapping pass.
   8061 
   8062 	   TODO: This may need a revise when we add LA32 as ldptr.w is not
   8063 	   guaranteed available by the manual.  */
   8064 	if (offset < 32768)
   8065 	  bitmap_set_bit (components, regno);
   8066 
   8067 	offset -= UNITS_PER_WORD;
   8068       }
   8069 
   8070   offset = cfun->machine->frame.fp_sp_offset;
   8071   for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
   8072     if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
   8073       {
   8074 	/* We can only wrap FP registers with imm12 offsets.  For large
   8075 	   offsets a pseudo register might be needed which cannot be
   8076 	   created during the shrink wrapping pass.  */
   8077 	if (IMM12_OPERAND (offset))
   8078 	  bitmap_set_bit (components, regno);
   8079 
   8080 	offset -= UNITS_PER_FP_REG;
   8081       }
   8082 
   8083   /* Don't mess with the hard frame pointer.  */
   8084   if (frame_pointer_needed)
   8085     bitmap_clear_bit (components, HARD_FRAME_POINTER_REGNUM);
   8086 
   8087   bitmap_clear_bit (components, RETURN_ADDR_REGNUM);
   8088 
   8089   return components;
   8090 }
   8091 
   8092 static sbitmap
   8093 loongarch_components_for_bb (basic_block bb)
   8094 {
   8095   /* Registers are used in a bb if they are in the IN, GEN, or KILL sets.  */
   8096   auto_bitmap used;
   8097   bitmap_copy (used, DF_LIVE_IN (bb));
   8098   bitmap_ior_into (used, &DF_LIVE_BB_INFO (bb)->gen);
   8099   bitmap_ior_into (used, &DF_LIVE_BB_INFO (bb)->kill);
   8100 
   8101   sbitmap components = sbitmap_alloc (FIRST_PSEUDO_REGISTER);
   8102   bitmap_clear (components);
   8103 
   8104   function_abi_aggregator callee_abis;
   8105   rtx_insn *insn;
   8106   FOR_BB_INSNS (bb, insn)
   8107     if (CALL_P (insn))
   8108       callee_abis.note_callee_abi (insn_callee_abi (insn));
   8109 
   8110   HARD_REG_SET extra_caller_saves =
   8111     callee_abis.caller_save_regs (*crtl->abi);
   8112 
   8113   for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
   8114     if (!fixed_regs[regno]
   8115 	&& !crtl->abi->clobbers_full_reg_p (regno)
   8116 	&& (TEST_HARD_REG_BIT (extra_caller_saves, regno) ||
   8117 	    bitmap_bit_p (used, regno)))
   8118       bitmap_set_bit (components, regno);
   8119 
   8120   for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
   8121     if (!fixed_regs[regno]
   8122 	&& !crtl->abi->clobbers_full_reg_p (regno)
   8123 	&& (TEST_HARD_REG_BIT (extra_caller_saves, regno) ||
   8124 	    bitmap_bit_p (used, regno)))
   8125       bitmap_set_bit (components, regno);
   8126 
   8127   return components;
   8128 }
   8129 
   8130 static void
   8131 loongarch_disqualify_components (sbitmap, edge, sbitmap, bool)
   8132 {
   8133   /* Do nothing.  */
   8134 }
   8135 
   8136 static void
   8137 loongarch_process_components (sbitmap components, loongarch_save_restore_fn fn)
   8138 {
   8139   HOST_WIDE_INT offset = cfun->machine->frame.gp_sp_offset;
   8140 
   8141   for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
   8142     if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
   8143       {
   8144 	if (bitmap_bit_p (components, regno))
   8145 	  loongarch_save_restore_reg (word_mode, regno, offset, fn);
   8146 
   8147 	offset -= UNITS_PER_WORD;
   8148       }
   8149 
   8150   offset = cfun->machine->frame.fp_sp_offset;
   8151   machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
   8152 
   8153   for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
   8154     if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
   8155       {
   8156 	if (bitmap_bit_p (components, regno))
   8157 	  loongarch_save_restore_reg (mode, regno, offset, fn);
   8158 
   8159 	offset -= UNITS_PER_FP_REG;
   8160       }
   8161 }
   8162 
   8163 static void
   8164 loongarch_emit_prologue_components (sbitmap components)
   8165 {
   8166   loongarch_process_components (components, loongarch_save_reg);
   8167 }
   8168 
   8169 static void
   8170 loongarch_emit_epilogue_components (sbitmap components)
   8171 {
   8172   loongarch_process_components (components, loongarch_restore_reg);
   8173 }
   8174 
   8175 static void
   8176 loongarch_set_handled_components (sbitmap components)
   8177 {
   8178     for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
   8179       if (bitmap_bit_p (components, regno))
   8180 	cfun->machine->reg_is_wrapped_separately[regno] = true;
   8181 
   8182     for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
   8183       if (bitmap_bit_p (components, regno))
   8184 	cfun->machine->reg_is_wrapped_separately[regno] = true;
   8185 }
   8186 
   8187 /* Initialize the GCC target structure.  */
   8188 #undef TARGET_ASM_ALIGNED_HI_OP
   8189 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
   8190 #undef TARGET_ASM_ALIGNED_SI_OP
   8191 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
   8192 #undef TARGET_ASM_ALIGNED_DI_OP
   8193 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
   8194 
   8195 /* Use the vshuf instruction to implement all 128-bit constant vector
   8196    permuatation.  */
   8197 
   8198 static bool
   8199 loongarch_try_expand_lsx_vshuf_const (struct expand_vec_perm_d *d)
   8200 {
   8201   int i;
   8202   rtx target, op0, op1, sel, tmp;
   8203   rtx rperm[MAX_VECT_LEN];
   8204 
   8205   if (GET_MODE_SIZE (d->vmode) == 16)
   8206     {
   8207       target = d->target;
   8208       op0 = d->op0;
   8209       op1 = d->one_vector_p ? d->op0 : d->op1;
   8210 
   8211       if (GET_MODE (op0) != GET_MODE (op1)
   8212 	  || GET_MODE (op0) != GET_MODE (target))
   8213 	return false;
   8214 
   8215       if (d->testing_p)
   8216 	return true;
   8217 
   8218       for (i = 0; i < d->nelt; i += 1)
   8219 	  rperm[i] = GEN_INT (d->perm[i]);
   8220 
   8221       if (d->vmode == E_V2DFmode)
   8222 	{
   8223 	  sel = gen_rtx_CONST_VECTOR (E_V2DImode, gen_rtvec_v (d->nelt, rperm));
   8224 	  tmp = simplify_gen_subreg (E_V2DImode, d->target, d->vmode, 0);
   8225 	  emit_move_insn (tmp, sel);
   8226 	}
   8227       else if (d->vmode == E_V4SFmode)
   8228 	{
   8229 	  sel = gen_rtx_CONST_VECTOR (E_V4SImode, gen_rtvec_v (d->nelt, rperm));
   8230 	  tmp = simplify_gen_subreg (E_V4SImode, d->target, d->vmode, 0);
   8231 	  emit_move_insn (tmp, sel);
   8232 	}
   8233       else
   8234 	{
   8235 	  sel = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (d->nelt, rperm));
   8236 	  emit_move_insn (d->target, sel);
   8237 	}
   8238 
   8239       switch (d->vmode)
   8240 	{
   8241 	case E_V2DFmode:
   8242 	  emit_insn (gen_lsx_vshuf_d_f (target, target, op1, op0));
   8243 	  break;
   8244 	case E_V2DImode:
   8245 	  emit_insn (gen_lsx_vshuf_d (target, target, op1, op0));
   8246 	  break;
   8247 	case E_V4SFmode:
   8248 	  emit_insn (gen_lsx_vshuf_w_f (target, target, op1, op0));
   8249 	  break;
   8250 	case E_V4SImode:
   8251 	  emit_insn (gen_lsx_vshuf_w (target, target, op1, op0));
   8252 	  break;
   8253 	case E_V8HImode:
   8254 	  emit_insn (gen_lsx_vshuf_h (target, target, op1, op0));
   8255 	  break;
   8256 	case E_V16QImode:
   8257 	  emit_insn (gen_lsx_vshuf_b (target, op1, op0, target));
   8258 	  break;
   8259 	default:
   8260 	  break;
   8261 	}
   8262 
   8263       return true;
   8264     }
   8265   return false;
   8266 }
   8267 
   8268 /* Construct (set target (vec_select op0 (parallel selector))) and
   8269    return true if that's a valid instruction in the active ISA.
   8270    In fact, it matches the special constant vector with repeated
   8271    4-element sets.  */
   8272 
   8273 static bool
   8274 loongarch_is_imm_set_shuffle (struct expand_vec_perm_d *d)
   8275 {
   8276   rtx x, elts[MAX_VECT_LEN];
   8277   rtvec v;
   8278   rtx_insn *insn;
   8279   unsigned i;
   8280 
   8281   if (!ISA_HAS_LSX && !ISA_HAS_LASX)
   8282     return false;
   8283 
   8284   for (i = 0; i < d->nelt; i++)
   8285     elts[i] = GEN_INT (d->perm[i]);
   8286 
   8287   v = gen_rtvec_v (d->nelt, elts);
   8288   x = gen_rtx_PARALLEL (VOIDmode, v);
   8289 
   8290   if (!loongarch_const_vector_shuffle_set_p (x, d->vmode))
   8291     return false;
   8292 
   8293   if (d->testing_p)
   8294     return true;
   8295 
   8296   x = gen_rtx_VEC_SELECT (d->vmode, d->op0, x);
   8297   x = gen_rtx_SET (d->target, x);
   8298 
   8299   insn = emit_insn (x);
   8300   if (recog_memoized (insn) < 0)
   8301     {
   8302       remove_insn (insn);
   8303       return false;
   8304     }
   8305   return true;
   8306 }
   8307 
   8308 static bool
   8309 loongarch_expand_vec_perm_even_odd (struct expand_vec_perm_d *);
   8310 
   8311 /* Try to match and expand all kinds of 128-bit const vector permutation
   8312    cases.  */
   8313 
   8314 static bool
   8315 loongarch_expand_lsx_shuffle (struct expand_vec_perm_d *d)
   8316 {
   8317   if (!ISA_HAS_LSX && GET_MODE_SIZE (d->vmode) != 16)
   8318     return false;
   8319 
   8320   if (loongarch_is_imm_set_shuffle (d))
   8321       return true;
   8322 
   8323   if (loongarch_expand_vec_perm_even_odd (d))
   8324     return true;
   8325 
   8326   return loongarch_try_expand_lsx_vshuf_const (d);
   8327 }
   8328 
   8329 /* Try to simplify a two vector permutation using 2 intra-lane interleave
   8330    insns and cross-lane shuffle for 32-byte vectors.  */
   8331 
   8332 static bool
   8333 loongarch_expand_vec_perm_interleave (struct expand_vec_perm_d *d)
   8334 {
   8335   unsigned i, nelt;
   8336   rtx t1,t2,t3;
   8337   rtx (*gen_high) (rtx, rtx, rtx);
   8338   rtx (*gen_low) (rtx, rtx, rtx);
   8339   machine_mode mode = GET_MODE (d->target);
   8340 
   8341   if (d->one_vector_p)
   8342     return false;
   8343   if (ISA_HAS_LASX && GET_MODE_SIZE (d->vmode) == 32)
   8344     ;
   8345   else
   8346     return false;
   8347 
   8348   nelt = d->nelt;
   8349   if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
   8350     return false;
   8351   for (i = 0; i < nelt; i += 2)
   8352     if (d->perm[i] != d->perm[0] + i / 2
   8353 	|| d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
   8354       return false;
   8355 
   8356   if (d->testing_p)
   8357     return true;
   8358 
   8359   switch (d->vmode)
   8360     {
   8361     case E_V32QImode:
   8362       gen_high = gen_lasx_xvilvh_b;
   8363       gen_low = gen_lasx_xvilvl_b;
   8364       break;
   8365     case E_V16HImode:
   8366       gen_high = gen_lasx_xvilvh_h;
   8367       gen_low = gen_lasx_xvilvl_h;
   8368       break;
   8369     case E_V8SImode:
   8370       gen_high = gen_lasx_xvilvh_w;
   8371       gen_low = gen_lasx_xvilvl_w;
   8372       break;
   8373     case E_V4DImode:
   8374       gen_high = gen_lasx_xvilvh_d;
   8375       gen_low = gen_lasx_xvilvl_d;
   8376       break;
   8377     case E_V8SFmode:
   8378       gen_high = gen_lasx_xvilvh_w_f;
   8379       gen_low = gen_lasx_xvilvl_w_f;
   8380       break;
   8381     case E_V4DFmode:
   8382       gen_high = gen_lasx_xvilvh_d_f;
   8383       gen_low = gen_lasx_xvilvl_d_f;
   8384       break;
   8385     default:
   8386       gcc_unreachable ();
   8387     }
   8388 
   8389   t1 = gen_reg_rtx (mode);
   8390   t2 = gen_reg_rtx (mode);
   8391   emit_insn (gen_high (t1, d->op0, d->op1));
   8392   emit_insn (gen_low (t2, d->op0, d->op1));
   8393   if (mode == V4DFmode || mode == V8SFmode)
   8394     {
   8395       t3 = gen_reg_rtx (V4DFmode);
   8396       if (d->perm[0])
   8397 	emit_insn (gen_lasx_xvpermi_q_v4df (t3, gen_lowpart (V4DFmode, t1),
   8398 					    gen_lowpart (V4DFmode, t2),
   8399 					    GEN_INT (0x31)));
   8400       else
   8401 	emit_insn (gen_lasx_xvpermi_q_v4df (t3, gen_lowpart (V4DFmode, t1),
   8402 					    gen_lowpart (V4DFmode, t2),
   8403 					    GEN_INT (0x20)));
   8404     }
   8405   else
   8406     {
   8407       t3 = gen_reg_rtx (V4DImode);
   8408       if (d->perm[0])
   8409 	emit_insn (gen_lasx_xvpermi_q_v4di (t3, gen_lowpart (V4DImode, t1),
   8410 					    gen_lowpart (V4DImode, t2),
   8411 					    GEN_INT (0x31)));
   8412       else
   8413 	emit_insn (gen_lasx_xvpermi_q_v4di (t3, gen_lowpart (V4DImode, t1),
   8414 					    gen_lowpart (V4DImode, t2),
   8415 					    GEN_INT (0x20)));
   8416     }
   8417   emit_move_insn (d->target, gen_lowpart (mode, t3));
   8418   return true;
   8419 }
   8420 
   8421 /* Implement 128-bit and 256-bit extract-even and extract-odd permutations.  */
   8422 
   8423 static bool
   8424 loongarch_expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
   8425 {
   8426   rtx t1;
   8427   machine_mode mode = GET_MODE (d->target);
   8428 
   8429   if (d->testing_p)
   8430     return true;
   8431 
   8432   t1 = gen_reg_rtx (mode);
   8433 
   8434   switch (d->vmode)
   8435     {
   8436     /* 128 bit.  */
   8437     case E_V2DFmode:
   8438       if (odd)
   8439 	emit_insn (gen_lsx_vilvh_d_f (d->target, d->op0, d->op1));
   8440       else
   8441 	emit_insn (gen_lsx_vilvl_d_f (d->target, d->op0, d->op1));
   8442       break;
   8443 
   8444     case E_V2DImode:
   8445       if (odd)
   8446 	emit_insn (gen_lsx_vilvh_d (d->target, d->op0, d->op1));
   8447       else
   8448 	emit_insn (gen_lsx_vilvl_d (d->target, d->op0, d->op1));
   8449       break;
   8450 
   8451     case E_V4SFmode:
   8452       if (odd)
   8453 	emit_insn (gen_lsx_vpickod_w_f (d->target, d->op0, d->op1));
   8454       else
   8455 	emit_insn (gen_lsx_vpickev_w_f (d->target, d->op0, d->op1));
   8456       break;
   8457 
   8458     case E_V4SImode:
   8459       if (odd)
   8460 	emit_insn (gen_lsx_vpickod_w (d->target, d->op0, d->op1));
   8461       else
   8462 	emit_insn (gen_lsx_vpickev_w (d->target, d->op0, d->op1));
   8463       break;
   8464 
   8465     case E_V8HImode:
   8466       if (odd)
   8467 	emit_insn (gen_lsx_vpickod_h (d->target, d->op0, d->op1));
   8468       else
   8469 	emit_insn (gen_lsx_vpickev_h (d->target, d->op0, d->op1));
   8470       break;
   8471 
   8472     case E_V16QImode:
   8473       if (odd)
   8474 	emit_insn (gen_lsx_vpickod_b (d->target, d->op0, d->op1));
   8475       else
   8476 	emit_insn (gen_lsx_vpickev_b (d->target, d->op0, d->op1));
   8477       break;
   8478 
   8479     /* 256 bit.  */
   8480     case E_V4DFmode:
   8481       /* Shuffle the lanes around into { 0 4 2 6 } and { 1 5 3 7 }.  */
   8482       if (odd)
   8483 	emit_insn (gen_lasx_xvilvh_d_f (t1, d->op0, d->op1));
   8484       else
   8485 	emit_insn (gen_lasx_xvilvl_d_f (t1, d->op0, d->op1));
   8486 
   8487       /* Shuffle within the 256-bit lanes to produce the result required.
   8488 	 { 0 2 4 6 } | { 1 3 5 7 }.  */
   8489       emit_insn (gen_lasx_xvpermi_d_v4df (d->target, t1, GEN_INT (0xd8)));
   8490       break;
   8491 
   8492     case E_V4DImode:
   8493       if (odd)
   8494 	emit_insn (gen_lasx_xvilvh_d (t1, d->op0, d->op1));
   8495       else
   8496 	emit_insn (gen_lasx_xvilvl_d (t1, d->op0, d->op1));
   8497 
   8498       emit_insn (gen_lasx_xvpermi_d_v4di (d->target, t1, GEN_INT (0xd8)));
   8499       break;
   8500 
   8501     case E_V8SFmode:
   8502       /* Shuffle the lanes around into:
   8503 	 { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }.  */
   8504       if (odd)
   8505 	emit_insn (gen_lasx_xvpickod_w_f (t1, d->op0, d->op1));
   8506       else
   8507 	emit_insn (gen_lasx_xvpickev_w_f (t1, d->op0, d->op1));
   8508 
   8509       /* Shuffle within the 256-bit lanes to produce the result required.
   8510 	 { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }.  */
   8511       emit_insn (gen_lasx_xvpermi_d_v8sf (d->target, t1, GEN_INT (0xd8)));
   8512       break;
   8513 
   8514     case E_V8SImode:
   8515       if (odd)
   8516 	emit_insn (gen_lasx_xvpickod_w (t1, d->op0, d->op1));
   8517       else
   8518 	emit_insn (gen_lasx_xvpickev_w (t1, d->op0, d->op1));
   8519 
   8520       emit_insn (gen_lasx_xvpermi_d_v8si (d->target, t1, GEN_INT (0xd8)));
   8521       break;
   8522 
   8523     case E_V16HImode:
   8524       if (odd)
   8525 	emit_insn (gen_lasx_xvpickod_h (t1, d->op0, d->op1));
   8526       else
   8527 	emit_insn (gen_lasx_xvpickev_h (t1, d->op0, d->op1));
   8528 
   8529       emit_insn (gen_lasx_xvpermi_d_v16hi (d->target, t1, GEN_INT (0xd8)));
   8530       break;
   8531 
   8532     case E_V32QImode:
   8533       if (odd)
   8534 	emit_insn (gen_lasx_xvpickod_b (t1, d->op0, d->op1));
   8535       else
   8536 	emit_insn (gen_lasx_xvpickev_b (t1, d->op0, d->op1));
   8537 
   8538       emit_insn (gen_lasx_xvpermi_d_v32qi (d->target, t1, GEN_INT (0xd8)));
   8539       break;
   8540 
   8541     default:
   8542       gcc_unreachable ();
   8543     }
   8544 
   8545   return true;
   8546 }
   8547 
   8548 /* Pattern match extract-even and extract-odd permutations.  */
   8549 
   8550 static bool
   8551 loongarch_expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
   8552 {
   8553   unsigned i, odd, nelt = d->nelt;
   8554   if (!ISA_HAS_LASX && !ISA_HAS_LSX)
   8555     return false;
   8556 
   8557   odd = d->perm[0];
   8558   if (odd != 0 && odd != 1)
   8559     return false;
   8560 
   8561   for (i = 1; i < nelt; ++i)
   8562     if (d->perm[i] != 2 * i + odd)
   8563       return false;
   8564 
   8565   return loongarch_expand_vec_perm_even_odd_1 (d, odd);
   8566 }
   8567 
   8568 static void
   8569 loongarch_expand_vec_interleave (rtx target, rtx op0, rtx op1, bool high_p)
   8570 {
   8571   struct expand_vec_perm_d d;
   8572   unsigned i, nelt, base;
   8573   bool ok;
   8574 
   8575   d.target = target;
   8576   d.op0 = op0;
   8577   d.op1 = op1;
   8578   d.vmode = GET_MODE (target);
   8579   d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
   8580   d.one_vector_p = false;
   8581   d.testing_p = false;
   8582 
   8583   base = high_p ? nelt / 2 : 0;
   8584   for (i = 0; i < nelt / 2; ++i)
   8585     {
   8586       d.perm[i * 2] = i + base;
   8587       d.perm[i * 2 + 1] = i + base + nelt;
   8588     }
   8589 
   8590   ok = loongarch_expand_vec_perm_interleave (&d);
   8591   gcc_assert (ok);
   8592 }
   8593 
   8594 /* The loongarch lasx instructions xvmulwev and xvmulwod return the even or odd
   8595    parts of the double sized result elements in the corresponding elements of
   8596    the target register. That's NOT what the vec_widen_umult_lo/hi patterns are
   8597    expected to do. We emulate the widening lo/hi multiplies with the even/odd
   8598    versions followed by a vector merge.  */
   8599 
   8600 void
   8601 loongarch_expand_vec_widen_hilo (rtx dest, rtx op1, rtx op2,
   8602 				 bool uns_p, bool high_p, const char *optab)
   8603 {
   8604   machine_mode wmode = GET_MODE (dest);
   8605   machine_mode mode = GET_MODE (op1);
   8606   rtx t1, t2, t3;
   8607 
   8608   t1 = gen_reg_rtx (wmode);
   8609   t2 = gen_reg_rtx (wmode);
   8610   t3 = gen_reg_rtx (wmode);
   8611   switch (mode)
   8612     {
   8613     case V16HImode:
   8614       if (!strcmp (optab, "add"))
   8615 	{
   8616 	  if (!uns_p)
   8617 	    {
   8618 	      emit_insn (gen_lasx_xvaddwev_w_h (t1, op1, op2));
   8619 	      emit_insn (gen_lasx_xvaddwod_w_h (t2, op1, op2));
   8620 	    }
   8621 	  else
   8622 	    {
   8623 	      emit_insn (gen_lasx_xvaddwev_w_hu (t1, op1, op2));
   8624 	      emit_insn (gen_lasx_xvaddwod_w_hu (t2, op1, op2));
   8625 	    }
   8626 	}
   8627       else if (!strcmp (optab, "mult"))
   8628 	{
   8629 	  if (!uns_p)
   8630 	    {
   8631 	      emit_insn (gen_lasx_xvmulwev_w_h (t1, op1, op2));
   8632 	      emit_insn (gen_lasx_xvmulwod_w_h (t2, op1, op2));
   8633 	    }
   8634 	  else
   8635 	    {
   8636 	      emit_insn (gen_lasx_xvmulwev_w_hu (t1, op1, op2));
   8637 	      emit_insn (gen_lasx_xvmulwod_w_hu (t2, op1, op2));
   8638 	    }
   8639 	}
   8640       else if (!strcmp (optab, "sub"))
   8641 	{
   8642 	  if (!uns_p)
   8643 	    {
   8644 	      emit_insn (gen_lasx_xvsubwev_w_h (t1, op1, op2));
   8645 	      emit_insn (gen_lasx_xvsubwod_w_h (t2, op1, op2));
   8646 	    }
   8647 	  else
   8648 	    {
   8649 	      emit_insn (gen_lasx_xvsubwev_w_hu (t1, op1, op2));
   8650 	      emit_insn (gen_lasx_xvsubwod_w_hu (t2, op1, op2));
   8651 	    }
   8652 	}
   8653       break;
   8654 
   8655     case V32QImode:
   8656       if (!strcmp (optab, "add"))
   8657 	{
   8658 	  if (!uns_p)
   8659 	    {
   8660 	      emit_insn (gen_lasx_xvaddwev_h_b (t1, op1, op2));
   8661 	      emit_insn (gen_lasx_xvaddwod_h_b (t2, op1, op2));
   8662 	    }
   8663 	  else
   8664 	    {
   8665 	      emit_insn (gen_lasx_xvaddwev_h_bu (t1, op1, op2));
   8666 	      emit_insn (gen_lasx_xvaddwod_h_bu (t2, op1, op2));
   8667 	    }
   8668 	}
   8669       else if (!strcmp (optab, "mult"))
   8670 	{
   8671 	  if (!uns_p)
   8672 	    {
   8673 	      emit_insn (gen_lasx_xvmulwev_h_b (t1, op1, op2));
   8674 	      emit_insn (gen_lasx_xvmulwod_h_b (t2, op1, op2));
   8675 	    }
   8676 	  else
   8677 	    {
   8678 	      emit_insn (gen_lasx_xvmulwev_h_bu (t1, op1, op2));
   8679 	      emit_insn (gen_lasx_xvmulwod_h_bu (t2, op1, op2));
   8680 	    }
   8681 	}
   8682       else if (!strcmp (optab, "sub"))
   8683 	{
   8684 	  if (!uns_p)
   8685 	    {
   8686 	      emit_insn (gen_lasx_xvsubwev_h_b (t1, op1, op2));
   8687 	      emit_insn (gen_lasx_xvsubwod_h_b (t2, op1, op2));
   8688 	    }
   8689 	  else
   8690 	    {
   8691 	      emit_insn (gen_lasx_xvsubwev_h_bu (t1, op1, op2));
   8692 	      emit_insn (gen_lasx_xvsubwod_h_bu (t2, op1, op2));
   8693 	    }
   8694 	}
   8695       break;
   8696 
   8697     default:
   8698       gcc_unreachable ();
   8699     }
   8700 
   8701   loongarch_expand_vec_interleave (t3, t1, t2, high_p);
   8702   emit_move_insn (dest, gen_lowpart (wmode, t3));
   8703 }
   8704 
   8705 /* Expand a variable vector permutation for LASX.  */
   8706 
   8707 void
   8708 loongarch_expand_vec_perm_1 (rtx operands[])
   8709 {
   8710   rtx target = operands[0];
   8711   rtx op0 = operands[1];
   8712   rtx op1 = operands[2];
   8713   rtx mask = operands[3];
   8714 
   8715   bool one_operand_shuffle = rtx_equal_p (op0, op1);
   8716   rtx t1 = NULL;
   8717   rtx t2 = NULL;
   8718   rtx t3, t4, t5, t6, vt = NULL;
   8719   rtx vec[32] = {NULL};
   8720   machine_mode mode = GET_MODE (op0);
   8721   machine_mode maskmode = GET_MODE (mask);
   8722   int w, i;
   8723 
   8724   /* Number of elements in the vector.  */
   8725   w = GET_MODE_NUNITS (mode);
   8726 
   8727   rtx round_data[MAX_VECT_LEN];
   8728   rtx round_reg, round_data_rtx;
   8729 
   8730   if (mode != E_V32QImode)
   8731     {
   8732       for (int i = 0; i < w; i += 1)
   8733 	{
   8734 	  round_data[i] = GEN_INT (0x1f);
   8735 	}
   8736 
   8737       if (mode == E_V4DFmode)
   8738 	{
   8739 	  round_data_rtx = gen_rtx_CONST_VECTOR (E_V4DImode,
   8740 						 gen_rtvec_v (w, round_data));
   8741 	  round_reg = gen_reg_rtx (E_V4DImode);
   8742 	}
   8743       else if (mode == E_V8SFmode)
   8744 	{
   8745 
   8746 	  round_data_rtx = gen_rtx_CONST_VECTOR (E_V8SImode,
   8747 						 gen_rtvec_v (w, round_data));
   8748 	  round_reg = gen_reg_rtx (E_V8SImode);
   8749 	}
   8750       else
   8751 	{
   8752 	  round_data_rtx = gen_rtx_CONST_VECTOR (mode,
   8753 						 gen_rtvec_v (w, round_data));
   8754 	  round_reg = gen_reg_rtx (mode);
   8755 	}
   8756 
   8757       emit_move_insn (round_reg, round_data_rtx);
   8758       switch (mode)
   8759 	{
   8760 	case E_V32QImode:
   8761 	  emit_insn (gen_andv32qi3 (mask, mask, round_reg));
   8762 	  break;
   8763 	case E_V16HImode:
   8764 	  emit_insn (gen_andv16hi3 (mask, mask, round_reg));
   8765 	  break;
   8766 	case E_V8SImode:
   8767 	case E_V8SFmode:
   8768 	  emit_insn (gen_andv8si3 (mask, mask, round_reg));
   8769 	  break;
   8770 	case E_V4DImode:
   8771 	case E_V4DFmode:
   8772 	  emit_insn (gen_andv4di3 (mask, mask, round_reg));
   8773 	  break;
   8774 	default:
   8775 	  gcc_unreachable ();
   8776 	  break;
   8777 	}
   8778     }
   8779 
   8780   if (mode == V4DImode || mode == V4DFmode)
   8781     {
   8782       maskmode = mode = V8SImode;
   8783       w = 8;
   8784       t1 = gen_reg_rtx (maskmode);
   8785 
   8786       /* Replicate the low bits of the V4DImode mask into V8SImode:
   8787 	 mask = { A B C D }
   8788 	 t1 = { A A B B C C D D }.  */
   8789       for (i = 0; i < w / 2; ++i)
   8790 	vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
   8791       vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
   8792       vt = force_reg (maskmode, vt);
   8793       mask = gen_lowpart (maskmode, mask);
   8794       emit_insn (gen_lasx_xvperm_w (t1, mask, vt));
   8795 
   8796       /* Multiply the shuffle indicies by two.  */
   8797       t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
   8798 				OPTAB_DIRECT);
   8799 
   8800       /* Add one to the odd shuffle indicies:
   8801 	 t1 = { A*2, A*2+1, B*2, B*2+1, ... }.  */
   8802       for (i = 0; i < w / 2; ++i)
   8803 	{
   8804 	  vec[i * 2] = const0_rtx;
   8805 	  vec[i * 2 + 1] = const1_rtx;
   8806 	}
   8807       vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
   8808       vt = validize_mem (force_const_mem (maskmode, vt));
   8809       t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
   8810 				OPTAB_DIRECT);
   8811 
   8812       /* Continue as if V8SImode (resp.  V32QImode) was used initially.  */
   8813       operands[3] = mask = t1;
   8814       target = gen_reg_rtx (mode);
   8815       op0 = gen_lowpart (mode, op0);
   8816       op1 = gen_lowpart (mode, op1);
   8817     }
   8818 
   8819   switch (mode)
   8820     {
   8821     case E_V8SImode:
   8822       if (one_operand_shuffle)
   8823 	{
   8824 	  emit_insn (gen_lasx_xvperm_w (target, op0, mask));
   8825 	  if (target != operands[0])
   8826 	    emit_move_insn (operands[0],
   8827 			    gen_lowpart (GET_MODE (operands[0]), target));
   8828 	}
   8829       else
   8830 	{
   8831 	  t1 = gen_reg_rtx (V8SImode);
   8832 	  t2 = gen_reg_rtx (V8SImode);
   8833 	  emit_insn (gen_lasx_xvperm_w (t1, op0, mask));
   8834 	  emit_insn (gen_lasx_xvperm_w (t2, op1, mask));
   8835 	  goto merge_two;
   8836 	}
   8837       return;
   8838 
   8839     case E_V8SFmode:
   8840       mask = gen_lowpart (V8SImode, mask);
   8841       if (one_operand_shuffle)
   8842 	emit_insn (gen_lasx_xvperm_w_f (target, op0, mask));
   8843       else
   8844 	{
   8845 	  t1 = gen_reg_rtx (V8SFmode);
   8846 	  t2 = gen_reg_rtx (V8SFmode);
   8847 	  emit_insn (gen_lasx_xvperm_w_f (t1, op0, mask));
   8848 	  emit_insn (gen_lasx_xvperm_w_f (t2, op1, mask));
   8849 	  goto merge_two;
   8850 	}
   8851       return;
   8852 
   8853     case E_V16HImode:
   8854       if (one_operand_shuffle)
   8855 	{
   8856 	  t1 = gen_reg_rtx (V16HImode);
   8857 	  t2 = gen_reg_rtx (V16HImode);
   8858 	  emit_insn (gen_lasx_xvpermi_d_v16hi (t1, op0, GEN_INT (0x44)));
   8859 	  emit_insn (gen_lasx_xvpermi_d_v16hi (t2, op0, GEN_INT (0xee)));
   8860 	  emit_insn (gen_lasx_xvshuf_h (target, mask, t2, t1));
   8861 	}
   8862       else
   8863 	{
   8864 	  t1 = gen_reg_rtx (V16HImode);
   8865 	  t2 = gen_reg_rtx (V16HImode);
   8866 	  t3 = gen_reg_rtx (V16HImode);
   8867 	  t4 = gen_reg_rtx (V16HImode);
   8868 	  t5 = gen_reg_rtx (V16HImode);
   8869 	  t6 = gen_reg_rtx (V16HImode);
   8870 	  emit_insn (gen_lasx_xvpermi_d_v16hi (t3, op0, GEN_INT (0x44)));
   8871 	  emit_insn (gen_lasx_xvpermi_d_v16hi (t4, op0, GEN_INT (0xee)));
   8872 	  emit_insn (gen_lasx_xvshuf_h (t1, mask, t4, t3));
   8873 	  emit_insn (gen_lasx_xvpermi_d_v16hi (t5, op1, GEN_INT (0x44)));
   8874 	  emit_insn (gen_lasx_xvpermi_d_v16hi (t6, op1, GEN_INT (0xee)));
   8875 	  emit_insn (gen_lasx_xvshuf_h (t2, mask, t6, t5));
   8876 	  goto merge_two;
   8877 	}
   8878       return;
   8879 
   8880     case E_V32QImode:
   8881       if (one_operand_shuffle)
   8882 	{
   8883 	  t1 = gen_reg_rtx (V32QImode);
   8884 	  t2 = gen_reg_rtx (V32QImode);
   8885 	  emit_insn (gen_lasx_xvpermi_d_v32qi (t1, op0, GEN_INT (0x44)));
   8886 	  emit_insn (gen_lasx_xvpermi_d_v32qi (t2, op0, GEN_INT (0xee)));
   8887 	  emit_insn (gen_lasx_xvshuf_b (target, t2, t1, mask));
   8888 	}
   8889       else
   8890 	{
   8891 	  t1 = gen_reg_rtx (V32QImode);
   8892 	  t2 = gen_reg_rtx (V32QImode);
   8893 	  t3 = gen_reg_rtx (V32QImode);
   8894 	  t4 = gen_reg_rtx (V32QImode);
   8895 	  t5 = gen_reg_rtx (V32QImode);
   8896 	  t6 = gen_reg_rtx (V32QImode);
   8897 	  emit_insn (gen_lasx_xvpermi_d_v32qi (t3, op0, GEN_INT (0x44)));
   8898 	  emit_insn (gen_lasx_xvpermi_d_v32qi (t4, op0, GEN_INT (0xee)));
   8899 	  emit_insn (gen_lasx_xvshuf_b (t1, t4, t3, mask));
   8900 	  emit_insn (gen_lasx_xvpermi_d_v32qi (t5, op1, GEN_INT (0x44)));
   8901 	  emit_insn (gen_lasx_xvpermi_d_v32qi (t6, op1, GEN_INT (0xee)));
   8902 	  emit_insn (gen_lasx_xvshuf_b (t2, t6, t5, mask));
   8903 	  goto merge_two;
   8904 	}
   8905       return;
   8906 
   8907     default:
   8908       gcc_assert (GET_MODE_SIZE (mode) == 32);
   8909       break;
   8910     }
   8911 
   8912 merge_two:
   8913   /* Then merge them together.  The key is whether any given control
   8914      element contained a bit set that indicates the second word.  */
   8915   rtx xops[6];
   8916   mask = operands[3];
   8917   vt = GEN_INT (w);
   8918   vt = gen_const_vec_duplicate (maskmode, vt);
   8919   vt = force_reg (maskmode, vt);
   8920   mask = expand_simple_binop (maskmode, AND, mask, vt,
   8921 			      NULL_RTX, 0, OPTAB_DIRECT);
   8922   if (GET_MODE (target) != mode)
   8923     target = gen_reg_rtx (mode);
   8924   xops[0] = target;
   8925   xops[1] = gen_lowpart (mode, t2);
   8926   xops[2] = gen_lowpart (mode, t1);
   8927   xops[3] = gen_rtx_EQ (maskmode, mask, vt);
   8928   xops[4] = mask;
   8929   xops[5] = vt;
   8930 
   8931   loongarch_expand_vec_cond_expr (mode, maskmode, xops);
   8932   if (target != operands[0])
   8933     emit_move_insn (operands[0],
   8934 		    gen_lowpart (GET_MODE (operands[0]), target));
   8935 }
   8936 
   8937 void
   8938 loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel)
   8939 {
   8940   machine_mode vmode = GET_MODE (target);
   8941   machine_mode vimode = GET_MODE (sel);
   8942   auto nelt = GET_MODE_NUNITS (vmode);
   8943   auto round_reg = gen_reg_rtx (vimode);
   8944   rtx round_data[MAX_VECT_LEN];
   8945 
   8946   for (int i = 0; i < nelt; i += 1)
   8947     {
   8948       round_data[i] = GEN_INT (0x1f);
   8949     }
   8950 
   8951   rtx round_data_rtx = gen_rtx_CONST_VECTOR (vimode, gen_rtvec_v (nelt, round_data));
   8952   emit_move_insn (round_reg, round_data_rtx);
   8953 
   8954   if (vmode != vimode)
   8955     {
   8956       target = lowpart_subreg (vimode, target, vmode);
   8957       op0 = lowpart_subreg (vimode, op0, vmode);
   8958       op1 = lowpart_subreg (vimode, op1, vmode);
   8959     }
   8960 
   8961   switch (vmode)
   8962     {
   8963     case E_V16QImode:
   8964       emit_insn (gen_andv16qi3 (sel, sel, round_reg));
   8965       emit_insn (gen_lsx_vshuf_b (target, op1, op0, sel));
   8966       break;
   8967     case E_V2DFmode:
   8968     case E_V2DImode:
   8969       emit_insn (gen_andv2di3 (sel, sel, round_reg));
   8970       emit_insn (gen_lsx_vshuf_d (target, sel, op1, op0));
   8971       break;
   8972     case E_V4SFmode:
   8973     case E_V4SImode:
   8974       emit_insn (gen_andv4si3 (sel, sel, round_reg));
   8975       emit_insn (gen_lsx_vshuf_w (target, sel, op1, op0));
   8976       break;
   8977     case E_V8HImode:
   8978       emit_insn (gen_andv8hi3 (sel, sel, round_reg));
   8979       emit_insn (gen_lsx_vshuf_h (target, sel, op1, op0));
   8980       break;
   8981     default:
   8982       break;
   8983     }
   8984 }
   8985 
   8986 /* Following are the assist function for const vector permutation support.  */
   8987 static bool
   8988 loongarch_is_quad_duplicate (struct expand_vec_perm_d *d)
   8989 {
   8990   if (d->perm[0] >= d->nelt / 2)
   8991     return false;
   8992 
   8993   bool result = true;
   8994   unsigned char lhs = d->perm[0];
   8995   unsigned char rhs = d->perm[d->nelt / 2];
   8996 
   8997   if ((rhs - lhs) != d->nelt / 2)
   8998     return false;
   8999 
   9000   for (int i = 1; i < d->nelt; i += 1)
   9001     {
   9002       if ((i < d->nelt / 2) && (d->perm[i] != lhs))
   9003 	{
   9004 	  result = false;
   9005 	  break;
   9006 	}
   9007       if ((i > d->nelt / 2) && (d->perm[i] != rhs))
   9008 	{
   9009 	  result = false;
   9010 	  break;
   9011 	}
   9012     }
   9013 
   9014   return result;
   9015 }
   9016 
   9017 static bool
   9018 loongarch_is_extraction_permutation (struct expand_vec_perm_d *d)
   9019 {
   9020   bool result = true;
   9021   unsigned char buf = d->perm[0];
   9022 
   9023   if (buf != 0 || buf != d->nelt)
   9024     return false;
   9025 
   9026   for (int i = 0; i < d->nelt; i += 1)
   9027     {
   9028       if (buf != d->perm[i])
   9029 	{
   9030 	  result = false;
   9031 	  break;
   9032 	}
   9033       buf += 1;
   9034     }
   9035 
   9036   return result;
   9037 }
   9038 
   9039 static bool
   9040 loongarch_is_lasx_lowpart_interleave (struct expand_vec_perm_d *d)
   9041 {
   9042   bool result = true;
   9043   unsigned char buf = 0;
   9044 
   9045   for (int i = 0;i < d->nelt; i += 2)
   9046     {
   9047       if (buf != d->perm[i])
   9048 	{
   9049 	  result = false;
   9050 	  break;
   9051 	}
   9052       buf += 1;
   9053     }
   9054 
   9055   if (result)
   9056     {
   9057       buf = d->nelt;
   9058       for (int i = 1; i < d->nelt; i += 2)
   9059 	{
   9060 	  if (buf != d->perm[i])
   9061 	    {
   9062 	      result = false;
   9063 	      break;
   9064 	    }
   9065 	  buf += 1;
   9066 	}
   9067     }
   9068 
   9069   return result;
   9070 }
   9071 
   9072 static bool
   9073 loongarch_is_lasx_lowpart_interleave_2 (struct expand_vec_perm_d *d)
   9074 {
   9075   if (d->vmode != E_V32QImode)
   9076     return false;
   9077   bool result = true;
   9078   unsigned char buf = 0;
   9079 
   9080 #define COMPARE_SELECTOR(INIT, BEGIN, END) \
   9081   buf = INIT; \
   9082   for (int i = BEGIN; i < END && result; i += 1) \
   9083     { \
   9084       if (buf != d->perm[i]) \
   9085 	{ \
   9086 	  result = false; \
   9087 	  break; \
   9088 	} \
   9089       buf += 1; \
   9090     }
   9091 
   9092   COMPARE_SELECTOR (0, 0, 8);
   9093   COMPARE_SELECTOR (32, 8, 16);
   9094   COMPARE_SELECTOR (8, 16, 24);
   9095   COMPARE_SELECTOR (40, 24, 32);
   9096 
   9097 #undef COMPARE_SELECTOR
   9098   return result;
   9099 }
   9100 
   9101 static bool
   9102 loongarch_is_lasx_highpart_interleave (expand_vec_perm_d *d)
   9103 {
   9104   bool result = true;
   9105   unsigned char buf = d->nelt / 2;
   9106 
   9107   for (int i = 0; i < d->nelt; i += 2)
   9108     {
   9109       if (buf != d->perm[i])
   9110 	{
   9111 	  result = false;
   9112 	  break;
   9113 	}
   9114       buf += 1;
   9115     }
   9116 
   9117   if (result)
   9118     {
   9119       buf = d->nelt + d->nelt / 2;
   9120       for (int i = 1; i < d->nelt;i += 2)
   9121 	{
   9122 	  if (buf != d->perm[i])
   9123 	    {
   9124 	      result = false;
   9125 	      break;
   9126 	    }
   9127 	  buf += 1;
   9128 	}
   9129     }
   9130 
   9131   return result;
   9132 }
   9133 
   9134 static bool
   9135 loongarch_is_lasx_highpart_interleave_2 (struct expand_vec_perm_d *d)
   9136 {
   9137   if (d->vmode != E_V32QImode)
   9138     return false;
   9139 
   9140   bool result = true;
   9141   unsigned char buf = 0;
   9142 
   9143 #define COMPARE_SELECTOR(INIT, BEGIN, END) \
   9144   buf = INIT; \
   9145   for (int i = BEGIN; i < END && result; i += 1) \
   9146     { \
   9147       if (buf != d->perm[i]) \
   9148 	{ \
   9149 	  result = false; \
   9150 	  break; \
   9151 	} \
   9152       buf += 1; \
   9153     }
   9154 
   9155   COMPARE_SELECTOR (16, 0, 8);
   9156   COMPARE_SELECTOR (48, 8, 16);
   9157   COMPARE_SELECTOR (24, 16, 24);
   9158   COMPARE_SELECTOR (56, 24, 32);
   9159 
   9160 #undef COMPARE_SELECTOR
   9161   return result;
   9162 }
   9163 
   9164 static bool
   9165 loongarch_is_elem_duplicate (struct expand_vec_perm_d *d)
   9166 {
   9167   bool result = true;
   9168   unsigned char buf = d->perm[0];
   9169 
   9170   for (int i = 0; i < d->nelt; i += 1)
   9171     {
   9172       if (buf != d->perm[i])
   9173 	{
   9174 	  result = false;
   9175 	  break;
   9176 	}
   9177     }
   9178 
   9179   return result;
   9180 }
   9181 
   9182 /* In LASX, some permutation insn does not have the behavior that gcc expects
   9183    when compiler wants to emit a vector permutation.
   9184 
   9185    1.  What GCC provides via vectorize_vec_perm_const ()'s paramater:
   9186    When GCC wants to performs a vector permutation, it provides two op
   9187    reigster, one target register, and a selector.
   9188    In const vector permutation case, GCC provides selector as a char array
   9189    that contains original value; in variable vector permuatation
   9190    (performs via vec_perm<mode> insn template), it provides a vector register.
   9191    We assume that nelt is the elements numbers inside single vector in current
   9192    256bit vector mode.
   9193 
   9194    2.  What GCC expects to perform:
   9195    Two op registers (op0, op1) will "combine" into a 512bit temp vector storage
   9196    that has 2*nelt elements inside it; the low 256bit is op0, and high 256bit
   9197    is op1, then the elements are indexed as below:
   9198    0 ~ nelt - 1		nelt ~ 2 * nelt - 1
   9199    |-------------------------|-------------------------|
   9200    Low 256bit (op0)	High 256bit (op1)
   9201    For example, the second element in op1 (V8SImode) will be indexed with 9.
   9202    Selector is a vector that has the same mode and number of elements  with
   9203    op0,op1 and target, it's look like this:
   9204    0 ~ nelt - 1
   9205    |-------------------------|
   9206    256bit (selector)
   9207    It describes which element from 512bit temp vector storage will fit into
   9208    target's every element slot.
   9209    GCC expects that every element in selector can be ANY indices of 512bit
   9210    vector storage (Selector can pick literally any element from op0 and op1, and
   9211    then fits into any place of target register). This is also what LSX 128bit
   9212    vshuf.* instruction do similarly, so we can handle 128bit vector permutation
   9213    by single instruction easily.
   9214 
   9215    3.  What LASX permutation instruction does:
   9216    In short, it just execute two independent 128bit vector permuatation, and
   9217    it's the reason that we need to do the jobs below.  We will explain it.
   9218    op0, op1, target, and selector will be separate into high 128bit and low
   9219    128bit, and do permutation as the description below:
   9220 
   9221    a) op0's low 128bit and op1's low 128bit "combines" into a 256bit temp
   9222    vector storage (TVS1), elements are indexed as below:
   9223    0 ~ nelt / 2 - 1	  nelt / 2 ~ nelt - 1
   9224    |---------------------|---------------------| TVS1
   9225    op0's low 128bit      op1's low 128bit
   9226    op0's high 128bit and op1's high 128bit are "combined" into TVS2 in the
   9227    same way.
   9228    0 ~ nelt / 2 - 1	  nelt / 2 ~ nelt - 1
   9229    |---------------------|---------------------| TVS2
   9230    op0's high 128bit	op1's high 128bit
   9231    b) Selector's low 128bit describes which elements from TVS1 will fit into
   9232    target vector's low 128bit.  No TVS2 elements are allowed.
   9233    c) Selector's high 128bit describes which elements from TVS2 will fit into
   9234    target vector's high 128bit.  No TVS1 elements are allowed.
   9235 
   9236    As we can see, if we want to handle vector permutation correctly, we can
   9237    achieve it in three ways:
   9238    a) Modify selector's elements, to make sure that every elements can inform
   9239    correct value that will put into target vector.
   9240    b) Generate extra instruction before/after permutation instruction, for
   9241    adjusting op vector or target vector, to make sure target vector's value is
   9242    what GCC expects.
   9243    c) Use other instructions to process op and put correct result into target.
   9244    */
   9245 
   9246 /* Implementation of constant vector permuatation.  This function identifies
   9247    recognized pattern of permuation selector argument, and use one or more
   9248    instruction (s) to finish the permutation job correctly.  For unsupported
   9249    patterns, it will return false.  */
   9250 
   9251 static bool
   9252 loongarch_expand_vec_perm_const (struct expand_vec_perm_d *d)
   9253 {
   9254   bool flag = false;
   9255   unsigned int i;
   9256   unsigned char idx;
   9257   rtx target, op0, op1, sel, tmp;
   9258   rtx rperm[MAX_VECT_LEN];
   9259   unsigned int remapped[MAX_VECT_LEN];
   9260   unsigned char perm2[MAX_VECT_LEN];
   9261 
   9262   if (GET_MODE_SIZE (d->vmode) == 16)
   9263     return loongarch_expand_lsx_shuffle (d);
   9264   else
   9265     {
   9266       if (d->one_vector_p)
   9267 	{
   9268 	  /* Try interleave with alternating operands.  */
   9269 	  memcpy (perm2, d->perm, sizeof (perm2));
   9270 	  for (i = 1; i < d->nelt; i += 2)
   9271 	    perm2[i] += d->nelt;
   9272 	  if (loongarch_expand_vselect_vconcat (d->target, d->op0, d->op1,
   9273 						perm2, d->nelt, d->testing_p))
   9274 	    return true;
   9275 	}
   9276       else
   9277 	{
   9278 	  if (loongarch_expand_vselect_vconcat (d->target, d->op0, d->op1,
   9279 						d->perm, d->nelt,
   9280 						d->testing_p))
   9281 	    return true;
   9282 
   9283 	  /* Try again with swapped operands.  */
   9284 	  for (i = 0; i < d->nelt; ++i)
   9285 	    perm2[i] = (d->perm[i] + d->nelt) & (2 * d->nelt - 1);
   9286 	  if (loongarch_expand_vselect_vconcat (d->target, d->op1, d->op0,
   9287 						perm2, d->nelt, d->testing_p))
   9288 	    return true;
   9289 	}
   9290 
   9291       if (loongarch_is_imm_set_shuffle (d))
   9292 	return true;
   9293 
   9294       if (loongarch_expand_vec_perm_even_odd (d))
   9295 	return true;
   9296 
   9297       if (loongarch_is_lasx_lowpart_interleave (d)
   9298 	  || loongarch_is_lasx_lowpart_interleave_2 (d)
   9299 	  || loongarch_is_lasx_highpart_interleave (d)
   9300 	  || loongarch_is_lasx_highpart_interleave_2 (d))
   9301 	{
   9302 	  if (loongarch_expand_vec_perm_interleave (d))
   9303 	    return true;
   9304 	}
   9305 
   9306       if (loongarch_is_quad_duplicate (d))
   9307 	{
   9308 	  if (d->testing_p)
   9309 	    return true;
   9310 	  /* Selector example: E_V8SImode, { 0, 0, 0, 0, 4, 4, 4, 4 }.  */
   9311 	  for (i = 0; i < d->nelt; i += 1)
   9312 	    {
   9313 	      rperm[i] = GEN_INT (d->perm[0]);
   9314 	    }
   9315 	  /* Selector after: { 0, 0, 0, 0, 0, 0, 0, 0 }.  */
   9316 	  flag = true;
   9317 	  goto expand_perm_const_end;
   9318 	}
   9319 
   9320       if (loongarch_is_extraction_permutation (d))
   9321 	{
   9322 	  if (d->testing_p)
   9323 	    return true;
   9324 	  /* Selector sample: E_V8SImode, { 0, 1, 2, 3, 4, 5, 6, 7 }.  */
   9325 	  if (d->perm[0] == 0)
   9326 	    {
   9327 	      for (i = 0; i < d->nelt / 2; i += 1)
   9328 		{
   9329 		  remapped[i] = i;
   9330 		  remapped[i + d->nelt / 2] = i;
   9331 		}
   9332 	    }
   9333 	  else
   9334 	    {
   9335 	      /* { 8, 9, 10, 11, 12, 13, 14, 15 }.  */
   9336 	      for (i = 0; i < d->nelt / 2; i += 1)
   9337 		{
   9338 		  idx = i + d->nelt / 2;
   9339 		  remapped[i] = idx;
   9340 		  remapped[i + d->nelt / 2] = idx;
   9341 		}
   9342 	    }
   9343 	  /* Selector after: { 0, 1, 2, 3, 0, 1, 2, 3 }
   9344 	     { 8, 9, 10, 11, 8, 9, 10, 11 }  */
   9345 
   9346 	  /* Convert remapped selector array to RTL array.  */
   9347 	  for (i = 0; i < d->nelt; i += 1)
   9348 	    {
   9349 	      rperm[i] = GEN_INT (remapped[i]);
   9350 	    }
   9351 
   9352 	  flag = true;
   9353 	  goto expand_perm_const_end;
   9354 	}
   9355 
   9356       if (loongarch_is_elem_duplicate (d))
   9357 	{
   9358 	  if (d->testing_p)
   9359 	    return true;
   9360 	  /* Brocast single element (from op0 or op1) to all slot of target
   9361 	     register.
   9362 	     Selector sample:E_V8SImode, { 2, 2, 2, 2, 2, 2, 2, 2 }  */
   9363 	  rtx conv_op1 = simplify_gen_subreg (E_V4DImode, d->op1, d->vmode, 0);
   9364 	  rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0);
   9365 	  rtx temp_reg = gen_reg_rtx (d->vmode);
   9366 	  rtx conv_temp = simplify_gen_subreg (E_V4DImode, temp_reg,
   9367 					       d->vmode, 0);
   9368 	  emit_move_insn (temp_reg, d->op0);
   9369 
   9370 	  idx = d->perm[0];
   9371 	  /* We will use xvrepl128vei.* insn to achieve the result, but we need
   9372 	     to make the high/low 128bit has the same contents that contain the
   9373 	     value that we need to broardcast, because xvrepl128vei does the
   9374 	     broardcast job from every 128bit of source register to
   9375 	     corresponded part of target register! (A deep sigh.)  */
   9376 	  if (idx < d->nelt / 2)
   9377 	    {
   9378 	      emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
   9379 						  conv_op0, GEN_INT (0x0)));
   9380 	    }
   9381 	  else if (idx >= d->nelt / 2 && idx < d->nelt)
   9382 	    {
   9383 	      emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
   9384 						  conv_op0, GEN_INT (0x11)));
   9385 	      idx -= d->nelt / 2;
   9386 	    }
   9387 	  else if (idx >= d->nelt && idx < (d->nelt + d->nelt / 2))
   9388 	    {
   9389 	      emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
   9390 						  conv_op1, GEN_INT (0x0)));
   9391 	    }
   9392 	  else if (idx >= (d->nelt + d->nelt / 2) && idx < d->nelt * 2)
   9393 	    {
   9394 	      emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
   9395 						  conv_op1, GEN_INT (0x11)));
   9396 	      idx -= d->nelt / 2;
   9397 	    }
   9398 
   9399 	  /* Then we can finally generate this insn.  */
   9400 	  switch (d->vmode)
   9401 	    {
   9402 	    case E_V4DImode:
   9403 	      emit_insn (gen_lasx_xvrepl128vei_d (d->target, temp_reg,
   9404 						  GEN_INT (idx)));
   9405 	      break;
   9406 	    case E_V4DFmode:
   9407 	      emit_insn (gen_lasx_xvrepl128vei_d_f (d->target, temp_reg,
   9408 						    GEN_INT (idx)));
   9409 	      break;
   9410 	    case E_V8SImode:
   9411 	      emit_insn (gen_lasx_xvrepl128vei_w (d->target, temp_reg,
   9412 						  GEN_INT (idx)));
   9413 	      break;
   9414 	    case E_V8SFmode:
   9415 	      emit_insn (gen_lasx_xvrepl128vei_w_f (d->target, temp_reg,
   9416 						    GEN_INT (idx)));
   9417 	      break;
   9418 	    case E_V16HImode:
   9419 	      emit_insn (gen_lasx_xvrepl128vei_h (d->target, temp_reg,
   9420 						  GEN_INT (idx)));
   9421 	      break;
   9422 	    case E_V32QImode:
   9423 	      emit_insn (gen_lasx_xvrepl128vei_b (d->target, temp_reg,
   9424 						  GEN_INT (idx)));
   9425 	      break;
   9426 	    default:
   9427 	      gcc_unreachable ();
   9428 	      break;
   9429 	    }
   9430 
   9431 	  return true;
   9432 	}
   9433 
   9434 expand_perm_const_end:
   9435       if (flag)
   9436 	{
   9437 	  /* Copy selector vector from memory to vector register for later insn
   9438 	     gen function.
   9439 	     If vector's element in floating point value, we cannot fit
   9440 	     selector argument into insn gen function directly, because of the
   9441 	     insn template definition.  As a solution, generate a integral mode
   9442 	     subreg of target, then copy selector vector (that is in integral
   9443 	     mode) to this subreg.  */
   9444 	  switch (d->vmode)
   9445 	    {
   9446 	    case E_V4DFmode:
   9447 	      sel = gen_rtx_CONST_VECTOR (E_V4DImode, gen_rtvec_v (d->nelt,
   9448 								   rperm));
   9449 	      tmp = simplify_gen_subreg (E_V4DImode, d->target, d->vmode, 0);
   9450 	      emit_move_insn (tmp, sel);
   9451 	      break;
   9452 	    case E_V8SFmode:
   9453 	      sel = gen_rtx_CONST_VECTOR (E_V8SImode, gen_rtvec_v (d->nelt,
   9454 								   rperm));
   9455 	      tmp = simplify_gen_subreg (E_V8SImode, d->target, d->vmode, 0);
   9456 	      emit_move_insn (tmp, sel);
   9457 	      break;
   9458 	    default:
   9459 	      sel = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (d->nelt,
   9460 								 rperm));
   9461 	      emit_move_insn (d->target, sel);
   9462 	      break;
   9463 	    }
   9464 
   9465 	  target = d->target;
   9466 	  op0 = d->op0;
   9467 	  op1 = d->one_vector_p ? d->op0 : d->op1;
   9468 
   9469 	  /* We FINALLY can generate xvshuf.* insn.  */
   9470 	  switch (d->vmode)
   9471 	    {
   9472 	    case E_V4DFmode:
   9473 	      emit_insn (gen_lasx_xvshuf_d_f (target, target, op1, op0));
   9474 	      break;
   9475 	    case E_V4DImode:
   9476 	      emit_insn (gen_lasx_xvshuf_d (target, target, op1, op0));
   9477 	      break;
   9478 	    case E_V8SFmode:
   9479 	      emit_insn (gen_lasx_xvshuf_w_f (target, target, op1, op0));
   9480 	      break;
   9481 	    case E_V8SImode:
   9482 	      emit_insn (gen_lasx_xvshuf_w (target, target, op1, op0));
   9483 	      break;
   9484 	    case E_V16HImode:
   9485 	      emit_insn (gen_lasx_xvshuf_h (target, target, op1, op0));
   9486 	      break;
   9487 	    case E_V32QImode:
   9488 	      emit_insn (gen_lasx_xvshuf_b (target, op1, op0, target));
   9489 	      break;
   9490 	    default:
   9491 	      gcc_unreachable ();
   9492 	      break;
   9493 	    }
   9494 
   9495 	  return true;
   9496 	}
   9497     }
   9498 
   9499   return false;
   9500 }
   9501 
   9502 /* Implement TARGET_VECTORIZE_VEC_PERM_CONST.  */
   9503 
   9504 static bool
   9505 loongarch_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
   9506 				    rtx target, rtx op0, rtx op1,
   9507 				    const vec_perm_indices &sel)
   9508 {
   9509   if (vmode != op_mode)
   9510     return false;
   9511 
   9512   struct expand_vec_perm_d d;
   9513   int i, nelt, which;
   9514   unsigned char orig_perm[MAX_VECT_LEN];
   9515   bool ok;
   9516 
   9517   d.target = target;
   9518   if (op0)
   9519     {
   9520       rtx nop0 = force_reg (vmode, op0);
   9521       if (op0 == op1)
   9522 	op1 = nop0;
   9523       op0 = nop0;
   9524     }
   9525   if (op1)
   9526     op1 = force_reg (vmode, op1);
   9527   d.op0 = op0;
   9528   d.op1 = op1;
   9529 
   9530   d.vmode = vmode;
   9531   gcc_assert (VECTOR_MODE_P (vmode));
   9532   d.nelt = nelt = GET_MODE_NUNITS (vmode);
   9533   d.testing_p = !target;
   9534 
   9535   /* This is overly conservative, but ensures we don't get an
   9536      uninitialized warning on ORIG_PERM.  */
   9537   memset (orig_perm, 0, MAX_VECT_LEN);
   9538   for (i = which = 0; i < nelt; ++i)
   9539     {
   9540       int ei = sel[i] & (2 * nelt - 1);
   9541       which |= (ei < nelt ? 1 : 2);
   9542       orig_perm[i] = ei;
   9543     }
   9544   memcpy (d.perm, orig_perm, MAX_VECT_LEN);
   9545 
   9546   switch (which)
   9547     {
   9548     default:
   9549       gcc_unreachable ();
   9550 
   9551     case 3:
   9552       d.one_vector_p = false;
   9553       if (d.testing_p || !rtx_equal_p (d.op0, d.op1))
   9554 	break;
   9555       /* FALLTHRU */
   9556 
   9557     case 2:
   9558       for (i = 0; i < nelt; ++i)
   9559 	d.perm[i] &= nelt - 1;
   9560       d.op0 = d.op1;
   9561       d.one_vector_p = true;
   9562       break;
   9563 
   9564     case 1:
   9565       d.op1 = d.op0;
   9566       d.one_vector_p = true;
   9567       break;
   9568     }
   9569 
   9570   // Do rounding for selector to avoid vshuf undefined behavior.
   9571   for (i = 0; i < d.nelt; i += 1)
   9572     {
   9573       d.perm[i] %= (d.nelt * 2);
   9574     }
   9575 
   9576   if (d.testing_p)
   9577     {
   9578       d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
   9579       d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
   9580       if (!d.one_vector_p)
   9581 	d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
   9582 
   9583       start_sequence ();
   9584       ok = loongarch_expand_vec_perm_const (&d);
   9585       end_sequence ();
   9586       return ok;
   9587     }
   9588 
   9589   ok = loongarch_expand_vec_perm_const (&d);
   9590 
   9591   /* If we were given a two-vector permutation which just happened to
   9592      have both input vectors equal, we folded this into a one-vector
   9593      permutation.  There are several loongson patterns that are matched
   9594      via direct vec_select+vec_concat expansion, but we do not have
   9595      support in loongarch_expand_vec_perm_const to guess the adjustment
   9596      that should be made for a single operand.  Just try again with
   9597      the original permutation.  */
   9598   if (!ok && which == 3)
   9599     {
   9600       d.op0 = op0;
   9601       d.op1 = op1;
   9602       d.one_vector_p = false;
   9603       memcpy (d.perm, orig_perm, MAX_VECT_LEN);
   9604       ok = loongarch_expand_vec_perm_const (&d);
   9605     }
   9606 
   9607   return ok;
   9608 }
   9609 
   9610 static int
   9611 loongarch_cpu_sched_reassociation_width (struct loongarch_target *target,
   9612 					 unsigned int opc, machine_mode mode)
   9613 {
   9614   /* unreferenced argument */
   9615   (void) opc;
   9616 
   9617   switch (target->cpu_tune)
   9618     {
   9619     case TUNE_GENERIC:
   9620     case TUNE_LOONGARCH64:
   9621     case TUNE_LA464:
   9622     case TUNE_LA664:
   9623       /* Vector part.  */
   9624       if (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))
   9625 	{
   9626 	  /* Integer vector instructions execute in FP unit.
   9627 	     The width of integer/float-point vector instructions is 3.  */
   9628 	  return 3;
   9629 	}
   9630 
   9631       /* Scalar part.  */
   9632       else if (INTEGRAL_MODE_P (mode))
   9633 	return 1;
   9634       else if (FLOAT_MODE_P (mode))
   9635 	{
   9636 	  if (opc == PLUS_EXPR)
   9637 	    {
   9638 	      return 2;
   9639 	    }
   9640 	  return 4;
   9641 	}
   9642       break;
   9643     default:
   9644       break;
   9645     }
   9646 
   9647   /* default is 1 */
   9648   return 1;
   9649 }
   9650 
   9651 /* Implement TARGET_SCHED_REASSOCIATION_WIDTH.  */
   9652 
   9653 static int
   9654 loongarch_sched_reassociation_width (unsigned int opc, machine_mode mode)
   9655 {
   9656   return loongarch_cpu_sched_reassociation_width (&la_target, opc, mode);
   9657 }
   9658 
   9659 /* Implement extract a scalar element from vecotr register */
   9660 
   9661 void
   9662 loongarch_expand_vector_extract (rtx target, rtx vec, int elt)
   9663 {
   9664   machine_mode mode = GET_MODE (vec);
   9665   machine_mode inner_mode = GET_MODE_INNER (mode);
   9666   rtx tmp;
   9667 
   9668   switch (mode)
   9669     {
   9670     case E_V8HImode:
   9671     case E_V16QImode:
   9672       break;
   9673 
   9674     case E_V32QImode:
   9675       if (ISA_HAS_LASX)
   9676 	{
   9677 	  if (elt >= 16)
   9678 	    {
   9679 	      tmp = gen_reg_rtx (V32QImode);
   9680 	      emit_insn (gen_lasx_xvpermi_d_v32qi (tmp, vec, GEN_INT (0xe)));
   9681 	      loongarch_expand_vector_extract (target,
   9682 					       gen_lowpart (V16QImode, tmp),
   9683 					       elt & 15);
   9684 	    }
   9685 	  else
   9686 	    loongarch_expand_vector_extract (target,
   9687 					     gen_lowpart (V16QImode, vec),
   9688 					     elt & 15);
   9689 	  return;
   9690 	}
   9691       break;
   9692 
   9693     case E_V16HImode:
   9694       if (ISA_HAS_LASX)
   9695 	{
   9696 	  if (elt >= 8)
   9697 	    {
   9698 	      tmp = gen_reg_rtx (V16HImode);
   9699 	      emit_insn (gen_lasx_xvpermi_d_v16hi (tmp, vec, GEN_INT (0xe)));
   9700 	      loongarch_expand_vector_extract (target,
   9701 					       gen_lowpart (V8HImode, tmp),
   9702 					       elt & 7);
   9703 	    }
   9704 	  else
   9705 	    loongarch_expand_vector_extract (target,
   9706 					     gen_lowpart (V8HImode, vec),
   9707 					     elt & 7);
   9708 	  return;
   9709 	}
   9710       break;
   9711 
   9712     default:
   9713       break;
   9714     }
   9715 
   9716   tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
   9717   tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
   9718 
   9719   /* Let the rtl optimizers know about the zero extension performed.  */
   9720   if (inner_mode == QImode || inner_mode == HImode)
   9721     {
   9722       tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
   9723       target = gen_lowpart (SImode, target);
   9724     }
   9725   if (inner_mode == SImode || inner_mode == DImode)
   9726     {
   9727       tmp = gen_rtx_SIGN_EXTEND (inner_mode, tmp);
   9728     }
   9729 
   9730   emit_insn (gen_rtx_SET (target, tmp));
   9731 }
   9732 
   9733 /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
   9734    to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
   9735    The upper bits of DEST are undefined, though they shouldn't cause
   9736    exceptions (some bits from src or all zeros are ok).  */
   9737 
   9738 static void
   9739 emit_reduc_half (rtx dest, rtx src, int i)
   9740 {
   9741   rtx tem, d = dest;
   9742   switch (GET_MODE (src))
   9743     {
   9744     case E_V4SFmode:
   9745       tem = gen_lsx_vbsrl_w_f (dest, src, GEN_INT (i == 128 ? 8 : 4));
   9746       break;
   9747     case E_V2DFmode:
   9748       tem = gen_lsx_vbsrl_d_f (dest, src, GEN_INT (8));
   9749       break;
   9750     case E_V8SFmode:
   9751       if (i == 256)
   9752 	tem = gen_lasx_xvpermi_d_v8sf (dest, src, GEN_INT (0xe));
   9753       else
   9754 	tem = gen_lasx_xvshuf4i_w_f (dest, src,
   9755 				     GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
   9756       break;
   9757     case E_V4DFmode:
   9758       if (i == 256)
   9759 	tem = gen_lasx_xvpermi_d_v4df (dest, src, GEN_INT (0xe));
   9760       else
   9761 	tem = gen_lasx_xvpermi_d_v4df (dest, src, const1_rtx);
   9762       break;
   9763     case E_V32QImode:
   9764     case E_V16HImode:
   9765     case E_V8SImode:
   9766     case E_V4DImode:
   9767       d = gen_reg_rtx (V4DImode);
   9768       if (i == 256)
   9769 	tem = gen_lasx_xvpermi_d_v4di (d, gen_lowpart (V4DImode, src),
   9770 				       GEN_INT (0xe));
   9771       else
   9772 	tem = gen_lasx_xvbsrl_d (d, gen_lowpart (V4DImode, src),
   9773 				 GEN_INT (i/16));
   9774       break;
   9775     case E_V16QImode:
   9776     case E_V8HImode:
   9777     case E_V4SImode:
   9778     case E_V2DImode:
   9779       d = gen_reg_rtx (V2DImode);
   9780       tem = gen_lsx_vbsrl_d (d, gen_lowpart (V2DImode, src), GEN_INT (i/16));
   9781       break;
   9782     default:
   9783       gcc_unreachable ();
   9784     }
   9785   emit_insn (tem);
   9786   if (d != dest)
   9787     emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
   9788 }
   9789 
   9790 /* Expand a vector reduction.  FN is the binary pattern to reduce;
   9791    DEST is the destination; IN is the input vector.  */
   9792 
   9793 void
   9794 loongarch_expand_vector_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
   9795 {
   9796   rtx half, dst, vec = in;
   9797   machine_mode mode = GET_MODE (in);
   9798   int i;
   9799 
   9800   for (i = GET_MODE_BITSIZE (mode);
   9801        i > GET_MODE_UNIT_BITSIZE (mode);
   9802        i >>= 1)
   9803     {
   9804       half = gen_reg_rtx (mode);
   9805       emit_reduc_half (half, vec, i);
   9806       if (i == GET_MODE_UNIT_BITSIZE (mode) * 2)
   9807 	dst = dest;
   9808       else
   9809 	dst = gen_reg_rtx (mode);
   9810       emit_insn (fn (dst, half, vec));
   9811       vec = dst;
   9812     }
   9813 }
   9814 
   9815 /* Expand an integral vector unpack operation.  */
   9816 
   9817 void
   9818 loongarch_expand_vec_unpack (rtx operands[2], bool unsigned_p, bool high_p)
   9819 {
   9820   machine_mode imode = GET_MODE (operands[1]);
   9821   rtx (*unpack) (rtx, rtx, rtx);
   9822   rtx (*extend) (rtx, rtx);
   9823   rtx (*cmpFunc) (rtx, rtx, rtx);
   9824   rtx (*swap_hi_lo) (rtx, rtx, rtx, rtx);
   9825   rtx tmp, dest;
   9826 
   9827   if (ISA_HAS_LASX && GET_MODE_SIZE (imode) == 32)
   9828     {
   9829       switch (imode)
   9830 	{
   9831 	case E_V8SImode:
   9832 	  if (unsigned_p)
   9833 	    extend = gen_lasx_vext2xv_du_wu;
   9834 	  else
   9835 	    extend = gen_lasx_vext2xv_d_w;
   9836 	  swap_hi_lo = gen_lasx_xvpermi_q_v8si;
   9837 	  break;
   9838 
   9839 	case E_V16HImode:
   9840 	  if (unsigned_p)
   9841 	    extend = gen_lasx_vext2xv_wu_hu;
   9842 	  else
   9843 	    extend = gen_lasx_vext2xv_w_h;
   9844 	  swap_hi_lo = gen_lasx_xvpermi_q_v16hi;
   9845 	  break;
   9846 
   9847 	case E_V32QImode:
   9848 	  if (unsigned_p)
   9849 	    extend = gen_lasx_vext2xv_hu_bu;
   9850 	  else
   9851 	    extend = gen_lasx_vext2xv_h_b;
   9852 	  swap_hi_lo = gen_lasx_xvpermi_q_v32qi;
   9853 	  break;
   9854 
   9855 	default:
   9856 	  gcc_unreachable ();
   9857 	  break;
   9858 	}
   9859 
   9860       if (high_p)
   9861 	{
   9862 	  tmp = gen_reg_rtx (imode);
   9863 	  emit_insn (swap_hi_lo (tmp, tmp, operands[1], const1_rtx));
   9864 	  emit_insn (extend (operands[0], tmp));
   9865 	  return;
   9866 	}
   9867 
   9868       emit_insn (extend (operands[0], operands[1]));
   9869       return;
   9870 
   9871     }
   9872   else if (ISA_HAS_LSX)
   9873     {
   9874       switch (imode)
   9875 	{
   9876 	case E_V4SImode:
   9877 	  if (high_p != 0)
   9878 	    unpack = gen_lsx_vilvh_w;
   9879 	  else
   9880 	    unpack = gen_lsx_vilvl_w;
   9881 
   9882 	  cmpFunc = gen_lsx_vslt_w;
   9883 	  break;
   9884 
   9885 	case E_V8HImode:
   9886 	  if (high_p != 0)
   9887 	    unpack = gen_lsx_vilvh_h;
   9888 	  else
   9889 	    unpack = gen_lsx_vilvl_h;
   9890 
   9891 	  cmpFunc = gen_lsx_vslt_h;
   9892 	  break;
   9893 
   9894 	case E_V16QImode:
   9895 	  if (high_p != 0)
   9896 	    unpack = gen_lsx_vilvh_b;
   9897 	  else
   9898 	    unpack = gen_lsx_vilvl_b;
   9899 
   9900 	  cmpFunc = gen_lsx_vslt_b;
   9901 	  break;
   9902 
   9903 	default:
   9904 	  gcc_unreachable ();
   9905 	  break;
   9906 	}
   9907 
   9908       if (!unsigned_p)
   9909 	{
   9910 	  /* Extract sign extention for each element comparing each element
   9911 	     with immediate zero.  */
   9912 	  tmp = gen_reg_rtx (imode);
   9913 	  emit_insn (cmpFunc (tmp, operands[1], CONST0_RTX (imode)));
   9914 	}
   9915       else
   9916 	tmp = force_reg (imode, CONST0_RTX (imode));
   9917 
   9918       dest = gen_reg_rtx (imode);
   9919 
   9920       emit_insn (unpack (dest, operands[1], tmp));
   9921       emit_move_insn (operands[0], gen_lowpart (GET_MODE (operands[0]), dest));
   9922       return;
   9923     }
   9924   gcc_unreachable ();
   9925 }
   9926 
   9927 /* Construct and return PARALLEL RTX with CONST_INTs for HIGH (high_p == TRUE)
   9928    or LOW (high_p == FALSE) half of a vector for mode MODE.  */
   9929 
   9930 rtx
   9931 loongarch_lsx_vec_parallel_const_half (machine_mode mode, bool high_p)
   9932 {
   9933   int nunits = GET_MODE_NUNITS (mode);
   9934   rtvec v = rtvec_alloc (nunits / 2);
   9935   int base;
   9936   int i;
   9937 
   9938   base = high_p ? nunits / 2 : 0;
   9939 
   9940   for (i = 0; i < nunits / 2; i++)
   9941     RTVEC_ELT (v, i) = GEN_INT (base + i);
   9942 
   9943   return gen_rtx_PARALLEL (VOIDmode, v);
   9944 }
   9945 
   9946 /* A subroutine of loongarch_expand_vec_init, match constant vector
   9947    elements.  */
   9948 
   9949 static inline bool
   9950 loongarch_constant_elt_p (rtx x)
   9951 {
   9952   return CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE;
   9953 }
   9954 
   9955 rtx
   9956 loongarch_gen_const_int_vector_shuffle (machine_mode mode, int val)
   9957 {
   9958   int nunits = GET_MODE_NUNITS (mode);
   9959   int nsets = nunits / 4;
   9960   rtx elts[MAX_VECT_LEN];
   9961   int set = 0;
   9962   int i, j;
   9963 
   9964   /* Generate a const_int vector replicating the same 4-element set
   9965      from an immediate.  */
   9966   for (j = 0; j < nsets; j++, set = 4 * j)
   9967     for (i = 0; i < 4; i++)
   9968       elts[set + i] = GEN_INT (set + ((val >> (2 * i)) & 0x3));
   9969 
   9970   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nunits, elts));
   9971 }
   9972 
   9973 
   9974 /* Expand a vector initialization.  */
   9975 
   9976 void
   9977 loongarch_expand_vector_group_init (rtx target, rtx vals)
   9978 {
   9979   machine_mode vmode = GET_MODE (target);
   9980   machine_mode half_mode = VOIDmode;
   9981   rtx low = XVECEXP (vals, 0, 0);
   9982   rtx high = XVECEXP (vals, 0, 1);
   9983 
   9984   switch (vmode)
   9985     {
   9986     case E_V32QImode:
   9987       half_mode = V16QImode;
   9988       break;
   9989     case E_V16HImode:
   9990       half_mode = V8HImode;
   9991       break;
   9992     case E_V8SImode:
   9993       half_mode = V4SImode;
   9994       break;
   9995     case E_V4DImode:
   9996       half_mode = V2DImode;
   9997       break;
   9998     case E_V8SFmode:
   9999       half_mode = V4SFmode;
   10000       break;
   10001     case E_V4DFmode:
   10002       half_mode = V2DFmode;
   10003       break;
   10004     default:
   10005       gcc_unreachable ();
   10006     }
   10007 
   10008   if (!register_operand (low, half_mode))
   10009     low = force_reg (half_mode, low);
   10010   if (!register_operand (high, half_mode))
   10011     high = force_reg (half_mode, high);
   10012   emit_insn (gen_rtx_SET (target,
   10013 			  gen_rtx_VEC_CONCAT (vmode, low, high)));
   10014 }
   10015 
   10016 /* Expand initialization of a vector which has all same elements.  */
   10017 
   10018 void
   10019 loongarch_expand_vector_init_same (rtx target, rtx vals, unsigned nvar)
   10020 {
   10021   machine_mode vmode = GET_MODE (target);
   10022   machine_mode imode = GET_MODE_INNER (vmode);
   10023   rtx same = XVECEXP (vals, 0, 0);
   10024   rtx temp;
   10025 
   10026   if (CONST_INT_P (same) && nvar == 0
   10027       && loongarch_signed_immediate_p (INTVAL (same), 10, 0))
   10028     {
   10029       switch (vmode)
   10030 	{
   10031 	case E_V32QImode:
   10032 	case E_V16HImode:
   10033 	case E_V8SImode:
   10034 	case E_V4DImode:
   10035 	case E_V16QImode:
   10036 	case E_V8HImode:
   10037 	case E_V4SImode:
   10038 	case E_V2DImode:
   10039 	  temp = gen_rtx_CONST_VECTOR (vmode, XVEC (vals, 0));
   10040 	  emit_move_insn (target, temp);
   10041 	  return;
   10042 	default:
   10043 	  gcc_unreachable ();
   10044 	}
   10045     }
   10046 
   10047   if (imode == GET_MODE (same))
   10048     temp = same;
   10049   else if (GET_MODE_SIZE (imode) >= UNITS_PER_WORD)
   10050     {
   10051       if (GET_CODE (same) == MEM)
   10052 	{
   10053 	  rtx reg_tmp = gen_reg_rtx (GET_MODE (same));
   10054 	  loongarch_emit_move (reg_tmp, same);
   10055 	  temp = simplify_gen_subreg (imode, reg_tmp, GET_MODE (reg_tmp), 0);
   10056 	}
   10057       else
   10058 	temp = simplify_gen_subreg (imode, same, GET_MODE (same), 0);
   10059     }
   10060   else
   10061     {
   10062       if (GET_CODE (same) == MEM)
   10063 	{
   10064 	  rtx reg_tmp = gen_reg_rtx (GET_MODE (same));
   10065 	  loongarch_emit_move (reg_tmp, same);
   10066 	  temp = lowpart_subreg (imode, reg_tmp, GET_MODE (reg_tmp));
   10067 	}
   10068       else
   10069 	temp = lowpart_subreg (imode, same, GET_MODE (same));
   10070     }
   10071 
   10072   temp = force_reg (imode, temp);
   10073 
   10074   switch (vmode)
   10075     {
   10076     case E_V32QImode:
   10077     case E_V16HImode:
   10078     case E_V8SImode:
   10079     case E_V4DImode:
   10080     case E_V16QImode:
   10081     case E_V8HImode:
   10082     case E_V4SImode:
   10083     case E_V2DImode:
   10084       loongarch_emit_move (target, gen_rtx_VEC_DUPLICATE (vmode, temp));
   10085       break;
   10086 
   10087     case E_V8SFmode:
   10088       emit_insn (gen_lasx_xvreplve0_w_f_scalar (target, temp));
   10089       break;
   10090 
   10091     case E_V4DFmode:
   10092       emit_insn (gen_lasx_xvreplve0_d_f_scalar (target, temp));
   10093       break;
   10094 
   10095     case E_V4SFmode:
   10096       emit_insn (gen_lsx_vreplvei_w_f_scalar (target, temp));
   10097       break;
   10098 
   10099     case E_V2DFmode:
   10100       emit_insn (gen_lsx_vreplvei_d_f_scalar (target, temp));
   10101       break;
   10102 
   10103     default:
   10104       gcc_unreachable ();
   10105     }
   10106 }
   10107 
   10108 /* Expand a vector initialization.  */
   10109 
   10110 void
   10111 loongarch_expand_vector_init (rtx target, rtx vals)
   10112 {
   10113   machine_mode vmode = GET_MODE (target);
   10114   machine_mode imode = GET_MODE_INNER (vmode);
   10115   unsigned i, nelt = GET_MODE_NUNITS (vmode);
   10116   /* VALS is divided into high and low half-part.  */
   10117   /* Number of non constant elements in corresponding parts of VALS.  */
   10118   unsigned nvar = 0, hi_nvar = 0, lo_nvar = 0;
   10119   /* all_same : true if all elements of VALS are the same.
   10120      hi_same : true if all elements of the high half-part are the same.
   10121      lo_same : true if all elements of the low half-part are the same.
   10122      half_same : true if the high half-part is the same as the low one.  */
   10123   bool all_same = false, hi_same = true, lo_same = true, half_same = true;
   10124   rtx val[32], val_hi[32], val_lo[16];
   10125   rtx x, op0, op1;
   10126   /* Copy one element of vals to per element of target vector.  */
   10127   typedef rtx (*loongarch_vec_repl1_fn) (rtx, rtx);
   10128   /* Copy two elements of vals to target vector.  */
   10129   typedef rtx (*loongarch_vec_repl2_fn) (rtx, rtx, rtx);
   10130   /* Insert scalar operands into the specified position of the vector.  */
   10131   typedef rtx (*loongarch_vec_set_fn) (rtx, rtx, rtx);
   10132   /* Copy 64bit lowpart to highpart.  */
   10133   typedef rtx (*loongarch_vec_mirror_fn) (rtx, rtx, rtx);
   10134   /* Merge lowpart and highpart into target.  */
   10135   typedef rtx (*loongarch_vec_merge_fn) (rtx, rtx, rtx, rtx);
   10136 
   10137   loongarch_vec_repl1_fn loongarch_vec_repl1_128 = NULL,
   10138 			 loongarch_vec_repl1_256 = NULL;
   10139   loongarch_vec_repl2_fn loongarch_vec_repl2_128 = NULL,
   10140 			 loongarch_vec_repl2_256 = NULL;
   10141   loongarch_vec_set_fn loongarch_vec_set128 = NULL, loongarch_vec_set256 = NULL;
   10142   loongarch_vec_mirror_fn loongarch_vec_mirror = NULL;
   10143   loongarch_vec_merge_fn loongarch_lasx_vecinit_merge = NULL;
   10144   machine_mode half_mode = VOIDmode;
   10145 
   10146   /* Check whether elements of each part are the same.  */
   10147   for (i = 0; i < nelt / 2; ++i)
   10148     {
   10149       val_hi[i] = val_hi[i + nelt / 2] = val[i + nelt / 2]
   10150 	= XVECEXP (vals, 0, i + nelt / 2);
   10151       val_lo[i] = val[i] = XVECEXP (vals, 0, i);
   10152       if (!loongarch_constant_elt_p (val_hi[i]))
   10153 	hi_nvar++;
   10154       if (!loongarch_constant_elt_p (val_lo[i]))
   10155 	lo_nvar++;
   10156       if (i > 0 && !rtx_equal_p (val_hi[i], val_hi[0]))
   10157 	hi_same = false;
   10158       if (i > 0 && !rtx_equal_p (val_lo[i], val_lo[0]))
   10159 	lo_same = false;
   10160       if (!rtx_equal_p (val_hi[i], val_lo[i]))
   10161 	half_same = false;
   10162     }
   10163 
   10164   /* If all elements are the same, set all_same true.  */
   10165   if (hi_same && lo_same && half_same)
   10166     all_same = true;
   10167 
   10168   nvar = hi_nvar + lo_nvar;
   10169 
   10170   switch (vmode)
   10171     {
   10172     case E_V32QImode:
   10173       half_mode = E_V16QImode;
   10174       loongarch_vec_set256 = gen_vec_setv32qi_internal;
   10175       loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_b;
   10176       loongarch_lasx_vecinit_merge
   10177 	= half_same ? gen_lasx_xvpermi_q_v32qi : gen_lasx_vecinit_merge_v32qi;
   10178       /* FALLTHRU.  */
   10179     case E_V16QImode:
   10180       loongarch_vec_set128 = gen_vec_setv16qi;
   10181       loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_b;
   10182       loongarch_vec_mirror = gen_lsx_vreplvei_mirror_b;
   10183       break;
   10184 
   10185     case E_V16HImode:
   10186       half_mode = E_V8HImode;
   10187       loongarch_vec_set256 = gen_vec_setv16hi_internal;
   10188       loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_h;
   10189       loongarch_lasx_vecinit_merge
   10190 	= half_same ? gen_lasx_xvpermi_q_v16hi : gen_lasx_vecinit_merge_v16hi;
   10191       /* FALLTHRU.  */
   10192     case E_V8HImode:
   10193       loongarch_vec_set128 = gen_vec_setv8hi;
   10194       loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_h;
   10195       loongarch_vec_mirror = gen_lsx_vreplvei_mirror_h;
   10196       break;
   10197 
   10198     case E_V8SImode:
   10199       half_mode = V4SImode;
   10200       loongarch_vec_set256 = gen_vec_setv8si;
   10201       loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_w;
   10202       loongarch_lasx_vecinit_merge
   10203 	= half_same ? gen_lasx_xvpermi_q_v8si : gen_lasx_vecinit_merge_v8si;
   10204       /* FALLTHRU.  */
   10205     case E_V4SImode:
   10206       loongarch_vec_set128 = gen_vec_setv4si;
   10207       loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_w;
   10208       loongarch_vec_mirror = gen_lsx_vreplvei_mirror_w;
   10209       break;
   10210 
   10211     case E_V4DImode:
   10212       half_mode = E_V2DImode;
   10213       loongarch_vec_set256 = gen_vec_setv4di;
   10214       loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_d;
   10215       loongarch_lasx_vecinit_merge
   10216 	= half_same ? gen_lasx_xvpermi_q_v4di : gen_lasx_vecinit_merge_v4di;
   10217       /* FALLTHRU.  */
   10218     case E_V2DImode:
   10219       loongarch_vec_set128 = gen_vec_setv2di;
   10220       loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_d;
   10221       loongarch_vec_mirror = gen_lsx_vreplvei_mirror_d;
   10222       break;
   10223 
   10224     case E_V8SFmode:
   10225       half_mode = E_V4SFmode;
   10226       loongarch_vec_set256 = gen_vec_setv8sf;
   10227       loongarch_vec_repl1_128 = gen_lsx_vreplvei_w_f_scalar;
   10228       loongarch_vec_repl2_256 = gen_lasx_xvilvl_w_f_internal;
   10229       loongarch_lasx_vecinit_merge
   10230 	= half_same ? gen_lasx_xvpermi_q_v8sf : gen_lasx_vecinit_merge_v8sf;
   10231       /* FALLTHRU.  */
   10232     case E_V4SFmode:
   10233       loongarch_vec_set128 = gen_vec_setv4sf;
   10234       loongarch_vec_repl2_128 = gen_lsx_vilvl_w_f_internal;
   10235       loongarch_vec_mirror = gen_lsx_vreplvei_mirror_w_f;
   10236       break;
   10237 
   10238     case E_V4DFmode:
   10239       half_mode = E_V2DFmode;
   10240       loongarch_vec_set256 = gen_vec_setv4df;
   10241       loongarch_vec_repl1_128 = gen_lsx_vreplvei_d_f_scalar;
   10242       loongarch_vec_repl2_256 = gen_lasx_xvilvl_d_f_internal;
   10243       loongarch_lasx_vecinit_merge
   10244 	= half_same ? gen_lasx_xvpermi_q_v4df : gen_lasx_vecinit_merge_v4df;
   10245       /* FALLTHRU.  */
   10246     case E_V2DFmode:
   10247       loongarch_vec_set128 = gen_vec_setv2df;
   10248       loongarch_vec_repl2_128 = gen_lsx_vilvl_d_f_internal;
   10249       loongarch_vec_mirror = gen_lsx_vreplvei_mirror_d_f;
   10250       break;
   10251 
   10252     default:
   10253       gcc_unreachable ();
   10254     }
   10255 
   10256   if (ISA_HAS_LASX && GET_MODE_SIZE (vmode) == 32)
   10257     {
   10258       /* If all elements are the same, just do a broadcost.  */
   10259       if (all_same)
   10260 	loongarch_expand_vector_init_same (target, vals, nvar);
   10261       else
   10262 	{
   10263 	  gcc_assert (nelt >= 4);
   10264 
   10265 	  rtx target_hi, target_lo;
   10266 	  /* Write elements of high half-part in target directly.  */
   10267 	  target_hi = target;
   10268 	  target_lo = gen_reg_rtx (half_mode);
   10269 
   10270 	  /* If all elements of high half-part are the same,
   10271 	     just do a broadcost.  Also applicable to low half-part.  */
   10272 	  if (hi_same)
   10273 	    {
   10274 	      rtx vtmp = gen_rtx_PARALLEL (vmode, gen_rtvec_v (nelt, val_hi));
   10275 	      loongarch_expand_vector_init_same (target_hi, vtmp, hi_nvar);
   10276 	    }
   10277 	  if (lo_same)
   10278 	    {
   10279 	      rtx vtmp
   10280 		= gen_rtx_PARALLEL (half_mode, gen_rtvec_v (nelt / 2, val_lo));
   10281 	      loongarch_expand_vector_init_same (target_lo, vtmp, lo_nvar);
   10282 	    }
   10283 
   10284 	  for (i = 0; i < nelt / 2; ++i)
   10285 	    {
   10286 	      if (!hi_same)
   10287 		{
   10288 		  if (vmode == E_V8SFmode || vmode == E_V4DFmode)
   10289 		    {
   10290 		      /* Using xvilvl to load lowest 2 elements simultaneously
   10291 			 to reduce the number of instructions.  */
   10292 		      if (i == 1)
   10293 			{
   10294 			  op0 = force_reg (imode, val_hi[0]);
   10295 			  op1 = force_reg (imode, val_hi[1]);
   10296 			  emit_insn (
   10297 			    loongarch_vec_repl2_256 (target_hi, op0, op1));
   10298 			}
   10299 		      else if (i > 1)
   10300 			{
   10301 			  op0 = force_reg (imode, val_hi[i]);
   10302 			  emit_insn (
   10303 			    loongarch_vec_set256 (target_hi, op0, GEN_INT (i)));
   10304 			}
   10305 		    }
   10306 		  else
   10307 		    {
   10308 		      op0 = force_reg (imode, val_hi[i]);
   10309 		      /* Assign the lowest element of val_hi to all elements
   10310 			 of target_hi.  */
   10311 		      if (i == 0)
   10312 			{
   10313 			  emit_insn (loongarch_vec_repl1_256 (target_hi, op0));
   10314 			}
   10315 		      else if (!rtx_equal_p (val_hi[i], val_hi[0]))
   10316 			{
   10317 			  emit_insn (
   10318 			    loongarch_vec_set256 (target_hi, op0, GEN_INT (i)));
   10319 			}
   10320 		    }
   10321 		}
   10322 	      if (!lo_same && !half_same)
   10323 		{
   10324 		  op0 = force_reg (imode, val_lo[i]);
   10325 		  /* Assign the lowest element of val_lo to all elements
   10326 		     of target_lo.  */
   10327 		  if (i == 0)
   10328 		    {
   10329 		      emit_insn (loongarch_vec_repl1_128 (target_lo, op0));
   10330 		    }
   10331 		  else if (!rtx_equal_p (val_lo[i], val_lo[0]))
   10332 		    {
   10333 		      emit_insn (
   10334 			loongarch_vec_set128 (target_lo, op0, GEN_INT (i)));
   10335 		    }
   10336 		}
   10337 	    }
   10338 	  if (half_same)
   10339 	    {
   10340 	      emit_insn (loongarch_lasx_vecinit_merge (target, target_hi,
   10341 						       target_hi, const0_rtx));
   10342 	      return;
   10343 	    }
   10344 	  emit_insn (loongarch_lasx_vecinit_merge (target, target_hi, target_lo,
   10345 						   GEN_INT (0x20)));
   10346 	}
   10347       return;
   10348     }
   10349 
   10350   if (ISA_HAS_LSX)
   10351     {
   10352       if (all_same)
   10353 	loongarch_expand_vector_init_same (target, vals, nvar);
   10354       else
   10355 	{
   10356 	  for (i = 0; i < nelt; ++i)
   10357 	    {
   10358 	      if (vmode == E_V4SFmode || vmode == E_V2DFmode)
   10359 		{
   10360 		  /* Using vilvl to load lowest 2 elements simultaneously to
   10361 		     reduce the number of instructions.  */
   10362 		  if (i == 1)
   10363 		    {
   10364 		      op0 = force_reg (imode, val[0]);
   10365 		      op1 = force_reg (imode, val[1]);
   10366 		      emit_insn (loongarch_vec_repl2_128 (target, op0, op1));
   10367 		    }
   10368 		  else if (i > 1)
   10369 		    {
   10370 		      op0 = force_reg (imode, val[i]);
   10371 		      emit_insn (
   10372 			loongarch_vec_set128 (target, op0, GEN_INT (i)));
   10373 		    }
   10374 		}
   10375 	      else
   10376 		{
   10377 		  if (half_same && i == nelt / 2)
   10378 		    {
   10379 		      emit_insn (
   10380 			loongarch_vec_mirror (target, target, const0_rtx));
   10381 		      return;
   10382 		    }
   10383 		  op0 = force_reg (imode, val[i]);
   10384 		  /* Assign the lowest element of val to all elements of
   10385 		     target.  */
   10386 		  if (i == 0)
   10387 		    {
   10388 		      emit_insn (loongarch_vec_repl1_128 (target, op0));
   10389 		    }
   10390 		  else if (!rtx_equal_p (val[i], val[0]))
   10391 		    {
   10392 		      emit_insn (
   10393 			loongarch_vec_set128 (target, op0, GEN_INT (i)));
   10394 		    }
   10395 		}
   10396 	    }
   10397 	}
   10398       return;
   10399     }
   10400 
   10401   /* Load constants from the pool, or whatever's handy.  */
   10402   if (nvar == 0)
   10403     {
   10404       emit_move_insn (target, gen_rtx_CONST_VECTOR (vmode, XVEC (vals, 0)));
   10405       return;
   10406     }
   10407 
   10408   /* For two-part initialization, always use CONCAT.  */
   10409   if (nelt == 2)
   10410     {
   10411       rtx op0 = force_reg (imode, val[0]);
   10412       rtx op1 = force_reg (imode, val[1]);
   10413       x = gen_rtx_VEC_CONCAT (vmode, op0, op1);
   10414       emit_insn (gen_rtx_SET (target, x));
   10415       return;
   10416     }
   10417 
   10418   /* No LoongArch CPU supports vectors with more elements as at now.  */
   10419   gcc_unreachable ();
   10420 }
   10421 
   10422 /* Implement HARD_REGNO_CALLER_SAVE_MODE.  */
   10423 
   10424 machine_mode
   10425 loongarch_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
   10426 				       machine_mode mode)
   10427 {
   10428   /* For performance, avoid saving/restoring upper parts of a register
   10429      by returning MODE as save mode when the mode is known.  */
   10430   if (mode == VOIDmode)
   10431     return choose_hard_reg_mode (regno, nregs, NULL);
   10432   else
   10433     return mode;
   10434 }
   10435 
   10436 /* Generate RTL for comparing CMP_OP0 and CMP_OP1 using condition COND and
   10437    store the result -1 or 0 in DEST.  */
   10438 
   10439 static void
   10440 loongarch_expand_lsx_cmp (rtx dest, enum rtx_code cond, rtx op0, rtx op1)
   10441 {
   10442   machine_mode cmp_mode = GET_MODE (op0);
   10443   bool negate = false;
   10444 
   10445   switch (cmp_mode)
   10446     {
   10447     case E_V16QImode:
   10448     case E_V32QImode:
   10449     case E_V8HImode:
   10450     case E_V16HImode:
   10451     case E_V4SImode:
   10452     case E_V8SImode:
   10453     case E_V2DImode:
   10454     case E_V4DImode:
   10455       switch (cond)
   10456 	{
   10457 	case NE:
   10458 	  cond = reverse_condition (cond);
   10459 	  negate = true;
   10460 	  break;
   10461 	case EQ:
   10462 	case LT:
   10463 	case LE:
   10464 	case LTU:
   10465 	case LEU:
   10466 	  break;
   10467 	case GE:
   10468 	case GT:
   10469 	case GEU:
   10470 	case GTU:
   10471 	  std::swap (op0, op1);
   10472 	  cond = swap_condition (cond);
   10473 	  break;
   10474 	default:
   10475 	  gcc_unreachable ();
   10476 	}
   10477       loongarch_emit_binary (cond, dest, op0, op1);
   10478       if (negate)
   10479 	emit_move_insn (dest, gen_rtx_NOT (GET_MODE (dest), dest));
   10480       break;
   10481 
   10482     case E_V4SFmode:
   10483     case E_V2DFmode:
   10484     case E_V8SFmode:
   10485     case E_V4DFmode:
   10486       loongarch_emit_binary (cond, dest, op0, op1);
   10487       break;
   10488 
   10489     default:
   10490       gcc_unreachable ();
   10491       break;
   10492     }
   10493 }
   10494 
   10495 /* Expand VEC_COND_EXPR, where:
   10496    MODE is mode of the result
   10497    VIMODE equivalent integer mode
   10498    OPERANDS operands of VEC_COND_EXPR.  */
   10499 
   10500 void
   10501 loongarch_expand_vec_cond_expr (machine_mode mode, machine_mode vimode,
   10502 				rtx *operands)
   10503 {
   10504   rtx cond = operands[3];
   10505   rtx cmp_op0 = operands[4];
   10506   rtx cmp_op1 = operands[5];
   10507   rtx cmp_res = gen_reg_rtx (vimode);
   10508 
   10509   loongarch_expand_lsx_cmp (cmp_res, GET_CODE (cond), cmp_op0, cmp_op1);
   10510 
   10511   /* We handle the following cases:
   10512      1) r = a CMP b ? -1 : 0
   10513      2) r = a CMP b ? -1 : v
   10514      3) r = a CMP b ?  v : 0
   10515      4) r = a CMP b ? v1 : v2  */
   10516 
   10517   /* Case (1) above.  We only move the results.  */
   10518   if (operands[1] == CONSTM1_RTX (vimode)
   10519       && operands[2] == CONST0_RTX (vimode))
   10520     emit_move_insn (operands[0], cmp_res);
   10521   else
   10522     {
   10523       rtx src1 = gen_reg_rtx (vimode);
   10524       rtx src2 = gen_reg_rtx (vimode);
   10525       rtx mask = gen_reg_rtx (vimode);
   10526       rtx bsel;
   10527 
   10528       /* Move the vector result to use it as a mask.  */
   10529       emit_move_insn (mask, cmp_res);
   10530 
   10531       if (register_operand (operands[1], mode))
   10532 	{
   10533 	  rtx xop1 = operands[1];
   10534 	  if (mode != vimode)
   10535 	    {
   10536 	      xop1 = gen_reg_rtx (vimode);
   10537 	      emit_move_insn (xop1,
   10538 			      simplify_gen_subreg (vimode, operands[1],
   10539 						   mode, 0));
   10540 	    }
   10541 	  emit_move_insn (src1, xop1);
   10542 	}
   10543       else
   10544 	{
   10545 	  gcc_assert (operands[1] == CONSTM1_RTX (vimode));
   10546 	  /* Case (2) if the below doesn't move the mask to src2.  */
   10547 	  emit_move_insn (src1, mask);
   10548 	}
   10549 
   10550       if (register_operand (operands[2], mode))
   10551 	{
   10552 	  rtx xop2 = operands[2];
   10553 	  if (mode != vimode)
   10554 	    {
   10555 	      xop2 = gen_reg_rtx (vimode);
   10556 	      emit_move_insn (xop2,
   10557 			      simplify_gen_subreg (vimode, operands[2],
   10558 						   mode, 0));
   10559 	    }
   10560 	  emit_move_insn (src2, xop2);
   10561 	}
   10562       else
   10563 	{
   10564 	  gcc_assert (operands[2] == CONST0_RTX (mode));
   10565 	  /* Case (3) if the above didn't move the mask to src1.  */
   10566 	  emit_move_insn (src2, mask);
   10567 	}
   10568 
   10569       /* We deal with case (4) if the mask wasn't moved to either src1 or src2.
   10570 	 In any case, we eventually do vector mask-based copy.  */
   10571       bsel = gen_rtx_IOR (vimode,
   10572 			  gen_rtx_AND (vimode,
   10573 				       gen_rtx_NOT (vimode, mask), src2),
   10574 			  gen_rtx_AND (vimode, mask, src1));
   10575       /* The result is placed back to a register with the mask.  */
   10576       emit_insn (gen_rtx_SET (mask, bsel));
   10577       emit_move_insn (operands[0],
   10578 		      simplify_gen_subreg (mode, mask, vimode, 0));
   10579     }
   10580 }
   10581 
   10582 void
   10583 loongarch_expand_vec_cond_mask_expr (machine_mode mode, machine_mode vimode,
   10584 				    rtx *operands)
   10585 {
   10586   rtx cmp_res = operands[3];
   10587 
   10588   /* We handle the following cases:
   10589      1) r = a CMP b ? -1 : 0
   10590      2) r = a CMP b ? -1 : v
   10591      3) r = a CMP b ?  v : 0
   10592      4) r = a CMP b ? v1 : v2  */
   10593 
   10594   /* Case (1) above.  We only move the results.  */
   10595   if (operands[1] == CONSTM1_RTX (vimode)
   10596       && operands[2] == CONST0_RTX (vimode))
   10597     emit_move_insn (operands[0], cmp_res);
   10598   else
   10599     {
   10600       rtx src1 = gen_reg_rtx (vimode);
   10601       rtx src2 = gen_reg_rtx (vimode);
   10602       rtx mask = gen_reg_rtx (vimode);
   10603       rtx bsel;
   10604 
   10605       /* Move the vector result to use it as a mask.  */
   10606       emit_move_insn (mask, cmp_res);
   10607 
   10608       if (register_operand (operands[1], mode))
   10609 	{
   10610 	  rtx xop1 = operands[1];
   10611 	  if (mode != vimode)
   10612 	    {
   10613 	      xop1 = gen_reg_rtx (vimode);
   10614 	      emit_move_insn (xop1,
   10615 			      simplify_gen_subreg (vimode, operands[1],
   10616 						   mode, 0));
   10617 	    }
   10618 	  emit_move_insn (src1, xop1);
   10619 	}
   10620       else
   10621 	{
   10622 	  gcc_assert (operands[1] == CONSTM1_RTX (vimode));
   10623 	  /* Case (2) if the below doesn't move the mask to src2.  */
   10624 	  emit_move_insn (src1, mask);
   10625 	}
   10626 
   10627       if (register_operand (operands[2], mode))
   10628 	{
   10629 	  rtx xop2 = operands[2];
   10630 	  if (mode != vimode)
   10631 	    {
   10632 	      xop2 = gen_reg_rtx (vimode);
   10633 	      emit_move_insn (xop2,
   10634 			      simplify_gen_subreg (vimode, operands[2],
   10635 						   mode, 0));
   10636 	    }
   10637 	  emit_move_insn (src2, xop2);
   10638 	}
   10639       else
   10640 	{
   10641 	  gcc_assert (operands[2] == CONST0_RTX (mode));
   10642 	  /* Case (3) if the above didn't move the mask to src1.  */
   10643 	  emit_move_insn (src2, mask);
   10644 	}
   10645 
   10646       /* We deal with case (4) if the mask wasn't moved to either src1 or src2.
   10647 	 In any case, we eventually do vector mask-based copy.  */
   10648       bsel = gen_rtx_IOR (vimode,
   10649 			  gen_rtx_AND (vimode,
   10650 				       gen_rtx_NOT (vimode, mask), src2),
   10651 			  gen_rtx_AND (vimode, mask, src1));
   10652       /* The result is placed back to a register with the mask.  */
   10653       emit_insn (gen_rtx_SET (mask, bsel));
   10654       emit_move_insn (operands[0], simplify_gen_subreg (mode, mask,
   10655 							vimode, 0));
   10656     }
   10657 }
   10658 
   10659 /* Expand integer vector comparison */
   10660 void
   10661 loongarch_expand_vec_cmp (rtx operands[])
   10662 {
   10663 
   10664   rtx_code code = GET_CODE (operands[1]);
   10665   loongarch_expand_lsx_cmp (operands[0], code, operands[2], operands[3]);
   10666 }
   10667 
   10668 /* Implement TARGET_PROMOTE_FUNCTION_MODE.  */
   10669 
   10670 /* This function is equivalent to default_promote_function_mode_always_promote
   10671    except that it returns a promoted mode even if type is NULL_TREE.  This is
   10672    needed by libcalls which have no type (only a mode) such as fixed conversion
   10673    routines that take a signed or unsigned char/short argument and convert it
   10674    to a fixed type.  */
   10675 
   10676 static machine_mode
   10677 loongarch_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
   10678 				 machine_mode mode,
   10679 				 int *punsignedp ATTRIBUTE_UNUSED,
   10680 				 const_tree fntype ATTRIBUTE_UNUSED,
   10681 				 int for_return ATTRIBUTE_UNUSED)
   10682 {
   10683   int unsignedp;
   10684 
   10685   if (type != NULL_TREE)
   10686     return promote_mode (type, mode, punsignedp);
   10687 
   10688   unsignedp = *punsignedp;
   10689   PROMOTE_MODE (mode, unsignedp, type);
   10690   *punsignedp = unsignedp;
   10691   return mode;
   10692 }
   10693 
   10694 /* Implement TARGET_STARTING_FRAME_OFFSET.  See loongarch_compute_frame_info
   10695    for details about the frame layout.  */
   10696 
   10697 static HOST_WIDE_INT
   10698 loongarch_starting_frame_offset (void)
   10699 {
   10700   if (FRAME_GROWS_DOWNWARD)
   10701     return 0;
   10702   return crtl->outgoing_args_size;
   10703 }
   10704 
   10705 /* A subroutine of loongarch_build_signbit_mask.  If VECT is true,
   10706    then replicate the value for all elements of the vector
   10707    register.  */
   10708 
   10709 rtx
   10710 loongarch_build_const_vector (machine_mode mode, bool vect, rtx value)
   10711 {
   10712   int i, n_elt;
   10713   rtvec v;
   10714   machine_mode scalar_mode;
   10715 
   10716   switch (mode)
   10717     {
   10718     case E_V32QImode:
   10719     case E_V16QImode:
   10720     case E_V32HImode:
   10721     case E_V16HImode:
   10722     case E_V8HImode:
   10723     case E_V8SImode:
   10724     case E_V4SImode:
   10725     case E_V8DImode:
   10726     case E_V4DImode:
   10727     case E_V2DImode:
   10728       gcc_assert (vect);
   10729       /* FALLTHRU */
   10730     case E_V8SFmode:
   10731     case E_V4SFmode:
   10732     case E_V8DFmode:
   10733     case E_V4DFmode:
   10734     case E_V2DFmode:
   10735       n_elt = GET_MODE_NUNITS (mode);
   10736       v = rtvec_alloc (n_elt);
   10737       scalar_mode = GET_MODE_INNER (mode);
   10738 
   10739       RTVEC_ELT (v, 0) = value;
   10740 
   10741       for (i = 1; i < n_elt; ++i)
   10742 	RTVEC_ELT (v, i) = vect ? value : CONST0_RTX (scalar_mode);
   10743 
   10744       return gen_rtx_CONST_VECTOR (mode, v);
   10745 
   10746     default:
   10747       gcc_unreachable ();
   10748     }
   10749 }
   10750 
   10751 /* Create a mask for the sign bit in MODE
   10752    for an register.  If VECT is true, then replicate the mask for
   10753    all elements of the vector register.  If INVERT is true, then create
   10754    a mask excluding the sign bit.  */
   10755 
   10756 rtx
   10757 loongarch_build_signbit_mask (machine_mode mode, bool vect, bool invert)
   10758 {
   10759   machine_mode vec_mode, imode;
   10760   wide_int w;
   10761   rtx mask, v;
   10762 
   10763   switch (mode)
   10764     {
   10765     case E_V16SImode:
   10766     case E_V16SFmode:
   10767     case E_V8SImode:
   10768     case E_V4SImode:
   10769     case E_V8SFmode:
   10770     case E_V4SFmode:
   10771       vec_mode = mode;
   10772       imode = SImode;
   10773       break;
   10774 
   10775     case E_V8DImode:
   10776     case E_V4DImode:
   10777     case E_V2DImode:
   10778     case E_V8DFmode:
   10779     case E_V4DFmode:
   10780     case E_V2DFmode:
   10781       vec_mode = mode;
   10782       imode = DImode;
   10783       break;
   10784 
   10785     case E_TImode:
   10786     case E_TFmode:
   10787       vec_mode = VOIDmode;
   10788       imode = TImode;
   10789       break;
   10790 
   10791     default:
   10792       gcc_unreachable ();
   10793     }
   10794 
   10795   machine_mode inner_mode = GET_MODE_INNER (mode);
   10796   w = wi::set_bit_in_zero (GET_MODE_BITSIZE (inner_mode) - 1,
   10797 			   GET_MODE_BITSIZE (inner_mode));
   10798   if (invert)
   10799     w = wi::bit_not (w);
   10800 
   10801   /* Force this value into the low part of a fp vector constant.  */
   10802   mask = immed_wide_int_const (w, imode);
   10803   mask = gen_lowpart (inner_mode, mask);
   10804 
   10805   if (vec_mode == VOIDmode)
   10806     return force_reg (inner_mode, mask);
   10807 
   10808   v = loongarch_build_const_vector (vec_mode, vect, mask);
   10809   return force_reg (vec_mode, v);
   10810 }
   10811 
   10812 /* Use rsqrte instruction and Newton-Rhapson to compute the approximation of
   10813    a single precision floating point [reciprocal] square root.  */
   10814 
   10815 void loongarch_emit_swrsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
   10816 {
   10817   rtx x0, e0, e1, e2, mhalf, monehalf;
   10818   REAL_VALUE_TYPE r;
   10819   int unspec;
   10820 
   10821   x0 = gen_reg_rtx (mode);
   10822   e0 = gen_reg_rtx (mode);
   10823   e1 = gen_reg_rtx (mode);
   10824   e2 = gen_reg_rtx (mode);
   10825 
   10826   real_arithmetic (&r, ABS_EXPR, &dconsthalf, NULL);
   10827   mhalf = const_double_from_real_value (r, SFmode);
   10828 
   10829   real_arithmetic (&r, PLUS_EXPR, &dconsthalf, &dconst1);
   10830   monehalf = const_double_from_real_value (r, SFmode);
   10831   unspec = UNSPEC_RSQRTE;
   10832 
   10833   if (VECTOR_MODE_P (mode))
   10834     {
   10835       mhalf = loongarch_build_const_vector (mode, true, mhalf);
   10836       monehalf = loongarch_build_const_vector (mode, true, monehalf);
   10837       unspec = GET_MODE_SIZE (mode) == 32 ? UNSPEC_LASX_XVFRSQRTE
   10838 					  : UNSPEC_LSX_VFRSQRTE;
   10839     }
   10840 
   10841   /* rsqrt(a) =  rsqrte(a) * (1.5 - 0.5 * a * rsqrte(a) * rsqrte(a))
   10842      sqrt(a)  =  a * rsqrte(a) * (1.5 - 0.5 * a * rsqrte(a) * rsqrte(a))  */
   10843 
   10844   a = force_reg (mode, a);
   10845 
   10846   /* x0 = rsqrt(a) estimate.  */
   10847   emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
   10848 					      unspec)));
   10849 
   10850   /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0).  */
   10851   if (!recip)
   10852     {
   10853       rtx zero = force_reg (mode, CONST0_RTX (mode));
   10854 
   10855       if (VECTOR_MODE_P (mode))
   10856 	{
   10857 	  machine_mode imode = related_int_vector_mode (mode).require ();
   10858 	  rtx mask = gen_reg_rtx (imode);
   10859 	  emit_insn (gen_rtx_SET (mask, gen_rtx_NE (imode, a, zero)));
   10860 	  emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0,
   10861 						   gen_lowpart (mode, mask))));
   10862 	}
   10863       else
   10864 	{
   10865 	  rtx target = emit_conditional_move (x0, { GT, a, zero, mode },
   10866 					      x0, zero, mode, 0);
   10867 	  if (target != x0)
   10868 	    emit_move_insn (x0, target);
   10869 	}
   10870     }
   10871 
   10872   /* e0 = x0 * a  */
   10873   emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
   10874   /* e1 = e0 * x0  */
   10875   emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0)));
   10876 
   10877   /* e2 = 1.5 - e1 * 0.5  */
   10878   mhalf = force_reg (mode, mhalf);
   10879   monehalf = force_reg (mode, monehalf);
   10880   emit_insn (gen_rtx_SET (e2, gen_rtx_FMA (mode,
   10881 					   gen_rtx_NEG (mode, e1),
   10882 							mhalf, monehalf)));
   10883 
   10884   if (recip)
   10885     /* res = e2 * x0  */
   10886     emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, x0, e2)));
   10887   else
   10888     /* res = e2 * e0  */
   10889     emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e0)));
   10890 }
   10891 
   10892 /* Use recipe instruction and Newton-Rhapson to compute the approximation of
   10893    a single precision floating point divide.  */
   10894 
   10895 void loongarch_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
   10896 {
   10897   rtx x0, e0, mtwo;
   10898   REAL_VALUE_TYPE r;
   10899   x0 = gen_reg_rtx (mode);
   10900   e0 = gen_reg_rtx (mode);
   10901   int unspec = UNSPEC_RECIPE;
   10902 
   10903   real_arithmetic (&r, ABS_EXPR, &dconst2, NULL);
   10904   mtwo = const_double_from_real_value (r, SFmode);
   10905 
   10906   if (VECTOR_MODE_P (mode))
   10907     {
   10908       mtwo = loongarch_build_const_vector (mode, true, mtwo);
   10909       unspec = GET_MODE_SIZE (mode) == 32 ? UNSPEC_LASX_XVFRECIPE
   10910 					  : UNSPEC_LSX_VFRECIPE;
   10911     }
   10912 
   10913   mtwo = force_reg (mode, mtwo);
   10914 
   10915   /* a / b = a * recipe(b) * (2.0 - b * recipe(b))  */
   10916 
   10917   /* x0 = 1./b estimate.  */
   10918   emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
   10919 					      unspec)));
   10920   /* e0 = 2.0 - b * x0.  */
   10921   emit_insn (gen_rtx_SET (e0, gen_rtx_FMA (mode,
   10922 					   gen_rtx_NEG (mode, b), x0, mtwo)));
   10923 
   10924   if (a != CONST1_RTX (mode))
   10925     {
   10926       rtx e1 = gen_reg_rtx (mode);
   10927       /* e1 = a * x0.  */
   10928       emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, a, x0)));
   10929       /* res = e0 * e1.  */
   10930       emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e0, e1)));
   10931     }
   10932   else
   10933     {
   10934       /* res = e0 * x0.  */
   10935       emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e0, x0)));
   10936     }
   10937 }
   10938 
   10939 static bool
   10940 loongarch_builtin_support_vector_misalignment (machine_mode mode,
   10941 					       const_tree type,
   10942 					       int misalignment,
   10943 					       bool is_packed)
   10944 {
   10945   if ((ISA_HAS_LSX || ISA_HAS_LASX) && STRICT_ALIGNMENT)
   10946     {
   10947       if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing)
   10948 	return false;
   10949       if (misalignment == -1)
   10950 	return false;
   10951     }
   10952   return default_builtin_support_vector_misalignment (mode, type, misalignment,
   10953 						      is_packed);
   10954 }
   10955 
   10956 static bool
   10957 use_rsqrt_p (void)
   10958 {
   10959   return (flag_finite_math_only
   10960 	  && !flag_trapping_math
   10961 	  && flag_unsafe_math_optimizations);
   10962 }
   10963 
   10964 /* Implement the TARGET_OPTAB_SUPPORTED_P hook.  */
   10965 
   10966 static bool
   10967 loongarch_optab_supported_p (int op, machine_mode, machine_mode,
   10968 			     optimization_type opt_type)
   10969 {
   10970   switch (op)
   10971     {
   10972     case rsqrt_optab:
   10973       return opt_type == OPTIMIZE_FOR_SPEED && use_rsqrt_p ();
   10974 
   10975     default:
   10976       return true;
   10977     }
   10978 }
   10979 
   10980 /* If -fverbose-asm, dump some info for debugging.  */
   10981 static void
   10982 loongarch_asm_code_end (void)
   10983 {
   10984 #define DUMP_FEATURE(PRED) \
   10985   fprintf (asm_out_file, "%s %s: %s\n", ASM_COMMENT_START, #PRED, \
   10986 	   (PRED) ? "enabled" : "disabled")
   10987 
   10988   if (flag_verbose_asm)
   10989     {
   10990       fprintf (asm_out_file, "\n%s CPU: %s\n", ASM_COMMENT_START,
   10991 	       loongarch_arch_strings[la_target.cpu_arch]);
   10992       fprintf (asm_out_file, "%s Tune: %s\n", ASM_COMMENT_START,
   10993 	       loongarch_tune_strings[la_target.cpu_tune]);
   10994       fprintf (asm_out_file, "%s Base ISA: %s\n", ASM_COMMENT_START,
   10995 	       loongarch_isa_base_strings [la_target.isa.base]);
   10996       DUMP_FEATURE (ISA_HAS_FRECIPE);
   10997       DUMP_FEATURE (ISA_HAS_DIV32);
   10998       DUMP_FEATURE (ISA_HAS_LAM_BH);
   10999       DUMP_FEATURE (ISA_HAS_LAMCAS);
   11000       DUMP_FEATURE (ISA_HAS_LD_SEQ_SA);
   11001     }
   11002 
   11003   fputs ("\n\n", asm_out_file);
   11004 #undef DUMP_FEATURE
   11005 }
   11006 
   11007 /* Target hook for c_mode_for_suffix.  */
   11008 static machine_mode
   11009 loongarch_c_mode_for_suffix (char suffix)
   11010 {
   11011   if (suffix == 'q')
   11012     return TFmode;
   11013 
   11014   return VOIDmode;
   11015 }
   11016 
   11017 /* Initialize the GCC target structure.  */
   11018 #undef TARGET_ASM_ALIGNED_HI_OP
   11019 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
   11020 #undef TARGET_ASM_ALIGNED_SI_OP
   11021 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
   11022 #undef TARGET_ASM_ALIGNED_DI_OP
   11023 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
   11024 
   11025 #undef TARGET_OPTION_OVERRIDE
   11026 #define TARGET_OPTION_OVERRIDE loongarch_option_override
   11027 #undef TARGET_OPTION_SAVE
   11028 #define TARGET_OPTION_SAVE loongarch_option_save
   11029 #undef TARGET_OPTION_RESTORE
   11030 #define TARGET_OPTION_RESTORE loongarch_option_restore
   11031 
   11032 #undef TARGET_SET_CURRENT_FUNCTION
   11033 #define TARGET_SET_CURRENT_FUNCTION loongarch_set_current_function
   11034 
   11035 #undef TARGET_LEGITIMIZE_ADDRESS
   11036 #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address
   11037 
   11038 #undef TARGET_ASM_SELECT_RTX_SECTION
   11039 #define TARGET_ASM_SELECT_RTX_SECTION loongarch_select_rtx_section
   11040 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
   11041 #define TARGET_ASM_FUNCTION_RODATA_SECTION loongarch_function_rodata_section
   11042 
   11043 #undef TARGET_ASM_CODE_END
   11044 #define TARGET_ASM_CODE_END loongarch_asm_code_end
   11045 
   11046 #undef TARGET_SCHED_INIT
   11047 #define TARGET_SCHED_INIT loongarch_sched_init
   11048 #undef TARGET_SCHED_REORDER
   11049 #define TARGET_SCHED_REORDER loongarch_sched_reorder
   11050 #undef TARGET_SCHED_REORDER2
   11051 #define TARGET_SCHED_REORDER2 loongarch_sched_reorder2
   11052 #undef TARGET_SCHED_VARIABLE_ISSUE
   11053 #define TARGET_SCHED_VARIABLE_ISSUE loongarch_variable_issue
   11054 #undef TARGET_SCHED_ADJUST_COST
   11055 #define TARGET_SCHED_ADJUST_COST loongarch_adjust_cost
   11056 #undef TARGET_SCHED_ISSUE_RATE
   11057 #define TARGET_SCHED_ISSUE_RATE loongarch_issue_rate
   11058 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
   11059 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
   11060   loongarch_multipass_dfa_lookahead
   11061 
   11062 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
   11063 #define TARGET_FUNCTION_OK_FOR_SIBCALL loongarch_function_ok_for_sibcall
   11064 
   11065 #undef TARGET_VALID_POINTER_MODE
   11066 #define TARGET_VALID_POINTER_MODE loongarch_valid_pointer_mode
   11067 #undef TARGET_REGISTER_MOVE_COST
   11068 #define TARGET_REGISTER_MOVE_COST loongarch_register_move_cost
   11069 #undef TARGET_MEMORY_MOVE_COST
   11070 #define TARGET_MEMORY_MOVE_COST loongarch_memory_move_cost
   11071 #undef TARGET_RTX_COSTS
   11072 #define TARGET_RTX_COSTS loongarch_rtx_costs
   11073 #undef TARGET_ADDRESS_COST
   11074 #define TARGET_ADDRESS_COST loongarch_address_cost
   11075 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
   11076 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
   11077   loongarch_builtin_vectorization_cost
   11078 #undef TARGET_VECTORIZE_CREATE_COSTS
   11079 #define TARGET_VECTORIZE_CREATE_COSTS loongarch_vectorize_create_costs
   11080 
   11081 
   11082 #undef TARGET_IN_SMALL_DATA_P
   11083 #define TARGET_IN_SMALL_DATA_P loongarch_in_small_data_p
   11084 
   11085 #undef TARGET_PREFERRED_RELOAD_CLASS
   11086 #define TARGET_PREFERRED_RELOAD_CLASS loongarch_preferred_reload_class
   11087 
   11088 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
   11089 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
   11090 
   11091 #undef TARGET_EXPAND_BUILTIN_VA_START
   11092 #define TARGET_EXPAND_BUILTIN_VA_START loongarch_va_start
   11093 
   11094 #undef TARGET_PROMOTE_FUNCTION_MODE
   11095 #define TARGET_PROMOTE_FUNCTION_MODE loongarch_promote_function_mode
   11096 #undef TARGET_RETURN_IN_MEMORY
   11097 #define TARGET_RETURN_IN_MEMORY loongarch_return_in_memory
   11098 
   11099 #undef TARGET_FUNCTION_VALUE
   11100 #define TARGET_FUNCTION_VALUE loongarch_function_value
   11101 #undef TARGET_LIBCALL_VALUE
   11102 #define TARGET_LIBCALL_VALUE loongarch_libcall_value
   11103 
   11104 #undef TARGET_ASM_OUTPUT_MI_THUNK
   11105 #define TARGET_ASM_OUTPUT_MI_THUNK loongarch_output_mi_thunk
   11106 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
   11107 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
   11108   hook_bool_const_tree_hwi_hwi_const_tree_true
   11109 
   11110 #undef TARGET_PRINT_OPERAND
   11111 #define TARGET_PRINT_OPERAND loongarch_print_operand
   11112 #undef TARGET_PRINT_OPERAND_ADDRESS
   11113 #define TARGET_PRINT_OPERAND_ADDRESS loongarch_print_operand_address
   11114 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
   11115 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P \
   11116   loongarch_print_operand_punct_valid_p
   11117 
   11118 #undef TARGET_SETUP_INCOMING_VARARGS
   11119 #define TARGET_SETUP_INCOMING_VARARGS loongarch_setup_incoming_varargs
   11120 #undef TARGET_STRICT_ARGUMENT_NAMING
   11121 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
   11122 #undef TARGET_MUST_PASS_IN_STACK
   11123 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
   11124 #undef TARGET_PASS_BY_REFERENCE
   11125 #define TARGET_PASS_BY_REFERENCE loongarch_pass_by_reference
   11126 #undef TARGET_ARG_PARTIAL_BYTES
   11127 #define TARGET_ARG_PARTIAL_BYTES loongarch_arg_partial_bytes
   11128 #undef TARGET_FUNCTION_ARG
   11129 #define TARGET_FUNCTION_ARG loongarch_function_arg
   11130 #undef TARGET_FUNCTION_ARG_ADVANCE
   11131 #define TARGET_FUNCTION_ARG_ADVANCE loongarch_function_arg_advance
   11132 #undef TARGET_FUNCTION_ARG_BOUNDARY
   11133 #define TARGET_FUNCTION_ARG_BOUNDARY loongarch_function_arg_boundary
   11134 
   11135 #undef TARGET_VECTOR_MODE_SUPPORTED_P
   11136 #define TARGET_VECTOR_MODE_SUPPORTED_P loongarch_vector_mode_supported_p
   11137 
   11138 #undef TARGET_SCALAR_MODE_SUPPORTED_P
   11139 #define TARGET_SCALAR_MODE_SUPPORTED_P loongarch_scalar_mode_supported_p
   11140 
   11141 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
   11142 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE loongarch_preferred_simd_mode
   11143 
   11144 #undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES
   11145 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES \
   11146   loongarch_autovectorize_vector_modes
   11147 
   11148 #undef TARGET_OPTAB_SUPPORTED_P
   11149 #define TARGET_OPTAB_SUPPORTED_P loongarch_optab_supported_p
   11150 
   11151 #undef TARGET_INIT_BUILTINS
   11152 #define TARGET_INIT_BUILTINS loongarch_init_builtins
   11153 #undef TARGET_BUILTIN_DECL
   11154 #define TARGET_BUILTIN_DECL loongarch_builtin_decl
   11155 #undef TARGET_EXPAND_BUILTIN
   11156 #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin
   11157 
   11158 /* The generic ELF target does not always have TLS support.  */
   11159 #ifdef HAVE_AS_TLS
   11160 #undef TARGET_HAVE_TLS
   11161 #define TARGET_HAVE_TLS HAVE_AS_TLS
   11162 #endif
   11163 
   11164 #undef TARGET_CANNOT_FORCE_CONST_MEM
   11165 #define TARGET_CANNOT_FORCE_CONST_MEM loongarch_cannot_force_const_mem
   11166 
   11167 #undef TARGET_LEGITIMATE_CONSTANT_P
   11168 #define TARGET_LEGITIMATE_CONSTANT_P loongarch_legitimate_constant_p
   11169 
   11170 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
   11171 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
   11172 
   11173 #ifdef HAVE_AS_DTPRELWORD
   11174 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
   11175 #define TARGET_ASM_OUTPUT_DWARF_DTPREL loongarch_output_dwarf_dtprel
   11176 #endif
   11177 
   11178 #undef TARGET_LEGITIMATE_ADDRESS_P
   11179 #define TARGET_LEGITIMATE_ADDRESS_P loongarch_legitimate_address_p
   11180 
   11181 #undef TARGET_FRAME_POINTER_REQUIRED
   11182 #define TARGET_FRAME_POINTER_REQUIRED loongarch_frame_pointer_required
   11183 
   11184 #undef TARGET_CAN_ELIMINATE
   11185 #define TARGET_CAN_ELIMINATE loongarch_can_eliminate
   11186 
   11187 #undef TARGET_CONDITIONAL_REGISTER_USAGE
   11188 #define TARGET_CONDITIONAL_REGISTER_USAGE loongarch_conditional_register_usage
   11189 
   11190 #undef TARGET_TRAMPOLINE_INIT
   11191 #define TARGET_TRAMPOLINE_INIT loongarch_trampoline_init
   11192 
   11193 #undef TARGET_MIN_ANCHOR_OFFSET
   11194 #define TARGET_MIN_ANCHOR_OFFSET (-IMM_REACH/2)
   11195 
   11196 #undef TARGET_MAX_ANCHOR_OFFSET
   11197 #define TARGET_MAX_ANCHOR_OFFSET (IMM_REACH/2-1)
   11198 #undef TARGET_VECTORIZE_VEC_PERM_CONST
   11199 #define TARGET_VECTORIZE_VEC_PERM_CONST loongarch_vectorize_vec_perm_const
   11200 
   11201 #undef TARGET_SCHED_REASSOCIATION_WIDTH
   11202 #define TARGET_SCHED_REASSOCIATION_WIDTH loongarch_sched_reassociation_width
   11203 
   11204 #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
   11205 #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV loongarch_atomic_assign_expand_fenv
   11206 
   11207 #undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
   11208 #define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
   11209 
   11210 #undef TARGET_HARD_REGNO_NREGS
   11211 #define TARGET_HARD_REGNO_NREGS loongarch_hard_regno_nregs
   11212 #undef TARGET_HARD_REGNO_MODE_OK
   11213 #define TARGET_HARD_REGNO_MODE_OK loongarch_hard_regno_mode_ok
   11214 
   11215 #undef TARGET_MODES_TIEABLE_P
   11216 #define TARGET_MODES_TIEABLE_P loongarch_modes_tieable_p
   11217 
   11218 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
   11219 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   11220   loongarch_hard_regno_call_part_clobbered
   11221 
   11222 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
   11223 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
   11224 
   11225 #undef TARGET_CAN_CHANGE_MODE_CLASS
   11226 #define TARGET_CAN_CHANGE_MODE_CLASS loongarch_can_change_mode_class
   11227 
   11228 #undef TARGET_CONSTANT_ALIGNMENT
   11229 #define TARGET_CONSTANT_ALIGNMENT loongarch_constant_alignment
   11230 
   11231 #undef TARGET_STARTING_FRAME_OFFSET
   11232 #define TARGET_STARTING_FRAME_OFFSET loongarch_starting_frame_offset
   11233 
   11234 #undef TARGET_SECONDARY_RELOAD
   11235 #define TARGET_SECONDARY_RELOAD loongarch_secondary_reload
   11236 
   11237 #undef  TARGET_HAVE_SPECULATION_SAFE_VALUE
   11238 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
   11239 
   11240 #undef  TARGET_ATTRIBUTE_TABLE
   11241 #define TARGET_ATTRIBUTE_TABLE loongarch_attribute_table
   11242 
   11243 #undef  TARGET_USE_ANCHORS_FOR_SYMBOL_P
   11244 #define TARGET_USE_ANCHORS_FOR_SYMBOL_P loongarch_use_anchors_for_symbol_p
   11245 
   11246 #undef TARGET_ASAN_SHADOW_OFFSET
   11247 #define TARGET_ASAN_SHADOW_OFFSET loongarch_asan_shadow_offset
   11248 
   11249 #undef TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS
   11250 #define TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS \
   11251   loongarch_get_separate_components
   11252 
   11253 #undef TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB
   11254 #define TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB loongarch_components_for_bb
   11255 
   11256 #undef TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS
   11257 #define TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS \
   11258   loongarch_disqualify_components
   11259 
   11260 #undef TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS
   11261 #define TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS \
   11262   loongarch_emit_prologue_components
   11263 
   11264 #undef TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS
   11265 #define TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS \
   11266   loongarch_emit_epilogue_components
   11267 
   11268 #undef TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS
   11269 #define TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS \
   11270   loongarch_set_handled_components
   11271 
   11272 #undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT
   11273 #define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \
   11274   loongarch_builtin_support_vector_misalignment
   11275 
   11276 #undef TARGET_C_MODE_FOR_SUFFIX
   11277 #define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix
   11278 
   11279 struct gcc_target targetm = TARGET_INITIALIZER;
   11280 
   11281 #include "gt-loongarch.h"
   11282