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)
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
26 #include "coretypes.h"
36 #include "stringpool.h"
43 #include "diagnostic.h"
44 #include "insn-attr.h"
47 #include "fold-const.h"
49 #include "stor-layout.h"
55 #include "common/common-target.h"
56 #include "langhooks.h"
59 #include "sched-int.h"
61 #include "target-globals.h"
62 #include "tree-pass.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
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.
97 A natural register + offset address. The register satisfies
98 loongarch_valid_base_register_p and the offset is a const_arith_operand.
101 A base register indexed by (optionally scaled) register.
104 A signed 16-bit constant address.
107 A constant symbolic address. */
108 enum loongarch_address_type
117 /* Information about an address described by loongarch_address_type.
123 REG is the base register and OFFSET is the constant offset.
126 A base register indexed by (optionally scaled) register.
129 SYMBOL_TYPE is the type of symbol that the address references. */
130 struct loongarch_address_info
132 enum loongarch_address_type type
;
135 enum loongarch_symbol_type symbol_type
;
138 /* Method of loading instant numbers:
141 Load 0-31 bit of the immediate number.
144 Load 32-51 bit of the immediate number.
147 Load 52-63 bit of the immediate number.
150 immediate like 0xfff00000fffffxxx
152 enum loongarch_load_imm_method
160 struct loongarch_integer_op
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
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. */
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) \
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
264 loongarch_fp_conditions
[16]= {LARCH_FP_CONDITIONS (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. */
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
));
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. */
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
)
296 if (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
)
306 HOST_WIDE_INT offset
;
307 } loongarch_aggregate_field
;
309 /* Identify subfields of aggregates that are candidates for passing in
310 floating-point registers. */
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
))
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
)))
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
)))
332 if (DECL_SIZE (f
) && integer_zerop (DECL_SIZE (f
)))
335 HOST_WIDE_INT pos
= offset
+ int_byte_position (f
);
336 n
= loongarch_flatten_aggregate_field (TREE_TYPE (f
), fields
, n
,
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
),
353 /* Can't handle incomplete types nor sizes that are not fixed. */
355 || !COMPLETE_TYPE_P (type
)
356 || TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
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
))
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
++)
375 fields
[n
] = subfields
[j
];
376 fields
[n
++].offset
+= i
* tree_to_uhwi (elt_size
);
384 /* Complex type need consume 2 field, so n must be 0. */
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
;
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
;
419 /* Identify candidate aggregates for passing in floating-point registers.
420 Candidates have at most two fields after flattening. */
423 loongarch_flatten_aggregate_argument (const_tree type
,
424 loongarch_aggregate_field fields
[2])
426 if (!type
|| TREE_CODE (type
) != RECORD_TYPE
)
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. */
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
))
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. */
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
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
));
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
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 (
505 gen_rtx_EXPR_LIST (VOIDmode
, gen_rtx_REG (mode1
, regno1
),
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. */
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
;
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. */
540 = loongarch_pass_aggregate_num_fpr (type
, fields
))
541 && info
->fpr_offset
+ info
->num_fprs
<= MAX_ARGS_IN_REGISTERS
)
542 switch (info
->num_fprs
)
545 return loongarch_pass_fpr_single (mode
, fregno
,
546 TYPE_MODE (fields
[0].type
),
550 return loongarch_pass_fpr_pair (mode
, fregno
,
551 TYPE_MODE (fields
[0].type
),
554 TYPE_MODE (fields
[1].type
),
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
))
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
));
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
)
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
),
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. */
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
);
617 /* Implement TARGET_FUNCTION_ARG. */
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 ())
628 return loongarch_get_arg_info (&info
, cum
, arg
.mode
, arg
.type
, arg
.named
,
632 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */
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. */
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. */
669 loongarch_function_value_1 (const_tree type
, const_tree func
,
672 struct loongarch_arg_info info
;
673 CUMULATIVE_ARGS args
;
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. */
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. */
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. */
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. */
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
,
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. */
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. */
754 loongarch_setup_incoming_varargs (cumulative_args_t cum
,
755 const function_arg_info
&arg
,
756 int *pretend_size ATTRIBUTE_UNUSED
,
759 CUMULATIVE_ARGS local_cum
;
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. */
789 loongarch_set_frame_expr (rtx frame_pattern
)
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
,
799 /* Return a frame-related rtx that stores REG at MEM.
800 REG must be a single register. */
803 loongarch_frame_set (rtx mem
, rtx reg
)
805 rtx set
= gen_rtx_SET (mem
, reg
);
806 RTX_FRAME_RELATED_P (set
) = 1;
810 /* Return true if the current function must save register REGNO. */
813 loongarch_save_reg_p (unsigned int regno
)
815 bool call_saved
= !global_regs
[regno
] && !call_used_regs
[regno
];
817 = crtl
->saves_all_registers
|| df_regs_ever_live_p (regno
);
819 if (call_saved
&& might_clobber
)
822 if (regno
== HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
825 if (regno
== RETURN_ADDR_REGNUM
&& crtl
->calls_eh_return
)
831 /* Determine which GPR save/restore routine to call. */
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;
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 |
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
870 +-------------------------------+ <-- frame_pointer_rtx (virtual)
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. */
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. */
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. */
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
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
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. */
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
;
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
990 loongarch_save_restore_reg (machine_mode mode
, int regno
, HOST_WIDE_INT offset
,
991 loongarch_save_restore_fn fn
)
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
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. */
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. */
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
;
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
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. */
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)))
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
,
1124 emit_stack_probe (plus_constant (Pmode
, stack_pointer_rtx
,
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. */
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 */
1151 emit_move_insn (r14
, GEN_INT (first
));
1152 emit_insn (gen_rtx_SET (r13
, gen_rtx_MINUS (Pmode
,
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
);
1167 emit_move_insn (r12
, GEN_INT (rounded_size
));
1168 emit_insn (gen_rtx_SET (r12
, gen_rtx_MINUS (Pmode
, r13
, r12
)));
1173 TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
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
)
1190 emit_stack_probe (plus_constant (Pmode
, r12
, rounded_size
- size
));
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. */
1214 loongarch_output_probe_stack_range (rtx reg1
, rtx reg2
, rtx reg3
)
1216 static int labelno
= 0;
1217 char loop_lab
[32], tmp
[64];
1220 ASM_GENERATE_INTERNAL_LABEL (loop_lab
, "LPSRL", labelno
++);
1223 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, loop_lab
);
1225 /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
1227 xops
[1] = GEN_INT (-PROBE_INTERVAL
);
1230 output_asm_insn ("sub.d\t%0,%0,%2", xops
);
1232 output_asm_insn ("sub.w\t%0,%0,%2", xops
);
1234 /* Probe at TEST_ADDR, test if TEST_ADDR == LAST_ADDR and branch. */
1236 strcpy (tmp
, "bne\t%0,%1,");
1238 output_asm_insn ("st.d\t$r0,%0,0", xops
);
1240 output_asm_insn ("st.w\t$r0,%0,0", xops
);
1241 output_asm_insn (strcat (tmp
, &loop_lab
[1]), xops
);
1246 /* Expand the "prologue" pattern. */
1249 loongarch_expand_prologue (void)
1251 struct loongarch_frame_info
*frame
= &cfun
->machine
->frame
;
1252 HOST_WIDE_INT size
= frame
->total_size
;
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 (),
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
,
1282 RTX_FRAME_RELATED_P (emit_insn (insn
)) = 1;
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. */
1301 if (IMM12_OPERAND (-size
))
1303 insn
= gen_add3_insn (stack_pointer_rtx
, stack_pointer_rtx
,
1305 RTX_FRAME_RELATED_P (emit_insn (insn
)) = 1;
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
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
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
);
1348 /* We need to add memory barrier to prevent read from deallocated stack. */
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 ());
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
,
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
,
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
);
1397 /* Set TARGET to BASE + STEP1. */
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
,
1416 rtx dwarf
= NULL_RTX
;
1417 rtx cfa_adjust_rtx
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
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
);
1431 loongarch_emit_stack_tie ();
1433 /* Deallocate the final bit of the frame. */
1436 insn
= emit_insn (gen_add3_insn (stack_pointer_rtx
,
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
));
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. */
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.
1477 codes
[0].code
= UNKNOWN
;
1478 codes
[0].method
= METHOD_NORMAL
;
1479 codes
[0].value
= low_part
;
1484 /* lu12i.w + ior. */
1485 codes
[0].code
= UNKNOWN
;
1486 codes
[0].method
= METHOD_NORMAL
;
1487 codes
[0].value
= low_part
& ~(IMM_REACH
- 1);
1489 HOST_WIDE_INT iorv
= low_part
& (IMM_REACH
- 1);
1492 codes
[1].code
= IOR
;
1493 codes
[1].method
= METHOD_NORMAL
;
1494 codes
[1].value
= iorv
;
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
1508 if (lu32i
[sign31
] && lu52i
[sign31
])
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;
1519 codes
[cost
].method
= METHOD_LU32I
;
1520 codes
[cost
].value
= ((value
<< 12) >> 44) << 32;
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;
1533 gcc_assert (cost
<= LARCH_MAX_INTEGER_OPS
);
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. */
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. */
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. */
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). */
1569 loongarch_global_symbol_p (const_rtx x
)
1571 if (LABEL_REF_P (x
))
1574 const_tree decl
= SYMBOL_REF_DECL (x
);
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
));
1586 loongarch_global_symbol_noweak_p (const_rtx x
)
1588 if (LABEL_REF_P (x
))
1591 const_tree decl
= SYMBOL_REF_DECL (x
);
1594 return !SYMBOL_REF_LOCAL_P (x
) || SYMBOL_REF_EXTERNAL_P (x
);
1596 return DECL_P (decl
) && TREE_PUBLIC (decl
);
1600 loongarch_weak_symbol_p (const_rtx x
)
1603 if (LABEL_REF_P (x
) || !(decl
= SYMBOL_REF_DECL (x
)))
1605 return DECL_P (decl
) && DECL_WEAK (decl
);
1608 /* Return true if SYMBOL_REF X binds locally. */
1611 loongarch_symbol_binds_local_p (const_rtx x
)
1613 if (LABEL_REF_P (x
))
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
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
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
))
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. */
1653 loongarch_symbolic_constant_p (rtx x
, enum loongarch_symbol_type
*symbol_type
)
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
)
1672 if (offset
== const0_rtx
)
1675 /* Check whether a nonzero offset is valid for the underlying
1677 switch (*symbol_type
)
1679 case SYMBOL_GOT_DISP
:
1688 /* Returns the number of instructions necessary to reference a symbol. */
1691 loongarch_symbol_insns (enum loongarch_symbol_type type
, machine_mode mode
)
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
)
1708 /* We don't treat a bare TLS symbol as a constant. */
1714 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1717 loongarch_cannot_force_const_mem (machine_mode mode
, rtx x
)
1719 enum loongarch_symbol_type type
;
1722 /* As an optimization, reject constants that loongarch_legitimize_move
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
))
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)
1743 /* TLS symbols must be computed by loongarch_legitimize_move. */
1744 if (tls_referenced_p (x
))
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
,
1758 if (!HARD_REGISTER_NUM_P (regno
))
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
)
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. */
1778 loongarch_valid_base_register_p (rtx x
, machine_mode mode
, bool strict_p
)
1780 if (!strict_p
&& SUBREG_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. */
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)))))
1802 /* We may need to split multiword moves, so make sure that every word
1804 if (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1805 && !IMM12_OPERAND (INTVAL (x
) + GET_MODE_SIZE (mode
) - UNITS_PER_WORD
))
1812 loongarch_valid_index_p (struct loongarch_address_info
*info
, rtx x
,
1813 machine_mode mode
, bool strict_p
)
1817 if ((REG_P (x
) || SUBREG_P (x
))
1818 && GET_MODE (x
) == Pmode
)
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
;
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
1845 loongarch_classify_address (struct loongarch_address_info
*info
, rtx x
,
1846 machine_mode mode
, bool strict_p
)
1848 switch (GET_CODE (x
))
1852 info
->type
= ADDRESS_REG
;
1854 info
->offset
= const0_rtx
;
1855 return loongarch_valid_base_register_p (info
->reg
, mode
, strict_p
);
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);
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);
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
));
1882 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
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
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)))
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
1912 loongarch_address_insns (rtx x
, machine_mode mode
, bool might_split_p
)
1914 struct loongarch_address_info addr
;
1917 if (!loongarch_classify_address (&addr
, x
, mode
, false))
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
1924 if (mode
!= BLKmode
&& might_split_p
)
1925 factor
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1929 if (loongarch_classify_address (&addr
, x
, mode
, false))
1935 case ADDRESS_REG_REG
:
1938 case ADDRESS_CONST_INT
:
1941 case ADDRESS_SYMBOLIC
:
1942 return factor
* loongarch_symbol_insns (addr
.symbol_type
, mode
);
1947 /* Return true if X fits within an unsigned field of BITS bits that is
1948 shifted left SHIFT bits before being used. */
1951 loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT x
, int bits
,
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. */
1961 loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x
, int bits
,
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. */
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. */
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
)));
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
;
2016 switch (GET_CODE (x
))
2019 return loongarch_integer_cost (INTVAL (x
));
2024 return x
== CONST0_RTX (GET_MODE (x
)) ? 1 : 0;
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
);
2042 int n
= loongarch_const_insns (x
);
2045 if (IMM12_INT (offset
))
2047 else if (!targetm
.cannot_force_const_mem (GET_MODE (x
), x
))
2048 return n
+ 1 + loongarch_integer_cost (INTVAL (offset
));
2055 return loongarch_symbol_insns (
2056 loongarch_classify_symbol (x
), MAX_MACHINE_MODE
);
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);
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
)
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
;
2095 set
= single_set (insn
);
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
)
2112 if (TARGET_CHECK_ZERO_DIV
)
2118 /* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */
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
),
2127 /* Compute (CODE OP0 OP1) and store the result in a new register
2128 of mode MODE. Return that new register. */
2131 loongarch_force_binary (machine_mode mode
, enum rtx_code code
, rtx op0
,
2136 reg
= gen_reg_rtx (mode
);
2137 loongarch_emit_binary (code
, reg
, op0
, op1
);
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. */
2145 loongarch_force_temporary (rtx dest
, rtx value
)
2147 if (can_create_pseudo_p ())
2148 return force_reg (Pmode
, value
);
2151 loongarch_emit_move (dest
, value
);
2156 /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
2157 then add CONST_INT OFFSET to the result. */
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
)
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
)
2190 split_const (op
, &base
, &offset
);
2191 if (UNSPEC_ADDRESS_P (base
))
2192 op
= plus_constant (Pmode
, UNSPEC_ADDRESS (base
), INTVAL (offset
));
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
2201 loongarch_add_offset (rtx temp
, rtx reg
, HOST_WIDE_INT offset
)
2203 if (!IMM12_OPERAND (offset
))
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. */
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. */
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. */
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. */
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. */
2259 loongarch_call_tls_get_addr (rtx sym
, enum loongarch_symbol_type type
, rtx v0
)
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
);
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
));
2280 insn
= emit_call_insn (gen_call_value_internal (v0
, loongarch_tls_symbol
,
2282 RTL_CONST_CALL_P (insn
) = 1;
2283 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), a0
);
2284 insn
= get_insns ();
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). */
2296 loongarch_legitimize_tls_address (rtx loc
)
2299 enum tls_model model
= SYMBOL_REF_TLS_MODEL (loc
);
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
);
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
);
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
));
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
));
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
);
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. */
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));
2372 /* If X is not a valid address for mode MODE, force it into a register. */
2375 loongarch_force_address (rtx x
, machine_mode mode
)
2377 if (!loongarch_legitimate_address_p (mode
, x
, false))
2378 x
= force_reg (Pmode
, 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. */
2388 loongarch_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
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
);
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
);
2410 /* Load VALUE into DEST. TEMP is as for loongarch_force_temporary. */
2413 loongarch_move_integer (rtx temp
, rtx dest
, unsigned HOST_WIDE_INT value
)
2415 struct loongarch_integer_op codes
[LARCH_MAX_INTEGER_OPS
];
2417 unsigned int i
, num_ops
;
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
));
2434 x
= force_reg (mode
, x
);
2436 switch (codes
[i
].method
)
2439 x
= gen_rtx_fmt_ee (codes
[i
].code
, mode
, x
,
2440 GEN_INT (codes
[i
].value
));
2445 gen_rtx_IOR (DImode
,
2446 gen_rtx_ZERO_EXTEND (
2447 DImode
, gen_rtx_SUBREG (SImode
, x
, 0)),
2448 GEN_INT (codes
[i
].value
))));
2451 emit_insn (gen_lu52i_d (x
, x
, GEN_INT (0xfffffffffffff),
2452 GEN_INT (codes
[i
].value
)));
2456 gen_rtx_SET (gen_rtx_ZERO_EXTRACT (DImode
, x
, GEN_INT (20),
2458 gen_rtx_REG (DImode
, 0)));
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
2473 loongarch_legitimize_const_move (machine_mode mode
, rtx dest
, rtx src
)
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
));
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
));
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
)));
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. */
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
));
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
));
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
));
2545 /* Return true if OP refers to small data symbols directly. */
2548 loongarch_small_data_pattern_1 (rtx x
)
2550 subrtx_var_iterator::array_type array
;
2551 FOR_EACH_SUBRTX_VAR (iter
, array
, x
, ALL
)
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 ();
2561 if (loongarch_small_data_pattern_1 (XEXP (x
, 0)))
2563 iter
.skip_subrtxes ();
2569 /* Return true if OP refers to small data symbols directly. */
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
2581 loongarch_rewrite_small_data_1 (rtx
*loc
)
2583 subrtx_ptr_iterator::array_type array
;
2584 FOR_EACH_SUBRTX_PTR (iter
, array
, loc
, ALL
)
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
);
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. */
2614 loongarch_immediate_operand_p (int code
, HOST_WIDE_INT x
)
2621 /* All shift counts are truncated to a valid constant. */
2631 /* These instructions take 12-bit unsigned immediates. */
2632 return IMM12_OPERAND_UNSIGNED (x
);
2637 /* These instructions take 12-bit signed immediates. */
2638 return IMM12_OPERAND (x
);
2644 /* The "immediate" forms of these instructions are really
2645 implemented as comparisons with register 0. */
2650 /* Likewise, meaning that the only valid immediate operand is 1. */
2654 /* We add 1 to the immediate and use SLT. */
2655 return IMM12_OPERAND (x
+ 1);
2658 /* Likewise SLTU, but reject the always-true case. */
2659 return IMM12_OPERAND (x
+ 1) && x
+ 1 != 0;
2663 /* The bit position and size are immediate operands. */
2667 /* By default assume that $0 can be used for 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. */
2678 loongarch_binary_cost (rtx x
, int single_cost
, int double_cost
, bool speed
)
2682 if (GET_MODE_SIZE (GET_MODE (x
)) == UNITS_PER_WORD
* 2)
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. */
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. */
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. */
2713 loongarch_sign_extend_cost (rtx op
)
2716 /* Extended loads are as cheap as unextended ones. */
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. */
2726 loongarch_zero_extend_cost (rtx op
)
2729 /* Extended loads are as cheap as unextended ones. */
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. */
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. */
2748 loongarch_set_reg_reg_cost (machine_mode mode
)
2750 switch (GET_MODE_CLASS (mode
))
2753 return loongarch_set_reg_reg_piece_cost (mode
, GET_MODE_SIZE (CCmode
));
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
);
2763 return loongarch_set_reg_reg_piece_cost (mode
, UNITS_PER_WORD
);
2767 /* Implement TARGET_RTX_COSTS. */
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
);
2778 if (outer_code
== COMPARE
)
2780 gcc_assert (CONSTANT_P (x
));
2788 if (TARGET_64BIT
&& outer_code
== AND
&& UINTVAL (x
) == 0xffffffff)
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
)))
2810 cost
= loongarch_const_insns (x
);
2813 if (cost
== 1 && outer_code
== SET
2814 && !(float_mode_p
&& TARGET_HARD_FLOAT
))
2816 else if ((outer_code
== SET
|| GET_MODE (x
) == VOIDmode
))
2818 *total
= COSTS_N_INSNS (cost
);
2821 /* The value will need to be fetched from the constant pool. */
2822 *total
= CONSTANT_POOL_COST
;
2826 /* If the address is legitimate, return the number of
2827 instructions it needs. */
2829 /* Check for a scaled indexed address. */
2830 if (loongarch_index_address_p (addr
, mode
))
2832 *total
= COSTS_N_INSNS (2);
2835 cost
= loongarch_address_insns (addr
, mode
, true);
2838 *total
= COSTS_N_INSNS (cost
+ 1);
2841 /* Otherwise use the default handling. */
2845 *total
= COSTS_N_INSNS (6);
2849 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
? 2 : 1);
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
));
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
));
2877 /* Double-word operations use two single-word operations. */
2878 *total
= loongarch_binary_cost (x
, COSTS_N_INSNS (1), COSTS_N_INSNS (2),
2887 if (CONSTANT_P (XEXP (x
, 1)))
2888 *total
= loongarch_binary_cost (x
, COSTS_N_INSNS (1),
2889 COSTS_N_INSNS (4), speed
);
2891 *total
= loongarch_binary_cost (x
, COSTS_N_INSNS (1),
2892 COSTS_N_INSNS (12), speed
);
2897 *total
= loongarch_cost
->fp_add
;
2899 *total
= COSTS_N_INSNS (4);
2918 /* Branch comparisons have VOIDmode, so use the first operand's
2920 mode
= GET_MODE (XEXP (x
, 0));
2921 if (FLOAT_MODE_P (mode
))
2923 *total
= loongarch_cost
->fp_add
;
2926 *total
= loongarch_binary_cost (x
, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
2934 *total
= loongarch_cost
->fp_add
;
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
));
2953 /* Double-word operations require three single-word operations and
2955 *total
= loongarch_binary_cost (x
, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
2961 *total
= loongarch_cost
->fp_add
;
2963 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
? 4 : 1);
2967 *total
= loongarch_fp_mult_cost (mode
);
2972 *total
= loongarch_fp_mult_cost (mode
);
2973 else if (mode
== DImode
&& !TARGET_64BIT
)
2975 ? loongarch_cost
->int_mult_si
* 3 + 6
2976 : COSTS_N_INSNS (7));
2978 *total
= COSTS_N_INSNS (1) + 1;
2979 else if (mode
== DImode
)
2980 *total
= loongarch_cost
->int_mult_di
;
2982 *total
= loongarch_cost
->int_mult_si
;
2986 /* Check for a reciprocal. */
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
);
2996 *total
= (loongarch_fp_div_cost (mode
)
2997 + set_src_cost (XEXP (x
, 1), mode
, speed
));
3006 *total
= loongarch_fp_div_cost (mode
);
3015 *total
= COSTS_N_INSNS (loongarch_idiv_insns (mode
));
3017 else if (mode
== DImode
)
3018 *total
= loongarch_cost
->int_div_di
;
3020 *total
= loongarch_cost
->int_div_si
;
3024 *total
= loongarch_sign_extend_cost (XEXP (x
, 0));
3028 *total
= loongarch_zero_extend_cost (XEXP (x
, 0));
3031 /* Costings for highpart multiplies. Matching patterns of the form:
3033 (lshiftrt:DI (mult:DI (sign_extend:DI (...)
3034 (sign_extend:DI (...))
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
)
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))
3053 *total
= COSTS_N_INSNS (1) + 1;
3054 else if (mode
== DImode
)
3055 *total
= loongarch_cost
->int_mult_di
;
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
);
3065 && GET_CODE (op
) == ZERO_EXTEND
3066 && GET_MODE (op
) == DImode
)
3067 *total
+= rtx_cost (op
, DImode
, MULT
, i
, speed
);
3069 *total
+= rtx_cost (XEXP (op
, 0), VOIDmode
, GET_CODE (op
), 0,
3078 case UNSIGNED_FLOAT
:
3081 case FLOAT_TRUNCATE
:
3082 *total
= loongarch_cost
->fp_add
;
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
)));
3099 /* Implement TARGET_ADDRESS_COST. */
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
)
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
);
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. */
3137 loongarch_split_move_p (rtx dest
, rtx src
)
3139 /* FPR-to-FPR moves can be done in a single instruction, if they're
3141 unsigned int size
= GET_MODE_SIZE (GET_MODE (dest
));
3142 if (size
== 8 && FP_REG_RTX_P (src
) && FP_REG_RTX_P (dest
))
3145 /* Check for floating-point loads and stores. */
3148 if (FP_REG_RTX_P (dest
) && MEM_P (src
))
3150 if (FP_REG_RTX_P (src
) && MEM_P (dest
))
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. */
3161 loongarch_split_move (rtx dest
, rtx src
, rtx insn_
)
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
));
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));
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
3199 rtx_insn
*insn
= (rtx_insn
*) insn_
;
3200 struct loongarch_address_info addr
= {};
3203 rtx_insn
*next
= next_nonnote_nondebug_insn_bb (insn
);
3206 rtx set
= single_set (next
);
3207 if (set
&& SET_SRC (set
) == dest
)
3211 rtx tmp
= XEXP (src
, 0);
3212 loongarch_classify_address (&addr
, tmp
, GET_MODE (tmp
),
3214 if (addr
.reg
&& !reg_overlap_mentioned_p (dest
, addr
.reg
))
3215 validate_change (next
, &SET_SRC (set
), src
, false);
3218 validate_change (next
, &SET_SRC (set
), src
, false);
3224 /* Return true if a move from SRC to DEST in INSN should be split. */
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. */
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
);
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))
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))
3264 const char *const insn
[][4] =
3280 return insn
[ldr
][index
];
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))
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))
3296 const char *const insn
[][2] =
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. */
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
))
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
),
3344 rtx offset
= XEXP (dest
, 0);
3345 if (GET_CODE (offset
) == PLUS
)
3346 offset
= XEXP (offset
, 1);
3347 switch (GET_MODE_SIZE (mode
))
3350 return "st.b\t%z1,%0";
3352 return "st.h\t%z1,%0";
3354 if (const_arith_operand (offset
, Pmode
))
3355 return "st.w\t%z1,%0";
3357 return "stptr.w\t%z1,%0";
3359 if (const_arith_operand (offset
, Pmode
))
3360 return "st.d\t%z1,%0";
3362 return "stptr.d\t%z1,%0";
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
),
3382 rtx offset
= XEXP (src
, 0);
3383 if (GET_CODE (offset
) == PLUS
)
3384 offset
= XEXP (offset
, 1);
3385 switch (GET_MODE_SIZE (mode
))
3388 return "ld.bu\t%0,%1";
3390 return "ld.hu\t%0,%1";
3392 if (const_arith_operand (offset
, Pmode
))
3393 return "ld.w\t%0,%1";
3395 return "ldptr.w\t%0,%1";
3397 if (const_arith_operand (offset
, Pmode
))
3398 return "ld.d\t%0,%1";
3400 return "ldptr.d\t%0,%1";
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";
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. */
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
;
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";
3459 return "la.global\t%0,%1";
3461 if (TARGET_CMODEL_EXTREME
)
3463 sorry ("Normal symbol loading not implemented in extreme mode.");
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),
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),
3497 return dbl_p
? "fld.d\t%0,%1" : "fld.s\t%0,%1";
3503 /* Return true if CMP1 is a suitable second operand for integer ordering
3507 loongarch_int_order_operand_ok_p (enum rtx_code code
, rtx cmp1
)
3513 return reg_or_0_operand (cmp1
, VOIDmode
);
3517 return cmp1
== const1_rtx
;
3521 return arith_operand (cmp1
, VOIDmode
);
3524 return sle_operand (cmp1
, VOIDmode
);
3527 return sleu_operand (cmp1
, VOIDmode
);
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
3541 loongarch_canonicalize_int_order_test (enum rtx_code
*code
, rtx
*cmp1
,
3544 HOST_WIDE_INT plus_one
;
3546 if (loongarch_int_order_operand_ok_p (*code
, *cmp1
))
3549 if (CONST_INT_P (*cmp1
))
3553 plus_one
= trunc_int_for_mode (UINTVAL (*cmp1
) + 1, mode
);
3554 if (INTVAL (*cmp1
) < plus_one
)
3557 *cmp1
= force_reg (mode
, GEN_INT (plus_one
));
3563 plus_one
= trunc_int_for_mode (UINTVAL (*cmp1
) + 1, mode
);
3567 *cmp1
= force_reg (mode
, GEN_INT (plus_one
));
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. */
3584 loongarch_emit_int_order_test (enum rtx_code code
, bool *invert_ptr
,
3585 rtx target
, rtx cmp0
, rtx cmp1
)
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
);
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)
3607 inv_target
= loongarch_force_binary (GET_MODE (target
),
3608 inv_code
, cmp0
, cmp1
);
3609 loongarch_emit_binary (XOR
, target
, inv_target
, const1_rtx
);
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. */
3623 loongarch_zero_if_equal (rtx cmp0
, rtx cmp1
)
3625 if (cmp1
== const0_rtx
)
3628 if (uns_arith_operand (cmp1
, VOIDmode
))
3629 return expand_binop (GET_MODE (cmp0
), xor_optab
, cmp0
, cmp1
, 0, 0,
3632 return expand_binop (GET_MODE (cmp0
), sub_optab
, cmp0
, cmp1
, 0, 0,
3636 /* Allocate a floating-point condition-code register of mode MODE. */
3639 loongarch_allocate_fcc (machine_mode mode
)
3641 unsigned int regno
, count
;
3643 gcc_assert (TARGET_HARD_FLOAT
);
3645 if (mode
== FCCmode
)
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. */
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
));
3674 *op1
= gen_rtx_ZERO_EXTEND (word_mode
, *op1
);
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. */
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
,
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
)
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
];
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. */
3743 loongarch_emit_float_compare (enum rtx_code
*code
, rtx
*op0
, rtx
*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. */
3759 *op0
= loongarch_allocate_fcc (FCCmode
);
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. */
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
);
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. */
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];
3804 if (FLOAT_MODE_P (GET_MODE (op1
)))
3805 loongarch_emit_float_compare (&code
, &op0
, &op1
);
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]. */
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
);
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
);
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
;
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
)));
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. */
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. */
3892 loongarch_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
3893 tree exp ATTRIBUTE_UNUSED
)
3899 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
3900 Assume that the areas do not overlap. */
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
;
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
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. */
3950 loongarch_adjust_block_mem (rtx mem
, HOST_WIDE_INT length
, rtx
*loop_reg
,
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. */
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
;
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
3982 final_src
= expand_simple_binop (Pmode
, PLUS
, src_reg
, GEN_INT (length
), 0,
3985 /* Emit the start of the loop. */
3986 label
= gen_label_rtx ();
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
));
4003 emit_jump_insn (gen_cbranchsi4 (test
, src_reg
, final_src
, label
));
4005 /* Mop up any left-over bytes. */
4007 loongarch_block_move_straight (dest
, src
, leftover
);
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. */
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
));
4031 loongarch_block_move_loop (dest
, src
, INTVAL (length
),
4032 LARCH_MAX_MOVE_BYTES_PER_LOOP_ITER
);
4039 /* Return true if loongarch_expand_block_move is the preferred
4040 implementation of the 'cpymemsi' template. */
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
4060 RESULT is the return register for the operation. Its value is NULL
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. */
4071 loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs generator
,
4072 rtx result
, rtx mem
, rtx oldval
, rtx newval
,
4075 rtx orig_addr
, memsi_addr
, memsi
, shift
, shiftsi
, unshifted_mask
;
4076 rtx unshifted_mask_reg
, mask
, inverted_mask
, si_op
;
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. */
4129 res
= gen_reg_rtx (SImode
);
4132 si_op
= generator
.fn_7 (res
, memsi
, mask
, inverted_mask
, oldval
, newval
,
4135 si_op
= generator
.fn_6 (res
, memsi
, mask
, inverted_mask
, oldval
, model
);
4137 si_op
= generator
.fn_5 (memsi
, mask
, inverted_mask
, oldval
, model
);
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. */
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
)
4169 if (!IN_RANGE (width
, 1, GET_MODE_BITSIZE (GET_MODE (op
)) - 1))
4172 if (bitpos
< 0 || bitpos
+ width
> GET_MODE_BITSIZE (GET_MODE (op
)))
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. */
4187 loongarch_print_operand_punctuation (FILE *file
, int ch
)
4192 fputs (reg_names
[GP_REG_FIRST
+ 0], file
);
4196 fputs (reg_names
[STACK_POINTER_REGNUM
], file
);
4205 /* Initialize loongarch_print_operand_punct. */
4208 loongarch_init_print_operand_punct (void)
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
4221 loongarch_print_int_branch_condition (FILE *file
, enum rtx_code code
,
4236 /* Conveniently, the LoongArch names for these conditions are the same
4237 as their RTL equivalents. */
4238 fputs (GET_RTX_NAME (code
), file
);
4242 output_operand_lossage ("'%%%c' is not a valid operand prefix", letter
);
4247 /* Likewise floating-point branches. */
4250 loongarch_print_float_branch_condition (FILE *file
, enum rtx_code code
,
4256 fputs ("ceqz", file
);
4260 fputs ("cnez", file
);
4264 output_operand_lossage ("'%%%c' is not a valid operand prefix", letter
);
4269 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
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. */
4281 loongarch_memmodel_needs_rel_acq_fence (enum memmodel 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
:
4295 case MEMMODEL_RELAXED
:
4303 /* Return true if a FENCE should be emitted to before a memory access to
4304 implement the release portion of memory model MODEL. */
4307 loongarch_memmodel_needs_release_fence (enum memmodel 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
:
4318 case MEMMODEL_ACQUIRE
:
4319 case MEMMODEL_CONSUME
:
4320 case MEMMODEL_SYNC_ACQUIRE
:
4321 case MEMMODEL_RELAXED
:
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. */
4354 loongarch_print_operand (FILE *file
, rtx op
, int letter
)
4358 if (loongarch_print_operand_punct_valid_p (letter
))
4360 loongarch_print_operand_punctuation (file
, letter
);
4365 code
= GET_CODE (op
);
4370 if (CONST_INT_P (op
))
4371 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, INTVAL (op
));
4373 output_operand_lossage ("invalid use of '%%%c'", letter
);
4377 if (CONST_INT_P (op
))
4378 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, INTVAL (op
) & 0xffff);
4380 output_operand_lossage ("invalid use of '%%%c'", letter
);
4384 if (CONST_INT_P (op
))
4385 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
));
4387 output_operand_lossage ("invalid use of '%%%c'", letter
);
4391 if (CONST_INT_P (op
))
4392 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
) - 1);
4394 output_operand_lossage ("invalid use of '%%%c'", letter
);
4398 if (CONST_INT_P (op
))
4400 int val
= exact_log2 (INTVAL (op
));
4402 fprintf (file
, "%d", val
);
4404 output_operand_lossage ("invalid use of '%%%c'", letter
);
4407 output_operand_lossage ("invalid use of '%%%c'", letter
);
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
));
4417 fprintf (file
, "%d", vlog2
);
4419 output_operand_lossage ("invalid use of '%%%c'", letter
);
4422 output_operand_lossage ("invalid use of '%%%c'", letter
);
4426 loongarch_print_int_branch_condition (file
, code
, letter
);
4430 loongarch_print_int_branch_condition (file
, reverse_condition (code
),
4435 loongarch_print_float_branch_condition (file
, code
, letter
);
4439 loongarch_print_float_branch_condition (file
, reverse_condition (code
),
4446 int truth
= (code
== NE
) == (letter
== 'T');
4447 fputc ("zfnt"[truth
* 2 + FCC_REG_P (REGNO (XEXP (op
, 0)))], file
);
4452 if (code
== CONST_INT
4453 && UINTVAL (op
) < ARRAY_SIZE (loongarch_fp_conditions
))
4454 fputs (loongarch_fp_conditions
[UINTVAL (op
)], file
);
4456 output_operand_lossage ("'%%%c' is not a valid operand prefix",
4461 loongarch_print_operand (file
, op
, 0);
4466 if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel
) INTVAL (op
)))
4467 fputs ("_db", file
);
4471 if (loongarch_memmodel_needs_release_fence ((enum memmodel
) INTVAL (op
)))
4472 fputs ("dbar\t0", file
);
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
]);
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
);
4504 output_address (GET_MODE (op
), XEXP (op
, 0));
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
);
4513 output_addr_const (file
, loongarch_strip_unspec_address (op
));
4519 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
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))
4530 fprintf (file
, "%s,", reg_names
[REGNO (addr
.reg
)]);
4531 loongarch_print_operand (file
, addr
.offset
, 0);
4534 case ADDRESS_REG_REG
:
4535 fprintf (file
, "%s,%s", reg_names
[REGNO (addr
.reg
)],
4536 reg_names
[REGNO (addr
.offset
)]);
4539 case ADDRESS_CONST_INT
:
4540 fprintf (file
, "%s,", reg_names
[GP_REG_FIRST
]);
4541 output_addr_const (file
, x
);
4544 case ADDRESS_SYMBOLIC
:
4545 output_addr_const (file
, loongarch_strip_unspec_address (x
));
4548 if (CONST_INT_P (x
))
4549 output_addr_const (file
, x
);
4554 /* Implement TARGET_ASM_SELECT_RTX_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. */
4575 loongarch_function_rodata_section (tree decl
, bool)
4577 return default_function_rodata_section (decl
, false);
4580 /* Implement TARGET_IN_SMALL_DATA_P. */
4583 loongarch_in_small_data_p (const_tree decl
)
4587 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
4590 if (VAR_P (decl
) && DECL_SECTION_NAME (decl
) != 0)
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)
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
))
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. */
4621 loongarch_debugger_offset (rtx addr
, HOST_WIDE_INT offset
)
4623 rtx offset2
= const0_rtx
;
4624 rtx reg
= eliminate_constant_term (addr
, &offset2
);
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
;
4641 /* Implement ASM_OUTPUT_EXTERNAL. */
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
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
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
)
4679 fputs ("\t.dtprelword\t", file
);
4683 fputs ("\t.dtpreldword\t", file
);
4689 output_addr_const (file
, x
);
4690 fputs ("+0x8000", file
);
4693 /* Implement ASM_OUTPUT_ASCII. */
4696 loongarch_output_ascii (FILE *stream
, const char *string
, size_t len
)
4702 fprintf (stream
, "\t.ascii\t\"");
4703 for (i
= 0; i
< len
; i
++)
4707 c
= (unsigned char) string
[i
];
4710 if (c
== '\\' || c
== '\"')
4712 putc ('\\', stream
);
4720 fprintf (stream
, "\\%03o", c
);
4724 if (cur_pos
> 72 && i
+ 1 < len
)
4727 fprintf (stream
, "\"\n\t.ascii\t\"");
4730 fprintf (stream
, "\"\n");
4733 /* Implement TARGET_FRAME_POINTER_REQUIRED. */
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
)
4746 /* Implement TARGET_CAN_ELIMINATE. Make sure that we're not trying
4747 to eliminate to the wrong hard frame pointer. */
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
4759 loongarch_return_addr (int count
, rtx frame ATTRIBUTE_UNUSED
)
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. */
4772 loongarch_set_return_address (rtx address
, rtx scratch
)
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
,
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
),
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. */
4793 loongarch_hard_regno_mode_ok_uncached (unsigned int regno
, machine_mode mode
)
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
;
4825 /* Implement TARGET_HARD_REGNO_MODE_OK. */
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. */
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
)
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. */
4883 loongarch_can_change_mode_class (machine_mode
, machine_mode
,
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,
4893 loongarch_mode_ok_for_mov_fmt_p (machine_mode mode
)
4899 return TARGET_HARD_FLOAT
;
4902 return TARGET_HARD_FLOAT
&& TARGET_DOUBLE_FLOAT
;
4909 /* Implement TARGET_MODES_TIEABLE_P. */
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. */
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
)))
4930 if (reg_class_subset_p (GR_REGS
, rclass
))
4936 /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation.
4937 Return a "canonical" class to represent it in later calculations. */
4940 loongarch_canonicalize_move_class (reg_class_t rclass
)
4942 if (reg_class_subset_p (rclass
, GENERAL_REGS
))
4943 rclass
= GENERAL_REGS
;
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
4953 loongarch_move_to_gpr_cost (reg_class_t from
)
4962 /* MOVFR2GR, etc. */
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
4975 loongarch_move_from_gpr_cost (reg_class_t to
)
4984 /* MOVGR2FR, etc. */
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. */
4997 loongarch_register_move_cost (machine_mode mode
, reg_class_t from
,
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
))
5014 /* Handle cases in which only one class deviates from the ideal. */
5015 dregs
= GENERAL_REGS
;
5017 return loongarch_move_from_gpr_cost (to
);
5019 return loongarch_move_to_gpr_cost (from
);
5021 /* Handles cases that require a GPR temporary. */
5022 cost1
= loongarch_move_to_gpr_cost (from
);
5025 cost2
= loongarch_move_from_gpr_cost (to
);
5027 return cost1
+ cost2
;
5033 /* Implement TARGET_MEMORY_MOVE_COST. */
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
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
)
5055 regno
= true_regnum (x
);
5057 if (reg_class_subset_p (rclass
, FP_REGS
))
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. */
5065 if (GP_REG_P (regno
) || x
== CONST0_RTX (mode
))
5066 /* In this case we can use movgr2fr.s, movfr2gr.s, movgr2fr.d or
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. */
5076 if (FP_REG_P (regno
) && loongarch_mode_ok_for_mov_fmt_p (mode
))
5077 /* In this case we can use fmov.{s/d}. */
5080 /* Otherwise, we need to reload through an integer register. */
5083 if (FP_REG_P (regno
))
5084 return reg_class_subset_p (rclass
, GR_REGS
) ? NO_REGS
: GR_REGS
;
5089 /* Implement TARGET_VALID_POINTER_MODE. */
5092 loongarch_valid_pointer_mode (scalar_int_mode mode
)
5094 return mode
== SImode
|| (TARGET_64BIT
&& mode
== DImode
);
5097 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
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
)
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. */
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
;
5123 gcc_assert (LABEL_P (operands
[0]));
5125 length
= get_attr_length (insn
);
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
));
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. */
5154 loongarch_output_equal_conditional_branch (rtx_insn
*insn
, rtx
*operands
,
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");
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],
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. */
5180 loongarch_output_order_conditional_branch (rtx_insn
*insn
, rtx
*operands
,
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]))
5198 inverted_p
= !inverted_p
;
5204 branch
[!inverted_p
] = LARCH_BRANCH ("b", "%0");
5205 branch
[inverted_p
] = "\t# branch never";
5213 switch (GET_CODE (operands
[1]))
5223 branch
[!inverted_p
] = LARCH_BRANCH ("b%C1", "%2,%3,%0");
5224 branch
[inverted_p
] = LARCH_BRANCH ("b%N1", "%2,%3,%0");
5233 switch (GET_CODE (operands
[1]))
5235 /* These cases are equivalent to comparisons against zero. */
5244 branch
[!inverted_p
] = LARCH_BRANCH ("b%C1", "%2,$r0,%0");
5245 branch
[inverted_p
] = LARCH_BRANCH ("b%N1", "%2,$r0,%0");
5251 return loongarch_output_conditional_branch (insn
, operands
, branch
[1],
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.
5260 loongarch_output_division (const char *division
, rtx
*operands
)
5265 if (TARGET_CHECK_ZERO_DIV
)
5267 output_asm_insn (s
, operands
);
5268 s
= "bne\t%2,%.,1f\n\tbreak\t7\n1:";
5273 /* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output
5274 dependencies have no cost. */
5277 loongarch_adjust_cost (rtx_insn
*, int dep_type
, rtx_insn
*, int cost
,
5280 if (dep_type
!= 0 && (dep_type
!= REG_DEP_OUTPUT
))
5285 /* Return the number of instructions that can be issued per cycle. */
5288 loongarch_issue_rate (void)
5290 if ((unsigned long) LARCH_ACTUAL_TUNE
< N_TUNE_TYPES
)
5291 return loongarch_cpu_issue_rate
[LARCH_ACTUAL_TUNE
];
5296 /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should
5297 be as wide as the scheduling freedom in the DFA. */
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
];
5308 /* Implement TARGET_SCHED_REORDER. */
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. */
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. */
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. */
5343 loongarch_variable_issue (FILE *file ATTRIBUTE_UNUSED
,
5344 int verbose ATTRIBUTE_UNUSED
, rtx_insn
*insn
,
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
)
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
;
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);
5375 if (INTVAL (locality
) <= 2)
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. */
5386 loongarch_output_mi_thunk (FILE *file
, tree thunk_fndecl ATTRIBUTE_UNUSED
,
5387 HOST_WIDE_INT delta
, HOST_WIDE_INT vcall_offset
,
5390 const char *fnname
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl
));
5391 rtx this_rtx
, temp1
, temp2
, fnaddr
;
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);
5413 this_rtx
= gen_rtx_REG (Pmode
, GP_ARG_FIRST
);
5415 /* Add DELTA to THIS_RTX. */
5418 rtx offset
= GEN_INT (delta
);
5419 if (!IMM12_OPERAND (delta
))
5421 loongarch_emit_move (temp1
, offset
);
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)
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. */
5447 insn
= emit_call_insn (gen_sibcall_internal (fnaddr
, const0_rtx
));
5448 SIBLING_CALL_P (insn
) = 1;
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
> ();
5480 loongarch_option_override_internal (struct gcc_options
*opts
)
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. */
5497 loongarch_cost
= &loongarch_rtx_cost_optimize_size
;
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
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");
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
;
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. */
5552 loongarch_option_override (void)
5554 loongarch_option_override_internal (&global_options
);
5557 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
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. */
5570 loongarch_eh_uses (unsigned int regno ATTRIBUTE_UNUSED
)
5575 /* Implement EPILOGUE_USES. */
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
)
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
;
5611 if (loongarch_address_insns (XEXP (mem1
, 0), mode
, false) == 0
5612 || loongarch_address_insns (XEXP (mem2
, 0), mode
, false) == 0)
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
))
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. */
5626 && (REGNO (reg1
) == REGNO (base1
) || (REGNO (reg2
) == REGNO (base1
))))
5629 /* Loading in same registers. */
5630 if (load_p
&& REGNO (reg1
) == REGNO (reg2
))
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
))
5640 if (abs (offset1
- offset2
) != GET_MODE_SIZE (mode
))
5646 /* Implement TARGET_TRAMPOLINE_INIT. */
5649 loongarch_trampoline_init (rtx m_tramp
, tree fndecl
, rtx chain_value
)
5651 rtx addr
, end_addr
, mem
;
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
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));
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. */
5671 /*pcaddi $static_chain,0
5672 ld.[dw] $tmp,$static_chain,target_function_offset
5673 ld.[dw] $static_chain,$static_chain,static_chain_offset
5675 trampoline
[i
++] = OP (0x18000000 | (STATIC_CHAIN_REGNUM
- GP_REG_FIRST
));
5676 trampoline
[i
++] = OP ((ptr_mode
== DImode
? 0x28c00000 : 0x28800000)
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));
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. */
5709 loongarch_hard_regno_caller_save_mode (unsigned int regno
, unsigned int nregs
,
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
);
5720 /* Implement TARGET_SPILL_CLASS. */
5723 loongarch_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED
,
5724 machine_mode mode ATTRIBUTE_UNUSED
)
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
5738 loongarch_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
5740 int *punsignedp ATTRIBUTE_UNUSED
,
5741 const_tree fntype ATTRIBUTE_UNUSED
,
5742 int for_return ATTRIBUTE_UNUSED
)
5746 if (type
!= NULL_TREE
)
5747 return promote_mode (type
, mode
, punsignedp
);
5749 unsignedp
= *punsignedp
;
5750 PROMOTE_MODE (mode
, unsignedp
, type
);
5751 *punsignedp
= unsignedp
;
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
)
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. */
5880 #undef TARGET_HAVE_TLS
5881 #define TARGET_HAVE_TLS HAVE_AS_TLS
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
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"