1 /* Subroutines for insn-output.c for VAX.
2 Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
32 #include "insn-attr.h"
39 #include "target-def.h"
41 static int follows_p
PARAMS ((rtx
, rtx
));
42 static void vax_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
44 static void vms_asm_out_constructor
PARAMS ((rtx
, int));
45 static void vms_asm_out_destructor
PARAMS ((rtx
, int));
46 static void vms_select_section
PARAMS ((tree
, int, unsigned HOST_WIDE_INT
));
47 static void vms_encode_section_info
PARAMS ((tree
, int));
48 static void vms_globalize_label
PARAMS ((FILE *, const char *));
51 /* Initialize the GCC target structure. */
52 #undef TARGET_ASM_ALIGNED_HI_OP
53 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
55 #undef TARGET_ASM_FUNCTION_PROLOGUE
56 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
59 #undef TARGET_ASM_SELECT_SECTION
60 #define TARGET_ASM_SELECT_SECTION vms_select_section
61 #undef TARGET_ENCODE_SECTION_INFO
62 #define TARGET_ENCODE_SECTION_INFO vms_encode_section_info
63 #undef TARGET_ASM_GLOBALIZE_LABEL
64 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label
67 struct gcc_target targetm
= TARGET_INITIALIZER
;
69 /* Generate the assembly code for function entry. FILE is a stdio
70 stream to output the code to. SIZE is an int: how many units of
71 temporary storage to allocate.
73 Refer to the array `regs_ever_live' to determine which registers to
74 save; `regs_ever_live[I]' is nonzero if register number I is ever
75 used in the function. This function is responsible for knowing
76 which registers should not be saved even if used. */
79 vax_output_function_prologue (file
, size
)
84 register int mask
= 0;
86 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
87 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
90 fprintf (file
, "\t.word 0x%x\n", mask
);
95 * This works for both gcc and g++. It first checks to see if
96 * the current routine is "main", which will only happen for
97 * GCC, and add the jsb if it is. If is not the case then try
98 * and see if __MAIN_NAME is part of current_function_name,
99 * which will only happen if we are running g++, and add the jsb
100 * if it is. In gcc there should never be a paren in the
101 * function name, and in g++ there is always a "(" in the
102 * function name, thus there should never be any confusion.
104 * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
105 * is required when linking with the VMS POSIX version of the C
106 * run-time library; using `subl2 $4,r0' is adequate but we use
107 * `clrl -(sp)' instead. The extra 4 bytes could be removed
108 * after the call because STARTING_FRAME_OFFSET's setting of -4
109 * will end up adding them right back again, but don't bother.
112 const char *p
= current_function_name
;
113 int is_main
= strcmp ("main", p
) == 0;
114 # define __MAIN_NAME " main("
116 while (!is_main
&& *p
!= '\0')
118 if (*p
== *__MAIN_NAME
119 && strncmp (p
, __MAIN_NAME
, sizeof __MAIN_NAME
- sizeof "") == 0)
126 fprintf (file
, "\tclrl -(%ssp)\n\tjsb _C$MAIN_ARGS\n",
130 size
-= STARTING_FRAME_OFFSET
;
132 fprintf (file
, "\tmovab %d(%ssp),%ssp\n", -size
, REGISTER_PREFIX
,
135 fprintf (file
, "\tsubl2 $%d,%ssp\n", size
, REGISTER_PREFIX
);
138 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
141 split_quadword_operands (operands
, low
, n
)
143 int n ATTRIBUTE_UNUSED
;
146 /* Split operands. */
148 low
[0] = low
[1] = low
[2] = 0;
149 for (i
= 0; i
< 3; i
++)
152 /* it's already been figured out */;
153 else if (GET_CODE (operands
[i
]) == MEM
154 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
156 rtx addr
= XEXP (operands
[i
], 0);
157 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
158 if (which_alternative
== 0 && i
== 0)
160 addr
= XEXP (operands
[i
], 0);
161 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
166 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
167 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
173 print_operand_address (file
, addr
)
177 register rtx reg1
, breg
, ireg
;
181 switch (GET_CODE (addr
))
185 addr
= XEXP (addr
, 0);
189 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
193 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
197 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
201 /* There can be either two or three things added here. One must be a
202 REG. One can be either a REG or a MULT of a REG and an appropriate
203 constant, and the third can only be a constant or a MEM.
205 We get these two or three things and put the constant or MEM in
206 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
207 a register and can't tell yet if it is a base or index register,
210 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
212 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
213 || GET_CODE (XEXP (addr
, 0)) == MEM
)
215 offset
= XEXP (addr
, 0);
216 addr
= XEXP (addr
, 1);
218 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
219 || GET_CODE (XEXP (addr
, 1)) == MEM
)
221 offset
= XEXP (addr
, 1);
222 addr
= XEXP (addr
, 0);
224 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
226 ireg
= XEXP (addr
, 1);
227 addr
= XEXP (addr
, 0);
229 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
231 ireg
= XEXP (addr
, 0);
232 addr
= XEXP (addr
, 1);
234 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
236 reg1
= XEXP (addr
, 1);
237 addr
= XEXP (addr
, 0);
239 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
241 reg1
= XEXP (addr
, 0);
242 addr
= XEXP (addr
, 1);
247 if (GET_CODE (addr
) == REG
)
254 else if (GET_CODE (addr
) == MULT
)
256 else if (GET_CODE (addr
) == PLUS
)
258 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
259 || GET_CODE (XEXP (addr
, 0)) == MEM
)
263 if (GET_CODE (offset
) == CONST_INT
)
264 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
265 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
266 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
270 offset
= XEXP (addr
, 0);
272 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
275 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
277 reg1
= XEXP (addr
, 0);
279 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
283 ireg
= XEXP (addr
, 0);
288 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
289 || GET_CODE (XEXP (addr
, 1)) == MEM
)
293 if (GET_CODE (offset
) == CONST_INT
)
294 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
295 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
296 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
300 offset
= XEXP (addr
, 1);
302 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
305 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
307 reg1
= XEXP (addr
, 1);
309 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
313 ireg
= XEXP (addr
, 1);
321 /* If REG1 is non-zero, figure out if it is a base or index register. */
324 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
335 output_address (offset
);
338 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
342 if (GET_CODE (ireg
) == MULT
)
343 ireg
= XEXP (ireg
, 0);
344 if (GET_CODE (ireg
) != REG
)
346 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
351 output_addr_const (file
, addr
);
359 switch (GET_CODE (op
))
391 register enum machine_mode mode
;
392 REAL_VALUE_TYPE r
, s
;
395 if (GET_CODE (c
) != CONST_DOUBLE
)
400 if (c
== const_tiny_rtx
[(int) mode
][0]
401 || c
== const_tiny_rtx
[(int) mode
][1]
402 || c
== const_tiny_rtx
[(int) mode
][2])
405 REAL_VALUE_FROM_CONST_DOUBLE (r
, c
);
407 for (i
= 0; i
< 7; i
++)
410 REAL_VALUE_FROM_INT (s
, x
, 0, mode
);
412 if (REAL_VALUES_EQUAL (r
, s
))
414 if (!exact_real_inverse (mode
, &s
))
416 if (REAL_VALUES_EQUAL (r
, s
))
423 /* Return the cost in cycles of a memory address, relative to register
426 Each of the following adds the indicated number of cycles:
430 1 - indexing and/or offset(register)
435 vax_address_cost (addr
)
438 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
439 rtx plus_op0
= 0, plus_op1
= 0;
441 switch (GET_CODE (addr
))
451 indexed
= 1; /* 2 on VAX 2 */
454 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
456 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
460 offset
= 1; /* 2 on VAX 2 */
462 case LABEL_REF
: /* this is probably a byte offset from the pc */
468 plus_op1
= XEXP (addr
, 0);
470 plus_op0
= XEXP (addr
, 0);
471 addr
= XEXP (addr
, 1);
474 indir
= 2; /* 3 on VAX 2 */
475 addr
= XEXP (addr
, 0);
481 /* Up to 3 things can be added in an address. They are stored in
482 plus_op0, plus_op1, and addr. */
496 /* Indexing and register+offset can both be used (except on a VAX 2)
497 without increasing execution time over either one alone. */
498 if (reg
&& indexed
&& offset
)
499 return reg
+ indir
+ offset
+ predec
;
500 return reg
+ indexed
+ indir
+ offset
+ predec
;
504 /* Cost of an expression on a VAX. This version has costs tuned for the
505 CVAX chip (found in the VAX 3 series) with comments for variations on
512 register enum rtx_code code
= GET_CODE (x
);
513 enum machine_mode mode
= GET_MODE (x
);
515 int i
= 0; /* may be modified in switch */
516 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
528 c
= 16; /* 4 on VAX 9000 */
531 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
534 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
539 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
542 return MAX_COST
; /* Mode is not supported. */
547 return MAX_COST
; /* Mode is not supported. */
552 c
= 30; /* highly variable */
553 else if (mode
== DFmode
)
554 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
557 c
= 11; /* 25 on VAX 2 */
564 return MAX_COST
; /* Mode is not supported. */
568 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
572 c
= 7; /* 17 on VAX 2 */
580 c
= 10; /* 6 on VAX 9000 */
584 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
585 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
586 fmt
= "e"; /* all constant rotate counts are short */
589 /* Check for small negative integer operand: subl2 can be used with
590 a short positive constant instead. */
591 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
592 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
595 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
601 /* AND is special because the first operand is complemented. */
603 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
605 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
614 else if (mode
== SFmode
)
616 else if (mode
== DImode
)
625 if (mode
== DImode
|| mode
== DFmode
)
626 c
= 5; /* 7 on VAX 2 */
628 c
= 3; /* 4 on VAX 2 */
630 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
632 return c
+ vax_address_cost (x
);
639 /* Now look inside the expression. Operands which are not registers or
640 short constants add to the cost.
642 FMT and I may have been adjusted in the switch above for instructions
643 which require special handling */
645 while (*fmt
++ == 'e')
647 register rtx op
= XEXP (x
, i
++);
648 code
= GET_CODE (op
);
650 /* A NOT is likely to be found as the first operand of an AND
651 (in which case the relevant cost is of the operand inside
652 the not) and not likely to be found anywhere else. */
654 op
= XEXP (op
, 0), code
= GET_CODE (op
);
659 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
660 c
+= 1; /* 2 on VAX 2 */
665 c
+= 1; /* 2 on VAX 2 */
668 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
670 /* Registers are faster than floating point constants -- even
671 those constants which can be encoded in a single byte. */
672 if (vax_float_literal (op
))
675 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
679 if (CONST_DOUBLE_HIGH (op
) != 0
680 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
685 c
+= 1; /* 2 on VAX 2 */
686 if (GET_CODE (XEXP (op
, 0)) != REG
)
687 c
+= vax_address_cost (XEXP (op
, 0));
700 /* Check a `double' value for validity for a particular machine mode. */
702 static const char *const float_strings
[] =
704 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
705 "-1.70141173319264430e+38",
706 "2.93873587705571877e-39", /* 2^-128 */
707 "-2.93873587705571877e-39"
710 static REAL_VALUE_TYPE float_values
[4];
712 static int inited_float_values
= 0;
716 check_float_value (mode
, d
, overflow
)
717 enum machine_mode mode
;
721 if (inited_float_values
== 0)
724 for (i
= 0; i
< 4; i
++)
726 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
729 inited_float_values
= 1;
734 memcpy (d
, &float_values
[0], sizeof (REAL_VALUE_TYPE
));
738 if ((mode
) == SFmode
)
741 memcpy (&r
, d
, sizeof (REAL_VALUE_TYPE
));
742 if (REAL_VALUES_LESS (float_values
[0], r
))
744 memcpy (d
, &float_values
[0], sizeof (REAL_VALUE_TYPE
));
747 else if (REAL_VALUES_LESS (r
, float_values
[1]))
749 memcpy (d
, &float_values
[1], sizeof (REAL_VALUE_TYPE
));
752 else if (REAL_VALUES_LESS (dconst0
, r
)
753 && REAL_VALUES_LESS (r
, float_values
[2]))
755 memcpy (d
, &dconst0
, sizeof (REAL_VALUE_TYPE
));
758 else if (REAL_VALUES_LESS (r
, dconst0
)
759 && REAL_VALUES_LESS (float_values
[3], r
))
761 memcpy (d
, &dconst0
, sizeof (REAL_VALUE_TYPE
));
770 /* Additional support code for VMS target. */
772 /* Linked list of all externals that are to be emitted when optimizing
773 for the global pointer if they haven't been declared by the end of
774 the program with an appropriate .comm or initialization. */
778 struct extern_list
*next
; /* next external */
779 const char *name
; /* name of the external */
780 int size
; /* external's actual size */
781 int in_const
; /* section type flag */
782 } *extern_head
= 0, *pending_head
= 0;
784 /* Check whether NAME is already on the external definition list. If not,
785 add it to either that list or the pending definition list. */
788 vms_check_external (decl
, name
, pending
)
793 register struct extern_list
*p
, *p0
;
795 for (p
= extern_head
; p
; p
= p
->next
)
796 if (!strcmp (p
->name
, name
))
799 for (p
= pending_head
, p0
= 0; p
; p0
= p
, p
= p
->next
)
800 if (!strcmp (p
->name
, name
))
805 /* Was pending, but has now been defined; move it to other list. */
806 if (p
== pending_head
)
807 pending_head
= p
->next
;
810 p
->next
= extern_head
;
815 /* Not previously seen; create a new list entry. */
816 p
= (struct extern_list
*) xmalloc (sizeof (struct extern_list
));
821 /* Save the size and section type and link to `pending' list. */
822 p
->size
= (DECL_SIZE (decl
) == 0) ? 0 :
823 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
824 size_int (BITS_PER_UNIT
)));
825 p
->in_const
= (TREE_READONLY (decl
) && ! TREE_THIS_VOLATILE (decl
));
827 p
->next
= pending_head
;
832 /* Size and section type don't matter; link to `declared' list. */
833 p
->size
= p
->in_const
= 0; /* arbitrary init */
835 p
->next
= extern_head
;
842 vms_flush_pending_externals (file
)
845 register struct extern_list
*p
;
849 /* Move next pending declaration to the "done" list. */
851 pending_head
= p
->next
;
852 p
->next
= extern_head
;
855 /* Now output the actual declaration. */
860 fputs (".comm ", file
);
861 assemble_name (file
, p
->name
);
862 fprintf (file
, ",%d\n", p
->size
);
867 vms_asm_out_constructor (symbol
, priority
)
869 int priority ATTRIBUTE_UNUSED
;
871 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
873 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
874 assemble_name (asm_out_file
, XSTR (symbol
, 0));
875 fputc ('\n', asm_out_file
);
879 vms_asm_out_destructor (symbol
, priority
)
881 int priority ATTRIBUTE_UNUSED
;
883 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
885 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
886 assemble_name (asm_out_file
, XSTR (symbol
, 0));
887 fputc ('\n', asm_out_file
);
891 vms_select_section (exp
, reloc
, align
)
893 int reloc ATTRIBUTE_UNUSED
;
894 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
;
896 if (TREE_CODE (exp
) == VAR_DECL
)
898 if (TREE_READONLY (exp
) && ! TREE_THIS_VOLATILE (exp
)
899 && DECL_INITIAL (exp
)
900 && (DECL_INITIAL (exp
) == error_mark_node
901 || TREE_CONSTANT (DECL_INITIAL (exp
))))
903 if (TREE_PUBLIC (exp
))
911 if (TREE_CODE_CLASS (TREE_CODE (exp
)) == 'c')
913 if (TREE_CODE (exp
) == STRING_CST
&& flag_writable_strings
)
920 /* Make sure that external variables are correctly addressed. Under VMS
921 there is some brain damage in the linker that requires us to do this. */
924 vms_encode_section_info (decl
, first
)
926 int first ATTRIBUTE_UNUSED
;
928 if (DECL_EXTERNAL (decl
) && TREE_PUBLIC (decl
))
929 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)) = 1;
932 /* This is how to output a command to make the user-level label named NAME
933 defined for reference from other files. */
935 vms_globalize_label (stream
, name
)
939 default_globalize_label (stream
, name
);
940 vms_check_external (NULL_TREE
, name
, 0);
942 #endif /* VMS_TARGET */
944 /* Additional support code for VMS host. */
945 /* ??? This should really be in libiberty; vax.c is a target file. */
946 #ifdef QSORT_WORKAROUND
948 Do not use VAXCRTL's qsort() due to a severe bug: once you've
949 sorted something which has a size that's an exact multiple of 4
950 and is longword aligned, you cannot safely sort anything which
951 is either not a multiple of 4 in size or not longword aligned.
952 A static "move-by-longword" optimization flag inside qsort() is
953 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
954 and was finally fixed in VMS V5.5-2.
956 In this work-around an insertion sort is used for simplicity.
957 The qsort code from glibc should probably be used instead.
960 not_qsort (array
, count
, size
, compare
)
962 unsigned count
, size
;
966 if (size
== sizeof (short))
969 register short *next
, *prev
;
970 short tmp
, *base
= array
;
972 for (next
= base
, i
= count
- 1; i
> 0; i
--)
975 if ((*compare
)(next
, prev
) < 0)
978 do *(prev
+ 1) = *prev
;
979 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
984 else if (size
== sizeof (long))
987 register long *next
, *prev
;
988 long tmp
, *base
= array
;
990 for (next
= base
, i
= count
- 1; i
> 0; i
--)
993 if ((*compare
)(next
, prev
) < 0)
996 do *(prev
+ 1) = *prev
;
997 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
1002 else /* arbitrary size */
1005 register char *next
, *prev
, *tmp
= alloca (size
), *base
= array
;
1007 for (next
= base
, i
= count
- 1; i
> 0; i
--)
1008 { /* count-1 forward iterations */
1009 prev
= next
, next
+= size
; /* increment front pointer */
1010 if ((*compare
)(next
, prev
) < 0)
1011 { /* found element out of order; move others up then re-insert */
1012 memcpy (tmp
, next
, size
); /* save smaller element */
1013 do { memcpy (prev
+ size
, prev
, size
); /* move larger elem. up */
1014 prev
-= size
; /* decrement back pointer */
1015 } while (prev
>= base
? (*compare
)(tmp
, prev
) < 0 : 0);
1016 memcpy (prev
+ size
, tmp
, size
); /* restore small element */
1026 #endif /* QSORT_WORKAROUND */
1028 /* Return 1 if insn A follows B. */
1036 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
1043 /* Returns 1 if we know operand OP was 0 before INSN. */
1046 reg_was_0_p (insn
, op
)
1051 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
1052 /* Make sure the insn that stored the 0 is still present
1053 and doesn't follow INSN in the insn sequence. */
1054 && ! INSN_DELETED_P (XEXP (link
, 0))
1055 && GET_CODE (XEXP (link
, 0)) != NOTE
1056 && ! follows_p (XEXP (link
, 0), insn
)
1057 /* Make sure cross jumping didn't happen here. */
1058 && no_labels_between_p (XEXP (link
, 0), insn
)
1059 /* Make sure the reg hasn't been clobbered. */
1060 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));