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