[Ada] Fix proof of runtime units
[official-gcc.git] / gcc / config / loongarch / loongarch.cc
blob80046b64006d32b4963bdc28cfcee46f159b7a3e
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.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #define IN_TARGET_CODE 1
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"
67 /* This file should be included last. */
68 #include "target-def.h"
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)
76 /* Extract the symbol or label from UNSPEC wrapper X. */
77 #define UNSPEC_ADDRESS(X) XVECEXP (X, 0, 0)
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))
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)
91 /* True if bit BIT is set in VALUE. */
92 #define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0)
94 /* Classifies an address.
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.
100 ADDRESS_REG_REG
101 A base register indexed by (optionally scaled) register.
103 ADDRESS_CONST_INT
104 A signed 16-bit constant address.
106 ADDRESS_SYMBOLIC:
107 A constant symbolic address. */
108 enum loongarch_address_type
110 ADDRESS_REG,
111 ADDRESS_REG_REG,
112 ADDRESS_CONST_INT,
113 ADDRESS_SYMBOLIC
117 /* Information about an address described by loongarch_address_type.
119 ADDRESS_CONST_INT
120 No fields are used.
122 ADDRESS_REG
123 REG is the base register and OFFSET is the constant offset.
125 ADDRESS_REG_REG
126 A base register indexed by (optionally scaled) register.
128 ADDRESS_SYMBOLIC
129 SYMBOL_TYPE is the type of symbol that the address references. */
130 struct loongarch_address_info
132 enum loongarch_address_type type;
133 rtx reg;
134 rtx offset;
135 enum loongarch_symbol_type symbol_type;
138 /* Method of loading instant numbers:
140 METHOD_NORMAL:
141 Load 0-31 bit of the immediate number.
143 METHOD_LU32I:
144 Load 32-51 bit of the immediate number.
146 METHOD_LU52I:
147 Load 52-63 bit of the immediate number.
149 METHOD_INSV:
150 immediate like 0xfff00000fffffxxx
152 enum loongarch_load_imm_method
154 METHOD_NORMAL,
155 METHOD_LU32I,
156 METHOD_LU52I,
157 METHOD_INSV
160 struct loongarch_integer_op
162 enum rtx_code code;
163 unsigned HOST_WIDE_INT value;
164 enum loongarch_load_imm_method method;
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
172 /* Arrays that map GCC register numbers to debugger register numbers. */
173 int loongarch_dwarf_regno[FIRST_PSEUDO_REGISTER];
175 /* Index [M][R] is true if register R is allowed to hold a value of mode M. */
176 static bool loongarch_hard_regno_mode_ok_p[MAX_MACHINE_MODE]
177 [FIRST_PSEUDO_REGISTER];
179 /* Index C is true if character C is a valid PRINT_OPERAND punctation
180 character. */
181 static bool loongarch_print_operand_punct[256];
183 /* Cached value of can_issue_more. This is cached in loongarch_variable_issue
184 hook and returned from loongarch_sched_reorder2. */
185 static int cached_can_issue_more;
187 /* Index R is the smallest register class that contains register R. */
188 const enum reg_class loongarch_regno_to_class[FIRST_PSEUDO_REGISTER] = {
189 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
190 JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS,
191 JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS,
192 SIBCALL_REGS, 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,
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
211 /* Which cost information to use. */
212 static const struct loongarch_rtx_cost_data *loongarch_cost;
214 /* Information about a single argument. */
215 struct loongarch_arg_info
217 /* True if the argument is at least partially passed on the stack. */
218 bool stack_p;
220 /* The number of integer registers allocated to this argument. */
221 unsigned int num_gprs;
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;
227 /* The number of floating-point registers allocated to this argument. */
228 unsigned int num_fprs;
230 /* The offset of the first register used, provided num_fprs is nonzero. */
231 unsigned int fpr_offset;
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)
253 /* Enumerates the codes above as LARCH_FP_COND_<X>. */
254 #define DECLARE_LARCH_COND(X) LARCH_FP_COND_##X
255 enum loongarch_fp_condition
257 LARCH_FP_CONDITIONS (DECLARE_LARCH_COND)
259 #undef DECLARE_LARCH_COND
261 /* Index X provides the string representation of LARCH_FP_COND_<X>. */
262 #define STRINGIFY(X) #X
263 const char *const
264 loongarch_fp_conditions[16]= {LARCH_FP_CONDITIONS (STRINGIFY)};
265 #undef STRINGIFY
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. */
271 static unsigned int
272 loongarch_function_arg_boundary (machine_mode mode, const_tree type)
274 unsigned int alignment;
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);
282 return MIN (PREFERRED_STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment));
285 /* If MODE represents an argument that can be passed or returned in
286 floating-point registers, return the number of registers, else 0. */
288 static unsigned
289 loongarch_pass_mode_in_fpr_p (machine_mode mode)
291 if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG)
293 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
294 return 1;
296 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
297 return 2;
300 return 0;
303 typedef struct
305 const_tree type;
306 HOST_WIDE_INT offset;
307 } loongarch_aggregate_field;
309 /* Identify subfields of aggregates that are candidates for passing in
310 floating-point registers. */
312 static int
313 loongarch_flatten_aggregate_field (const_tree type,
314 loongarch_aggregate_field fields[2], int n,
315 HOST_WIDE_INT offset)
317 switch (TREE_CODE (type))
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;
326 for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
327 if (TREE_CODE (f) == FIELD_DECL)
329 if (!TYPE_P (TREE_TYPE (f)))
330 return -1;
332 if (DECL_SIZE (f) && integer_zerop (DECL_SIZE (f)))
333 continue;
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;
341 return n;
343 case ARRAY_TYPE:
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);
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;
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);
369 for (HOST_WIDE_INT i = 0; i < n_elts; i++)
370 for (int j = 0; j < n_subfields; j++)
372 if (n >= 2)
373 return -1;
375 fields[n] = subfields[j];
376 fields[n++].offset += i * tree_to_uhwi (elt_size);
379 return n;
382 case COMPLEX_TYPE:
384 /* Complex type need consume 2 field, so n must be 0. */
385 if (n != 0)
386 return -1;
388 HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)));
390 if (elt_size <= UNITS_PER_FP_ARG)
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;
397 return 2;
400 return -1;
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)))
410 fields[n].type = type;
411 fields[n].offset = offset;
412 return n + 1;
414 else
415 return -1;
419 /* Identify candidate aggregates for passing in floating-point registers.
420 Candidates have at most two fields after flattening. */
422 static int
423 loongarch_flatten_aggregate_argument (const_tree type,
424 loongarch_aggregate_field fields[2])
426 if (!type || TREE_CODE (type) != RECORD_TYPE)
427 return -1;
429 return loongarch_flatten_aggregate_field (type, fields, 0, 0);
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. */
435 static unsigned
436 loongarch_pass_aggregate_num_fpr (const_tree type,
437 loongarch_aggregate_field fields[2])
439 int n = loongarch_flatten_aggregate_argument (type, fields);
441 for (int i = 0; i < n; i++)
442 if (!SCALAR_FLOAT_TYPE_P (fields[i].type))
443 return 0;
445 return n > 0 ? n : 0;
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. */
452 static bool
453 loongarch_pass_aggregate_in_fpr_and_gpr_p (const_tree type,
454 loongarch_aggregate_field fields[2])
456 unsigned num_int = 0, num_float = 0;
457 int n = loongarch_flatten_aggregate_argument (type, fields);
459 for (int i = 0; i < n; i++)
461 num_float += SCALAR_FLOAT_TYPE_P (fields[i].type);
462 num_int += INTEGRAL_TYPE_P (fields[i].type);
465 return num_int == 1 && num_float == 1;
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:
472 struct __attribute__((packed)) foo { float f; }
474 where the SFmode value "f" is passed in REGNO but the struct itself
475 has mode BLKmode. */
477 static rtx
478 loongarch_pass_fpr_single (machine_mode type_mode, unsigned regno,
479 machine_mode value_mode,
480 HOST_WIDE_INT offset)
482 rtx x = gen_rtx_REG (value_mode, regno);
484 if (type_mode != value_mode)
486 x = gen_rtx_EXPR_LIST (VOIDmode, x, GEN_INT (offset));
487 x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x));
489 return x;
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. */
497 static rtx
498 loongarch_pass_fpr_pair (machine_mode mode, unsigned regno1,
499 machine_mode mode1, HOST_WIDE_INT offset1,
500 unsigned regno2, machine_mode mode2,
501 HOST_WIDE_INT offset2)
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))));
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. */
518 static rtx
519 loongarch_get_arg_info (struct loongarch_arg_info *info,
520 const CUMULATIVE_ARGS *cum, machine_mode mode,
521 const_tree type, bool named, bool return_p)
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);
528 memset (info, 0, sizeof (*info));
529 info->gpr_offset = cum->num_gprs;
530 info->fpr_offset = cum->num_fprs;
532 if (named)
534 loongarch_aggregate_field fields[2];
535 unsigned fregno = fpr_base + info->fpr_offset;
536 unsigned gregno = gpr_base + info->gpr_offset;
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)
544 case 1:
545 return loongarch_pass_fpr_single (mode, fregno,
546 TYPE_MODE (fields[0].type),
547 fields[0].offset);
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);
557 default:
558 gcc_unreachable ();
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))
566 case MODE_FLOAT:
567 return gen_rtx_REG (mode, fregno);
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));
575 default:
576 gcc_unreachable ();
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)
584 info->num_gprs = 1;
585 info->num_fprs = 1;
587 if (!SCALAR_FLOAT_TYPE_P (fields[0].type))
588 std::swap (fregno, gregno);
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);
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;
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;
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;
611 if (info->num_gprs || return_p)
612 return gen_rtx_REG (mode, gpr_base + info->gpr_offset);
614 return NULL_RTX;
617 /* Implement TARGET_FUNCTION_ARG. */
619 static rtx
620 loongarch_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
622 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
623 struct loongarch_arg_info info;
625 if (arg.end_marker_p ())
626 return NULL;
628 return loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named,
629 false);
632 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */
634 static void
635 loongarch_function_arg_advance (cumulative_args_t cum_v,
636 const function_arg_info &arg)
638 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
639 struct loongarch_arg_info info;
641 loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
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;
651 /* Implement TARGET_ARG_PARTIAL_BYTES. */
653 static int
654 loongarch_arg_partial_bytes (cumulative_args_t cum,
655 const function_arg_info &generic_arg)
657 struct loongarch_arg_info arg;
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;
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. */
668 static rtx
669 loongarch_function_value_1 (const_tree type, const_tree func,
670 machine_mode mode)
672 struct loongarch_arg_info info;
673 CUMULATIVE_ARGS args;
675 if (type)
677 int unsigned_p = TYPE_UNSIGNED (type);
679 mode = TYPE_MODE (type);
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);
686 memset (&args, 0, sizeof (args));
687 return loongarch_get_arg_info (&info, &args, mode, type, true, true);
691 /* Implement TARGET_FUNCTION_VALUE. */
693 static rtx
694 loongarch_function_value (const_tree valtype, const_tree fn_decl_or_type,
695 bool outgoing ATTRIBUTE_UNUSED)
697 return loongarch_function_value_1 (valtype, fn_decl_or_type, VOIDmode);
700 /* Implement TARGET_LIBCALL_VALUE. */
702 static rtx
703 loongarch_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
705 return loongarch_function_value_1 (NULL_TREE, NULL_TREE, mode);
709 /* Implement TARGET_PASS_BY_REFERENCE. */
711 static bool
712 loongarch_pass_by_reference (cumulative_args_t cum_v,
713 const function_arg_info &arg)
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);
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)
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;
731 /* Pass by reference if the data do not fit in two integer registers. */
732 return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD);
735 /* Implement TARGET_RETURN_IN_MEMORY. */
737 static bool
738 loongarch_return_in_memory (const_tree type,
739 const_tree fndecl ATTRIBUTE_UNUSED)
741 CUMULATIVE_ARGS args;
742 cumulative_args_t cum = pack_cumulative_args (&args);
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);
751 /* Implement TARGET_SETUP_INCOMING_VARARGS. */
753 static void
754 loongarch_setup_incoming_varargs (cumulative_args_t cum,
755 const function_arg_info &arg,
756 int *pretend_size ATTRIBUTE_UNUSED,
757 int no_rtl)
759 CUMULATIVE_ARGS local_cum;
760 int gp_saved;
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);
768 /* Found out how many registers we need to save. */
769 gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
771 if (!no_rtl && gp_saved > 0)
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 ());
779 move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, mem, gp_saved);
781 if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
782 cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD;
785 /* Make the last instruction frame-related and note that it performs
786 the operation described by FRAME_PATTERN. */
788 static void
789 loongarch_set_frame_expr (rtx frame_pattern)
791 rtx insn;
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));
799 /* Return a frame-related rtx that stores REG at MEM.
800 REG must be a single register. */
802 static rtx
803 loongarch_frame_set (rtx mem, rtx reg)
805 rtx set = gen_rtx_SET (mem, reg);
806 RTX_FRAME_RELATED_P (set) = 1;
807 return set;
810 /* Return true if the current function must save register REGNO. */
812 static bool
813 loongarch_save_reg_p (unsigned int regno)
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);
819 if (call_saved && might_clobber)
820 return true;
822 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
823 return true;
825 if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
826 return true;
828 return false;
831 /* Determine which GPR save/restore routine to call. */
833 static unsigned
834 loongarch_save_libcall_count (unsigned mask)
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 ();
842 /* Populate the current function's loongarch_frame_info structure.
844 LoongArch stack frames grown downward. High addresses are at the top.
846 +-------------------------------+
848 | incoming stack arguments |
850 +-------------------------------+ <-- incoming stack pointer
852 | callee-allocated save area |
853 | for arguments that are |
854 | split between registers and |
855 | the stack |
857 +-------------------------------+ <-- arg_pointer_rtx (virtual)
859 | callee-allocated save area |
860 | for register varargs |
862 +-------------------------------+ <-- hard_frame_pointer_rtx;
863 | | stack_pointer_rtx + gp_sp_offset
864 | GPR save area | + UNITS_PER_WORD
866 +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
867 | | + UNITS_PER_HWVALUE
868 | FPR save area |
870 +-------------------------------+ <-- frame_pointer_rtx (virtual)
872 | local variables |
874 P +-------------------------------+
876 | outgoing stack arguments |
878 +-------------------------------+ <-- stack_pointer_rtx
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. */
884 static void
885 loongarch_compute_frame_info (void)
887 struct loongarch_frame_info *frame;
888 HOST_WIDE_INT offset;
889 unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
891 frame = &cfun->machine->frame;
892 memset (frame, 0, sizeof (*frame));
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++;
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++;
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++;
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)
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);
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;
933 offset += x_save_size;
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. */
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;
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. */
957 HOST_WIDE_INT
958 loongarch_initial_elimination_offset (int from, int to)
960 HOST_WIDE_INT src, dest;
962 loongarch_compute_frame_info ();
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 ();
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 ();
978 return src - dest;
981 /* A function to save or store a register. The first argument is the
982 register and the second is the stack slot. */
983 typedef void (*loongarch_save_restore_fn) (rtx, rtx);
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. */
989 static void
990 loongarch_save_restore_reg (machine_mode mode, int regno, HOST_WIDE_INT offset,
991 loongarch_save_restore_fn fn)
993 rtx mem;
995 mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset));
996 fn (gen_rtx_REG (mode, regno), mem);
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. */
1003 static void
1004 loongarch_for_each_saved_reg (HOST_WIDE_INT sp_offset,
1005 loongarch_save_restore_fn fn)
1007 HOST_WIDE_INT offset;
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))
1014 loongarch_save_restore_reg (word_mode, regno, offset, fn);
1015 offset -= UNITS_PER_WORD;
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))
1024 machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
1026 loongarch_save_restore_reg (mode, regno, offset, fn);
1027 offset -= GET_MODE_SIZE (mode);
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. */
1038 loongarch_emit_move (rtx dest, rtx src)
1040 return (can_create_pseudo_p () ? emit_move_insn (dest, src)
1041 : emit_move_insn_1 (dest, src));
1044 /* Save register REG to MEM. Make the instruction frame-related. */
1046 static void
1047 loongarch_save_reg (rtx reg, rtx mem)
1049 loongarch_emit_move (mem, reg);
1050 loongarch_set_frame_expr (loongarch_frame_set (mem, reg));
1053 /* Restore register REG from MEM. */
1055 static void
1056 loongarch_restore_reg (rtx reg, rtx mem)
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;
1063 RTX_FRAME_RELATED_P (insn) = 1;
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. */
1070 static HOST_WIDE_INT
1071 loongarch_first_stack_step (struct loongarch_frame_info *frame)
1073 if (IMM12_OPERAND (frame->total_size))
1074 return frame->total_size;
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);
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;
1089 return max_first_step;
1092 static void
1093 loongarch_emit_stack_tie (void)
1095 emit_insn (gen_stack_tie (Pmode, stack_pointer_rtx, hard_frame_pointer_rtx));
1098 #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
1100 #if PROBE_INTERVAL > 16384
1101 #error Cannot use indexed addressing mode for stack probing
1102 #endif
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. */
1107 static void
1108 loongarch_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
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)))
1115 HOST_WIDE_INT i;
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)));
1124 emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
1125 -(first + size)));
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
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);
1140 /* Sanity check for the addressing mode we're going to use. */
1141 gcc_assert (first <= 16384);
1144 /* Step 1: round SIZE to the previous multiple of the interval. */
1146 rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
1148 /* TEST_ADDR = SP + FIRST */
1149 if (first != 0)
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)));
1156 else
1157 emit_move_insn (r13, stack_pointer_rtx);
1159 /* Step 2: compute initial and final value of the loop counter. */
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
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
1173 TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
1174 probe at TEST_ADDR
1176 while (TEST_ADDR != LAST_ADDR)
1178 probes at FIRST + N * PROBE_INTERVAL for values of N from 1
1179 until it is equal to ROUNDED_SIZE. */
1181 emit_insn (gen_probe_stack_range (Pmode, r13, r13, r12, r14));
1184 /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
1185 that SIZE is equal to ROUNDED_SIZE. */
1187 if (size != rounded_size)
1189 if (TARGET_64BIT)
1190 emit_stack_probe (plus_constant (Pmode, r12, rounded_size - size));
1191 else
1193 HOST_WIDE_INT i;
1194 for (i = 2048; i < (size - rounded_size); i += 2048)
1196 emit_stack_probe (plus_constant (Pmode, r12, -i));
1197 emit_insn (gen_rtx_SET (r12,
1198 plus_constant (Pmode, r12, -2048)));
1200 rtx r1 = plus_constant (Pmode, r12,
1201 -(size - rounded_size - i + 2048));
1202 emit_stack_probe (r1);
1207 /* Make sure nothing is scheduled before we are done. */
1208 emit_insn (gen_blockage ());
1211 /* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
1212 absolute addresses. */
1213 const char *
1214 loongarch_output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3)
1216 static int labelno = 0;
1217 char loop_lab[32], tmp[64];
1218 rtx xops[3];
1220 ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
1222 /* Loop. */
1223 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
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);
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);
1243 return "";
1246 /* Expand the "prologue" pattern. */
1248 void
1249 loongarch_expand_prologue (void)
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;
1256 if (flag_stack_usage_info)
1257 current_function_static_stack_size = size;
1259 if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
1260 || flag_stack_clash_protection)
1262 if (crtl->is_leaf && !cfun->calls_alloca)
1264 if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
1266 tmp = size - get_stack_check_protect ();
1267 loongarch_emit_probe_stack_range (get_stack_check_protect (),
1268 tmp);
1271 else if (size > 0)
1272 loongarch_emit_probe_stack_range (get_stack_check_protect (), size);
1275 /* Save the registers. */
1276 if ((frame->mask | frame->fmask) != 0)
1278 HOST_WIDE_INT step1 = MIN (size, loongarch_first_stack_step (frame));
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);
1288 /* Set up the frame pointer, if we're using one. */
1289 if (frame_pointer_needed)
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;
1295 loongarch_emit_stack_tie ();
1298 /* Allocate the rest of the frame. */
1299 if (size > 0)
1301 if (IMM12_OPERAND (-size))
1303 insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
1304 GEN_INT (-size));
1305 RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
1307 else
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)));
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);
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. */
1325 bool
1326 loongarch_can_use_return_insn (void)
1328 return reload_completed && cfun->machine->frame.total_size == 0;
1331 /* Expand an "epilogue" or "sibcall_epilogue" pattern; SIBCALL_P
1332 says which. */
1334 void
1335 loongarch_expand_epilogue (bool sibcall_p)
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.
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;
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;
1352 if (!sibcall_p && loongarch_can_use_return_insn ())
1354 emit_jump_insn (gen_return ());
1355 return;
1358 /* Move past any dynamic stack allocations. */
1359 if (cfun->calls_alloca)
1361 /* Emit a barrier to prevent loads from a deallocated stack. */
1362 loongarch_emit_stack_tie ();
1363 need_barrier_p = false;
1365 rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset);
1366 if (!IMM12_OPERAND (INTVAL (adjust)))
1368 loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust);
1369 adjust = LARCH_PROLOGUE_TEMP (Pmode);
1372 insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
1373 hard_frame_pointer_rtx,
1374 adjust));
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);
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;
1386 REG_NOTES (insn) = dwarf;
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)
1393 step2 = loongarch_first_stack_step (frame);
1394 step1 -= step2;
1397 /* Set TARGET to BASE + STEP1. */
1398 if (step1 > 0)
1400 /* Emit a barrier to prevent loads from a deallocated stack. */
1401 loongarch_emit_stack_tie ();
1402 need_barrier_p = false;
1404 /* Get an rtx for STEP1 that we can add to BASE. */
1405 rtx adjust = GEN_INT (step1);
1406 if (!IMM12_OPERAND (step1))
1408 loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust);
1409 adjust = LARCH_PROLOGUE_TEMP (Pmode);
1412 insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
1413 stack_pointer_rtx,
1414 adjust));
1416 rtx dwarf = NULL_RTX;
1417 rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1418 GEN_INT (step2));
1420 dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
1421 RTX_FRAME_RELATED_P (insn) = 1;
1423 REG_NOTES (insn) = dwarf;
1426 /* Restore the registers. */
1427 loongarch_for_each_saved_reg (frame->total_size - step2,
1428 loongarch_restore_reg);
1430 if (need_barrier_p)
1431 loongarch_emit_stack_tie ();
1433 /* Deallocate the final bit of the frame. */
1434 if (step2 > 0)
1436 insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
1437 stack_pointer_rtx,
1438 GEN_INT (step2)));
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;
1445 REG_NOTES (insn) = dwarf;
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));
1453 if (!sibcall_p)
1454 emit_jump_insn (gen_simple_return_internal (ra));
1457 #define LU32I_B (0xfffffULL << 32)
1458 #define LU52I_B (0xfffULL << 52)
1460 /* Fill CODES with a sequence of rtl operations to load VALUE.
1461 Return the number of operations needed. */
1463 static unsigned int
1464 loongarch_build_integer (struct loongarch_integer_op *codes,
1465 HOST_WIDE_INT value)
1468 unsigned int cost = 0;
1470 /* Get the lower 32 bits of the value. */
1471 HOST_WIDE_INT low_part = TARGET_64BIT ? value << 32 >> 32 : value;
1473 if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part))
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++;
1482 else
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)
1492 codes[1].code = IOR;
1493 codes[1].method = METHOD_NORMAL;
1494 codes[1].value = iorv;
1495 cost++;
1499 if (TARGET_64BIT)
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};
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])
1514 codes[cost].method = METHOD_LU52I;
1515 codes[cost].value = (value >> 52) << 52;
1516 return cost + 1;
1519 codes[cost].method = METHOD_LU32I;
1520 codes[cost].value = ((value << 12) >> 44) << 32;
1521 cost++;
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])
1527 codes[cost].method = METHOD_LU52I;
1528 codes[cost].value = (value >> 52) << 52;
1529 cost++;
1533 gcc_assert (cost <= LARCH_MAX_INTEGER_OPS);
1535 return cost;
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. */
1542 static unsigned int
1543 loongarch_integer_cost (HOST_WIDE_INT value)
1545 struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS];
1546 return loongarch_build_integer (codes, value);
1549 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1551 static bool
1552 loongarch_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1554 return loongarch_const_insns (x) > 0;
1557 /* Return true if X is a thread-local symbol. */
1559 static bool
1560 loongarch_tls_symbol_p (rtx x)
1562 return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0;
1565 /* Return true if SYMBOL_REF X is associated with a global symbol
1566 (in the STB_GLOBAL sense). */
1568 bool
1569 loongarch_global_symbol_p (const_rtx x)
1571 if (LABEL_REF_P (x))
1572 return false;
1574 const_tree decl = SYMBOL_REF_DECL (x);
1576 if (!decl)
1577 return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x);
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));
1585 bool
1586 loongarch_global_symbol_noweak_p (const_rtx x)
1588 if (LABEL_REF_P (x))
1589 return false;
1591 const_tree decl = SYMBOL_REF_DECL (x);
1593 if (!decl)
1594 return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x);
1596 return DECL_P (decl) && TREE_PUBLIC (decl);
1599 bool
1600 loongarch_weak_symbol_p (const_rtx x)
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);
1608 /* Return true if SYMBOL_REF X binds locally. */
1610 bool
1611 loongarch_symbol_binds_local_p (const_rtx x)
1613 if (LABEL_REF_P (x))
1614 return false;
1616 return (SYMBOL_REF_DECL (x) ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
1617 : SYMBOL_REF_LOCAL_P (x));
1620 /* Return true if rtx constants of mode MODE should be put into a small
1621 data section. */
1623 static bool
1624 loongarch_rtx_constant_in_small_data_p (machine_mode mode)
1626 return (GET_MODE_SIZE (mode) <= g_switch_value);
1629 /* Return the method that should be used to access SYMBOL_REF or
1630 LABEL_REF X. */
1632 static enum loongarch_symbol_type
1633 loongarch_classify_symbol (const_rtx x)
1635 if (LABEL_REF_P (x))
1636 return SYMBOL_GOT_DISP;
1638 gcc_assert (SYMBOL_REF_P (x));
1640 if (SYMBOL_REF_TLS_MODEL (x))
1641 return SYMBOL_TLS;
1643 if (SYMBOL_REF_P (x))
1644 return SYMBOL_GOT_DISP;
1646 return SYMBOL_GOT_DISP;
1649 /* Return true if X is a symbolic constant. If it is,
1650 store the type of the symbol in *SYMBOL_TYPE. */
1652 bool
1653 loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type)
1655 rtx offset;
1657 split_const (x, &x, &offset);
1658 if (UNSPEC_ADDRESS_P (x))
1660 *symbol_type = UNSPEC_ADDRESS_TYPE (x);
1661 x = UNSPEC_ADDRESS (x);
1663 else if (SYMBOL_REF_P (x) || LABEL_REF_P (x))
1665 *symbol_type = loongarch_classify_symbol (x);
1666 if (*symbol_type == SYMBOL_TLS)
1667 return true;
1669 else
1670 return false;
1672 if (offset == const0_rtx)
1673 return true;
1675 /* Check whether a nonzero offset is valid for the underlying
1676 relocations. */
1677 switch (*symbol_type)
1679 case SYMBOL_GOT_DISP:
1680 case SYMBOL_TLSGD:
1681 case SYMBOL_TLSLDM:
1682 case SYMBOL_TLS:
1683 return false;
1685 gcc_unreachable ();
1688 /* Returns the number of instructions necessary to reference a symbol. */
1690 static int
1691 loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
1693 switch (type)
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;
1701 return 3;
1703 case SYMBOL_TLSGD:
1704 case SYMBOL_TLSLDM:
1705 return 1;
1707 case SYMBOL_TLS:
1708 /* We don't treat a bare TLS symbol as a constant. */
1709 return 0;
1711 gcc_unreachable ();
1714 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1716 static bool
1717 loongarch_cannot_force_const_mem (machine_mode mode, rtx x)
1719 enum loongarch_symbol_type type;
1720 rtx base, offset;
1722 /* As an optimization, reject constants that loongarch_legitimize_move
1723 can expand inline.
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;
1734 split_const (x, &base, &offset);
1735 if (loongarch_symbolic_constant_p (base, &type))
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;
1743 /* TLS symbols must be computed by loongarch_legitimize_move. */
1744 if (tls_referenced_p (x))
1745 return true;
1747 return false;
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. */
1754 loongarch_regno_mode_ok_for_base_p (int regno,
1755 machine_mode mode ATTRIBUTE_UNUSED,
1756 bool strict_p)
1758 if (!HARD_REGISTER_NUM_P (regno))
1760 if (!strict_p)
1761 return true;
1762 regno = reg_renumber[regno];
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;
1771 return GP_REG_P (regno);
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. */
1777 static bool
1778 loongarch_valid_base_register_p (rtx x, machine_mode mode, bool strict_p)
1780 if (!strict_p && SUBREG_P (x))
1781 x = SUBREG_REG (x);
1783 return (REG_P (x)
1784 && loongarch_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p));
1787 /* Return true if, for every base register BASE_REG, (plus BASE_REG X)
1788 can address a value of mode MODE. */
1790 static bool
1791 loongarch_valid_offset_p (rtx x, machine_mode mode)
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;
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;
1808 return true;
1811 static bool
1812 loongarch_valid_index_p (struct loongarch_address_info *info, rtx x,
1813 machine_mode mode, bool strict_p)
1815 rtx index;
1817 if ((REG_P (x) || SUBREG_P (x))
1818 && GET_MODE (x) == Pmode)
1820 index = x;
1822 else
1823 return false;
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);
1830 if (loongarch_valid_base_register_p (index, mode, strict_p))
1832 info->type = ADDRESS_REG_REG;
1833 info->offset = index;
1834 return true;
1837 return false;
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. */
1844 static bool
1845 loongarch_classify_address (struct loongarch_address_info *info, rtx x,
1846 machine_mode mode, bool strict_p)
1848 switch (GET_CODE (x))
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);
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))
1861 info->reg = XEXP (x, 0);
1862 return true;
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))
1868 info->reg = XEXP (x, 1);
1869 return true;
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;
1882 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1884 static bool
1885 loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
1887 struct loongarch_address_info addr;
1889 return loongarch_classify_address (&addr, x, mode, strict_p);
1892 /* Return true if ADDR matches the pattern for the indexed address
1893 instruction. */
1895 static bool
1896 loongarch_index_address_p (rtx addr, machine_mode mode ATTRIBUTE_UNUSED)
1898 if (GET_CODE (addr) != PLUS
1899 || !REG_P (XEXP (addr, 0))
1900 || !REG_P (XEXP (addr, 1)))
1901 return false;
1902 return true;
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. */
1912 loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
1914 struct loongarch_address_info addr;
1915 int factor;
1917 if (!loongarch_classify_address (&addr, x, mode, false))
1918 return 0;
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;
1929 if (loongarch_classify_address (&addr, x, mode, false))
1930 switch (addr.type)
1932 case ADDRESS_REG:
1933 return factor;
1935 case ADDRESS_REG_REG:
1936 return factor;
1938 case ADDRESS_CONST_INT:
1939 return factor;
1941 case ADDRESS_SYMBOLIC:
1942 return factor * loongarch_symbol_insns (addr.symbol_type, mode);
1944 return 0;
1947 /* Return true if X fits within an unsigned field of BITS bits that is
1948 shifted left SHIFT bits before being used. */
1950 bool
1951 loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits,
1952 int shift = 0)
1954 return (x & ((1 << shift) - 1)) == 0 && x < ((unsigned) 1 << (shift + bits));
1957 /* Return true if X fits within a signed field of BITS bits that is
1958 shifted left SHIFT bits before being used. */
1960 bool
1961 loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits,
1962 int shift = 0)
1964 x += 1 << (bits + shift - 1);
1965 return loongarch_unsigned_immediate_p (x, bits, shift);
1968 /* Return true if X is a legitimate address with a 12-bit offset.
1969 MODE is the mode of the value being accessed. */
1971 bool
1972 loongarch_12bit_offset_address_p (rtx x, machine_mode mode)
1974 struct loongarch_address_info addr;
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)));
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. */
1985 bool
1986 loongarch_14bit_shifted_offset_address_p (rtx x, machine_mode mode)
1988 struct loongarch_address_info addr;
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)));
1997 bool
1998 loongarch_base_index_address_p (rtx x, machine_mode mode)
2000 struct loongarch_address_info addr;
2002 return (loongarch_classify_address (&addr, x, mode, false)
2003 && addr.type == ADDRESS_REG_REG
2004 && REG_P (addr.offset));
2007 /* Return the number of instructions needed to load constant X,
2008 Return 0 if X isn't a valid constant. */
2011 loongarch_const_insns (rtx x)
2013 enum loongarch_symbol_type symbol_type;
2014 rtx offset;
2016 switch (GET_CODE (x))
2018 case CONST_INT:
2019 return loongarch_integer_cost (INTVAL (x));
2021 case CONST_VECTOR:
2022 /* Fall through. */
2023 case CONST_DOUBLE:
2024 return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0;
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);
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)
2042 int n = loongarch_const_insns (x);
2043 if (n != 0)
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));
2051 return 0;
2053 case SYMBOL_REF:
2054 case LABEL_REF:
2055 return loongarch_symbol_insns (
2056 loongarch_classify_symbol (x), MAX_MACHINE_MODE);
2058 default:
2059 return 0;
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. */
2068 loongarch_split_const_insns (rtx x)
2070 unsigned int low, high;
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;
2078 /* Return the number of instructions needed to implement INSN,
2079 given that it loads from or stores to MEM. */
2082 loongarch_load_store_insns (rtx mem, rtx_insn *insn)
2084 machine_mode mode;
2085 bool might_split_p;
2086 rtx set;
2088 gcc_assert (MEM_P (mem));
2089 mode = GET_MODE (mem);
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)
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;
2101 return loongarch_address_insns (XEXP (mem, 0), mode, might_split_p);
2104 /* Return the number of instructions needed for an integer division. */
2107 loongarch_idiv_insns (machine_mode mode ATTRIBUTE_UNUSED)
2109 int count;
2111 count = 1;
2112 if (TARGET_CHECK_ZERO_DIV)
2113 count += 2;
2115 return count;
2118 /* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */
2120 void
2121 loongarch_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
2123 emit_insn (gen_rtx_SET (target, gen_rtx_fmt_ee (code, GET_MODE (target),
2124 op0, op1)));
2127 /* Compute (CODE OP0 OP1) and store the result in a new register
2128 of mode MODE. Return that new register. */
2130 static rtx
2131 loongarch_force_binary (machine_mode mode, enum rtx_code code, rtx op0,
2132 rtx op1)
2134 rtx reg;
2136 reg = gen_reg_rtx (mode);
2137 loongarch_emit_binary (code, reg, op0, op1);
2138 return reg;
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. */
2144 static rtx
2145 loongarch_force_temporary (rtx dest, rtx value)
2147 if (can_create_pseudo_p ())
2148 return force_reg (Pmode, value);
2149 else
2151 loongarch_emit_move (dest, value);
2152 return dest;
2156 /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
2157 then add CONST_INT OFFSET to the result. */
2159 static rtx
2160 loongarch_unspec_address_offset (rtx base, rtx offset,
2161 enum loongarch_symbol_type symbol_type)
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);
2170 /* Return an UNSPEC address with underlying address ADDRESS and symbol
2171 type SYMBOL_TYPE. */
2174 loongarch_unspec_address (rtx address, enum loongarch_symbol_type symbol_type)
2176 rtx base, offset;
2178 split_const (address, &base, &offset);
2179 return loongarch_unspec_address_offset (base, offset, symbol_type);
2182 /* If OP is an UNSPEC address, return the address to which it refers,
2183 otherwise return OP itself. */
2186 loongarch_strip_unspec_address (rtx op)
2188 rtx base, offset;
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;
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. */
2200 static rtx
2201 loongarch_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
2203 if (!IMM12_OPERAND (offset))
2205 rtx high;
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));
2215 return plus_constant (Pmode, reg, offset);
2218 /* The __tls_get_attr symbol. */
2219 static GTY (()) rtx loongarch_tls_symbol;
2221 /* Load an entry from the GOT for a TLS GD access. */
2223 static rtx
2224 loongarch_got_load_tls_gd (rtx dest, rtx sym)
2226 return gen_got_load_tls_gd (Pmode, dest, sym);
2229 /* Load an entry from the GOT for a TLS LD access. */
2231 static rtx
2232 loongarch_got_load_tls_ld (rtx dest, rtx sym)
2234 return gen_got_load_tls_ld (Pmode, dest, sym);
2237 /* Load an entry from the GOT for a TLS IE access. */
2239 static rtx
2240 loongarch_got_load_tls_ie (rtx dest, rtx sym)
2242 return gen_got_load_tls_ie (Pmode, dest, sym);
2245 /* Add in the thread pointer for a TLS LE access. */
2247 static rtx
2248 loongarch_got_load_tls_le (rtx dest, rtx sym)
2250 return gen_got_load_tls_le (Pmode, dest, sym);
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. */
2258 static rtx_insn *
2259 loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
2261 rtx loc, a0;
2262 rtx_insn *insn;
2264 a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
2266 if (!loongarch_tls_symbol)
2267 loongarch_tls_symbol = init_one_libfunc ("__tls_get_addr");
2269 loc = loongarch_unspec_address (sym, type);
2271 start_sequence ();
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 ();
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 ();
2286 end_sequence ();
2288 return insn;
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). */
2295 static rtx
2296 loongarch_legitimize_tls_address (rtx loc)
2298 rtx dest, tp, tmp;
2299 enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
2300 rtx_insn *insn;
2302 switch (model)
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;
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;
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;
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;
2336 default:
2337 gcc_unreachable ();
2339 return dest;
2343 loongarch_legitimize_call_address (rtx addr)
2345 if (!call_insn_operand (addr, VOIDmode))
2347 rtx reg = gen_reg_rtx (Pmode);
2348 loongarch_emit_move (reg, addr);
2349 return reg;
2351 return addr;
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. */
2357 static void
2358 loongarch_split_plus (rtx x, rtx *base_ptr, HOST_WIDE_INT *offset_ptr)
2360 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2362 *base_ptr = XEXP (x, 0);
2363 *offset_ptr = INTVAL (XEXP (x, 1));
2365 else
2367 *base_ptr = x;
2368 *offset_ptr = 0;
2372 /* If X is not a valid address for mode MODE, force it into a register. */
2374 static rtx
2375 loongarch_force_address (rtx x, machine_mode mode)
2377 if (!loongarch_legitimate_address_p (mode, x, false))
2378 x = force_reg (Pmode, x);
2379 return x;
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. */
2387 static rtx
2388 loongarch_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
2389 machine_mode mode)
2391 rtx base, addr;
2392 HOST_WIDE_INT offset;
2394 if (loongarch_tls_symbol_p (x))
2395 return loongarch_legitimize_tls_address (x);
2397 /* Handle BASE + OFFSET using loongarch_add_offset. */
2398 loongarch_split_plus (x, &base, &offset);
2399 if (offset != 0)
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);
2407 return x;
2410 /* Load VALUE into DEST. TEMP is as for loongarch_force_temporary. */
2412 void
2413 loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value)
2415 struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS];
2416 machine_mode mode;
2417 unsigned int i, num_ops;
2418 rtx x;
2420 mode = GET_MODE (dest);
2421 num_ops = loongarch_build_integer (codes, value);
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++)
2428 if (!can_create_pseudo_p ())
2430 emit_insn (gen_rtx_SET (temp, x));
2431 x = temp;
2433 else
2434 x = force_reg (mode, x);
2436 switch (codes[i].method)
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 ();
2465 emit_insn (gen_rtx_SET (dest, x));
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. */
2472 static void
2473 loongarch_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
2475 rtx base, offset;
2477 /* Split moves of big integers into smaller pieces. */
2478 if (splittable_const_int_operand (src, mode))
2480 loongarch_move_integer (dest, dest, INTVAL (src));
2481 return;
2484 /* Generate the appropriate access sequences for TLS symbols. */
2485 if (loongarch_tls_symbol_p (src))
2487 loongarch_emit_move (dest, loongarch_legitimize_tls_address (src));
2488 return;
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 ())))
2500 base = loongarch_force_temporary (dest, base);
2501 loongarch_emit_move (dest,
2502 loongarch_add_offset (NULL, base, INTVAL (offset)));
2503 return;
2506 src = force_const_mem (mode, src);
2508 loongarch_emit_move (dest, src);
2511 /* If (set DEST SRC) is not a valid move instruction, emit an equivalent
2512 sequence that is valid. */
2514 bool
2515 loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src)
2517 if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
2519 loongarch_emit_move (dest, force_reg (mode, src));
2520 return true;
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.
2526 if (!register_operand (dest, mode) && !register_operand (src, mode)
2527 && !const_0_operand (src, mode))
2529 loongarch_emit_move (dest, force_reg (mode, src));
2530 return true;
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))
2537 loongarch_legitimize_const_move (mode, dest, src);
2538 set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
2539 return true;
2542 return false;
2545 /* Return true if OP refers to small data symbols directly. */
2547 static int
2548 loongarch_small_data_pattern_1 (rtx x)
2550 subrtx_var_iterator::array_type array;
2551 FOR_EACH_SUBRTX_VAR (iter, array, x, ALL)
2553 rtx x = *iter;
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))
2561 if (loongarch_small_data_pattern_1 (XEXP (x, 0)))
2562 return true;
2563 iter.skip_subrtxes ();
2566 return false;
2569 /* Return true if OP refers to small data symbols directly. */
2571 bool
2572 loongarch_small_data_pattern_p (rtx op)
2574 return loongarch_small_data_pattern_1 (op);
2577 /* Rewrite *LOC so that it refers to small data using explicit
2578 relocations. */
2580 static void
2581 loongarch_rewrite_small_data_1 (rtx *loc)
2583 subrtx_ptr_iterator::array_type array;
2584 FOR_EACH_SUBRTX_PTR (iter, array, loc, ALL)
2586 rtx *loc = *iter;
2587 if (MEM_P (*loc))
2589 loongarch_rewrite_small_data_1 (&XEXP (*loc, 0));
2590 iter.skip_subrtxes ();
2595 /* Rewrite instruction pattern PATTERN so that it refers to small data
2596 using explicit relocations. */
2599 loongarch_rewrite_small_data (rtx pattern)
2601 pattern = copy_insn (pattern);
2602 loongarch_rewrite_small_data_1 (&pattern);
2603 return pattern;
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)
2610 /* Return true if there is a instruction that implements CODE
2611 and if that instruction accepts X as an immediate operand. */
2613 static int
2614 loongarch_immediate_operand_p (int code, HOST_WIDE_INT x)
2616 switch (code)
2618 case ASHIFT:
2619 case ASHIFTRT:
2620 case LSHIFTRT:
2621 /* All shift counts are truncated to a valid constant. */
2622 return true;
2624 case ROTATE:
2625 case ROTATERT:
2626 return true;
2628 case AND:
2629 case IOR:
2630 case XOR:
2631 /* These instructions take 12-bit unsigned immediates. */
2632 return IMM12_OPERAND_UNSIGNED (x);
2634 case PLUS:
2635 case LT:
2636 case LTU:
2637 /* These instructions take 12-bit signed immediates. */
2638 return IMM12_OPERAND (x);
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;
2648 case GE:
2649 case GEU:
2650 /* Likewise, meaning that the only valid immediate operand is 1. */
2651 return x == 1;
2653 case LE:
2654 /* We add 1 to the immediate and use SLT. */
2655 return IMM12_OPERAND (x + 1);
2657 case LEU:
2658 /* Likewise SLTU, but reject the always-true case. */
2659 return IMM12_OPERAND (x + 1) && x + 1 != 0;
2661 case SIGN_EXTRACT:
2662 case ZERO_EXTRACT:
2663 /* The bit position and size are immediate operands. */
2664 return 1;
2666 default:
2667 /* By default assume that $0 can be used for 0. */
2668 return x == 0;
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. */
2677 static int
2678 loongarch_binary_cost (rtx x, int single_cost, int double_cost, bool speed)
2680 int cost;
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));
2691 /* Return the cost of floating-point multiplications of mode MODE. */
2693 static int
2694 loongarch_fp_mult_cost (machine_mode mode)
2696 return mode == DFmode ? loongarch_cost->fp_mult_df
2697 : loongarch_cost->fp_mult_sf;
2700 /* Return the cost of floating-point divisions of mode MODE. */
2702 static int
2703 loongarch_fp_div_cost (machine_mode mode)
2705 return mode == DFmode ? loongarch_cost->fp_div_df
2706 : loongarch_cost->fp_div_sf;
2709 /* Return the cost of sign-extending OP to mode MODE, not including the
2710 cost of OP itself. */
2712 static int
2713 loongarch_sign_extend_cost (rtx op)
2715 if (MEM_P (op))
2716 /* Extended loads are as cheap as unextended ones. */
2717 return 0;
2719 return COSTS_N_INSNS (1);
2722 /* Return the cost of zero-extending OP to mode MODE, not including the
2723 cost of OP itself. */
2725 static int
2726 loongarch_zero_extend_cost (rtx op)
2728 if (MEM_P (op))
2729 /* Extended loads are as cheap as unextended ones. */
2730 return 0;
2732 /* We can use ANDI. */
2733 return COSTS_N_INSNS (1);
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. */
2739 static int
2740 loongarch_set_reg_reg_piece_cost (machine_mode mode, unsigned int units)
2742 return COSTS_N_INSNS ((GET_MODE_SIZE (mode) + units - 1) / units);
2745 /* Return the cost of moving between two registers of mode MODE. */
2747 static int
2748 loongarch_set_reg_reg_cost (machine_mode mode)
2750 switch (GET_MODE_CLASS (mode))
2752 case MODE_CC:
2753 return loongarch_set_reg_reg_piece_cost (mode, GET_MODE_SIZE (CCmode));
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. */
2762 default:
2763 return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_WORD);
2767 /* Implement TARGET_RTX_COSTS. */
2769 static bool
2770 loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code,
2771 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
2773 int code = GET_CODE (x);
2774 bool float_mode_p = FLOAT_MODE_P (mode);
2775 int cost;
2776 rtx addr;
2778 if (outer_code == COMPARE)
2780 gcc_assert (CONSTANT_P (x));
2781 *total = 0;
2782 return true;
2785 switch (code)
2787 case CONST_INT:
2788 if (TARGET_64BIT && outer_code == AND && UINTVAL (x) == 0xffffffff)
2790 *total = 0;
2791 return true;
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)))
2801 *total = 0;
2802 return true;
2804 /* Fall through. */
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)
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;
2821 /* The value will need to be fetched from the constant pool. */
2822 *total = CONSTANT_POOL_COST;
2823 return true;
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))
2832 *total = COSTS_N_INSNS (2);
2833 return true;
2835 cost = loongarch_address_insns (addr, mode, true);
2836 if (cost > 0)
2838 *total = COSTS_N_INSNS (cost + 1);
2839 return true;
2841 /* Otherwise use the default handling. */
2842 return false;
2844 case FFS:
2845 *total = COSTS_N_INSNS (6);
2846 return false;
2848 case NOT:
2849 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
2850 return false;
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)
2858 *total = (loongarch_zero_extend_cost (XEXP (x, 0))
2859 + set_src_cost (XEXP (x, 0), mode, speed));
2860 return true;
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)
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;
2873 /* Fall through. */
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;
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;
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;
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))
2923 *total = loongarch_cost->fp_add;
2924 return false;
2926 *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
2927 speed);
2928 return true;
2930 case MINUS:
2931 case PLUS:
2932 if (float_mode_p)
2934 *total = loongarch_cost->fp_add;
2935 return false;
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)
2943 rtx op2 = XEXP (XEXP (x, 0), 1);
2944 if (const_immalsl_operand (op2, mode))
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;
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;
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;
2966 case FMA:
2967 *total = loongarch_fp_mult_cost (mode);
2968 return false;
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;
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))
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;
3000 /* Fall through. */
3002 case SQRT:
3003 case MOD:
3004 if (float_mode_p)
3006 *total = loongarch_fp_div_cost (mode);
3007 return false;
3009 /* Fall through. */
3011 case UDIV:
3012 case UMOD:
3013 if (!speed)
3015 *total = COSTS_N_INSNS (loongarch_idiv_insns (mode));
3017 else if (mode == DImode)
3018 *total = loongarch_cost->int_div_di;
3019 else
3020 *total = loongarch_cost->int_div_si;
3021 return false;
3023 case SIGN_EXTEND:
3024 *total = loongarch_sign_extend_cost (XEXP (x, 0));
3025 return false;
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:
3033 (lshiftrt:DI (mult:DI (sign_extend:DI (...)
3034 (sign_extend:DI (...))
3035 (const_int 32)
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))))
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;
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)
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);
3073 return true;
3075 return false;
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;
3085 case SET:
3086 if (register_operand (SET_DEST (x), VOIDmode)
3087 && reg_or_0_operand (SET_SRC (x), VOIDmode))
3089 *total = loongarch_set_reg_reg_cost (GET_MODE (SET_DEST (x)));
3090 return true;
3092 return false;
3094 default:
3095 return false;
3099 /* Implement TARGET_ADDRESS_COST. */
3101 static int
3102 loongarch_address_cost (rtx addr, machine_mode mode,
3103 addr_space_t as ATTRIBUTE_UNUSED,
3104 bool speed ATTRIBUTE_UNUSED)
3106 return loongarch_address_insns (addr, mode, false);
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. */
3114 loongarch_subword (rtx op, bool high_p)
3116 unsigned int byte;
3117 machine_mode mode;
3119 byte = high_p ? UNITS_PER_WORD : 0;
3120 mode = GET_MODE (op);
3121 if (mode == VOIDmode)
3122 mode = TARGET_64BIT ? TImode : DImode;
3124 if (FP_REG_RTX_P (op))
3125 return gen_rtx_REG (word_mode, REGNO (op) + high_p);
3127 if (MEM_P (op))
3128 return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte));
3130 return simplify_gen_subreg (word_mode, op, mode, byte);
3133 /* Return true if a move from SRC to DEST should be split into two.
3134 SPLIT_TYPE describes the split condition. */
3136 bool
3137 loongarch_split_move_p (rtx dest, rtx src)
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;
3145 /* Check for floating-point loads and stores. */
3146 if (size == 8)
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;
3153 /* Otherwise split all multiword moves. */
3154 return size > UNITS_PER_WORD;
3157 /* Split a move from SRC to DEST, given that loongarch_split_move_p holds.
3158 SPLIT_TYPE describes the split condition. */
3160 void
3161 loongarch_split_move (rtx dest, rtx src, rtx insn_)
3163 rtx low_dest;
3165 gcc_checking_assert (loongarch_split_move_p (dest, src));
3166 if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
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 ();
3177 else
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))
3184 loongarch_emit_move (loongarch_subword (dest, true),
3185 loongarch_subword (src, true));
3186 loongarch_emit_move (low_dest, loongarch_subword (src, false));
3188 else
3190 loongarch_emit_move (low_dest, loongarch_subword (src, false));
3191 loongarch_emit_move (loongarch_subword (dest, true),
3192 loongarch_subword (src, true));
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)
3203 rtx_insn *next = next_nonnote_nondebug_insn_bb (insn);
3204 if (next)
3206 rtx set = single_set (next);
3207 if (set && SET_SRC (set) == dest)
3209 if (MEM_P (src))
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);
3217 else
3218 validate_change (next, &SET_SRC (set), src, false);
3224 /* Return true if a move from SRC to DEST in INSN should be split. */
3226 bool
3227 loongarch_split_move_insn_p (rtx dest, rtx src)
3229 return loongarch_split_move_p (dest, src);
3232 /* Split a move from SRC to DEST in INSN, given that
3233 loongarch_split_move_insn_p holds. */
3235 void
3236 loongarch_split_move_insn (rtx dest, rtx src, rtx insn)
3238 loongarch_split_move (dest, src, insn);
3241 /* Implement TARGET_CONSTANT_ALIGNMENT. */
3243 static HOST_WIDE_INT
3244 loongarch_constant_alignment (const_tree exp, HOST_WIDE_INT align)
3246 if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR)
3247 return MAX (align, BITS_PER_WORD);
3248 return align;
3251 const char *
3252 loongarch_output_move_index (rtx x, machine_mode mode, bool ldr)
3254 int index = exact_log2 (GET_MODE_SIZE (mode));
3255 if (!IN_RANGE (index, 0, 3))
3256 return NULL;
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;
3264 const char *const insn[][4] =
3267 "stx.b\t%z1,%0",
3268 "stx.h\t%z1,%0",
3269 "stx.w\t%z1,%0",
3270 "stx.d\t%z1,%0",
3273 "ldx.bu\t%0,%1",
3274 "ldx.hu\t%0,%1",
3275 "ldx.w\t%0,%1",
3276 "ldx.d\t%0,%1",
3280 return insn[ldr][index];
3283 const char *
3284 loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr)
3286 int index = exact_log2 (GET_MODE_SIZE (mode));
3287 if (!IN_RANGE (index, 2, 3))
3288 return NULL;
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;
3296 const char *const insn[][2] =
3299 "fstx.s\t%1,%0",
3300 "fstx.d\t%1,%0"
3303 "fldx.s\t%0,%1",
3304 "fldx.d\t%0,%1"
3308 return insn[ldr][index-2];
3311 /* Return the appropriate instructions to move SRC into DEST. Assume
3312 that SRC is operand 1 and DEST is operand 0. */
3314 const char *
3315 loongarch_output_move (rtx dest, rtx src)
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);
3322 if (loongarch_split_move_p (dest, src))
3323 return "#";
3325 if ((src_code == REG && GP_REG_P (REGNO (src)))
3326 || (src == CONST0_RTX (mode)))
3328 if (dest_code == REG)
3330 if (GP_REG_P (REGNO (dest)))
3331 return "or\t%0,%z1,$r0";
3333 if (FP_REG_P (REGNO (dest)))
3334 return dbl_p ? "movgr2fr.d\t%0,%z1" : "movgr2fr.w\t%0,%z1";
3336 if (dest_code == MEM)
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;
3344 rtx offset = XEXP (dest, 0);
3345 if (GET_CODE (offset) == PLUS)
3346 offset = XEXP (offset, 1);
3347 switch (GET_MODE_SIZE (mode))
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 ();
3368 if (dest_code == REG && GP_REG_P (REGNO (dest)))
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";
3374 if (src_code == MEM)
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;
3382 rtx offset = XEXP (src, 0);
3383 if (GET_CODE (offset) == PLUS)
3384 offset = XEXP (offset, 1);
3385 switch (GET_MODE_SIZE (mode))
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 ();
3406 if (src_code == CONST_INT)
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 ();
3420 if (symbolic_operand (src, VOIDmode))
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)))
3426 /* The symbol must be aligned to 4 byte. */
3427 unsigned int align;
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))
3435 tree exp = SYMBOL_REF_DECL (src);
3436 align = TYPE_ALIGN (TREE_TYPE (exp));
3437 align = loongarch_constant_alignment (exp, align);
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;
3447 if (align % (4 * 8) == 0)
3448 return "pcaddi\t%0,%%pcrel(%1)>>2";
3450 if (TARGET_CMODEL_TINY
3451 || TARGET_CMODEL_TINY_STATIC
3452 || TARGET_CMODEL_NORMAL
3453 || TARGET_CMODEL_LARGE)
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";
3461 if (TARGET_CMODEL_EXTREME)
3463 sorry ("Normal symbol loading not implemented in extreme mode.");
3464 gcc_unreachable ();
3469 if (src_code == REG && FP_REG_P (REGNO (src)))
3471 if (dest_code == REG && FP_REG_P (REGNO (dest)))
3472 return dbl_p ? "fmov.d\t%0,%1" : "fmov.s\t%0,%1";
3474 if (dest_code == MEM)
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;
3483 return dbl_p ? "fst.d\t%1,%0" : "fst.s\t%1,%0";
3486 if (dest_code == REG && FP_REG_P (REGNO (dest)))
3488 if (src_code == MEM)
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;
3497 return dbl_p ? "fld.d\t%0,%1" : "fld.s\t%0,%1";
3500 gcc_unreachable ();
3503 /* Return true if CMP1 is a suitable second operand for integer ordering
3504 test CODE. */
3506 static bool
3507 loongarch_int_order_operand_ok_p (enum rtx_code code, rtx cmp1)
3509 switch (code)
3511 case GT:
3512 case GTU:
3513 return reg_or_0_operand (cmp1, VOIDmode);
3515 case GE:
3516 case GEU:
3517 return cmp1 == const1_rtx;
3519 case LT:
3520 case LTU:
3521 return arith_operand (cmp1, VOIDmode);
3523 case LE:
3524 return sle_operand (cmp1, VOIDmode);
3526 case LEU:
3527 return sleu_operand (cmp1, VOIDmode);
3529 default:
3530 gcc_unreachable ();
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. */
3540 static bool
3541 loongarch_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1,
3542 machine_mode mode)
3544 HOST_WIDE_INT plus_one;
3546 if (loongarch_int_order_operand_ok_p (*code, *cmp1))
3547 return true;
3549 if (CONST_INT_P (*cmp1))
3550 switch (*code)
3552 case LE:
3553 plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
3554 if (INTVAL (*cmp1) < plus_one)
3556 *code = LT;
3557 *cmp1 = force_reg (mode, GEN_INT (plus_one));
3558 return true;
3560 break;
3562 case LEU:
3563 plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
3564 if (plus_one != 0)
3566 *code = LTU;
3567 *cmp1 = force_reg (mode, GEN_INT (plus_one));
3568 return true;
3570 break;
3572 default:
3573 break;
3575 return false;
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. */
3583 static void
3584 loongarch_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
3585 rtx target, rtx cmp0, rtx cmp1)
3587 machine_mode mode;
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
3597 enum rtx_code inv_code = reverse_condition (code);
3598 if (!loongarch_canonicalize_int_order_test (&inv_code, &cmp1, mode))
3600 cmp1 = force_reg (mode, cmp1);
3601 loongarch_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1);
3603 else if (invert_ptr == 0)
3605 rtx inv_target;
3607 inv_target = loongarch_force_binary (GET_MODE (target),
3608 inv_code, cmp0, cmp1);
3609 loongarch_emit_binary (XOR, target, inv_target, const1_rtx);
3611 else
3613 *invert_ptr = !*invert_ptr;
3614 loongarch_emit_binary (inv_code, target, cmp0, cmp1);
3619 /* Return a register that is zero if CMP0 and CMP1 are equal.
3620 The register will have the same mode as CMP0. */
3622 static rtx
3623 loongarch_zero_if_equal (rtx cmp0, rtx cmp1)
3625 if (cmp1 == const0_rtx)
3626 return cmp0;
3628 if (uns_arith_operand (cmp1, VOIDmode))
3629 return expand_binop (GET_MODE (cmp0), xor_optab, cmp0, cmp1, 0, 0,
3630 OPTAB_DIRECT);
3632 return expand_binop (GET_MODE (cmp0), sub_optab, cmp0, cmp1, 0, 0,
3633 OPTAB_DIRECT);
3636 /* Allocate a floating-point condition-code register of mode MODE. */
3638 static rtx
3639 loongarch_allocate_fcc (machine_mode mode)
3641 unsigned int regno, count;
3643 gcc_assert (TARGET_HARD_FLOAT);
3645 if (mode == FCCmode)
3646 count = 1;
3647 else
3648 gcc_unreachable ();
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;
3654 regno = FCC_REG_FIRST + cfun->machine->next_fcc;
3655 cfun->machine->next_fcc += count;
3656 return gen_rtx_REG (mode, regno);
3659 /* Sign- or zero-extend OP0 and OP1 for integer comparisons. */
3661 static void
3662 loongarch_extend_comparands (rtx_code code, rtx *op0, rtx *op1)
3664 /* Comparisons consider all XLEN bits, so extend sub-XLEN values. */
3665 if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0)))
3667 /* TODO: checkout It is more profitable to zero-extend QImode values. */
3668 if (unsigned_condition (code) == code && GET_MODE (*op0) == QImode)
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);
3676 else
3678 *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0);
3679 if (*op1 != const0_rtx)
3680 *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1);
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. */
3689 static void
3690 loongarch_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1)
3692 static const enum rtx_code
3693 mag_comparisons[][2] = {{LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE}};
3695 if (splittable_const_int_operand (*op1, VOIDmode))
3697 HOST_WIDE_INT rhs = INTVAL (*op1);
3699 if (*code == EQ || *code == NE)
3701 /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */
3702 if (IMM12_OPERAND (-rhs))
3704 *op0 = loongarch_force_binary (GET_MODE (*op0), PLUS, *op0,
3705 GEN_INT (-rhs));
3706 *op1 = const0_rtx;
3709 else
3711 /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000). */
3712 for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++)
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;
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))
3725 *op1 = GEN_INT (new_rhs);
3726 *code = mag_comparisons[i][increment];
3728 break;
3733 loongarch_extend_comparands (*code, op0, op1);
3735 *op0 = force_reg (word_mode, *op0);
3736 if (*op1 != const0_rtx)
3737 *op1 = force_reg (word_mode, *op1);
3740 /* Like loongarch_emit_int_compare, but for floating-point comparisons. */
3742 static void
3743 loongarch_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
3745 rtx cmp_op0 = *op0;
3746 rtx cmp_op1 = *op1;
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.
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);
3761 *op1 = const0_rtx;
3762 loongarch_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
3765 /* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
3766 and OPERAND[3]. Store the result in OPERANDS[0].
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. */
3771 void
3772 loongarch_expand_scc (rtx operands[])
3774 rtx target = operands[0];
3775 enum rtx_code code = GET_CODE (operands[1]);
3776 rtx op0 = operands[2];
3777 rtx op1 = operands[3];
3779 loongarch_extend_comparands (code, &op0, &op1);
3780 op0 = force_reg (word_mode, op0);
3782 gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT);
3784 if (code == EQ || code == NE)
3786 rtx zie = loongarch_zero_if_equal (op0, op1);
3787 loongarch_emit_binary (code, target, zie, const0_rtx);
3789 else
3790 loongarch_emit_int_order_test (code, 0, target, op0, op1);
3793 /* Compare OPERANDS[1] with OPERANDS[2] using comparison code
3794 CODE and jump to OPERANDS[3] if the condition holds. */
3796 void
3797 loongarch_expand_conditional_branch (rtx *operands)
3799 enum rtx_code code = GET_CODE (operands[0]);
3800 rtx op0 = operands[1];
3801 rtx op1 = operands[2];
3802 rtx condition;
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);
3809 condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3810 emit_jump_insn (gen_condjump (condition, operands[3]));
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]. */
3816 void
3817 loongarch_expand_conditional_move (rtx *operands)
3819 enum rtx_code code = GET_CODE (operands[1]);
3820 rtx op0 = XEXP (operands[1], 0);
3821 rtx op1 = XEXP (operands[1], 1);
3823 if (FLOAT_MODE_P (GET_MODE (op1)))
3824 loongarch_emit_float_compare (&code, &op0, &op1);
3825 else
3827 loongarch_extend_comparands (code, &op0, &op1);
3829 op0 = force_reg (word_mode, op0);
3831 if (code == EQ || code == NE)
3833 op0 = loongarch_zero_if_equal (op0, op1);
3834 op1 = const0_rtx;
3836 else
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;
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))
3856 machine_mode mode = GET_MODE (operands[0]);
3857 rtx temp = gen_reg_rtx (mode);
3858 rtx temp2 = gen_reg_rtx (mode);
3860 emit_insn (gen_rtx_SET (temp,
3861 gen_rtx_IF_THEN_ELSE (mode, cond,
3862 operands[2], const0_rtx)));
3864 /* Flip the test for the second operand. */
3865 cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, GET_MODE (op0), op0, op1);
3867 emit_insn (gen_rtx_SET (temp2,
3868 gen_rtx_IF_THEN_ELSE (mode, cond,
3869 operands[3], const0_rtx)));
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)));
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])));
3880 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */
3882 static void
3883 loongarch_va_start (tree valist, rtx nextarg)
3885 nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size);
3886 std_expand_builtin_va_start (valist, nextarg);
3889 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
3891 static bool
3892 loongarch_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
3893 tree exp ATTRIBUTE_UNUSED)
3895 /* Always OK. */
3896 return true;
3899 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
3900 Assume that the areas do not overlap. */
3902 static void
3903 loongarch_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
3905 HOST_WIDE_INT offset, delta;
3906 unsigned HOST_WIDE_INT bits;
3907 int i;
3908 machine_mode mode;
3909 rtx *regs;
3911 bits = MIN (BITS_PER_WORD, MIN (MEM_ALIGN (src), MEM_ALIGN (dest)));
3913 mode = int_mode_for_size (bits, 0).require ();
3914 delta = bits / BITS_PER_UNIT;
3916 /* Allocate a buffer for the temporary registers. */
3917 regs = XALLOCAVEC (rtx, length / delta);
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++)
3923 regs[i] = gen_reg_rtx (mode);
3924 loongarch_emit_move (regs[i], adjust_address (src, mode, offset));
3927 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
3928 loongarch_emit_move (adjust_address (dest, mode, offset), regs[i]);
3930 /* Mop up any left-over bytes. */
3931 if (offset < length)
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);
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.
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. */
3949 static void
3950 loongarch_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg,
3951 rtx *loop_mem)
3953 *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
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));
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. */
3965 static void
3966 loongarch_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
3967 HOST_WIDE_INT bytes_per_iter)
3969 rtx_code_label *label;
3970 rtx src_reg, dest_reg, final_src, test;
3971 HOST_WIDE_INT leftover;
3973 leftover = length % bytes_per_iter;
3974 length -= leftover;
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);
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);
3985 /* Emit the start of the loop. */
3986 label = gen_label_rtx ();
3987 emit_label (label);
3989 /* Emit the loop body. */
3990 loongarch_block_move_straight (dest, src, bytes_per_iter);
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));
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));
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 ());
4013 /* Expand a cpymemsi instruction, which copies LENGTH bytes from
4014 memory reference SRC to memory reference DEST. */
4016 bool
4017 loongarch_expand_block_move (rtx dest, rtx src, rtx length)
4019 int max_move_bytes = LARCH_MAX_MOVE_BYTES_STRAIGHT;
4021 if (CONST_INT_P (length)
4022 && INTVAL (length) <= loongarch_max_inline_memcpy_size)
4024 if (INTVAL (length) <= max_move_bytes)
4026 loongarch_block_move_straight (dest, src, INTVAL (length));
4027 return true;
4029 else if (optimize)
4031 loongarch_block_move_loop (dest, src, INTVAL (length),
4032 LARCH_MAX_MOVE_BYTES_PER_LOOP_ITER);
4033 return true;
4036 return false;
4039 /* Return true if loongarch_expand_block_move is the preferred
4040 implementation of the 'cpymemsi' template. */
4042 bool
4043 loongarch_do_optimize_block_move_p (void)
4045 /* if -m[no-]memcpy is given explicitly. */
4046 if (target_flags_explicit & MASK_MEMCPY)
4047 return !TARGET_MEMCPY;
4049 /* if not, don't optimize under -Os. */
4050 return !optimize_size;
4054 /* Expand a QI or HI mode atomic memory operation.
4056 GENERATOR contains a pointer to the gen_* function that generates
4057 the SI mode underlying atomic operation using masks that we
4058 calculate.
4060 RESULT is the return register for the operation. Its value is NULL
4061 if unused.
4063 MEM is the location of the atomic access.
4065 OLDVAL is the first operand for the operation.
4067 NEWVAL is the optional second operand for the operation. Its value
4068 is NULL if unused. */
4070 void
4071 loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs generator,
4072 rtx result, rtx mem, rtx oldval, rtx newval,
4073 rtx model)
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;
4080 mode = GET_MODE (mem);
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)));
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);
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));
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));
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);
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)));
4111 /* Shift the old value into place. */
4112 if (oldval != const0_rtx)
4114 oldval = convert_modes (SImode, mode, oldval, true);
4115 oldval = force_reg (SImode, oldval);
4116 oldval = loongarch_force_binary (SImode, ASHIFT, oldval, shiftsi);
4119 /* Do the same for the new value. */
4120 if (newval && newval != const0_rtx)
4122 newval = convert_modes (SImode, mode, newval, true);
4123 newval = force_reg (SImode, newval);
4124 newval = loongarch_force_binary (SImode, ASHIFT, newval, shiftsi);
4127 /* Do the SImode atomic access. */
4128 if (result)
4129 res = gen_reg_rtx (SImode);
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);
4139 emit_insn (si_op);
4141 if (result)
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));
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:
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))
4159 Also reject lengths equal to a word as they are better handled
4160 by the move patterns. */
4162 bool
4163 loongarch_use_ins_ext_p (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos)
4165 if (!register_operand (op, VOIDmode)
4166 || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
4167 return false;
4169 if (!IN_RANGE (width, 1, GET_MODE_BITSIZE (GET_MODE (op)) - 1))
4170 return false;
4172 if (bitpos < 0 || bitpos + width > GET_MODE_BITSIZE (GET_MODE (op)))
4173 return false;
4175 return true;
4178 /* Print the text for PRINT_OPERAND punctation character CH to FILE.
4179 The punctuation characters are:
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).
4184 See also loongarch_init_print_operand_punct. */
4186 static void
4187 loongarch_print_operand_punctuation (FILE *file, int ch)
4189 switch (ch)
4191 case '.':
4192 fputs (reg_names[GP_REG_FIRST + 0], file);
4193 break;
4195 case '$':
4196 fputs (reg_names[STACK_POINTER_REGNUM], file);
4197 break;
4199 default:
4200 gcc_unreachable ();
4201 break;
4205 /* Initialize loongarch_print_operand_punct. */
4207 static void
4208 loongarch_init_print_operand_punct (void)
4210 const char *p;
4212 for (p = ".$"; *p; p++)
4213 loongarch_print_operand_punct[(unsigned char) *p] = true;
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. */
4220 static void
4221 loongarch_print_int_branch_condition (FILE *file, enum rtx_code code,
4222 int letter)
4224 switch (code)
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;
4241 default:
4242 output_operand_lossage ("'%%%c' is not a valid operand prefix", letter);
4243 break;
4247 /* Likewise floating-point branches. */
4249 static void
4250 loongarch_print_float_branch_condition (FILE *file, enum rtx_code code,
4251 int letter)
4253 switch (code)
4255 case EQ:
4256 fputs ("ceqz", file);
4257 break;
4259 case NE:
4260 fputs ("cnez", file);
4261 break;
4263 default:
4264 output_operand_lossage ("'%%%c' is not a valid operand prefix", letter);
4265 break;
4269 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
4271 static bool
4272 loongarch_print_operand_punct_valid_p (unsigned char code)
4274 return loongarch_print_operand_punct[code];
4277 /* Return true if a FENCE should be emitted to before a memory access to
4278 implement the release portion of memory model MODEL. */
4280 static bool
4281 loongarch_memmodel_needs_rel_acq_fence (enum memmodel model)
4283 switch (model)
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;
4295 case MEMMODEL_RELAXED:
4296 return false;
4298 default:
4299 gcc_unreachable ();
4303 /* Return true if a FENCE should be emitted to before a memory access to
4304 implement the release portion of memory model MODEL. */
4306 static bool
4307 loongarch_memmodel_needs_release_fence (enum memmodel model)
4309 switch (model)
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;
4318 case MEMMODEL_ACQUIRE:
4319 case MEMMODEL_CONSUME:
4320 case MEMMODEL_SYNC_ACQUIRE:
4321 case MEMMODEL_RELAXED:
4322 return false;
4324 default:
4325 gcc_unreachable ();
4329 /* Implement TARGET_PRINT_OPERAND. The LoongArch-specific operand codes are:
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. */
4353 static void
4354 loongarch_print_operand (FILE *file, rtx op, int letter)
4356 enum rtx_code code;
4358 if (loongarch_print_operand_punct_valid_p (letter))
4360 loongarch_print_operand_punctuation (file, letter);
4361 return;
4364 gcc_assert (op);
4365 code = GET_CODE (op);
4367 switch (letter)
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;
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;
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;
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;
4397 case 'y':
4398 if (CONST_INT_P (op))
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);
4406 else
4407 output_operand_lossage ("invalid use of '%%%c'", letter);
4408 break;
4410 case 'V':
4411 if (CONST_VECTOR_P (op))
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);
4421 else
4422 output_operand_lossage ("invalid use of '%%%c'", letter);
4423 break;
4425 case 'C':
4426 loongarch_print_int_branch_condition (file, code, letter);
4427 break;
4429 case 'N':
4430 loongarch_print_int_branch_condition (file, reverse_condition (code),
4431 letter);
4432 break;
4434 case 'F':
4435 loongarch_print_float_branch_condition (file, code, letter);
4436 break;
4438 case 'W':
4439 loongarch_print_float_branch_condition (file, reverse_condition (code),
4440 letter);
4441 break;
4443 case 'T':
4444 case 't':
4446 int truth = (code == NE) == (letter == 'T');
4447 fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file);
4449 break;
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;
4460 case 'Z':
4461 loongarch_print_operand (file, op, 0);
4462 fputc (',', file);
4463 break;
4465 case 'A':
4466 if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op)))
4467 fputs ("_db", file);
4468 break;
4470 case 'G':
4471 if (loongarch_memmodel_needs_release_fence ((enum memmodel) INTVAL (op)))
4472 fputs ("dbar\t0", file);
4473 break;
4475 case 'i':
4476 if (code != REG)
4477 fputs ("i", file);
4478 break;
4480 default:
4481 switch (code)
4483 case REG:
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]);
4490 break;
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')
4498 gcc_assert (REG_P (XEXP (op, 0)));
4499 loongarch_print_operand (file, XEXP (op, 0), 0);
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;
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;
4519 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
4521 static void
4522 loongarch_print_operand_address (FILE *file, machine_mode /* mode */, rtx x)
4524 struct loongarch_address_info addr;
4526 if (loongarch_classify_address (&addr, x, word_mode, true))
4527 switch (addr.type)
4529 case ADDRESS_REG:
4530 fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
4531 loongarch_print_operand (file, addr.offset, 0);
4532 return;
4534 case ADDRESS_REG_REG:
4535 fprintf (file, "%s,%s", reg_names[REGNO (addr.reg)],
4536 reg_names[REGNO (addr.offset)]);
4537 return;
4539 case ADDRESS_CONST_INT:
4540 fprintf (file, "%s,", reg_names[GP_REG_FIRST]);
4541 output_addr_const (file, x);
4542 return;
4544 case ADDRESS_SYMBOLIC:
4545 output_addr_const (file, loongarch_strip_unspec_address (x));
4546 return;
4548 if (CONST_INT_P (x))
4549 output_addr_const (file, x);
4550 else
4551 gcc_unreachable ();
4554 /* Implement TARGET_ASM_SELECT_RTX_SECTION. */
4556 static section *
4557 loongarch_select_rtx_section (machine_mode mode, rtx x,
4558 unsigned HOST_WIDE_INT align)
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);
4564 return default_elf_select_rtx_section (mode, x, align);
4567 /* Implement TARGET_ASM_FUNCTION_RODATA_SECTION.
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. */
4574 static section *
4575 loongarch_function_rodata_section (tree decl, bool)
4577 return default_function_rodata_section (decl, false);
4580 /* Implement TARGET_IN_SMALL_DATA_P. */
4582 static bool
4583 loongarch_in_small_data_p (const_tree decl)
4585 int size;
4587 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
4588 return false;
4590 if (VAR_P (decl) && DECL_SECTION_NAME (decl) != 0)
4592 const char *name;
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;
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;
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;
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. */
4620 HOST_WIDE_INT
4621 loongarch_debugger_offset (rtx addr, HOST_WIDE_INT offset)
4623 rtx offset2 = const0_rtx;
4624 rtx reg = eliminate_constant_term (addr, &offset2);
4626 if (offset == 0)
4627 offset = INTVAL (offset2);
4629 if (reg == stack_pointer_rtx
4630 || reg == frame_pointer_rtx
4631 || reg == hard_frame_pointer_rtx)
4633 offset -= cfun->machine->frame.total_size;
4634 if (reg == hard_frame_pointer_rtx)
4635 offset += cfun->machine->frame.hard_frame_pointer_offset;
4638 return offset;
4641 /* Implement ASM_OUTPUT_EXTERNAL. */
4643 void
4644 loongarch_output_external (FILE *file, tree decl, const char *name)
4646 default_elf_asm_output_external (file, decl, name);
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)))
4653 if (loongarch_in_small_data_p (decl))
4655 /* When using assembler macros, emit .extern directives for
4656 all small-data externs so that the assembler knows how
4657 big they are.
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)));
4671 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
4673 static void ATTRIBUTE_UNUSED
4674 loongarch_output_dwarf_dtprel (FILE *file, int size, rtx x)
4676 switch (size)
4678 case 4:
4679 fputs ("\t.dtprelword\t", file);
4680 break;
4682 case 8:
4683 fputs ("\t.dtpreldword\t", file);
4684 break;
4686 default:
4687 gcc_unreachable ();
4689 output_addr_const (file, x);
4690 fputs ("+0x8000", file);
4693 /* Implement ASM_OUTPUT_ASCII. */
4695 void
4696 loongarch_output_ascii (FILE *stream, const char *string, size_t len)
4698 size_t i;
4699 int cur_pos;
4701 cur_pos = 17;
4702 fprintf (stream, "\t.ascii\t\"");
4703 for (i = 0; i < len; i++)
4705 int c;
4707 c = (unsigned char) string[i];
4708 if (ISPRINT (c))
4710 if (c == '\\' || c == '\"')
4712 putc ('\\', stream);
4713 cur_pos++;
4715 putc (c, stream);
4716 cur_pos++;
4718 else
4720 fprintf (stream, "\\%03o", c);
4721 cur_pos += 4;
4724 if (cur_pos > 72 && i + 1 < len)
4726 cur_pos = 17;
4727 fprintf (stream, "\"\n\t.ascii\t\"");
4730 fprintf (stream, "\"\n");
4733 /* Implement TARGET_FRAME_POINTER_REQUIRED. */
4735 static bool
4736 loongarch_frame_pointer_required (void)
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;
4743 return false;
4746 /* Implement TARGET_CAN_ELIMINATE. Make sure that we're not trying
4747 to eliminate to the wrong hard frame pointer. */
4749 static bool
4750 loongarch_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
4752 return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
4755 /* Implement RETURN_ADDR_RTX. We do not support moving back to a
4756 previous frame. */
4759 loongarch_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
4761 if (count != 0)
4762 return const0_rtx;
4764 return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
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. */
4771 void
4772 loongarch_set_return_address (rtx address, rtx scratch)
4774 rtx slot_address;
4776 gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM));
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);
4785 loongarch_emit_move (gen_frame_mem (GET_MODE (address), slot_address),
4786 address);
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. */
4792 static bool
4793 loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode)
4795 unsigned int size;
4796 enum mode_class mclass;
4798 if (mode == FCCmode)
4799 return FCC_REG_P (regno);
4801 size = GET_MODE_SIZE (mode);
4802 mclass = GET_MODE_CLASS (mode);
4804 if (GP_REG_P (regno))
4805 return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD;
4807 if (FP_REG_P (regno))
4809 if (mclass == MODE_FLOAT
4810 || mclass == MODE_COMPLEX_FLOAT
4811 || mclass == MODE_VECTOR_FLOAT)
4812 return size <= UNITS_PER_FPVALUE;
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;
4822 return false;
4825 /* Implement TARGET_HARD_REGNO_MODE_OK. */
4827 static bool
4828 loongarch_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
4830 return loongarch_hard_regno_mode_ok_p[mode][regno];
4833 /* Implement TARGET_HARD_REGNO_NREGS. */
4835 static unsigned int
4836 loongarch_hard_regno_nregs (unsigned int regno, machine_mode mode)
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;
4843 if (FP_REG_P (regno))
4844 return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
4846 /* All other registers are word-sized. */
4847 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4850 /* Implement CLASS_MAX_NREGS, taking the maximum of the cases
4851 in loongarch_hard_regno_nregs. */
4854 loongarch_class_max_nregs (enum reg_class rclass, machine_mode mode)
4856 int size;
4857 HARD_REG_SET left;
4859 size = 0x8000;
4860 left = reg_class_contents[rclass];
4861 if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FCC_REGS]))
4863 if (loongarch_hard_regno_mode_ok (FCC_REG_FIRST, mode))
4864 size = MIN (size, 4);
4866 left &= ~reg_class_contents[FCC_REGS];
4868 if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS]))
4870 if (loongarch_hard_regno_mode_ok (FP_REG_FIRST, mode))
4871 size = MIN (size, UNITS_PER_FPREG);
4873 left &= ~reg_class_contents[FP_REGS];
4875 if (!hard_reg_set_empty_p (left))
4876 size = MIN (size, UNITS_PER_WORD);
4877 return (GET_MODE_SIZE (mode) + size - 1) / size;
4880 /* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
4882 static bool
4883 loongarch_can_change_mode_class (machine_mode, machine_mode,
4884 reg_class_t rclass)
4886 return !reg_classes_intersect_p (FP_REGS, rclass);
4889 /* Return true if moves in mode MODE can use the FPU's fmov.fmt instruction,
4892 static bool
4893 loongarch_mode_ok_for_mov_fmt_p (machine_mode mode)
4895 switch (mode)
4897 case E_FCCmode:
4898 case E_SFmode:
4899 return TARGET_HARD_FLOAT;
4901 case E_DFmode:
4902 return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT;
4904 default:
4905 return 0;
4909 /* Implement TARGET_MODES_TIEABLE_P. */
4911 static bool
4912 loongarch_modes_tieable_p (machine_mode mode1, machine_mode mode2)
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)));
4921 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
4923 static reg_class_t
4924 loongarch_preferred_reload_class (rtx x, reg_class_t rclass)
4926 if (reg_class_subset_p (FP_REGS, rclass)
4927 && loongarch_mode_ok_for_mov_fmt_p (GET_MODE (x)))
4928 return FP_REGS;
4930 if (reg_class_subset_p (GR_REGS, rclass))
4931 rclass = GR_REGS;
4933 return rclass;
4936 /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation.
4937 Return a "canonical" class to represent it in later calculations. */
4939 static reg_class_t
4940 loongarch_canonicalize_move_class (reg_class_t rclass)
4942 if (reg_class_subset_p (rclass, GENERAL_REGS))
4943 rclass = GENERAL_REGS;
4945 return rclass;
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. */
4952 static int
4953 loongarch_move_to_gpr_cost (reg_class_t from)
4955 switch (from)
4957 case GENERAL_REGS:
4958 /* MOVE macro. */
4959 return 2;
4961 case FP_REGS:
4962 /* MOVFR2GR, etc. */
4963 return 4;
4965 default:
4966 return 0;
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. */
4974 static int
4975 loongarch_move_from_gpr_cost (reg_class_t to)
4977 switch (to)
4979 case GENERAL_REGS:
4980 /*MOVE macro. */
4981 return 2;
4983 case FP_REGS:
4984 /* MOVGR2FR, etc. */
4985 return 4;
4987 default:
4988 return 0;
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. */
4996 static int
4997 loongarch_register_move_cost (machine_mode mode, reg_class_t from,
4998 reg_class_t to)
5000 reg_class_t dregs;
5001 int cost1, cost2;
5003 from = loongarch_canonicalize_move_class (from);
5004 to = loongarch_canonicalize_move_class (to);
5006 /* Handle moves that can be done without using general-purpose registers. */
5007 if (from == FP_REGS)
5009 if (to == FP_REGS && loongarch_mode_ok_for_mov_fmt_p (mode))
5010 /* FMOV.FMT. */
5011 return 4;
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);
5021 /* Handles cases that require a GPR temporary. */
5022 cost1 = loongarch_move_to_gpr_cost (from);
5023 if (cost1 != 0)
5025 cost2 = loongarch_move_from_gpr_cost (to);
5026 if (cost2 != 0)
5027 return cost1 + cost2;
5030 return 0;
5033 /* Implement TARGET_MEMORY_MOVE_COST. */
5035 static int
5036 loongarch_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in)
5038 return (loongarch_cost->memory_latency
5039 + memory_move_secondary_cost (mode, rclass, in));
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. */
5048 static reg_class_t
5049 loongarch_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
5050 reg_class_t rclass, machine_mode mode,
5051 secondary_reload_info *sri ATTRIBUTE_UNUSED)
5053 int regno;
5055 regno = true_regnum (x);
5057 if (reg_class_subset_p (rclass, FP_REGS))
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;
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;
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;
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;
5080 /* Otherwise, we need to reload through an integer register. */
5081 return GR_REGS;
5083 if (FP_REG_P (regno))
5084 return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS;
5086 return NO_REGS;
5089 /* Implement TARGET_VALID_POINTER_MODE. */
5091 static bool
5092 loongarch_valid_pointer_mode (scalar_int_mode mode)
5094 return mode == SImode || (TARGET_64BIT && mode == DImode);
5097 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
5099 static bool
5100 loongarch_scalar_mode_supported_p (scalar_mode mode)
5102 if (ALL_FIXED_POINT_MODE_P (mode)
5103 && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
5104 return true;
5106 return default_scalar_mode_supported_p (mode);
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. */
5115 const char *
5116 loongarch_output_conditional_branch (rtx_insn *insn, rtx *operands,
5117 const char *branch_if_true,
5118 const char *branch_if_false)
5120 unsigned int length;
5121 rtx taken;
5123 gcc_assert (LABEL_P (operands[0]));
5125 length = get_attr_length (insn);
5126 if (length <= 4)
5128 return branch_if_true;
5131 /* Generate a reversed branch around a direct jump. */
5132 rtx_code_label *not_taken = gen_label_rtx ();
5133 taken = operands[0];
5135 /* Generate the reversed branch to NOT_TAKEN. */
5136 operands[0] = not_taken;
5137 output_asm_insn (branch_if_false, operands);
5139 output_asm_insn ("b\t%0", &taken);
5141 /* Output NOT_TAKEN. */
5142 targetm.asm_out.internal_label (asm_out_file, "L",
5143 CODE_LABEL_NUMBER (not_taken));
5144 return "";
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. */
5153 const char *
5154 loongarch_output_equal_conditional_branch (rtx_insn *insn, rtx *operands,
5155 bool inverted_p)
5157 const char *branch[2];
5158 if (operands[3] == const0_rtx)
5160 branch[!inverted_p] = LARCH_BRANCH ("b%C1z", "%2,%0");
5161 branch[inverted_p] = LARCH_BRANCH ("b%N1z", "%2,%0");
5163 else
5165 branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%z3,%0");
5166 branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%z3,%0");
5169 return loongarch_output_conditional_branch (insn, operands, branch[1],
5170 branch[0]);
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. */
5179 const char *
5180 loongarch_output_order_conditional_branch (rtx_insn *insn, rtx *operands,
5181 bool inverted_p)
5183 const char *branch[2];
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)
5189 /* Handle degenerate cases that should not, but do, occur. */
5190 if (REGNO (operands[2]) == REGNO (operands[3]))
5192 switch (GET_CODE (operands[1]))
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 ();
5211 else
5213 switch (GET_CODE (operands[1]))
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 ();
5231 else
5233 switch (GET_CODE (operands[1]))
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 ();
5251 return loongarch_output_conditional_branch (insn, operands, branch[1],
5252 branch[0]);
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.
5259 const char *
5260 loongarch_output_division (const char *division, rtx *operands)
5262 const char *s;
5264 s = division;
5265 if (TARGET_CHECK_ZERO_DIV)
5267 output_asm_insn (s, operands);
5268 s = "bne\t%2,%.,1f\n\tbreak\t7\n1:";
5270 return s;
5273 /* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output
5274 dependencies have no cost. */
5276 static int
5277 loongarch_adjust_cost (rtx_insn *, int dep_type, rtx_insn *, int cost,
5278 unsigned int)
5280 if (dep_type != 0 && (dep_type != REG_DEP_OUTPUT))
5281 return 0;
5282 return cost;
5285 /* Return the number of instructions that can be issued per cycle. */
5287 static int
5288 loongarch_issue_rate (void)
5290 if ((unsigned long) LARCH_ACTUAL_TUNE < N_TUNE_TYPES)
5291 return loongarch_cpu_issue_rate[LARCH_ACTUAL_TUNE];
5292 else
5293 return 1;
5296 /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should
5297 be as wide as the scheduling freedom in the DFA. */
5299 static int
5300 loongarch_multipass_dfa_lookahead (void)
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;
5308 /* Implement TARGET_SCHED_REORDER. */
5310 static int
5311 loongarch_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)
5317 return loongarch_issue_rate ();
5320 /* Implement TARGET_SCHED_REORDER2. */
5322 static int
5323 loongarch_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)
5329 return cached_can_issue_more;
5332 /* Implement TARGET_SCHED_INIT. */
5334 static void
5335 loongarch_sched_init (FILE *file ATTRIBUTE_UNUSED,
5336 int verbose ATTRIBUTE_UNUSED,
5337 int max_ready ATTRIBUTE_UNUSED)
5340 /* Implement TARGET_SCHED_VARIABLE_ISSUE. */
5342 static int
5343 loongarch_variable_issue (FILE *file ATTRIBUTE_UNUSED,
5344 int verbose ATTRIBUTE_UNUSED, rtx_insn *insn,
5345 int more)
5347 /* Ignore USEs and CLOBBERs; don't count them against the issue rate. */
5348 if (USEFUL_INSN_P (insn))
5350 if (get_attr_type (insn) != TYPE_GHOST)
5351 more--;
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);
5360 cached_can_issue_more = more;
5361 return more;
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. */
5368 loongarch_prefetch_cookie (rtx write, rtx locality)
5370 /* store_streamed / load_streamed. */
5371 if (INTVAL (locality) <= 0)
5372 return GEN_INT (INTVAL (write) + 4);
5374 /* store / load. */
5375 if (INTVAL (locality) <= 2)
5376 return write;
5378 /* store_retained / load_retained. */
5379 return GEN_INT (INTVAL (write) + 6);
5382 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
5383 in order to avoid duplicating too much logic from elsewhere. */
5385 static void
5386 loongarch_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
5387 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
5388 tree function)
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;
5395 /* Pretend to be a post-reload pass while generating rtl. */
5396 reload_completed = 1;
5398 /* Mark the end of the (empty) prologue. */
5399 emit_note (NOTE_INSN_PROLOGUE_END);
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);
5405 /* We need two temporary registers in some cases. */
5406 temp1 = gen_rtx_REG (Pmode, 12);
5407 temp2 = gen_rtx_REG (Pmode, 13);
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);
5415 /* Add DELTA to THIS_RTX. */
5416 if (delta != 0)
5418 rtx offset = GEN_INT (delta);
5419 if (!IMM12_OPERAND (delta))
5421 loongarch_emit_move (temp1, offset);
5422 offset = temp1;
5424 emit_insn (gen_add3_insn (this_rtx, this_rtx, offset));
5427 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
5428 if (vcall_offset != 0)
5430 rtx addr;
5432 /* Set TEMP1 to *THIS_RTX. */
5433 loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx));
5435 /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */
5436 addr = loongarch_add_offset (temp2, temp1, vcall_offset);
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));
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)
5447 insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
5448 SIBLING_CALL_P (insn) = 1;
5450 else
5452 loongarch_emit_move (temp1, fnaddr);
5453 emit_jump_insn (gen_indirect_jump (temp1));
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);
5467 /* Stop pretending to be a post-reload pass. */
5468 reload_completed = 0;
5471 /* Allocate a chunk of memory for per-function machine-dependent data. */
5473 static struct machine_function *
5474 loongarch_init_machine_status (void)
5476 return ggc_cleared_alloc<machine_function> ();
5479 static void
5480 loongarch_option_override_internal (struct gcc_options *opts)
5482 int i, regno, mode;
5484 if (flag_pic)
5485 g_switch_value = 0;
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);
5492 if (TARGET_ABI_LP64)
5493 flag_pcc_struct_return = 0;
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];
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;
5507 switch (la_target.cmodel)
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;
5516 case CMODEL_NORMAL:
5517 case CMODEL_TINY:
5518 case CMODEL_LARGE:
5519 break;
5521 default:
5522 gcc_unreachable ();
5525 loongarch_init_print_operand_punct ();
5527 /* Set up array to map GCC register number to debug register number.
5528 Ignore the special purpose register numbers. */
5530 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
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;
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);
5544 /* Function to allocate machine-dependent function status. */
5545 init_machine_status = &loongarch_init_machine_status;
5549 /* Implement TARGET_OPTION_OVERRIDE. */
5551 static void
5552 loongarch_option_override (void)
5554 loongarch_option_override_internal (&global_options);
5557 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
5559 static void
5560 loongarch_conditional_register_usage (void)
5562 if (!TARGET_HARD_FLOAT)
5563 accessible_reg_set &= ~(reg_class_contents[FP_REGS]
5564 | reg_class_contents[FCC_REGS]);
5567 /* Implement EH_USES. */
5569 bool
5570 loongarch_eh_uses (unsigned int regno ATTRIBUTE_UNUSED)
5572 return false;
5575 /* Implement EPILOGUE_USES. */
5577 bool
5578 loongarch_epilogue_uses (unsigned int regno)
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;
5586 return false;
5589 bool
5590 loongarch_load_store_bonding_p (rtx *operands, machine_mode mode, bool load_p)
5592 rtx reg1, reg2, mem1, mem2, base1, base2;
5593 enum reg_class rc1, rc2;
5594 HOST_WIDE_INT offset1, offset2;
5596 if (load_p)
5598 reg1 = operands[0];
5599 reg2 = operands[2];
5600 mem1 = operands[1];
5601 mem2 = operands[3];
5603 else
5605 reg1 = operands[1];
5606 reg2 = operands[3];
5607 mem1 = operands[0];
5608 mem2 = operands[2];
5611 if (loongarch_address_insns (XEXP (mem1, 0), mode, false) == 0
5612 || loongarch_address_insns (XEXP (mem2, 0), mode, false) == 0)
5613 return false;
5615 loongarch_split_plus (XEXP (mem1, 0), &base1, &offset1);
5616 loongarch_split_plus (XEXP (mem2, 0), &base2, &offset2);
5618 /* Base regs do not match. */
5619 if (!REG_P (base1) || !rtx_equal_p (base1, base2))
5620 return false;
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;
5629 /* Loading in same registers. */
5630 if (load_p && REGNO (reg1) == REGNO (reg2))
5631 return false;
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;
5640 if (abs (offset1 - offset2) != GET_MODE_SIZE (mode))
5641 return false;
5643 return true;
5646 /* Implement TARGET_TRAMPOLINE_INIT. */
5648 static void
5649 loongarch_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
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;
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);
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));
5667 #define OP(X) gen_int_mode (X, SImode)
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
5687 for (j = 0; j < i; j++)
5689 mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode));
5690 loongarch_emit_move (mem, trampoline[j]);
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);
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));
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));
5706 /* Implement HARD_REGNO_CALLER_SAVE_MODE. */
5708 machine_mode
5709 loongarch_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
5710 machine_mode mode)
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;
5720 /* Implement TARGET_SPILL_CLASS. */
5722 static reg_class_t
5723 loongarch_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED,
5724 machine_mode mode ATTRIBUTE_UNUSED)
5726 return NO_REGS;
5729 /* Implement TARGET_PROMOTE_FUNCTION_MODE. */
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. */
5737 static machine_mode
5738 loongarch_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)
5744 int unsignedp;
5746 if (type != NULL_TREE)
5747 return promote_mode (type, mode, punsignedp);
5749 unsignedp = *punsignedp;
5750 PROMOTE_MODE (mode, unsignedp, type);
5751 *punsignedp = unsignedp;
5752 return mode;
5755 /* Implement TARGET_STARTING_FRAME_OFFSET. See loongarch_compute_frame_info
5756 for details about the frame layout. */
5758 static HOST_WIDE_INT
5759 loongarch_starting_frame_offset (void)
5761 if (FRAME_GROWS_DOWNWARD)
5762 return 0;
5763 return crtl->outgoing_args_size;
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"
5774 #undef TARGET_OPTION_OVERRIDE
5775 #define TARGET_OPTION_OVERRIDE loongarch_option_override
5777 #undef TARGET_LEGITIMIZE_ADDRESS
5778 #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address
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
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
5801 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5802 #define TARGET_FUNCTION_OK_FOR_SIBCALL loongarch_function_ok_for_sibcall
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
5815 #undef TARGET_IN_SMALL_DATA_P
5816 #define TARGET_IN_SMALL_DATA_P loongarch_in_small_data_p
5818 #undef TARGET_PREFERRED_RELOAD_CLASS
5819 #define TARGET_PREFERRED_RELOAD_CLASS loongarch_preferred_reload_class
5821 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
5822 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
5824 #undef TARGET_EXPAND_BUILTIN_VA_START
5825 #define TARGET_EXPAND_BUILTIN_VA_START loongarch_va_start
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
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
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
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
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
5868 #undef TARGET_SCALAR_MODE_SUPPORTED_P
5869 #define TARGET_SCALAR_MODE_SUPPORTED_P loongarch_scalar_mode_supported_p
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
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
5884 #undef TARGET_CANNOT_FORCE_CONST_MEM
5885 #define TARGET_CANNOT_FORCE_CONST_MEM loongarch_cannot_force_const_mem
5887 #undef TARGET_LEGITIMATE_CONSTANT_P
5888 #define TARGET_LEGITIMATE_CONSTANT_P loongarch_legitimate_constant_p
5890 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
5891 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
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
5898 #undef TARGET_LEGITIMATE_ADDRESS_P
5899 #define TARGET_LEGITIMATE_ADDRESS_P loongarch_legitimate_address_p
5901 #undef TARGET_FRAME_POINTER_REQUIRED
5902 #define TARGET_FRAME_POINTER_REQUIRED loongarch_frame_pointer_required
5904 #undef TARGET_CAN_ELIMINATE
5905 #define TARGET_CAN_ELIMINATE loongarch_can_eliminate
5907 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5908 #define TARGET_CONDITIONAL_REGISTER_USAGE loongarch_conditional_register_usage
5910 #undef TARGET_TRAMPOLINE_INIT
5911 #define TARGET_TRAMPOLINE_INIT loongarch_trampoline_init
5913 #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
5914 #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV loongarch_atomic_assign_expand_fenv
5916 #undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
5917 #define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
5919 #undef TARGET_SPILL_CLASS
5920 #define TARGET_SPILL_CLASS loongarch_spill_class
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
5927 #undef TARGET_MODES_TIEABLE_P
5928 #define TARGET_MODES_TIEABLE_P loongarch_modes_tieable_p
5930 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
5931 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
5933 #undef TARGET_CAN_CHANGE_MODE_CLASS
5934 #define TARGET_CAN_CHANGE_MODE_CLASS loongarch_can_change_mode_class
5936 #undef TARGET_CONSTANT_ALIGNMENT
5937 #define TARGET_CONSTANT_ALIGNMENT loongarch_constant_alignment
5939 #undef TARGET_STARTING_FRAME_OFFSET
5940 #define TARGET_STARTING_FRAME_OFFSET loongarch_starting_frame_offset
5942 #undef TARGET_SECONDARY_RELOAD
5943 #define TARGET_SECONDARY_RELOAD loongarch_secondary_reload
5945 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
5946 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
5948 struct gcc_target targetm = TARGET_INITIALIZER;
5950 #include "gt-loongarch.h"