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