xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/loongarch/loongarch.cc (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /* Subroutines used for LoongArch code generation.
2    Copyright (C) 2021-2022 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 
67 /* This file should be included last.  */
68 #include "target-def.h"
69 
70 /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF.  */
71 #define UNSPEC_ADDRESS_P(X)					\
72   (GET_CODE (X) == UNSPEC					\
73    && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST			\
74    && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
75 
76 /* Extract the symbol or label from UNSPEC wrapper X.  */
77 #define UNSPEC_ADDRESS(X) XVECEXP (X, 0, 0)
78 
79 /* Extract the symbol type from UNSPEC wrapper X.  */
80 #define UNSPEC_ADDRESS_TYPE(X) \
81   ((enum loongarch_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
82 
83 /* True if INSN is a loongarch.md pattern or asm statement.  */
84 /* ???	This test exists through the compiler, perhaps it should be
85    moved to rtl.h.  */
86 #define USEFUL_INSN_P(INSN)						\
87   (NONDEBUG_INSN_P (INSN)						\
88    && GET_CODE (PATTERN (INSN)) != USE					\
89    && GET_CODE (PATTERN (INSN)) != CLOBBER)
90 
91 /* True if bit BIT is set in VALUE.  */
92 #define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0)
93 
94 /* Classifies an address.
95 
96    ADDRESS_REG
97        A natural register + offset address.  The register satisfies
98        loongarch_valid_base_register_p and the offset is a const_arith_operand.
99 
100    ADDRESS_REG_REG
101        A base register indexed by (optionally scaled) register.
102 
103    ADDRESS_CONST_INT
104        A signed 16-bit constant address.
105 
106    ADDRESS_SYMBOLIC:
107        A constant symbolic address.  */
108 enum loongarch_address_type
109 {
110   ADDRESS_REG,
111   ADDRESS_REG_REG,
112   ADDRESS_CONST_INT,
113   ADDRESS_SYMBOLIC
114 };
115 
116 
117 /* Information about an address described by loongarch_address_type.
118 
119    ADDRESS_CONST_INT
120        No fields are used.
121 
122    ADDRESS_REG
123        REG is the base register and OFFSET is the constant offset.
124 
125    ADDRESS_REG_REG
126        A base register indexed by (optionally scaled) register.
127 
128    ADDRESS_SYMBOLIC
129        SYMBOL_TYPE is the type of symbol that the address references.  */
130 struct loongarch_address_info
131 {
132   enum loongarch_address_type type;
133   rtx reg;
134   rtx offset;
135   enum loongarch_symbol_type symbol_type;
136 };
137 
138 /* Method of loading instant numbers:
139 
140    METHOD_NORMAL:
141      Load 0-31 bit of the immediate number.
142 
143    METHOD_LU32I:
144      Load 32-51 bit of the immediate number.
145 
146    METHOD_LU52I:
147      Load 52-63 bit of the immediate number.
148 
149    METHOD_INSV:
150      immediate like 0xfff00000fffffxxx
151    */
152 enum loongarch_load_imm_method
153 {
154   METHOD_NORMAL,
155   METHOD_LU32I,
156   METHOD_LU52I,
157   METHOD_INSV
158 };
159 
160 struct loongarch_integer_op
161 {
162   enum rtx_code code;
163   HOST_WIDE_INT 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 /* Which cost information to use.  */
212 static const struct loongarch_rtx_cost_data *loongarch_cost;
213 
214 /* Information about a single argument.  */
215 struct loongarch_arg_info
216 {
217   /* True if the argument is at least partially passed on the stack.  */
218   bool stack_p;
219 
220   /* The number of integer registers allocated to this argument.  */
221   unsigned int num_gprs;
222 
223   /* The offset of the first register used, provided num_gprs is nonzero.
224      If passed entirely on the stack, the value is MAX_ARGS_IN_REGISTERS.  */
225   unsigned int gpr_offset;
226 
227   /* The number of floating-point registers allocated to this argument.  */
228   unsigned int num_fprs;
229 
230   /* The offset of the first register used, provided num_fprs is nonzero.  */
231   unsigned int fpr_offset;
232 };
233 
234 /* Invoke MACRO (COND) for each fcmp.cond.{s/d} condition.  */
235 #define LARCH_FP_CONDITIONS(MACRO) \
236   MACRO (f),	\
237   MACRO (un),	\
238   MACRO (eq),	\
239   MACRO (ueq),	\
240   MACRO (olt),	\
241   MACRO (ult),	\
242   MACRO (ole),	\
243   MACRO (ule),	\
244   MACRO (sf),	\
245   MACRO (ngle),	\
246   MACRO (seq),	\
247   MACRO (ngl),	\
248   MACRO (lt),	\
249   MACRO (nge),	\
250   MACRO (le),	\
251   MACRO (ngt)
252 
253 /* Enumerates the codes above as LARCH_FP_COND_<X>.  */
254 #define DECLARE_LARCH_COND(X) LARCH_FP_COND_##X
255 enum loongarch_fp_condition
256 {
257   LARCH_FP_CONDITIONS (DECLARE_LARCH_COND)
258 };
259 #undef DECLARE_LARCH_COND
260 
261 /* Index X provides the string representation of LARCH_FP_COND_<X>.  */
262 #define STRINGIFY(X) #X
263 const char *const
264 loongarch_fp_conditions[16]= {LARCH_FP_CONDITIONS (STRINGIFY)};
265 #undef STRINGIFY
266 
267 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  Every parameter gets at
268    least PARM_BOUNDARY bits of alignment, but will be given anything up
269    to PREFERRED_STACK_BOUNDARY bits if the type requires it.  */
270 
271 static unsigned int
loongarch_function_arg_boundary(machine_mode mode,const_tree type)272 loongarch_function_arg_boundary (machine_mode mode, const_tree type)
273 {
274   unsigned int alignment;
275 
276   /* Use natural alignment if the type is not aggregate data.  */
277   if (type && !AGGREGATE_TYPE_P (type))
278     alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type));
279   else
280     alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
281 
282   return MIN (PREFERRED_STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment));
283 }
284 
285 /* If MODE represents an argument that can be passed or returned in
286    floating-point registers, return the number of registers, else 0.  */
287 
288 static unsigned
loongarch_pass_mode_in_fpr_p(machine_mode mode)289 loongarch_pass_mode_in_fpr_p (machine_mode mode)
290 {
291   if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG)
292     {
293       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
294 	return 1;
295 
296       if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
297 	return 2;
298     }
299 
300   return 0;
301 }
302 
303 typedef struct
304 {
305   const_tree type;
306   HOST_WIDE_INT offset;
307 } loongarch_aggregate_field;
308 
309 /* Identify subfields of aggregates that are candidates for passing in
310    floating-point registers.  */
311 
312 static int
loongarch_flatten_aggregate_field(const_tree type,loongarch_aggregate_field fields[2],int n,HOST_WIDE_INT offset)313 loongarch_flatten_aggregate_field (const_tree type,
314 				   loongarch_aggregate_field fields[2], int n,
315 				   HOST_WIDE_INT offset)
316 {
317   switch (TREE_CODE (type))
318     {
319     case RECORD_TYPE:
320       /* Can't handle incomplete types nor sizes that are not fixed.  */
321       if (!COMPLETE_TYPE_P (type)
322 	  || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
323 	  || !tree_fits_uhwi_p (TYPE_SIZE (type)))
324 	return -1;
325 
326       for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
327 	if (TREE_CODE (f) == FIELD_DECL)
328 	  {
329 	    if (!TYPE_P (TREE_TYPE (f)))
330 	      return -1;
331 
332 	    if (DECL_SIZE (f) && integer_zerop (DECL_SIZE (f)))
333 	      continue;
334 
335 	    HOST_WIDE_INT pos = offset + int_byte_position (f);
336 	    n = loongarch_flatten_aggregate_field (TREE_TYPE (f), fields, n,
337 						   pos);
338 	    if (n < 0)
339 	      return -1;
340 	  }
341       return n;
342 
343     case ARRAY_TYPE:
344       {
345 	HOST_WIDE_INT n_elts;
346 	loongarch_aggregate_field subfields[2];
347 	tree index = TYPE_DOMAIN (type);
348 	tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type));
349 	int n_subfields = loongarch_flatten_aggregate_field (TREE_TYPE (type),
350 							     subfields, 0,
351 							     offset);
352 
353 	/* Can't handle incomplete types nor sizes that are not fixed.  */
354 	if (n_subfields <= 0
355 	    || !COMPLETE_TYPE_P (type)
356 	    || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
357 	    || !index
358 	    || !TYPE_MAX_VALUE (index)
359 	    || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index))
360 	    || !TYPE_MIN_VALUE (index)
361 	    || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index))
362 	    || !tree_fits_uhwi_p (elt_size))
363 	  return -1;
364 
365 	n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index))
366 		 - tree_to_uhwi (TYPE_MIN_VALUE (index));
367 	gcc_assert (n_elts >= 0);
368 
369 	for (HOST_WIDE_INT i = 0; i < n_elts; i++)
370 	  for (int j = 0; j < n_subfields; j++)
371 	    {
372 	      if (n >= 2)
373 		return -1;
374 
375 	      fields[n] = subfields[j];
376 	      fields[n++].offset += i * tree_to_uhwi (elt_size);
377 	    }
378 
379 	return n;
380       }
381 
382     case COMPLEX_TYPE:
383       {
384 	/* Complex type need consume 2 field, so n must be 0.  */
385 	if (n != 0)
386 	  return -1;
387 
388 	HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)));
389 
390 	if (elt_size <= UNITS_PER_FP_ARG)
391 	  {
392 	    fields[0].type = TREE_TYPE (type);
393 	    fields[0].offset = offset;
394 	    fields[1].type = TREE_TYPE (type);
395 	    fields[1].offset = offset + elt_size;
396 
397 	    return 2;
398 	  }
399 
400 	return -1;
401       }
402 
403     default:
404       if (n < 2
405 	  && ((SCALAR_FLOAT_TYPE_P (type)
406 	       && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG)
407 	      || (INTEGRAL_TYPE_P (type)
408 		  && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD)))
409 	{
410 	  fields[n].type = type;
411 	  fields[n].offset = offset;
412 	  return n + 1;
413 	}
414       else
415 	return -1;
416     }
417 }
418 
419 /* Identify candidate aggregates for passing in floating-point registers.
420    Candidates have at most two fields after flattening.  */
421 
422 static int
loongarch_flatten_aggregate_argument(const_tree type,loongarch_aggregate_field fields[2])423 loongarch_flatten_aggregate_argument (const_tree type,
424 				      loongarch_aggregate_field fields[2])
425 {
426   if (!type || TREE_CODE (type) != RECORD_TYPE)
427     return -1;
428 
429   return loongarch_flatten_aggregate_field (type, fields, 0, 0);
430 }
431 
432 /* See whether TYPE is a record whose fields should be returned in one or
433    two floating-point registers.  If so, populate FIELDS accordingly.  */
434 
435 static unsigned
loongarch_pass_aggregate_num_fpr(const_tree type,loongarch_aggregate_field fields[2])436 loongarch_pass_aggregate_num_fpr (const_tree type,
437 					loongarch_aggregate_field fields[2])
438 {
439   int n = loongarch_flatten_aggregate_argument (type, fields);
440 
441   for (int i = 0; i < n; i++)
442     if (!SCALAR_FLOAT_TYPE_P (fields[i].type))
443       return 0;
444 
445   return n > 0 ? n : 0;
446 }
447 
448 /* See whether TYPE is a record whose fields should be returned in one
449    floating-point register and one integer register.  If so, populate
450    FIELDS accordingly.  */
451 
452 static bool
loongarch_pass_aggregate_in_fpr_and_gpr_p(const_tree type,loongarch_aggregate_field fields[2])453 loongarch_pass_aggregate_in_fpr_and_gpr_p (const_tree type,
454 					   loongarch_aggregate_field fields[2])
455 {
456   unsigned num_int = 0, num_float = 0;
457   int n = loongarch_flatten_aggregate_argument (type, fields);
458 
459   for (int i = 0; i < n; i++)
460     {
461       num_float += SCALAR_FLOAT_TYPE_P (fields[i].type);
462       num_int += INTEGRAL_TYPE_P (fields[i].type);
463     }
464 
465   return num_int == 1 && num_float == 1;
466 }
467 
468 /* Return the representation of an argument passed or returned in an FPR
469    when the value has mode VALUE_MODE and the type has TYPE_MODE.  The
470    two modes may be different for structures like:
471 
472    struct __attribute__((packed)) foo { float f; }
473 
474    where the SFmode value "f" is passed in REGNO but the struct itself
475    has mode BLKmode.  */
476 
477 static rtx
loongarch_pass_fpr_single(machine_mode type_mode,unsigned regno,machine_mode value_mode,HOST_WIDE_INT offset)478 loongarch_pass_fpr_single (machine_mode type_mode, unsigned regno,
479 			   machine_mode value_mode,
480 			   HOST_WIDE_INT offset)
481 {
482   rtx x = gen_rtx_REG (value_mode, regno);
483 
484   if (type_mode != value_mode)
485     {
486       x = gen_rtx_EXPR_LIST (VOIDmode, x, GEN_INT (offset));
487       x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x));
488     }
489   return x;
490 }
491 
492 /* Pass or return a composite value in the FPR pair REGNO and REGNO + 1.
493    MODE is the mode of the composite.  MODE1 and OFFSET1 are the mode and
494    byte offset for the first value, likewise MODE2 and OFFSET2 for the
495    second value.  */
496 
497 static rtx
loongarch_pass_fpr_pair(machine_mode mode,unsigned regno1,machine_mode mode1,HOST_WIDE_INT offset1,unsigned regno2,machine_mode mode2,HOST_WIDE_INT offset2)498 loongarch_pass_fpr_pair (machine_mode mode, unsigned regno1,
499 			 machine_mode mode1, HOST_WIDE_INT offset1,
500 			 unsigned regno2, machine_mode mode2,
501 			 HOST_WIDE_INT offset2)
502 {
503   return gen_rtx_PARALLEL (
504     mode, gen_rtvec (2,
505 		     gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode1, regno1),
506 					GEN_INT (offset1)),
507 		     gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode2, regno2),
508 					GEN_INT (offset2))));
509 }
510 
511 /* Fill INFO with information about a single argument, and return an
512    RTL pattern to pass or return the argument.  CUM is the cumulative
513    state for earlier arguments.  MODE is the mode of this argument and
514    TYPE is its type (if known).  NAMED is true if this is a named
515    (fixed) argument rather than a variable one.  RETURN_P is true if
516    returning the argument, or false if passing the argument.  */
517 
518 static rtx
loongarch_get_arg_info(struct loongarch_arg_info * info,const CUMULATIVE_ARGS * cum,machine_mode mode,const_tree type,bool named,bool return_p)519 loongarch_get_arg_info (struct loongarch_arg_info *info,
520 			const CUMULATIVE_ARGS *cum, machine_mode mode,
521 			const_tree type, bool named, bool return_p)
522 {
523   unsigned num_bytes, num_words;
524   unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST;
525   unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST;
526   unsigned alignment = loongarch_function_arg_boundary (mode, type);
527 
528   memset (info, 0, sizeof (*info));
529   info->gpr_offset = cum->num_gprs;
530   info->fpr_offset = cum->num_fprs;
531 
532   if (named)
533     {
534       loongarch_aggregate_field fields[2];
535       unsigned fregno = fpr_base + info->fpr_offset;
536       unsigned gregno = gpr_base + info->gpr_offset;
537 
538       /* Pass one- or two-element floating-point aggregates in FPRs.  */
539       if ((info->num_fprs
540 	   = loongarch_pass_aggregate_num_fpr (type, fields))
541 	  && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS)
542 	switch (info->num_fprs)
543 	  {
544 	  case 1:
545 	    return loongarch_pass_fpr_single (mode, fregno,
546 					      TYPE_MODE (fields[0].type),
547 					      fields[0].offset);
548 
549 	  case 2:
550 	    return loongarch_pass_fpr_pair (mode, fregno,
551 					    TYPE_MODE (fields[0].type),
552 					    fields[0].offset,
553 					    fregno + 1,
554 					    TYPE_MODE (fields[1].type),
555 					    fields[1].offset);
556 
557 	  default:
558 	    gcc_unreachable ();
559 	  }
560 
561       /* Pass real and complex floating-point numbers in FPRs.  */
562       if ((info->num_fprs = loongarch_pass_mode_in_fpr_p (mode))
563 	  && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS)
564 	switch (GET_MODE_CLASS (mode))
565 	  {
566 	  case MODE_FLOAT:
567 	    return gen_rtx_REG (mode, fregno);
568 
569 	  case MODE_COMPLEX_FLOAT:
570 	    return loongarch_pass_fpr_pair (mode, fregno,
571 					    GET_MODE_INNER (mode), 0,
572 					    fregno + 1, GET_MODE_INNER (mode),
573 					    GET_MODE_UNIT_SIZE (mode));
574 
575 	  default:
576 	    gcc_unreachable ();
577 	  }
578 
579       /* Pass structs with one float and one integer in an FPR and a GPR.  */
580       if (loongarch_pass_aggregate_in_fpr_and_gpr_p (type, fields)
581 	  && info->gpr_offset < MAX_ARGS_IN_REGISTERS
582 	  && info->fpr_offset < MAX_ARGS_IN_REGISTERS)
583 	{
584 	  info->num_gprs = 1;
585 	  info->num_fprs = 1;
586 
587 	  if (!SCALAR_FLOAT_TYPE_P (fields[0].type))
588 	    std::swap (fregno, gregno);
589 
590 	  return loongarch_pass_fpr_pair (mode, fregno,
591 					  TYPE_MODE (fields[0].type),
592 					  fields[0].offset, gregno,
593 					  TYPE_MODE (fields[1].type),
594 					  fields[1].offset);
595 	}
596     }
597 
598   /* Work out the size of the argument.  */
599   num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
600   num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
601 
602   /* Doubleword-aligned varargs start on an even register boundary.  */
603   if (!named && num_bytes != 0 && alignment > BITS_PER_WORD)
604     info->gpr_offset += info->gpr_offset & 1;
605 
606   /* Partition the argument between registers and stack.  */
607   info->num_fprs = 0;
608   info->num_gprs = MIN (num_words, MAX_ARGS_IN_REGISTERS - info->gpr_offset);
609   info->stack_p = (num_words - info->num_gprs) != 0;
610 
611   if (info->num_gprs || return_p)
612     return gen_rtx_REG (mode, gpr_base + info->gpr_offset);
613 
614   return NULL_RTX;
615 }
616 
617 /* Implement TARGET_FUNCTION_ARG.  */
618 
619 static rtx
loongarch_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)620 loongarch_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
621 {
622   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
623   struct loongarch_arg_info info;
624 
625   if (arg.end_marker_p ())
626     return NULL;
627 
628   return loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named,
629 				 false);
630 }
631 
632 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
633 
634 static void
loongarch_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)635 loongarch_function_arg_advance (cumulative_args_t cum_v,
636 				const function_arg_info &arg)
637 {
638   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
639   struct loongarch_arg_info info;
640 
641   loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
642 
643   /* Advance the register count.  This has the effect of setting
644      num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned
645      argument required us to skip the final GPR and pass the whole
646      argument on the stack.  */
647   cum->num_fprs = info.fpr_offset + info.num_fprs;
648   cum->num_gprs = info.gpr_offset + info.num_gprs;
649 }
650 
651 /* Implement TARGET_ARG_PARTIAL_BYTES.  */
652 
653 static int
loongarch_arg_partial_bytes(cumulative_args_t cum,const function_arg_info & generic_arg)654 loongarch_arg_partial_bytes (cumulative_args_t cum,
655 			     const function_arg_info &generic_arg)
656 {
657   struct loongarch_arg_info arg;
658 
659   loongarch_get_arg_info (&arg, get_cumulative_args (cum), generic_arg.mode,
660 			  generic_arg.type, generic_arg.named, false);
661   return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0;
662 }
663 
664 /* Implement FUNCTION_VALUE and LIBCALL_VALUE.  For normal calls,
665    VALTYPE is the return type and MODE is VOIDmode.  For libcalls,
666    VALTYPE is null and MODE is the mode of the return value.  */
667 
668 static rtx
loongarch_function_value_1(const_tree type,const_tree func,machine_mode mode)669 loongarch_function_value_1 (const_tree type, const_tree func,
670 			    machine_mode mode)
671 {
672   struct loongarch_arg_info info;
673   CUMULATIVE_ARGS args;
674 
675   if (type)
676     {
677       int unsigned_p = TYPE_UNSIGNED (type);
678 
679       mode = TYPE_MODE (type);
680 
681       /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes,
682 	 return values, promote the mode here too.  */
683       mode = promote_function_mode (type, mode, &unsigned_p, func, 1);
684     }
685 
686   memset (&args, 0, sizeof (args));
687   return loongarch_get_arg_info (&info, &args, mode, type, true, true);
688 }
689 
690 
691 /* Implement TARGET_FUNCTION_VALUE.  */
692 
693 static rtx
loongarch_function_value(const_tree valtype,const_tree fn_decl_or_type,bool outgoing ATTRIBUTE_UNUSED)694 loongarch_function_value (const_tree valtype, const_tree fn_decl_or_type,
695 			  bool outgoing ATTRIBUTE_UNUSED)
696 {
697   return loongarch_function_value_1 (valtype, fn_decl_or_type, VOIDmode);
698 }
699 
700 /* Implement TARGET_LIBCALL_VALUE.  */
701 
702 static rtx
loongarch_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)703 loongarch_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
704 {
705   return loongarch_function_value_1 (NULL_TREE, NULL_TREE, mode);
706 }
707 
708 
709 /* Implement TARGET_PASS_BY_REFERENCE.  */
710 
711 static bool
loongarch_pass_by_reference(cumulative_args_t cum_v,const function_arg_info & arg)712 loongarch_pass_by_reference (cumulative_args_t cum_v,
713 			     const function_arg_info &arg)
714 {
715   HOST_WIDE_INT size = arg.type_size_in_bytes ();
716   struct loongarch_arg_info info;
717   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
718 
719   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  Fortunately, we
720      never pass variadic arguments in floating-point registers, so we can
721      avoid the call to loongarch_get_arg_info in this case.  */
722   if (cum != NULL)
723     {
724       /* Don't pass by reference if we can use a floating-point register.  */
725       loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named,
726 			      false);
727       if (info.num_fprs)
728 	return false;
729     }
730 
731   /* Pass by reference if the data do not fit in two integer registers.  */
732   return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD);
733 }
734 
735 /* Implement TARGET_RETURN_IN_MEMORY.  */
736 
737 static bool
loongarch_return_in_memory(const_tree type,const_tree fndecl ATTRIBUTE_UNUSED)738 loongarch_return_in_memory (const_tree type,
739 			    const_tree fndecl ATTRIBUTE_UNUSED)
740 {
741   CUMULATIVE_ARGS args;
742   cumulative_args_t cum = pack_cumulative_args (&args);
743 
744   /* The rules for returning in memory are the same as for passing the
745      first named argument by reference.  */
746   memset (&args, 0, sizeof (args));
747   function_arg_info arg (const_cast<tree> (type), /*named=*/true);
748   return loongarch_pass_by_reference (cum, arg);
749 }
750 
751 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
752 
753 static void
loongarch_setup_incoming_varargs(cumulative_args_t cum,const function_arg_info & arg,int * pretend_size ATTRIBUTE_UNUSED,int no_rtl)754 loongarch_setup_incoming_varargs (cumulative_args_t cum,
755 				  const function_arg_info &arg,
756 				  int *pretend_size ATTRIBUTE_UNUSED,
757 				  int no_rtl)
758 {
759   CUMULATIVE_ARGS local_cum;
760   int gp_saved;
761 
762   /* The caller has advanced CUM up to, but not beyond, the last named
763      argument.  Advance a local copy of CUM past the last "real" named
764      argument, to find out how many registers are left over.  */
765   local_cum = *get_cumulative_args (cum);
766   loongarch_function_arg_advance (pack_cumulative_args (&local_cum), arg);
767 
768   /* Found out how many registers we need to save.  */
769   gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
770 
771   if (!no_rtl && gp_saved > 0)
772     {
773       rtx ptr = plus_constant (Pmode, virtual_incoming_args_rtx,
774 			       REG_PARM_STACK_SPACE (cfun->decl)
775 				 - gp_saved * UNITS_PER_WORD);
776       rtx mem = gen_frame_mem (BLKmode, ptr);
777       set_mem_alias_set (mem, get_varargs_alias_set ());
778 
779       move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, mem, gp_saved);
780     }
781   if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
782     cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD;
783 }
784 
785 /* Make the last instruction frame-related and note that it performs
786    the operation described by FRAME_PATTERN.  */
787 
788 static void
loongarch_set_frame_expr(rtx frame_pattern)789 loongarch_set_frame_expr (rtx frame_pattern)
790 {
791   rtx insn;
792 
793   insn = get_last_insn ();
794   RTX_FRAME_RELATED_P (insn) = 1;
795   REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, frame_pattern,
796 				      REG_NOTES (insn));
797 }
798 
799 /* Return a frame-related rtx that stores REG at MEM.
800    REG must be a single register.  */
801 
802 static rtx
loongarch_frame_set(rtx mem,rtx reg)803 loongarch_frame_set (rtx mem, rtx reg)
804 {
805   rtx set = gen_rtx_SET (mem, reg);
806   RTX_FRAME_RELATED_P (set) = 1;
807   return set;
808 }
809 
810 /* Return true if the current function must save register REGNO.  */
811 
812 static bool
loongarch_save_reg_p(unsigned int regno)813 loongarch_save_reg_p (unsigned int regno)
814 {
815   bool call_saved = !global_regs[regno] && !call_used_regs[regno];
816   bool might_clobber
817     = crtl->saves_all_registers || df_regs_ever_live_p (regno);
818 
819   if (call_saved && might_clobber)
820     return true;
821 
822   if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
823     return true;
824 
825   if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
826     return true;
827 
828   return false;
829 }
830 
831 /* Determine which GPR save/restore routine to call.  */
832 
833 static unsigned
loongarch_save_libcall_count(unsigned mask)834 loongarch_save_libcall_count (unsigned mask)
835 {
836   for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--)
837     if (BITSET_P (mask, n))
838       return CALLEE_SAVED_REG_NUMBER (n) + 1;
839   abort ();
840 }
841 
842 /* Populate the current function's loongarch_frame_info structure.
843 
844    LoongArch stack frames grown downward.  High addresses are at the top.
845 
846      +-------------------------------+
847      |				     |
848      |  incoming stack arguments     |
849      |				     |
850      +-------------------------------+ <-- incoming stack pointer
851      |				     |
852      |  callee-allocated save area   |
853      |  for arguments that are       |
854      |  split between registers and  |
855      |  the stack		     |
856      |				     |
857      +-------------------------------+ <-- arg_pointer_rtx (virtual)
858      |				     |
859      |  callee-allocated save area   |
860      |  for register varargs	     |
861      |				     |
862      +-------------------------------+ <-- hard_frame_pointer_rtx;
863      |				     |     stack_pointer_rtx + gp_sp_offset
864      |  GPR save area		     |       + UNITS_PER_WORD
865      |				     |
866      +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
867      |				     |       + UNITS_PER_HWVALUE
868      |  FPR save area		     |
869      |				     |
870      +-------------------------------+ <-- frame_pointer_rtx (virtual)
871      |				     |
872      |  local variables		     |
873      |				     |
874    P +-------------------------------+
875      |				     |
876      |  outgoing stack arguments     |
877      |				     |
878      +-------------------------------+ <-- stack_pointer_rtx
879 
880    Dynamic stack allocations such as alloca insert data at point P.
881    They decrease stack_pointer_rtx but leave frame_pointer_rtx and
882    hard_frame_pointer_rtx unchanged.  */
883 
884 static void
loongarch_compute_frame_info(void)885 loongarch_compute_frame_info (void)
886 {
887   struct loongarch_frame_info *frame;
888   HOST_WIDE_INT offset;
889   unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
890 
891   frame = &cfun->machine->frame;
892   memset (frame, 0, sizeof (*frame));
893 
894   /* Find out which GPRs we need to save.  */
895   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
896     if (loongarch_save_reg_p (regno))
897       frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
898 
899   /* If this function calls eh_return, we must also save and restore the
900      EH data registers.  */
901   if (crtl->calls_eh_return)
902     for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
903       frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
904 
905   /* Find out which FPRs we need to save.  This loop must iterate over
906      the same space as its companion in loongarch_for_each_saved_reg.  */
907   if (TARGET_HARD_FLOAT)
908     for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
909       if (loongarch_save_reg_p (regno))
910 	frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
911 
912   /* At the bottom of the frame are any outgoing stack arguments.  */
913   offset = LARCH_STACK_ALIGN (crtl->outgoing_args_size);
914   /* Next are local stack variables.  */
915   offset += LARCH_STACK_ALIGN (get_frame_size ());
916   /* The virtual frame pointer points above the local variables.  */
917   frame->frame_pointer_offset = offset;
918   /* Next are the callee-saved FPRs.  */
919   if (frame->fmask)
920     {
921       offset += LARCH_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG);
922       frame->fp_sp_offset = offset - UNITS_PER_FP_REG;
923     }
924   else
925     frame->fp_sp_offset = offset;
926   /* Next are the callee-saved GPRs.  */
927   if (frame->mask)
928     {
929       unsigned x_save_size = LARCH_STACK_ALIGN (num_x_saved * UNITS_PER_WORD);
930       unsigned num_save_restore
931 	= 1 + loongarch_save_libcall_count (frame->mask);
932 
933       /* Only use save/restore routines if they don't alter the stack size.  */
934       if (LARCH_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size)
935 	frame->save_libcall_adjustment = x_save_size;
936 
937       offset += x_save_size;
938       frame->gp_sp_offset = offset - UNITS_PER_WORD;
939     }
940   else
941     frame->gp_sp_offset = offset;
942   /* The hard frame pointer points above the callee-saved GPRs.  */
943   frame->hard_frame_pointer_offset = offset;
944   /* Above the hard frame pointer is the callee-allocated varags save area.  */
945   offset += LARCH_STACK_ALIGN (cfun->machine->varargs_size);
946   /* Next is the callee-allocated area for pretend stack arguments.  */
947   offset += LARCH_STACK_ALIGN (crtl->args.pretend_args_size);
948   /* Arg pointer must be below pretend args, but must be above alignment
949      padding.  */
950   frame->arg_pointer_offset = offset - crtl->args.pretend_args_size;
951   frame->total_size = offset;
952   /* Next points the incoming stack pointer and any incoming arguments.  */
953 
954   /* Only use save/restore routines when the GPRs are atop the frame.  */
955   if (frame->hard_frame_pointer_offset != frame->total_size)
956     frame->save_libcall_adjustment = 0;
957 }
958 
959 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame pointer
960    or argument pointer.  TO is either the stack pointer or hard frame
961    pointer.  */
962 
963 HOST_WIDE_INT
loongarch_initial_elimination_offset(int from,int to)964 loongarch_initial_elimination_offset (int from, int to)
965 {
966   HOST_WIDE_INT src, dest;
967 
968   loongarch_compute_frame_info ();
969 
970   if (to == HARD_FRAME_POINTER_REGNUM)
971     dest = cfun->machine->frame.hard_frame_pointer_offset;
972   else if (to == STACK_POINTER_REGNUM)
973     dest = 0; /* The stack pointer is the base of all offsets, hence 0.  */
974   else
975     gcc_unreachable ();
976 
977   if (from == FRAME_POINTER_REGNUM)
978     src = cfun->machine->frame.frame_pointer_offset;
979   else if (from == ARG_POINTER_REGNUM)
980     src = cfun->machine->frame.arg_pointer_offset;
981   else
982     gcc_unreachable ();
983 
984   return src - dest;
985 }
986 
987 /* A function to save or store a register.  The first argument is the
988    register and the second is the stack slot.  */
989 typedef void (*loongarch_save_restore_fn) (rtx, rtx);
990 
991 /* Use FN to save or restore register REGNO.  MODE is the register's
992    mode and OFFSET is the offset of its save slot from the current
993    stack pointer.  */
994 
995 static void
loongarch_save_restore_reg(machine_mode mode,int regno,HOST_WIDE_INT offset,loongarch_save_restore_fn fn)996 loongarch_save_restore_reg (machine_mode mode, int regno, HOST_WIDE_INT offset,
997 			    loongarch_save_restore_fn fn)
998 {
999   rtx mem;
1000 
1001   mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset));
1002   fn (gen_rtx_REG (mode, regno), mem);
1003 }
1004 
1005 /* Call FN for each register that is saved by the current function.
1006    SP_OFFSET is the offset of the current stack pointer from the start
1007    of the frame.  */
1008 
1009 static void
loongarch_for_each_saved_reg(HOST_WIDE_INT sp_offset,loongarch_save_restore_fn fn,bool skip_eh_data_regs_p)1010 loongarch_for_each_saved_reg (HOST_WIDE_INT sp_offset,
1011 			      loongarch_save_restore_fn fn,
1012 			      bool skip_eh_data_regs_p)
1013 {
1014   HOST_WIDE_INT offset;
1015 
1016   /* Save the link register and s-registers.  */
1017   offset = cfun->machine->frame.gp_sp_offset - sp_offset;
1018   for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
1019     if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
1020       {
1021 	/* Special care needs to be taken for $r4-$r7 (EH_RETURN_DATA_REGNO)
1022 	   when returning normally from a function that calls
1023 	   __builtin_eh_return.  In this case, these registers are saved but
1024 	   should not be restored, or the return value may be clobbered.  */
1025 
1026 	if (!(skip_eh_data_regs_p
1027 	      && GP_ARG_FIRST <= regno && regno < GP_ARG_FIRST + 4))
1028 	  loongarch_save_restore_reg (word_mode, regno, offset, fn);
1029 
1030 	offset -= UNITS_PER_WORD;
1031       }
1032 
1033   /* This loop must iterate over the same space as its companion in
1034      loongarch_compute_frame_info.  */
1035   offset = cfun->machine->frame.fp_sp_offset - sp_offset;
1036   for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
1037     if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
1038       {
1039 	machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
1040 
1041 	loongarch_save_restore_reg (mode, regno, offset, fn);
1042 	offset -= GET_MODE_SIZE (mode);
1043       }
1044 }
1045 
1046 /* Emit a move from SRC to DEST.  Assume that the move expanders can
1047    handle all moves if !can_create_pseudo_p ().  The distinction is
1048    important because, unlike emit_move_insn, the move expanders know
1049    how to force Pmode objects into the constant pool even when the
1050    constant pool address is not itself legitimate.  */
1051 
1052 rtx
loongarch_emit_move(rtx dest,rtx src)1053 loongarch_emit_move (rtx dest, rtx src)
1054 {
1055   return (can_create_pseudo_p () ? emit_move_insn (dest, src)
1056 				 : emit_move_insn_1 (dest, src));
1057 }
1058 
1059 /* Save register REG to MEM.  Make the instruction frame-related.  */
1060 
1061 static void
loongarch_save_reg(rtx reg,rtx mem)1062 loongarch_save_reg (rtx reg, rtx mem)
1063 {
1064   loongarch_emit_move (mem, reg);
1065   loongarch_set_frame_expr (loongarch_frame_set (mem, reg));
1066 }
1067 
1068 /* Restore register REG from MEM.  */
1069 
1070 static void
loongarch_restore_reg(rtx reg,rtx mem)1071 loongarch_restore_reg (rtx reg, rtx mem)
1072 {
1073   rtx insn = loongarch_emit_move (reg, mem);
1074   rtx dwarf = NULL_RTX;
1075   dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
1076   REG_NOTES (insn) = dwarf;
1077 
1078   RTX_FRAME_RELATED_P (insn) = 1;
1079 }
1080 
1081 /* For stack frames that can't be allocated with a single ADDI instruction,
1082    compute the best value to initially allocate.  It must at a minimum
1083    allocate enough space to spill the callee-saved registers.  */
1084 
1085 static HOST_WIDE_INT
loongarch_first_stack_step(struct loongarch_frame_info * frame)1086 loongarch_first_stack_step (struct loongarch_frame_info *frame)
1087 {
1088   if (IMM12_OPERAND (frame->total_size))
1089     return frame->total_size;
1090 
1091   HOST_WIDE_INT min_first_step
1092     = LARCH_STACK_ALIGN (frame->total_size - frame->fp_sp_offset);
1093   HOST_WIDE_INT max_first_step = IMM_REACH / 2 - PREFERRED_STACK_BOUNDARY / 8;
1094   HOST_WIDE_INT min_second_step = frame->total_size - max_first_step;
1095   gcc_assert (min_first_step <= max_first_step);
1096 
1097   /* As an optimization, use the least-significant bits of the total frame
1098      size, so that the second adjustment step is just LU12I + ADD.  */
1099   if (!IMM12_OPERAND (min_second_step)
1100       && frame->total_size % IMM_REACH < IMM_REACH / 2
1101       && frame->total_size % IMM_REACH >= min_first_step)
1102     return frame->total_size % IMM_REACH;
1103 
1104   return max_first_step;
1105 }
1106 
1107 static void
loongarch_emit_stack_tie(void)1108 loongarch_emit_stack_tie (void)
1109 {
1110   emit_insn (gen_stack_tie (Pmode, stack_pointer_rtx,
1111 			    frame_pointer_needed ? hard_frame_pointer_rtx
1112 			    : stack_pointer_rtx));
1113 }
1114 
1115 #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
1116 
1117 #if PROBE_INTERVAL > 16384
1118 #error Cannot use indexed addressing mode for stack probing
1119 #endif
1120 
1121 /* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
1122    inclusive.  These are offsets from the current stack pointer.  */
1123 
1124 static void
loongarch_emit_probe_stack_range(HOST_WIDE_INT first,HOST_WIDE_INT size)1125 loongarch_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
1126 {
1127   /* See if we have a constant small number of probes to generate.  If so,
1128      that's the easy case.  */
1129   if ((TARGET_64BIT && (first + size <= 32768))
1130       || (!TARGET_64BIT && (first + size <= 2048)))
1131     {
1132       HOST_WIDE_INT i;
1133 
1134       /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
1135 	 it exceeds SIZE.  If only one probe is needed, this will not
1136 	 generate any code.  Then probe at FIRST + SIZE.  */
1137       for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
1138 	emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
1139 					 -(first + i)));
1140 
1141       emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
1142 				       -(first + size)));
1143     }
1144 
1145   /* Otherwise, do the same as above, but in a loop.  Note that we must be
1146      extra careful with variables wrapping around because we might be at
1147      the very top (or the very bottom) of the address space and we have
1148      to be able to handle this case properly; in particular, we use an
1149      equality test for the loop condition.  */
1150   else
1151     {
1152       HOST_WIDE_INT rounded_size;
1153       rtx r13 = LARCH_PROLOGUE_TEMP (Pmode);
1154       rtx r12 = LARCH_PROLOGUE_TEMP2 (Pmode);
1155       rtx r14 = LARCH_PROLOGUE_TEMP3 (Pmode);
1156 
1157       /* Sanity check for the addressing mode we're going to use.  */
1158       gcc_assert (first <= 16384);
1159 
1160 
1161       /* Step 1: round SIZE to the previous multiple of the interval.  */
1162 
1163       rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
1164 
1165       /* TEST_ADDR = SP + FIRST */
1166       if (first != 0)
1167 	{
1168 	  emit_move_insn (r14, GEN_INT (first));
1169 	  emit_insn (gen_rtx_SET (r13, gen_rtx_MINUS (Pmode,
1170 						      stack_pointer_rtx,
1171 						      r14)));
1172 	}
1173       else
1174 	emit_move_insn (r13, stack_pointer_rtx);
1175 
1176       /* Step 2: compute initial and final value of the loop counter.  */
1177 
1178       emit_move_insn (r14, GEN_INT (PROBE_INTERVAL));
1179       /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE.  */
1180       if (rounded_size == 0)
1181 	emit_move_insn (r12, r13);
1182       else
1183 	{
1184 	  emit_move_insn (r12, GEN_INT (rounded_size));
1185 	  emit_insn (gen_rtx_SET (r12, gen_rtx_MINUS (Pmode, r13, r12)));
1186 	  /* Step 3: the loop
1187 
1188 	     do
1189 	     {
1190 	     TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
1191 	     probe at TEST_ADDR
1192 	     }
1193 	     while (TEST_ADDR != LAST_ADDR)
1194 
1195 	     probes at FIRST + N * PROBE_INTERVAL for values of N from 1
1196 	     until it is equal to ROUNDED_SIZE.  */
1197 
1198 	  emit_insn (gen_probe_stack_range (Pmode, r13, r13, r12, r14));
1199 	}
1200 
1201       /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
1202 	 that SIZE is equal to ROUNDED_SIZE.  */
1203 
1204       if (size != rounded_size)
1205 	{
1206 	  if (TARGET_64BIT)
1207 	    emit_stack_probe (plus_constant (Pmode, r12, rounded_size - size));
1208 	  else
1209 	    {
1210 	      HOST_WIDE_INT i;
1211 	      for (i = 2048; i < (size - rounded_size); i += 2048)
1212 		{
1213 		  emit_stack_probe (plus_constant (Pmode, r12, -i));
1214 		  emit_insn (gen_rtx_SET (r12,
1215 					  plus_constant (Pmode, r12, -2048)));
1216 		}
1217 	      rtx r1 = plus_constant (Pmode, r12,
1218 				      -(size - rounded_size - i + 2048));
1219 	      emit_stack_probe (r1);
1220 	    }
1221 	}
1222     }
1223 
1224   /* Make sure nothing is scheduled before we are done.  */
1225   emit_insn (gen_blockage ());
1226 }
1227 
1228 /* Probe a range of stack addresses from REG1 to REG2 inclusive.  These are
1229    absolute addresses.  */
1230 const char *
loongarch_output_probe_stack_range(rtx reg1,rtx reg2,rtx reg3)1231 loongarch_output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3)
1232 {
1233   static int labelno = 0;
1234   char loop_lab[32], tmp[64];
1235   rtx xops[3];
1236 
1237   ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
1238 
1239   /* Loop.  */
1240   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
1241 
1242   /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL.  */
1243   xops[0] = reg1;
1244   xops[1] = GEN_INT (-PROBE_INTERVAL);
1245   xops[2] = reg3;
1246   if (TARGET_64BIT)
1247     output_asm_insn ("sub.d\t%0,%0,%2", xops);
1248   else
1249     output_asm_insn ("sub.w\t%0,%0,%2", xops);
1250 
1251   /* Probe at TEST_ADDR, test if TEST_ADDR == LAST_ADDR and branch.  */
1252   xops[1] = reg2;
1253   strcpy (tmp, "bne\t%0,%1,");
1254   if (TARGET_64BIT)
1255     output_asm_insn ("st.d\t$r0,%0,0", xops);
1256   else
1257     output_asm_insn ("st.w\t$r0,%0,0", xops);
1258   output_asm_insn (strcat (tmp, &loop_lab[1]), xops);
1259 
1260   return "";
1261 }
1262 
1263 /* Expand the "prologue" pattern.  */
1264 
1265 void
loongarch_expand_prologue(void)1266 loongarch_expand_prologue (void)
1267 {
1268   struct loongarch_frame_info *frame = &cfun->machine->frame;
1269   HOST_WIDE_INT size = frame->total_size;
1270   HOST_WIDE_INT tmp;
1271   rtx insn;
1272 
1273   if (flag_stack_usage_info)
1274     current_function_static_stack_size = size;
1275 
1276   if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
1277       || flag_stack_clash_protection)
1278     {
1279       if (crtl->is_leaf && !cfun->calls_alloca)
1280 	{
1281 	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
1282 	    {
1283 	      tmp = size - get_stack_check_protect ();
1284 	      loongarch_emit_probe_stack_range (get_stack_check_protect (),
1285 						tmp);
1286 	    }
1287 	}
1288       else if (size > 0)
1289 	loongarch_emit_probe_stack_range (get_stack_check_protect (), size);
1290     }
1291 
1292   /* Save the registers.  */
1293   if ((frame->mask | frame->fmask) != 0)
1294     {
1295       HOST_WIDE_INT step1 = MIN (size, loongarch_first_stack_step (frame));
1296 
1297       insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
1298 			    GEN_INT (-step1));
1299       RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
1300       size -= step1;
1301       loongarch_for_each_saved_reg (size, loongarch_save_reg, false);
1302     }
1303 
1304 
1305   /* Set up the frame pointer, if we're using one.  */
1306   if (frame_pointer_needed)
1307     {
1308       insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
1309 			    GEN_INT (frame->hard_frame_pointer_offset - size));
1310       RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
1311 
1312       loongarch_emit_stack_tie ();
1313     }
1314 
1315   /* Allocate the rest of the frame.  */
1316   if (size > 0)
1317     {
1318       if (IMM12_OPERAND (-size))
1319 	{
1320 	  insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
1321 				GEN_INT (-size));
1322 	  RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
1323 	}
1324       else
1325 	{
1326 	  loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), GEN_INT (-size));
1327 	  emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
1328 				    LARCH_PROLOGUE_TEMP (Pmode)));
1329 
1330 	  /* Describe the effect of the previous instructions.  */
1331 	  insn = plus_constant (Pmode, stack_pointer_rtx, -size);
1332 	  insn = gen_rtx_SET (stack_pointer_rtx, insn);
1333 	  loongarch_set_frame_expr (insn);
1334 	}
1335     }
1336 }
1337 
1338 /* Return nonzero if this function is known to have a null epilogue.
1339    This allows the optimizer to omit jumps to jumps if no stack
1340    was created.  */
1341 
1342 bool
loongarch_can_use_return_insn(void)1343 loongarch_can_use_return_insn (void)
1344 {
1345   return reload_completed && cfun->machine->frame.total_size == 0;
1346 }
1347 
1348 /* Expand function epilogue using the following insn patterns:
1349    "epilogue"	      (style == NORMAL_RETURN)
1350    "sibcall_epilogue" (style == SIBCALL_RETURN)
1351    "eh_return"	      (style == EXCEPTION_RETURN) */
1352 
1353 void
loongarch_expand_epilogue(int style)1354 loongarch_expand_epilogue (int style)
1355 {
1356   /* Split the frame into two.  STEP1 is the amount of stack we should
1357      deallocate before restoring the registers.  STEP2 is the amount we
1358      should deallocate afterwards.
1359 
1360      Start off by assuming that no registers need to be restored.  */
1361   struct loongarch_frame_info *frame = &cfun->machine->frame;
1362   HOST_WIDE_INT step1 = frame->total_size;
1363   HOST_WIDE_INT step2 = 0;
1364   rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
1365   rtx insn;
1366 
1367   /* We need to add memory barrier to prevent read from deallocated stack.  */
1368   bool need_barrier_p
1369     = (get_frame_size () + cfun->machine->frame.arg_pointer_offset) != 0;
1370 
1371   /* Handle simple returns.  */
1372   if (style == NORMAL_RETURN && loongarch_can_use_return_insn ())
1373     {
1374       emit_jump_insn (gen_return ());
1375       return;
1376     }
1377 
1378   /* Move past any dynamic stack allocations.  */
1379   if (cfun->calls_alloca)
1380     {
1381       /* Emit a barrier to prevent loads from a deallocated stack.  */
1382       loongarch_emit_stack_tie ();
1383       need_barrier_p = false;
1384 
1385       rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset);
1386       if (!IMM12_OPERAND (INTVAL (adjust)))
1387 	{
1388 	  loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust);
1389 	  adjust = LARCH_PROLOGUE_TEMP (Pmode);
1390 	}
1391 
1392       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
1393 				       hard_frame_pointer_rtx,
1394 				       adjust));
1395 
1396       rtx dwarf = NULL_RTX;
1397       rtx minus_offset = GEN_INT (-frame->hard_frame_pointer_offset);
1398       rtx cfa_adjust_value = gen_rtx_PLUS (Pmode,
1399 					   hard_frame_pointer_rtx,
1400 					   minus_offset);
1401 
1402       rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value);
1403       dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf);
1404       RTX_FRAME_RELATED_P (insn) = 1;
1405 
1406       REG_NOTES (insn) = dwarf;
1407     }
1408 
1409   /* If we need to restore registers, deallocate as much stack as
1410      possible in the second step without going out of range.  */
1411   if ((frame->mask | frame->fmask) != 0)
1412     {
1413       step2 = loongarch_first_stack_step (frame);
1414       step1 -= step2;
1415     }
1416 
1417   /* Set TARGET to BASE + STEP1.  */
1418   if (step1 > 0)
1419     {
1420       /* Emit a barrier to prevent loads from a deallocated stack.  */
1421       loongarch_emit_stack_tie ();
1422       need_barrier_p = false;
1423 
1424       /* Get an rtx for STEP1 that we can add to BASE.  */
1425       rtx adjust = GEN_INT (step1);
1426       if (!IMM12_OPERAND (step1))
1427 	{
1428 	  loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust);
1429 	  adjust = LARCH_PROLOGUE_TEMP (Pmode);
1430 	}
1431 
1432       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
1433 				       stack_pointer_rtx,
1434 				       adjust));
1435 
1436       rtx dwarf = NULL_RTX;
1437       rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1438 					 GEN_INT (step2));
1439 
1440       dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
1441       RTX_FRAME_RELATED_P (insn) = 1;
1442 
1443       REG_NOTES (insn) = dwarf;
1444     }
1445 
1446   /* Restore the registers.  */
1447   loongarch_for_each_saved_reg (frame->total_size - step2,
1448 				loongarch_restore_reg,
1449 				crtl->calls_eh_return
1450 				&& style != EXCEPTION_RETURN);
1451 
1452   if (need_barrier_p)
1453     loongarch_emit_stack_tie ();
1454 
1455   /* Deallocate the final bit of the frame.  */
1456   if (step2 > 0)
1457     {
1458       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
1459 				       stack_pointer_rtx,
1460 				       GEN_INT (step2)));
1461 
1462       rtx dwarf = NULL_RTX;
1463       rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx);
1464       dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
1465       RTX_FRAME_RELATED_P (insn) = 1;
1466 
1467       REG_NOTES (insn) = dwarf;
1468     }
1469 
1470   /* Add in the __builtin_eh_return stack adjustment.  */
1471   if (crtl->calls_eh_return && style == EXCEPTION_RETURN)
1472     emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
1473 			      EH_RETURN_STACKADJ_RTX));
1474 
1475   /* Emit return unless doing sibcall.  */
1476   if (style != SIBCALL_RETURN)
1477     emit_jump_insn (gen_simple_return_internal (ra));
1478 }
1479 
1480 #define LU32I_B (0xfffffULL << 32)
1481 #define LU52I_B (0xfffULL << 52)
1482 
1483 /* Fill CODES with a sequence of rtl operations to load VALUE.
1484    Return the number of operations needed.  */
1485 
1486 static unsigned int
loongarch_build_integer(struct loongarch_integer_op * codes,HOST_WIDE_INT value)1487 loongarch_build_integer (struct loongarch_integer_op *codes,
1488 			 HOST_WIDE_INT value)
1489 
1490 {
1491   unsigned int cost = 0;
1492 
1493   /* Get the lower 32 bits of the value.  */
1494   HOST_WIDE_INT low_part = (int32_t)value;
1495 
1496   if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part))
1497     {
1498       /* The value of the lower 32 bit be loaded with one instruction.
1499 	 lu12i.w.  */
1500       codes[0].code = UNKNOWN;
1501       codes[0].method = METHOD_NORMAL;
1502       codes[0].value = low_part;
1503       cost++;
1504     }
1505   else
1506     {
1507       /* lu12i.w + ior.  */
1508       codes[0].code = UNKNOWN;
1509       codes[0].method = METHOD_NORMAL;
1510       codes[0].value = low_part & ~(IMM_REACH - 1);
1511       cost++;
1512       HOST_WIDE_INT iorv = low_part & (IMM_REACH - 1);
1513       if (iorv != 0)
1514 	{
1515 	  codes[1].code = IOR;
1516 	  codes[1].method = METHOD_NORMAL;
1517 	  codes[1].value = iorv;
1518 	  cost++;
1519 	}
1520     }
1521 
1522   if (TARGET_64BIT)
1523     {
1524       bool lu32i[2] = {(value & LU32I_B) == 0, (value & LU32I_B) == LU32I_B};
1525       bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B};
1526 
1527       int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31;
1528       int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51;
1529       /* Determine whether the upper 32 bits are sign-extended from the lower
1530 	 32 bits. If it is, the instructions to load the high order can be
1531 	 ommitted.  */
1532       if (lu32i[sign31] && lu52i[sign31])
1533 	return cost;
1534       /* Determine whether bits 32-51 are sign-extended from the lower 32
1535 	 bits. If so, directly load 52-63 bits.  */
1536       else if (lu32i[sign31])
1537 	{
1538 	  codes[cost].method = METHOD_LU52I;
1539 	  codes[cost].value = value & LU52I_B;
1540 	  return cost + 1;
1541 	}
1542 
1543       codes[cost].method = METHOD_LU32I;
1544       codes[cost].value = (value & LU32I_B) | (sign51 ? LU52I_B : 0);
1545       cost++;
1546 
1547       /* Determine whether the 52-61 bits are sign-extended from the low order,
1548 	 and if not, load the 52-61 bits.  */
1549       if (!lu52i[(value & (HOST_WIDE_INT_1U << 51)) >> 51])
1550 	{
1551 	  codes[cost].method = METHOD_LU52I;
1552 	  codes[cost].value = value & LU52I_B;
1553 	  cost++;
1554 	}
1555     }
1556 
1557   gcc_assert (cost <= LARCH_MAX_INTEGER_OPS);
1558 
1559   return cost;
1560 }
1561 
1562 /* Fill CODES with a sequence of rtl operations to load VALUE.
1563    Return the number of operations needed.
1564    Split interger in loongarch_output_move.  */
1565 
1566 static unsigned int
loongarch_integer_cost(HOST_WIDE_INT value)1567 loongarch_integer_cost (HOST_WIDE_INT value)
1568 {
1569   struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS];
1570   return loongarch_build_integer (codes, value);
1571 }
1572 
1573 /* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
1574 
1575 static bool
loongarch_legitimate_constant_p(machine_mode mode ATTRIBUTE_UNUSED,rtx x)1576 loongarch_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1577 {
1578   return loongarch_const_insns (x) > 0;
1579 }
1580 
1581 /* Return true if X is a thread-local symbol.  */
1582 
1583 static bool
loongarch_tls_symbol_p(rtx x)1584 loongarch_tls_symbol_p (rtx x)
1585 {
1586   return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0;
1587 }
1588 
1589 /* Return true if SYMBOL_REF X is associated with a global symbol
1590    (in the STB_GLOBAL sense).  */
1591 
1592 bool
loongarch_global_symbol_p(const_rtx x)1593 loongarch_global_symbol_p (const_rtx x)
1594 {
1595   if (LABEL_REF_P (x))
1596     return false;
1597 
1598   const_tree decl = SYMBOL_REF_DECL (x);
1599 
1600   if (!decl)
1601     return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x);
1602 
1603   /* Weakref symbols are not TREE_PUBLIC, but their targets are global
1604      or weak symbols.  Relocations in the object file will be against
1605      the target symbol, so it's that symbol's binding that matters here.  */
1606   return DECL_P (decl) && (TREE_PUBLIC (decl) || DECL_WEAK (decl));
1607 }
1608 
1609 bool
loongarch_global_symbol_noweak_p(const_rtx x)1610 loongarch_global_symbol_noweak_p (const_rtx x)
1611 {
1612   if (LABEL_REF_P (x))
1613     return false;
1614 
1615   const_tree decl = SYMBOL_REF_DECL (x);
1616 
1617   if (!decl)
1618     return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x);
1619 
1620   return DECL_P (decl) && TREE_PUBLIC (decl);
1621 }
1622 
1623 bool
loongarch_weak_symbol_p(const_rtx x)1624 loongarch_weak_symbol_p (const_rtx x)
1625 {
1626   const_tree decl;
1627   if (LABEL_REF_P (x) || !(decl = SYMBOL_REF_DECL (x)))
1628     return false;
1629   return DECL_P (decl) && DECL_WEAK (decl);
1630 }
1631 
1632 /* Return true if SYMBOL_REF X binds locally.  */
1633 
1634 bool
loongarch_symbol_binds_local_p(const_rtx x)1635 loongarch_symbol_binds_local_p (const_rtx x)
1636 {
1637   if (LABEL_REF_P (x))
1638     return false;
1639 
1640   return (SYMBOL_REF_DECL (x) ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
1641 			      : SYMBOL_REF_LOCAL_P (x));
1642 }
1643 
1644 /* Return true if rtx constants of mode MODE should be put into a small
1645    data section.  */
1646 
1647 static bool
loongarch_rtx_constant_in_small_data_p(machine_mode mode)1648 loongarch_rtx_constant_in_small_data_p (machine_mode mode)
1649 {
1650   return (GET_MODE_SIZE (mode) <= g_switch_value);
1651 }
1652 
1653 /* Return the method that should be used to access SYMBOL_REF or
1654    LABEL_REF X.  */
1655 
1656 static enum loongarch_symbol_type
loongarch_classify_symbol(const_rtx x)1657 loongarch_classify_symbol (const_rtx x)
1658 {
1659   if (LABEL_REF_P (x))
1660     return SYMBOL_GOT_DISP;
1661 
1662   gcc_assert (SYMBOL_REF_P (x));
1663 
1664   if (SYMBOL_REF_TLS_MODEL (x))
1665     return SYMBOL_TLS;
1666 
1667   if (SYMBOL_REF_P (x))
1668     return SYMBOL_GOT_DISP;
1669 
1670   return SYMBOL_GOT_DISP;
1671 }
1672 
1673 /* Return true if X is a symbolic constant.  If it is,
1674    store the type of the symbol in *SYMBOL_TYPE.  */
1675 
1676 bool
loongarch_symbolic_constant_p(rtx x,enum loongarch_symbol_type * symbol_type)1677 loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type)
1678 {
1679   rtx offset;
1680 
1681   split_const (x, &x, &offset);
1682   if (UNSPEC_ADDRESS_P (x))
1683     {
1684       *symbol_type = UNSPEC_ADDRESS_TYPE (x);
1685       x = UNSPEC_ADDRESS (x);
1686     }
1687   else if (SYMBOL_REF_P (x) || LABEL_REF_P (x))
1688     {
1689       *symbol_type = loongarch_classify_symbol (x);
1690       if (*symbol_type == SYMBOL_TLS)
1691 	return true;
1692     }
1693   else
1694     return false;
1695 
1696   if (offset == const0_rtx)
1697     return true;
1698 
1699   /* Check whether a nonzero offset is valid for the underlying
1700      relocations.  */
1701   switch (*symbol_type)
1702     {
1703     case SYMBOL_GOT_DISP:
1704     case SYMBOL_TLSGD:
1705     case SYMBOL_TLSLDM:
1706     case SYMBOL_TLS:
1707       return false;
1708     }
1709   gcc_unreachable ();
1710 }
1711 
1712 /* Returns the number of instructions necessary to reference a symbol.  */
1713 
1714 static int
loongarch_symbol_insns(enum loongarch_symbol_type type,machine_mode mode)1715 loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
1716 {
1717   switch (type)
1718     {
1719     case SYMBOL_GOT_DISP:
1720       /* The constant will have to be loaded from the GOT before it
1721 	 is used in an address.  */
1722       if (mode != MAX_MACHINE_MODE)
1723 	return 0;
1724 
1725       return 3;
1726 
1727     case SYMBOL_TLSGD:
1728     case SYMBOL_TLSLDM:
1729       return 1;
1730 
1731     case SYMBOL_TLS:
1732       /* We don't treat a bare TLS symbol as a constant.  */
1733       return 0;
1734     }
1735   gcc_unreachable ();
1736 }
1737 
1738 /* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
1739 
1740 static bool
loongarch_cannot_force_const_mem(machine_mode mode,rtx x)1741 loongarch_cannot_force_const_mem (machine_mode mode, rtx x)
1742 {
1743   enum loongarch_symbol_type type;
1744   rtx base, offset;
1745 
1746   /* As an optimization, reject constants that loongarch_legitimize_move
1747      can expand inline.
1748 
1749      Suppose we have a multi-instruction sequence that loads constant C
1750      into register R.  If R does not get allocated a hard register, and
1751      R is used in an operand that allows both registers and memory
1752      references, reload will consider forcing C into memory and using
1753      one of the instruction's memory alternatives.  Returning false
1754      here will force it to use an input reload instead.  */
1755   if (CONST_INT_P (x) && loongarch_legitimate_constant_p (mode, x))
1756     return true;
1757 
1758   split_const (x, &base, &offset);
1759   if (loongarch_symbolic_constant_p (base, &type))
1760     {
1761       /* The same optimization as for CONST_INT.  */
1762       if (IMM12_INT (offset)
1763 	  && loongarch_symbol_insns (type, MAX_MACHINE_MODE) > 0)
1764 	return true;
1765     }
1766 
1767   /* TLS symbols must be computed by loongarch_legitimize_move.  */
1768   if (tls_referenced_p (x))
1769     return true;
1770 
1771   return false;
1772 }
1773 
1774 /* Return true if register REGNO is a valid base register for mode MODE.
1775    STRICT_P is true if REG_OK_STRICT is in effect.  */
1776 
1777 int
loongarch_regno_mode_ok_for_base_p(int regno,machine_mode mode ATTRIBUTE_UNUSED,bool strict_p)1778 loongarch_regno_mode_ok_for_base_p (int regno,
1779 				    machine_mode mode ATTRIBUTE_UNUSED,
1780 				    bool strict_p)
1781 {
1782   if (!HARD_REGISTER_NUM_P (regno))
1783     {
1784       if (!strict_p)
1785 	return true;
1786       regno = reg_renumber[regno];
1787     }
1788 
1789   /* These fake registers will be eliminated to either the stack or
1790      hard frame pointer, both of which are usually valid base registers.
1791      Reload deals with the cases where the eliminated form isn't valid.  */
1792   if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
1793     return true;
1794 
1795   return GP_REG_P (regno);
1796 }
1797 
1798 /* Return true if X is a valid base register for mode MODE.
1799    STRICT_P is true if REG_OK_STRICT is in effect.  */
1800 
1801 static bool
loongarch_valid_base_register_p(rtx x,machine_mode mode,bool strict_p)1802 loongarch_valid_base_register_p (rtx x, machine_mode mode, bool strict_p)
1803 {
1804   if (!strict_p && SUBREG_P (x))
1805     x = SUBREG_REG (x);
1806 
1807   return (REG_P (x)
1808 	  && loongarch_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p));
1809 }
1810 
1811 /* Return true if, for every base register BASE_REG, (plus BASE_REG X)
1812    can address a value of mode MODE.  */
1813 
1814 static bool
loongarch_valid_offset_p(rtx x,machine_mode mode)1815 loongarch_valid_offset_p (rtx x, machine_mode mode)
1816 {
1817   /* Check that X is a signed 12-bit number,
1818      or check that X is a signed 16-bit number
1819      and offset 4 byte aligned.  */
1820   if (!(const_arith_operand (x, Pmode)
1821 	|| ((mode == E_SImode || mode == E_DImode)
1822 	    && const_imm16_operand (x, Pmode)
1823 	    && (loongarch_signed_immediate_p (INTVAL (x), 14, 2)))))
1824     return false;
1825 
1826   /* We may need to split multiword moves, so make sure that every word
1827      is accessible.  */
1828   if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
1829       && !IMM12_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD))
1830     return false;
1831 
1832   return true;
1833 }
1834 
1835 static bool
loongarch_valid_index_p(struct loongarch_address_info * info,rtx x,machine_mode mode,bool strict_p)1836 loongarch_valid_index_p (struct loongarch_address_info *info, rtx x,
1837 			  machine_mode mode, bool strict_p)
1838 {
1839   rtx index;
1840 
1841   if ((REG_P (x) || SUBREG_P (x))
1842       && GET_MODE (x) == Pmode)
1843     {
1844       index = x;
1845     }
1846   else
1847     return false;
1848 
1849   if (!strict_p
1850       && SUBREG_P (index)
1851       && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))])
1852     index = SUBREG_REG (index);
1853 
1854   if (loongarch_valid_base_register_p (index, mode, strict_p))
1855     {
1856       info->type = ADDRESS_REG_REG;
1857       info->offset = index;
1858       return true;
1859     }
1860 
1861   return false;
1862 }
1863 
1864 /* Return true if X is a valid address for machine mode MODE.  If it is,
1865    fill in INFO appropriately.  STRICT_P is true if REG_OK_STRICT is in
1866    effect.  */
1867 
1868 static bool
loongarch_classify_address(struct loongarch_address_info * info,rtx x,machine_mode mode,bool strict_p)1869 loongarch_classify_address (struct loongarch_address_info *info, rtx x,
1870 			    machine_mode mode, bool strict_p)
1871 {
1872   switch (GET_CODE (x))
1873     {
1874     case REG:
1875     case SUBREG:
1876       info->type = ADDRESS_REG;
1877       info->reg = x;
1878       info->offset = const0_rtx;
1879       return loongarch_valid_base_register_p (info->reg, mode, strict_p);
1880 
1881     case PLUS:
1882       if (loongarch_valid_base_register_p (XEXP (x, 0), mode, strict_p)
1883 	  && loongarch_valid_index_p (info, XEXP (x, 1), mode, strict_p))
1884 	{
1885 	  info->reg = XEXP (x, 0);
1886 	  return true;
1887 	}
1888 
1889       if (loongarch_valid_base_register_p (XEXP (x, 1), mode, strict_p)
1890 	 && loongarch_valid_index_p (info, XEXP (x, 0), mode, strict_p))
1891 	{
1892 	  info->reg = XEXP (x, 1);
1893 	  return true;
1894 	}
1895 
1896       info->type = ADDRESS_REG;
1897       info->reg = XEXP (x, 0);
1898       info->offset = XEXP (x, 1);
1899       return (loongarch_valid_base_register_p (info->reg, mode, strict_p)
1900 	      && loongarch_valid_offset_p (info->offset, mode));
1901     default:
1902       return false;
1903     }
1904 }
1905 
1906 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
1907 
1908 static bool
loongarch_legitimate_address_p(machine_mode mode,rtx x,bool strict_p)1909 loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
1910 {
1911   struct loongarch_address_info addr;
1912 
1913   return loongarch_classify_address (&addr, x, mode, strict_p);
1914 }
1915 
1916 /* Return true if ADDR matches the pattern for the indexed address
1917    instruction.  */
1918 
1919 static bool
loongarch_index_address_p(rtx addr,machine_mode mode ATTRIBUTE_UNUSED)1920 loongarch_index_address_p (rtx addr, machine_mode mode ATTRIBUTE_UNUSED)
1921 {
1922   if (GET_CODE (addr) != PLUS
1923       || !REG_P (XEXP (addr, 0))
1924       || !REG_P (XEXP (addr, 1)))
1925     return false;
1926   return true;
1927 }
1928 
1929 /* Return the number of instructions needed to load or store a value
1930    of mode MODE at address X.  Return 0 if X isn't valid for MODE.
1931    Assume that multiword moves may need to be split into word moves
1932    if MIGHT_SPLIT_P, otherwise assume that a single load or store is
1933    enough.  */
1934 
1935 int
loongarch_address_insns(rtx x,machine_mode mode,bool might_split_p)1936 loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
1937 {
1938   struct loongarch_address_info addr;
1939   int factor;
1940 
1941   if (!loongarch_classify_address (&addr, x, mode, false))
1942     return 0;
1943 
1944   /* BLKmode is used for single unaligned loads and stores and should
1945      not count as a multiword mode.  (GET_MODE_SIZE (BLKmode) is pretty
1946      meaningless, so we have to single it out as a special case one way
1947      or the other.)  */
1948   if (mode != BLKmode && might_split_p)
1949     factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1950   else
1951     factor = 1;
1952 
1953   if (loongarch_classify_address (&addr, x, mode, false))
1954     switch (addr.type)
1955       {
1956       case ADDRESS_REG:
1957 	return factor;
1958 
1959       case ADDRESS_REG_REG:
1960 	return factor;
1961 
1962       case ADDRESS_CONST_INT:
1963 	return factor;
1964 
1965       case ADDRESS_SYMBOLIC:
1966 	return factor * loongarch_symbol_insns (addr.symbol_type, mode);
1967       }
1968   return 0;
1969 }
1970 
1971 /* Return true if X fits within an unsigned field of BITS bits that is
1972    shifted left SHIFT bits before being used.  */
1973 
1974 bool
loongarch_unsigned_immediate_p(unsigned HOST_WIDE_INT x,int bits,int shift=0)1975 loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits,
1976 				int shift = 0)
1977 {
1978   return (x & ((1 << shift) - 1)) == 0 && x < ((unsigned) 1 << (shift + bits));
1979 }
1980 
1981 /* Return true if X fits within a signed field of BITS bits that is
1982    shifted left SHIFT bits before being used.  */
1983 
1984 bool
loongarch_signed_immediate_p(unsigned HOST_WIDE_INT x,int bits,int shift=0)1985 loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits,
1986 			      int shift = 0)
1987 {
1988   x += 1 << (bits + shift - 1);
1989   return loongarch_unsigned_immediate_p (x, bits, shift);
1990 }
1991 
1992 /* Return true if X is a legitimate address with a 12-bit offset.
1993    MODE is the mode of the value being accessed.  */
1994 
1995 bool
loongarch_12bit_offset_address_p(rtx x,machine_mode mode)1996 loongarch_12bit_offset_address_p (rtx x, machine_mode mode)
1997 {
1998   struct loongarch_address_info addr;
1999 
2000   return (loongarch_classify_address (&addr, x, mode, false)
2001 	  && addr.type == ADDRESS_REG
2002 	  && CONST_INT_P (addr.offset)
2003 	  && LARCH_U12BIT_OFFSET_P (INTVAL (addr.offset)));
2004 }
2005 
2006 /* Return true if X is a legitimate address with a 14-bit offset shifted 2.
2007    MODE is the mode of the value being accessed.  */
2008 
2009 bool
loongarch_14bit_shifted_offset_address_p(rtx x,machine_mode mode)2010 loongarch_14bit_shifted_offset_address_p (rtx x, machine_mode mode)
2011 {
2012   struct loongarch_address_info addr;
2013 
2014   return (loongarch_classify_address (&addr, x, mode, false)
2015 	  && addr.type == ADDRESS_REG
2016 	  && CONST_INT_P (addr.offset)
2017 	  && LARCH_16BIT_OFFSET_P (INTVAL (addr.offset))
2018 	  && LARCH_SHIFT_2_OFFSET_P (INTVAL (addr.offset)));
2019 }
2020 
2021 bool
loongarch_base_index_address_p(rtx x,machine_mode mode)2022 loongarch_base_index_address_p (rtx x, machine_mode mode)
2023 {
2024   struct loongarch_address_info addr;
2025 
2026   return (loongarch_classify_address (&addr, x, mode, false)
2027 	  && addr.type == ADDRESS_REG_REG
2028 	  && REG_P (addr.offset));
2029 }
2030 
2031 /* Return the number of instructions needed to load constant X,
2032    Return 0 if X isn't a valid constant.  */
2033 
2034 int
loongarch_const_insns(rtx x)2035 loongarch_const_insns (rtx x)
2036 {
2037   enum loongarch_symbol_type symbol_type;
2038   rtx offset;
2039 
2040   switch (GET_CODE (x))
2041     {
2042     case CONST_INT:
2043       return loongarch_integer_cost (INTVAL (x));
2044 
2045     case CONST_VECTOR:
2046       /* Fall through.  */
2047     case CONST_DOUBLE:
2048       return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0;
2049 
2050     case CONST:
2051       /* See if we can refer to X directly.  */
2052       if (loongarch_symbolic_constant_p (x, &symbol_type))
2053 	return loongarch_symbol_insns (symbol_type, MAX_MACHINE_MODE);
2054 
2055       /* Otherwise try splitting the constant into a base and offset.
2056 	 If the offset is a 12-bit value, we can load the base address
2057 	 into a register and then use ADDI.{W/D} to add in the offset.
2058 	 If the offset is larger, we can load the base and offset
2059 	 into separate registers and add them together with ADD.{W/D}.
2060 	 However, the latter is only possible before reload; during
2061 	 and after reload, we must have the option of forcing the
2062 	 constant into the pool instead.  */
2063       split_const (x, &x, &offset);
2064       if (offset != 0)
2065 	{
2066 	  int n = loongarch_const_insns (x);
2067 	  if (n != 0)
2068 	    {
2069 	      if (IMM12_INT (offset))
2070 		return n + 1;
2071 	      else if (!targetm.cannot_force_const_mem (GET_MODE (x), x))
2072 		return n + 1 + loongarch_integer_cost (INTVAL (offset));
2073 	    }
2074 	}
2075       return 0;
2076 
2077     case SYMBOL_REF:
2078     case LABEL_REF:
2079       return loongarch_symbol_insns (
2080 	loongarch_classify_symbol (x), MAX_MACHINE_MODE);
2081 
2082     default:
2083       return 0;
2084     }
2085 }
2086 
2087 /* X is a doubleword constant that can be handled by splitting it into
2088    two words and loading each word separately.  Return the number of
2089    instructions required to do this.  */
2090 
2091 int
loongarch_split_const_insns(rtx x)2092 loongarch_split_const_insns (rtx x)
2093 {
2094   unsigned int low, high;
2095 
2096   low = loongarch_const_insns (loongarch_subword (x, false));
2097   high = loongarch_const_insns (loongarch_subword (x, true));
2098   gcc_assert (low > 0 && high > 0);
2099   return low + high;
2100 }
2101 
2102 /* Return the number of instructions needed to implement INSN,
2103    given that it loads from or stores to MEM.  */
2104 
2105 int
loongarch_load_store_insns(rtx mem,rtx_insn * insn)2106 loongarch_load_store_insns (rtx mem, rtx_insn *insn)
2107 {
2108   machine_mode mode;
2109   bool might_split_p;
2110   rtx set;
2111 
2112   gcc_assert (MEM_P (mem));
2113   mode = GET_MODE (mem);
2114 
2115   /* Try to prove that INSN does not need to be split.  */
2116   might_split_p = GET_MODE_SIZE (mode) > UNITS_PER_WORD;
2117   if (might_split_p)
2118     {
2119       set = single_set (insn);
2120       if (set
2121 	  && !loongarch_split_move_insn_p (SET_DEST (set), SET_SRC (set)))
2122 	might_split_p = false;
2123     }
2124 
2125   return loongarch_address_insns (XEXP (mem, 0), mode, might_split_p);
2126 }
2127 
2128 /* Return true if we need to trap on division by zero.  */
2129 
2130 static bool
loongarch_check_zero_div_p(void)2131 loongarch_check_zero_div_p (void)
2132 {
2133   /* if -m[no-]check-zero-division is given explicitly.  */
2134   if (target_flags_explicit & MASK_CHECK_ZERO_DIV)
2135     return TARGET_CHECK_ZERO_DIV;
2136 
2137   /* if not, don't trap for optimized code except -Og.  */
2138   return !optimize || optimize_debug;
2139 }
2140 
2141 /* Return the number of instructions needed for an integer division.  */
2142 
2143 int
loongarch_idiv_insns(machine_mode mode ATTRIBUTE_UNUSED)2144 loongarch_idiv_insns (machine_mode mode ATTRIBUTE_UNUSED)
2145 {
2146   int count;
2147 
2148   count = 1;
2149   if (loongarch_check_zero_div_p ())
2150     count += 2;
2151 
2152   return count;
2153 }
2154 
2155 /* Emit an instruction of the form (set TARGET (CODE OP0 OP1)).  */
2156 
2157 void
loongarch_emit_binary(enum rtx_code code,rtx target,rtx op0,rtx op1)2158 loongarch_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
2159 {
2160   emit_insn (gen_rtx_SET (target, gen_rtx_fmt_ee (code, GET_MODE (target),
2161 						  op0, op1)));
2162 }
2163 
2164 /* Compute (CODE OP0 OP1) and store the result in a new register
2165    of mode MODE.  Return that new register.  */
2166 
2167 static rtx
loongarch_force_binary(machine_mode mode,enum rtx_code code,rtx op0,rtx op1)2168 loongarch_force_binary (machine_mode mode, enum rtx_code code, rtx op0,
2169 			rtx op1)
2170 {
2171   rtx reg;
2172 
2173   reg = gen_reg_rtx (mode);
2174   loongarch_emit_binary (code, reg, op0, op1);
2175   return reg;
2176 }
2177 
2178 /* Copy VALUE to a register and return that register.  If new pseudos
2179    are allowed, copy it into a new register, otherwise use DEST.  */
2180 
2181 static rtx
loongarch_force_temporary(rtx dest,rtx value)2182 loongarch_force_temporary (rtx dest, rtx value)
2183 {
2184   if (can_create_pseudo_p ())
2185     return force_reg (Pmode, value);
2186   else
2187     {
2188       loongarch_emit_move (dest, value);
2189       return dest;
2190     }
2191 }
2192 
2193 /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
2194    then add CONST_INT OFFSET to the result.  */
2195 
2196 static rtx
loongarch_unspec_address_offset(rtx base,rtx offset,enum loongarch_symbol_type symbol_type)2197 loongarch_unspec_address_offset (rtx base, rtx offset,
2198 				 enum loongarch_symbol_type symbol_type)
2199 {
2200   base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
2201 			 UNSPEC_ADDRESS_FIRST + symbol_type);
2202   if (offset != const0_rtx)
2203     base = gen_rtx_PLUS (Pmode, base, offset);
2204   return gen_rtx_CONST (Pmode, base);
2205 }
2206 
2207 /* Return an UNSPEC address with underlying address ADDRESS and symbol
2208    type SYMBOL_TYPE.  */
2209 
2210 rtx
loongarch_unspec_address(rtx address,enum loongarch_symbol_type symbol_type)2211 loongarch_unspec_address (rtx address, enum loongarch_symbol_type symbol_type)
2212 {
2213   rtx base, offset;
2214 
2215   split_const (address, &base, &offset);
2216   return loongarch_unspec_address_offset (base, offset, symbol_type);
2217 }
2218 
2219 /* If OP is an UNSPEC address, return the address to which it refers,
2220    otherwise return OP itself.  */
2221 
2222 rtx
loongarch_strip_unspec_address(rtx op)2223 loongarch_strip_unspec_address (rtx op)
2224 {
2225   rtx base, offset;
2226 
2227   split_const (op, &base, &offset);
2228   if (UNSPEC_ADDRESS_P (base))
2229     op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset));
2230   return op;
2231 }
2232 
2233 /* Return a legitimate address for REG + OFFSET.  TEMP is as for
2234    loongarch_force_temporary; it is only needed when OFFSET is not a
2235    IMM12_OPERAND.  */
2236 
2237 static rtx
loongarch_add_offset(rtx temp,rtx reg,HOST_WIDE_INT offset)2238 loongarch_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
2239 {
2240   if (!IMM12_OPERAND (offset))
2241     {
2242       rtx high;
2243 
2244       /* Leave OFFSET as a 12-bit offset and put the excess in HIGH.
2245 	 The addition inside the macro CONST_HIGH_PART may cause an
2246 	 overflow, so we need to force a sign-extension check.  */
2247       high = gen_int_mode (CONST_HIGH_PART (offset), Pmode);
2248       offset = CONST_LOW_PART (offset);
2249       high = loongarch_force_temporary (temp, high);
2250       reg = loongarch_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
2251     }
2252   return plus_constant (Pmode, reg, offset);
2253 }
2254 
2255 /* The __tls_get_attr symbol.  */
2256 static GTY (()) rtx loongarch_tls_symbol;
2257 
2258 /* Load an entry from the GOT for a TLS GD access.  */
2259 
2260 static rtx
loongarch_got_load_tls_gd(rtx dest,rtx sym)2261 loongarch_got_load_tls_gd (rtx dest, rtx sym)
2262 {
2263   return gen_got_load_tls_gd (Pmode, dest, sym);
2264 }
2265 
2266 /* Load an entry from the GOT for a TLS LD access.  */
2267 
2268 static rtx
loongarch_got_load_tls_ld(rtx dest,rtx sym)2269 loongarch_got_load_tls_ld (rtx dest, rtx sym)
2270 {
2271   return gen_got_load_tls_ld (Pmode, dest, sym);
2272 }
2273 
2274 /* Load an entry from the GOT for a TLS IE access.  */
2275 
2276 static rtx
loongarch_got_load_tls_ie(rtx dest,rtx sym)2277 loongarch_got_load_tls_ie (rtx dest, rtx sym)
2278 {
2279   return gen_got_load_tls_ie (Pmode, dest, sym);
2280 }
2281 
2282 /* Add in the thread pointer for a TLS LE access.  */
2283 
2284 static rtx
loongarch_got_load_tls_le(rtx dest,rtx sym)2285 loongarch_got_load_tls_le (rtx dest, rtx sym)
2286 {
2287   return gen_got_load_tls_le (Pmode, dest, sym);
2288 }
2289 
2290 /* Return an instruction sequence that calls __tls_get_addr.  SYM is
2291    the TLS symbol we are referencing and TYPE is the symbol type to use
2292    (either global dynamic or local dynamic).  V0 is an RTX for the
2293    return value location.  */
2294 
2295 static rtx_insn *
loongarch_call_tls_get_addr(rtx sym,enum loongarch_symbol_type type,rtx v0)2296 loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
2297 {
2298   rtx loc, a0;
2299   rtx_insn *insn;
2300 
2301   a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
2302 
2303   if (!loongarch_tls_symbol)
2304     loongarch_tls_symbol = init_one_libfunc ("__tls_get_addr");
2305 
2306   loc = loongarch_unspec_address (sym, type);
2307 
2308   start_sequence ();
2309 
2310   if (type == SYMBOL_TLSLDM)
2311     emit_insn (loongarch_got_load_tls_ld (a0, loc));
2312   else if (type == SYMBOL_TLSGD)
2313     emit_insn (loongarch_got_load_tls_gd (a0, loc));
2314   else
2315     gcc_unreachable ();
2316 
2317   insn = emit_call_insn (gen_call_value_internal (v0, loongarch_tls_symbol,
2318 						  const0_rtx));
2319   RTL_CONST_CALL_P (insn) = 1;
2320   use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
2321   insn = get_insns ();
2322 
2323   end_sequence ();
2324 
2325   return insn;
2326 }
2327 
2328 /* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
2329    its address.  The return value will be both a valid address and a valid
2330    SET_SRC (either a REG or a LO_SUM).  */
2331 
2332 static rtx
loongarch_legitimize_tls_address(rtx loc)2333 loongarch_legitimize_tls_address (rtx loc)
2334 {
2335   rtx dest, tp, tmp;
2336   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
2337   rtx_insn *insn;
2338 
2339   switch (model)
2340     {
2341     case TLS_MODEL_LOCAL_DYNAMIC:
2342       tmp = gen_rtx_REG (Pmode, GP_RETURN);
2343       dest = gen_reg_rtx (Pmode);
2344       insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
2345       emit_libcall_block (insn, dest, tmp, loc);
2346       break;
2347 
2348     case TLS_MODEL_GLOBAL_DYNAMIC:
2349       tmp = gen_rtx_REG (Pmode, GP_RETURN);
2350       dest = gen_reg_rtx (Pmode);
2351       insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
2352       emit_libcall_block (insn, dest, tmp, loc);
2353       break;
2354 
2355     case TLS_MODEL_INITIAL_EXEC:
2356       /* la.tls.ie; tp-relative add  */
2357       tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
2358       tmp = gen_reg_rtx (Pmode);
2359       emit_insn (loongarch_got_load_tls_ie (tmp, loc));
2360       dest = gen_reg_rtx (Pmode);
2361       emit_insn (gen_add3_insn (dest, tmp, tp));
2362       break;
2363 
2364     case TLS_MODEL_LOCAL_EXEC:
2365       /* la.tls.le; tp-relative add  */
2366       tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
2367       tmp = gen_reg_rtx (Pmode);
2368       emit_insn (loongarch_got_load_tls_le (tmp, loc));
2369       dest = gen_reg_rtx (Pmode);
2370       emit_insn (gen_add3_insn (dest, tmp, tp));
2371       break;
2372 
2373     default:
2374       gcc_unreachable ();
2375     }
2376   return dest;
2377 }
2378 
2379 rtx
loongarch_legitimize_call_address(rtx addr)2380 loongarch_legitimize_call_address (rtx addr)
2381 {
2382   if (!call_insn_operand (addr, VOIDmode))
2383     {
2384       rtx reg = gen_reg_rtx (Pmode);
2385       loongarch_emit_move (reg, addr);
2386       return reg;
2387     }
2388   return addr;
2389 }
2390 
2391 /* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR
2392    and *OFFSET_PTR.  Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise.  */
2393 
2394 static void
loongarch_split_plus(rtx x,rtx * base_ptr,HOST_WIDE_INT * offset_ptr)2395 loongarch_split_plus (rtx x, rtx *base_ptr, HOST_WIDE_INT *offset_ptr)
2396 {
2397   if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2398     {
2399       *base_ptr = XEXP (x, 0);
2400       *offset_ptr = INTVAL (XEXP (x, 1));
2401     }
2402   else
2403     {
2404       *base_ptr = x;
2405       *offset_ptr = 0;
2406     }
2407 }
2408 
2409 /* If X is not a valid address for mode MODE, force it into a register.  */
2410 
2411 static rtx
loongarch_force_address(rtx x,machine_mode mode)2412 loongarch_force_address (rtx x, machine_mode mode)
2413 {
2414   if (!loongarch_legitimate_address_p (mode, x, false))
2415     x = force_reg (Pmode, x);
2416   return x;
2417 }
2418 
2419 /* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
2420    be legitimized in a way that the generic machinery might not expect,
2421    return a new address, otherwise return NULL.  MODE is the mode of
2422    the memory being accessed.  */
2423 
2424 static rtx
loongarch_legitimize_address(rtx x,rtx oldx ATTRIBUTE_UNUSED,machine_mode mode)2425 loongarch_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
2426 			      machine_mode mode)
2427 {
2428   rtx base, addr;
2429   HOST_WIDE_INT offset;
2430 
2431   if (loongarch_tls_symbol_p (x))
2432     return loongarch_legitimize_tls_address (x);
2433 
2434   /* Handle BASE + OFFSET using loongarch_add_offset.  */
2435   loongarch_split_plus (x, &base, &offset);
2436   if (offset != 0)
2437     {
2438       if (!loongarch_valid_base_register_p (base, mode, false))
2439 	base = copy_to_mode_reg (Pmode, base);
2440       addr = loongarch_add_offset (NULL, base, offset);
2441       return loongarch_force_address (addr, mode);
2442     }
2443 
2444   return x;
2445 }
2446 
2447 /* Load VALUE into DEST.  TEMP is as for loongarch_force_temporary.  */
2448 
2449 void
loongarch_move_integer(rtx temp,rtx dest,unsigned HOST_WIDE_INT value)2450 loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value)
2451 {
2452   struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS];
2453   machine_mode mode;
2454   unsigned int i, num_ops;
2455   rtx x;
2456 
2457   mode = GET_MODE (dest);
2458   num_ops = loongarch_build_integer (codes, value);
2459 
2460   /* Apply each binary operation to X.  Invariant: X is a legitimate
2461      source operand for a SET pattern.  */
2462   x = GEN_INT (codes[0].value);
2463   for (i = 1; i < num_ops; i++)
2464     {
2465       if (!can_create_pseudo_p ())
2466 	{
2467 	  emit_insn (gen_rtx_SET (temp, x));
2468 	  x = temp;
2469 	}
2470       else
2471 	x = force_reg (mode, x);
2472 
2473       switch (codes[i].method)
2474 	{
2475 	case METHOD_NORMAL:
2476 	  x = gen_rtx_fmt_ee (codes[i].code, mode, x,
2477 			      GEN_INT (codes[i].value));
2478 	  break;
2479 	case METHOD_LU32I:
2480 	  emit_insn (
2481 	    gen_rtx_SET (x,
2482 			 gen_rtx_IOR (DImode,
2483 				      gen_rtx_ZERO_EXTEND (
2484 					DImode, gen_rtx_SUBREG (SImode, x, 0)),
2485 				      GEN_INT (codes[i].value))));
2486 	  break;
2487 	case METHOD_LU52I:
2488 	  emit_insn (gen_lu52i_d (x, x, GEN_INT (0xfffffffffffff),
2489 				  GEN_INT (codes[i].value)));
2490 	  break;
2491 	case METHOD_INSV:
2492 	  emit_insn (
2493 	    gen_rtx_SET (gen_rtx_ZERO_EXTRACT (DImode, x, GEN_INT (20),
2494 					       GEN_INT (32)),
2495 			 gen_rtx_REG (DImode, 0)));
2496 	  break;
2497 	default:
2498 	  gcc_unreachable ();
2499 	}
2500     }
2501 
2502   emit_insn (gen_rtx_SET (dest, x));
2503 }
2504 
2505 /* Subroutine of loongarch_legitimize_move.  Move constant SRC into register
2506    DEST given that SRC satisfies immediate_operand but doesn't satisfy
2507    move_operand.  */
2508 
2509 static void
loongarch_legitimize_const_move(machine_mode mode,rtx dest,rtx src)2510 loongarch_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
2511 {
2512   rtx base, offset;
2513 
2514   /* Split moves of big integers into smaller pieces.  */
2515   if (splittable_const_int_operand (src, mode))
2516     {
2517       loongarch_move_integer (dest, dest, INTVAL (src));
2518       return;
2519     }
2520 
2521   /* Generate the appropriate access sequences for TLS symbols.  */
2522   if (loongarch_tls_symbol_p (src))
2523     {
2524       loongarch_emit_move (dest, loongarch_legitimize_tls_address (src));
2525       return;
2526     }
2527 
2528   /* If we have (const (plus symbol offset)), and that expression cannot
2529      be forced into memory, load the symbol first and add in the offset.
2530      prefer to do this even if the constant _can_ be forced into memory,
2531      as it usually produces better code.  */
2532   split_const (src, &base, &offset);
2533   if (offset != const0_rtx
2534       && (targetm.cannot_force_const_mem (mode, src)
2535 	  || (can_create_pseudo_p ())))
2536     {
2537       base = loongarch_force_temporary (dest, base);
2538       loongarch_emit_move (dest,
2539 			   loongarch_add_offset (NULL, base, INTVAL (offset)));
2540       return;
2541     }
2542 
2543   src = force_const_mem (mode, src);
2544 
2545   loongarch_emit_move (dest, src);
2546 }
2547 
2548 /* If (set DEST SRC) is not a valid move instruction, emit an equivalent
2549    sequence that is valid.  */
2550 
2551 bool
loongarch_legitimize_move(machine_mode mode,rtx dest,rtx src)2552 loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src)
2553 {
2554   if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
2555     {
2556       loongarch_emit_move (dest, force_reg (mode, src));
2557       return true;
2558     }
2559 
2560   /* Both src and dest are non-registers;  one special case is supported where
2561      the source is (const_int 0) and the store can source the zero register.
2562      */
2563   if (!register_operand (dest, mode) && !register_operand (src, mode)
2564       && !const_0_operand (src, mode))
2565     {
2566       loongarch_emit_move (dest, force_reg (mode, src));
2567       return true;
2568     }
2569 
2570   /* We need to deal with constants that would be legitimate
2571      immediate_operands but aren't legitimate move_operands.  */
2572   if (CONSTANT_P (src) && !move_operand (src, mode))
2573     {
2574       loongarch_legitimize_const_move (mode, dest, src);
2575       set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
2576       return true;
2577     }
2578 
2579   return false;
2580 }
2581 
2582 /* Return true if OP refers to small data symbols directly.  */
2583 
2584 static int
loongarch_small_data_pattern_1(rtx x)2585 loongarch_small_data_pattern_1 (rtx x)
2586 {
2587   subrtx_var_iterator::array_type array;
2588   FOR_EACH_SUBRTX_VAR (iter, array, x, ALL)
2589     {
2590       rtx x = *iter;
2591 
2592       /* We make no particular guarantee about which symbolic constants are
2593 	 acceptable as asm operands versus which must be forced into a GPR.  */
2594       if (GET_CODE (x) == ASM_OPERANDS)
2595 	iter.skip_subrtxes ();
2596       else if (MEM_P (x))
2597 	{
2598 	  if (loongarch_small_data_pattern_1 (XEXP (x, 0)))
2599 	    return true;
2600 	  iter.skip_subrtxes ();
2601 	}
2602     }
2603   return false;
2604 }
2605 
2606 /* Return true if OP refers to small data symbols directly.  */
2607 
2608 bool
loongarch_small_data_pattern_p(rtx op)2609 loongarch_small_data_pattern_p (rtx op)
2610 {
2611   return loongarch_small_data_pattern_1 (op);
2612 }
2613 
2614 /* Rewrite *LOC so that it refers to small data using explicit
2615    relocations.  */
2616 
2617 static void
loongarch_rewrite_small_data_1(rtx * loc)2618 loongarch_rewrite_small_data_1 (rtx *loc)
2619 {
2620   subrtx_ptr_iterator::array_type array;
2621   FOR_EACH_SUBRTX_PTR (iter, array, loc, ALL)
2622     {
2623       rtx *loc = *iter;
2624       if (MEM_P (*loc))
2625 	{
2626 	  loongarch_rewrite_small_data_1 (&XEXP (*loc, 0));
2627 	  iter.skip_subrtxes ();
2628 	}
2629     }
2630 }
2631 
2632 /* Rewrite instruction pattern PATTERN so that it refers to small data
2633    using explicit relocations.  */
2634 
2635 rtx
loongarch_rewrite_small_data(rtx pattern)2636 loongarch_rewrite_small_data (rtx pattern)
2637 {
2638   pattern = copy_insn (pattern);
2639   loongarch_rewrite_small_data_1 (&pattern);
2640   return pattern;
2641 }
2642 
2643 /* The cost of loading values from the constant pool.  It should be
2644    larger than the cost of any constant we want to synthesize inline.  */
2645 #define CONSTANT_POOL_COST COSTS_N_INSNS (8)
2646 
2647 /* Return true if there is a instruction that implements CODE
2648    and if that instruction accepts X as an immediate operand.  */
2649 
2650 static int
loongarch_immediate_operand_p(int code,HOST_WIDE_INT x)2651 loongarch_immediate_operand_p (int code, HOST_WIDE_INT x)
2652 {
2653   switch (code)
2654     {
2655     case ASHIFT:
2656     case ASHIFTRT:
2657     case LSHIFTRT:
2658       /* All shift counts are truncated to a valid constant.  */
2659       return true;
2660 
2661     case ROTATE:
2662     case ROTATERT:
2663       return true;
2664 
2665     case AND:
2666     case IOR:
2667     case XOR:
2668       /* These instructions take 12-bit unsigned immediates.  */
2669       return IMM12_OPERAND_UNSIGNED (x);
2670 
2671     case PLUS:
2672     case LT:
2673     case LTU:
2674       /* These instructions take 12-bit signed immediates.  */
2675       return IMM12_OPERAND (x);
2676 
2677     case EQ:
2678     case NE:
2679     case GT:
2680     case GTU:
2681       /* The "immediate" forms of these instructions are really
2682 	 implemented as comparisons with register 0.  */
2683       return x == 0;
2684 
2685     case GE:
2686     case GEU:
2687       /* Likewise, meaning that the only valid immediate operand is 1.  */
2688       return x == 1;
2689 
2690     case LE:
2691       /* We add 1 to the immediate and use SLT.  */
2692       return IMM12_OPERAND (x + 1);
2693 
2694     case LEU:
2695       /* Likewise SLTU, but reject the always-true case.  */
2696       return IMM12_OPERAND (x + 1) && x + 1 != 0;
2697 
2698     case SIGN_EXTRACT:
2699     case ZERO_EXTRACT:
2700       /* The bit position and size are immediate operands.  */
2701       return 1;
2702 
2703     default:
2704       /* By default assume that $0 can be used for 0.  */
2705       return x == 0;
2706     }
2707 }
2708 
2709 /* Return the cost of binary operation X, given that the instruction
2710    sequence for a word-sized or smaller operation has cost SINGLE_COST
2711    and that the sequence of a double-word operation has cost DOUBLE_COST.
2712    If SPEED is true, optimize for speed otherwise optimize for size.  */
2713 
2714 static int
loongarch_binary_cost(rtx x,int single_cost,int double_cost,bool speed)2715 loongarch_binary_cost (rtx x, int single_cost, int double_cost, bool speed)
2716 {
2717   int cost;
2718 
2719   if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2)
2720     cost = double_cost;
2721   else
2722     cost = single_cost;
2723   return (cost
2724 	  + set_src_cost (XEXP (x, 0), GET_MODE (x), speed)
2725 	  + rtx_cost (XEXP (x, 1), GET_MODE (x), GET_CODE (x), 1, speed));
2726 }
2727 
2728 /* Return the cost of floating-point multiplications of mode MODE.  */
2729 
2730 static int
loongarch_fp_mult_cost(machine_mode mode)2731 loongarch_fp_mult_cost (machine_mode mode)
2732 {
2733   return mode == DFmode ? loongarch_cost->fp_mult_df
2734 			: loongarch_cost->fp_mult_sf;
2735 }
2736 
2737 /* Return the cost of floating-point divisions of mode MODE.  */
2738 
2739 static int
loongarch_fp_div_cost(machine_mode mode)2740 loongarch_fp_div_cost (machine_mode mode)
2741 {
2742   return mode == DFmode ? loongarch_cost->fp_div_df
2743 			: loongarch_cost->fp_div_sf;
2744 }
2745 
2746 /* Return the cost of sign-extending OP to mode MODE, not including the
2747    cost of OP itself.  */
2748 
2749 static int
loongarch_sign_extend_cost(rtx op)2750 loongarch_sign_extend_cost (rtx op)
2751 {
2752   if (MEM_P (op))
2753     /* Extended loads are as cheap as unextended ones.  */
2754     return 0;
2755 
2756   return COSTS_N_INSNS (1);
2757 }
2758 
2759 /* Return the cost of zero-extending OP to mode MODE, not including the
2760    cost of OP itself.  */
2761 
2762 static int
loongarch_zero_extend_cost(rtx op)2763 loongarch_zero_extend_cost (rtx op)
2764 {
2765   if (MEM_P (op))
2766     /* Extended loads are as cheap as unextended ones.  */
2767     return 0;
2768 
2769   /* We can use ANDI.  */
2770   return COSTS_N_INSNS (1);
2771 }
2772 
2773 /* Return the cost of moving between two registers of mode MODE,
2774    assuming that the move will be in pieces of at most UNITS bytes.  */
2775 
2776 static int
loongarch_set_reg_reg_piece_cost(machine_mode mode,unsigned int units)2777 loongarch_set_reg_reg_piece_cost (machine_mode mode, unsigned int units)
2778 {
2779   return COSTS_N_INSNS ((GET_MODE_SIZE (mode) + units - 1) / units);
2780 }
2781 
2782 /* Return the cost of moving between two registers of mode MODE.  */
2783 
2784 static int
loongarch_set_reg_reg_cost(machine_mode mode)2785 loongarch_set_reg_reg_cost (machine_mode mode)
2786 {
2787   switch (GET_MODE_CLASS (mode))
2788     {
2789     case MODE_CC:
2790       return loongarch_set_reg_reg_piece_cost (mode, GET_MODE_SIZE (CCmode));
2791 
2792     case MODE_FLOAT:
2793     case MODE_COMPLEX_FLOAT:
2794     case MODE_VECTOR_FLOAT:
2795       if (TARGET_HARD_FLOAT)
2796 	return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_HWFPVALUE);
2797       /* Fall through.  */
2798 
2799     default:
2800       return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_WORD);
2801     }
2802 }
2803 
2804 /* Implement TARGET_RTX_COSTS.  */
2805 
2806 static bool
loongarch_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)2807 loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code,
2808 		     int opno ATTRIBUTE_UNUSED, int *total, bool speed)
2809 {
2810   int code = GET_CODE (x);
2811   bool float_mode_p = FLOAT_MODE_P (mode);
2812   int cost;
2813   rtx addr;
2814 
2815   if (outer_code == COMPARE)
2816     {
2817       gcc_assert (CONSTANT_P (x));
2818       *total = 0;
2819       return true;
2820     }
2821 
2822   switch (code)
2823     {
2824     case CONST_INT:
2825       if (TARGET_64BIT && outer_code == AND && UINTVAL (x) == 0xffffffff)
2826 	{
2827 	  *total = 0;
2828 	  return true;
2829 	}
2830 
2831       /* When not optimizing for size, we care more about the cost
2832 	 of hot code, and hot code is often in a loop.  If a constant
2833 	 operand needs to be forced into a register, we will often be
2834 	 able to hoist the constant load out of the loop, so the load
2835 	 should not contribute to the cost.  */
2836       if (speed || loongarch_immediate_operand_p (outer_code, INTVAL (x)))
2837 	{
2838 	  *total = 0;
2839 	  return true;
2840 	}
2841       /* Fall through.  */
2842 
2843     case CONST:
2844     case SYMBOL_REF:
2845     case LABEL_REF:
2846     case CONST_DOUBLE:
2847       cost = loongarch_const_insns (x);
2848       if (cost > 0)
2849 	{
2850 	  if (cost == 1 && outer_code == SET
2851 	      && !(float_mode_p && TARGET_HARD_FLOAT))
2852 	    cost = 0;
2853 	  else if ((outer_code == SET || GET_MODE (x) == VOIDmode))
2854 	    cost = 1;
2855 	  *total = COSTS_N_INSNS (cost);
2856 	  return true;
2857 	}
2858       /* The value will need to be fetched from the constant pool.  */
2859       *total = CONSTANT_POOL_COST;
2860       return true;
2861 
2862     case MEM:
2863       /* If the address is legitimate, return the number of
2864 	 instructions it needs.  */
2865       addr = XEXP (x, 0);
2866       /* Check for a scaled indexed address.  */
2867       if (loongarch_index_address_p (addr, mode))
2868 	{
2869 	  *total = COSTS_N_INSNS (2);
2870 	  return true;
2871 	}
2872       cost = loongarch_address_insns (addr, mode, true);
2873       if (cost > 0)
2874 	{
2875 	  *total = COSTS_N_INSNS (cost + 1);
2876 	  return true;
2877 	}
2878       /* Otherwise use the default handling.  */
2879       return false;
2880 
2881     case FFS:
2882       *total = COSTS_N_INSNS (6);
2883       return false;
2884 
2885     case NOT:
2886       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
2887       return false;
2888 
2889     case AND:
2890       /* Check for a *clear_upper32 pattern and treat it like a zero
2891 	 extension.  See the pattern's comment for details.  */
2892       if (TARGET_64BIT && mode == DImode && CONST_INT_P (XEXP (x, 1))
2893 	  && UINTVAL (XEXP (x, 1)) == 0xffffffff)
2894 	{
2895 	  *total = (loongarch_zero_extend_cost (XEXP (x, 0))
2896 		    + set_src_cost (XEXP (x, 0), mode, speed));
2897 	  return true;
2898 	}
2899       /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in
2900 	 a single instruction.  */
2901       if (GET_CODE (XEXP (x, 0)) == NOT && GET_CODE (XEXP (x, 1)) == NOT)
2902 	{
2903 	  cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
2904 	  *total = (COSTS_N_INSNS (cost)
2905 		    + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
2906 		    + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed));
2907 	  return true;
2908 	}
2909 
2910       /* Fall through.  */
2911 
2912     case IOR:
2913     case XOR:
2914       /* Double-word operations use two single-word operations.  */
2915       *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (2),
2916 				      speed);
2917       return true;
2918 
2919     case ASHIFT:
2920     case ASHIFTRT:
2921     case LSHIFTRT:
2922     case ROTATE:
2923     case ROTATERT:
2924       if (CONSTANT_P (XEXP (x, 1)))
2925 	*total = loongarch_binary_cost (x, COSTS_N_INSNS (1),
2926 					COSTS_N_INSNS (4), speed);
2927       else
2928 	*total = loongarch_binary_cost (x, COSTS_N_INSNS (1),
2929 					COSTS_N_INSNS (12), speed);
2930       return true;
2931 
2932     case ABS:
2933       if (float_mode_p)
2934 	*total = loongarch_cost->fp_add;
2935       else
2936 	*total = COSTS_N_INSNS (4);
2937       return false;
2938 
2939     case LT:
2940     case LTU:
2941     case LE:
2942     case LEU:
2943     case GT:
2944     case GTU:
2945     case GE:
2946     case GEU:
2947     case EQ:
2948     case NE:
2949     case UNORDERED:
2950     case LTGT:
2951     case UNGE:
2952     case UNGT:
2953     case UNLE:
2954     case UNLT:
2955       /* Branch comparisons have VOIDmode, so use the first operand's
2956 	 mode instead.  */
2957       mode = GET_MODE (XEXP (x, 0));
2958       if (FLOAT_MODE_P (mode))
2959 	{
2960 	  *total = loongarch_cost->fp_add;
2961 	  return false;
2962 	}
2963       *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
2964 				      speed);
2965       return true;
2966 
2967     case MINUS:
2968     case PLUS:
2969       if (float_mode_p)
2970 	{
2971 	  *total = loongarch_cost->fp_add;
2972 	  return false;
2973 	}
2974 
2975       /* If it's an add + mult (which is equivalent to shift left) and
2976 	 it's immediate operand satisfies const_immalsl_operand predicate.  */
2977       if ((mode == SImode || (TARGET_64BIT && mode == DImode))
2978 	  && GET_CODE (XEXP (x, 0)) == MULT)
2979 	{
2980 	  rtx op2 = XEXP (XEXP (x, 0), 1);
2981 	  if (const_immalsl_operand (op2, mode))
2982 	    {
2983 	      *total = (COSTS_N_INSNS (1)
2984 			+ set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
2985 			+ set_src_cost (XEXP (x, 1), mode, speed));
2986 	      return true;
2987 	    }
2988 	}
2989 
2990       /* Double-word operations require three single-word operations and
2991 	 an SLTU.  */
2992       *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
2993 				      speed);
2994       return true;
2995 
2996     case NEG:
2997       if (float_mode_p)
2998 	*total = loongarch_cost->fp_add;
2999       else
3000 	*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
3001       return false;
3002 
3003     case FMA:
3004       *total = loongarch_fp_mult_cost (mode);
3005       return false;
3006 
3007     case MULT:
3008       if (float_mode_p)
3009 	*total = loongarch_fp_mult_cost (mode);
3010       else if (mode == DImode && !TARGET_64BIT)
3011 	*total = (speed
3012 		  ? loongarch_cost->int_mult_si * 3 + 6
3013 		  : COSTS_N_INSNS (7));
3014       else if (!speed)
3015 	*total = COSTS_N_INSNS (1) + 1;
3016       else if (mode == DImode)
3017 	*total = loongarch_cost->int_mult_di;
3018       else
3019 	*total = loongarch_cost->int_mult_si;
3020       return false;
3021 
3022     case DIV:
3023       /* Check for a reciprocal.  */
3024       if (float_mode_p
3025 	  && flag_unsafe_math_optimizations
3026 	  && XEXP (x, 0) == CONST1_RTX (mode))
3027 	{
3028 	  if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT)
3029 	    /* An rsqrt<mode>a or rsqrt<mode>b pattern.  Count the
3030 	       division as being free.  */
3031 	    *total = set_src_cost (XEXP (x, 1), mode, speed);
3032 	  else
3033 	    *total = (loongarch_fp_div_cost (mode)
3034 		      + set_src_cost (XEXP (x, 1), mode, speed));
3035 	  return true;
3036 	}
3037       /* Fall through.  */
3038 
3039     case SQRT:
3040     case MOD:
3041       if (float_mode_p)
3042 	{
3043 	  *total = loongarch_fp_div_cost (mode);
3044 	  return false;
3045 	}
3046       /* Fall through.  */
3047 
3048     case UDIV:
3049     case UMOD:
3050       if (!speed)
3051 	{
3052 	  *total = COSTS_N_INSNS (loongarch_idiv_insns (mode));
3053 	}
3054       else if (mode == DImode)
3055 	*total = loongarch_cost->int_div_di;
3056       else
3057 	*total = loongarch_cost->int_div_si;
3058       return false;
3059 
3060     case SIGN_EXTEND:
3061       *total = loongarch_sign_extend_cost (XEXP (x, 0));
3062       return false;
3063 
3064     case ZERO_EXTEND:
3065       *total = loongarch_zero_extend_cost (XEXP (x, 0));
3066       return false;
3067     case TRUNCATE:
3068       /* Costings for highpart multiplies.  Matching patterns of the form:
3069 
3070 	 (lshiftrt:DI (mult:DI (sign_extend:DI (...)
3071 			       (sign_extend:DI (...))
3072 		      (const_int 32)
3073       */
3074       if ((GET_CODE (XEXP (x, 0)) == ASHIFTRT
3075 	   || GET_CODE (XEXP (x, 0)) == LSHIFTRT)
3076 	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
3077 	  && ((INTVAL (XEXP (XEXP (x, 0), 1)) == 32
3078 	       && GET_MODE (XEXP (x, 0)) == DImode)
3079 	      || (TARGET_64BIT
3080 		  && INTVAL (XEXP (XEXP (x, 0), 1)) == 64
3081 		  && GET_MODE (XEXP (x, 0)) == TImode))
3082 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
3083 	  && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND
3084 	       && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND)
3085 	      || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
3086 		  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1))
3087 		      == ZERO_EXTEND))))
3088 	{
3089 	  if (!speed)
3090 	    *total = COSTS_N_INSNS (1) + 1;
3091 	  else if (mode == DImode)
3092 	    *total = loongarch_cost->int_mult_di;
3093 	  else
3094 	    *total = loongarch_cost->int_mult_si;
3095 
3096 	  /* Sign extension is free, zero extension costs for DImode when
3097 	     on a 64bit core / when DMUL is present.  */
3098 	  for (int i = 0; i < 2; ++i)
3099 	    {
3100 	      rtx op = XEXP (XEXP (XEXP (x, 0), 0), i);
3101 	      if (TARGET_64BIT
3102 		  && GET_CODE (op) == ZERO_EXTEND
3103 		  && GET_MODE (op) == DImode)
3104 		*total += rtx_cost (op, DImode, MULT, i, speed);
3105 	      else
3106 		*total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op), 0,
3107 				    speed);
3108 	    }
3109 
3110 	  return true;
3111 	}
3112       return false;
3113 
3114     case FLOAT:
3115     case UNSIGNED_FLOAT:
3116     case FIX:
3117     case FLOAT_EXTEND:
3118     case FLOAT_TRUNCATE:
3119       *total = loongarch_cost->fp_add;
3120       return false;
3121 
3122     case SET:
3123       if (register_operand (SET_DEST (x), VOIDmode)
3124 	  && reg_or_0_operand (SET_SRC (x), VOIDmode))
3125 	{
3126 	  *total = loongarch_set_reg_reg_cost (GET_MODE (SET_DEST (x)));
3127 	  return true;
3128 	}
3129       return false;
3130 
3131     default:
3132       return false;
3133     }
3134 }
3135 
3136 /* Implement TARGET_ADDRESS_COST.  */
3137 
3138 static int
loongarch_address_cost(rtx addr,machine_mode mode,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)3139 loongarch_address_cost (rtx addr, machine_mode mode,
3140 			addr_space_t as ATTRIBUTE_UNUSED,
3141 			bool speed ATTRIBUTE_UNUSED)
3142 {
3143   return loongarch_address_insns (addr, mode, false);
3144 }
3145 
3146 /* Return one word of double-word value OP, taking into account the fixed
3147    endianness of certain registers.  HIGH_P is true to select the high part,
3148    false to select the low part.  */
3149 
3150 rtx
loongarch_subword(rtx op,bool high_p)3151 loongarch_subword (rtx op, bool high_p)
3152 {
3153   unsigned int byte;
3154   machine_mode mode;
3155 
3156   byte = high_p ? UNITS_PER_WORD : 0;
3157   mode = GET_MODE (op);
3158   if (mode == VOIDmode)
3159     mode = TARGET_64BIT ? TImode : DImode;
3160 
3161   if (FP_REG_RTX_P (op))
3162     return gen_rtx_REG (word_mode, REGNO (op) + high_p);
3163 
3164   if (MEM_P (op))
3165     return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte));
3166 
3167   return simplify_gen_subreg (word_mode, op, mode, byte);
3168 }
3169 
3170 /* Return true if a move from SRC to DEST should be split into two.
3171    SPLIT_TYPE describes the split condition.  */
3172 
3173 bool
loongarch_split_move_p(rtx dest,rtx src)3174 loongarch_split_move_p (rtx dest, rtx src)
3175 {
3176   /* FPR-to-FPR moves can be done in a single instruction, if they're
3177      allowed at all.  */
3178   unsigned int size = GET_MODE_SIZE (GET_MODE (dest));
3179   if (size == 8 && FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
3180     return false;
3181 
3182   /* Check for floating-point loads and stores.  */
3183   if (size == 8)
3184     {
3185       if (FP_REG_RTX_P (dest) && MEM_P (src))
3186 	return false;
3187       if (FP_REG_RTX_P (src) && MEM_P (dest))
3188 	return false;
3189     }
3190   /* Otherwise split all multiword moves.  */
3191   return size > UNITS_PER_WORD;
3192 }
3193 
3194 /* Split a move from SRC to DEST, given that loongarch_split_move_p holds.
3195    SPLIT_TYPE describes the split condition.  */
3196 
3197 void
loongarch_split_move(rtx dest,rtx src,rtx insn_)3198 loongarch_split_move (rtx dest, rtx src, rtx insn_)
3199 {
3200   rtx low_dest;
3201 
3202   gcc_checking_assert (loongarch_split_move_p (dest, src));
3203   if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
3204     {
3205       if (!TARGET_64BIT && GET_MODE (dest) == DImode)
3206 	emit_insn (gen_move_doubleword_fprdi (dest, src));
3207       else if (!TARGET_64BIT && GET_MODE (dest) == DFmode)
3208 	emit_insn (gen_move_doubleword_fprdf (dest, src));
3209       else if (TARGET_64BIT && GET_MODE (dest) == TFmode)
3210 	emit_insn (gen_move_doubleword_fprtf (dest, src));
3211       else
3212 	gcc_unreachable ();
3213     }
3214   else
3215     {
3216       /* The operation can be split into two normal moves.  Decide in
3217 	 which order to do them.  */
3218       low_dest = loongarch_subword (dest, false);
3219       if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src))
3220 	{
3221 	  loongarch_emit_move (loongarch_subword (dest, true),
3222 			       loongarch_subword (src, true));
3223 	  loongarch_emit_move (low_dest, loongarch_subword (src, false));
3224 	}
3225       else
3226 	{
3227 	  loongarch_emit_move (low_dest, loongarch_subword (src, false));
3228 	  loongarch_emit_move (loongarch_subword (dest, true),
3229 			       loongarch_subword (src, true));
3230 	}
3231     }
3232 
3233   /* This is a hack.  See if the next insn uses DEST and if so, see if we
3234      can forward SRC for DEST.  This is most useful if the next insn is a
3235      simple store.  */
3236   rtx_insn *insn = (rtx_insn *) insn_;
3237   struct loongarch_address_info addr = {};
3238   if (insn)
3239     {
3240       rtx_insn *next = next_nonnote_nondebug_insn_bb (insn);
3241       if (next)
3242 	{
3243 	  rtx set = single_set (next);
3244 	  if (set && SET_SRC (set) == dest)
3245 	    {
3246 	      if (MEM_P (src))
3247 		{
3248 		  rtx tmp = XEXP (src, 0);
3249 		  loongarch_classify_address (&addr, tmp, GET_MODE (tmp),
3250 					      true);
3251 		  if (addr.reg && !reg_overlap_mentioned_p (dest, addr.reg))
3252 		    validate_change (next, &SET_SRC (set), src, false);
3253 		}
3254 	      else
3255 		validate_change (next, &SET_SRC (set), src, false);
3256 	    }
3257 	}
3258     }
3259 }
3260 
3261 /* Return true if a move from SRC to DEST in INSN should be split.  */
3262 
3263 bool
loongarch_split_move_insn_p(rtx dest,rtx src)3264 loongarch_split_move_insn_p (rtx dest, rtx src)
3265 {
3266   return loongarch_split_move_p (dest, src);
3267 }
3268 
3269 /* Split a move from SRC to DEST in INSN, given that
3270    loongarch_split_move_insn_p holds.  */
3271 
3272 void
loongarch_split_move_insn(rtx dest,rtx src,rtx insn)3273 loongarch_split_move_insn (rtx dest, rtx src, rtx insn)
3274 {
3275   loongarch_split_move (dest, src, insn);
3276 }
3277 
3278 /* Implement TARGET_CONSTANT_ALIGNMENT.  */
3279 
3280 static HOST_WIDE_INT
loongarch_constant_alignment(const_tree exp,HOST_WIDE_INT align)3281 loongarch_constant_alignment (const_tree exp, HOST_WIDE_INT align)
3282 {
3283   if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR)
3284     return MAX (align, BITS_PER_WORD);
3285   return align;
3286 }
3287 
3288 const char *
loongarch_output_move_index(rtx x,machine_mode mode,bool ldr)3289 loongarch_output_move_index (rtx x, machine_mode mode, bool ldr)
3290 {
3291   int index = exact_log2 (GET_MODE_SIZE (mode));
3292   if (!IN_RANGE (index, 0, 3))
3293     return NULL;
3294 
3295   struct loongarch_address_info info;
3296   if ((loongarch_classify_address (&info, x, mode, false)
3297        && !(info.type == ADDRESS_REG_REG))
3298       || !loongarch_legitimate_address_p (mode, x, false))
3299     return NULL;
3300 
3301   const char *const insn[][4] =
3302     {
3303       {
3304 	"stx.b\t%z1,%0",
3305 	"stx.h\t%z1,%0",
3306 	"stx.w\t%z1,%0",
3307 	"stx.d\t%z1,%0",
3308       },
3309       {
3310 	"ldx.bu\t%0,%1",
3311 	"ldx.hu\t%0,%1",
3312 	"ldx.w\t%0,%1",
3313 	"ldx.d\t%0,%1",
3314       }
3315     };
3316 
3317   return insn[ldr][index];
3318 }
3319 
3320 const char *
loongarch_output_move_index_float(rtx x,machine_mode mode,bool ldr)3321 loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr)
3322 {
3323   int index = exact_log2 (GET_MODE_SIZE (mode));
3324   if (!IN_RANGE (index, 2, 3))
3325     return NULL;
3326 
3327   struct loongarch_address_info info;
3328   if ((loongarch_classify_address (&info, x, mode, false)
3329        && !(info.type == ADDRESS_REG_REG))
3330       || !loongarch_legitimate_address_p (mode, x, false))
3331     return NULL;
3332 
3333   const char *const insn[][2] =
3334     {
3335 	{
3336 	  "fstx.s\t%1,%0",
3337 	  "fstx.d\t%1,%0"
3338 	},
3339 	{
3340 	  "fldx.s\t%0,%1",
3341 	  "fldx.d\t%0,%1"
3342 	},
3343     };
3344 
3345   return insn[ldr][index-2];
3346 }
3347 
3348 /* Return the appropriate instructions to move SRC into DEST.  Assume
3349    that SRC is operand 1 and DEST is operand 0.  */
3350 
3351 const char *
loongarch_output_move(rtx dest,rtx src)3352 loongarch_output_move (rtx dest, rtx src)
3353 {
3354   enum rtx_code dest_code = GET_CODE (dest);
3355   enum rtx_code src_code = GET_CODE (src);
3356   machine_mode mode = GET_MODE (dest);
3357   bool dbl_p = (GET_MODE_SIZE (mode) == 8);
3358 
3359   if (loongarch_split_move_p (dest, src))
3360     return "#";
3361 
3362   if ((src_code == REG && GP_REG_P (REGNO (src)))
3363       || (src == CONST0_RTX (mode)))
3364     {
3365       if (dest_code == REG)
3366 	{
3367 	  if (GP_REG_P (REGNO (dest)))
3368 	    return "or\t%0,%z1,$r0";
3369 
3370 	  if (FP_REG_P (REGNO (dest)))
3371 	    return dbl_p ? "movgr2fr.d\t%0,%z1" : "movgr2fr.w\t%0,%z1";
3372 	}
3373       if (dest_code == MEM)
3374 	{
3375 	  const char *insn = NULL;
3376 	  insn = loongarch_output_move_index (XEXP (dest, 0), GET_MODE (dest),
3377 					      false);
3378 	  if (insn)
3379 	    return insn;
3380 
3381 	  rtx offset = XEXP (dest, 0);
3382 	  if (GET_CODE (offset) == PLUS)
3383 	    offset = XEXP (offset, 1);
3384 	  switch (GET_MODE_SIZE (mode))
3385 	    {
3386 	    case 1:
3387 	      return "st.b\t%z1,%0";
3388 	    case 2:
3389 	      return "st.h\t%z1,%0";
3390 	    case 4:
3391 	      if (const_arith_operand (offset, Pmode))
3392 		return "st.w\t%z1,%0";
3393 	      else
3394 		return "stptr.w\t%z1,%0";
3395 	    case 8:
3396 	      if (const_arith_operand (offset, Pmode))
3397 		return "st.d\t%z1,%0";
3398 	      else
3399 		return "stptr.d\t%z1,%0";
3400 	    default:
3401 	      gcc_unreachable ();
3402 	    }
3403 	}
3404     }
3405   if (dest_code == REG && GP_REG_P (REGNO (dest)))
3406     {
3407       if (src_code == REG)
3408 	if (FP_REG_P (REGNO (src)))
3409 	  return dbl_p ? "movfr2gr.d\t%0,%1" : "movfr2gr.s\t%0,%1";
3410 
3411       if (src_code == MEM)
3412 	{
3413 	  const char *insn = NULL;
3414 	  insn = loongarch_output_move_index (XEXP (src, 0), GET_MODE (src),
3415 					      true);
3416 	  if (insn)
3417 	    return insn;
3418 
3419 	  rtx offset = XEXP (src, 0);
3420 	  if (GET_CODE (offset) == PLUS)
3421 	    offset = XEXP (offset, 1);
3422 	  switch (GET_MODE_SIZE (mode))
3423 	    {
3424 	    case 1:
3425 	      return "ld.bu\t%0,%1";
3426 	    case 2:
3427 	      return "ld.hu\t%0,%1";
3428 	    case 4:
3429 	      if (const_arith_operand (offset, Pmode))
3430 		return "ld.w\t%0,%1";
3431 	      else
3432 		return "ldptr.w\t%0,%1";
3433 	    case 8:
3434 	      if (const_arith_operand (offset, Pmode))
3435 		return "ld.d\t%0,%1";
3436 	      else
3437 		return "ldptr.d\t%0,%1";
3438 	    default:
3439 	      gcc_unreachable ();
3440 	    }
3441 	}
3442 
3443       if (src_code == CONST_INT)
3444 	{
3445 	  if (LU12I_INT (src))
3446 	    return "lu12i.w\t%0,%1>>12\t\t\t# %X1";
3447 	  else if (IMM12_INT (src))
3448 	    return "addi.w\t%0,$r0,%1\t\t\t# %X1";
3449 	  else if (IMM12_INT_UNSIGNED (src))
3450 	    return "ori\t%0,$r0,%1\t\t\t# %X1";
3451 	  else if (LU52I_INT (src))
3452 	    return "lu52i.d\t%0,$r0,%X1>>52\t\t\t# %1";
3453 	  else
3454 	    gcc_unreachable ();
3455 	}
3456 
3457       if (symbolic_operand (src, VOIDmode))
3458 	{
3459 	  if ((TARGET_CMODEL_TINY && (!loongarch_global_symbol_p (src)
3460 				      || loongarch_symbol_binds_local_p (src)))
3461 	      || (TARGET_CMODEL_TINY_STATIC && !loongarch_weak_symbol_p (src)))
3462 	    {
3463 	      /* The symbol must be aligned to 4 byte.  */
3464 	      unsigned int align;
3465 
3466 	      if (LABEL_REF_P (src))
3467 		align = 32 /* Whatever.  */;
3468 	      else if (CONSTANT_POOL_ADDRESS_P (src))
3469 		align = GET_MODE_ALIGNMENT (get_pool_mode (src));
3470 	      else if (TREE_CONSTANT_POOL_ADDRESS_P (src))
3471 		{
3472 		  tree exp = SYMBOL_REF_DECL (src);
3473 		  align = TYPE_ALIGN (TREE_TYPE (exp));
3474 		  align = loongarch_constant_alignment (exp, align);
3475 		}
3476 	      else if (SYMBOL_REF_DECL (src))
3477 		align = DECL_ALIGN (SYMBOL_REF_DECL (src));
3478 	      else if (SYMBOL_REF_HAS_BLOCK_INFO_P (src)
3479 		       && SYMBOL_REF_BLOCK (src) != NULL)
3480 		align = SYMBOL_REF_BLOCK (src)->alignment;
3481 	      else
3482 		align = BITS_PER_UNIT;
3483 
3484 	      if (align % (4 * 8) == 0)
3485 		return "pcaddi\t%0,%%pcrel(%1)>>2";
3486 	    }
3487 	  if (TARGET_CMODEL_TINY
3488 	      || TARGET_CMODEL_TINY_STATIC
3489 	      || TARGET_CMODEL_NORMAL
3490 	      || TARGET_CMODEL_LARGE)
3491 	    {
3492 	      if (!loongarch_global_symbol_p (src)
3493 		  || loongarch_symbol_binds_local_p (src))
3494 		return "la.local\t%0,%1";
3495 	      else
3496 		return "la.global\t%0,%1";
3497 	    }
3498 	  if (TARGET_CMODEL_EXTREME)
3499 	    {
3500 	      sorry ("Normal symbol loading not implemented in extreme mode.");
3501 	      gcc_unreachable ();
3502 	    }
3503 
3504 	}
3505     }
3506   if (src_code == REG && FP_REG_P (REGNO (src)))
3507     {
3508       if (dest_code == REG && FP_REG_P (REGNO (dest)))
3509 	return dbl_p ? "fmov.d\t%0,%1" : "fmov.s\t%0,%1";
3510 
3511       if (dest_code == MEM)
3512 	{
3513 	  const char *insn = NULL;
3514 	  insn = loongarch_output_move_index_float (XEXP (dest, 0),
3515 						    GET_MODE (dest),
3516 						    false);
3517 	  if (insn)
3518 	    return insn;
3519 
3520 	  return dbl_p ? "fst.d\t%1,%0" : "fst.s\t%1,%0";
3521 	}
3522     }
3523   if (dest_code == REG && FP_REG_P (REGNO (dest)))
3524     {
3525       if (src_code == MEM)
3526 	{
3527 	  const char *insn = NULL;
3528 	  insn = loongarch_output_move_index_float (XEXP (src, 0),
3529 						    GET_MODE (src),
3530 						    true);
3531 	  if (insn)
3532 	    return insn;
3533 
3534 	  return dbl_p ? "fld.d\t%0,%1" : "fld.s\t%0,%1";
3535 	}
3536     }
3537   gcc_unreachable ();
3538 }
3539 
3540 /* Return true if CMP1 is a suitable second operand for integer ordering
3541    test CODE.  */
3542 
3543 static bool
loongarch_int_order_operand_ok_p(enum rtx_code code,rtx cmp1)3544 loongarch_int_order_operand_ok_p (enum rtx_code code, rtx cmp1)
3545 {
3546   switch (code)
3547     {
3548     case GT:
3549     case GTU:
3550       return reg_or_0_operand (cmp1, VOIDmode);
3551 
3552     case GE:
3553     case GEU:
3554       return cmp1 == const1_rtx;
3555 
3556     case LT:
3557     case LTU:
3558       return arith_operand (cmp1, VOIDmode);
3559 
3560     case LE:
3561       return sle_operand (cmp1, VOIDmode);
3562 
3563     case LEU:
3564       return sleu_operand (cmp1, VOIDmode);
3565 
3566     default:
3567       gcc_unreachable ();
3568     }
3569 }
3570 
3571 /* Return true if *CMP1 (of mode MODE) is a valid second operand for
3572    integer ordering test *CODE, or if an equivalent combination can
3573    be formed by adjusting *CODE and *CMP1.  When returning true, update
3574    *CODE and *CMP1 with the chosen code and operand, otherwise leave
3575    them alone.  */
3576 
3577 static bool
loongarch_canonicalize_int_order_test(enum rtx_code * code,rtx * cmp1,machine_mode mode)3578 loongarch_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1,
3579 				       machine_mode mode)
3580 {
3581   HOST_WIDE_INT plus_one;
3582 
3583   if (loongarch_int_order_operand_ok_p (*code, *cmp1))
3584     return true;
3585 
3586   if (CONST_INT_P (*cmp1))
3587     switch (*code)
3588       {
3589       case LE:
3590 	plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
3591 	if (INTVAL (*cmp1) < plus_one)
3592 	  {
3593 	    *code = LT;
3594 	    *cmp1 = force_reg (mode, GEN_INT (plus_one));
3595 	    return true;
3596 	  }
3597 	break;
3598 
3599       case LEU:
3600 	plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
3601 	if (plus_one != 0)
3602 	  {
3603 	    *code = LTU;
3604 	    *cmp1 = force_reg (mode, GEN_INT (plus_one));
3605 	    return true;
3606 	  }
3607 	break;
3608 
3609       default:
3610 	break;
3611       }
3612   return false;
3613 }
3614 
3615 /* Compare CMP0 and CMP1 using ordering test CODE and store the result
3616    in TARGET.  CMP0 and TARGET are register_operands.  If INVERT_PTR
3617    is nonnull, it's OK to set TARGET to the inverse of the result and
3618    flip *INVERT_PTR instead.  */
3619 
3620 static void
loongarch_emit_int_order_test(enum rtx_code code,bool * invert_ptr,rtx target,rtx cmp0,rtx cmp1)3621 loongarch_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
3622 			       rtx target, rtx cmp0, rtx cmp1)
3623 {
3624   machine_mode mode;
3625 
3626   /* First see if there is a LoongArch instruction that can do this operation.
3627      If not, try doing the same for the inverse operation.  If that also
3628      fails, force CMP1 into a register and try again.  */
3629   mode = GET_MODE (cmp0);
3630   if (loongarch_canonicalize_int_order_test (&code, &cmp1, mode))
3631     loongarch_emit_binary (code, target, cmp0, cmp1);
3632   else
3633     {
3634       enum rtx_code inv_code = reverse_condition (code);
3635       if (!loongarch_canonicalize_int_order_test (&inv_code, &cmp1, mode))
3636 	{
3637 	  cmp1 = force_reg (mode, cmp1);
3638 	  loongarch_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1);
3639 	}
3640       else if (invert_ptr == 0)
3641 	{
3642 	  rtx inv_target;
3643 
3644 	  inv_target = loongarch_force_binary (GET_MODE (target),
3645 					       inv_code, cmp0, cmp1);
3646 	  loongarch_emit_binary (XOR, target, inv_target, const1_rtx);
3647 	}
3648       else
3649 	{
3650 	  *invert_ptr = !*invert_ptr;
3651 	  loongarch_emit_binary (inv_code, target, cmp0, cmp1);
3652 	}
3653     }
3654 }
3655 
3656 /* Return a register that is zero if CMP0 and CMP1 are equal.
3657    The register will have the same mode as CMP0.  */
3658 
3659 static rtx
loongarch_zero_if_equal(rtx cmp0,rtx cmp1)3660 loongarch_zero_if_equal (rtx cmp0, rtx cmp1)
3661 {
3662   if (cmp1 == const0_rtx)
3663     return cmp0;
3664 
3665   if (uns_arith_operand (cmp1, VOIDmode))
3666     return expand_binop (GET_MODE (cmp0), xor_optab, cmp0, cmp1, 0, 0,
3667 			 OPTAB_DIRECT);
3668 
3669   return expand_binop (GET_MODE (cmp0), sub_optab, cmp0, cmp1, 0, 0,
3670 		       OPTAB_DIRECT);
3671 }
3672 
3673 /* Allocate a floating-point condition-code register of mode MODE.  */
3674 
3675 static rtx
loongarch_allocate_fcc(machine_mode mode)3676 loongarch_allocate_fcc (machine_mode mode)
3677 {
3678   unsigned int regno, count;
3679 
3680   gcc_assert (TARGET_HARD_FLOAT);
3681 
3682   if (mode == FCCmode)
3683     count = 1;
3684   else
3685     gcc_unreachable ();
3686 
3687   cfun->machine->next_fcc += -cfun->machine->next_fcc & (count - 1);
3688   if (cfun->machine->next_fcc > FCC_REG_LAST - FCC_REG_FIRST)
3689     cfun->machine->next_fcc = 0;
3690 
3691   regno = FCC_REG_FIRST + cfun->machine->next_fcc;
3692   cfun->machine->next_fcc += count;
3693   return gen_rtx_REG (mode, regno);
3694 }
3695 
3696 /* Sign- or zero-extend OP0 and OP1 for integer comparisons.  */
3697 
3698 static void
loongarch_extend_comparands(rtx_code code,rtx * op0,rtx * op1)3699 loongarch_extend_comparands (rtx_code code, rtx *op0, rtx *op1)
3700 {
3701   /* Comparisons consider all XLEN bits, so extend sub-XLEN values.  */
3702   if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0)))
3703     {
3704       /* TODO: checkout It is more profitable to zero-extend QImode values.  */
3705       if (unsigned_condition (code) == code && GET_MODE (*op0) == QImode)
3706 	{
3707 	  *op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0);
3708 	  if (CONST_INT_P (*op1))
3709 	    *op1 = GEN_INT ((uint8_t) INTVAL (*op1));
3710 	  else
3711 	    *op1 = gen_rtx_ZERO_EXTEND (word_mode, *op1);
3712 	}
3713       else
3714 	{
3715 	  *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0);
3716 	  if (*op1 != const0_rtx)
3717 	    *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1);
3718 	}
3719     }
3720 }
3721 
3722 /* Convert a comparison into something that can be used in a branch.  On
3723    entry, *OP0 and *OP1 are the values being compared and *CODE is the code
3724    used to compare them.  Update them to describe the final comparison.  */
3725 
3726 static void
loongarch_emit_int_compare(enum rtx_code * code,rtx * op0,rtx * op1)3727 loongarch_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1)
3728 {
3729   static const enum rtx_code
3730   mag_comparisons[][2] = {{LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE}};
3731 
3732   if (splittable_const_int_operand (*op1, VOIDmode))
3733     {
3734       HOST_WIDE_INT rhs = INTVAL (*op1);
3735 
3736       if (*code == EQ || *code == NE)
3737 	{
3738 	  /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0.  */
3739 	  if (IMM12_OPERAND (-rhs))
3740 	    {
3741 	      *op0 = loongarch_force_binary (GET_MODE (*op0), PLUS, *op0,
3742 					     GEN_INT (-rhs));
3743 	      *op1 = const0_rtx;
3744 	    }
3745 	}
3746       else
3747 	{
3748 	  /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000).  */
3749 	  for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++)
3750 	    {
3751 	      HOST_WIDE_INT new_rhs;
3752 	      bool increment = *code == mag_comparisons[i][0];
3753 	      bool decrement = *code == mag_comparisons[i][1];
3754 	      if (!increment && !decrement)
3755 		continue;
3756 
3757 	      new_rhs = rhs + (increment ? 1 : -1);
3758 	      if (loongarch_integer_cost (new_rhs)
3759 		    < loongarch_integer_cost (rhs)
3760 		  && (rhs < 0) == (new_rhs < 0))
3761 		{
3762 		  *op1 = GEN_INT (new_rhs);
3763 		  *code = mag_comparisons[i][increment];
3764 		}
3765 	      break;
3766 	    }
3767 	}
3768     }
3769 
3770   loongarch_extend_comparands (*code, op0, op1);
3771 
3772   *op0 = force_reg (word_mode, *op0);
3773   if (*op1 != const0_rtx)
3774     *op1 = force_reg (word_mode, *op1);
3775 }
3776 
3777 /* Like loongarch_emit_int_compare, but for floating-point comparisons.  */
3778 
3779 static void
loongarch_emit_float_compare(enum rtx_code * code,rtx * op0,rtx * op1)3780 loongarch_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
3781 {
3782   rtx cmp_op0 = *op0;
3783   rtx cmp_op1 = *op1;
3784 
3785   /* Floating-point tests use a separate FCMP.cond.fmt
3786      comparison to set a register.  The branch or conditional move will
3787      then compare that register against zero.
3788 
3789      Set CMP_CODE to the code of the comparison instruction and
3790      *CODE to the code that the branch or move should use.  */
3791   enum rtx_code cmp_code = *code;
3792   /* Three FP conditions cannot be implemented by reversing the
3793      operands for FCMP.cond.fmt, instead a reversed condition code is
3794      required and a test for false.  */
3795   *code = NE;
3796   *op0 = loongarch_allocate_fcc (FCCmode);
3797 
3798   *op1 = const0_rtx;
3799   loongarch_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
3800 }
3801 
3802 /* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
3803    and OPERAND[3].  Store the result in OPERANDS[0].
3804 
3805    On 64-bit targets, the mode of the comparison and target will always be
3806    SImode, thus possibly narrower than that of the comparison's operands.  */
3807 
3808 void
loongarch_expand_scc(rtx operands[])3809 loongarch_expand_scc (rtx operands[])
3810 {
3811   rtx target = operands[0];
3812   enum rtx_code code = GET_CODE (operands[1]);
3813   rtx op0 = operands[2];
3814   rtx op1 = operands[3];
3815 
3816   loongarch_extend_comparands (code, &op0, &op1);
3817   op0 = force_reg (word_mode, op0);
3818 
3819   gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT);
3820 
3821   if (code == EQ || code == NE)
3822     {
3823       rtx zie = loongarch_zero_if_equal (op0, op1);
3824       loongarch_emit_binary (code, target, zie, const0_rtx);
3825     }
3826   else
3827     loongarch_emit_int_order_test (code, 0, target, op0, op1);
3828 }
3829 
3830 /* Compare OPERANDS[1] with OPERANDS[2] using comparison code
3831    CODE and jump to OPERANDS[3] if the condition holds.  */
3832 
3833 void
loongarch_expand_conditional_branch(rtx * operands)3834 loongarch_expand_conditional_branch (rtx *operands)
3835 {
3836   enum rtx_code code = GET_CODE (operands[0]);
3837   rtx op0 = operands[1];
3838   rtx op1 = operands[2];
3839   rtx condition;
3840 
3841   if (FLOAT_MODE_P (GET_MODE (op1)))
3842     loongarch_emit_float_compare (&code, &op0, &op1);
3843   else
3844     loongarch_emit_int_compare (&code, &op0, &op1);
3845 
3846   condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3847   emit_jump_insn (gen_condjump (condition, operands[3]));
3848 }
3849 
3850 /* Perform the comparison in OPERANDS[1].  Move OPERANDS[2] into OPERANDS[0]
3851    if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0].  */
3852 
3853 void
loongarch_expand_conditional_move(rtx * operands)3854 loongarch_expand_conditional_move (rtx *operands)
3855 {
3856   enum rtx_code code = GET_CODE (operands[1]);
3857   rtx op0 = XEXP (operands[1], 0);
3858   rtx op1 = XEXP (operands[1], 1);
3859 
3860   if (FLOAT_MODE_P (GET_MODE (op1)))
3861     loongarch_emit_float_compare (&code, &op0, &op1);
3862   else
3863     {
3864       loongarch_extend_comparands (code, &op0, &op1);
3865 
3866       op0 = force_reg (word_mode, op0);
3867 
3868       if (code == EQ || code == NE)
3869 	{
3870 	  op0 = loongarch_zero_if_equal (op0, op1);
3871 	  op1 = const0_rtx;
3872 	}
3873       else
3874 	{
3875 	  /* The comparison needs a separate scc instruction.  Store the
3876 	     result of the scc in *OP0 and compare it against zero.  */
3877 	  bool invert = false;
3878 	  rtx target = gen_reg_rtx (GET_MODE (op0));
3879 	  loongarch_emit_int_order_test (code, &invert, target, op0, op1);
3880 	  code = invert ? EQ : NE;
3881 	  op0 = target;
3882 	  op1 = const0_rtx;
3883 	}
3884     }
3885 
3886   rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
3887   /* There is no direct support for general conditional GP move involving
3888      two registers using SEL.  */
3889   if (INTEGRAL_MODE_P (GET_MODE (operands[2]))
3890       && register_operand (operands[2], VOIDmode)
3891       && register_operand (operands[3], VOIDmode))
3892     {
3893       machine_mode mode = GET_MODE (operands[0]);
3894       rtx temp = gen_reg_rtx (mode);
3895       rtx temp2 = gen_reg_rtx (mode);
3896 
3897       emit_insn (gen_rtx_SET (temp,
3898 			      gen_rtx_IF_THEN_ELSE (mode, cond,
3899 						    operands[2], const0_rtx)));
3900 
3901       /* Flip the test for the second operand.  */
3902       cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, GET_MODE (op0), op0, op1);
3903 
3904       emit_insn (gen_rtx_SET (temp2,
3905 			      gen_rtx_IF_THEN_ELSE (mode, cond,
3906 						    operands[3], const0_rtx)));
3907 
3908       /* Merge the two results, at least one is guaranteed to be zero.  */
3909       emit_insn (gen_rtx_SET (operands[0], gen_rtx_IOR (mode, temp, temp2)));
3910     }
3911   else
3912     emit_insn (gen_rtx_SET (operands[0],
3913 			    gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond,
3914 						  operands[2], operands[3])));
3915 }
3916 
3917 /* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
3918 
3919 static void
loongarch_va_start(tree valist,rtx nextarg)3920 loongarch_va_start (tree valist, rtx nextarg)
3921 {
3922   nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size);
3923   std_expand_builtin_va_start (valist, nextarg);
3924 }
3925 
3926 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
3927 
3928 static bool
loongarch_function_ok_for_sibcall(tree decl ATTRIBUTE_UNUSED,tree exp ATTRIBUTE_UNUSED)3929 loongarch_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
3930 				   tree exp ATTRIBUTE_UNUSED)
3931 {
3932   /* Always OK.  */
3933   return true;
3934 }
3935 
3936 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
3937    Assume that the areas do not overlap.  */
3938 
3939 static void
loongarch_block_move_straight(rtx dest,rtx src,HOST_WIDE_INT length)3940 loongarch_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
3941 {
3942   HOST_WIDE_INT offset, delta;
3943   unsigned HOST_WIDE_INT bits;
3944   int i;
3945   machine_mode mode;
3946   rtx *regs;
3947 
3948   bits = MIN (BITS_PER_WORD, MIN (MEM_ALIGN (src), MEM_ALIGN (dest)));
3949 
3950   mode = int_mode_for_size (bits, 0).require ();
3951   delta = bits / BITS_PER_UNIT;
3952 
3953   /* Allocate a buffer for the temporary registers.  */
3954   regs = XALLOCAVEC (rtx, length / delta);
3955 
3956   /* Load as many BITS-sized chunks as possible.  Use a normal load if
3957      the source has enough alignment, otherwise use left/right pairs.  */
3958   for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
3959     {
3960       regs[i] = gen_reg_rtx (mode);
3961       loongarch_emit_move (regs[i], adjust_address (src, mode, offset));
3962     }
3963 
3964   for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
3965     loongarch_emit_move (adjust_address (dest, mode, offset), regs[i]);
3966 
3967   /* Mop up any left-over bytes.  */
3968   if (offset < length)
3969     {
3970       src = adjust_address (src, BLKmode, offset);
3971       dest = adjust_address (dest, BLKmode, offset);
3972       move_by_pieces (dest, src, length - offset,
3973 		      MIN (MEM_ALIGN (src), MEM_ALIGN (dest)),
3974 		      (enum memop_ret) 0);
3975     }
3976 }
3977 
3978 /* Helper function for doing a loop-based block operation on memory
3979    reference MEM.  Each iteration of the loop will operate on LENGTH
3980    bytes of MEM.
3981 
3982    Create a new base register for use within the loop and point it to
3983    the start of MEM.  Create a new memory reference that uses this
3984    register.  Store them in *LOOP_REG and *LOOP_MEM respectively.  */
3985 
3986 static void
loongarch_adjust_block_mem(rtx mem,HOST_WIDE_INT length,rtx * loop_reg,rtx * loop_mem)3987 loongarch_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg,
3988 			    rtx *loop_mem)
3989 {
3990   *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
3991 
3992   /* Although the new mem does not refer to a known location,
3993      it does keep up to LENGTH bytes of alignment.  */
3994   *loop_mem = change_address (mem, BLKmode, *loop_reg);
3995   set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
3996 }
3997 
3998 /* Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER
3999    bytes at a time.  LENGTH must be at least BYTES_PER_ITER.  Assume that
4000    the memory regions do not overlap.  */
4001 
4002 static void
loongarch_block_move_loop(rtx dest,rtx src,HOST_WIDE_INT length,HOST_WIDE_INT bytes_per_iter)4003 loongarch_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
4004 			   HOST_WIDE_INT bytes_per_iter)
4005 {
4006   rtx_code_label *label;
4007   rtx src_reg, dest_reg, final_src, test;
4008   HOST_WIDE_INT leftover;
4009 
4010   leftover = length % bytes_per_iter;
4011   length -= leftover;
4012 
4013   /* Create registers and memory references for use within the loop.  */
4014   loongarch_adjust_block_mem (src, bytes_per_iter, &src_reg, &src);
4015   loongarch_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest);
4016 
4017   /* Calculate the value that SRC_REG should have after the last iteration
4018      of the loop.  */
4019   final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), 0,
4020 				   0, OPTAB_WIDEN);
4021 
4022   /* Emit the start of the loop.  */
4023   label = gen_label_rtx ();
4024   emit_label (label);
4025 
4026   /* Emit the loop body.  */
4027   loongarch_block_move_straight (dest, src, bytes_per_iter);
4028 
4029   /* Move on to the next block.  */
4030   loongarch_emit_move (src_reg,
4031 		       plus_constant (Pmode, src_reg, bytes_per_iter));
4032   loongarch_emit_move (dest_reg,
4033 		       plus_constant (Pmode, dest_reg, bytes_per_iter));
4034 
4035   /* Emit the loop condition.  */
4036   test = gen_rtx_NE (VOIDmode, src_reg, final_src);
4037   if (Pmode == DImode)
4038     emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label));
4039   else
4040     emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
4041 
4042   /* Mop up any left-over bytes.  */
4043   if (leftover)
4044     loongarch_block_move_straight (dest, src, leftover);
4045   else
4046     /* Temporary fix for PR79150.  */
4047     emit_insn (gen_nop ());
4048 }
4049 
4050 /* Expand a cpymemsi instruction, which copies LENGTH bytes from
4051    memory reference SRC to memory reference DEST.  */
4052 
4053 bool
loongarch_expand_block_move(rtx dest,rtx src,rtx length)4054 loongarch_expand_block_move (rtx dest, rtx src, rtx length)
4055 {
4056   int max_move_bytes = LARCH_MAX_MOVE_BYTES_STRAIGHT;
4057 
4058   if (CONST_INT_P (length)
4059       && INTVAL (length) <= loongarch_max_inline_memcpy_size)
4060     {
4061       if (INTVAL (length) <= max_move_bytes)
4062 	{
4063 	  loongarch_block_move_straight (dest, src, INTVAL (length));
4064 	  return true;
4065 	}
4066       else if (optimize)
4067 	{
4068 	  loongarch_block_move_loop (dest, src, INTVAL (length),
4069 				     LARCH_MAX_MOVE_BYTES_PER_LOOP_ITER);
4070 	  return true;
4071 	}
4072     }
4073   return false;
4074 }
4075 
4076 /* Return true if loongarch_expand_block_move is the preferred
4077    implementation of the 'cpymemsi' template.  */
4078 
4079 bool
loongarch_do_optimize_block_move_p(void)4080 loongarch_do_optimize_block_move_p (void)
4081 {
4082   /* if -m[no-]memcpy is given explicitly.  */
4083   if (target_flags_explicit & MASK_MEMCPY)
4084     return !TARGET_MEMCPY;
4085 
4086   /* if not, don't optimize under -Os.  */
4087   return !optimize_size;
4088 }
4089 
4090 /* Expand a QI or HI mode atomic memory operation.
4091 
4092    GENERATOR contains a pointer to the gen_* function that generates
4093    the SI mode underlying atomic operation using masks that we
4094    calculate.
4095 
4096    RESULT is the return register for the operation.  Its value is NULL
4097    if unused.
4098 
4099    MEM is the location of the atomic access.
4100 
4101    OLDVAL is the first operand for the operation.
4102 
4103    NEWVAL is the optional second operand for the operation.  Its value
4104    is NULL if unused.  */
4105 
4106 void
loongarch_expand_atomic_qihi(union loongarch_gen_fn_ptrs generator,rtx result,rtx mem,rtx oldval,rtx newval,rtx model)4107 loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs generator,
4108 			      rtx result, rtx mem, rtx oldval, rtx newval,
4109 			      rtx model)
4110 {
4111   rtx orig_addr, memsi_addr, memsi, shift, shiftsi, unshifted_mask;
4112   rtx unshifted_mask_reg, mask, inverted_mask, si_op;
4113   rtx res = NULL;
4114   machine_mode mode;
4115 
4116   mode = GET_MODE (mem);
4117 
4118   /* Compute the address of the containing SImode value.  */
4119   orig_addr = force_reg (Pmode, XEXP (mem, 0));
4120   memsi_addr = loongarch_force_binary (Pmode, AND, orig_addr,
4121 				       force_reg (Pmode, GEN_INT (-4)));
4122 
4123   /* Create a memory reference for it.  */
4124   memsi = gen_rtx_MEM (SImode, memsi_addr);
4125   set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
4126   MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
4127 
4128   /* Work out the byte offset of the QImode or HImode value,
4129      counting from the least significant byte.  */
4130   shift = loongarch_force_binary (Pmode, AND, orig_addr, GEN_INT (3));
4131   /* Multiply by eight to convert the shift value from bytes to bits.  */
4132   loongarch_emit_binary (ASHIFT, shift, shift, GEN_INT (3));
4133 
4134   /* Make the final shift an SImode value, so that it can be used in
4135      SImode operations.  */
4136   shiftsi = force_reg (SImode, gen_lowpart (SImode, shift));
4137 
4138   /* Set MASK to an inclusive mask of the QImode or HImode value.  */
4139   unshifted_mask = GEN_INT (GET_MODE_MASK (mode));
4140   unshifted_mask_reg = force_reg (SImode, unshifted_mask);
4141   mask = loongarch_force_binary (SImode, ASHIFT, unshifted_mask_reg, shiftsi);
4142 
4143   /* Compute the equivalent exclusive mask.  */
4144   inverted_mask = gen_reg_rtx (SImode);
4145   emit_insn (gen_rtx_SET (inverted_mask, gen_rtx_NOT (SImode, mask)));
4146 
4147   /* Shift the old value into place.  */
4148   if (oldval != const0_rtx)
4149     {
4150       oldval = convert_modes (SImode, mode, oldval, true);
4151       oldval = force_reg (SImode, oldval);
4152       oldval = loongarch_force_binary (SImode, ASHIFT, oldval, shiftsi);
4153     }
4154 
4155   /* Do the same for the new value.  */
4156   if (newval && newval != const0_rtx)
4157     {
4158       newval = convert_modes (SImode, mode, newval, true);
4159       newval = force_reg (SImode, newval);
4160       newval = loongarch_force_binary (SImode, ASHIFT, newval, shiftsi);
4161     }
4162 
4163   /* Do the SImode atomic access.  */
4164   if (result)
4165     res = gen_reg_rtx (SImode);
4166 
4167   if (newval)
4168     si_op = generator.fn_7 (res, memsi, mask, inverted_mask, oldval, newval,
4169 			    model);
4170   else if (result)
4171     si_op = generator.fn_6 (res, memsi, mask, inverted_mask, oldval, model);
4172   else
4173     si_op = generator.fn_5 (memsi, mask, inverted_mask, oldval, model);
4174 
4175   emit_insn (si_op);
4176 
4177   if (result)
4178     {
4179       /* Shift and convert the result.  */
4180       loongarch_emit_binary (AND, res, res, mask);
4181       loongarch_emit_binary (LSHIFTRT, res, res, shiftsi);
4182       loongarch_emit_move (result, gen_lowpart (GET_MODE (result), res));
4183     }
4184 }
4185 
4186 /* Return true if (zero_extract OP WIDTH BITPOS) can be used as the
4187    source of an "ext" instruction or the destination of an "ins"
4188    instruction.  OP must be a register operand and the following
4189    conditions must hold:
4190 
4191    0 <= BITPOS < GET_MODE_BITSIZE (GET_MODE (op))
4192    0 < WIDTH <= GET_MODE_BITSIZE (GET_MODE (op))
4193    0 < BITPOS + WIDTH <= GET_MODE_BITSIZE (GET_MODE (op))
4194 
4195    Also reject lengths equal to a word as they are better handled
4196    by the move patterns.  */
4197 
4198 bool
loongarch_use_ins_ext_p(rtx op,HOST_WIDE_INT width,HOST_WIDE_INT bitpos)4199 loongarch_use_ins_ext_p (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos)
4200 {
4201   if (!register_operand (op, VOIDmode)
4202       || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
4203     return false;
4204 
4205   if (!IN_RANGE (width, 1, GET_MODE_BITSIZE (GET_MODE (op)) - 1))
4206     return false;
4207 
4208   if (bitpos < 0 || bitpos + width > GET_MODE_BITSIZE (GET_MODE (op)))
4209     return false;
4210 
4211   return true;
4212 }
4213 
4214 /* Print the text for PRINT_OPERAND punctation character CH to FILE.
4215    The punctuation characters are:
4216 
4217    '.'	Print the name of the register with a hard-wired zero (zero or $r0).
4218    '$'	Print the name of the stack pointer register (sp or $r3).
4219 
4220    See also loongarch_init_print_operand_punct.  */
4221 
4222 static void
loongarch_print_operand_punctuation(FILE * file,int ch)4223 loongarch_print_operand_punctuation (FILE *file, int ch)
4224 {
4225   switch (ch)
4226     {
4227     case '.':
4228       fputs (reg_names[GP_REG_FIRST + 0], file);
4229       break;
4230 
4231     case '$':
4232       fputs (reg_names[STACK_POINTER_REGNUM], file);
4233       break;
4234 
4235     default:
4236       gcc_unreachable ();
4237       break;
4238     }
4239 }
4240 
4241 /* Initialize loongarch_print_operand_punct.  */
4242 
4243 static void
loongarch_init_print_operand_punct(void)4244 loongarch_init_print_operand_punct (void)
4245 {
4246   const char *p;
4247 
4248   for (p = ".$"; *p; p++)
4249     loongarch_print_operand_punct[(unsigned char) *p] = true;
4250 }
4251 
4252 /* PRINT_OPERAND prefix LETTER refers to the integer branch instruction
4253    associated with condition CODE.  Print the condition part of the
4254    opcode to FILE.  */
4255 
4256 static void
loongarch_print_int_branch_condition(FILE * file,enum rtx_code code,int letter)4257 loongarch_print_int_branch_condition (FILE *file, enum rtx_code code,
4258 				      int letter)
4259 {
4260   switch (code)
4261     {
4262     case EQ:
4263     case NE:
4264     case GT:
4265     case GE:
4266     case LT:
4267     case LE:
4268     case GTU:
4269     case GEU:
4270     case LTU:
4271     case LEU:
4272       /* Conveniently, the LoongArch names for these conditions are the same
4273 	 as their RTL equivalents.  */
4274       fputs (GET_RTX_NAME (code), file);
4275       break;
4276 
4277     default:
4278       output_operand_lossage ("'%%%c' is not a valid operand prefix", letter);
4279       break;
4280     }
4281 }
4282 
4283 /* Likewise floating-point branches.  */
4284 
4285 static void
loongarch_print_float_branch_condition(FILE * file,enum rtx_code code,int letter)4286 loongarch_print_float_branch_condition (FILE *file, enum rtx_code code,
4287 					int letter)
4288 {
4289   switch (code)
4290     {
4291     case EQ:
4292       fputs ("ceqz", file);
4293       break;
4294 
4295     case NE:
4296       fputs ("cnez", file);
4297       break;
4298 
4299     default:
4300       output_operand_lossage ("'%%%c' is not a valid operand prefix", letter);
4301       break;
4302     }
4303 }
4304 
4305 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P.  */
4306 
4307 static bool
loongarch_print_operand_punct_valid_p(unsigned char code)4308 loongarch_print_operand_punct_valid_p (unsigned char code)
4309 {
4310   return loongarch_print_operand_punct[code];
4311 }
4312 
4313 /* Return true if a FENCE should be emitted to before a memory access to
4314    implement the release portion of memory model MODEL.  */
4315 
4316 static bool
loongarch_memmodel_needs_rel_acq_fence(enum memmodel model)4317 loongarch_memmodel_needs_rel_acq_fence (enum memmodel model)
4318 {
4319   switch (model)
4320     {
4321       case MEMMODEL_ACQ_REL:
4322       case MEMMODEL_SEQ_CST:
4323       case MEMMODEL_SYNC_SEQ_CST:
4324       case MEMMODEL_RELEASE:
4325       case MEMMODEL_SYNC_RELEASE:
4326       case MEMMODEL_ACQUIRE:
4327       case MEMMODEL_CONSUME:
4328       case MEMMODEL_SYNC_ACQUIRE:
4329 	return true;
4330 
4331       case MEMMODEL_RELAXED:
4332 	return false;
4333 
4334       default:
4335 	gcc_unreachable ();
4336     }
4337 }
4338 
4339 /* Return true if a FENCE should be emitted after a failed CAS to
4340    implement the acquire semantic of failure_memorder.  */
4341 
4342 static bool
loongarch_cas_failure_memorder_needs_acquire(enum memmodel model)4343 loongarch_cas_failure_memorder_needs_acquire (enum memmodel model)
4344 {
4345   switch (memmodel_base (model))
4346     {
4347     case MEMMODEL_ACQUIRE:
4348     case MEMMODEL_ACQ_REL:
4349     case MEMMODEL_SEQ_CST:
4350       return true;
4351 
4352     case MEMMODEL_RELAXED:
4353     case MEMMODEL_RELEASE:
4354       return false;
4355 
4356     /* MEMMODEL_CONSUME is deliberately not handled because it's always
4357        replaced by MEMMODEL_ACQUIRE as at now.  If you see an ICE caused by
4358        MEMMODEL_CONSUME, read the change (re)introducing it carefully and
4359        decide what to do.  See PR 59448 and get_memmodel in builtins.cc.  */
4360     default:
4361       gcc_unreachable ();
4362     }
4363 }
4364 
4365 /* Implement TARGET_PRINT_OPERAND.  The LoongArch-specific operand codes are:
4366 
4367    'X'	Print CONST_INT OP in hexadecimal format.
4368    'x'	Print the low 16 bits of CONST_INT OP in hexadecimal format.
4369    'd'	Print CONST_INT OP in decimal.
4370    'm'	Print one less than CONST_INT OP in decimal.
4371    'y'	Print exact log2 of CONST_INT OP in decimal.
4372    'C'	Print the integer branch condition for comparison OP.
4373    'N'	Print the inverse of the integer branch condition for comparison OP.
4374    'F'	Print the FPU branch condition for comparison OP.
4375    'W'	Print the inverse of the FPU branch condition for comparison OP.
4376    'T'	Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
4377 	      'z' for (eq:?I ...), 'n' for (ne:?I ...).
4378    't'	Like 'T', but with the EQ/NE cases reversed
4379    'Y'	Print loongarch_fp_conditions[INTVAL (OP)]
4380    'Z'	Print OP and a comma for 8CC, otherwise print nothing.
4381    'z'	Print $0 if OP is zero, otherwise print OP normally.
4382    'b'	Print the address of a memory operand, without offset.
4383    'V'	Print exact log2 of CONST_INT OP element 0 of a replicated
4384 	  CONST_VECTOR in decimal.
4385    'A'	Print a _DB suffix if the memory model requires a release.
4386    'G'	Print a DBAR insn for CAS failure (with an acquire semantic if
4387 	needed, otherwise a simple load-load barrier).
4388    'i'	Print i if the operand is not a register.  */
4389 
4390 static void
loongarch_print_operand(FILE * file,rtx op,int letter)4391 loongarch_print_operand (FILE *file, rtx op, int letter)
4392 {
4393   enum rtx_code code;
4394 
4395   if (loongarch_print_operand_punct_valid_p (letter))
4396     {
4397       loongarch_print_operand_punctuation (file, letter);
4398       return;
4399     }
4400 
4401   gcc_assert (op);
4402   code = GET_CODE (op);
4403 
4404   switch (letter)
4405     {
4406     case 'X':
4407       if (CONST_INT_P (op))
4408 	fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
4409       else
4410 	output_operand_lossage ("invalid use of '%%%c'", letter);
4411       break;
4412 
4413     case 'x':
4414       if (CONST_INT_P (op))
4415 	fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff);
4416       else
4417 	output_operand_lossage ("invalid use of '%%%c'", letter);
4418       break;
4419 
4420     case 'd':
4421       if (CONST_INT_P (op))
4422 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
4423       else
4424 	output_operand_lossage ("invalid use of '%%%c'", letter);
4425       break;
4426 
4427     case 'm':
4428       if (CONST_INT_P (op))
4429 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1);
4430       else
4431 	output_operand_lossage ("invalid use of '%%%c'", letter);
4432       break;
4433 
4434     case 'y':
4435       if (CONST_INT_P (op))
4436 	{
4437 	  int val = exact_log2 (INTVAL (op));
4438 	  if (val != -1)
4439 	    fprintf (file, "%d", val);
4440 	  else
4441 	    output_operand_lossage ("invalid use of '%%%c'", letter);
4442 	}
4443       else
4444 	output_operand_lossage ("invalid use of '%%%c'", letter);
4445       break;
4446 
4447     case 'V':
4448       if (CONST_VECTOR_P (op))
4449 	{
4450 	  machine_mode mode = GET_MODE_INNER (GET_MODE (op));
4451 	  unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0));
4452 	  int vlog2 = exact_log2 (val & GET_MODE_MASK (mode));
4453 	  if (vlog2 != -1)
4454 	    fprintf (file, "%d", vlog2);
4455 	  else
4456 	    output_operand_lossage ("invalid use of '%%%c'", letter);
4457 	}
4458       else
4459 	output_operand_lossage ("invalid use of '%%%c'", letter);
4460       break;
4461 
4462     case 'C':
4463       loongarch_print_int_branch_condition (file, code, letter);
4464       break;
4465 
4466     case 'N':
4467       loongarch_print_int_branch_condition (file, reverse_condition (code),
4468 					    letter);
4469       break;
4470 
4471     case 'F':
4472       loongarch_print_float_branch_condition (file, code, letter);
4473       break;
4474 
4475     case 'W':
4476       loongarch_print_float_branch_condition (file, reverse_condition (code),
4477 					      letter);
4478       break;
4479 
4480     case 'T':
4481     case 't':
4482       {
4483 	int truth = (code == NE) == (letter == 'T');
4484 	fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file);
4485       }
4486       break;
4487 
4488     case 'Y':
4489       if (code == CONST_INT
4490 	  && UINTVAL (op) < ARRAY_SIZE (loongarch_fp_conditions))
4491 	fputs (loongarch_fp_conditions[UINTVAL (op)], file);
4492       else
4493 	output_operand_lossage ("'%%%c' is not a valid operand prefix",
4494 				letter);
4495       break;
4496 
4497     case 'Z':
4498       loongarch_print_operand (file, op, 0);
4499       fputc (',', file);
4500       break;
4501 
4502     case 'A':
4503       if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op)))
4504 	fputs ("_db", file);
4505       break;
4506 
4507     case 'G':
4508       if (loongarch_cas_failure_memorder_needs_acquire (
4509 	    memmodel_from_int (INTVAL (op))))
4510 	fputs ("dbar\t0b10100", file);
4511       else
4512 	fputs ("dbar\t0x700", file);
4513       break;
4514 
4515     case 'i':
4516       if (code != REG)
4517 	fputs ("i", file);
4518       break;
4519 
4520     default:
4521       switch (code)
4522 	{
4523 	case REG:
4524 	  {
4525 	    unsigned int regno = REGNO (op);
4526 	    if (letter && letter != 'z')
4527 	      output_operand_lossage ("invalid use of '%%%c'", letter);
4528 	    fprintf (file, "%s", reg_names[regno]);
4529 	  }
4530 	  break;
4531 
4532 	case MEM:
4533 	  if (letter == 'D')
4534 	    output_address (GET_MODE (op),
4535 			    plus_constant (Pmode, XEXP (op, 0), 4));
4536 	  else if (letter == 'b')
4537 	    {
4538 	      gcc_assert (REG_P (XEXP (op, 0)));
4539 	      loongarch_print_operand (file, XEXP (op, 0), 0);
4540 	    }
4541 	  else if (letter && letter != 'z')
4542 	    output_operand_lossage ("invalid use of '%%%c'", letter);
4543 	  else
4544 	    output_address (GET_MODE (op), XEXP (op, 0));
4545 	  break;
4546 
4547 	default:
4548 	  if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
4549 	    fputs (reg_names[GP_REG_FIRST], file);
4550 	  else if (letter && letter != 'z')
4551 	    output_operand_lossage ("invalid use of '%%%c'", letter);
4552 	  else
4553 	    output_addr_const (file, loongarch_strip_unspec_address (op));
4554 	  break;
4555 	}
4556     }
4557 }
4558 
4559 /* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
4560 
4561 static void
loongarch_print_operand_address(FILE * file,machine_mode,rtx x)4562 loongarch_print_operand_address (FILE *file, machine_mode /* mode  */, rtx x)
4563 {
4564   struct loongarch_address_info addr;
4565 
4566   if (loongarch_classify_address (&addr, x, word_mode, true))
4567     switch (addr.type)
4568       {
4569       case ADDRESS_REG:
4570 	fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
4571 	loongarch_print_operand (file, addr.offset, 0);
4572 	return;
4573 
4574       case ADDRESS_REG_REG:
4575 	fprintf (file, "%s,%s", reg_names[REGNO (addr.reg)],
4576 				reg_names[REGNO (addr.offset)]);
4577 	return;
4578 
4579       case ADDRESS_CONST_INT:
4580 	fprintf (file, "%s,", reg_names[GP_REG_FIRST]);
4581 	output_addr_const (file, x);
4582 	return;
4583 
4584       case ADDRESS_SYMBOLIC:
4585 	output_addr_const (file, loongarch_strip_unspec_address (x));
4586 	return;
4587       }
4588   if (CONST_INT_P (x))
4589     output_addr_const (file, x);
4590   else
4591     gcc_unreachable ();
4592 }
4593 
4594 /* Implement TARGET_ASM_SELECT_RTX_SECTION.  */
4595 
4596 static section *
loongarch_select_rtx_section(machine_mode mode,rtx x,unsigned HOST_WIDE_INT align)4597 loongarch_select_rtx_section (machine_mode mode, rtx x,
4598 			      unsigned HOST_WIDE_INT align)
4599 {
4600   /* ??? Consider using mergeable small data sections.  */
4601   if (loongarch_rtx_constant_in_small_data_p (mode))
4602     return get_named_section (NULL, ".sdata", 0);
4603 
4604   return default_elf_select_rtx_section (mode, x, align);
4605 }
4606 
4607 /* Implement TARGET_ASM_FUNCTION_RODATA_SECTION.
4608 
4609    The complication here is that jump tables will use absolute addresses,
4610    and should therefore not be included in the read-only part of a DSO.
4611    Handle such cases by selecting a normal data section instead of a
4612    read-only one.  The logic apes that in default_function_rodata_section.  */
4613 
4614 static section *
loongarch_function_rodata_section(tree decl,bool)4615 loongarch_function_rodata_section (tree decl, bool)
4616 {
4617   return default_function_rodata_section (decl, false);
4618 }
4619 
4620 /* Implement TARGET_IN_SMALL_DATA_P.  */
4621 
4622 static bool
loongarch_in_small_data_p(const_tree decl)4623 loongarch_in_small_data_p (const_tree decl)
4624 {
4625   int size;
4626 
4627   if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
4628     return false;
4629 
4630   if (VAR_P (decl) && DECL_SECTION_NAME (decl) != 0)
4631     {
4632       const char *name;
4633 
4634       /* Reject anything that isn't in a known small-data section.  */
4635       name = DECL_SECTION_NAME (decl);
4636       if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
4637 	return false;
4638 
4639       /* If a symbol is defined externally, the assembler will use the
4640 	 usual -G rules when deciding how to implement macros.  */
4641       if (!DECL_EXTERNAL (decl))
4642 	return true;
4643     }
4644 
4645   /* We have traditionally not treated zero-sized objects as small data,
4646      so this is now effectively part of the ABI.  */
4647   size = int_size_in_bytes (TREE_TYPE (decl));
4648   return size > 0 && size <= g_switch_value;
4649 }
4650 
4651 /* The LoongArch debug format wants all automatic variables and arguments
4652    to be in terms of the virtual frame pointer (stack pointer before
4653    any adjustment in the function), while the LoongArch linker wants
4654    the frame pointer to be the stack pointer after the initial
4655    adjustment.  So, we do the adjustment here.  The arg pointer (which
4656    is eliminated) points to the virtual frame pointer, while the frame
4657    pointer (which may be eliminated) points to the stack pointer after
4658    the initial adjustments.  */
4659 
4660 HOST_WIDE_INT
loongarch_debugger_offset(rtx addr,HOST_WIDE_INT offset)4661 loongarch_debugger_offset (rtx addr, HOST_WIDE_INT offset)
4662 {
4663   rtx offset2 = const0_rtx;
4664   rtx reg = eliminate_constant_term (addr, &offset2);
4665 
4666   if (offset == 0)
4667     offset = INTVAL (offset2);
4668 
4669   if (reg == stack_pointer_rtx
4670       || reg == frame_pointer_rtx
4671       || reg == hard_frame_pointer_rtx)
4672     {
4673       offset -= cfun->machine->frame.total_size;
4674       if (reg == hard_frame_pointer_rtx)
4675 	offset += cfun->machine->frame.hard_frame_pointer_offset;
4676     }
4677 
4678   return offset;
4679 }
4680 
4681 /* Implement ASM_OUTPUT_EXTERNAL.  */
4682 
4683 void
loongarch_output_external(FILE * file,tree decl,const char * name)4684 loongarch_output_external (FILE *file, tree decl, const char *name)
4685 {
4686   default_elf_asm_output_external (file, decl, name);
4687 
4688   /* We output the name if and only if TREE_SYMBOL_REFERENCED is
4689      set in order to avoid putting out names that are never really
4690      used.  */
4691   if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
4692     {
4693       if (loongarch_in_small_data_p (decl))
4694 	{
4695 	  /* When using assembler macros, emit .extern directives for
4696 	     all small-data externs so that the assembler knows how
4697 	     big they are.
4698 
4699 	     In most cases it would be safe (though pointless) to emit
4700 	     .externs for other symbols too.  One exception is when an
4701 	     object is within the -G limit but declared by the user to
4702 	     be in a section other than .sbss or .sdata.  */
4703 	  fputs ("\t.extern\t", file);
4704 	  assemble_name (file, name);
4705 	  fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC "\n",
4706 		   int_size_in_bytes (TREE_TYPE (decl)));
4707 	}
4708     }
4709 }
4710 
4711 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL.  */
4712 
4713 static void ATTRIBUTE_UNUSED
loongarch_output_dwarf_dtprel(FILE * file,int size,rtx x)4714 loongarch_output_dwarf_dtprel (FILE *file, int size, rtx x)
4715 {
4716   switch (size)
4717     {
4718     case 4:
4719       fputs ("\t.dtprelword\t", file);
4720       break;
4721 
4722     case 8:
4723       fputs ("\t.dtpreldword\t", file);
4724       break;
4725 
4726     default:
4727       gcc_unreachable ();
4728     }
4729   output_addr_const (file, x);
4730   fputs ("+0x8000", file);
4731 }
4732 
4733 /* Implement ASM_OUTPUT_ASCII.  */
4734 
4735 void
loongarch_output_ascii(FILE * stream,const char * string,size_t len)4736 loongarch_output_ascii (FILE *stream, const char *string, size_t len)
4737 {
4738   size_t i;
4739   int cur_pos;
4740 
4741   cur_pos = 17;
4742   fprintf (stream, "\t.ascii\t\"");
4743   for (i = 0; i < len; i++)
4744     {
4745       int c;
4746 
4747       c = (unsigned char) string[i];
4748       if (ISPRINT (c))
4749 	{
4750 	  if (c == '\\' || c == '\"')
4751 	    {
4752 	      putc ('\\', stream);
4753 	      cur_pos++;
4754 	    }
4755 	  putc (c, stream);
4756 	  cur_pos++;
4757 	}
4758       else
4759 	{
4760 	  fprintf (stream, "\\%03o", c);
4761 	  cur_pos += 4;
4762 	}
4763 
4764       if (cur_pos > 72 && i + 1 < len)
4765 	{
4766 	  cur_pos = 17;
4767 	  fprintf (stream, "\"\n\t.ascii\t\"");
4768 	}
4769     }
4770   fprintf (stream, "\"\n");
4771 }
4772 
4773 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
4774 
4775 static bool
loongarch_frame_pointer_required(void)4776 loongarch_frame_pointer_required (void)
4777 {
4778   /* If the function contains dynamic stack allocations, we need to
4779      use the frame pointer to access the static parts of the frame.  */
4780   if (cfun->calls_alloca)
4781     return true;
4782 
4783   return false;
4784 }
4785 
4786 /* Implement TARGET_CAN_ELIMINATE.  Make sure that we're not trying
4787    to eliminate to the wrong hard frame pointer.  */
4788 
4789 static bool
loongarch_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)4790 loongarch_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
4791 {
4792   return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
4793 }
4794 
4795 /* Implement RETURN_ADDR_RTX.  We do not support moving back to a
4796    previous frame.  */
4797 
4798 rtx
loongarch_return_addr(int count,rtx frame ATTRIBUTE_UNUSED)4799 loongarch_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
4800 {
4801   if (count != 0)
4802     return const0_rtx;
4803 
4804   return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
4805 }
4806 
4807 /* Emit code to change the current function's return address to
4808    ADDRESS.  SCRATCH is available as a scratch register, if needed.
4809    ADDRESS and SCRATCH are both word-mode GPRs.  */
4810 
4811 void
loongarch_set_return_address(rtx address,rtx scratch)4812 loongarch_set_return_address (rtx address, rtx scratch)
4813 {
4814   rtx slot_address;
4815 
4816   gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM));
4817 
4818   if (frame_pointer_needed)
4819     slot_address = loongarch_add_offset (scratch, hard_frame_pointer_rtx,
4820 					 -UNITS_PER_WORD);
4821   else
4822     slot_address = loongarch_add_offset (scratch, stack_pointer_rtx,
4823 					 cfun->machine->frame.gp_sp_offset);
4824 
4825   loongarch_emit_move (gen_frame_mem (GET_MODE (address), slot_address),
4826 		       address);
4827 }
4828 
4829 /* Return true if register REGNO can store a value of mode MODE.
4830    The result of this function is cached in loongarch_hard_regno_mode_ok.  */
4831 
4832 static bool
loongarch_hard_regno_mode_ok_uncached(unsigned int regno,machine_mode mode)4833 loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode)
4834 {
4835   unsigned int size;
4836   enum mode_class mclass;
4837 
4838   if (mode == FCCmode)
4839     return FCC_REG_P (regno);
4840 
4841   size = GET_MODE_SIZE (mode);
4842   mclass = GET_MODE_CLASS (mode);
4843 
4844   if (GP_REG_P (regno))
4845     return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD;
4846 
4847   if (FP_REG_P (regno))
4848     {
4849       if (mclass == MODE_FLOAT
4850 	  || mclass == MODE_COMPLEX_FLOAT
4851 	  || mclass == MODE_VECTOR_FLOAT)
4852 	return size <= UNITS_PER_FPVALUE;
4853 
4854       /* Allow integer modes that fit into a single register.  We need
4855 	 to put integers into FPRs when using instructions like CVT
4856 	 and TRUNC.  There's no point allowing sizes smaller than a word,
4857 	 because the FPU has no appropriate load/store instructions.  */
4858       if (mclass == MODE_INT)
4859 	return size >= MIN_UNITS_PER_WORD && size <= UNITS_PER_FPREG;
4860     }
4861 
4862   return false;
4863 }
4864 
4865 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
4866 
4867 static bool
loongarch_hard_regno_mode_ok(unsigned int regno,machine_mode mode)4868 loongarch_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
4869 {
4870   return loongarch_hard_regno_mode_ok_p[mode][regno];
4871 }
4872 
4873 /* Implement TARGET_HARD_REGNO_NREGS.  */
4874 
4875 static unsigned int
loongarch_hard_regno_nregs(unsigned int regno,machine_mode mode)4876 loongarch_hard_regno_nregs (unsigned int regno, machine_mode mode)
4877 {
4878   if (FCC_REG_P (regno))
4879     /* The size of FP status registers is always 4, because they only hold
4880        FCCmode values, and FCCmode is always considered to be 4 bytes wide.  */
4881     return (GET_MODE_SIZE (mode) + 3) / 4;
4882 
4883   if (FP_REG_P (regno))
4884     return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
4885 
4886   /* All other registers are word-sized.  */
4887   return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4888 }
4889 
4890 /* Implement CLASS_MAX_NREGS, taking the maximum of the cases
4891    in loongarch_hard_regno_nregs.  */
4892 
4893 int
loongarch_class_max_nregs(enum reg_class rclass,machine_mode mode)4894 loongarch_class_max_nregs (enum reg_class rclass, machine_mode mode)
4895 {
4896   int size;
4897   HARD_REG_SET left;
4898 
4899   size = 0x8000;
4900   left = reg_class_contents[rclass];
4901   if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FCC_REGS]))
4902     {
4903       if (loongarch_hard_regno_mode_ok (FCC_REG_FIRST, mode))
4904 	size = MIN (size, 4);
4905 
4906       left &= ~reg_class_contents[FCC_REGS];
4907     }
4908   if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS]))
4909     {
4910       if (loongarch_hard_regno_mode_ok (FP_REG_FIRST, mode))
4911 	size = MIN (size, UNITS_PER_FPREG);
4912 
4913       left &= ~reg_class_contents[FP_REGS];
4914     }
4915   if (!hard_reg_set_empty_p (left))
4916     size = MIN (size, UNITS_PER_WORD);
4917   return (GET_MODE_SIZE (mode) + size - 1) / size;
4918 }
4919 
4920 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
4921 
4922 static bool
loongarch_can_change_mode_class(machine_mode,machine_mode,reg_class_t rclass)4923 loongarch_can_change_mode_class (machine_mode, machine_mode,
4924 				 reg_class_t rclass)
4925 {
4926   return !reg_classes_intersect_p (FP_REGS, rclass);
4927 }
4928 
4929 /* Return true if moves in mode MODE can use the FPU's fmov.fmt instruction,
4930 */
4931 
4932 static bool
loongarch_mode_ok_for_mov_fmt_p(machine_mode mode)4933 loongarch_mode_ok_for_mov_fmt_p (machine_mode mode)
4934 {
4935   switch (mode)
4936     {
4937     case E_FCCmode:
4938     case E_SFmode:
4939       return TARGET_HARD_FLOAT;
4940 
4941     case E_DFmode:
4942       return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT;
4943 
4944     default:
4945       return 0;
4946     }
4947 }
4948 
4949 /* Implement TARGET_MODES_TIEABLE_P.  */
4950 
4951 static bool
loongarch_modes_tieable_p(machine_mode mode1,machine_mode mode2)4952 loongarch_modes_tieable_p (machine_mode mode1, machine_mode mode2)
4953 {
4954   /* FPRs allow no mode punning, so it's not worth tying modes if we'd
4955      prefer to put one of them in FPRs.  */
4956   return (mode1 == mode2
4957 	  || (!loongarch_mode_ok_for_mov_fmt_p (mode1)
4958 	      && !loongarch_mode_ok_for_mov_fmt_p (mode2)));
4959 }
4960 
4961 /* Implement TARGET_PREFERRED_RELOAD_CLASS.  */
4962 
4963 static reg_class_t
loongarch_preferred_reload_class(rtx x,reg_class_t rclass)4964 loongarch_preferred_reload_class (rtx x, reg_class_t rclass)
4965 {
4966   if (reg_class_subset_p (FP_REGS, rclass)
4967       && loongarch_mode_ok_for_mov_fmt_p (GET_MODE (x)))
4968     return FP_REGS;
4969 
4970   if (reg_class_subset_p (GR_REGS, rclass))
4971     rclass = GR_REGS;
4972 
4973   return rclass;
4974 }
4975 
4976 /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation.
4977    Return a "canonical" class to represent it in later calculations.  */
4978 
4979 static reg_class_t
loongarch_canonicalize_move_class(reg_class_t rclass)4980 loongarch_canonicalize_move_class (reg_class_t rclass)
4981 {
4982   if (reg_class_subset_p (rclass, GENERAL_REGS))
4983     rclass = GENERAL_REGS;
4984 
4985   return rclass;
4986 }
4987 
4988 /* Return the cost of moving a value from a register of class FROM to a GPR.
4989    Return 0 for classes that are unions of other classes handled by this
4990    function.  */
4991 
4992 static int
loongarch_move_to_gpr_cost(reg_class_t from)4993 loongarch_move_to_gpr_cost (reg_class_t from)
4994 {
4995   switch (from)
4996     {
4997     case GENERAL_REGS:
4998       /* MOVE macro.  */
4999       return 2;
5000 
5001     case FP_REGS:
5002       /* MOVFR2GR, etc.  */
5003       return 4;
5004 
5005     default:
5006       return 0;
5007     }
5008 }
5009 
5010 /* Return the cost of moving a value from a GPR to a register of class TO.
5011    Return 0 for classes that are unions of other classes handled by this
5012    function.  */
5013 
5014 static int
loongarch_move_from_gpr_cost(reg_class_t to)5015 loongarch_move_from_gpr_cost (reg_class_t to)
5016 {
5017   switch (to)
5018     {
5019     case GENERAL_REGS:
5020       /*MOVE macro.  */
5021       return 2;
5022 
5023     case FP_REGS:
5024       /* MOVGR2FR, etc.  */
5025       return 4;
5026 
5027     default:
5028       return 0;
5029     }
5030 }
5031 
5032 /* Implement TARGET_REGISTER_MOVE_COST.  Return 0 for classes that are the
5033    maximum of the move costs for subclasses; regclass will work out
5034    the maximum for us.  */
5035 
5036 static int
loongarch_register_move_cost(machine_mode mode,reg_class_t from,reg_class_t to)5037 loongarch_register_move_cost (machine_mode mode, reg_class_t from,
5038 			      reg_class_t to)
5039 {
5040   reg_class_t dregs;
5041   int cost1, cost2;
5042 
5043   from = loongarch_canonicalize_move_class (from);
5044   to = loongarch_canonicalize_move_class (to);
5045 
5046   /* Handle moves that can be done without using general-purpose registers.  */
5047   if (from == FP_REGS)
5048     {
5049       if (to == FP_REGS && loongarch_mode_ok_for_mov_fmt_p (mode))
5050 	/* FMOV.FMT.  */
5051 	return 4;
5052     }
5053 
5054   /* Handle cases in which only one class deviates from the ideal.  */
5055   dregs = GENERAL_REGS;
5056   if (from == dregs)
5057     return loongarch_move_from_gpr_cost (to);
5058   if (to == dregs)
5059     return loongarch_move_to_gpr_cost (from);
5060 
5061   /* Handles cases that require a GPR temporary.  */
5062   cost1 = loongarch_move_to_gpr_cost (from);
5063   if (cost1 != 0)
5064     {
5065       cost2 = loongarch_move_from_gpr_cost (to);
5066       if (cost2 != 0)
5067 	return cost1 + cost2;
5068     }
5069 
5070   return 0;
5071 }
5072 
5073 /* Implement TARGET_MEMORY_MOVE_COST.  */
5074 
5075 static int
loongarch_memory_move_cost(machine_mode mode,reg_class_t rclass,bool in)5076 loongarch_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in)
5077 {
5078   return (loongarch_cost->memory_latency
5079 	  + memory_move_secondary_cost (mode, rclass, in));
5080 }
5081 
5082 /* Return the register class required for a secondary register when
5083    copying between one of the registers in RCLASS and value X, which
5084    has mode MODE.  X is the source of the move if IN_P, otherwise it
5085    is the destination.  Return NO_REGS if no secondary register is
5086    needed.  */
5087 
5088 static reg_class_t
loongarch_secondary_reload(bool in_p ATTRIBUTE_UNUSED,rtx x,reg_class_t rclass,machine_mode mode,secondary_reload_info * sri ATTRIBUTE_UNUSED)5089 loongarch_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
5090 			    reg_class_t rclass, machine_mode mode,
5091 			    secondary_reload_info *sri ATTRIBUTE_UNUSED)
5092 {
5093   int regno;
5094 
5095   regno = true_regnum (x);
5096 
5097   if (reg_class_subset_p (rclass, FP_REGS))
5098     {
5099       if (regno < 0
5100 	  || (MEM_P (x)
5101 	      && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)))
5102 	/* In this case we can use fld.s, fst.s, fld.d or fst.d.  */
5103 	return NO_REGS;
5104 
5105       if (GP_REG_P (regno) || x == CONST0_RTX (mode))
5106 	/* In this case we can use movgr2fr.s, movfr2gr.s, movgr2fr.d or
5107 	 * movfr2gr.d.  */
5108 	return NO_REGS;
5109 
5110       if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (mode, x))
5111 	/* We can force the constant to memory and use fld.s
5112 	   and fld.d.  As above, we will use pairs of lwc1s if
5113 	   ldc1 is not supported.  */
5114 	return NO_REGS;
5115 
5116       if (FP_REG_P (regno) && loongarch_mode_ok_for_mov_fmt_p (mode))
5117 	/* In this case we can use fmov.{s/d}.  */
5118 	return NO_REGS;
5119 
5120       /* Otherwise, we need to reload through an integer register.  */
5121       return GR_REGS;
5122     }
5123   if (FP_REG_P (regno))
5124     return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS;
5125 
5126   return NO_REGS;
5127 }
5128 
5129 /* Implement TARGET_VALID_POINTER_MODE.  */
5130 
5131 static bool
loongarch_valid_pointer_mode(scalar_int_mode mode)5132 loongarch_valid_pointer_mode (scalar_int_mode mode)
5133 {
5134   return mode == SImode || (TARGET_64BIT && mode == DImode);
5135 }
5136 
5137 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
5138 
5139 static bool
loongarch_scalar_mode_supported_p(scalar_mode mode)5140 loongarch_scalar_mode_supported_p (scalar_mode mode)
5141 {
5142   if (ALL_FIXED_POINT_MODE_P (mode)
5143       && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
5144     return true;
5145 
5146   return default_scalar_mode_supported_p (mode);
5147 }
5148 
5149 /* Return the assembly code for INSN, which has the operands given by
5150    OPERANDS, and which branches to OPERANDS[0] if some condition is true.
5151    BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0]
5152    is in range of a direct branch.  BRANCH_IF_FALSE is an inverted
5153    version of BRANCH_IF_TRUE.  */
5154 
5155 const char *
loongarch_output_conditional_branch(rtx_insn * insn,rtx * operands,const char * branch_if_true,const char * branch_if_false)5156 loongarch_output_conditional_branch (rtx_insn *insn, rtx *operands,
5157 				     const char *branch_if_true,
5158 				     const char *branch_if_false)
5159 {
5160   unsigned int length;
5161   rtx taken;
5162 
5163   gcc_assert (LABEL_P (operands[0]));
5164 
5165   length = get_attr_length (insn);
5166   if (length <= 4)
5167     {
5168       return branch_if_true;
5169     }
5170 
5171   /* Generate a reversed branch around a direct jump.  */
5172   rtx_code_label *not_taken = gen_label_rtx ();
5173   taken = operands[0];
5174 
5175   /* Generate the reversed branch to NOT_TAKEN.  */
5176   operands[0] = not_taken;
5177   output_asm_insn (branch_if_false, operands);
5178 
5179   output_asm_insn ("b\t%0", &taken);
5180 
5181   /* Output NOT_TAKEN.  */
5182   targetm.asm_out.internal_label (asm_out_file, "L",
5183 				  CODE_LABEL_NUMBER (not_taken));
5184   return "";
5185 }
5186 
5187 /* Return the assembly code for INSN, which branches to OPERANDS[0]
5188    if some equality condition is true.  The condition is given by
5189    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of
5190    OPERANDS[1].  OPERANDS[2] is the comparison's first operand;
5191    OPERANDS[3] is the second operand and may be zero or a register.  */
5192 
5193 const char *
loongarch_output_equal_conditional_branch(rtx_insn * insn,rtx * operands,bool inverted_p)5194 loongarch_output_equal_conditional_branch (rtx_insn *insn, rtx *operands,
5195 					   bool inverted_p)
5196 {
5197   const char *branch[2];
5198   if (operands[3] == const0_rtx)
5199     {
5200       branch[!inverted_p] = LARCH_BRANCH ("b%C1z", "%2,%0");
5201       branch[inverted_p] = LARCH_BRANCH ("b%N1z", "%2,%0");
5202     }
5203   else
5204     {
5205       branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%z3,%0");
5206       branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%z3,%0");
5207     }
5208 
5209   return loongarch_output_conditional_branch (insn, operands, branch[1],
5210 					      branch[0]);
5211 }
5212 
5213 /* Return the assembly code for INSN, which branches to OPERANDS[0]
5214    if some ordering condition is true.  The condition is given by
5215    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of
5216    OPERANDS[1].  OPERANDS[2] is the comparison's first operand;
5217    OPERANDS[3] is the second operand and may be zero or a register.  */
5218 
5219 const char *
loongarch_output_order_conditional_branch(rtx_insn * insn,rtx * operands,bool inverted_p)5220 loongarch_output_order_conditional_branch (rtx_insn *insn, rtx *operands,
5221 					   bool inverted_p)
5222 {
5223   const char *branch[2];
5224 
5225   /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true.
5226      Make BRANCH[0] branch on the inverse condition.  */
5227   if (operands[3] != const0_rtx)
5228     {
5229       /* Handle degenerate cases that should not, but do, occur.  */
5230       if (REGNO (operands[2]) == REGNO (operands[3]))
5231 	{
5232 	  switch (GET_CODE (operands[1]))
5233 	    {
5234 	    case LT:
5235 	    case LTU:
5236 	    case GT:
5237 	    case GTU:
5238 	      inverted_p = !inverted_p;
5239 	      /* Fall through.  */
5240 	    case LE:
5241 	    case LEU:
5242 	    case GE:
5243 	    case GEU:
5244 	      branch[!inverted_p] = LARCH_BRANCH ("b", "%0");
5245 	      branch[inverted_p] = "\t# branch never";
5246 	      break;
5247 	    default:
5248 	      gcc_unreachable ();
5249 	    }
5250 	}
5251       else
5252 	{
5253 	  switch (GET_CODE (operands[1]))
5254 	    {
5255 	    case LE:
5256 	    case LEU:
5257 	    case GT:
5258 	    case GTU:
5259 	    case LT:
5260 	    case LTU:
5261 	    case GE:
5262 	    case GEU:
5263 	      branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%3,%0");
5264 	      branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%3,%0");
5265 	      break;
5266 	    default:
5267 	      gcc_unreachable ();
5268 	    }
5269 	}
5270     }
5271   else
5272     {
5273       switch (GET_CODE (operands[1]))
5274 	{
5275 	  /* These cases are equivalent to comparisons against zero.  */
5276 	case LEU:
5277 	case GTU:
5278 	case LTU:
5279 	case GEU:
5280 	case LE:
5281 	case GT:
5282 	case LT:
5283 	case GE:
5284 	  branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,$r0,%0");
5285 	  branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,$r0,%0");
5286 	  break;
5287 	default:
5288 	  gcc_unreachable ();
5289 	}
5290     }
5291   return loongarch_output_conditional_branch (insn, operands, branch[1],
5292 					      branch[0]);
5293 }
5294 
5295 /* Return the assembly code for DIV.{W/D} instruction DIVISION, which has
5296    the operands given by OPERANDS.  Add in a divide-by-zero check if needed.
5297    */
5298 
5299 const char *
loongarch_output_division(const char * division,rtx * operands)5300 loongarch_output_division (const char *division, rtx *operands)
5301 {
5302   const char *s;
5303 
5304   s = division;
5305   if (loongarch_check_zero_div_p ())
5306     {
5307       output_asm_insn (s, operands);
5308       s = "bne\t%2,%.,1f\n\tbreak\t7\n1:";
5309     }
5310   return s;
5311 }
5312 
5313 /* Implement TARGET_SCHED_ADJUST_COST.  We assume that anti and output
5314    dependencies have no cost.  */
5315 
5316 static int
loongarch_adjust_cost(rtx_insn *,int dep_type,rtx_insn *,int cost,unsigned int)5317 loongarch_adjust_cost (rtx_insn *, int dep_type, rtx_insn *, int cost,
5318 		       unsigned int)
5319 {
5320   if (dep_type != 0 && (dep_type != REG_DEP_OUTPUT))
5321     return 0;
5322   return cost;
5323 }
5324 
5325 /* Return the number of instructions that can be issued per cycle.  */
5326 
5327 static int
loongarch_issue_rate(void)5328 loongarch_issue_rate (void)
5329 {
5330   if ((unsigned long) LARCH_ACTUAL_TUNE < N_TUNE_TYPES)
5331     return loongarch_cpu_issue_rate[LARCH_ACTUAL_TUNE];
5332   else
5333     return 1;
5334 }
5335 
5336 /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD.  This should
5337    be as wide as the scheduling freedom in the DFA.  */
5338 
5339 static int
loongarch_multipass_dfa_lookahead(void)5340 loongarch_multipass_dfa_lookahead (void)
5341 {
5342   if ((unsigned long) LARCH_ACTUAL_TUNE < N_ARCH_TYPES)
5343     return loongarch_cpu_multipass_dfa_lookahead[LARCH_ACTUAL_TUNE];
5344   else
5345     return 0;
5346 }
5347 
5348 /* Implement TARGET_SCHED_REORDER.  */
5349 
5350 static int
loongarch_sched_reorder(FILE * file ATTRIBUTE_UNUSED,int verbose ATTRIBUTE_UNUSED,rtx_insn ** ready ATTRIBUTE_UNUSED,int * nreadyp ATTRIBUTE_UNUSED,int cycle ATTRIBUTE_UNUSED)5351 loongarch_sched_reorder (FILE *file ATTRIBUTE_UNUSED,
5352 			 int verbose ATTRIBUTE_UNUSED,
5353 			 rtx_insn **ready ATTRIBUTE_UNUSED,
5354 			 int *nreadyp ATTRIBUTE_UNUSED,
5355 			 int cycle ATTRIBUTE_UNUSED)
5356 {
5357   return loongarch_issue_rate ();
5358 }
5359 
5360 /* Implement TARGET_SCHED_REORDER2.  */
5361 
5362 static int
loongarch_sched_reorder2(FILE * file ATTRIBUTE_UNUSED,int verbose ATTRIBUTE_UNUSED,rtx_insn ** ready ATTRIBUTE_UNUSED,int * nreadyp ATTRIBUTE_UNUSED,int cycle ATTRIBUTE_UNUSED)5363 loongarch_sched_reorder2 (FILE *file ATTRIBUTE_UNUSED,
5364 			  int verbose ATTRIBUTE_UNUSED,
5365 			  rtx_insn **ready ATTRIBUTE_UNUSED,
5366 			  int *nreadyp ATTRIBUTE_UNUSED,
5367 			  int cycle ATTRIBUTE_UNUSED)
5368 {
5369   return cached_can_issue_more;
5370 }
5371 
5372 /* Implement TARGET_SCHED_INIT.  */
5373 
5374 static void
loongarch_sched_init(FILE * file ATTRIBUTE_UNUSED,int verbose ATTRIBUTE_UNUSED,int max_ready ATTRIBUTE_UNUSED)5375 loongarch_sched_init (FILE *file ATTRIBUTE_UNUSED,
5376 		      int verbose ATTRIBUTE_UNUSED,
5377 		      int max_ready ATTRIBUTE_UNUSED)
5378 {}
5379 
5380 /* Implement TARGET_SCHED_VARIABLE_ISSUE.  */
5381 
5382 static int
loongarch_variable_issue(FILE * file ATTRIBUTE_UNUSED,int verbose ATTRIBUTE_UNUSED,rtx_insn * insn,int more)5383 loongarch_variable_issue (FILE *file ATTRIBUTE_UNUSED,
5384 			  int verbose ATTRIBUTE_UNUSED, rtx_insn *insn,
5385 			  int more)
5386 {
5387   /* Ignore USEs and CLOBBERs; don't count them against the issue rate.  */
5388   if (USEFUL_INSN_P (insn))
5389     {
5390       if (get_attr_type (insn) != TYPE_GHOST)
5391 	more--;
5392     }
5393 
5394   /* Instructions of type 'multi' should all be split before
5395      the second scheduling pass.  */
5396   gcc_assert (!reload_completed
5397 	      || recog_memoized (insn) < 0
5398 	      || get_attr_type (insn) != TYPE_MULTI);
5399 
5400   cached_can_issue_more = more;
5401   return more;
5402 }
5403 
5404 /* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY),
5405    return the first operand of the associated PREF or PREFX insn.  */
5406 
5407 rtx
loongarch_prefetch_cookie(rtx write,rtx locality)5408 loongarch_prefetch_cookie (rtx write, rtx locality)
5409 {
5410   /* store_streamed / load_streamed.  */
5411   if (INTVAL (locality) <= 0)
5412     return GEN_INT (INTVAL (write) + 4);
5413 
5414   /* store / load.  */
5415   if (INTVAL (locality) <= 2)
5416     return write;
5417 
5418   /* store_retained / load_retained.  */
5419   return GEN_INT (INTVAL (write) + 6);
5420 }
5421 
5422 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
5423    in order to avoid duplicating too much logic from elsewhere.  */
5424 
5425 static void
loongarch_output_mi_thunk(FILE * file,tree thunk_fndecl ATTRIBUTE_UNUSED,HOST_WIDE_INT delta,HOST_WIDE_INT vcall_offset,tree function)5426 loongarch_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
5427 			   HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
5428 			   tree function)
5429 {
5430   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
5431   rtx this_rtx, temp1, temp2, fnaddr;
5432   rtx_insn *insn;
5433   bool use_sibcall_p;
5434 
5435   /* Pretend to be a post-reload pass while generating rtl.  */
5436   reload_completed = 1;
5437 
5438   /* Mark the end of the (empty) prologue.  */
5439   emit_note (NOTE_INSN_PROLOGUE_END);
5440 
5441   /* Determine if we can use a sibcall to call FUNCTION directly.  */
5442   fnaddr = XEXP (DECL_RTL (function), 0);
5443   use_sibcall_p = const_call_insn_operand (fnaddr, Pmode);
5444 
5445   /* We need two temporary registers in some cases.  */
5446   temp1 = gen_rtx_REG (Pmode, 12);
5447   temp2 = gen_rtx_REG (Pmode, 13);
5448 
5449   /* Find out which register contains the "this" pointer.  */
5450   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
5451     this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
5452   else
5453     this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST);
5454 
5455   /* Add DELTA to THIS_RTX.  */
5456   if (delta != 0)
5457     {
5458       rtx offset = GEN_INT (delta);
5459       if (!IMM12_OPERAND (delta))
5460 	{
5461 	  loongarch_emit_move (temp1, offset);
5462 	  offset = temp1;
5463 	}
5464       emit_insn (gen_add3_insn (this_rtx, this_rtx, offset));
5465     }
5466 
5467   /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
5468   if (vcall_offset != 0)
5469     {
5470       rtx addr;
5471 
5472       /* Set TEMP1 to *THIS_RTX.  */
5473       loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx));
5474 
5475       /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET.  */
5476       addr = loongarch_add_offset (temp2, temp1, vcall_offset);
5477 
5478       /* Load the offset and add it to THIS_RTX.  */
5479       loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, addr));
5480       emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1));
5481     }
5482 
5483   /* Jump to the target function.  Use a sibcall if direct jumps are
5484      allowed, otherwise load the address into a register first.  */
5485   if (use_sibcall_p)
5486     {
5487       insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
5488       SIBLING_CALL_P (insn) = 1;
5489     }
5490   else
5491     {
5492       loongarch_emit_move (temp1, fnaddr);
5493       emit_jump_insn (gen_indirect_jump (temp1));
5494     }
5495 
5496   /* Run just enough of rest_of_compilation.  This sequence was
5497      "borrowed" from alpha.c.  */
5498   insn = get_insns ();
5499   split_all_insns_noflow ();
5500   shorten_branches (insn);
5501   assemble_start_function (thunk_fndecl, fnname);
5502   final_start_function (insn, file, 1);
5503   final (insn, file, 1);
5504   final_end_function ();
5505   assemble_end_function (thunk_fndecl, fnname);
5506 
5507   /* Stop pretending to be a post-reload pass.  */
5508   reload_completed = 0;
5509 }
5510 
5511 /* Allocate a chunk of memory for per-function machine-dependent data.  */
5512 
5513 static struct machine_function *
loongarch_init_machine_status(void)5514 loongarch_init_machine_status (void)
5515 {
5516   return ggc_cleared_alloc<machine_function> ();
5517 }
5518 
5519 static void
loongarch_option_override_internal(struct gcc_options * opts,struct gcc_options * opts_set)5520 loongarch_option_override_internal (struct gcc_options *opts,
5521 				    struct gcc_options *opts_set)
5522 {
5523   int i, regno, mode;
5524 
5525   if (flag_pic)
5526     g_switch_value = 0;
5527 
5528   /* Handle target-specific options: compute defaults/conflicts etc.  */
5529   loongarch_config_target (&la_target, la_opt_switches,
5530 			   la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu,
5531 			   la_opt_abi_base, la_opt_abi_ext, la_opt_cmodel, 0);
5532 
5533   loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
5534 
5535   if (TARGET_ABI_LP64)
5536     flag_pcc_struct_return = 0;
5537 
5538   /* Decide which rtx_costs structure to use.  */
5539   if (optimize_size)
5540     loongarch_cost = &loongarch_rtx_cost_optimize_size;
5541   else
5542     loongarch_cost = &loongarch_cpu_rtx_cost_data[LARCH_ACTUAL_TUNE];
5543 
5544   /* If the user hasn't specified a branch cost, use the processor's
5545      default.  */
5546   if (loongarch_branch_cost == 0)
5547     loongarch_branch_cost = loongarch_cost->branch_cost;
5548 
5549 
5550   switch (la_target.cmodel)
5551     {
5552       case CMODEL_TINY_STATIC:
5553       case CMODEL_EXTREME:
5554 	if (opts->x_flag_plt)
5555 	  error ("code model %qs and %qs not support %s mode",
5556 		 "tiny-static", "extreme", "plt");
5557 	break;
5558 
5559       case CMODEL_NORMAL:
5560       case CMODEL_TINY:
5561       case CMODEL_LARGE:
5562 	break;
5563 
5564       default:
5565 	gcc_unreachable ();
5566     }
5567 
5568   loongarch_init_print_operand_punct ();
5569 
5570   /* Set up array to map GCC register number to debug register number.
5571      Ignore the special purpose register numbers.  */
5572 
5573   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
5574     {
5575       if (GP_REG_P (i) || FP_REG_P (i))
5576 	loongarch_dwarf_regno[i] = i;
5577       else
5578 	loongarch_dwarf_regno[i] = INVALID_REGNUM;
5579     }
5580 
5581   /* Set up loongarch_hard_regno_mode_ok.  */
5582   for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
5583     for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
5584       loongarch_hard_regno_mode_ok_p[mode][regno]
5585 	= loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode);
5586 
5587   /* Function to allocate machine-dependent function status.  */
5588   init_machine_status = &loongarch_init_machine_status;
5589 }
5590 
5591 
5592 /* Implement TARGET_OPTION_OVERRIDE.  */
5593 
5594 static void
loongarch_option_override(void)5595 loongarch_option_override (void)
5596 {
5597   loongarch_option_override_internal (&global_options, &global_options_set);
5598 }
5599 
5600 /* Implement TARGET_OPTION_SAVE.  */
5601 static void
loongarch_option_save(struct cl_target_option *,struct gcc_options * opts,struct gcc_options * opts_set)5602 loongarch_option_save (struct cl_target_option *,
5603 		       struct gcc_options *opts,
5604 		       struct gcc_options *opts_set)
5605 {
5606   loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
5607 }
5608 
5609 /* Implement TARGET_OPTION_RESTORE.  */
5610 static void
loongarch_option_restore(struct gcc_options *,struct gcc_options *,struct cl_target_option * ptr)5611 loongarch_option_restore (struct gcc_options *,
5612 			  struct gcc_options *,
5613 			  struct cl_target_option *ptr)
5614 {
5615   la_target.cpu_arch = ptr->x_la_opt_cpu_arch;
5616   la_target.cpu_tune = ptr->x_la_opt_cpu_tune;
5617 
5618   la_target.isa.fpu = ptr->x_la_opt_fpu;
5619 
5620   la_target.cmodel = ptr->x_la_opt_cmodel;
5621 }
5622 
5623 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
5624 
5625 static void
loongarch_conditional_register_usage(void)5626 loongarch_conditional_register_usage (void)
5627 {
5628   if (!TARGET_HARD_FLOAT)
5629     accessible_reg_set &= ~(reg_class_contents[FP_REGS]
5630 			    | reg_class_contents[FCC_REGS]);
5631 }
5632 
5633 /* Implement EH_USES.  */
5634 
5635 bool
loongarch_eh_uses(unsigned int regno ATTRIBUTE_UNUSED)5636 loongarch_eh_uses (unsigned int regno ATTRIBUTE_UNUSED)
5637 {
5638   return false;
5639 }
5640 
5641 /* Implement EPILOGUE_USES.  */
5642 
5643 bool
loongarch_epilogue_uses(unsigned int regno)5644 loongarch_epilogue_uses (unsigned int regno)
5645 {
5646   /* Say that the epilogue uses the return address register.  Note that
5647      in the case of sibcalls, the values "used by the epilogue" are
5648      considered live at the start of the called function.  */
5649   if (regno == RETURN_ADDR_REGNUM)
5650     return true;
5651 
5652   return false;
5653 }
5654 
5655 bool
loongarch_load_store_bonding_p(rtx * operands,machine_mode mode,bool load_p)5656 loongarch_load_store_bonding_p (rtx *operands, machine_mode mode, bool load_p)
5657 {
5658   rtx reg1, reg2, mem1, mem2, base1, base2;
5659   enum reg_class rc1, rc2;
5660   HOST_WIDE_INT offset1, offset2;
5661 
5662   if (load_p)
5663     {
5664       reg1 = operands[0];
5665       reg2 = operands[2];
5666       mem1 = operands[1];
5667       mem2 = operands[3];
5668     }
5669   else
5670     {
5671       reg1 = operands[1];
5672       reg2 = operands[3];
5673       mem1 = operands[0];
5674       mem2 = operands[2];
5675     }
5676 
5677   if (loongarch_address_insns (XEXP (mem1, 0), mode, false) == 0
5678       || loongarch_address_insns (XEXP (mem2, 0), mode, false) == 0)
5679     return false;
5680 
5681   loongarch_split_plus (XEXP (mem1, 0), &base1, &offset1);
5682   loongarch_split_plus (XEXP (mem2, 0), &base2, &offset2);
5683 
5684   /* Base regs do not match.  */
5685   if (!REG_P (base1) || !rtx_equal_p (base1, base2))
5686     return false;
5687 
5688   /* Either of the loads is clobbering base register.  It is legitimate to bond
5689      loads if second load clobbers base register.  However, hardware does not
5690      support such bonding.  */
5691   if (load_p
5692       && (REGNO (reg1) == REGNO (base1) || (REGNO (reg2) == REGNO (base1))))
5693     return false;
5694 
5695   /* Loading in same registers.  */
5696   if (load_p && REGNO (reg1) == REGNO (reg2))
5697     return false;
5698 
5699   /* The loads/stores are not of same type.  */
5700   rc1 = REGNO_REG_CLASS (REGNO (reg1));
5701   rc2 = REGNO_REG_CLASS (REGNO (reg2));
5702   if (rc1 != rc2 && !reg_class_subset_p (rc1, rc2)
5703       && !reg_class_subset_p (rc2, rc1))
5704     return false;
5705 
5706   if (abs (offset1 - offset2) != GET_MODE_SIZE (mode))
5707     return false;
5708 
5709   return true;
5710 }
5711 
5712 /* Implement TARGET_TRAMPOLINE_INIT.  */
5713 
5714 static void
loongarch_trampoline_init(rtx m_tramp,tree fndecl,rtx chain_value)5715 loongarch_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
5716 {
5717   rtx addr, end_addr, mem;
5718   rtx trampoline[8];
5719   unsigned int i, j;
5720   HOST_WIDE_INT end_addr_offset, static_chain_offset, target_function_offset;
5721 
5722   /* Work out the offsets of the pointers from the start of the
5723      trampoline code.  */
5724   end_addr_offset = TRAMPOLINE_CODE_SIZE;
5725   static_chain_offset = end_addr_offset;
5726   target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode);
5727 
5728   /* Get pointers to the beginning and end of the code block.  */
5729   addr = force_reg (Pmode, XEXP (m_tramp, 0));
5730   end_addr
5731     = loongarch_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset));
5732 
5733 #define OP(X) gen_int_mode (X, SImode)
5734 
5735   /* Build up the code in TRAMPOLINE.  */
5736   i = 0;
5737   /*pcaddi $static_chain,0
5738     ld.[dw] $tmp,$static_chain,target_function_offset
5739     ld.[dw] $static_chain,$static_chain,static_chain_offset
5740     jirl $r0,$tmp,0  */
5741   trampoline[i++] = OP (0x18000000 | (STATIC_CHAIN_REGNUM - GP_REG_FIRST));
5742   trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000)
5743 			| 19 /* $t7  */
5744 			| ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5)
5745 			| ((target_function_offset & 0xfff) << 10));
5746   trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000)
5747 			| (STATIC_CHAIN_REGNUM - GP_REG_FIRST)
5748 			| ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5)
5749 			| ((static_chain_offset & 0xfff) << 10));
5750   trampoline[i++] = OP (0x4c000000 | (19 << 5));
5751 #undef OP
5752 
5753   for (j = 0; j < i; j++)
5754    {
5755      mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode));
5756      loongarch_emit_move (mem, trampoline[j]);
5757    }
5758 
5759   /* Set up the static chain pointer field.  */
5760   mem = adjust_address (m_tramp, ptr_mode, static_chain_offset);
5761   loongarch_emit_move (mem, chain_value);
5762 
5763   /* Set up the target function field.  */
5764   mem = adjust_address (m_tramp, ptr_mode, target_function_offset);
5765   loongarch_emit_move (mem, XEXP (DECL_RTL (fndecl), 0));
5766 
5767   /* Flush the code part of the trampoline.  */
5768   emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE)));
5769   emit_insn (gen_clear_cache (addr, end_addr));
5770 }
5771 
5772 /* Implement HARD_REGNO_CALLER_SAVE_MODE.  */
5773 
5774 machine_mode
loongarch_hard_regno_caller_save_mode(unsigned int regno,unsigned int nregs,machine_mode mode)5775 loongarch_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
5776 				       machine_mode mode)
5777 {
5778   /* For performance, avoid saving/restoring upper parts of a register
5779      by returning MODE as save mode when the mode is known.  */
5780   if (mode == VOIDmode)
5781     return choose_hard_reg_mode (regno, nregs, NULL);
5782   else
5783     return mode;
5784 }
5785 
5786 /* Implement TARGET_SPILL_CLASS.  */
5787 
5788 static reg_class_t
loongarch_spill_class(reg_class_t rclass ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED)5789 loongarch_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED,
5790 		       machine_mode mode ATTRIBUTE_UNUSED)
5791 {
5792   return NO_REGS;
5793 }
5794 
5795 /* Implement TARGET_PROMOTE_FUNCTION_MODE.  */
5796 
5797 /* This function is equivalent to default_promote_function_mode_always_promote
5798    except that it returns a promoted mode even if type is NULL_TREE.  This is
5799    needed by libcalls which have no type (only a mode) such as fixed conversion
5800    routines that take a signed or unsigned char/short argument and convert it
5801    to a fixed type.  */
5802 
5803 static machine_mode
loongarch_promote_function_mode(const_tree type ATTRIBUTE_UNUSED,machine_mode mode,int * punsignedp ATTRIBUTE_UNUSED,const_tree fntype ATTRIBUTE_UNUSED,int for_return ATTRIBUTE_UNUSED)5804 loongarch_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
5805 				 machine_mode mode,
5806 				 int *punsignedp ATTRIBUTE_UNUSED,
5807 				 const_tree fntype ATTRIBUTE_UNUSED,
5808 				 int for_return ATTRIBUTE_UNUSED)
5809 {
5810   int unsignedp;
5811 
5812   if (type != NULL_TREE)
5813     return promote_mode (type, mode, punsignedp);
5814 
5815   unsignedp = *punsignedp;
5816   PROMOTE_MODE (mode, unsignedp, type);
5817   *punsignedp = unsignedp;
5818   return mode;
5819 }
5820 
5821 /* Implement TARGET_STARTING_FRAME_OFFSET.  See loongarch_compute_frame_info
5822    for details about the frame layout.  */
5823 
5824 static HOST_WIDE_INT
loongarch_starting_frame_offset(void)5825 loongarch_starting_frame_offset (void)
5826 {
5827   if (FRAME_GROWS_DOWNWARD)
5828     return 0;
5829   return crtl->outgoing_args_size;
5830 }
5831 
5832 /* Initialize the GCC target structure.  */
5833 #undef TARGET_ASM_ALIGNED_HI_OP
5834 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
5835 #undef TARGET_ASM_ALIGNED_SI_OP
5836 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
5837 #undef TARGET_ASM_ALIGNED_DI_OP
5838 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
5839 
5840 #undef TARGET_OPTION_OVERRIDE
5841 #define TARGET_OPTION_OVERRIDE loongarch_option_override
5842 #define TARGET_OPTION_SAVE loongarch_option_save
5843 #undef TARGET_OPTION_RESTORE
5844 #define TARGET_OPTION_RESTORE loongarch_option_restore
5845 
5846 
5847 #undef TARGET_LEGITIMIZE_ADDRESS
5848 #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address
5849 
5850 #undef TARGET_ASM_SELECT_RTX_SECTION
5851 #define TARGET_ASM_SELECT_RTX_SECTION loongarch_select_rtx_section
5852 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
5853 #define TARGET_ASM_FUNCTION_RODATA_SECTION loongarch_function_rodata_section
5854 
5855 #undef TARGET_SCHED_INIT
5856 #define TARGET_SCHED_INIT loongarch_sched_init
5857 #undef TARGET_SCHED_REORDER
5858 #define TARGET_SCHED_REORDER loongarch_sched_reorder
5859 #undef TARGET_SCHED_REORDER2
5860 #define TARGET_SCHED_REORDER2 loongarch_sched_reorder2
5861 #undef TARGET_SCHED_VARIABLE_ISSUE
5862 #define TARGET_SCHED_VARIABLE_ISSUE loongarch_variable_issue
5863 #undef TARGET_SCHED_ADJUST_COST
5864 #define TARGET_SCHED_ADJUST_COST loongarch_adjust_cost
5865 #undef TARGET_SCHED_ISSUE_RATE
5866 #define TARGET_SCHED_ISSUE_RATE loongarch_issue_rate
5867 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
5868 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
5869   loongarch_multipass_dfa_lookahead
5870 
5871 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5872 #define TARGET_FUNCTION_OK_FOR_SIBCALL loongarch_function_ok_for_sibcall
5873 
5874 #undef TARGET_VALID_POINTER_MODE
5875 #define TARGET_VALID_POINTER_MODE loongarch_valid_pointer_mode
5876 #undef TARGET_REGISTER_MOVE_COST
5877 #define TARGET_REGISTER_MOVE_COST loongarch_register_move_cost
5878 #undef TARGET_MEMORY_MOVE_COST
5879 #define TARGET_MEMORY_MOVE_COST loongarch_memory_move_cost
5880 #undef TARGET_RTX_COSTS
5881 #define TARGET_RTX_COSTS loongarch_rtx_costs
5882 #undef TARGET_ADDRESS_COST
5883 #define TARGET_ADDRESS_COST loongarch_address_cost
5884 
5885 #undef TARGET_IN_SMALL_DATA_P
5886 #define TARGET_IN_SMALL_DATA_P loongarch_in_small_data_p
5887 
5888 #undef TARGET_PREFERRED_RELOAD_CLASS
5889 #define TARGET_PREFERRED_RELOAD_CLASS loongarch_preferred_reload_class
5890 
5891 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
5892 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
5893 
5894 #undef TARGET_EXPAND_BUILTIN_VA_START
5895 #define TARGET_EXPAND_BUILTIN_VA_START loongarch_va_start
5896 
5897 #undef TARGET_PROMOTE_FUNCTION_MODE
5898 #define TARGET_PROMOTE_FUNCTION_MODE loongarch_promote_function_mode
5899 #undef TARGET_RETURN_IN_MEMORY
5900 #define TARGET_RETURN_IN_MEMORY loongarch_return_in_memory
5901 
5902 #undef TARGET_FUNCTION_VALUE
5903 #define TARGET_FUNCTION_VALUE loongarch_function_value
5904 #undef TARGET_LIBCALL_VALUE
5905 #define TARGET_LIBCALL_VALUE loongarch_libcall_value
5906 
5907 #undef TARGET_ASM_OUTPUT_MI_THUNK
5908 #define TARGET_ASM_OUTPUT_MI_THUNK loongarch_output_mi_thunk
5909 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5910 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5911   hook_bool_const_tree_hwi_hwi_const_tree_true
5912 
5913 #undef TARGET_PRINT_OPERAND
5914 #define TARGET_PRINT_OPERAND loongarch_print_operand
5915 #undef TARGET_PRINT_OPERAND_ADDRESS
5916 #define TARGET_PRINT_OPERAND_ADDRESS loongarch_print_operand_address
5917 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
5918 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P \
5919   loongarch_print_operand_punct_valid_p
5920 
5921 #undef TARGET_SETUP_INCOMING_VARARGS
5922 #define TARGET_SETUP_INCOMING_VARARGS loongarch_setup_incoming_varargs
5923 #undef TARGET_STRICT_ARGUMENT_NAMING
5924 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
5925 #undef TARGET_MUST_PASS_IN_STACK
5926 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
5927 #undef TARGET_PASS_BY_REFERENCE
5928 #define TARGET_PASS_BY_REFERENCE loongarch_pass_by_reference
5929 #undef TARGET_ARG_PARTIAL_BYTES
5930 #define TARGET_ARG_PARTIAL_BYTES loongarch_arg_partial_bytes
5931 #undef TARGET_FUNCTION_ARG
5932 #define TARGET_FUNCTION_ARG loongarch_function_arg
5933 #undef TARGET_FUNCTION_ARG_ADVANCE
5934 #define TARGET_FUNCTION_ARG_ADVANCE loongarch_function_arg_advance
5935 #undef TARGET_FUNCTION_ARG_BOUNDARY
5936 #define TARGET_FUNCTION_ARG_BOUNDARY loongarch_function_arg_boundary
5937 
5938 #undef TARGET_SCALAR_MODE_SUPPORTED_P
5939 #define TARGET_SCALAR_MODE_SUPPORTED_P loongarch_scalar_mode_supported_p
5940 
5941 #undef TARGET_INIT_BUILTINS
5942 #define TARGET_INIT_BUILTINS loongarch_init_builtins
5943 #undef TARGET_BUILTIN_DECL
5944 #define TARGET_BUILTIN_DECL loongarch_builtin_decl
5945 #undef TARGET_EXPAND_BUILTIN
5946 #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin
5947 
5948 /* The generic ELF target does not always have TLS support.  */
5949 #ifdef HAVE_AS_TLS
5950 #undef TARGET_HAVE_TLS
5951 #define TARGET_HAVE_TLS HAVE_AS_TLS
5952 #endif
5953 
5954 #undef TARGET_CANNOT_FORCE_CONST_MEM
5955 #define TARGET_CANNOT_FORCE_CONST_MEM loongarch_cannot_force_const_mem
5956 
5957 #undef TARGET_LEGITIMATE_CONSTANT_P
5958 #define TARGET_LEGITIMATE_CONSTANT_P loongarch_legitimate_constant_p
5959 
5960 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
5961 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
5962 
5963 #ifdef HAVE_AS_DTPRELWORD
5964 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
5965 #define TARGET_ASM_OUTPUT_DWARF_DTPREL loongarch_output_dwarf_dtprel
5966 #endif
5967 
5968 #undef TARGET_LEGITIMATE_ADDRESS_P
5969 #define TARGET_LEGITIMATE_ADDRESS_P loongarch_legitimate_address_p
5970 
5971 #undef TARGET_FRAME_POINTER_REQUIRED
5972 #define TARGET_FRAME_POINTER_REQUIRED loongarch_frame_pointer_required
5973 
5974 #undef TARGET_CAN_ELIMINATE
5975 #define TARGET_CAN_ELIMINATE loongarch_can_eliminate
5976 
5977 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5978 #define TARGET_CONDITIONAL_REGISTER_USAGE loongarch_conditional_register_usage
5979 
5980 #undef TARGET_TRAMPOLINE_INIT
5981 #define TARGET_TRAMPOLINE_INIT loongarch_trampoline_init
5982 
5983 #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
5984 #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV loongarch_atomic_assign_expand_fenv
5985 
5986 #undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
5987 #define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
5988 
5989 #undef TARGET_SPILL_CLASS
5990 #define TARGET_SPILL_CLASS loongarch_spill_class
5991 
5992 #undef TARGET_HARD_REGNO_NREGS
5993 #define TARGET_HARD_REGNO_NREGS loongarch_hard_regno_nregs
5994 #undef TARGET_HARD_REGNO_MODE_OK
5995 #define TARGET_HARD_REGNO_MODE_OK loongarch_hard_regno_mode_ok
5996 
5997 #undef TARGET_MODES_TIEABLE_P
5998 #define TARGET_MODES_TIEABLE_P loongarch_modes_tieable_p
5999 
6000 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
6001 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
6002 
6003 #undef TARGET_CAN_CHANGE_MODE_CLASS
6004 #define TARGET_CAN_CHANGE_MODE_CLASS loongarch_can_change_mode_class
6005 
6006 #undef TARGET_CONSTANT_ALIGNMENT
6007 #define TARGET_CONSTANT_ALIGNMENT loongarch_constant_alignment
6008 
6009 #undef TARGET_STARTING_FRAME_OFFSET
6010 #define TARGET_STARTING_FRAME_OFFSET loongarch_starting_frame_offset
6011 
6012 #undef TARGET_SECONDARY_RELOAD
6013 #define TARGET_SECONDARY_RELOAD loongarch_secondary_reload
6014 
6015 #undef  TARGET_HAVE_SPECULATION_SAFE_VALUE
6016 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
6017 
6018 struct gcc_target targetm = TARGET_INITIALIZER;
6019 
6020 #include "gt-loongarch.h"
6021