1132727Skan/* Emit RTL for the GCC expander. 290075Sobrien Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3169699Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 4169699Skan Free Software Foundation, Inc. 518334Speter 690075SobrienThis file is part of GCC. 718334Speter 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1218334Speter 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169699SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169699Skan02110-1301, USA. */ 2218334Speter 2318334Speter 2418334Speter/* Middle-to-low level generation of rtx code and insns. 2518334Speter 26169699Skan This file contains support functions for creating rtl expressions 27169699Skan and manipulating them in the doubly-linked chain of insns. 2818334Speter 2918334Speter The patterns of the insns are created by machine-dependent 3018334Speter routines in insn-emit.c, which is generated automatically from 31169699Skan the machine description. These routines make the individual rtx's 32169699Skan of the pattern with `gen_rtx_fmt_ee' and others in genrtl.[ch], 33169699Skan which are automatically generated from rtl.def; what is machine 34169699Skan dependent is the kind of rtx's they make and what arguments they 35169699Skan use. */ 3618334Speter 3718334Speter#include "config.h" 3850397Sobrien#include "system.h" 39132727Skan#include "coretypes.h" 40132727Skan#include "tm.h" 4152284Sobrien#include "toplev.h" 4218334Speter#include "rtl.h" 4318334Speter#include "tree.h" 4490075Sobrien#include "tm_p.h" 4518334Speter#include "flags.h" 4618334Speter#include "function.h" 4718334Speter#include "expr.h" 4818334Speter#include "regs.h" 4950397Sobrien#include "hard-reg-set.h" 5090075Sobrien#include "hashtab.h" 5118334Speter#include "insn-config.h" 5250397Sobrien#include "recog.h" 5318334Speter#include "real.h" 5450397Sobrien#include "bitmap.h" 5590075Sobrien#include "basic-block.h" 5690075Sobrien#include "ggc.h" 5790075Sobrien#include "debug.h" 5890075Sobrien#include "langhooks.h" 59169699Skan#include "tree-pass.h" 6018334Speter 6118334Speter/* Commonly used modes. */ 6218334Speter 6350397Sobrienenum machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT. */ 6450397Sobrienenum machine_mode word_mode; /* Mode whose width is BITS_PER_WORD. */ 6550397Sobrienenum machine_mode double_mode; /* Mode whose width is DOUBLE_TYPE_SIZE. */ 6650397Sobrienenum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */ 6718334Speter 6818334Speter 6918334Speter/* This is *not* reset after each function. It gives each CODE_LABEL 7018334Speter in the entire compilation a unique label number. */ 7118334Speter 72132727Skanstatic GTY(()) int label_num = 1; 7318334Speter 7418334Speter/* Nonzero means do not generate NOTEs for source line numbers. */ 7518334Speter 7618334Speterstatic int no_line_numbers; 7718334Speter 7818334Speter/* Commonly used rtx's, so that we only need space for one copy. 7918334Speter These are initialized once for the entire compilation. 80117404Skan All of these are unique; no other rtx-object will be equal to any 81117404Skan of these. */ 8218334Speter 8390075Sobrienrtx global_rtl[GR_MAX]; 8452284Sobrien 85117404Skan/* Commonly used RTL for hard registers. These objects are not necessarily 86117404Skan unique, so we allocate them separately from global_rtl. They are 87117404Skan initialized once per compilation unit, then copied into regno_reg_rtx 88117404Skan at the beginning of each function. */ 89117404Skanstatic GTY(()) rtx static_regno_reg_rtx[FIRST_PSEUDO_REGISTER]; 90117404Skan 9118334Speter/* We record floating-point CONST_DOUBLEs in each floating-point mode for 9218334Speter the values of 0, 1, and 2. For the integer entries and VOIDmode, we 9318334Speter record a copy of const[012]_rtx. */ 9418334Speter 9518334Speterrtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE]; 9618334Speter 9750397Sobrienrtx const_true_rtx; 9850397Sobrien 9918334SpeterREAL_VALUE_TYPE dconst0; 10018334SpeterREAL_VALUE_TYPE dconst1; 10118334SpeterREAL_VALUE_TYPE dconst2; 102132727SkanREAL_VALUE_TYPE dconst3; 103132727SkanREAL_VALUE_TYPE dconst10; 10418334SpeterREAL_VALUE_TYPE dconstm1; 105132727SkanREAL_VALUE_TYPE dconstm2; 106132727SkanREAL_VALUE_TYPE dconsthalf; 107132727SkanREAL_VALUE_TYPE dconstthird; 108132727SkanREAL_VALUE_TYPE dconstpi; 109132727SkanREAL_VALUE_TYPE dconste; 11018334Speter 11118334Speter/* All references to the following fixed hard registers go through 11218334Speter these unique rtl objects. On machines where the frame-pointer and 11318334Speter arg-pointer are the same register, they use the same unique object. 11418334Speter 11518334Speter After register allocation, other rtl objects which used to be pseudo-regs 11618334Speter may be clobbered to refer to the frame-pointer register. 11718334Speter But references that were originally to the frame-pointer can be 11818334Speter distinguished from the others because they contain frame_pointer_rtx. 11918334Speter 12018334Speter When to use frame_pointer_rtx and hard_frame_pointer_rtx is a little 12118334Speter tricky: until register elimination has taken place hard_frame_pointer_rtx 12290075Sobrien should be used if it is being set, and frame_pointer_rtx otherwise. After 12318334Speter register elimination hard_frame_pointer_rtx should always be used. 12418334Speter On machines where the two registers are same (most) then these are the 12518334Speter same. 12618334Speter 12718334Speter In an inline procedure, the stack and frame pointer rtxs may not be 12818334Speter used for anything else. */ 12918334Speterrtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */ 13018334Speterrtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */ 13118334Speterrtx pic_offset_table_rtx; /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */ 13218334Speter 13350397Sobrien/* This is used to implement __builtin_return_address for some machines. 13450397Sobrien See for instance the MIPS port. */ 13550397Sobrienrtx return_address_pointer_rtx; /* (REG:Pmode RETURN_ADDRESS_POINTER_REGNUM) */ 13618334Speter 13718334Speter/* We make one copy of (const_int C) where C is in 13818334Speter [- MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT] 13918334Speter to save space during the compilation and simplify comparisons of 14018334Speter integers. */ 14118334Speter 14290075Sobrienrtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1]; 14318334Speter 14490075Sobrien/* A hash table storing CONST_INTs whose absolute value is greater 14590075Sobrien than MAX_SAVED_CONST_INT. */ 14618334Speter 147117404Skanstatic GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) 148117404Skan htab_t const_int_htab; 14918334Speter 15090075Sobrien/* A hash table storing memory attribute structures. */ 151117404Skanstatic GTY ((if_marked ("ggc_marked_p"), param_is (struct mem_attrs))) 152117404Skan htab_t mem_attrs_htab; 15318334Speter 154132727Skan/* A hash table storing register attribute structures. */ 155132727Skanstatic GTY ((if_marked ("ggc_marked_p"), param_is (struct reg_attrs))) 156132727Skan htab_t reg_attrs_htab; 157132727Skan 158117404Skan/* A hash table storing all CONST_DOUBLEs. */ 159117404Skanstatic GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) 160117404Skan htab_t const_double_htab; 16118334Speter 16290075Sobrien#define first_insn (cfun->emit->x_first_insn) 16390075Sobrien#define last_insn (cfun->emit->x_last_insn) 16490075Sobrien#define cur_insn_uid (cfun->emit->x_cur_insn_uid) 165132727Skan#define last_location (cfun->emit->x_last_location) 16690075Sobrien#define first_label_num (cfun->emit->x_first_label_num) 16718334Speter 168132727Skanstatic rtx make_call_insn_raw (rtx); 169132727Skanstatic rtx find_line_note (rtx); 170132727Skanstatic rtx change_address_1 (rtx, enum machine_mode, rtx, int); 171132727Skanstatic void unshare_all_decls (tree); 172132727Skanstatic void reset_used_decls (tree); 173132727Skanstatic void mark_label_nuses (rtx); 174132727Skanstatic hashval_t const_int_htab_hash (const void *); 175132727Skanstatic int const_int_htab_eq (const void *, const void *); 176132727Skanstatic hashval_t const_double_htab_hash (const void *); 177132727Skanstatic int const_double_htab_eq (const void *, const void *); 178132727Skanstatic rtx lookup_const_double (rtx); 179132727Skanstatic hashval_t mem_attrs_htab_hash (const void *); 180132727Skanstatic int mem_attrs_htab_eq (const void *, const void *); 181132727Skanstatic mem_attrs *get_mem_attrs (HOST_WIDE_INT, tree, rtx, rtx, unsigned int, 182132727Skan enum machine_mode); 183132727Skanstatic hashval_t reg_attrs_htab_hash (const void *); 184132727Skanstatic int reg_attrs_htab_eq (const void *, const void *); 185132727Skanstatic reg_attrs *get_reg_attrs (tree, int); 186132727Skanstatic tree component_ref_for_mem_expr (tree); 187169699Skanstatic rtx gen_const_vector (enum machine_mode, int); 188132727Skanstatic void copy_rtx_if_shared_1 (rtx *orig); 18950397Sobrien 19090075Sobrien/* Probability of the conditional branch currently proceeded by try_split. 19190075Sobrien Set to -1 otherwise. */ 19290075Sobrienint split_branch_probability = -1; 19390075Sobrien 19490075Sobrien/* Returns a hash code for X (which is a really a CONST_INT). */ 19518334Speter 19690075Sobrienstatic hashval_t 197132727Skanconst_int_htab_hash (const void *x) 19890075Sobrien{ 199132727Skan return (hashval_t) INTVAL ((rtx) x); 20090075Sobrien} 20118334Speter 202117404Skan/* Returns nonzero if the value represented by X (which is really a 20390075Sobrien CONST_INT) is the same as that given by Y (which is really a 20490075Sobrien HOST_WIDE_INT *). */ 20518334Speter 20690075Sobrienstatic int 207132727Skanconst_int_htab_eq (const void *x, const void *y) 20890075Sobrien{ 209117404Skan return (INTVAL ((rtx) x) == *((const HOST_WIDE_INT *) y)); 21090075Sobrien} 21118334Speter 212117404Skan/* Returns a hash code for X (which is really a CONST_DOUBLE). */ 213117404Skanstatic hashval_t 214132727Skanconst_double_htab_hash (const void *x) 215117404Skan{ 216117404Skan rtx value = (rtx) x; 217117404Skan hashval_t h; 218117404Skan 219117404Skan if (GET_MODE (value) == VOIDmode) 220117404Skan h = CONST_DOUBLE_LOW (value) ^ CONST_DOUBLE_HIGH (value); 221117404Skan else 222132727Skan { 223132727Skan h = real_hash (CONST_DOUBLE_REAL_VALUE (value)); 224132727Skan /* MODE is used in the comparison, so it should be in the hash. */ 225132727Skan h ^= GET_MODE (value); 226132727Skan } 227117404Skan return h; 228117404Skan} 229117404Skan 230117404Skan/* Returns nonzero if the value represented by X (really a ...) 231117404Skan is the same as that represented by Y (really a ...) */ 232117404Skanstatic int 233132727Skanconst_double_htab_eq (const void *x, const void *y) 234117404Skan{ 235117404Skan rtx a = (rtx)x, b = (rtx)y; 236117404Skan 237117404Skan if (GET_MODE (a) != GET_MODE (b)) 238117404Skan return 0; 239117404Skan if (GET_MODE (a) == VOIDmode) 240117404Skan return (CONST_DOUBLE_LOW (a) == CONST_DOUBLE_LOW (b) 241117404Skan && CONST_DOUBLE_HIGH (a) == CONST_DOUBLE_HIGH (b)); 242117404Skan else 243117404Skan return real_identical (CONST_DOUBLE_REAL_VALUE (a), 244117404Skan CONST_DOUBLE_REAL_VALUE (b)); 245117404Skan} 246117404Skan 24790075Sobrien/* Returns a hash code for X (which is a really a mem_attrs *). */ 24818334Speter 24990075Sobrienstatic hashval_t 250132727Skanmem_attrs_htab_hash (const void *x) 25190075Sobrien{ 25290075Sobrien mem_attrs *p = (mem_attrs *) x; 25318334Speter 25490075Sobrien return (p->alias ^ (p->align * 1000) 25590075Sobrien ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000) 25690075Sobrien ^ ((p->size ? INTVAL (p->size) : 0) * 2500000) 257169699Skan ^ (size_t) iterative_hash_expr (p->expr, 0)); 25890075Sobrien} 25918334Speter 260117404Skan/* Returns nonzero if the value represented by X (which is really a 26190075Sobrien mem_attrs *) is the same as that given by Y (which is also really a 26290075Sobrien mem_attrs *). */ 26318334Speter 26490075Sobrienstatic int 265132727Skanmem_attrs_htab_eq (const void *x, const void *y) 26690075Sobrien{ 26790075Sobrien mem_attrs *p = (mem_attrs *) x; 26890075Sobrien mem_attrs *q = (mem_attrs *) y; 26918334Speter 270169699Skan return (p->alias == q->alias && p->offset == q->offset 271169699Skan && p->size == q->size && p->align == q->align 272169699Skan && (p->expr == q->expr 273169699Skan || (p->expr != NULL_TREE && q->expr != NULL_TREE 274169699Skan && operand_equal_p (p->expr, q->expr, 0)))); 27590075Sobrien} 27618334Speter 27790075Sobrien/* Allocate a new mem_attrs structure and insert it into the hash table if 27890075Sobrien one identical to it is not already in the table. We are doing this for 27990075Sobrien MEM of mode MODE. */ 28090075Sobrien 28190075Sobrienstatic mem_attrs * 282132727Skanget_mem_attrs (HOST_WIDE_INT alias, tree expr, rtx offset, rtx size, 283132727Skan unsigned int align, enum machine_mode mode) 28490075Sobrien{ 28590075Sobrien mem_attrs attrs; 28690075Sobrien void **slot; 28790075Sobrien 288132727Skan /* If everything is the default, we can just return zero. 289132727Skan This must match what the corresponding MEM_* macros return when the 290132727Skan field is not present. */ 29190075Sobrien if (alias == 0 && expr == 0 && offset == 0 29290075Sobrien && (size == 0 29390075Sobrien || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size))) 294132727Skan && (STRICT_ALIGNMENT && mode != BLKmode 295132727Skan ? align == GET_MODE_ALIGNMENT (mode) : align == BITS_PER_UNIT)) 29690075Sobrien return 0; 29790075Sobrien 29890075Sobrien attrs.alias = alias; 29990075Sobrien attrs.expr = expr; 30090075Sobrien attrs.offset = offset; 30190075Sobrien attrs.size = size; 30290075Sobrien attrs.align = align; 30390075Sobrien 30490075Sobrien slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT); 30590075Sobrien if (*slot == 0) 30690075Sobrien { 30790075Sobrien *slot = ggc_alloc (sizeof (mem_attrs)); 30890075Sobrien memcpy (*slot, &attrs, sizeof (mem_attrs)); 30990075Sobrien } 31090075Sobrien 31190075Sobrien return *slot; 31290075Sobrien} 31390075Sobrien 314132727Skan/* Returns a hash code for X (which is a really a reg_attrs *). */ 315132727Skan 316132727Skanstatic hashval_t 317132727Skanreg_attrs_htab_hash (const void *x) 318132727Skan{ 319132727Skan reg_attrs *p = (reg_attrs *) x; 320132727Skan 321132727Skan return ((p->offset * 1000) ^ (long) p->decl); 322132727Skan} 323132727Skan 324132727Skan/* Returns nonzero if the value represented by X (which is really a 325132727Skan reg_attrs *) is the same as that given by Y (which is also really a 326132727Skan reg_attrs *). */ 327132727Skan 328132727Skanstatic int 329132727Skanreg_attrs_htab_eq (const void *x, const void *y) 330132727Skan{ 331132727Skan reg_attrs *p = (reg_attrs *) x; 332132727Skan reg_attrs *q = (reg_attrs *) y; 333132727Skan 334132727Skan return (p->decl == q->decl && p->offset == q->offset); 335132727Skan} 336132727Skan/* Allocate a new reg_attrs structure and insert it into the hash table if 337132727Skan one identical to it is not already in the table. We are doing this for 338132727Skan MEM of mode MODE. */ 339132727Skan 340132727Skanstatic reg_attrs * 341132727Skanget_reg_attrs (tree decl, int offset) 342132727Skan{ 343132727Skan reg_attrs attrs; 344132727Skan void **slot; 345132727Skan 346132727Skan /* If everything is the default, we can just return zero. */ 347132727Skan if (decl == 0 && offset == 0) 348132727Skan return 0; 349132727Skan 350132727Skan attrs.decl = decl; 351132727Skan attrs.offset = offset; 352132727Skan 353132727Skan slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT); 354132727Skan if (*slot == 0) 355132727Skan { 356132727Skan *slot = ggc_alloc (sizeof (reg_attrs)); 357132727Skan memcpy (*slot, &attrs, sizeof (reg_attrs)); 358132727Skan } 359132727Skan 360132727Skan return *slot; 361132727Skan} 362132727Skan 36390075Sobrien/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and 36490075Sobrien don't attempt to share with the various global pieces of rtl (such as 36590075Sobrien frame_pointer_rtx). */ 36690075Sobrien 36750397Sobrienrtx 368132727Skangen_raw_REG (enum machine_mode mode, int regno) 36990075Sobrien{ 37090075Sobrien rtx x = gen_rtx_raw_REG (mode, regno); 37190075Sobrien ORIGINAL_REGNO (x) = regno; 37290075Sobrien return x; 37390075Sobrien} 37490075Sobrien 37590075Sobrien/* There are some RTL codes that require special attention; the generation 37690075Sobrien functions do the raw handling. If you add to this list, modify 37790075Sobrien special_rtx in gengenrtl.c as well. */ 37890075Sobrien 37990075Sobrienrtx 380132727Skangen_rtx_CONST_INT (enum machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg) 38150397Sobrien{ 38290075Sobrien void **slot; 38390075Sobrien 38450397Sobrien if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT) 38590075Sobrien return const_int_rtx[arg + MAX_SAVED_CONST_INT]; 38618334Speter 38750397Sobrien#if STORE_FLAG_VALUE != 1 && STORE_FLAG_VALUE != -1 38850397Sobrien if (const_true_rtx && arg == STORE_FLAG_VALUE) 38950397Sobrien return const_true_rtx; 39050397Sobrien#endif 39150397Sobrien 39290075Sobrien /* Look up the CONST_INT in the hash table. */ 39390075Sobrien slot = htab_find_slot_with_hash (const_int_htab, &arg, 39490075Sobrien (hashval_t) arg, INSERT); 39590075Sobrien if (*slot == 0) 39690075Sobrien *slot = gen_rtx_raw_CONST_INT (VOIDmode, arg); 39790075Sobrien 39890075Sobrien return (rtx) *slot; 39950397Sobrien} 40050397Sobrien 401102793Skanrtx 402132727Skangen_int_mode (HOST_WIDE_INT c, enum machine_mode mode) 403102793Skan{ 404102793Skan return GEN_INT (trunc_int_for_mode (c, mode)); 405102793Skan} 406102793Skan 407117404Skan/* CONST_DOUBLEs might be created from pairs of integers, or from 408117404Skan REAL_VALUE_TYPEs. Also, their length is known only at run time, 409117404Skan so we cannot use gen_rtx_raw_CONST_DOUBLE. */ 41090075Sobrien 411117404Skan/* Determine whether REAL, a CONST_DOUBLE, already exists in the 412117404Skan hash table. If so, return its counterpart; otherwise add it 413117404Skan to the hash table and return it. */ 414117404Skanstatic rtx 415132727Skanlookup_const_double (rtx real) 416117404Skan{ 417117404Skan void **slot = htab_find_slot (const_double_htab, real, INSERT); 418117404Skan if (*slot == 0) 419117404Skan *slot = real; 420117404Skan 421117404Skan return (rtx) *slot; 422117404Skan} 423117404Skan 424117404Skan/* Return a CONST_DOUBLE rtx for a floating-point value specified by 425117404Skan VALUE in mode MODE. */ 42650397Sobrienrtx 427132727Skanconst_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode) 42852284Sobrien{ 429117404Skan rtx real = rtx_alloc (CONST_DOUBLE); 430117404Skan PUT_MODE (real, mode); 43152284Sobrien 432169699Skan real->u.rv = value; 43352284Sobrien 434117404Skan return lookup_const_double (real); 435117404Skan} 43652284Sobrien 437117404Skan/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair 438117404Skan of ints: I0 is the low-order word and I1 is the high-order word. 439117404Skan Do not use this routine for non-integer modes; convert to 440117404Skan REAL_VALUE_TYPE and use CONST_DOUBLE_FROM_REAL_VALUE. */ 441117404Skan 442117404Skanrtx 443132727Skanimmed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode) 444117404Skan{ 445117404Skan rtx value; 446117404Skan unsigned int i; 447117404Skan 448169699Skan /* There are the following cases (note that there are no modes with 449169699Skan HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode) < 2 * HOST_BITS_PER_WIDE_INT): 450169699Skan 451169699Skan 1) If GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT, then we use 452169699Skan gen_int_mode. 453169699Skan 2) GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT, but the value of 454169699Skan the integer fits into HOST_WIDE_INT anyway (i.e., i1 consists only 455169699Skan from copies of the sign bit, and sign of i0 and i1 are the same), then 456169699Skan we return a CONST_INT for i0. 457169699Skan 3) Otherwise, we create a CONST_DOUBLE for i0 and i1. */ 458117404Skan if (mode != VOIDmode) 459117404Skan { 460169699Skan gcc_assert (GET_MODE_CLASS (mode) == MODE_INT 461169699Skan || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT 462169699Skan /* We can get a 0 for an error mark. */ 463169699Skan || GET_MODE_CLASS (mode) == MODE_VECTOR_INT 464169699Skan || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT); 465117404Skan 466169699Skan if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) 467169699Skan return gen_int_mode (i0, mode); 468117404Skan 469169699Skan gcc_assert (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT); 470117404Skan } 471117404Skan 472117404Skan /* If this integer fits in one word, return a CONST_INT. */ 473117404Skan if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) 474117404Skan return GEN_INT (i0); 475117404Skan 476117404Skan /* We use VOIDmode for integers. */ 477117404Skan value = rtx_alloc (CONST_DOUBLE); 478117404Skan PUT_MODE (value, VOIDmode); 479117404Skan 480117404Skan CONST_DOUBLE_LOW (value) = i0; 481117404Skan CONST_DOUBLE_HIGH (value) = i1; 482117404Skan 483117404Skan for (i = 2; i < (sizeof CONST_DOUBLE_FORMAT - 1); i++) 484117404Skan XWINT (value, i) = 0; 485117404Skan 486117404Skan return lookup_const_double (value); 48752284Sobrien} 48852284Sobrien 48952284Sobrienrtx 490132727Skangen_rtx_REG (enum machine_mode mode, unsigned int regno) 49150397Sobrien{ 49250397Sobrien /* In case the MD file explicitly references the frame pointer, have 49350397Sobrien all such references point to the same frame pointer. This is 49450397Sobrien used during frame pointer elimination to distinguish the explicit 49550397Sobrien references to these registers from pseudos that happened to be 49650397Sobrien assigned to them. 49750397Sobrien 49850397Sobrien If we have eliminated the frame pointer or arg pointer, we will 49950397Sobrien be using it as a normal register, for example as a spill 50050397Sobrien register. In such cases, we might be accessing it in a mode that 50150397Sobrien is not Pmode and therefore cannot use the pre-allocated rtx. 50250397Sobrien 50350397Sobrien Also don't do this when we are making new REGs in reload, since 50450397Sobrien we don't want to get confused with the real pointers. */ 50550397Sobrien 50650397Sobrien if (mode == Pmode && !reload_in_progress) 50750397Sobrien { 508117404Skan if (regno == FRAME_POINTER_REGNUM 509117404Skan && (!reload_completed || frame_pointer_needed)) 51050397Sobrien return frame_pointer_rtx; 51150397Sobrien#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM 512117404Skan if (regno == HARD_FRAME_POINTER_REGNUM 513117404Skan && (!reload_completed || frame_pointer_needed)) 51450397Sobrien return hard_frame_pointer_rtx; 51550397Sobrien#endif 51650397Sobrien#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM 51750397Sobrien if (regno == ARG_POINTER_REGNUM) 51850397Sobrien return arg_pointer_rtx; 51950397Sobrien#endif 52050397Sobrien#ifdef RETURN_ADDRESS_POINTER_REGNUM 52150397Sobrien if (regno == RETURN_ADDRESS_POINTER_REGNUM) 52250397Sobrien return return_address_pointer_rtx; 52350397Sobrien#endif 524132727Skan if (regno == (unsigned) PIC_OFFSET_TABLE_REGNUM 52590075Sobrien && fixed_regs[PIC_OFFSET_TABLE_REGNUM]) 526117404Skan return pic_offset_table_rtx; 52750397Sobrien if (regno == STACK_POINTER_REGNUM) 52850397Sobrien return stack_pointer_rtx; 52950397Sobrien } 53050397Sobrien 531117404Skan#if 0 532117404Skan /* If the per-function register table has been set up, try to re-use 533117404Skan an existing entry in that table to avoid useless generation of RTL. 534117404Skan 535117404Skan This code is disabled for now until we can fix the various backends 536117404Skan which depend on having non-shared hard registers in some cases. Long 537117404Skan term we want to re-enable this code as it can significantly cut down 538117404Skan on the amount of useless RTL that gets generated. 539117404Skan 540117404Skan We'll also need to fix some code that runs after reload that wants to 541117404Skan set ORIGINAL_REGNO. */ 542117404Skan 543117404Skan if (cfun 544117404Skan && cfun->emit 545117404Skan && regno_reg_rtx 546117404Skan && regno < FIRST_PSEUDO_REGISTER 547117404Skan && reg_raw_mode[regno] == mode) 548117404Skan return regno_reg_rtx[regno]; 549117404Skan#endif 550117404Skan 55190075Sobrien return gen_raw_REG (mode, regno); 55250397Sobrien} 55350397Sobrien 55450397Sobrienrtx 555132727Skangen_rtx_MEM (enum machine_mode mode, rtx addr) 55650397Sobrien{ 55750397Sobrien rtx rt = gen_rtx_raw_MEM (mode, addr); 55850397Sobrien 55950397Sobrien /* This field is not cleared by the mere allocation of the rtx, so 56050397Sobrien we clear it here. */ 56190075Sobrien MEM_ATTRS (rt) = 0; 56250397Sobrien 56350397Sobrien return rt; 56450397Sobrien} 56550397Sobrien 566169699Skan/* Generate a memory referring to non-trapping constant memory. */ 567169699Skan 56890075Sobrienrtx 569169699Skangen_const_mem (enum machine_mode mode, rtx addr) 57090075Sobrien{ 571169699Skan rtx mem = gen_rtx_MEM (mode, addr); 572169699Skan MEM_READONLY_P (mem) = 1; 573169699Skan MEM_NOTRAP_P (mem) = 1; 574169699Skan return mem; 57590075Sobrien} 57690075Sobrien 577169699Skan/* Generate a MEM referring to fixed portions of the frame, e.g., register 578169699Skan save areas. */ 57990075Sobrien 58090075Sobrienrtx 581169699Skangen_frame_mem (enum machine_mode mode, rtx addr) 58290075Sobrien{ 583169699Skan rtx mem = gen_rtx_MEM (mode, addr); 584169699Skan MEM_NOTRAP_P (mem) = 1; 585169699Skan set_mem_alias_set (mem, get_frame_alias_set ()); 586169699Skan return mem; 58790075Sobrien} 58818334Speter 589169699Skan/* Generate a MEM referring to a temporary use of the stack, not part 590169699Skan of the fixed stack frame. For example, something which is pushed 591169699Skan by a target splitter. */ 59218334Speterrtx 593169699Skangen_tmp_stack_mem (enum machine_mode mode, rtx addr) 59418334Speter{ 595169699Skan rtx mem = gen_rtx_MEM (mode, addr); 596169699Skan MEM_NOTRAP_P (mem) = 1; 597169699Skan if (!current_function_calls_alloca) 598169699Skan set_mem_alias_set (mem, get_frame_alias_set ()); 599169699Skan return mem; 600169699Skan} 60118334Speter 602169699Skan/* We want to create (subreg:OMODE (obj:IMODE) OFFSET). Return true if 603169699Skan this construct would be valid, and false otherwise. */ 60418334Speter 605169699Skanbool 606169699Skanvalidate_subreg (enum machine_mode omode, enum machine_mode imode, 607169699Skan rtx reg, unsigned int offset) 608169699Skan{ 609169699Skan unsigned int isize = GET_MODE_SIZE (imode); 610169699Skan unsigned int osize = GET_MODE_SIZE (omode); 61152284Sobrien 612169699Skan /* All subregs must be aligned. */ 613169699Skan if (offset % osize != 0) 614169699Skan return false; 61590075Sobrien 616169699Skan /* The subreg offset cannot be outside the inner object. */ 617169699Skan if (offset >= isize) 618169699Skan return false; 61952284Sobrien 620169699Skan /* ??? This should not be here. Temporarily continue to allow word_mode 621169699Skan subregs of anything. The most common offender is (subreg:SI (reg:DF)). 622169699Skan Generally, backends are doing something sketchy but it'll take time to 623169699Skan fix them all. */ 624169699Skan if (omode == word_mode) 625169699Skan ; 626169699Skan /* ??? Similarly, e.g. with (subreg:DF (reg:TI)). Though store_bit_field 627169699Skan is the culprit here, and not the backends. */ 628169699Skan else if (osize >= UNITS_PER_WORD && isize >= osize) 629169699Skan ; 630169699Skan /* Allow component subregs of complex and vector. Though given the below 631169699Skan extraction rules, it's not always clear what that means. */ 632169699Skan else if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode)) 633169699Skan && GET_MODE_INNER (imode) == omode) 634169699Skan ; 635169699Skan /* ??? x86 sse code makes heavy use of *paradoxical* vector subregs, 636169699Skan i.e. (subreg:V4SF (reg:SF) 0). This surely isn't the cleanest way to 637169699Skan represent this. It's questionable if this ought to be represented at 638169699Skan all -- why can't this all be hidden in post-reload splitters that make 639169699Skan arbitrarily mode changes to the registers themselves. */ 640169699Skan else if (VECTOR_MODE_P (omode) && GET_MODE_INNER (omode) == imode) 641169699Skan ; 642169699Skan /* Subregs involving floating point modes are not allowed to 643169699Skan change size. Therefore (subreg:DI (reg:DF) 0) is fine, but 644169699Skan (subreg:SI (reg:DF) 0) isn't. */ 645169699Skan else if (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode)) 646169699Skan { 647169699Skan if (isize != osize) 648169699Skan return false; 649169699Skan } 65052284Sobrien 651169699Skan /* Paradoxical subregs must have offset zero. */ 652169699Skan if (osize > isize) 653169699Skan return offset == 0; 65452284Sobrien 655169699Skan /* This is a normal subreg. Verify that the offset is representable. */ 65618334Speter 657169699Skan /* For hard registers, we already have most of these rules collected in 658169699Skan subreg_offset_representable_p. */ 659169699Skan if (reg && REG_P (reg) && HARD_REGISTER_P (reg)) 660169699Skan { 661169699Skan unsigned int regno = REGNO (reg); 66218334Speter 663169699Skan#ifdef CANNOT_CHANGE_MODE_CLASS 664169699Skan if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode)) 665169699Skan && GET_MODE_INNER (imode) == omode) 666169699Skan ; 667169699Skan else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, omode)) 668169699Skan return false; 669169699Skan#endif 67018334Speter 671169699Skan return subreg_offset_representable_p (regno, imode, offset, omode); 672169699Skan } 67318334Speter 674169699Skan /* For pseudo registers, we want most of the same checks. Namely: 675169699Skan If the register no larger than a word, the subreg must be lowpart. 676169699Skan If the register is larger than a word, the subreg must be the lowpart 677169699Skan of a subword. A subreg does *not* perform arbitrary bit extraction. 678169699Skan Given that we've already checked mode/offset alignment, we only have 679169699Skan to check subword subregs here. */ 680169699Skan if (osize < UNITS_PER_WORD) 681169699Skan { 682169699Skan enum machine_mode wmode = isize > UNITS_PER_WORD ? word_mode : imode; 683169699Skan unsigned int low_off = subreg_lowpart_offset (omode, wmode); 684169699Skan if (offset % UNITS_PER_WORD != low_off) 685169699Skan return false; 686169699Skan } 687169699Skan return true; 688169699Skan} 68918334Speter 690169699Skanrtx 691169699Skangen_rtx_SUBREG (enum machine_mode mode, rtx reg, int offset) 692169699Skan{ 693169699Skan gcc_assert (validate_subreg (mode, GET_MODE (reg), reg, offset)); 694169699Skan return gen_rtx_raw_SUBREG (mode, reg, offset); 695169699Skan} 69618334Speter 697169699Skan/* Generate a SUBREG representing the least-significant part of REG if MODE 698169699Skan is smaller than mode of REG, otherwise paradoxical SUBREG. */ 69918334Speter 700169699Skanrtx 701169699Skangen_lowpart_SUBREG (enum machine_mode mode, rtx reg) 702169699Skan{ 703169699Skan enum machine_mode inmode; 70450397Sobrien 705169699Skan inmode = GET_MODE (reg); 706169699Skan if (inmode == VOIDmode) 707169699Skan inmode = mode; 708169699Skan return gen_rtx_SUBREG (mode, reg, 709169699Skan subreg_lowpart_offset (mode, inmode)); 71018334Speter} 711169699Skan 71218334Speter/* gen_rtvec (n, [rt1, ..., rtn]) 71318334Speter** 71418334Speter** This routine creates an rtvec and stores within it the 71518334Speter** pointers to rtx's which are its arguments. 71618334Speter*/ 71718334Speter 71818334Speter/*VARARGS1*/ 71918334Speterrtvec 720132727Skangen_rtvec (int n, ...) 72118334Speter{ 72290075Sobrien int i, save_n; 72318334Speter rtx *vector; 724132727Skan va_list p; 72518334Speter 726132727Skan va_start (p, n); 72718334Speter 72818334Speter if (n == 0) 72918334Speter return NULL_RTVEC; /* Don't allocate an empty rtvec... */ 73018334Speter 731132727Skan vector = alloca (n * sizeof (rtx)); 73218334Speter 73318334Speter for (i = 0; i < n; i++) 73418334Speter vector[i] = va_arg (p, rtx); 73518334Speter 73690075Sobrien /* The definition of VA_* in K&R C causes `n' to go out of scope. */ 73790075Sobrien save_n = n; 738132727Skan va_end (p); 73990075Sobrien 74090075Sobrien return gen_rtvec_v (save_n, vector); 74118334Speter} 74218334Speter 74318334Speterrtvec 744132727Skangen_rtvec_v (int n, rtx *argp) 74518334Speter{ 74690075Sobrien int i; 74790075Sobrien rtvec rt_val; 74818334Speter 74918334Speter if (n == 0) 75018334Speter return NULL_RTVEC; /* Don't allocate an empty rtvec... */ 75118334Speter 75218334Speter rt_val = rtvec_alloc (n); /* Allocate an rtvec... */ 75318334Speter 75418334Speter for (i = 0; i < n; i++) 75590075Sobrien rt_val->elem[i] = *argp++; 75618334Speter 75718334Speter return rt_val; 75818334Speter} 75918334Speter 76018334Speter/* Generate a REG rtx for a new pseudo register of mode MODE. 76118334Speter This pseudo is assigned the next sequential register number. */ 76218334Speter 76318334Speterrtx 764132727Skangen_reg_rtx (enum machine_mode mode) 76518334Speter{ 76690075Sobrien struct function *f = cfun; 76790075Sobrien rtx val; 76818334Speter 76952284Sobrien /* Don't let anything called after initial flow analysis create new 77052284Sobrien registers. */ 771169699Skan gcc_assert (!no_new_pseudos); 77218334Speter 77390075Sobrien if (generating_concat_p 77490075Sobrien && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 77590075Sobrien || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)) 77618334Speter { 77718334Speter /* For complex modes, don't make a single pseudo. 77818334Speter Instead, make a CONCAT of two pseudos. 77918334Speter This allows noncontiguous allocation of the real and imaginary parts, 78018334Speter which makes much better code. Besides, allocating DCmode 78118334Speter pseudos overstrains reload on some machines like the 386. */ 78218334Speter rtx realpart, imagpart; 783117404Skan enum machine_mode partmode = GET_MODE_INNER (mode); 78418334Speter 78518334Speter realpart = gen_reg_rtx (partmode); 78618334Speter imagpart = gen_reg_rtx (partmode); 78750397Sobrien return gen_rtx_CONCAT (mode, realpart, imagpart); 78818334Speter } 78918334Speter 790132727Skan /* Make sure regno_pointer_align, and regno_reg_rtx are large 79118334Speter enough to have an element for this pseudo reg number. */ 79218334Speter 79390075Sobrien if (reg_rtx_no == f->emit->regno_pointer_align_length) 79418334Speter { 79590075Sobrien int old_size = f->emit->regno_pointer_align_length; 79690075Sobrien char *new; 79718334Speter rtx *new1; 79818334Speter 799117404Skan new = ggc_realloc (f->emit->regno_pointer_align, old_size * 2); 80090075Sobrien memset (new + old_size, 0, old_size); 80190075Sobrien f->emit->regno_pointer_align = (unsigned char *) new; 80250397Sobrien 803132727Skan new1 = ggc_realloc (f->emit->x_regno_reg_rtx, 804132727Skan old_size * 2 * sizeof (rtx)); 80590075Sobrien memset (new1 + old_size, 0, old_size * sizeof (rtx)); 80618334Speter regno_reg_rtx = new1; 80718334Speter 80890075Sobrien f->emit->regno_pointer_align_length = old_size * 2; 80918334Speter } 81018334Speter 81190075Sobrien val = gen_raw_REG (mode, reg_rtx_no); 81218334Speter regno_reg_rtx[reg_rtx_no++] = val; 81318334Speter return val; 81418334Speter} 81518334Speter 816169699Skan/* Generate a register with same attributes as REG, but offsetted by OFFSET. 817169699Skan Do the big endian correction if needed. */ 818132727Skan 819132727Skanrtx 820132727Skangen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int offset) 821132727Skan{ 822132727Skan rtx new = gen_rtx_REG (mode, regno); 823169699Skan tree decl; 824169699Skan HOST_WIDE_INT var_size; 825169699Skan 826169699Skan /* PR middle-end/14084 827169699Skan The problem appears when a variable is stored in a larger register 828169699Skan and later it is used in the original mode or some mode in between 829169699Skan or some part of variable is accessed. 830169699Skan 831169699Skan On little endian machines there is no problem because 832169699Skan the REG_OFFSET of the start of the variable is the same when 833169699Skan accessed in any mode (it is 0). 834169699Skan 835169699Skan However, this is not true on big endian machines. 836169699Skan The offset of the start of the variable is different when accessed 837169699Skan in different modes. 838169699Skan When we are taking a part of the REG we have to change the OFFSET 839169699Skan from offset WRT size of mode of REG to offset WRT size of variable. 840169699Skan 841169699Skan If we would not do the big endian correction the resulting REG_OFFSET 842169699Skan would be larger than the size of the DECL. 843169699Skan 844169699Skan Examples of correction, for BYTES_BIG_ENDIAN WORDS_BIG_ENDIAN machine: 845169699Skan 846169699Skan REG.mode MODE DECL size old offset new offset description 847169699Skan DI SI 4 4 0 int32 in SImode 848169699Skan DI SI 1 4 0 char in SImode 849169699Skan DI QI 1 7 0 char in QImode 850169699Skan DI QI 4 5 1 1st element in QImode 851169699Skan of char[4] 852169699Skan DI HI 4 6 2 1st element in HImode 853169699Skan of int16[2] 854169699Skan 855169699Skan If the size of DECL is equal or greater than the size of REG 856169699Skan we can't do this correction because the register holds the 857169699Skan whole variable or a part of the variable and thus the REG_OFFSET 858169699Skan is already correct. */ 859169699Skan 860169699Skan decl = REG_EXPR (reg); 861169699Skan if ((BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN) 862169699Skan && decl != NULL 863169699Skan && offset > 0 864169699Skan && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode) 865169699Skan && ((var_size = int_size_in_bytes (TREE_TYPE (decl))) > 0 866169699Skan && var_size < GET_MODE_SIZE (GET_MODE (reg)))) 867169699Skan { 868169699Skan int offset_le; 869169699Skan 870169699Skan /* Convert machine endian to little endian WRT size of mode of REG. */ 871169699Skan if (WORDS_BIG_ENDIAN) 872169699Skan offset_le = ((GET_MODE_SIZE (GET_MODE (reg)) - 1 - offset) 873169699Skan / UNITS_PER_WORD) * UNITS_PER_WORD; 874169699Skan else 875169699Skan offset_le = (offset / UNITS_PER_WORD) * UNITS_PER_WORD; 876169699Skan 877169699Skan if (BYTES_BIG_ENDIAN) 878169699Skan offset_le += ((GET_MODE_SIZE (GET_MODE (reg)) - 1 - offset) 879169699Skan % UNITS_PER_WORD); 880169699Skan else 881169699Skan offset_le += offset % UNITS_PER_WORD; 882169699Skan 883169699Skan if (offset_le >= var_size) 884169699Skan { 885169699Skan /* MODE is wider than the variable so the new reg will cover 886169699Skan the whole variable so the resulting OFFSET should be 0. */ 887169699Skan offset = 0; 888169699Skan } 889169699Skan else 890169699Skan { 891169699Skan /* Convert little endian to machine endian WRT size of variable. */ 892169699Skan if (WORDS_BIG_ENDIAN) 893169699Skan offset = ((var_size - 1 - offset_le) 894169699Skan / UNITS_PER_WORD) * UNITS_PER_WORD; 895169699Skan else 896169699Skan offset = (offset_le / UNITS_PER_WORD) * UNITS_PER_WORD; 897169699Skan 898169699Skan if (BYTES_BIG_ENDIAN) 899169699Skan offset += ((var_size - 1 - offset_le) 900169699Skan % UNITS_PER_WORD); 901169699Skan else 902169699Skan offset += offset_le % UNITS_PER_WORD; 903169699Skan } 904169699Skan } 905169699Skan 906132727Skan REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg), 907132727Skan REG_OFFSET (reg) + offset); 908132727Skan return new; 909132727Skan} 910132727Skan 911132727Skan/* Set the decl for MEM to DECL. */ 912132727Skan 913132727Skanvoid 914132727Skanset_reg_attrs_from_mem (rtx reg, rtx mem) 915132727Skan{ 916132727Skan if (MEM_OFFSET (mem) && GET_CODE (MEM_OFFSET (mem)) == CONST_INT) 917132727Skan REG_ATTRS (reg) 918132727Skan = get_reg_attrs (MEM_EXPR (mem), INTVAL (MEM_OFFSET (mem))); 919132727Skan} 920132727Skan 921132727Skan/* Set the register attributes for registers contained in PARM_RTX. 922132727Skan Use needed values from memory attributes of MEM. */ 923132727Skan 924132727Skanvoid 925132727Skanset_reg_attrs_for_parm (rtx parm_rtx, rtx mem) 926132727Skan{ 927169699Skan if (REG_P (parm_rtx)) 928132727Skan set_reg_attrs_from_mem (parm_rtx, mem); 929132727Skan else if (GET_CODE (parm_rtx) == PARALLEL) 930132727Skan { 931132727Skan /* Check for a NULL entry in the first slot, used to indicate that the 932132727Skan parameter goes both on the stack and in registers. */ 933132727Skan int i = XEXP (XVECEXP (parm_rtx, 0, 0), 0) ? 0 : 1; 934132727Skan for (; i < XVECLEN (parm_rtx, 0); i++) 935132727Skan { 936132727Skan rtx x = XVECEXP (parm_rtx, 0, i); 937169699Skan if (REG_P (XEXP (x, 0))) 938132727Skan REG_ATTRS (XEXP (x, 0)) 939132727Skan = get_reg_attrs (MEM_EXPR (mem), 940132727Skan INTVAL (XEXP (x, 1))); 941132727Skan } 942132727Skan } 943132727Skan} 944132727Skan 945132727Skan/* Assign the RTX X to declaration T. */ 946132727Skanvoid 947132727Skanset_decl_rtl (tree t, rtx x) 948132727Skan{ 949169699Skan DECL_WRTL_CHECK (t)->decl_with_rtl.rtl = x; 950132727Skan 951132727Skan if (!x) 952132727Skan return; 953132727Skan /* For register, we maintain the reverse information too. */ 954169699Skan if (REG_P (x)) 955132727Skan REG_ATTRS (x) = get_reg_attrs (t, 0); 956132727Skan else if (GET_CODE (x) == SUBREG) 957132727Skan REG_ATTRS (SUBREG_REG (x)) 958132727Skan = get_reg_attrs (t, -SUBREG_BYTE (x)); 959132727Skan if (GET_CODE (x) == CONCAT) 960132727Skan { 961132727Skan if (REG_P (XEXP (x, 0))) 962132727Skan REG_ATTRS (XEXP (x, 0)) = get_reg_attrs (t, 0); 963132727Skan if (REG_P (XEXP (x, 1))) 964132727Skan REG_ATTRS (XEXP (x, 1)) 965132727Skan = get_reg_attrs (t, GET_MODE_UNIT_SIZE (GET_MODE (XEXP (x, 0)))); 966132727Skan } 967132727Skan if (GET_CODE (x) == PARALLEL) 968132727Skan { 969132727Skan int i; 970132727Skan for (i = 0; i < XVECLEN (x, 0); i++) 971132727Skan { 972132727Skan rtx y = XVECEXP (x, 0, i); 973132727Skan if (REG_P (XEXP (y, 0))) 974132727Skan REG_ATTRS (XEXP (y, 0)) = get_reg_attrs (t, INTVAL (XEXP (y, 1))); 975132727Skan } 976132727Skan } 977132727Skan} 978132727Skan 979169699Skan/* Assign the RTX X to parameter declaration T. */ 980169699Skanvoid 981169699Skanset_decl_incoming_rtl (tree t, rtx x) 982169699Skan{ 983169699Skan DECL_INCOMING_RTL (t) = x; 984169699Skan 985169699Skan if (!x) 986169699Skan return; 987169699Skan /* For register, we maintain the reverse information too. */ 988169699Skan if (REG_P (x)) 989169699Skan REG_ATTRS (x) = get_reg_attrs (t, 0); 990169699Skan else if (GET_CODE (x) == SUBREG) 991169699Skan REG_ATTRS (SUBREG_REG (x)) 992169699Skan = get_reg_attrs (t, -SUBREG_BYTE (x)); 993169699Skan if (GET_CODE (x) == CONCAT) 994169699Skan { 995169699Skan if (REG_P (XEXP (x, 0))) 996169699Skan REG_ATTRS (XEXP (x, 0)) = get_reg_attrs (t, 0); 997169699Skan if (REG_P (XEXP (x, 1))) 998169699Skan REG_ATTRS (XEXP (x, 1)) 999169699Skan = get_reg_attrs (t, GET_MODE_UNIT_SIZE (GET_MODE (XEXP (x, 0)))); 1000169699Skan } 1001169699Skan if (GET_CODE (x) == PARALLEL) 1002169699Skan { 1003169699Skan int i, start; 1004169699Skan 1005169699Skan /* Check for a NULL entry, used to indicate that the parameter goes 1006169699Skan both on the stack and in registers. */ 1007169699Skan if (XEXP (XVECEXP (x, 0, 0), 0)) 1008169699Skan start = 0; 1009169699Skan else 1010169699Skan start = 1; 1011169699Skan 1012169699Skan for (i = start; i < XVECLEN (x, 0); i++) 1013169699Skan { 1014169699Skan rtx y = XVECEXP (x, 0, i); 1015169699Skan if (REG_P (XEXP (y, 0))) 1016169699Skan REG_ATTRS (XEXP (y, 0)) = get_reg_attrs (t, INTVAL (XEXP (y, 1))); 1017169699Skan } 1018169699Skan } 1019169699Skan} 1020169699Skan 102150397Sobrien/* Identify REG (which may be a CONCAT) as a user register. */ 102218334Speter 102318334Spetervoid 1024132727Skanmark_user_reg (rtx reg) 102518334Speter{ 102650397Sobrien if (GET_CODE (reg) == CONCAT) 102750397Sobrien { 102850397Sobrien REG_USERVAR_P (XEXP (reg, 0)) = 1; 102950397Sobrien REG_USERVAR_P (XEXP (reg, 1)) = 1; 103050397Sobrien } 103150397Sobrien else 1032169699Skan { 1033169699Skan gcc_assert (REG_P (reg)); 1034169699Skan REG_USERVAR_P (reg) = 1; 1035169699Skan } 103650397Sobrien} 103750397Sobrien 103850397Sobrien/* Identify REG as a probable pointer register and show its alignment 103950397Sobrien as ALIGN, if nonzero. */ 104050397Sobrien 104150397Sobrienvoid 1042132727Skanmark_reg_pointer (rtx reg, int align) 104350397Sobrien{ 104490075Sobrien if (! REG_POINTER (reg)) 104552284Sobrien { 104690075Sobrien REG_POINTER (reg) = 1; 104750397Sobrien 104852284Sobrien if (align) 104952284Sobrien REGNO_POINTER_ALIGN (REGNO (reg)) = align; 105052284Sobrien } 105152284Sobrien else if (align && align < REGNO_POINTER_ALIGN (REGNO (reg))) 1052132727Skan /* We can no-longer be sure just how aligned this pointer is. */ 105350397Sobrien REGNO_POINTER_ALIGN (REGNO (reg)) = align; 105418334Speter} 105518334Speter 105618334Speter/* Return 1 plus largest pseudo reg number used in the current function. */ 105718334Speter 105818334Speterint 1059132727Skanmax_reg_num (void) 106018334Speter{ 106118334Speter return reg_rtx_no; 106218334Speter} 106318334Speter 106418334Speter/* Return 1 + the largest label number used so far in the current function. */ 106518334Speter 106618334Speterint 1067132727Skanmax_label_num (void) 106818334Speter{ 106918334Speter return label_num; 107018334Speter} 107118334Speter 107218334Speter/* Return first label number used in this function (if any were used). */ 107318334Speter 107418334Speterint 1075132727Skanget_first_label_num (void) 107618334Speter{ 107718334Speter return first_label_num; 107818334Speter} 107990075Sobrien 1080169699Skan/* If the rtx for label was created during the expansion of a nested 1081169699Skan function, then first_label_num won't include this label number. 1082169699Skan Fix this now so that array indicies work later. */ 108390075Sobrien 1084169699Skanvoid 1085169699Skanmaybe_set_first_label_num (rtx x) 1086169699Skan{ 1087169699Skan if (CODE_LABEL_NUMBER (x) < first_label_num) 1088169699Skan first_label_num = CODE_LABEL_NUMBER (x); 108990075Sobrien} 1090169699Skan 109118334Speter/* Return a value representing some low-order bits of X, where the number 109218334Speter of low-order bits is given by MODE. Note that no conversion is done 109390075Sobrien between floating-point and fixed-point values, rather, the bit 109418334Speter representation is returned. 109518334Speter 109618334Speter This function handles the cases in common between gen_lowpart, below, 109718334Speter and two variants in cse.c and combine.c. These are the cases that can 109818334Speter be safely handled at all points in the compilation. 109918334Speter 110018334Speter If this is not a case we can handle, return 0. */ 110118334Speter 110218334Speterrtx 1103132727Skangen_lowpart_common (enum machine_mode mode, rtx x) 110418334Speter{ 110590075Sobrien int msize = GET_MODE_SIZE (mode); 1106132727Skan int xsize; 110790075Sobrien int offset = 0; 1108132727Skan enum machine_mode innermode; 110918334Speter 1110132727Skan /* Unfortunately, this routine doesn't take a parameter for the mode of X, 1111132727Skan so we have to make one up. Yuk. */ 1112132727Skan innermode = GET_MODE (x); 1113169699Skan if (GET_CODE (x) == CONST_INT 1114169699Skan && msize * BITS_PER_UNIT <= HOST_BITS_PER_WIDE_INT) 1115132727Skan innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0); 1116132727Skan else if (innermode == VOIDmode) 1117132727Skan innermode = mode_for_size (HOST_BITS_PER_WIDE_INT * 2, MODE_INT, 0); 1118132727Skan 1119132727Skan xsize = GET_MODE_SIZE (innermode); 1120132727Skan 1121169699Skan gcc_assert (innermode != VOIDmode && innermode != BLKmode); 1122132727Skan 1123132727Skan if (innermode == mode) 112418334Speter return x; 112518334Speter 112618334Speter /* MODE must occupy no more words than the mode of X. */ 1127132727Skan if ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD 1128132727Skan > ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)) 112918334Speter return 0; 113018334Speter 113199396Sobrien /* Don't allow generating paradoxical FLOAT_MODE subregs. */ 1132169699Skan if (SCALAR_FLOAT_MODE_P (mode) && msize > xsize) 113399396Sobrien return 0; 113499396Sobrien 1135132727Skan offset = subreg_lowpart_offset (mode, innermode); 113618334Speter 113718334Speter if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) 113818334Speter && (GET_MODE_CLASS (mode) == MODE_INT 113918334Speter || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)) 114018334Speter { 114118334Speter /* If we are getting the low-order part of something that has been 114218334Speter sign- or zero-extended, we can either just use the object being 114318334Speter extended or make a narrower extension. If we want an even smaller 114418334Speter piece than the size of the object being extended, call ourselves 114518334Speter recursively. 114618334Speter 114718334Speter This case is used mostly by combine and cse. */ 114818334Speter 114918334Speter if (GET_MODE (XEXP (x, 0)) == mode) 115018334Speter return XEXP (x, 0); 1151132727Skan else if (msize < GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))) 115218334Speter return gen_lowpart_common (mode, XEXP (x, 0)); 1153132727Skan else if (msize < xsize) 115450397Sobrien return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0)); 115518334Speter } 1156169699Skan else if (GET_CODE (x) == SUBREG || REG_P (x) 1157132727Skan || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR 1158132727Skan || GET_CODE (x) == CONST_DOUBLE || GET_CODE (x) == CONST_INT) 1159132727Skan return simplify_gen_subreg (mode, x, innermode, offset); 116018334Speter 1161132727Skan /* Otherwise, we can't do this. */ 1162132727Skan return 0; 1163132727Skan} 1164132727Skan 116518334Speterrtx 1166132727Skangen_highpart (enum machine_mode mode, rtx x) 116718334Speter{ 116890075Sobrien unsigned int msize = GET_MODE_SIZE (mode); 116990075Sobrien rtx result; 117090075Sobrien 117118334Speter /* This case loses if X is a subreg. To catch bugs early, 117218334Speter complain if an invalid MODE is used even in other cases. */ 1173169699Skan gcc_assert (msize <= UNITS_PER_WORD 1174169699Skan || msize == (unsigned int) GET_MODE_UNIT_SIZE (GET_MODE (x))); 117518334Speter 117690075Sobrien result = simplify_gen_subreg (mode, x, GET_MODE (x), 117790075Sobrien subreg_highpart_offset (mode, GET_MODE (x))); 1178169699Skan gcc_assert (result); 1179169699Skan 118090075Sobrien /* simplify_gen_subreg is not guaranteed to return a valid operand for 118190075Sobrien the target if we have a MEM. gen_highpart must return a valid operand, 118290075Sobrien emitting code if necessary to do so. */ 1183169699Skan if (MEM_P (result)) 1184169699Skan { 1185169699Skan result = validize_mem (result); 1186169699Skan gcc_assert (result); 1187169699Skan } 1188169699Skan 118990075Sobrien return result; 119090075Sobrien} 119190075Sobrien 1192132727Skan/* Like gen_highpart, but accept mode of EXP operand in case EXP can 119390075Sobrien be VOIDmode constant. */ 119490075Sobrienrtx 1195132727Skangen_highpart_mode (enum machine_mode outermode, enum machine_mode innermode, rtx exp) 119690075Sobrien{ 119790075Sobrien if (GET_MODE (exp) != VOIDmode) 119818334Speter { 1199169699Skan gcc_assert (GET_MODE (exp) == innermode); 120090075Sobrien return gen_highpart (outermode, exp); 120118334Speter } 120290075Sobrien return simplify_gen_subreg (outermode, exp, innermode, 120390075Sobrien subreg_highpart_offset (outermode, innermode)); 120490075Sobrien} 1205117404Skan 120690075Sobrien/* Return offset in bytes to get OUTERMODE low part 120790075Sobrien of the value in mode INNERMODE stored in memory in target format. */ 120818334Speter 120990075Sobrienunsigned int 1210132727Skansubreg_lowpart_offset (enum machine_mode outermode, enum machine_mode innermode) 121190075Sobrien{ 121290075Sobrien unsigned int offset = 0; 121390075Sobrien int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); 121450397Sobrien 121590075Sobrien if (difference > 0) 121690075Sobrien { 121750397Sobrien if (WORDS_BIG_ENDIAN) 121890075Sobrien offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 121990075Sobrien if (BYTES_BIG_ENDIAN) 122090075Sobrien offset += difference % UNITS_PER_WORD; 122190075Sobrien } 122218334Speter 122390075Sobrien return offset; 122490075Sobrien} 122590075Sobrien 122690075Sobrien/* Return offset in bytes to get OUTERMODE high part 122790075Sobrien of the value in mode INNERMODE stored in memory in target format. */ 122890075Sobrienunsigned int 1229132727Skansubreg_highpart_offset (enum machine_mode outermode, enum machine_mode innermode) 123090075Sobrien{ 123190075Sobrien unsigned int offset = 0; 123290075Sobrien int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); 123390075Sobrien 1234169699Skan gcc_assert (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode)); 123590075Sobrien 123690075Sobrien if (difference > 0) 123790075Sobrien { 123890075Sobrien if (! WORDS_BIG_ENDIAN) 123990075Sobrien offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 124090075Sobrien if (! BYTES_BIG_ENDIAN) 124190075Sobrien offset += difference % UNITS_PER_WORD; 124218334Speter } 124390075Sobrien 124490075Sobrien return offset; 124518334Speter} 124618334Speter 124718334Speter/* Return 1 iff X, assumed to be a SUBREG, 124818334Speter refers to the least significant part of its containing reg. 124918334Speter If X is not a SUBREG, always return 1 (it is its own low part!). */ 125018334Speter 125118334Speterint 1252132727Skansubreg_lowpart_p (rtx x) 125318334Speter{ 125418334Speter if (GET_CODE (x) != SUBREG) 125518334Speter return 1; 125650397Sobrien else if (GET_MODE (SUBREG_REG (x)) == VOIDmode) 125750397Sobrien return 0; 125818334Speter 125990075Sobrien return (subreg_lowpart_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x))) 126090075Sobrien == SUBREG_BYTE (x)); 126118334Speter} 126218334Speter 126390075Sobrien/* Return subword OFFSET of operand OP. 126490075Sobrien The word number, OFFSET, is interpreted as the word number starting 126590075Sobrien at the low-order address. OFFSET 0 is the low-order word if not 126690075Sobrien WORDS_BIG_ENDIAN, otherwise it is the high-order word. 126750397Sobrien 126890075Sobrien If we cannot extract the required word, we return zero. Otherwise, 126990075Sobrien an rtx corresponding to the requested word will be returned. 127050397Sobrien 127190075Sobrien VALIDATE_ADDRESS is nonzero if the address should be validated. Before 127290075Sobrien reload has completed, a valid address will always be returned. After 127390075Sobrien reload, if a valid address cannot be returned, we return zero. 127490075Sobrien 127590075Sobrien If VALIDATE_ADDRESS is zero, we simply form the required address; validating 127690075Sobrien it is the responsibility of the caller. 127790075Sobrien 127890075Sobrien MODE is the mode of OP in case it is a CONST_INT. 127990075Sobrien 128090075Sobrien ??? This is still rather broken for some cases. The problem for the 128190075Sobrien moment is that all callers of this thing provide no 'goal mode' to 128290075Sobrien tell us to work with. This exists because all callers were written 128390075Sobrien in a word based SUBREG world. 128490075Sobrien Now use of this function can be deprecated by simplify_subreg in most 128590075Sobrien cases. 128690075Sobrien */ 128790075Sobrien 128890075Sobrienrtx 1289132727Skanoperand_subword (rtx op, unsigned int offset, int validate_address, enum machine_mode mode) 129090075Sobrien{ 129190075Sobrien if (mode == VOIDmode) 129290075Sobrien mode = GET_MODE (op); 129390075Sobrien 1294169699Skan gcc_assert (mode != VOIDmode); 129590075Sobrien 129690075Sobrien /* If OP is narrower than a word, fail. */ 129790075Sobrien if (mode != BLKmode 129890075Sobrien && (GET_MODE_SIZE (mode) < UNITS_PER_WORD)) 129990075Sobrien return 0; 130090075Sobrien 130190075Sobrien /* If we want a word outside OP, return zero. */ 130290075Sobrien if (mode != BLKmode 130390075Sobrien && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode)) 130490075Sobrien return const0_rtx; 130590075Sobrien 130690075Sobrien /* Form a new MEM at the requested address. */ 1307169699Skan if (MEM_P (op)) 130890075Sobrien { 130990075Sobrien rtx new = adjust_address_nv (op, word_mode, offset * UNITS_PER_WORD); 131090075Sobrien 131190075Sobrien if (! validate_address) 131290075Sobrien return new; 131390075Sobrien 131490075Sobrien else if (reload_completed) 131590075Sobrien { 131690075Sobrien if (! strict_memory_address_p (word_mode, XEXP (new, 0))) 131790075Sobrien return 0; 131890075Sobrien } 131990075Sobrien else 132090075Sobrien return replace_equiv_address (new, XEXP (new, 0)); 132190075Sobrien } 132290075Sobrien 132390075Sobrien /* Rest can be handled by simplify_subreg. */ 132490075Sobrien return simplify_gen_subreg (word_mode, op, mode, (offset * UNITS_PER_WORD)); 132518334Speter} 132618334Speter 1327169699Skan/* Similar to `operand_subword', but never return 0. If we can't 1328169699Skan extract the required subword, put OP into a register and try again. 1329169699Skan The second attempt must succeed. We always validate the address in 1330169699Skan this case. 133118334Speter 133218334Speter MODE is the mode of OP, in case it is CONST_INT. */ 133318334Speter 133418334Speterrtx 1335132727Skanoperand_subword_force (rtx op, unsigned int offset, enum machine_mode mode) 133618334Speter{ 133790075Sobrien rtx result = operand_subword (op, offset, 1, mode); 133818334Speter 133918334Speter if (result) 134018334Speter return result; 134118334Speter 134218334Speter if (mode != BLKmode && mode != VOIDmode) 134350397Sobrien { 134450397Sobrien /* If this is a register which can not be accessed by words, copy it 134550397Sobrien to a pseudo register. */ 1346169699Skan if (REG_P (op)) 134750397Sobrien op = copy_to_reg (op); 134850397Sobrien else 134950397Sobrien op = force_reg (mode, op); 135050397Sobrien } 135118334Speter 135290075Sobrien result = operand_subword (op, offset, 1, mode); 1353169699Skan gcc_assert (result); 135418334Speter 135518334Speter return result; 135618334Speter} 135718334Speter 135890075Sobrien/* Within a MEM_EXPR, we care about either (1) a component ref of a decl, 135990075Sobrien or (2) a component ref of something variable. Represent the later with 136090075Sobrien a NULL expression. */ 136118334Speter 136290075Sobrienstatic tree 1363132727Skancomponent_ref_for_mem_expr (tree ref) 136490075Sobrien{ 136590075Sobrien tree inner = TREE_OPERAND (ref, 0); 136690075Sobrien 136790075Sobrien if (TREE_CODE (inner) == COMPONENT_REF) 136890075Sobrien inner = component_ref_for_mem_expr (inner); 136990075Sobrien else 137090075Sobrien { 137190075Sobrien /* Now remove any conversions: they don't change what the underlying 1372169699Skan object is. Likewise for SAVE_EXPR. */ 137390075Sobrien while (TREE_CODE (inner) == NOP_EXPR || TREE_CODE (inner) == CONVERT_EXPR 137490075Sobrien || TREE_CODE (inner) == NON_LVALUE_EXPR 137590075Sobrien || TREE_CODE (inner) == VIEW_CONVERT_EXPR 1376169699Skan || TREE_CODE (inner) == SAVE_EXPR) 1377169699Skan inner = TREE_OPERAND (inner, 0); 137890075Sobrien 137990075Sobrien if (! DECL_P (inner)) 138090075Sobrien inner = NULL_TREE; 138190075Sobrien } 138290075Sobrien 138390075Sobrien if (inner == TREE_OPERAND (ref, 0)) 138490075Sobrien return ref; 138590075Sobrien else 1386169699Skan return build3 (COMPONENT_REF, TREE_TYPE (ref), inner, 1387169699Skan TREE_OPERAND (ref, 1), NULL_TREE); 138890075Sobrien} 138990075Sobrien 1390132727Skan/* Returns 1 if both MEM_EXPR can be considered equal 1391132727Skan and 0 otherwise. */ 1392132727Skan 1393132727Skanint 1394132727Skanmem_expr_equal_p (tree expr1, tree expr2) 1395132727Skan{ 1396132727Skan if (expr1 == expr2) 1397132727Skan return 1; 1398132727Skan 1399132727Skan if (! expr1 || ! expr2) 1400132727Skan return 0; 1401132727Skan 1402132727Skan if (TREE_CODE (expr1) != TREE_CODE (expr2)) 1403132727Skan return 0; 1404132727Skan 1405132727Skan if (TREE_CODE (expr1) == COMPONENT_REF) 1406132727Skan return 1407132727Skan mem_expr_equal_p (TREE_OPERAND (expr1, 0), 1408132727Skan TREE_OPERAND (expr2, 0)) 1409132727Skan && mem_expr_equal_p (TREE_OPERAND (expr1, 1), /* field decl */ 1410132727Skan TREE_OPERAND (expr2, 1)); 1411132727Skan 1412169699Skan if (INDIRECT_REF_P (expr1)) 1413132727Skan return mem_expr_equal_p (TREE_OPERAND (expr1, 0), 1414132727Skan TREE_OPERAND (expr2, 0)); 1415169699Skan 1416169699Skan /* ARRAY_REFs, ARRAY_RANGE_REFs and BIT_FIELD_REFs should already 1417169699Skan have been resolved here. */ 1418169699Skan gcc_assert (DECL_P (expr1)); 1419132727Skan 1420132727Skan /* Decls with different pointers can't be equal. */ 1421169699Skan return 0; 1422132727Skan} 1423132727Skan 142490075Sobrien/* Given REF, a MEM, and T, either the type of X or the expression 142590075Sobrien corresponding to REF, set the memory attributes. OBJECTP is nonzero 1426110621Skan if we are making a new object of this type. BITPOS is nonzero if 1427110621Skan there is an offset outstanding on T that will be applied later. */ 142890075Sobrien 142990075Sobrienvoid 1430132727Skanset_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, 1431132727Skan HOST_WIDE_INT bitpos) 143290075Sobrien{ 143390075Sobrien HOST_WIDE_INT alias = MEM_ALIAS_SET (ref); 143490075Sobrien tree expr = MEM_EXPR (ref); 143590075Sobrien rtx offset = MEM_OFFSET (ref); 143690075Sobrien rtx size = MEM_SIZE (ref); 143790075Sobrien unsigned int align = MEM_ALIGN (ref); 1438110621Skan HOST_WIDE_INT apply_bitpos = 0; 143990075Sobrien tree type; 144090075Sobrien 144190075Sobrien /* It can happen that type_for_mode was given a mode for which there 144290075Sobrien is no language-level type. In which case it returns NULL, which 144390075Sobrien we can see here. */ 144490075Sobrien if (t == NULL_TREE) 144590075Sobrien return; 144690075Sobrien 144790075Sobrien type = TYPE_P (t) ? t : TREE_TYPE (t); 1448132727Skan if (type == error_mark_node) 1449132727Skan return; 145090075Sobrien 145190075Sobrien /* If we have already set DECL_RTL = ref, get_alias_set will get the 145290075Sobrien wrong answer, as it assumes that DECL_RTL already has the right alias 145390075Sobrien info. Callers should not set DECL_RTL until after the call to 145490075Sobrien set_mem_attributes. */ 1455169699Skan gcc_assert (!DECL_P (t) || ref != DECL_RTL_IF_SET (t)); 145690075Sobrien 145790075Sobrien /* Get the alias set from the expression or type (perhaps using a 145890075Sobrien front-end routine) and use it. */ 145990075Sobrien alias = get_alias_set (t); 146090075Sobrien 1461169699Skan MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type); 146290075Sobrien MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type); 1463169699Skan MEM_POINTER (ref) = POINTER_TYPE_P (type); 146490075Sobrien 146590075Sobrien /* If we are making an object of this type, or if this is a DECL, we know 146690075Sobrien that it is a scalar if the type is not an aggregate. */ 146790075Sobrien if ((objectp || DECL_P (t)) && ! AGGREGATE_TYPE_P (type)) 146890075Sobrien MEM_SCALAR_P (ref) = 1; 146990075Sobrien 147090075Sobrien /* We can set the alignment from the type if we are making an object, 147190075Sobrien this is an INDIRECT_REF, or if TYPE_ALIGN_OK. */ 1472169699Skan if (objectp || TREE_CODE (t) == INDIRECT_REF 1473169699Skan || TREE_CODE (t) == ALIGN_INDIRECT_REF 1474169699Skan || TYPE_ALIGN_OK (type)) 147590075Sobrien align = MAX (align, TYPE_ALIGN (type)); 1476169699Skan else 1477169699Skan if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF) 1478169699Skan { 1479169699Skan if (integer_zerop (TREE_OPERAND (t, 1))) 1480169699Skan /* We don't know anything about the alignment. */ 1481169699Skan align = BITS_PER_UNIT; 1482169699Skan else 1483169699Skan align = tree_low_cst (TREE_OPERAND (t, 1), 1); 1484169699Skan } 148590075Sobrien 148690075Sobrien /* If the size is known, we can set that. */ 148790075Sobrien if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1)) 148890075Sobrien size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1)); 148990075Sobrien 149090075Sobrien /* If T is not a type, we may be able to deduce some more information about 149190075Sobrien the expression. */ 149290075Sobrien if (! TYPE_P (t)) 149390075Sobrien { 1494169699Skan tree base; 1495169699Skan 149690075Sobrien if (TREE_THIS_VOLATILE (t)) 149790075Sobrien MEM_VOLATILE_P (ref) = 1; 149890075Sobrien 149990075Sobrien /* Now remove any conversions: they don't change what the underlying 150090075Sobrien object is. Likewise for SAVE_EXPR. */ 150190075Sobrien while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR 150290075Sobrien || TREE_CODE (t) == NON_LVALUE_EXPR 150390075Sobrien || TREE_CODE (t) == VIEW_CONVERT_EXPR 150490075Sobrien || TREE_CODE (t) == SAVE_EXPR) 150590075Sobrien t = TREE_OPERAND (t, 0); 150690075Sobrien 1507169699Skan /* We may look through structure-like accesses for the purposes of 1508169699Skan examining TREE_THIS_NOTRAP, but not array-like accesses. */ 1509169699Skan base = t; 1510169699Skan while (TREE_CODE (base) == COMPONENT_REF 1511169699Skan || TREE_CODE (base) == REALPART_EXPR 1512169699Skan || TREE_CODE (base) == IMAGPART_EXPR 1513169699Skan || TREE_CODE (base) == BIT_FIELD_REF) 1514169699Skan base = TREE_OPERAND (base, 0); 1515169699Skan 1516169699Skan if (DECL_P (base)) 1517169699Skan { 1518169699Skan if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS)) 1519169699Skan MEM_NOTRAP_P (ref) = !DECL_WEAK (base); 1520169699Skan else 1521169699Skan MEM_NOTRAP_P (ref) = 1; 1522169699Skan } 1523169699Skan else 1524169699Skan MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (base); 1525169699Skan 1526169699Skan base = get_base_address (base); 1527169699Skan if (base && DECL_P (base) 1528169699Skan && TREE_READONLY (base) 1529169699Skan && (TREE_STATIC (base) || DECL_EXTERNAL (base))) 1530169699Skan { 1531169699Skan tree base_type = TREE_TYPE (base); 1532169699Skan gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type)) 1533169699Skan || DECL_ARTIFICIAL (base)); 1534169699Skan MEM_READONLY_P (ref) = 1; 1535169699Skan } 1536169699Skan 1537169699Skan /* If this expression uses it's parent's alias set, mark it such 1538169699Skan that we won't change it. */ 1539169699Skan if (component_uses_parent_alias_set (t)) 154090075Sobrien MEM_KEEP_ALIAS_SET_P (ref) = 1; 154190075Sobrien 154290075Sobrien /* If this is a decl, set the attributes of the MEM from it. */ 154390075Sobrien if (DECL_P (t)) 154490075Sobrien { 154590075Sobrien expr = t; 154690075Sobrien offset = const0_rtx; 1547110621Skan apply_bitpos = bitpos; 154890075Sobrien size = (DECL_SIZE_UNIT (t) 154990075Sobrien && host_integerp (DECL_SIZE_UNIT (t), 1) 155090075Sobrien ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0); 1551117404Skan align = DECL_ALIGN (t); 155290075Sobrien } 155390075Sobrien 155490075Sobrien /* If this is a constant, we know the alignment. */ 1555169699Skan else if (CONSTANT_CLASS_P (t)) 155690075Sobrien { 155790075Sobrien align = TYPE_ALIGN (type); 155890075Sobrien#ifdef CONSTANT_ALIGNMENT 155990075Sobrien align = CONSTANT_ALIGNMENT (t, align); 156090075Sobrien#endif 156190075Sobrien } 156290075Sobrien 156390075Sobrien /* If this is a field reference and not a bit-field, record it. */ 156490075Sobrien /* ??? There is some information that can be gleened from bit-fields, 156590075Sobrien such as the word offset in the structure that might be modified. 156690075Sobrien But skip it for now. */ 156790075Sobrien else if (TREE_CODE (t) == COMPONENT_REF 156890075Sobrien && ! DECL_BIT_FIELD (TREE_OPERAND (t, 1))) 156990075Sobrien { 157090075Sobrien expr = component_ref_for_mem_expr (t); 157190075Sobrien offset = const0_rtx; 1572110621Skan apply_bitpos = bitpos; 157390075Sobrien /* ??? Any reason the field size would be different than 157490075Sobrien the size we got from the type? */ 157590075Sobrien } 157690075Sobrien 157790075Sobrien /* If this is an array reference, look for an outer field reference. */ 157890075Sobrien else if (TREE_CODE (t) == ARRAY_REF) 157990075Sobrien { 158090075Sobrien tree off_tree = size_zero_node; 1581117404Skan /* We can't modify t, because we use it at the end of the 1582117404Skan function. */ 1583117404Skan tree t2 = t; 158490075Sobrien 158590075Sobrien do 158690075Sobrien { 1587117404Skan tree index = TREE_OPERAND (t2, 1); 1588169699Skan tree low_bound = array_ref_low_bound (t2); 1589169699Skan tree unit_size = array_ref_element_size (t2); 1590110621Skan 1591110621Skan /* We assume all arrays have sizes that are a multiple of a byte. 1592110621Skan First subtract the lower bound, if any, in the type of the 1593169699Skan index, then convert to sizetype and multiply by the size of 1594169699Skan the array element. */ 1595169699Skan if (! integer_zerop (low_bound)) 1596169699Skan index = fold_build2 (MINUS_EXPR, TREE_TYPE (index), 1597169699Skan index, low_bound); 1598110621Skan 1599169699Skan off_tree = size_binop (PLUS_EXPR, 1600169699Skan size_binop (MULT_EXPR, 1601169699Skan fold_convert (sizetype, 1602169699Skan index), 1603169699Skan unit_size), 1604169699Skan off_tree); 1605117404Skan t2 = TREE_OPERAND (t2, 0); 160690075Sobrien } 1607117404Skan while (TREE_CODE (t2) == ARRAY_REF); 160890075Sobrien 1609117404Skan if (DECL_P (t2)) 161090075Sobrien { 1611117404Skan expr = t2; 1612110621Skan offset = NULL; 1613110621Skan if (host_integerp (off_tree, 1)) 1614110621Skan { 1615110621Skan HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1); 1616110621Skan HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT; 1617117404Skan align = DECL_ALIGN (t2); 1618132727Skan if (aoff && (unsigned HOST_WIDE_INT) aoff < align) 1619110621Skan align = aoff; 1620110621Skan offset = GEN_INT (ioff); 1621110621Skan apply_bitpos = bitpos; 1622110621Skan } 1623110621Skan } 1624117404Skan else if (TREE_CODE (t2) == COMPONENT_REF) 1625110621Skan { 1626117404Skan expr = component_ref_for_mem_expr (t2); 162790075Sobrien if (host_integerp (off_tree, 1)) 1628110621Skan { 1629110621Skan offset = GEN_INT (tree_low_cst (off_tree, 1)); 1630110621Skan apply_bitpos = bitpos; 1631110621Skan } 163290075Sobrien /* ??? Any reason the field size would be different than 163390075Sobrien the size we got from the type? */ 163490075Sobrien } 1635110621Skan else if (flag_argument_noalias > 1 1636169699Skan && (INDIRECT_REF_P (t2)) 1637117404Skan && TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL) 1638110621Skan { 1639117404Skan expr = t2; 1640110621Skan offset = NULL; 1641110621Skan } 164290075Sobrien } 1643110621Skan 1644110621Skan /* If this is a Fortran indirect argument reference, record the 1645110621Skan parameter decl. */ 1646110621Skan else if (flag_argument_noalias > 1 1647169699Skan && (INDIRECT_REF_P (t)) 1648110621Skan && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL) 1649110621Skan { 1650110621Skan expr = t; 1651110621Skan offset = NULL; 1652110621Skan } 165390075Sobrien } 165490075Sobrien 1655132727Skan /* If we modified OFFSET based on T, then subtract the outstanding 1656110621Skan bit position offset. Similarly, increase the size of the accessed 1657110621Skan object to contain the negative offset. */ 1658110621Skan if (apply_bitpos) 1659110621Skan { 1660110621Skan offset = plus_constant (offset, -(apply_bitpos / BITS_PER_UNIT)); 1661110621Skan if (size) 1662110621Skan size = plus_constant (size, apply_bitpos / BITS_PER_UNIT); 1663110621Skan } 1664110621Skan 1665169699Skan if (TREE_CODE (t) == ALIGN_INDIRECT_REF) 1666169699Skan { 1667169699Skan /* Force EXPR and OFFSE to NULL, since we don't know exactly what 1668169699Skan we're overlapping. */ 1669169699Skan offset = NULL; 1670169699Skan expr = NULL; 1671169699Skan } 1672169699Skan 167390075Sobrien /* Now set the attributes we computed above. */ 167490075Sobrien MEM_ATTRS (ref) 167590075Sobrien = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref)); 167690075Sobrien 167790075Sobrien /* If this is already known to be a scalar or aggregate, we are done. */ 167890075Sobrien if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref)) 167990075Sobrien return; 168090075Sobrien 168190075Sobrien /* If it is a reference into an aggregate, this is part of an aggregate. 168290075Sobrien Otherwise we don't know. */ 168390075Sobrien else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF 168490075Sobrien || TREE_CODE (t) == ARRAY_RANGE_REF 168590075Sobrien || TREE_CODE (t) == BIT_FIELD_REF) 168690075Sobrien MEM_IN_STRUCT_P (ref) = 1; 168790075Sobrien} 168890075Sobrien 1689110621Skanvoid 1690132727Skanset_mem_attributes (rtx ref, tree t, int objectp) 1691110621Skan{ 1692110621Skan set_mem_attributes_minus_bitpos (ref, t, objectp, 0); 1693110621Skan} 1694110621Skan 1695132727Skan/* Set the decl for MEM to DECL. */ 1696132727Skan 1697132727Skanvoid 1698132727Skanset_mem_attrs_from_reg (rtx mem, rtx reg) 1699132727Skan{ 1700132727Skan MEM_ATTRS (mem) 1701132727Skan = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg), 1702132727Skan GEN_INT (REG_OFFSET (reg)), 1703132727Skan MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem)); 1704132727Skan} 1705132727Skan 170690075Sobrien/* Set the alias set of MEM to SET. */ 170790075Sobrien 170890075Sobrienvoid 1709132727Skanset_mem_alias_set (rtx mem, HOST_WIDE_INT set) 171090075Sobrien{ 1711117404Skan#ifdef ENABLE_CHECKING 171290075Sobrien /* If the new and old alias sets don't conflict, something is wrong. */ 1713169699Skan gcc_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem))); 171490075Sobrien#endif 171590075Sobrien 171690075Sobrien MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem), 171790075Sobrien MEM_SIZE (mem), MEM_ALIGN (mem), 171890075Sobrien GET_MODE (mem)); 171990075Sobrien} 172090075Sobrien 172190075Sobrien/* Set the alignment of MEM to ALIGN bits. */ 172290075Sobrien 172390075Sobrienvoid 1724132727Skanset_mem_align (rtx mem, unsigned int align) 172590075Sobrien{ 172690075Sobrien MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), 172790075Sobrien MEM_OFFSET (mem), MEM_SIZE (mem), align, 172890075Sobrien GET_MODE (mem)); 172990075Sobrien} 173090075Sobrien 173190075Sobrien/* Set the expr for MEM to EXPR. */ 173290075Sobrien 173390075Sobrienvoid 1734132727Skanset_mem_expr (rtx mem, tree expr) 173590075Sobrien{ 173690075Sobrien MEM_ATTRS (mem) 173790075Sobrien = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem), 173890075Sobrien MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem)); 173990075Sobrien} 174090075Sobrien 174190075Sobrien/* Set the offset of MEM to OFFSET. */ 174290075Sobrien 174390075Sobrienvoid 1744132727Skanset_mem_offset (rtx mem, rtx offset) 174590075Sobrien{ 174690075Sobrien MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), 174790075Sobrien offset, MEM_SIZE (mem), MEM_ALIGN (mem), 174890075Sobrien GET_MODE (mem)); 174990075Sobrien} 1750103453Skan 1751103453Skan/* Set the size of MEM to SIZE. */ 1752103453Skan 1753103453Skanvoid 1754132727Skanset_mem_size (rtx mem, rtx size) 1755103453Skan{ 1756103453Skan MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), 1757103453Skan MEM_OFFSET (mem), size, MEM_ALIGN (mem), 1758103453Skan GET_MODE (mem)); 1759103453Skan} 176090075Sobrien 176190075Sobrien/* Return a memory reference like MEMREF, but with its mode changed to MODE 176290075Sobrien and its address changed to ADDR. (VOIDmode means don't change the mode. 176390075Sobrien NULL for ADDR means don't change the address.) VALIDATE is nonzero if the 176490075Sobrien returned memory location is required to be valid. The memory 176590075Sobrien attributes are not changed. */ 176690075Sobrien 176790075Sobrienstatic rtx 1768132727Skanchange_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate) 176918334Speter{ 177018334Speter rtx new; 177118334Speter 1772169699Skan gcc_assert (MEM_P (memref)); 177318334Speter if (mode == VOIDmode) 177418334Speter mode = GET_MODE (memref); 177518334Speter if (addr == 0) 177618334Speter addr = XEXP (memref, 0); 1777132727Skan if (mode == GET_MODE (memref) && addr == XEXP (memref, 0) 1778132727Skan && (!validate || memory_address_p (mode, addr))) 1779132727Skan return memref; 178018334Speter 178190075Sobrien if (validate) 178218334Speter { 178390075Sobrien if (reload_in_progress || reload_completed) 1784169699Skan gcc_assert (memory_address_p (mode, addr)); 178590075Sobrien else 178690075Sobrien addr = memory_address (mode, addr); 178718334Speter } 178890075Sobrien 178950397Sobrien if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref)) 179050397Sobrien return memref; 179150397Sobrien 179250397Sobrien new = gen_rtx_MEM (mode, addr); 179352284Sobrien MEM_COPY_ATTRIBUTES (new, memref); 179418334Speter return new; 179518334Speter} 179690075Sobrien 179790075Sobrien/* Like change_address_1 with VALIDATE nonzero, but we are not saying in what 179890075Sobrien way we are changing MEMREF, so we only preserve the alias set. */ 179990075Sobrien 180090075Sobrienrtx 1801132727Skanchange_address (rtx memref, enum machine_mode mode, rtx addr) 180290075Sobrien{ 1803132727Skan rtx new = change_address_1 (memref, mode, addr, 1), size; 180490075Sobrien enum machine_mode mmode = GET_MODE (new); 1805132727Skan unsigned int align; 180690075Sobrien 1807132727Skan size = mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode)); 1808132727Skan align = mmode == BLKmode ? BITS_PER_UNIT : GET_MODE_ALIGNMENT (mmode); 1809132727Skan 1810132727Skan /* If there are no changes, just return the original memory reference. */ 1811132727Skan if (new == memref) 1812132727Skan { 1813132727Skan if (MEM_ATTRS (memref) == 0 1814132727Skan || (MEM_EXPR (memref) == NULL 1815132727Skan && MEM_OFFSET (memref) == NULL 1816132727Skan && MEM_SIZE (memref) == size 1817132727Skan && MEM_ALIGN (memref) == align)) 1818132727Skan return new; 1819132727Skan 1820132727Skan new = gen_rtx_MEM (mmode, XEXP (memref, 0)); 1821132727Skan MEM_COPY_ATTRIBUTES (new, memref); 1822132727Skan } 1823132727Skan 182490075Sobrien MEM_ATTRS (new) 1825132727Skan = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, mmode); 182690075Sobrien 182790075Sobrien return new; 182890075Sobrien} 182990075Sobrien 183090075Sobrien/* Return a memory reference like MEMREF, but with its mode changed 183190075Sobrien to MODE and its address offset by OFFSET bytes. If VALIDATE is 183290075Sobrien nonzero, the memory address is forced to be valid. 183390075Sobrien If ADJUST is zero, OFFSET is only used to update MEM_ATTRS 183490075Sobrien and caller is responsible for adjusting MEMREF base register. */ 183590075Sobrien 183690075Sobrienrtx 1837132727Skanadjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, 1838132727Skan int validate, int adjust) 183990075Sobrien{ 184090075Sobrien rtx addr = XEXP (memref, 0); 184190075Sobrien rtx new; 184290075Sobrien rtx memoffset = MEM_OFFSET (memref); 184390075Sobrien rtx size = 0; 184490075Sobrien unsigned int memalign = MEM_ALIGN (memref); 184590075Sobrien 1846132727Skan /* If there are no changes, just return the original memory reference. */ 1847132727Skan if (mode == GET_MODE (memref) && !offset 1848132727Skan && (!validate || memory_address_p (mode, addr))) 1849132727Skan return memref; 1850132727Skan 185190075Sobrien /* ??? Prefer to create garbage instead of creating shared rtl. 1852117404Skan This may happen even if offset is nonzero -- consider 185390075Sobrien (plus (plus reg reg) const_int) -- so do this always. */ 185490075Sobrien addr = copy_rtx (addr); 185590075Sobrien 185690075Sobrien if (adjust) 185790075Sobrien { 185890075Sobrien /* If MEMREF is a LO_SUM and the offset is within the alignment of the 185990075Sobrien object, we can merge it into the LO_SUM. */ 186090075Sobrien if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM 186190075Sobrien && offset >= 0 186290075Sobrien && (unsigned HOST_WIDE_INT) offset 186390075Sobrien < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT) 186490075Sobrien addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0), 186590075Sobrien plus_constant (XEXP (addr, 1), offset)); 186690075Sobrien else 186790075Sobrien addr = plus_constant (addr, offset); 186890075Sobrien } 186990075Sobrien 187090075Sobrien new = change_address_1 (memref, mode, addr, validate); 187190075Sobrien 187290075Sobrien /* Compute the new values of the memory attributes due to this adjustment. 187390075Sobrien We add the offsets and update the alignment. */ 187490075Sobrien if (memoffset) 187590075Sobrien memoffset = GEN_INT (offset + INTVAL (memoffset)); 187690075Sobrien 187790075Sobrien /* Compute the new alignment by taking the MIN of the alignment and the 187890075Sobrien lowest-order set bit in OFFSET, but don't change the alignment if OFFSET 187990075Sobrien if zero. */ 188090075Sobrien if (offset != 0) 188196263Sobrien memalign 188296263Sobrien = MIN (memalign, 188396263Sobrien (unsigned HOST_WIDE_INT) (offset & -offset) * BITS_PER_UNIT); 188490075Sobrien 188590075Sobrien /* We can compute the size in a number of ways. */ 188690075Sobrien if (GET_MODE (new) != BLKmode) 188790075Sobrien size = GEN_INT (GET_MODE_SIZE (GET_MODE (new))); 188890075Sobrien else if (MEM_SIZE (memref)) 188990075Sobrien size = plus_constant (MEM_SIZE (memref), -offset); 189090075Sobrien 189190075Sobrien MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 189290075Sobrien memoffset, size, memalign, GET_MODE (new)); 189390075Sobrien 189490075Sobrien /* At some point, we should validate that this offset is within the object, 189590075Sobrien if all the appropriate values are known. */ 189690075Sobrien return new; 189790075Sobrien} 189890075Sobrien 189990075Sobrien/* Return a memory reference like MEMREF, but with its mode changed 190090075Sobrien to MODE and its address changed to ADDR, which is assumed to be 190190075Sobrien MEMREF offseted by OFFSET bytes. If VALIDATE is 190290075Sobrien nonzero, the memory address is forced to be valid. */ 190390075Sobrien 190490075Sobrienrtx 1905132727Skanadjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr, 1906132727Skan HOST_WIDE_INT offset, int validate) 190790075Sobrien{ 190890075Sobrien memref = change_address_1 (memref, VOIDmode, addr, validate); 190990075Sobrien return adjust_address_1 (memref, mode, offset, validate, 0); 191090075Sobrien} 191190075Sobrien 191290075Sobrien/* Return a memory reference like MEMREF, but whose address is changed by 191390075Sobrien adding OFFSET, an RTX, to it. POW2 is the highest power of two factor 191490075Sobrien known to be in OFFSET (possibly 1). */ 191590075Sobrien 191690075Sobrienrtx 1917132727Skanoffset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) 191890075Sobrien{ 191996263Sobrien rtx new, addr = XEXP (memref, 0); 192090075Sobrien 192196263Sobrien new = simplify_gen_binary (PLUS, Pmode, addr, offset); 192296263Sobrien 1923117404Skan /* At this point we don't know _why_ the address is invalid. It 1924132727Skan could have secondary memory references, multiplies or anything. 192596263Sobrien 192696263Sobrien However, if we did go and rearrange things, we can wind up not 192796263Sobrien being able to recognize the magic around pic_offset_table_rtx. 192896263Sobrien This stuff is fragile, and is yet another example of why it is 192996263Sobrien bad to expose PIC machinery too early. */ 193096263Sobrien if (! memory_address_p (GET_MODE (memref), new) 193196263Sobrien && GET_CODE (addr) == PLUS 193296263Sobrien && XEXP (addr, 0) == pic_offset_table_rtx) 193396263Sobrien { 193496263Sobrien addr = force_reg (GET_MODE (addr), addr); 193596263Sobrien new = simplify_gen_binary (PLUS, Pmode, addr, offset); 193696263Sobrien } 193796263Sobrien 193896263Sobrien update_temp_slot_address (XEXP (memref, 0), new); 193996263Sobrien new = change_address_1 (memref, VOIDmode, new, 1); 194096263Sobrien 1941132727Skan /* If there are no changes, just return the original memory reference. */ 1942132727Skan if (new == memref) 1943132727Skan return new; 1944132727Skan 194590075Sobrien /* Update the alignment to reflect the offset. Reset the offset, which 194690075Sobrien we don't know. */ 194790075Sobrien MEM_ATTRS (new) 194890075Sobrien = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0, 1949132727Skan MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT), 195090075Sobrien GET_MODE (new)); 195190075Sobrien return new; 195290075Sobrien} 1953117404Skan 195490075Sobrien/* Return a memory reference like MEMREF, but with its address changed to 195590075Sobrien ADDR. The caller is asserting that the actual piece of memory pointed 195690075Sobrien to is the same, just the form of the address is being changed, such as 195790075Sobrien by putting something into a register. */ 195890075Sobrien 195990075Sobrienrtx 1960132727Skanreplace_equiv_address (rtx memref, rtx addr) 196190075Sobrien{ 196290075Sobrien /* change_address_1 copies the memory attribute structure without change 196390075Sobrien and that's exactly what we want here. */ 196490075Sobrien update_temp_slot_address (XEXP (memref, 0), addr); 196590075Sobrien return change_address_1 (memref, VOIDmode, addr, 1); 196690075Sobrien} 196790075Sobrien 196890075Sobrien/* Likewise, but the reference is not required to be valid. */ 196990075Sobrien 197090075Sobrienrtx 1971132727Skanreplace_equiv_address_nv (rtx memref, rtx addr) 197290075Sobrien{ 197390075Sobrien return change_address_1 (memref, VOIDmode, addr, 0); 197490075Sobrien} 197590075Sobrien 197690075Sobrien/* Return a memory reference like MEMREF, but with its mode widened to 197790075Sobrien MODE and offset by OFFSET. This would be used by targets that e.g. 197890075Sobrien cannot issue QImode memory operations and have to use SImode memory 197990075Sobrien operations plus masking logic. */ 198090075Sobrien 198190075Sobrienrtx 1982132727Skanwiden_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset) 198390075Sobrien{ 198490075Sobrien rtx new = adjust_address_1 (memref, mode, offset, 1, 1); 198590075Sobrien tree expr = MEM_EXPR (new); 198690075Sobrien rtx memoffset = MEM_OFFSET (new); 198790075Sobrien unsigned int size = GET_MODE_SIZE (mode); 198890075Sobrien 1989132727Skan /* If there are no changes, just return the original memory reference. */ 1990132727Skan if (new == memref) 1991132727Skan return new; 1992132727Skan 199390075Sobrien /* If we don't know what offset we were at within the expression, then 199490075Sobrien we can't know if we've overstepped the bounds. */ 199596263Sobrien if (! memoffset) 199690075Sobrien expr = NULL_TREE; 199790075Sobrien 199890075Sobrien while (expr) 199990075Sobrien { 200090075Sobrien if (TREE_CODE (expr) == COMPONENT_REF) 200190075Sobrien { 200290075Sobrien tree field = TREE_OPERAND (expr, 1); 2003169699Skan tree offset = component_ref_field_offset (expr); 200490075Sobrien 200590075Sobrien if (! DECL_SIZE_UNIT (field)) 200690075Sobrien { 200790075Sobrien expr = NULL_TREE; 200890075Sobrien break; 200990075Sobrien } 201090075Sobrien 201190075Sobrien /* Is the field at least as large as the access? If so, ok, 201290075Sobrien otherwise strip back to the containing structure. */ 201390075Sobrien if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST 201490075Sobrien && compare_tree_int (DECL_SIZE_UNIT (field), size) >= 0 201590075Sobrien && INTVAL (memoffset) >= 0) 201690075Sobrien break; 201790075Sobrien 2018169699Skan if (! host_integerp (offset, 1)) 201990075Sobrien { 202090075Sobrien expr = NULL_TREE; 202190075Sobrien break; 202290075Sobrien } 202390075Sobrien 202490075Sobrien expr = TREE_OPERAND (expr, 0); 2025169699Skan memoffset 2026169699Skan = (GEN_INT (INTVAL (memoffset) 2027169699Skan + tree_low_cst (offset, 1) 2028169699Skan + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) 2029169699Skan / BITS_PER_UNIT))); 203090075Sobrien } 203190075Sobrien /* Similarly for the decl. */ 203290075Sobrien else if (DECL_P (expr) 203390075Sobrien && DECL_SIZE_UNIT (expr) 2034102793Skan && TREE_CODE (DECL_SIZE_UNIT (expr)) == INTEGER_CST 203590075Sobrien && compare_tree_int (DECL_SIZE_UNIT (expr), size) >= 0 203690075Sobrien && (! memoffset || INTVAL (memoffset) >= 0)) 203790075Sobrien break; 203890075Sobrien else 203990075Sobrien { 204090075Sobrien /* The widened memory access overflows the expression, which means 204190075Sobrien that it could alias another expression. Zap it. */ 204290075Sobrien expr = NULL_TREE; 204390075Sobrien break; 204490075Sobrien } 204590075Sobrien } 204690075Sobrien 204790075Sobrien if (! expr) 204890075Sobrien memoffset = NULL_RTX; 204990075Sobrien 205090075Sobrien /* The widened memory may alias other stuff, so zap the alias set. */ 205190075Sobrien /* ??? Maybe use get_alias_set on any remaining expression. */ 205290075Sobrien 205390075Sobrien MEM_ATTRS (new) = get_mem_attrs (0, expr, memoffset, GEN_INT (size), 205490075Sobrien MEM_ALIGN (new), mode); 205590075Sobrien 205690075Sobrien return new; 205790075Sobrien} 205818334Speter 205918334Speter/* Return a newly created CODE_LABEL rtx with a unique label number. */ 206018334Speter 206118334Speterrtx 2062132727Skangen_label_rtx (void) 206318334Speter{ 2064117404Skan return gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, NULL_RTX, 2065260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 2066260918Spfg NULL, label_num++, NULL, 0); 2067260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 206818334Speter} 206918334Speter 207018334Speter/* For procedure integration. */ 207118334Speter 207218334Speter/* Install new pointers to the first and last insns in the chain. 207350397Sobrien Also, set cur_insn_uid to one higher than the last in use. 207418334Speter Used for an inline-procedure after copying the insn chain. */ 207518334Speter 207618334Spetervoid 2077132727Skanset_new_first_and_last_insn (rtx first, rtx last) 207818334Speter{ 207950397Sobrien rtx insn; 208050397Sobrien 208118334Speter first_insn = first; 208218334Speter last_insn = last; 208350397Sobrien cur_insn_uid = 0; 208450397Sobrien 208550397Sobrien for (insn = first; insn; insn = NEXT_INSN (insn)) 208650397Sobrien cur_insn_uid = MAX (cur_insn_uid, INSN_UID (insn)); 208750397Sobrien 208850397Sobrien cur_insn_uid++; 208918334Speter} 209090075Sobrien 209190075Sobrien/* Go through all the RTL insn bodies and copy any invalid shared 209272562Sobrien structure. This routine should only be called once. */ 209318334Speter 2094169699Skanstatic void 2095169699Skanunshare_all_rtl_1 (tree fndecl, rtx insn) 209618334Speter{ 209772562Sobrien tree decl; 209818334Speter 209972562Sobrien /* Make sure that virtual parameters are not shared. */ 210072562Sobrien for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) 210190075Sobrien SET_DECL_RTL (decl, copy_rtx_if_shared (DECL_RTL (decl))); 210272562Sobrien 210372562Sobrien /* Make sure that virtual stack slots are not shared. */ 210472562Sobrien unshare_all_decls (DECL_INITIAL (fndecl)); 210572562Sobrien 210672562Sobrien /* Unshare just about everything else. */ 2107132727Skan unshare_all_rtl_in_chain (insn); 210890075Sobrien 210918334Speter /* Make sure the addresses of stack slots found outside the insn chain 211018334Speter (such as, in DECL_RTL of a variable) are not shared 211118334Speter with the insn chain. 211218334Speter 211318334Speter This special care is necessary when the stack slot MEM does not 211418334Speter actually appear in the insn chain. If it does appear, its address 211518334Speter is unshared from all else at that point. */ 211672562Sobrien stack_slot_list = copy_rtx_if_shared (stack_slot_list); 211772562Sobrien} 211818334Speter 211990075Sobrien/* Go through all the RTL insn bodies and copy any invalid shared 212072562Sobrien structure, again. This is a fairly expensive thing to do so it 212172562Sobrien should be done sparingly. */ 212272562Sobrien 212372562Sobrienvoid 2124132727Skanunshare_all_rtl_again (rtx insn) 212572562Sobrien{ 212672562Sobrien rtx p; 212790075Sobrien tree decl; 212890075Sobrien 212972562Sobrien for (p = insn; p; p = NEXT_INSN (p)) 213090075Sobrien if (INSN_P (p)) 213172562Sobrien { 213272562Sobrien reset_used_flags (PATTERN (p)); 213372562Sobrien reset_used_flags (REG_NOTES (p)); 213472562Sobrien reset_used_flags (LOG_LINKS (p)); 213572562Sobrien } 213690075Sobrien 213790075Sobrien /* Make sure that virtual stack slots are not shared. */ 213890075Sobrien reset_used_decls (DECL_INITIAL (cfun->decl)); 213990075Sobrien 214090075Sobrien /* Make sure that virtual parameters are not shared. */ 214190075Sobrien for (decl = DECL_ARGUMENTS (cfun->decl); decl; decl = TREE_CHAIN (decl)) 214290075Sobrien reset_used_flags (DECL_RTL (decl)); 214390075Sobrien 214490075Sobrien reset_used_flags (stack_slot_list); 214590075Sobrien 2146169699Skan unshare_all_rtl_1 (cfun->decl, insn); 214718334Speter} 214818334Speter 2149169699Skanunsigned int 2150169699Skanunshare_all_rtl (void) 2151169699Skan{ 2152169699Skan unshare_all_rtl_1 (current_function_decl, get_insns ()); 2153169699Skan return 0; 2154169699Skan} 2155169699Skan 2156169699Skanstruct tree_opt_pass pass_unshare_all_rtl = 2157169699Skan{ 2158169699Skan "unshare", /* name */ 2159169699Skan NULL, /* gate */ 2160169699Skan unshare_all_rtl, /* execute */ 2161169699Skan NULL, /* sub */ 2162169699Skan NULL, /* next */ 2163169699Skan 0, /* static_pass_number */ 2164169699Skan 0, /* tv_id */ 2165169699Skan 0, /* properties_required */ 2166169699Skan 0, /* properties_provided */ 2167169699Skan 0, /* properties_destroyed */ 2168169699Skan 0, /* todo_flags_start */ 2169169699Skan TODO_dump_func, /* todo_flags_finish */ 2170169699Skan 0 /* letter */ 2171169699Skan}; 2172169699Skan 2173169699Skan 2174132727Skan/* Check that ORIG is not marked when it should not be and mark ORIG as in use, 2175132727Skan Recursively does the same for subexpressions. */ 2176132727Skan 2177132727Skanstatic void 2178132727Skanverify_rtx_sharing (rtx orig, rtx insn) 2179132727Skan{ 2180132727Skan rtx x = orig; 2181132727Skan int i; 2182132727Skan enum rtx_code code; 2183132727Skan const char *format_ptr; 2184132727Skan 2185132727Skan if (x == 0) 2186132727Skan return; 2187132727Skan 2188132727Skan code = GET_CODE (x); 2189132727Skan 2190132727Skan /* These types may be freely shared. */ 2191132727Skan 2192132727Skan switch (code) 2193132727Skan { 2194132727Skan case REG: 2195132727Skan case CONST_INT: 2196132727Skan case CONST_DOUBLE: 2197132727Skan case CONST_VECTOR: 2198132727Skan case SYMBOL_REF: 2199132727Skan case LABEL_REF: 2200132727Skan case CODE_LABEL: 2201132727Skan case PC: 2202132727Skan case CC0: 2203132727Skan case SCRATCH: 2204169699Skan return; 2205132727Skan /* SCRATCH must be shared because they represent distinct values. */ 2206169699Skan case CLOBBER: 2207169699Skan if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) 2208169699Skan return; 2209169699Skan break; 2210132727Skan 2211132727Skan case CONST: 2212132727Skan /* CONST can be shared if it contains a SYMBOL_REF. If it contains 2213132727Skan a LABEL_REF, it isn't sharable. */ 2214132727Skan if (GET_CODE (XEXP (x, 0)) == PLUS 2215132727Skan && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF 2216132727Skan && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) 2217132727Skan return; 2218132727Skan break; 2219132727Skan 2220132727Skan case MEM: 2221132727Skan /* A MEM is allowed to be shared if its address is constant. */ 2222132727Skan if (CONSTANT_ADDRESS_P (XEXP (x, 0)) 2223132727Skan || reload_completed || reload_in_progress) 2224132727Skan return; 2225132727Skan 2226132727Skan break; 2227132727Skan 2228132727Skan default: 2229132727Skan break; 2230132727Skan } 2231132727Skan 2232132727Skan /* This rtx may not be shared. If it has already been seen, 2233132727Skan replace it with a copy of itself. */ 2234169699Skan#ifdef ENABLE_CHECKING 2235132727Skan if (RTX_FLAG (x, used)) 2236132727Skan { 2237169699Skan error ("invalid rtl sharing found in the insn"); 2238132727Skan debug_rtx (insn); 2239169699Skan error ("shared rtx"); 2240132727Skan debug_rtx (x); 2241169699Skan internal_error ("internal consistency failure"); 2242132727Skan } 2243169699Skan#endif 2244169699Skan gcc_assert (!RTX_FLAG (x, used)); 2245169699Skan 2246132727Skan RTX_FLAG (x, used) = 1; 2247132727Skan 2248132727Skan /* Now scan the subexpressions recursively. */ 2249132727Skan 2250132727Skan format_ptr = GET_RTX_FORMAT (code); 2251132727Skan 2252132727Skan for (i = 0; i < GET_RTX_LENGTH (code); i++) 2253132727Skan { 2254132727Skan switch (*format_ptr++) 2255132727Skan { 2256132727Skan case 'e': 2257132727Skan verify_rtx_sharing (XEXP (x, i), insn); 2258132727Skan break; 2259132727Skan 2260132727Skan case 'E': 2261132727Skan if (XVEC (x, i) != NULL) 2262132727Skan { 2263132727Skan int j; 2264132727Skan int len = XVECLEN (x, i); 2265132727Skan 2266132727Skan for (j = 0; j < len; j++) 2267132727Skan { 2268169699Skan /* We allow sharing of ASM_OPERANDS inside single 2269169699Skan instruction. */ 2270132727Skan if (j && GET_CODE (XVECEXP (x, i, j)) == SET 2271169699Skan && (GET_CODE (SET_SRC (XVECEXP (x, i, j))) 2272169699Skan == ASM_OPERANDS)) 2273132727Skan verify_rtx_sharing (SET_DEST (XVECEXP (x, i, j)), insn); 2274132727Skan else 2275132727Skan verify_rtx_sharing (XVECEXP (x, i, j), insn); 2276132727Skan } 2277132727Skan } 2278132727Skan break; 2279132727Skan } 2280132727Skan } 2281132727Skan return; 2282132727Skan} 2283132727Skan 2284132727Skan/* Go through all the RTL insn bodies and check that there is no unexpected 2285132727Skan sharing in between the subexpressions. */ 2286132727Skan 2287132727Skanvoid 2288132727Skanverify_rtl_sharing (void) 2289132727Skan{ 2290132727Skan rtx p; 2291132727Skan 2292132727Skan for (p = get_insns (); p; p = NEXT_INSN (p)) 2293132727Skan if (INSN_P (p)) 2294132727Skan { 2295132727Skan reset_used_flags (PATTERN (p)); 2296132727Skan reset_used_flags (REG_NOTES (p)); 2297132727Skan reset_used_flags (LOG_LINKS (p)); 2298132727Skan } 2299132727Skan 2300132727Skan for (p = get_insns (); p; p = NEXT_INSN (p)) 2301132727Skan if (INSN_P (p)) 2302132727Skan { 2303132727Skan verify_rtx_sharing (PATTERN (p), p); 2304132727Skan verify_rtx_sharing (REG_NOTES (p), p); 2305132727Skan verify_rtx_sharing (LOG_LINKS (p), p); 2306132727Skan } 2307132727Skan} 2308132727Skan 230972562Sobrien/* Go through all the RTL insn bodies and copy any invalid shared structure. 231072562Sobrien Assumes the mark bits are cleared at entry. */ 231172562Sobrien 2312132727Skanvoid 2313132727Skanunshare_all_rtl_in_chain (rtx insn) 231472562Sobrien{ 231572562Sobrien for (; insn; insn = NEXT_INSN (insn)) 231690075Sobrien if (INSN_P (insn)) 231772562Sobrien { 231872562Sobrien PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn)); 231972562Sobrien REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn)); 232072562Sobrien LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn)); 232172562Sobrien } 232272562Sobrien} 232372562Sobrien 232472562Sobrien/* Go through all virtual stack slots of a function and copy any 232572562Sobrien shared structure. */ 232672562Sobrienstatic void 2327132727Skanunshare_all_decls (tree blk) 232872562Sobrien{ 232972562Sobrien tree t; 233072562Sobrien 233172562Sobrien /* Copy shared decls. */ 233272562Sobrien for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) 233390075Sobrien if (DECL_RTL_SET_P (t)) 233490075Sobrien SET_DECL_RTL (t, copy_rtx_if_shared (DECL_RTL (t))); 233572562Sobrien 233672562Sobrien /* Now process sub-blocks. */ 233772562Sobrien for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) 233872562Sobrien unshare_all_decls (t); 233972562Sobrien} 234072562Sobrien 234172562Sobrien/* Go through all virtual stack slots of a function and mark them as 234290075Sobrien not shared. */ 234372562Sobrienstatic void 2344132727Skanreset_used_decls (tree blk) 234572562Sobrien{ 234672562Sobrien tree t; 234772562Sobrien 234872562Sobrien /* Mark decls. */ 234972562Sobrien for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) 235090075Sobrien if (DECL_RTL_SET_P (t)) 235190075Sobrien reset_used_flags (DECL_RTL (t)); 235272562Sobrien 235372562Sobrien /* Now process sub-blocks. */ 235472562Sobrien for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) 235572562Sobrien reset_used_decls (t); 235672562Sobrien} 235772562Sobrien 235818334Speter/* Mark ORIG as in use, and return a copy of it if it was already in use. 2359132727Skan Recursively does the same for subexpressions. Uses 2360132727Skan copy_rtx_if_shared_1 to reduce stack space. */ 236118334Speter 236218334Speterrtx 2363132727Skancopy_rtx_if_shared (rtx orig) 236418334Speter{ 2365132727Skan copy_rtx_if_shared_1 (&orig); 2366132727Skan return orig; 2367132727Skan} 2368132727Skan 2369132727Skan/* Mark *ORIG1 as in use, and set it to a copy of it if it was already in 2370132727Skan use. Recursively does the same for subexpressions. */ 2371132727Skan 2372132727Skanstatic void 2373132727Skancopy_rtx_if_shared_1 (rtx *orig1) 2374132727Skan{ 2375132727Skan rtx x; 237690075Sobrien int i; 237790075Sobrien enum rtx_code code; 2378132727Skan rtx *last_ptr; 237990075Sobrien const char *format_ptr; 238018334Speter int copied = 0; 2381132727Skan int length; 238218334Speter 2383132727Skan /* Repeat is used to turn tail-recursion into iteration. */ 2384132727Skanrepeat: 2385132727Skan x = *orig1; 2386132727Skan 238718334Speter if (x == 0) 2388132727Skan return; 238918334Speter 239018334Speter code = GET_CODE (x); 239118334Speter 239218334Speter /* These types may be freely shared. */ 239318334Speter 239418334Speter switch (code) 239518334Speter { 239618334Speter case REG: 239718334Speter case CONST_INT: 239818334Speter case CONST_DOUBLE: 239996263Sobrien case CONST_VECTOR: 240018334Speter case SYMBOL_REF: 2401132727Skan case LABEL_REF: 240218334Speter case CODE_LABEL: 240318334Speter case PC: 240418334Speter case CC0: 240518334Speter case SCRATCH: 240650397Sobrien /* SCRATCH must be shared because they represent distinct values. */ 2407132727Skan return; 2408169699Skan case CLOBBER: 2409169699Skan if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) 2410169699Skan return; 2411169699Skan break; 241218334Speter 241318334Speter case CONST: 241418334Speter /* CONST can be shared if it contains a SYMBOL_REF. If it contains 241518334Speter a LABEL_REF, it isn't sharable. */ 241618334Speter if (GET_CODE (XEXP (x, 0)) == PLUS 241718334Speter && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF 241818334Speter && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) 2419132727Skan return; 242018334Speter break; 242118334Speter 242218334Speter case INSN: 242318334Speter case JUMP_INSN: 242418334Speter case CALL_INSN: 242518334Speter case NOTE: 242618334Speter case BARRIER: 242718334Speter /* The chain of insns is not being copied. */ 2428132727Skan return; 242918334Speter 243050397Sobrien default: 243150397Sobrien break; 243218334Speter } 243318334Speter 243418334Speter /* This rtx may not be shared. If it has already been seen, 243518334Speter replace it with a copy of itself. */ 243618334Speter 2437117404Skan if (RTX_FLAG (x, used)) 243818334Speter { 2439169699Skan x = shallow_copy_rtx (x); 244018334Speter copied = 1; 244118334Speter } 2442117404Skan RTX_FLAG (x, used) = 1; 244318334Speter 244418334Speter /* Now scan the subexpressions recursively. 244518334Speter We can store any replaced subexpressions directly into X 244618334Speter since we know X is not shared! Any vectors in X 244718334Speter must be copied if X was copied. */ 244818334Speter 244918334Speter format_ptr = GET_RTX_FORMAT (code); 2450132727Skan length = GET_RTX_LENGTH (code); 2451132727Skan last_ptr = NULL; 2452132727Skan 2453132727Skan for (i = 0; i < length; i++) 245418334Speter { 245518334Speter switch (*format_ptr++) 245618334Speter { 245718334Speter case 'e': 2458132727Skan if (last_ptr) 2459132727Skan copy_rtx_if_shared_1 (last_ptr); 2460132727Skan last_ptr = &XEXP (x, i); 246118334Speter break; 246218334Speter 246318334Speter case 'E': 246418334Speter if (XVEC (x, i) != NULL) 246518334Speter { 246690075Sobrien int j; 246718334Speter int len = XVECLEN (x, i); 2468132727Skan 2469132727Skan /* Copy the vector iff I copied the rtx and the length 2470132727Skan is nonzero. */ 247118334Speter if (copied && len > 0) 247290075Sobrien XVEC (x, i) = gen_rtvec_v (len, XVEC (x, i)->elem); 2473132727Skan 2474132727Skan /* Call recursively on all inside the vector. */ 247518334Speter for (j = 0; j < len; j++) 2476132727Skan { 2477132727Skan if (last_ptr) 2478132727Skan copy_rtx_if_shared_1 (last_ptr); 2479132727Skan last_ptr = &XVECEXP (x, i, j); 2480132727Skan } 248118334Speter } 248218334Speter break; 248318334Speter } 248418334Speter } 2485132727Skan *orig1 = x; 2486132727Skan if (last_ptr) 2487132727Skan { 2488132727Skan orig1 = last_ptr; 2489132727Skan goto repeat; 2490132727Skan } 2491132727Skan return; 249218334Speter} 249318334Speter 249418334Speter/* Clear all the USED bits in X to allow copy_rtx_if_shared to be used 249518334Speter to look for shared sub-parts. */ 249618334Speter 249718334Spetervoid 2498132727Skanreset_used_flags (rtx x) 249918334Speter{ 250090075Sobrien int i, j; 250190075Sobrien enum rtx_code code; 250290075Sobrien const char *format_ptr; 2503132727Skan int length; 250418334Speter 2505132727Skan /* Repeat is used to turn tail-recursion into iteration. */ 2506132727Skanrepeat: 250718334Speter if (x == 0) 250818334Speter return; 250918334Speter 251018334Speter code = GET_CODE (x); 251118334Speter 251218334Speter /* These types may be freely shared so we needn't do any resetting 251318334Speter for them. */ 251418334Speter 251518334Speter switch (code) 251618334Speter { 251718334Speter case REG: 251818334Speter case CONST_INT: 251918334Speter case CONST_DOUBLE: 252096263Sobrien case CONST_VECTOR: 252118334Speter case SYMBOL_REF: 252218334Speter case CODE_LABEL: 252318334Speter case PC: 252418334Speter case CC0: 252518334Speter return; 252618334Speter 252718334Speter case INSN: 252818334Speter case JUMP_INSN: 252918334Speter case CALL_INSN: 253018334Speter case NOTE: 253118334Speter case LABEL_REF: 253218334Speter case BARRIER: 253318334Speter /* The chain of insns is not being copied. */ 253418334Speter return; 253590075Sobrien 253650397Sobrien default: 253750397Sobrien break; 253818334Speter } 253918334Speter 2540117404Skan RTX_FLAG (x, used) = 0; 254118334Speter 254218334Speter format_ptr = GET_RTX_FORMAT (code); 2543132727Skan length = GET_RTX_LENGTH (code); 2544132727Skan 2545132727Skan for (i = 0; i < length; i++) 254618334Speter { 254718334Speter switch (*format_ptr++) 254818334Speter { 254918334Speter case 'e': 2550132727Skan if (i == length-1) 2551132727Skan { 2552132727Skan x = XEXP (x, i); 2553132727Skan goto repeat; 2554132727Skan } 255518334Speter reset_used_flags (XEXP (x, i)); 255618334Speter break; 255718334Speter 255818334Speter case 'E': 255918334Speter for (j = 0; j < XVECLEN (x, i); j++) 256018334Speter reset_used_flags (XVECEXP (x, i, j)); 256118334Speter break; 256218334Speter } 256318334Speter } 256418334Speter} 2565132727Skan 2566132727Skan/* Set all the USED bits in X to allow copy_rtx_if_shared to be used 2567132727Skan to look for shared sub-parts. */ 2568132727Skan 2569132727Skanvoid 2570132727Skanset_used_flags (rtx x) 2571132727Skan{ 2572132727Skan int i, j; 2573132727Skan enum rtx_code code; 2574132727Skan const char *format_ptr; 2575132727Skan 2576132727Skan if (x == 0) 2577132727Skan return; 2578132727Skan 2579132727Skan code = GET_CODE (x); 2580132727Skan 2581132727Skan /* These types may be freely shared so we needn't do any resetting 2582132727Skan for them. */ 2583132727Skan 2584132727Skan switch (code) 2585132727Skan { 2586132727Skan case REG: 2587132727Skan case CONST_INT: 2588132727Skan case CONST_DOUBLE: 2589132727Skan case CONST_VECTOR: 2590132727Skan case SYMBOL_REF: 2591132727Skan case CODE_LABEL: 2592132727Skan case PC: 2593132727Skan case CC0: 2594132727Skan return; 2595132727Skan 2596132727Skan case INSN: 2597132727Skan case JUMP_INSN: 2598132727Skan case CALL_INSN: 2599132727Skan case NOTE: 2600132727Skan case LABEL_REF: 2601132727Skan case BARRIER: 2602132727Skan /* The chain of insns is not being copied. */ 2603132727Skan return; 2604132727Skan 2605132727Skan default: 2606132727Skan break; 2607132727Skan } 2608132727Skan 2609132727Skan RTX_FLAG (x, used) = 1; 2610132727Skan 2611132727Skan format_ptr = GET_RTX_FORMAT (code); 2612132727Skan for (i = 0; i < GET_RTX_LENGTH (code); i++) 2613132727Skan { 2614132727Skan switch (*format_ptr++) 2615132727Skan { 2616132727Skan case 'e': 2617132727Skan set_used_flags (XEXP (x, i)); 2618132727Skan break; 2619132727Skan 2620132727Skan case 'E': 2621132727Skan for (j = 0; j < XVECLEN (x, i); j++) 2622132727Skan set_used_flags (XVECEXP (x, i, j)); 2623132727Skan break; 2624132727Skan } 2625132727Skan } 2626132727Skan} 262718334Speter 262818334Speter/* Copy X if necessary so that it won't be altered by changes in OTHER. 262918334Speter Return X or the rtx for the pseudo reg the value of X was copied into. 263018334Speter OTHER must be valid as a SET_DEST. */ 263118334Speter 263218334Speterrtx 2633132727Skanmake_safe_from (rtx x, rtx other) 263418334Speter{ 263518334Speter while (1) 263618334Speter switch (GET_CODE (other)) 263718334Speter { 263818334Speter case SUBREG: 263918334Speter other = SUBREG_REG (other); 264018334Speter break; 264118334Speter case STRICT_LOW_PART: 264218334Speter case SIGN_EXTEND: 264318334Speter case ZERO_EXTEND: 264418334Speter other = XEXP (other, 0); 264518334Speter break; 264618334Speter default: 264718334Speter goto done; 264818334Speter } 264918334Speter done: 2650169699Skan if ((MEM_P (other) 265118334Speter && ! CONSTANT_P (x) 2652169699Skan && !REG_P (x) 265318334Speter && GET_CODE (x) != SUBREG) 2654169699Skan || (REG_P (other) 265518334Speter && (REGNO (other) < FIRST_PSEUDO_REGISTER 265618334Speter || reg_mentioned_p (other, x)))) 265718334Speter { 265818334Speter rtx temp = gen_reg_rtx (GET_MODE (x)); 265918334Speter emit_move_insn (temp, x); 266018334Speter return temp; 266118334Speter } 266218334Speter return x; 266318334Speter} 266418334Speter 266518334Speter/* Emission of insns (adding them to the doubly-linked list). */ 266618334Speter 266718334Speter/* Return the first insn of the current sequence or current function. */ 266818334Speter 266918334Speterrtx 2670132727Skanget_insns (void) 267118334Speter{ 267218334Speter return first_insn; 267318334Speter} 267418334Speter 2675117404Skan/* Specify a new insn as the first in the chain. */ 2676117404Skan 2677117404Skanvoid 2678132727Skanset_first_insn (rtx insn) 2679117404Skan{ 2680169699Skan gcc_assert (!PREV_INSN (insn)); 2681117404Skan first_insn = insn; 2682117404Skan} 2683117404Skan 268418334Speter/* Return the last insn emitted in current sequence or current function. */ 268518334Speter 268618334Speterrtx 2687132727Skanget_last_insn (void) 268818334Speter{ 268918334Speter return last_insn; 269018334Speter} 269118334Speter 269218334Speter/* Specify a new insn as the last in the chain. */ 269318334Speter 269418334Spetervoid 2695132727Skanset_last_insn (rtx insn) 269618334Speter{ 2697169699Skan gcc_assert (!NEXT_INSN (insn)); 269818334Speter last_insn = insn; 269918334Speter} 270018334Speter 270118334Speter/* Return the last insn emitted, even if it is in a sequence now pushed. */ 270218334Speter 270318334Speterrtx 2704132727Skanget_last_insn_anywhere (void) 270518334Speter{ 270618334Speter struct sequence_stack *stack; 270718334Speter if (last_insn) 270818334Speter return last_insn; 270990075Sobrien for (stack = seq_stack; stack; stack = stack->next) 271018334Speter if (stack->last != 0) 271118334Speter return stack->last; 271218334Speter return 0; 271318334Speter} 271418334Speter 2715117404Skan/* Return the first nonnote insn emitted in current sequence or current 2716117404Skan function. This routine looks inside SEQUENCEs. */ 2717117404Skan 2718117404Skanrtx 2719132727Skanget_first_nonnote_insn (void) 2720117404Skan{ 2721117404Skan rtx insn = first_insn; 2722117404Skan 2723146906Skan if (insn) 2724117404Skan { 2725146906Skan if (NOTE_P (insn)) 2726146906Skan for (insn = next_insn (insn); 2727146906Skan insn && NOTE_P (insn); 2728146906Skan insn = next_insn (insn)) 2729146906Skan continue; 2730146906Skan else 2731146906Skan { 2732169699Skan if (NONJUMP_INSN_P (insn) 2733146906Skan && GET_CODE (PATTERN (insn)) == SEQUENCE) 2734146906Skan insn = XVECEXP (PATTERN (insn), 0, 0); 2735146906Skan } 2736117404Skan } 2737117404Skan 2738117404Skan return insn; 2739117404Skan} 2740117404Skan 2741117404Skan/* Return the last nonnote insn emitted in current sequence or current 2742117404Skan function. This routine looks inside SEQUENCEs. */ 2743117404Skan 2744117404Skanrtx 2745132727Skanget_last_nonnote_insn (void) 2746117404Skan{ 2747117404Skan rtx insn = last_insn; 2748117404Skan 2749146906Skan if (insn) 2750117404Skan { 2751146906Skan if (NOTE_P (insn)) 2752146906Skan for (insn = previous_insn (insn); 2753146906Skan insn && NOTE_P (insn); 2754146906Skan insn = previous_insn (insn)) 2755146906Skan continue; 2756146906Skan else 2757146906Skan { 2758169699Skan if (NONJUMP_INSN_P (insn) 2759146906Skan && GET_CODE (PATTERN (insn)) == SEQUENCE) 2760146906Skan insn = XVECEXP (PATTERN (insn), 0, 2761146906Skan XVECLEN (PATTERN (insn), 0) - 1); 2762146906Skan } 2763117404Skan } 2764117404Skan 2765117404Skan return insn; 2766117404Skan} 2767117404Skan 276818334Speter/* Return a number larger than any instruction's uid in this function. */ 276918334Speter 277018334Speterint 2771132727Skanget_max_uid (void) 277218334Speter{ 277318334Speter return cur_insn_uid; 277418334Speter} 277590075Sobrien 277690075Sobrien/* Renumber instructions so that no instruction UIDs are wasted. */ 277790075Sobrien 277890075Sobrienvoid 2779169699Skanrenumber_insns (void) 278090075Sobrien{ 278190075Sobrien rtx insn; 278290075Sobrien 278390075Sobrien /* If we're not supposed to renumber instructions, don't. */ 278490075Sobrien if (!flag_renumber_insns) 278590075Sobrien return; 278690075Sobrien 278790075Sobrien /* If there aren't that many instructions, then it's not really 278890075Sobrien worth renumbering them. */ 278990075Sobrien if (flag_renumber_insns == 1 && get_max_uid () < 25000) 279090075Sobrien return; 279190075Sobrien 279290075Sobrien cur_insn_uid = 1; 279390075Sobrien 279490075Sobrien for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 279590075Sobrien { 2796169699Skan if (dump_file) 2797169699Skan fprintf (dump_file, "Renumbering insn %d to %d\n", 279890075Sobrien INSN_UID (insn), cur_insn_uid); 279990075Sobrien INSN_UID (insn) = cur_insn_uid++; 280090075Sobrien } 280190075Sobrien} 280218334Speter 280318334Speter/* Return the next insn. If it is a SEQUENCE, return the first insn 280418334Speter of the sequence. */ 280518334Speter 280618334Speterrtx 2807132727Skannext_insn (rtx insn) 280818334Speter{ 280918334Speter if (insn) 281018334Speter { 281118334Speter insn = NEXT_INSN (insn); 2812169699Skan if (insn && NONJUMP_INSN_P (insn) 281318334Speter && GET_CODE (PATTERN (insn)) == SEQUENCE) 281418334Speter insn = XVECEXP (PATTERN (insn), 0, 0); 281518334Speter } 281618334Speter 281718334Speter return insn; 281818334Speter} 281918334Speter 282018334Speter/* Return the previous insn. If it is a SEQUENCE, return the last insn 282118334Speter of the sequence. */ 282218334Speter 282318334Speterrtx 2824132727Skanprevious_insn (rtx insn) 282518334Speter{ 282618334Speter if (insn) 282718334Speter { 282818334Speter insn = PREV_INSN (insn); 2829169699Skan if (insn && NONJUMP_INSN_P (insn) 283018334Speter && GET_CODE (PATTERN (insn)) == SEQUENCE) 283118334Speter insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1); 283218334Speter } 283318334Speter 283418334Speter return insn; 283518334Speter} 283618334Speter 283718334Speter/* Return the next insn after INSN that is not a NOTE. This routine does not 283818334Speter look inside SEQUENCEs. */ 283918334Speter 284018334Speterrtx 2841132727Skannext_nonnote_insn (rtx insn) 284218334Speter{ 284318334Speter while (insn) 284418334Speter { 284518334Speter insn = NEXT_INSN (insn); 2846169699Skan if (insn == 0 || !NOTE_P (insn)) 284718334Speter break; 284818334Speter } 284918334Speter 285018334Speter return insn; 285118334Speter} 285218334Speter 285318334Speter/* Return the previous insn before INSN that is not a NOTE. This routine does 285418334Speter not look inside SEQUENCEs. */ 285518334Speter 285618334Speterrtx 2857132727Skanprev_nonnote_insn (rtx insn) 285818334Speter{ 285918334Speter while (insn) 286018334Speter { 286118334Speter insn = PREV_INSN (insn); 2862169699Skan if (insn == 0 || !NOTE_P (insn)) 286318334Speter break; 286418334Speter } 286518334Speter 286618334Speter return insn; 286718334Speter} 286818334Speter 286918334Speter/* Return the next INSN, CALL_INSN or JUMP_INSN after INSN; 287018334Speter or 0, if there is none. This routine does not look inside 287150397Sobrien SEQUENCEs. */ 287218334Speter 287318334Speterrtx 2874132727Skannext_real_insn (rtx insn) 287518334Speter{ 287618334Speter while (insn) 287718334Speter { 287818334Speter insn = NEXT_INSN (insn); 2879169699Skan if (insn == 0 || INSN_P (insn)) 288018334Speter break; 288118334Speter } 288218334Speter 288318334Speter return insn; 288418334Speter} 288518334Speter 288618334Speter/* Return the last INSN, CALL_INSN or JUMP_INSN before INSN; 288718334Speter or 0, if there is none. This routine does not look inside 288818334Speter SEQUENCEs. */ 288918334Speter 289018334Speterrtx 2891132727Skanprev_real_insn (rtx insn) 289218334Speter{ 289318334Speter while (insn) 289418334Speter { 289518334Speter insn = PREV_INSN (insn); 2896169699Skan if (insn == 0 || INSN_P (insn)) 289718334Speter break; 289818334Speter } 289918334Speter 290018334Speter return insn; 290118334Speter} 290218334Speter 2903132727Skan/* Return the last CALL_INSN in the current list, or 0 if there is none. 2904132727Skan This routine does not look inside SEQUENCEs. */ 2905132727Skan 2906132727Skanrtx 2907132727Skanlast_call_insn (void) 2908132727Skan{ 2909132727Skan rtx insn; 2910132727Skan 2911132727Skan for (insn = get_last_insn (); 2912169699Skan insn && !CALL_P (insn); 2913132727Skan insn = PREV_INSN (insn)) 2914132727Skan ; 2915132727Skan 2916132727Skan return insn; 2917132727Skan} 2918132727Skan 291918334Speter/* Find the next insn after INSN that really does something. This routine 292018334Speter does not look inside SEQUENCEs. Until reload has completed, this is the 292118334Speter same as next_real_insn. */ 292218334Speter 292390075Sobrienint 2924132727Skanactive_insn_p (rtx insn) 292590075Sobrien{ 2926169699Skan return (CALL_P (insn) || JUMP_P (insn) 2927169699Skan || (NONJUMP_INSN_P (insn) 292890075Sobrien && (! reload_completed 292990075Sobrien || (GET_CODE (PATTERN (insn)) != USE 293090075Sobrien && GET_CODE (PATTERN (insn)) != CLOBBER)))); 293190075Sobrien} 293290075Sobrien 293318334Speterrtx 2934132727Skannext_active_insn (rtx insn) 293518334Speter{ 293618334Speter while (insn) 293718334Speter { 293818334Speter insn = NEXT_INSN (insn); 293990075Sobrien if (insn == 0 || active_insn_p (insn)) 294018334Speter break; 294118334Speter } 294218334Speter 294318334Speter return insn; 294418334Speter} 294518334Speter 294618334Speter/* Find the last insn before INSN that really does something. This routine 294718334Speter does not look inside SEQUENCEs. Until reload has completed, this is the 294818334Speter same as prev_real_insn. */ 294918334Speter 295018334Speterrtx 2951132727Skanprev_active_insn (rtx insn) 295218334Speter{ 295318334Speter while (insn) 295418334Speter { 295518334Speter insn = PREV_INSN (insn); 295690075Sobrien if (insn == 0 || active_insn_p (insn)) 295718334Speter break; 295818334Speter } 295918334Speter 296018334Speter return insn; 296118334Speter} 296218334Speter 296318334Speter/* Return the next CODE_LABEL after the insn INSN, or 0 if there is none. */ 296418334Speter 296518334Speterrtx 2966132727Skannext_label (rtx insn) 296718334Speter{ 296818334Speter while (insn) 296918334Speter { 297018334Speter insn = NEXT_INSN (insn); 2971169699Skan if (insn == 0 || LABEL_P (insn)) 297218334Speter break; 297318334Speter } 297418334Speter 297518334Speter return insn; 297618334Speter} 297718334Speter 297818334Speter/* Return the last CODE_LABEL before the insn INSN, or 0 if there is none. */ 297918334Speter 298018334Speterrtx 2981132727Skanprev_label (rtx insn) 298218334Speter{ 298318334Speter while (insn) 298418334Speter { 298518334Speter insn = PREV_INSN (insn); 2986169699Skan if (insn == 0 || LABEL_P (insn)) 298718334Speter break; 298818334Speter } 298918334Speter 299018334Speter return insn; 299118334Speter} 2992169699Skan 2993169699Skan/* Return the last label to mark the same position as LABEL. Return null 2994169699Skan if LABEL itself is null. */ 2995169699Skan 2996169699Skanrtx 2997169699Skanskip_consecutive_labels (rtx label) 2998169699Skan{ 2999169699Skan rtx insn; 3000169699Skan 3001169699Skan for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn)) 3002169699Skan if (LABEL_P (insn)) 3003169699Skan label = insn; 3004169699Skan 3005169699Skan return label; 3006169699Skan} 300718334Speter 300818334Speter#ifdef HAVE_cc0 300918334Speter/* INSN uses CC0 and is being moved into a delay slot. Set up REG_CC_SETTER 301018334Speter and REG_CC_USER notes so we can find it. */ 301118334Speter 301218334Spetervoid 3013132727Skanlink_cc0_insns (rtx insn) 301418334Speter{ 301518334Speter rtx user = next_nonnote_insn (insn); 301618334Speter 3017169699Skan if (NONJUMP_INSN_P (user) && GET_CODE (PATTERN (user)) == SEQUENCE) 301818334Speter user = XVECEXP (PATTERN (user), 0, 0); 301918334Speter 302090075Sobrien REG_NOTES (user) = gen_rtx_INSN_LIST (REG_CC_SETTER, insn, 302190075Sobrien REG_NOTES (user)); 302250397Sobrien REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_CC_USER, user, REG_NOTES (insn)); 302318334Speter} 302418334Speter 302518334Speter/* Return the next insn that uses CC0 after INSN, which is assumed to 302618334Speter set it. This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter 302718334Speter applied to the result of this function should yield INSN). 302818334Speter 302918334Speter Normally, this is simply the next insn. However, if a REG_CC_USER note 303018334Speter is present, it contains the insn that uses CC0. 303118334Speter 303218334Speter Return 0 if we can't find the insn. */ 303318334Speter 303418334Speterrtx 3035132727Skannext_cc0_user (rtx insn) 303618334Speter{ 303718334Speter rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX); 303818334Speter 303918334Speter if (note) 304018334Speter return XEXP (note, 0); 304118334Speter 304218334Speter insn = next_nonnote_insn (insn); 3043169699Skan if (insn && NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE) 304418334Speter insn = XVECEXP (PATTERN (insn), 0, 0); 304518334Speter 304690075Sobrien if (insn && INSN_P (insn) && reg_mentioned_p (cc0_rtx, PATTERN (insn))) 304718334Speter return insn; 304818334Speter 304918334Speter return 0; 305018334Speter} 305118334Speter 305218334Speter/* Find the insn that set CC0 for INSN. Unless INSN has a REG_CC_SETTER 305318334Speter note, it is the previous insn. */ 305418334Speter 305518334Speterrtx 3056132727Skanprev_cc0_setter (rtx insn) 305718334Speter{ 305818334Speter rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); 305918334Speter 306018334Speter if (note) 306118334Speter return XEXP (note, 0); 306218334Speter 306318334Speter insn = prev_nonnote_insn (insn); 3064169699Skan gcc_assert (sets_cc0_p (PATTERN (insn))); 306518334Speter 306618334Speter return insn; 306718334Speter} 306818334Speter#endif 306990075Sobrien 307090075Sobrien/* Increment the label uses for all labels present in rtx. */ 307190075Sobrien 307290075Sobrienstatic void 3073132727Skanmark_label_nuses (rtx x) 307490075Sobrien{ 307590075Sobrien enum rtx_code code; 307690075Sobrien int i, j; 307790075Sobrien const char *fmt; 307890075Sobrien 307990075Sobrien code = GET_CODE (x); 3080132727Skan if (code == LABEL_REF && LABEL_P (XEXP (x, 0))) 308190075Sobrien LABEL_NUSES (XEXP (x, 0))++; 308290075Sobrien 308390075Sobrien fmt = GET_RTX_FORMAT (code); 308490075Sobrien for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 308590075Sobrien { 308690075Sobrien if (fmt[i] == 'e') 3087117404Skan mark_label_nuses (XEXP (x, i)); 308890075Sobrien else if (fmt[i] == 'E') 3089117404Skan for (j = XVECLEN (x, i) - 1; j >= 0; j--) 309090075Sobrien mark_label_nuses (XVECEXP (x, i, j)); 309190075Sobrien } 309290075Sobrien} 309390075Sobrien 309418334Speter 309518334Speter/* Try splitting insns that can be split for better scheduling. 309618334Speter PAT is the pattern which might split. 309718334Speter TRIAL is the insn providing PAT. 3098117404Skan LAST is nonzero if we should return the last insn of the sequence produced. 309918334Speter 310018334Speter If this routine succeeds in splitting, it returns the first or last 310118334Speter replacement insn depending on the value of LAST. Otherwise, it 310218334Speter returns TRIAL. If the insn to be returned can be split, it will be. */ 310318334Speter 310418334Speterrtx 3105132727Skantry_split (rtx pat, rtx trial, int last) 310618334Speter{ 310718334Speter rtx before = PREV_INSN (trial); 310818334Speter rtx after = NEXT_INSN (trial); 310918334Speter int has_barrier = 0; 311018334Speter rtx tem; 311190075Sobrien rtx note, seq; 311290075Sobrien int probability; 3113117404Skan rtx insn_last, insn; 3114117404Skan int njumps = 0; 311518334Speter 311690075Sobrien if (any_condjump_p (trial) 311790075Sobrien && (note = find_reg_note (trial, REG_BR_PROB, 0))) 311890075Sobrien split_branch_probability = INTVAL (XEXP (note, 0)); 311990075Sobrien probability = split_branch_probability; 312090075Sobrien 312190075Sobrien seq = split_insns (pat, trial); 312290075Sobrien 312390075Sobrien split_branch_probability = -1; 312490075Sobrien 312518334Speter /* If we are splitting a JUMP_INSN, it might be followed by a BARRIER. 312618334Speter We may need to handle this specially. */ 3127169699Skan if (after && BARRIER_P (after)) 312818334Speter { 312918334Speter has_barrier = 1; 313018334Speter after = NEXT_INSN (after); 313118334Speter } 313218334Speter 3133117404Skan if (!seq) 3134117404Skan return trial; 3135117404Skan 3136117404Skan /* Avoid infinite loop if any insn of the result matches 3137117404Skan the original pattern. */ 3138117404Skan insn_last = seq; 3139117404Skan while (1) 314018334Speter { 3141117404Skan if (INSN_P (insn_last) 3142117404Skan && rtx_equal_p (PATTERN (insn_last), pat)) 3143117404Skan return trial; 3144117404Skan if (!NEXT_INSN (insn_last)) 3145117404Skan break; 3146117404Skan insn_last = NEXT_INSN (insn_last); 3147117404Skan } 3148117404Skan 3149117404Skan /* Mark labels. */ 3150117404Skan for (insn = insn_last; insn ; insn = PREV_INSN (insn)) 3151117404Skan { 3152169699Skan if (JUMP_P (insn)) 315318334Speter { 3154117404Skan mark_jump_label (PATTERN (insn), insn, 0); 3155117404Skan njumps++; 3156117404Skan if (probability != -1 3157117404Skan && any_condjump_p (insn) 3158117404Skan && !find_reg_note (insn, REG_BR_PROB, 0)) 3159117404Skan { 3160117404Skan /* We can preserve the REG_BR_PROB notes only if exactly 3161117404Skan one jump is created, otherwise the machine description 3162117404Skan is responsible for this step using 3163117404Skan split_branch_probability variable. */ 3164169699Skan gcc_assert (njumps == 1); 3165117404Skan REG_NOTES (insn) 3166117404Skan = gen_rtx_EXPR_LIST (REG_BR_PROB, 3167117404Skan GEN_INT (probability), 3168117404Skan REG_NOTES (insn)); 3169117404Skan } 3170117404Skan } 3171117404Skan } 317270635Sobrien 3173117404Skan /* If we are splitting a CALL_INSN, look for the CALL_INSN 3174117404Skan in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */ 3175169699Skan if (CALL_P (trial)) 3176117404Skan { 3177117404Skan for (insn = insn_last; insn ; insn = PREV_INSN (insn)) 3178169699Skan if (CALL_P (insn)) 3179117404Skan { 3180132727Skan rtx *p = &CALL_INSN_FUNCTION_USAGE (insn); 3181132727Skan while (*p) 3182132727Skan p = &XEXP (*p, 1); 3183132727Skan *p = CALL_INSN_FUNCTION_USAGE (trial); 3184117404Skan SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial); 3185117404Skan } 3186117404Skan } 318770635Sobrien 3188117404Skan /* Copy notes, particularly those related to the CFG. */ 3189117404Skan for (note = REG_NOTES (trial); note; note = XEXP (note, 1)) 3190117404Skan { 3191117404Skan switch (REG_NOTE_KIND (note)) 3192117404Skan { 3193117404Skan case REG_EH_REGION: 3194117404Skan insn = insn_last; 3195117404Skan while (insn != NULL_RTX) 3196117404Skan { 3197169699Skan if (CALL_P (insn) 3198169699Skan || (flag_non_call_exceptions && INSN_P (insn) 3199117404Skan && may_trap_p (PATTERN (insn)))) 3200117404Skan REG_NOTES (insn) 3201117404Skan = gen_rtx_EXPR_LIST (REG_EH_REGION, 3202117404Skan XEXP (note, 0), 3203117404Skan REG_NOTES (insn)); 3204117404Skan insn = PREV_INSN (insn); 3205117404Skan } 3206117404Skan break; 320718334Speter 3208117404Skan case REG_NORETURN: 3209117404Skan case REG_SETJMP: 3210117404Skan insn = insn_last; 3211117404Skan while (insn != NULL_RTX) 3212117404Skan { 3213169699Skan if (CALL_P (insn)) 3214117404Skan REG_NOTES (insn) 3215222207Sbenl = gen_rtx_EXPR_LIST (GET_MODE (note), 3216117404Skan XEXP (note, 0), 3217117404Skan REG_NOTES (insn)); 3218117404Skan insn = PREV_INSN (insn); 3219117404Skan } 3220117404Skan break; 322190075Sobrien 3222117404Skan case REG_NON_LOCAL_GOTO: 3223117404Skan insn = insn_last; 3224117404Skan while (insn != NULL_RTX) 322590075Sobrien { 3226169699Skan if (JUMP_P (insn)) 3227117404Skan REG_NOTES (insn) 3228222207Sbenl = gen_rtx_EXPR_LIST (GET_MODE (note), 3229117404Skan XEXP (note, 0), 3230117404Skan REG_NOTES (insn)); 3231117404Skan insn = PREV_INSN (insn); 3232117404Skan } 3233117404Skan break; 323418334Speter 3235117404Skan default: 3236117404Skan break; 3237117404Skan } 3238117404Skan } 323990075Sobrien 3240117404Skan /* If there are LABELS inside the split insns increment the 3241117404Skan usage count so we don't delete the label. */ 3242169699Skan if (NONJUMP_INSN_P (trial)) 3243117404Skan { 3244117404Skan insn = insn_last; 3245117404Skan while (insn != NULL_RTX) 3246117404Skan { 3247169699Skan if (NONJUMP_INSN_P (insn)) 3248117404Skan mark_label_nuses (PATTERN (insn)); 324990075Sobrien 3250117404Skan insn = PREV_INSN (insn); 3251117404Skan } 3252117404Skan } 325318334Speter 3254132727Skan tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial)); 325518334Speter 3256117404Skan delete_insn (trial); 3257117404Skan if (has_barrier) 3258117404Skan emit_barrier_after (tem); 325990075Sobrien 3260117404Skan /* Recursively call try_split for each new insn created; by the 3261117404Skan time control returns here that insn will be fully split, so 3262117404Skan set LAST and continue from the insn after the one returned. 3263117404Skan We can't use next_active_insn here since AFTER may be a note. 3264117404Skan Ignore deleted insns, which can be occur if not optimizing. */ 3265117404Skan for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) 3266117404Skan if (! INSN_DELETED_P (tem) && INSN_P (tem)) 3267117404Skan tem = try_split (PATTERN (tem), tem, 1); 326818334Speter 3269117404Skan /* Return either the first or the last insn, depending on which was 3270117404Skan requested. */ 3271117404Skan return last 3272117404Skan ? (after ? PREV_INSN (after) : last_insn) 3273117404Skan : NEXT_INSN (before); 327418334Speter} 327518334Speter 327618334Speter/* Make and return an INSN rtx, initializing all its slots. 327718334Speter Store PATTERN in the pattern slots. */ 327818334Speter 327918334Speterrtx 3280132727Skanmake_insn_raw (rtx pattern) 328118334Speter{ 328290075Sobrien rtx insn; 328318334Speter 328490075Sobrien insn = rtx_alloc (INSN); 328550397Sobrien 328618334Speter INSN_UID (insn) = cur_insn_uid++; 328718334Speter PATTERN (insn) = pattern; 328818334Speter INSN_CODE (insn) = -1; 328918334Speter LOG_LINKS (insn) = NULL; 329018334Speter REG_NOTES (insn) = NULL; 3291132727Skan INSN_LOCATOR (insn) = 0; 3292117404Skan BLOCK_FOR_INSN (insn) = NULL; 329318334Speter 329490075Sobrien#ifdef ENABLE_RTL_CHECKING 329590075Sobrien if (insn 329690075Sobrien && INSN_P (insn) 329790075Sobrien && (returnjump_p (insn) 329890075Sobrien || (GET_CODE (insn) == SET 329990075Sobrien && SET_DEST (insn) == pc_rtx))) 330090075Sobrien { 3301169699Skan warning (0, "ICE: emit_insn used where emit_jump_insn needed:\n"); 330290075Sobrien debug_rtx (insn); 330390075Sobrien } 330490075Sobrien#endif 330590075Sobrien 330618334Speter return insn; 330718334Speter} 330818334Speter 3309117404Skan/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */ 331018334Speter 3311169699Skanrtx 3312132727Skanmake_jump_insn_raw (rtx pattern) 331318334Speter{ 331490075Sobrien rtx insn; 331518334Speter 331618334Speter insn = rtx_alloc (JUMP_INSN); 331718334Speter INSN_UID (insn) = cur_insn_uid++; 331818334Speter 331918334Speter PATTERN (insn) = pattern; 332018334Speter INSN_CODE (insn) = -1; 332118334Speter LOG_LINKS (insn) = NULL; 332218334Speter REG_NOTES (insn) = NULL; 332318334Speter JUMP_LABEL (insn) = NULL; 3324132727Skan INSN_LOCATOR (insn) = 0; 3325117404Skan BLOCK_FOR_INSN (insn) = NULL; 332618334Speter 332718334Speter return insn; 332818334Speter} 332918334Speter 3330117404Skan/* Like `make_insn_raw' but make a CALL_INSN instead of an insn. */ 333118334Speter 333218334Speterstatic rtx 3333132727Skanmake_call_insn_raw (rtx pattern) 333418334Speter{ 333590075Sobrien rtx insn; 333618334Speter 333718334Speter insn = rtx_alloc (CALL_INSN); 333818334Speter INSN_UID (insn) = cur_insn_uid++; 333918334Speter 334018334Speter PATTERN (insn) = pattern; 334118334Speter INSN_CODE (insn) = -1; 334218334Speter LOG_LINKS (insn) = NULL; 334318334Speter REG_NOTES (insn) = NULL; 334418334Speter CALL_INSN_FUNCTION_USAGE (insn) = NULL; 3345132727Skan INSN_LOCATOR (insn) = 0; 3346117404Skan BLOCK_FOR_INSN (insn) = NULL; 334718334Speter 334818334Speter return insn; 334918334Speter} 335018334Speter 335118334Speter/* Add INSN to the end of the doubly-linked list. 335218334Speter INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE. */ 335318334Speter 335418334Spetervoid 3355132727Skanadd_insn (rtx insn) 335618334Speter{ 335718334Speter PREV_INSN (insn) = last_insn; 335818334Speter NEXT_INSN (insn) = 0; 335918334Speter 336018334Speter if (NULL != last_insn) 336118334Speter NEXT_INSN (last_insn) = insn; 336218334Speter 336318334Speter if (NULL == first_insn) 336418334Speter first_insn = insn; 336518334Speter 336618334Speter last_insn = insn; 336718334Speter} 336818334Speter 336918334Speter/* Add INSN into the doubly-linked list after insn AFTER. This and 337018334Speter the next should be the only functions called to insert an insn once 337118334Speter delay slots have been filled since only they know how to update a 337218334Speter SEQUENCE. */ 337318334Speter 337418334Spetervoid 3375132727Skanadd_insn_after (rtx insn, rtx after) 337618334Speter{ 337718334Speter rtx next = NEXT_INSN (after); 337890075Sobrien basic_block bb; 337918334Speter 3380169699Skan gcc_assert (!optimize || !INSN_DELETED_P (after)); 338118334Speter 338218334Speter NEXT_INSN (insn) = next; 338318334Speter PREV_INSN (insn) = after; 338418334Speter 338518334Speter if (next) 338618334Speter { 338718334Speter PREV_INSN (next) = insn; 3388169699Skan if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE) 338918334Speter PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn; 339018334Speter } 339118334Speter else if (last_insn == after) 339218334Speter last_insn = insn; 339318334Speter else 339418334Speter { 339590075Sobrien struct sequence_stack *stack = seq_stack; 339618334Speter /* Scan all pending sequences too. */ 339718334Speter for (; stack; stack = stack->next) 339818334Speter if (after == stack->last) 339918334Speter { 340018334Speter stack->last = insn; 340118334Speter break; 340218334Speter } 340318334Speter 3404169699Skan gcc_assert (stack); 340518334Speter } 340618334Speter 3407169699Skan if (!BARRIER_P (after) 3408169699Skan && !BARRIER_P (insn) 340990075Sobrien && (bb = BLOCK_FOR_INSN (after))) 341090075Sobrien { 341190075Sobrien set_block_for_insn (insn, bb); 3412117404Skan if (INSN_P (insn)) 3413117404Skan bb->flags |= BB_DIRTY; 341490075Sobrien /* Should not happen as first in the BB is always 341590075Sobrien either NOTE or LABEL. */ 3416132727Skan if (BB_END (bb) == after 341790075Sobrien /* Avoid clobbering of structure when creating new BB. */ 3418169699Skan && !BARRIER_P (insn) 3419169699Skan && (!NOTE_P (insn) 342090075Sobrien || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)) 3421132727Skan BB_END (bb) = insn; 342290075Sobrien } 342390075Sobrien 342418334Speter NEXT_INSN (after) = insn; 3425169699Skan if (NONJUMP_INSN_P (after) && GET_CODE (PATTERN (after)) == SEQUENCE) 342618334Speter { 342718334Speter rtx sequence = PATTERN (after); 342818334Speter NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn; 342918334Speter } 343018334Speter} 343118334Speter 343218334Speter/* Add INSN into the doubly-linked list before insn BEFORE. This and 343318334Speter the previous should be the only functions called to insert an insn once 343418334Speter delay slots have been filled since only they know how to update a 343518334Speter SEQUENCE. */ 343618334Speter 343718334Spetervoid 3438132727Skanadd_insn_before (rtx insn, rtx before) 343918334Speter{ 344018334Speter rtx prev = PREV_INSN (before); 344190075Sobrien basic_block bb; 344218334Speter 3443169699Skan gcc_assert (!optimize || !INSN_DELETED_P (before)); 344418334Speter 344518334Speter PREV_INSN (insn) = prev; 344618334Speter NEXT_INSN (insn) = before; 344718334Speter 344818334Speter if (prev) 344918334Speter { 345018334Speter NEXT_INSN (prev) = insn; 3451169699Skan if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE) 345218334Speter { 345318334Speter rtx sequence = PATTERN (prev); 345418334Speter NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn; 345518334Speter } 345618334Speter } 345718334Speter else if (first_insn == before) 345818334Speter first_insn = insn; 345918334Speter else 346018334Speter { 346190075Sobrien struct sequence_stack *stack = seq_stack; 346218334Speter /* Scan all pending sequences too. */ 346318334Speter for (; stack; stack = stack->next) 346418334Speter if (before == stack->first) 346518334Speter { 346618334Speter stack->first = insn; 346718334Speter break; 346818334Speter } 346918334Speter 3470169699Skan gcc_assert (stack); 347118334Speter } 347218334Speter 3473169699Skan if (!BARRIER_P (before) 3474169699Skan && !BARRIER_P (insn) 347590075Sobrien && (bb = BLOCK_FOR_INSN (before))) 347690075Sobrien { 347790075Sobrien set_block_for_insn (insn, bb); 3478117404Skan if (INSN_P (insn)) 3479117404Skan bb->flags |= BB_DIRTY; 3480169699Skan /* Should not happen as first in the BB is always either NOTE or 3481169699Skan LABEL. */ 3482169699Skan gcc_assert (BB_HEAD (bb) != insn 3483169699Skan /* Avoid clobbering of structure when creating new BB. */ 3484169699Skan || BARRIER_P (insn) 3485169699Skan || (NOTE_P (insn) 3486169699Skan && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)); 348790075Sobrien } 348890075Sobrien 348918334Speter PREV_INSN (before) = insn; 3490169699Skan if (NONJUMP_INSN_P (before) && GET_CODE (PATTERN (before)) == SEQUENCE) 349118334Speter PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn; 349218334Speter} 349318334Speter 349452284Sobrien/* Remove an insn from its doubly-linked list. This function knows how 349552284Sobrien to handle sequences. */ 349652284Sobrienvoid 3497132727Skanremove_insn (rtx insn) 349852284Sobrien{ 349952284Sobrien rtx next = NEXT_INSN (insn); 350052284Sobrien rtx prev = PREV_INSN (insn); 350190075Sobrien basic_block bb; 350290075Sobrien 350352284Sobrien if (prev) 350452284Sobrien { 350552284Sobrien NEXT_INSN (prev) = next; 3506169699Skan if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE) 350752284Sobrien { 350852284Sobrien rtx sequence = PATTERN (prev); 350952284Sobrien NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next; 351052284Sobrien } 351152284Sobrien } 351252284Sobrien else if (first_insn == insn) 351352284Sobrien first_insn = next; 351452284Sobrien else 351552284Sobrien { 351690075Sobrien struct sequence_stack *stack = seq_stack; 351752284Sobrien /* Scan all pending sequences too. */ 351852284Sobrien for (; stack; stack = stack->next) 351952284Sobrien if (insn == stack->first) 352052284Sobrien { 352152284Sobrien stack->first = next; 352252284Sobrien break; 352352284Sobrien } 352452284Sobrien 3525169699Skan gcc_assert (stack); 352652284Sobrien } 352752284Sobrien 352852284Sobrien if (next) 352952284Sobrien { 353052284Sobrien PREV_INSN (next) = prev; 3531169699Skan if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE) 353252284Sobrien PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev; 353352284Sobrien } 353452284Sobrien else if (last_insn == insn) 353552284Sobrien last_insn = prev; 353652284Sobrien else 353752284Sobrien { 353890075Sobrien struct sequence_stack *stack = seq_stack; 353952284Sobrien /* Scan all pending sequences too. */ 354052284Sobrien for (; stack; stack = stack->next) 354152284Sobrien if (insn == stack->last) 354252284Sobrien { 354352284Sobrien stack->last = prev; 354452284Sobrien break; 354552284Sobrien } 354652284Sobrien 3547169699Skan gcc_assert (stack); 354852284Sobrien } 3549169699Skan if (!BARRIER_P (insn) 355090075Sobrien && (bb = BLOCK_FOR_INSN (insn))) 355190075Sobrien { 3552117404Skan if (INSN_P (insn)) 3553117404Skan bb->flags |= BB_DIRTY; 3554132727Skan if (BB_HEAD (bb) == insn) 355590075Sobrien { 355696263Sobrien /* Never ever delete the basic block note without deleting whole 355796263Sobrien basic block. */ 3558169699Skan gcc_assert (!NOTE_P (insn)); 3559132727Skan BB_HEAD (bb) = next; 356090075Sobrien } 3561132727Skan if (BB_END (bb) == insn) 3562132727Skan BB_END (bb) = prev; 356390075Sobrien } 356452284Sobrien} 356552284Sobrien 3566132727Skan/* Append CALL_FUSAGE to the CALL_INSN_FUNCTION_USAGE for CALL_INSN. */ 3567132727Skan 3568132727Skanvoid 3569132727Skanadd_function_usage_to (rtx call_insn, rtx call_fusage) 3570132727Skan{ 3571169699Skan gcc_assert (call_insn && CALL_P (call_insn)); 3572132727Skan 3573132727Skan /* Put the register usage information on the CALL. If there is already 3574132727Skan some usage information, put ours at the end. */ 3575132727Skan if (CALL_INSN_FUNCTION_USAGE (call_insn)) 3576132727Skan { 3577132727Skan rtx link; 3578132727Skan 3579132727Skan for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0; 3580132727Skan link = XEXP (link, 1)) 3581132727Skan ; 3582132727Skan 3583132727Skan XEXP (link, 1) = call_fusage; 3584132727Skan } 3585132727Skan else 3586132727Skan CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage; 3587132727Skan} 3588132727Skan 358918334Speter/* Delete all insns made since FROM. 359018334Speter FROM becomes the new last instruction. */ 359118334Speter 359218334Spetervoid 3593132727Skandelete_insns_since (rtx from) 359418334Speter{ 359518334Speter if (from == 0) 359618334Speter first_insn = 0; 359718334Speter else 359818334Speter NEXT_INSN (from) = 0; 359918334Speter last_insn = from; 360018334Speter} 360118334Speter 360218334Speter/* This function is deprecated, please use sequences instead. 360318334Speter 360418334Speter Move a consecutive bunch of insns to a different place in the chain. 360518334Speter The insns to be moved are those between FROM and TO. 360618334Speter They are moved to a new position after the insn AFTER. 360718334Speter AFTER must not be FROM or TO or any insn in between. 360818334Speter 360918334Speter This function does not know about SEQUENCEs and hence should not be 361018334Speter called after delay-slot filling has been done. */ 361118334Speter 361218334Spetervoid 3613132727Skanreorder_insns_nobb (rtx from, rtx to, rtx after) 361418334Speter{ 361518334Speter /* Splice this bunch out of where it is now. */ 361618334Speter if (PREV_INSN (from)) 361718334Speter NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to); 361818334Speter if (NEXT_INSN (to)) 361918334Speter PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from); 362018334Speter if (last_insn == to) 362118334Speter last_insn = PREV_INSN (from); 362218334Speter if (first_insn == from) 362318334Speter first_insn = NEXT_INSN (to); 362418334Speter 362518334Speter /* Make the new neighbors point to it and it to them. */ 362618334Speter if (NEXT_INSN (after)) 362718334Speter PREV_INSN (NEXT_INSN (after)) = to; 362818334Speter 362918334Speter NEXT_INSN (to) = NEXT_INSN (after); 363018334Speter PREV_INSN (from) = after; 363118334Speter NEXT_INSN (after) = from; 363218334Speter if (after == last_insn) 363318334Speter last_insn = to; 363418334Speter} 363518334Speter 363690075Sobrien/* Same as function above, but take care to update BB boundaries. */ 363790075Sobrienvoid 3638132727Skanreorder_insns (rtx from, rtx to, rtx after) 363990075Sobrien{ 364090075Sobrien rtx prev = PREV_INSN (from); 364190075Sobrien basic_block bb, bb2; 364290075Sobrien 364390075Sobrien reorder_insns_nobb (from, to, after); 364490075Sobrien 3645169699Skan if (!BARRIER_P (after) 364690075Sobrien && (bb = BLOCK_FOR_INSN (after))) 364790075Sobrien { 364890075Sobrien rtx x; 3649117404Skan bb->flags |= BB_DIRTY; 3650117404Skan 3651169699Skan if (!BARRIER_P (from) 365290075Sobrien && (bb2 = BLOCK_FOR_INSN (from))) 365390075Sobrien { 3654132727Skan if (BB_END (bb2) == to) 3655132727Skan BB_END (bb2) = prev; 3656117404Skan bb2->flags |= BB_DIRTY; 365790075Sobrien } 365890075Sobrien 3659132727Skan if (BB_END (bb) == after) 3660132727Skan BB_END (bb) = to; 366190075Sobrien 366290075Sobrien for (x = from; x != NEXT_INSN (to); x = NEXT_INSN (x)) 3663169699Skan if (!BARRIER_P (x)) 3664169699Skan set_block_for_insn (x, bb); 366590075Sobrien } 366690075Sobrien} 366790075Sobrien 366818334Speter/* Return the line note insn preceding INSN. */ 366918334Speter 367018334Speterstatic rtx 3671132727Skanfind_line_note (rtx insn) 367218334Speter{ 367318334Speter if (no_line_numbers) 367418334Speter return 0; 367518334Speter 367618334Speter for (; insn; insn = PREV_INSN (insn)) 3677169699Skan if (NOTE_P (insn) 3678117404Skan && NOTE_LINE_NUMBER (insn) >= 0) 367918334Speter break; 368018334Speter 368118334Speter return insn; 368218334Speter} 368318334Speter 368418334Speter 3685117404Skan/* Emit insn(s) of given code and pattern 3686117404Skan at a specified place within the doubly-linked list. 368718334Speter 3688117404Skan All of the emit_foo global entry points accept an object 3689117404Skan X which is either an insn list or a PATTERN of a single 3690117404Skan instruction. 369118334Speter 3692117404Skan There are thus a few canonical ways to generate code and 3693117404Skan emit it at a specific place in the instruction stream. For 3694117404Skan example, consider the instruction named SPOT and the fact that 3695117404Skan we would like to emit some instructions before SPOT. We might 3696117404Skan do it like this: 3697117404Skan 3698117404Skan start_sequence (); 3699117404Skan ... emit the new instructions ... 3700117404Skan insns_head = get_insns (); 3701117404Skan end_sequence (); 3702117404Skan 3703117404Skan emit_insn_before (insns_head, SPOT); 3704117404Skan 3705117404Skan It used to be common to generate SEQUENCE rtl instead, but that 3706117404Skan is a relic of the past which no longer occurs. The reason is that 3707117404Skan SEQUENCE rtl results in much fragmented RTL memory since the SEQUENCE 3708117404Skan generated would almost certainly die right after it was created. */ 3709117404Skan 3710117404Skan/* Make X be output before the instruction BEFORE. */ 3711117404Skan 371218334Speterrtx 3713132727Skanemit_insn_before_noloc (rtx x, rtx before) 371418334Speter{ 3715117404Skan rtx last = before; 3716117404Skan rtx insn; 371718334Speter 3718169699Skan gcc_assert (before); 3719117404Skan 3720117404Skan if (x == NULL_RTX) 3721117404Skan return last; 3722117404Skan 3723117404Skan switch (GET_CODE (x)) 372418334Speter { 3725117404Skan case INSN: 3726117404Skan case JUMP_INSN: 3727117404Skan case CALL_INSN: 3728117404Skan case CODE_LABEL: 3729117404Skan case BARRIER: 3730117404Skan case NOTE: 3731117404Skan insn = x; 3732117404Skan while (insn) 373318334Speter { 3734117404Skan rtx next = NEXT_INSN (insn); 373518334Speter add_insn_before (insn, before); 3736117404Skan last = insn; 3737117404Skan insn = next; 373818334Speter } 3739117404Skan break; 3740117404Skan 3741117404Skan#ifdef ENABLE_RTL_CHECKING 3742117404Skan case SEQUENCE: 3743169699Skan gcc_unreachable (); 3744117404Skan break; 3745117404Skan#endif 3746117404Skan 3747117404Skan default: 3748117404Skan last = make_insn_raw (x); 3749117404Skan add_insn_before (last, before); 3750117404Skan break; 375118334Speter } 375218334Speter 3753117404Skan return last; 375418334Speter} 375518334Speter 3756117404Skan/* Make an instruction with body X and code JUMP_INSN 375718334Speter and output it before the instruction BEFORE. */ 375818334Speter 375918334Speterrtx 3760132727Skanemit_jump_insn_before_noloc (rtx x, rtx before) 376118334Speter{ 3762117404Skan rtx insn, last = NULL_RTX; 376318334Speter 3764169699Skan gcc_assert (before); 3765117404Skan 3766117404Skan switch (GET_CODE (x)) 376718334Speter { 3768117404Skan case INSN: 3769117404Skan case JUMP_INSN: 3770117404Skan case CALL_INSN: 3771117404Skan case CODE_LABEL: 3772117404Skan case BARRIER: 3773117404Skan case NOTE: 3774117404Skan insn = x; 3775117404Skan while (insn) 3776117404Skan { 3777117404Skan rtx next = NEXT_INSN (insn); 3778117404Skan add_insn_before (insn, before); 3779117404Skan last = insn; 3780117404Skan insn = next; 3781117404Skan } 3782117404Skan break; 3783117404Skan 3784117404Skan#ifdef ENABLE_RTL_CHECKING 3785117404Skan case SEQUENCE: 3786169699Skan gcc_unreachable (); 3787117404Skan break; 3788117404Skan#endif 3789117404Skan 3790117404Skan default: 3791117404Skan last = make_jump_insn_raw (x); 3792117404Skan add_insn_before (last, before); 3793117404Skan break; 379418334Speter } 379518334Speter 3796117404Skan return last; 379718334Speter} 379818334Speter 3799117404Skan/* Make an instruction with body X and code CALL_INSN 380018334Speter and output it before the instruction BEFORE. */ 380118334Speter 380218334Speterrtx 3803132727Skanemit_call_insn_before_noloc (rtx x, rtx before) 380418334Speter{ 3805117404Skan rtx last = NULL_RTX, insn; 380618334Speter 3807169699Skan gcc_assert (before); 3808117404Skan 3809117404Skan switch (GET_CODE (x)) 381018334Speter { 3811117404Skan case INSN: 3812117404Skan case JUMP_INSN: 3813117404Skan case CALL_INSN: 3814117404Skan case CODE_LABEL: 3815117404Skan case BARRIER: 3816117404Skan case NOTE: 3817117404Skan insn = x; 3818117404Skan while (insn) 3819117404Skan { 3820117404Skan rtx next = NEXT_INSN (insn); 3821117404Skan add_insn_before (insn, before); 3822117404Skan last = insn; 3823117404Skan insn = next; 3824117404Skan } 3825117404Skan break; 3826117404Skan 3827117404Skan#ifdef ENABLE_RTL_CHECKING 3828117404Skan case SEQUENCE: 3829169699Skan gcc_unreachable (); 3830117404Skan break; 3831117404Skan#endif 3832117404Skan 3833117404Skan default: 3834117404Skan last = make_call_insn_raw (x); 3835117404Skan add_insn_before (last, before); 3836117404Skan break; 383718334Speter } 383818334Speter 3839117404Skan return last; 384018334Speter} 384118334Speter 384218334Speter/* Make an insn of code BARRIER 384352284Sobrien and output it before the insn BEFORE. */ 384418334Speter 384518334Speterrtx 3846132727Skanemit_barrier_before (rtx before) 384718334Speter{ 384890075Sobrien rtx insn = rtx_alloc (BARRIER); 384918334Speter 385018334Speter INSN_UID (insn) = cur_insn_uid++; 385118334Speter 385218334Speter add_insn_before (insn, before); 385318334Speter return insn; 385418334Speter} 385518334Speter 385652284Sobrien/* Emit the label LABEL before the insn BEFORE. */ 385752284Sobrien 385852284Sobrienrtx 3859132727Skanemit_label_before (rtx label, rtx before) 386052284Sobrien{ 386152284Sobrien /* This can be called twice for the same label as a result of the 386252284Sobrien confusion that follows a syntax error! So make it harmless. */ 386352284Sobrien if (INSN_UID (label) == 0) 386452284Sobrien { 386552284Sobrien INSN_UID (label) = cur_insn_uid++; 386652284Sobrien add_insn_before (label, before); 386752284Sobrien } 386852284Sobrien 386952284Sobrien return label; 387052284Sobrien} 387152284Sobrien 387218334Speter/* Emit a note of subtype SUBTYPE before the insn BEFORE. */ 387318334Speter 387418334Speterrtx 3875132727Skanemit_note_before (int subtype, rtx before) 387618334Speter{ 387790075Sobrien rtx note = rtx_alloc (NOTE); 387818334Speter INSN_UID (note) = cur_insn_uid++; 3879169699Skan#ifndef USE_MAPPED_LOCATION 388018334Speter NOTE_SOURCE_FILE (note) = 0; 3881169699Skan#endif 388218334Speter NOTE_LINE_NUMBER (note) = subtype; 3883117404Skan BLOCK_FOR_INSN (note) = NULL; 388418334Speter 388518334Speter add_insn_before (note, before); 388618334Speter return note; 388718334Speter} 388818334Speter 3889117404Skan/* Helper for emit_insn_after, handles lists of instructions 3890117404Skan efficiently. */ 389118334Speter 3892132727Skanstatic rtx emit_insn_after_1 (rtx, rtx); 3893117404Skan 3894117404Skanstatic rtx 3895132727Skanemit_insn_after_1 (rtx first, rtx after) 389618334Speter{ 3897117404Skan rtx last; 3898117404Skan rtx after_after; 3899117404Skan basic_block bb; 390018334Speter 3901169699Skan if (!BARRIER_P (after) 3902117404Skan && (bb = BLOCK_FOR_INSN (after))) 390318334Speter { 3904117404Skan bb->flags |= BB_DIRTY; 3905117404Skan for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) 3906169699Skan if (!BARRIER_P (last)) 3907117404Skan set_block_for_insn (last, bb); 3908169699Skan if (!BARRIER_P (last)) 3909117404Skan set_block_for_insn (last, bb); 3910132727Skan if (BB_END (bb) == after) 3911132727Skan BB_END (bb) = last; 391218334Speter } 391318334Speter else 3914117404Skan for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) 3915117404Skan continue; 3916117404Skan 3917117404Skan after_after = NEXT_INSN (after); 3918117404Skan 3919117404Skan NEXT_INSN (after) = first; 3920117404Skan PREV_INSN (first) = after; 3921117404Skan NEXT_INSN (last) = after_after; 3922117404Skan if (after_after) 3923117404Skan PREV_INSN (after_after) = last; 3924117404Skan 3925117404Skan if (after == last_insn) 3926117404Skan last_insn = last; 3927117404Skan return last; 3928117404Skan} 3929117404Skan 3930117404Skan/* Make X be output after the insn AFTER. */ 3931117404Skan 3932117404Skanrtx 3933132727Skanemit_insn_after_noloc (rtx x, rtx after) 3934117404Skan{ 3935117404Skan rtx last = after; 3936117404Skan 3937169699Skan gcc_assert (after); 3938117404Skan 3939117404Skan if (x == NULL_RTX) 3940117404Skan return last; 3941117404Skan 3942117404Skan switch (GET_CODE (x)) 394318334Speter { 3944117404Skan case INSN: 3945117404Skan case JUMP_INSN: 3946117404Skan case CALL_INSN: 3947117404Skan case CODE_LABEL: 3948117404Skan case BARRIER: 3949117404Skan case NOTE: 3950117404Skan last = emit_insn_after_1 (x, after); 3951117404Skan break; 3952117404Skan 3953117404Skan#ifdef ENABLE_RTL_CHECKING 3954117404Skan case SEQUENCE: 3955169699Skan gcc_unreachable (); 3956117404Skan break; 3957117404Skan#endif 3958117404Skan 3959117404Skan default: 3960117404Skan last = make_insn_raw (x); 3961117404Skan add_insn_after (last, after); 3962117404Skan break; 396318334Speter } 396418334Speter 3965117404Skan return last; 396618334Speter} 396718334Speter 396818334Speter/* Similar to emit_insn_after, except that line notes are to be inserted so 396918334Speter as to act as if this insn were at FROM. */ 397018334Speter 397118334Spetervoid 3972132727Skanemit_insn_after_with_line_notes (rtx x, rtx after, rtx from) 397318334Speter{ 397418334Speter rtx from_line = find_line_note (from); 397518334Speter rtx after_line = find_line_note (after); 3976117404Skan rtx insn = emit_insn_after (x, after); 397718334Speter 397818334Speter if (from_line) 3979132727Skan emit_note_copy_after (from_line, after); 398018334Speter 398118334Speter if (after_line) 3982132727Skan emit_note_copy_after (after_line, insn); 398318334Speter} 398418334Speter 3985117404Skan/* Make an insn of code JUMP_INSN with body X 398618334Speter and output it after the insn AFTER. */ 398718334Speter 398818334Speterrtx 3989132727Skanemit_jump_insn_after_noloc (rtx x, rtx after) 399018334Speter{ 3991117404Skan rtx last; 399218334Speter 3993169699Skan gcc_assert (after); 3994117404Skan 3995117404Skan switch (GET_CODE (x)) 399618334Speter { 3997117404Skan case INSN: 3998117404Skan case JUMP_INSN: 3999117404Skan case CALL_INSN: 4000117404Skan case CODE_LABEL: 4001117404Skan case BARRIER: 4002117404Skan case NOTE: 4003117404Skan last = emit_insn_after_1 (x, after); 4004117404Skan break; 4005117404Skan 4006117404Skan#ifdef ENABLE_RTL_CHECKING 4007117404Skan case SEQUENCE: 4008169699Skan gcc_unreachable (); 4009117404Skan break; 4010117404Skan#endif 4011117404Skan 4012117404Skan default: 4013117404Skan last = make_jump_insn_raw (x); 4014117404Skan add_insn_after (last, after); 4015117404Skan break; 401618334Speter } 401718334Speter 4018117404Skan return last; 401918334Speter} 402018334Speter 4021117404Skan/* Make an instruction with body X and code CALL_INSN 4022117404Skan and output it after the instruction AFTER. */ 4023117404Skan 4024117404Skanrtx 4025132727Skanemit_call_insn_after_noloc (rtx x, rtx after) 4026117404Skan{ 4027117404Skan rtx last; 4028117404Skan 4029169699Skan gcc_assert (after); 4030117404Skan 4031117404Skan switch (GET_CODE (x)) 4032117404Skan { 4033117404Skan case INSN: 4034117404Skan case JUMP_INSN: 4035117404Skan case CALL_INSN: 4036117404Skan case CODE_LABEL: 4037117404Skan case BARRIER: 4038117404Skan case NOTE: 4039117404Skan last = emit_insn_after_1 (x, after); 4040117404Skan break; 4041117404Skan 4042117404Skan#ifdef ENABLE_RTL_CHECKING 4043117404Skan case SEQUENCE: 4044169699Skan gcc_unreachable (); 4045117404Skan break; 4046117404Skan#endif 4047117404Skan 4048117404Skan default: 4049117404Skan last = make_call_insn_raw (x); 4050117404Skan add_insn_after (last, after); 4051117404Skan break; 4052117404Skan } 4053117404Skan 4054117404Skan return last; 4055117404Skan} 4056117404Skan 405718334Speter/* Make an insn of code BARRIER 405818334Speter and output it after the insn AFTER. */ 405918334Speter 406018334Speterrtx 4061132727Skanemit_barrier_after (rtx after) 406218334Speter{ 406390075Sobrien rtx insn = rtx_alloc (BARRIER); 406418334Speter 406518334Speter INSN_UID (insn) = cur_insn_uid++; 406618334Speter 406718334Speter add_insn_after (insn, after); 406818334Speter return insn; 406918334Speter} 407018334Speter 407118334Speter/* Emit the label LABEL after the insn AFTER. */ 407218334Speter 407318334Speterrtx 4074132727Skanemit_label_after (rtx label, rtx after) 407518334Speter{ 407618334Speter /* This can be called twice for the same label 407718334Speter as a result of the confusion that follows a syntax error! 407818334Speter So make it harmless. */ 407918334Speter if (INSN_UID (label) == 0) 408018334Speter { 408118334Speter INSN_UID (label) = cur_insn_uid++; 408218334Speter add_insn_after (label, after); 408318334Speter } 408418334Speter 408518334Speter return label; 408618334Speter} 408718334Speter 408818334Speter/* Emit a note of subtype SUBTYPE after the insn AFTER. */ 408918334Speter 409018334Speterrtx 4091132727Skanemit_note_after (int subtype, rtx after) 409218334Speter{ 409390075Sobrien rtx note = rtx_alloc (NOTE); 409418334Speter INSN_UID (note) = cur_insn_uid++; 4095169699Skan#ifndef USE_MAPPED_LOCATION 409618334Speter NOTE_SOURCE_FILE (note) = 0; 4097169699Skan#endif 409818334Speter NOTE_LINE_NUMBER (note) = subtype; 4099117404Skan BLOCK_FOR_INSN (note) = NULL; 410018334Speter add_insn_after (note, after); 410118334Speter return note; 410218334Speter} 410318334Speter 4104132727Skan/* Emit a copy of note ORIG after the insn AFTER. */ 410518334Speter 410618334Speterrtx 4107132727Skanemit_note_copy_after (rtx orig, rtx after) 410818334Speter{ 410990075Sobrien rtx note; 411018334Speter 4111132727Skan if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers) 411218334Speter { 411318334Speter cur_insn_uid++; 411418334Speter return 0; 411518334Speter } 411618334Speter 4117117404Skan note = rtx_alloc (NOTE); 411818334Speter INSN_UID (note) = cur_insn_uid++; 4119132727Skan NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig); 4120132727Skan NOTE_DATA (note) = NOTE_DATA (orig); 4121117404Skan BLOCK_FOR_INSN (note) = NULL; 412218334Speter add_insn_after (note, after); 412318334Speter return note; 412418334Speter} 412518334Speter 4126132727Skan/* Like emit_insn_after_noloc, but set INSN_LOCATOR according to SCOPE. */ 4127117404Skanrtx 4128132727Skanemit_insn_after_setloc (rtx pattern, rtx after, int loc) 4129117404Skan{ 4130132727Skan rtx last = emit_insn_after_noloc (pattern, after); 413118334Speter 4132132727Skan if (pattern == NULL_RTX || !loc) 4133132727Skan return last; 4134132727Skan 4135117404Skan after = NEXT_INSN (after); 4136117404Skan while (1) 4137117404Skan { 4138132727Skan if (active_insn_p (after) && !INSN_LOCATOR (after)) 4139132727Skan INSN_LOCATOR (after) = loc; 4140117404Skan if (after == last) 4141117404Skan break; 4142117404Skan after = NEXT_INSN (after); 4143117404Skan } 4144117404Skan return last; 4145117404Skan} 414618334Speter 4147132727Skan/* Like emit_insn_after_noloc, but set INSN_LOCATOR according to AFTER. */ 414818334Speterrtx 4149132727Skanemit_insn_after (rtx pattern, rtx after) 415018334Speter{ 4151132727Skan if (INSN_P (after)) 4152132727Skan return emit_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); 4153132727Skan else 4154132727Skan return emit_insn_after_noloc (pattern, after); 4155132727Skan} 415618334Speter 4157132727Skan/* Like emit_jump_insn_after_noloc, but set INSN_LOCATOR according to SCOPE. */ 4158132727Skanrtx 4159132727Skanemit_jump_insn_after_setloc (rtx pattern, rtx after, int loc) 4160132727Skan{ 4161132727Skan rtx last = emit_jump_insn_after_noloc (pattern, after); 4162132727Skan 4163132727Skan if (pattern == NULL_RTX || !loc) 4164132727Skan return last; 4165132727Skan 4166117404Skan after = NEXT_INSN (after); 4167117404Skan while (1) 416818334Speter { 4169132727Skan if (active_insn_p (after) && !INSN_LOCATOR (after)) 4170132727Skan INSN_LOCATOR (after) = loc; 4171117404Skan if (after == last) 4172117404Skan break; 4173117404Skan after = NEXT_INSN (after); 417418334Speter } 4175117404Skan return last; 417618334Speter} 417718334Speter 4178132727Skan/* Like emit_jump_insn_after_noloc, but set INSN_LOCATOR according to AFTER. */ 417918334Speterrtx 4180132727Skanemit_jump_insn_after (rtx pattern, rtx after) 418118334Speter{ 4182132727Skan if (INSN_P (after)) 4183132727Skan return emit_jump_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); 4184132727Skan else 4185132727Skan return emit_jump_insn_after_noloc (pattern, after); 4186132727Skan} 418718334Speter 4188132727Skan/* Like emit_call_insn_after_noloc, but set INSN_LOCATOR according to SCOPE. */ 4189132727Skanrtx 4190132727Skanemit_call_insn_after_setloc (rtx pattern, rtx after, int loc) 4191132727Skan{ 4192132727Skan rtx last = emit_call_insn_after_noloc (pattern, after); 4193132727Skan 4194132727Skan if (pattern == NULL_RTX || !loc) 4195132727Skan return last; 4196132727Skan 4197117404Skan after = NEXT_INSN (after); 4198117404Skan while (1) 419918334Speter { 4200132727Skan if (active_insn_p (after) && !INSN_LOCATOR (after)) 4201132727Skan INSN_LOCATOR (after) = loc; 4202117404Skan if (after == last) 4203117404Skan break; 4204117404Skan after = NEXT_INSN (after); 420518334Speter } 420618334Speter return last; 420718334Speter} 420818334Speter 4209132727Skan/* Like emit_call_insn_after_noloc, but set INSN_LOCATOR according to AFTER. */ 421018334Speterrtx 4211132727Skanemit_call_insn_after (rtx pattern, rtx after) 421218334Speter{ 4213132727Skan if (INSN_P (after)) 4214132727Skan return emit_call_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); 4215132727Skan else 4216132727Skan return emit_call_insn_after_noloc (pattern, after); 4217132727Skan} 4218132727Skan 4219132727Skan/* Like emit_insn_before_noloc, but set INSN_LOCATOR according to SCOPE. */ 4220132727Skanrtx 4221132727Skanemit_insn_before_setloc (rtx pattern, rtx before, int loc) 4222132727Skan{ 4223117404Skan rtx first = PREV_INSN (before); 4224132727Skan rtx last = emit_insn_before_noloc (pattern, before); 422518334Speter 4226132727Skan if (pattern == NULL_RTX || !loc) 4227132727Skan return last; 4228132727Skan 4229117404Skan first = NEXT_INSN (first); 4230117404Skan while (1) 423118334Speter { 4232132727Skan if (active_insn_p (first) && !INSN_LOCATOR (first)) 4233132727Skan INSN_LOCATOR (first) = loc; 4234117404Skan if (first == last) 4235117404Skan break; 4236117404Skan first = NEXT_INSN (first); 423718334Speter } 423818334Speter return last; 423918334Speter} 4240132727Skan 4241132727Skan/* Like emit_insn_before_noloc, but set INSN_LOCATOR according to BEFORE. */ 4242132727Skanrtx 4243132727Skanemit_insn_before (rtx pattern, rtx before) 4244132727Skan{ 4245132727Skan if (INSN_P (before)) 4246132727Skan return emit_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); 4247132727Skan else 4248132727Skan return emit_insn_before_noloc (pattern, before); 4249132727Skan} 4250132727Skan 4251132727Skan/* like emit_insn_before_noloc, but set insn_locator according to scope. */ 4252132727Skanrtx 4253132727Skanemit_jump_insn_before_setloc (rtx pattern, rtx before, int loc) 4254132727Skan{ 4255132727Skan rtx first = PREV_INSN (before); 4256132727Skan rtx last = emit_jump_insn_before_noloc (pattern, before); 4257132727Skan 4258132727Skan if (pattern == NULL_RTX) 4259132727Skan return last; 4260132727Skan 4261132727Skan first = NEXT_INSN (first); 4262132727Skan while (1) 4263132727Skan { 4264132727Skan if (active_insn_p (first) && !INSN_LOCATOR (first)) 4265132727Skan INSN_LOCATOR (first) = loc; 4266132727Skan if (first == last) 4267132727Skan break; 4268132727Skan first = NEXT_INSN (first); 4269132727Skan } 4270132727Skan return last; 4271132727Skan} 4272132727Skan 4273132727Skan/* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according to BEFORE. */ 4274132727Skanrtx 4275132727Skanemit_jump_insn_before (rtx pattern, rtx before) 4276132727Skan{ 4277132727Skan if (INSN_P (before)) 4278132727Skan return emit_jump_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); 4279132727Skan else 4280132727Skan return emit_jump_insn_before_noloc (pattern, before); 4281132727Skan} 4282132727Skan 4283132727Skan/* like emit_insn_before_noloc, but set insn_locator according to scope. */ 4284132727Skanrtx 4285132727Skanemit_call_insn_before_setloc (rtx pattern, rtx before, int loc) 4286132727Skan{ 4287132727Skan rtx first = PREV_INSN (before); 4288132727Skan rtx last = emit_call_insn_before_noloc (pattern, before); 4289132727Skan 4290132727Skan if (pattern == NULL_RTX) 4291132727Skan return last; 4292132727Skan 4293132727Skan first = NEXT_INSN (first); 4294132727Skan while (1) 4295132727Skan { 4296132727Skan if (active_insn_p (first) && !INSN_LOCATOR (first)) 4297132727Skan INSN_LOCATOR (first) = loc; 4298132727Skan if (first == last) 4299132727Skan break; 4300132727Skan first = NEXT_INSN (first); 4301132727Skan } 4302132727Skan return last; 4303132727Skan} 4304132727Skan 4305132727Skan/* like emit_call_insn_before_noloc, 4306132727Skan but set insn_locator according to before. */ 4307132727Skanrtx 4308132727Skanemit_call_insn_before (rtx pattern, rtx before) 4309132727Skan{ 4310132727Skan if (INSN_P (before)) 4311132727Skan return emit_call_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); 4312132727Skan else 4313132727Skan return emit_call_insn_before_noloc (pattern, before); 4314132727Skan} 4315117404Skan 4316117404Skan/* Take X and emit it at the end of the doubly-linked 4317117404Skan INSN list. 431818334Speter 4319117404Skan Returns the last insn emitted. */ 432018334Speter 432118334Speterrtx 4322132727Skanemit_insn (rtx x) 432318334Speter{ 4324117404Skan rtx last = last_insn; 4325117404Skan rtx insn; 432618334Speter 4327117404Skan if (x == NULL_RTX) 4328117404Skan return last; 432918334Speter 4330117404Skan switch (GET_CODE (x)) 433190075Sobrien { 4332117404Skan case INSN: 4333117404Skan case JUMP_INSN: 4334117404Skan case CALL_INSN: 4335117404Skan case CODE_LABEL: 4336117404Skan case BARRIER: 4337117404Skan case NOTE: 4338117404Skan insn = x; 4339117404Skan while (insn) 4340117404Skan { 4341117404Skan rtx next = NEXT_INSN (insn); 4342117404Skan add_insn (insn); 4343117404Skan last = insn; 4344117404Skan insn = next; 4345117404Skan } 4346117404Skan break; 434718334Speter 4348117404Skan#ifdef ENABLE_RTL_CHECKING 4349117404Skan case SEQUENCE: 4350169699Skan gcc_unreachable (); 4351117404Skan break; 4352117404Skan#endif 435318334Speter 4354117404Skan default: 4355117404Skan last = make_insn_raw (x); 4356117404Skan add_insn (last); 4357117404Skan break; 4358117404Skan } 435918334Speter 436018334Speter return last; 436118334Speter} 436218334Speter 4363117404Skan/* Make an insn of code JUMP_INSN with pattern X 436418334Speter and add it to the end of the doubly-linked list. */ 436518334Speter 436618334Speterrtx 4367132727Skanemit_jump_insn (rtx x) 436818334Speter{ 4369117404Skan rtx last = NULL_RTX, insn; 4370117404Skan 4371117404Skan switch (GET_CODE (x)) 437218334Speter { 4373117404Skan case INSN: 4374117404Skan case JUMP_INSN: 4375117404Skan case CALL_INSN: 4376117404Skan case CODE_LABEL: 4377117404Skan case BARRIER: 4378117404Skan case NOTE: 4379117404Skan insn = x; 4380117404Skan while (insn) 4381117404Skan { 4382117404Skan rtx next = NEXT_INSN (insn); 4383117404Skan add_insn (insn); 4384117404Skan last = insn; 4385117404Skan insn = next; 4386117404Skan } 4387117404Skan break; 4388117404Skan 4389117404Skan#ifdef ENABLE_RTL_CHECKING 4390117404Skan case SEQUENCE: 4391169699Skan gcc_unreachable (); 4392117404Skan break; 4393117404Skan#endif 4394117404Skan 4395117404Skan default: 4396117404Skan last = make_jump_insn_raw (x); 4397117404Skan add_insn (last); 4398117404Skan break; 439918334Speter } 4400117404Skan 4401117404Skan return last; 440218334Speter} 440318334Speter 4404117404Skan/* Make an insn of code CALL_INSN with pattern X 440518334Speter and add it to the end of the doubly-linked list. */ 440618334Speter 440718334Speterrtx 4408132727Skanemit_call_insn (rtx x) 440918334Speter{ 4410117404Skan rtx insn; 4411117404Skan 4412117404Skan switch (GET_CODE (x)) 441318334Speter { 4414117404Skan case INSN: 4415117404Skan case JUMP_INSN: 4416117404Skan case CALL_INSN: 4417117404Skan case CODE_LABEL: 4418117404Skan case BARRIER: 4419117404Skan case NOTE: 4420117404Skan insn = emit_insn (x); 4421117404Skan break; 4422117404Skan 4423117404Skan#ifdef ENABLE_RTL_CHECKING 4424117404Skan case SEQUENCE: 4425169699Skan gcc_unreachable (); 4426117404Skan break; 4427117404Skan#endif 4428117404Skan 4429117404Skan default: 4430117404Skan insn = make_call_insn_raw (x); 443118334Speter add_insn (insn); 4432117404Skan break; 443318334Speter } 4434117404Skan 4435117404Skan return insn; 443618334Speter} 443718334Speter 443818334Speter/* Add the label LABEL to the end of the doubly-linked list. */ 443918334Speter 444018334Speterrtx 4441132727Skanemit_label (rtx label) 444218334Speter{ 444318334Speter /* This can be called twice for the same label 444418334Speter as a result of the confusion that follows a syntax error! 444518334Speter So make it harmless. */ 444618334Speter if (INSN_UID (label) == 0) 444718334Speter { 444818334Speter INSN_UID (label) = cur_insn_uid++; 444918334Speter add_insn (label); 445018334Speter } 445118334Speter return label; 445218334Speter} 445318334Speter 445418334Speter/* Make an insn of code BARRIER 445518334Speter and add it to the end of the doubly-linked list. */ 445618334Speter 445718334Speterrtx 4458132727Skanemit_barrier (void) 445918334Speter{ 446090075Sobrien rtx barrier = rtx_alloc (BARRIER); 446118334Speter INSN_UID (barrier) = cur_insn_uid++; 446218334Speter add_insn (barrier); 446318334Speter return barrier; 446418334Speter} 446518334Speter 4466132727Skan/* Make line numbering NOTE insn for LOCATION add it to the end 4467132727Skan of the doubly-linked list, but only if line-numbers are desired for 4468132727Skan debugging info and it doesn't match the previous one. */ 446918334Speter 447018334Speterrtx 4471132727Skanemit_line_note (location_t location) 447218334Speter{ 4473132727Skan rtx note; 4474132727Skan 4475169699Skan#ifdef USE_MAPPED_LOCATION 4476169699Skan if (location == last_location) 4477169699Skan return NULL_RTX; 4478169699Skan#else 4479132727Skan if (location.file && last_location.file 4480132727Skan && !strcmp (location.file, last_location.file) 4481132727Skan && location.line == last_location.line) 4482132727Skan return NULL_RTX; 4483169699Skan#endif 4484132727Skan last_location = location; 4485132727Skan 448618334Speter if (no_line_numbers) 4487132727Skan { 4488132727Skan cur_insn_uid++; 4489132727Skan return NULL_RTX; 4490132727Skan } 449118334Speter 4492169699Skan#ifdef USE_MAPPED_LOCATION 4493169699Skan note = emit_note ((int) location); 4494169699Skan#else 4495132727Skan note = emit_note (location.line); 4496132727Skan NOTE_SOURCE_FILE (note) = location.file; 4497169699Skan#endif 4498132727Skan 4499132727Skan return note; 450018334Speter} 450118334Speter 4502132727Skan/* Emit a copy of note ORIG. */ 450318334Speter 450418334Speterrtx 4505132727Skanemit_note_copy (rtx orig) 450618334Speter{ 450790075Sobrien rtx note; 4508132727Skan 4509132727Skan if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers) 451018334Speter { 451118334Speter cur_insn_uid++; 4512132727Skan return NULL_RTX; 451318334Speter } 4514132727Skan 451518334Speter note = rtx_alloc (NOTE); 4516132727Skan 451718334Speter INSN_UID (note) = cur_insn_uid++; 4518132727Skan NOTE_DATA (note) = NOTE_DATA (orig); 4519132727Skan NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig); 4520117404Skan BLOCK_FOR_INSN (note) = NULL; 452118334Speter add_insn (note); 4522132727Skan 452318334Speter return note; 452418334Speter} 452518334Speter 4526132727Skan/* Make an insn of code NOTE or type NOTE_NO 4527132727Skan and add it to the end of the doubly-linked list. */ 452818334Speter 452918334Speterrtx 4530132727Skanemit_note (int note_no) 453118334Speter{ 4532132727Skan rtx note; 4533132727Skan 4534132727Skan note = rtx_alloc (NOTE); 4535132727Skan INSN_UID (note) = cur_insn_uid++; 4536132727Skan NOTE_LINE_NUMBER (note) = note_no; 4537132727Skan memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note))); 4538132727Skan BLOCK_FOR_INSN (note) = NULL; 4539132727Skan add_insn (note); 4540132727Skan return note; 454118334Speter} 454218334Speter 454318334Speter/* Cause next statement to emit a line note even if the line number 4544132727Skan has not changed. */ 454518334Speter 454618334Spetervoid 4547132727Skanforce_next_line_note (void) 454818334Speter{ 4549169699Skan#ifdef USE_MAPPED_LOCATION 4550169699Skan last_location = -1; 4551169699Skan#else 4552132727Skan last_location.line = -1; 4553169699Skan#endif 455418334Speter} 455552284Sobrien 455652284Sobrien/* Place a note of KIND on insn INSN with DATUM as the datum. If a 455790075Sobrien note of this type already exists, remove it first. */ 455852284Sobrien 455990075Sobrienrtx 4560132727Skanset_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) 456152284Sobrien{ 456252284Sobrien rtx note = find_reg_note (insn, kind, NULL_RTX); 456352284Sobrien 456490075Sobrien switch (kind) 456590075Sobrien { 456690075Sobrien case REG_EQUAL: 456790075Sobrien case REG_EQUIV: 456890075Sobrien /* Don't add REG_EQUAL/REG_EQUIV notes if the insn 456990075Sobrien has multiple sets (some callers assume single_set 457090075Sobrien means the insn only has one set, when in fact it 457190075Sobrien means the insn only has one * useful * set). */ 457290075Sobrien if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn)) 457390075Sobrien { 4574169699Skan gcc_assert (!note); 457590075Sobrien return NULL_RTX; 457690075Sobrien } 457752284Sobrien 457890075Sobrien /* Don't add ASM_OPERAND REG_EQUAL/REG_EQUIV notes. 457990075Sobrien It serves no useful purpose and breaks eliminate_regs. */ 458090075Sobrien if (GET_CODE (datum) == ASM_OPERANDS) 458190075Sobrien return NULL_RTX; 458290075Sobrien break; 458390075Sobrien 458490075Sobrien default: 458590075Sobrien break; 458690075Sobrien } 458790075Sobrien 458890075Sobrien if (note) 458990075Sobrien { 459090075Sobrien XEXP (note, 0) = datum; 459190075Sobrien return note; 459290075Sobrien } 459390075Sobrien 4594222207Sbenl REG_NOTES (insn) = gen_rtx_EXPR_LIST ((enum machine_mode) kind, datum, 4595222207Sbenl REG_NOTES (insn)); 459690075Sobrien return REG_NOTES (insn); 459752284Sobrien} 459818334Speter 459918334Speter/* Return an indication of which type of insn should have X as a body. 460018334Speter The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */ 460118334Speter 4602169699Skanstatic enum rtx_code 4603132727Skanclassify_insn (rtx x) 460418334Speter{ 4605169699Skan if (LABEL_P (x)) 460618334Speter return CODE_LABEL; 460718334Speter if (GET_CODE (x) == CALL) 460818334Speter return CALL_INSN; 460918334Speter if (GET_CODE (x) == RETURN) 461018334Speter return JUMP_INSN; 461118334Speter if (GET_CODE (x) == SET) 461218334Speter { 461318334Speter if (SET_DEST (x) == pc_rtx) 461418334Speter return JUMP_INSN; 461518334Speter else if (GET_CODE (SET_SRC (x)) == CALL) 461618334Speter return CALL_INSN; 461718334Speter else 461818334Speter return INSN; 461918334Speter } 462018334Speter if (GET_CODE (x) == PARALLEL) 462118334Speter { 462290075Sobrien int j; 462318334Speter for (j = XVECLEN (x, 0) - 1; j >= 0; j--) 462418334Speter if (GET_CODE (XVECEXP (x, 0, j)) == CALL) 462518334Speter return CALL_INSN; 462618334Speter else if (GET_CODE (XVECEXP (x, 0, j)) == SET 462718334Speter && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx) 462818334Speter return JUMP_INSN; 462918334Speter else if (GET_CODE (XVECEXP (x, 0, j)) == SET 463018334Speter && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) 463118334Speter return CALL_INSN; 463218334Speter } 463318334Speter return INSN; 463418334Speter} 463518334Speter 463618334Speter/* Emit the rtl pattern X as an appropriate kind of insn. 463718334Speter If X is a label, it is simply added into the insn chain. */ 463818334Speter 463918334Speterrtx 4640132727Skanemit (rtx x) 464118334Speter{ 464218334Speter enum rtx_code code = classify_insn (x); 464318334Speter 4644169699Skan switch (code) 464518334Speter { 4646169699Skan case CODE_LABEL: 4647169699Skan return emit_label (x); 4648169699Skan case INSN: 4649169699Skan return emit_insn (x); 4650169699Skan case JUMP_INSN: 4651169699Skan { 4652169699Skan rtx insn = emit_jump_insn (x); 4653169699Skan if (any_uncondjump_p (insn) || GET_CODE (x) == RETURN) 4654169699Skan return emit_barrier (); 4655169699Skan return insn; 4656169699Skan } 4657169699Skan case CALL_INSN: 4658169699Skan return emit_call_insn (x); 4659169699Skan default: 4660169699Skan gcc_unreachable (); 466118334Speter } 466218334Speter} 466318334Speter 4664117404Skan/* Space for free sequence stack entries. */ 4665169699Skanstatic GTY ((deletable)) struct sequence_stack *free_sequence_stack; 4666117404Skan 4667169699Skan/* Begin emitting insns to a sequence. If this sequence will contain 4668169699Skan something that might cause the compiler to pop arguments to function 4669169699Skan calls (because those pops have previously been deferred; see 4670169699Skan INHIBIT_DEFER_POP for more details), use do_pending_stack_adjust 4671169699Skan before calling this function. That will ensure that the deferred 4672169699Skan pops are not accidentally emitted in the middle of this sequence. */ 467318334Speter 467418334Spetervoid 4675132727Skanstart_sequence (void) 467618334Speter{ 467718334Speter struct sequence_stack *tem; 467818334Speter 4679117404Skan if (free_sequence_stack != NULL) 4680117404Skan { 4681117404Skan tem = free_sequence_stack; 4682117404Skan free_sequence_stack = tem->next; 4683117404Skan } 4684117404Skan else 4685132727Skan tem = ggc_alloc (sizeof (struct sequence_stack)); 468618334Speter 468790075Sobrien tem->next = seq_stack; 468818334Speter tem->first = first_insn; 468918334Speter tem->last = last_insn; 469018334Speter 469190075Sobrien seq_stack = tem; 469218334Speter 469318334Speter first_insn = 0; 469418334Speter last_insn = 0; 469518334Speter} 469618334Speter 469752284Sobrien/* Set up the insn chain starting with FIRST as the current sequence, 469852284Sobrien saving the previously current one. See the documentation for 469952284Sobrien start_sequence for more information about how to use this function. */ 470018334Speter 470118334Spetervoid 4702132727Skanpush_to_sequence (rtx first) 470318334Speter{ 470418334Speter rtx last; 470518334Speter 470618334Speter start_sequence (); 470718334Speter 470818334Speter for (last = first; last && NEXT_INSN (last); last = NEXT_INSN (last)); 470918334Speter 471018334Speter first_insn = first; 471118334Speter last_insn = last; 471218334Speter} 471318334Speter 471418334Speter/* Set up the outer-level insn chain 471518334Speter as the current sequence, saving the previously current one. */ 471618334Speter 471718334Spetervoid 4718132727Skanpush_topmost_sequence (void) 471918334Speter{ 472050397Sobrien struct sequence_stack *stack, *top = NULL; 472118334Speter 472218334Speter start_sequence (); 472318334Speter 472490075Sobrien for (stack = seq_stack; stack; stack = stack->next) 472518334Speter top = stack; 472618334Speter 472718334Speter first_insn = top->first; 472818334Speter last_insn = top->last; 472918334Speter} 473018334Speter 473118334Speter/* After emitting to the outer-level insn chain, update the outer-level 473218334Speter insn chain, and restore the previous saved state. */ 473318334Speter 473418334Spetervoid 4735132727Skanpop_topmost_sequence (void) 473618334Speter{ 473750397Sobrien struct sequence_stack *stack, *top = NULL; 473818334Speter 473990075Sobrien for (stack = seq_stack; stack; stack = stack->next) 474018334Speter top = stack; 474118334Speter 474218334Speter top->first = first_insn; 474318334Speter top->last = last_insn; 474418334Speter 474518334Speter end_sequence (); 474618334Speter} 474718334Speter 474818334Speter/* After emitting to a sequence, restore previous saved state. 474918334Speter 475052284Sobrien To get the contents of the sequence just made, you must call 4751117404Skan `get_insns' *before* calling here. 475218334Speter 475352284Sobrien If the compiler might have deferred popping arguments while 475452284Sobrien generating this sequence, and this sequence will not be immediately 475552284Sobrien inserted into the instruction stream, use do_pending_stack_adjust 4756117404Skan before calling get_insns. That will ensure that the deferred 475752284Sobrien pops are inserted into this sequence, and not into some random 475852284Sobrien location in the instruction stream. See INHIBIT_DEFER_POP for more 475952284Sobrien information about deferred popping of arguments. */ 476052284Sobrien 476118334Spetervoid 4762132727Skanend_sequence (void) 476318334Speter{ 476490075Sobrien struct sequence_stack *tem = seq_stack; 476518334Speter 476618334Speter first_insn = tem->first; 476718334Speter last_insn = tem->last; 476890075Sobrien seq_stack = tem->next; 476918334Speter 4770117404Skan memset (tem, 0, sizeof (*tem)); 4771117404Skan tem->next = free_sequence_stack; 4772117404Skan free_sequence_stack = tem; 477318334Speter} 477418334Speter 477518334Speter/* Return 1 if currently emitting into a sequence. */ 477618334Speter 477718334Speterint 4778132727Skanin_sequence_p (void) 477918334Speter{ 478090075Sobrien return seq_stack != 0; 478118334Speter} 478218334Speter 478352284Sobrien/* Put the various virtual registers into REGNO_REG_RTX. */ 478452284Sobrien 4785169699Skanstatic void 4786132727Skaninit_virtual_regs (struct emit_status *es) 478752284Sobrien{ 478890075Sobrien rtx *ptr = es->x_regno_reg_rtx; 478990075Sobrien ptr[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx; 479090075Sobrien ptr[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx; 479190075Sobrien ptr[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx; 479290075Sobrien ptr[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx; 479390075Sobrien ptr[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx; 479452284Sobrien} 479552284Sobrien 479690075Sobrien 479790075Sobrien/* Used by copy_insn_1 to avoid copying SCRATCHes more than once. */ 479890075Sobrienstatic rtx copy_insn_scratch_in[MAX_RECOG_OPERANDS]; 479990075Sobrienstatic rtx copy_insn_scratch_out[MAX_RECOG_OPERANDS]; 480090075Sobrienstatic int copy_insn_n_scratches; 480190075Sobrien 480290075Sobrien/* When an insn is being copied by copy_insn_1, this is nonzero if we have 480390075Sobrien copied an ASM_OPERANDS. 480490075Sobrien In that case, it is the original input-operand vector. */ 480590075Sobrienstatic rtvec orig_asm_operands_vector; 480690075Sobrien 480790075Sobrien/* When an insn is being copied by copy_insn_1, this is nonzero if we have 480890075Sobrien copied an ASM_OPERANDS. 480990075Sobrien In that case, it is the copied input-operand vector. */ 481090075Sobrienstatic rtvec copy_asm_operands_vector; 481190075Sobrien 481290075Sobrien/* Likewise for the constraints vector. */ 481390075Sobrienstatic rtvec orig_asm_constraints_vector; 481490075Sobrienstatic rtvec copy_asm_constraints_vector; 481590075Sobrien 481690075Sobrien/* Recursively create a new copy of an rtx for copy_insn. 481790075Sobrien This function differs from copy_rtx in that it handles SCRATCHes and 481890075Sobrien ASM_OPERANDs properly. 481990075Sobrien Normally, this function is not used directly; use copy_insn as front end. 482090075Sobrien However, you could first copy an insn pattern with copy_insn and then use 482190075Sobrien this function afterwards to properly copy any REG_NOTEs containing 482290075Sobrien SCRATCHes. */ 482390075Sobrien 482490075Sobrienrtx 4825132727Skancopy_insn_1 (rtx orig) 482690075Sobrien{ 482790075Sobrien rtx copy; 482890075Sobrien int i, j; 482990075Sobrien RTX_CODE code; 483090075Sobrien const char *format_ptr; 483190075Sobrien 483290075Sobrien code = GET_CODE (orig); 483390075Sobrien 483490075Sobrien switch (code) 483590075Sobrien { 483690075Sobrien case REG: 483790075Sobrien case CONST_INT: 483890075Sobrien case CONST_DOUBLE: 483996263Sobrien case CONST_VECTOR: 484090075Sobrien case SYMBOL_REF: 484190075Sobrien case CODE_LABEL: 484290075Sobrien case PC: 484390075Sobrien case CC0: 484490075Sobrien return orig; 4845169699Skan case CLOBBER: 4846169699Skan if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER) 4847169699Skan return orig; 4848169699Skan break; 484990075Sobrien 485090075Sobrien case SCRATCH: 485190075Sobrien for (i = 0; i < copy_insn_n_scratches; i++) 485290075Sobrien if (copy_insn_scratch_in[i] == orig) 485390075Sobrien return copy_insn_scratch_out[i]; 485490075Sobrien break; 485590075Sobrien 485690075Sobrien case CONST: 485790075Sobrien /* CONST can be shared if it contains a SYMBOL_REF. If it contains 485890075Sobrien a LABEL_REF, it isn't sharable. */ 485990075Sobrien if (GET_CODE (XEXP (orig, 0)) == PLUS 486090075Sobrien && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF 486190075Sobrien && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT) 486290075Sobrien return orig; 486390075Sobrien break; 486490075Sobrien 486590075Sobrien /* A MEM with a constant address is not sharable. The problem is that 486690075Sobrien the constant address may need to be reloaded. If the mem is shared, 486790075Sobrien then reloading one copy of this mem will cause all copies to appear 486890075Sobrien to have been reloaded. */ 486990075Sobrien 487090075Sobrien default: 487190075Sobrien break; 487290075Sobrien } 487390075Sobrien 4874169699Skan /* Copy the various flags, fields, and other information. We assume 4875169699Skan that all fields need copying, and then clear the fields that should 487690075Sobrien not be copied. That is the sensible default behavior, and forces 487790075Sobrien us to explicitly document why we are *not* copying a flag. */ 4878169699Skan copy = shallow_copy_rtx (orig); 487990075Sobrien 488090075Sobrien /* We do not copy the USED flag, which is used as a mark bit during 488190075Sobrien walks over the RTL. */ 4882117404Skan RTX_FLAG (copy, used) = 0; 488390075Sobrien 488490075Sobrien /* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs. */ 4885169699Skan if (INSN_P (orig)) 488690075Sobrien { 4887117404Skan RTX_FLAG (copy, jump) = 0; 4888117404Skan RTX_FLAG (copy, call) = 0; 4889117404Skan RTX_FLAG (copy, frame_related) = 0; 489090075Sobrien } 489190075Sobrien 489290075Sobrien format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); 489390075Sobrien 489490075Sobrien for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) 4895169699Skan switch (*format_ptr++) 4896169699Skan { 4897169699Skan case 'e': 4898169699Skan if (XEXP (orig, i) != NULL) 4899169699Skan XEXP (copy, i) = copy_insn_1 (XEXP (orig, i)); 4900169699Skan break; 490190075Sobrien 4902169699Skan case 'E': 4903169699Skan case 'V': 4904169699Skan if (XVEC (orig, i) == orig_asm_constraints_vector) 4905169699Skan XVEC (copy, i) = copy_asm_constraints_vector; 4906169699Skan else if (XVEC (orig, i) == orig_asm_operands_vector) 4907169699Skan XVEC (copy, i) = copy_asm_operands_vector; 4908169699Skan else if (XVEC (orig, i) != NULL) 4909169699Skan { 4910169699Skan XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); 4911169699Skan for (j = 0; j < XVECLEN (copy, i); j++) 4912169699Skan XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j)); 4913169699Skan } 4914169699Skan break; 491590075Sobrien 4916169699Skan case 't': 4917169699Skan case 'w': 4918169699Skan case 'i': 4919169699Skan case 's': 4920169699Skan case 'S': 4921169699Skan case 'u': 4922169699Skan case '0': 4923169699Skan /* These are left unchanged. */ 4924169699Skan break; 492590075Sobrien 4926169699Skan default: 4927169699Skan gcc_unreachable (); 4928169699Skan } 492990075Sobrien 493090075Sobrien if (code == SCRATCH) 493190075Sobrien { 493290075Sobrien i = copy_insn_n_scratches++; 4933169699Skan gcc_assert (i < MAX_RECOG_OPERANDS); 493490075Sobrien copy_insn_scratch_in[i] = orig; 493590075Sobrien copy_insn_scratch_out[i] = copy; 493690075Sobrien } 493790075Sobrien else if (code == ASM_OPERANDS) 493890075Sobrien { 493990075Sobrien orig_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (orig); 494090075Sobrien copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy); 494190075Sobrien orig_asm_constraints_vector = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (orig); 494290075Sobrien copy_asm_constraints_vector = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy); 494390075Sobrien } 494490075Sobrien 494590075Sobrien return copy; 494690075Sobrien} 494790075Sobrien 494890075Sobrien/* Create a new copy of an rtx. 494990075Sobrien This function differs from copy_rtx in that it handles SCRATCHes and 495090075Sobrien ASM_OPERANDs properly. 495190075Sobrien INSN doesn't really have to be a full INSN; it could be just the 495290075Sobrien pattern. */ 495390075Sobrienrtx 4954132727Skancopy_insn (rtx insn) 495590075Sobrien{ 495690075Sobrien copy_insn_n_scratches = 0; 495790075Sobrien orig_asm_operands_vector = 0; 495890075Sobrien orig_asm_constraints_vector = 0; 495990075Sobrien copy_asm_operands_vector = 0; 496090075Sobrien copy_asm_constraints_vector = 0; 496190075Sobrien return copy_insn_1 (insn); 496290075Sobrien} 496390075Sobrien 496418334Speter/* Initialize data structures and variables in this file 496518334Speter before generating rtl for each function. */ 496618334Speter 496718334Spetervoid 4968132727Skaninit_emit (void) 496918334Speter{ 497090075Sobrien struct function *f = cfun; 497118334Speter 4972132727Skan f->emit = ggc_alloc (sizeof (struct emit_status)); 497318334Speter first_insn = NULL; 497418334Speter last_insn = NULL; 497518334Speter cur_insn_uid = 1; 497618334Speter reg_rtx_no = LAST_VIRTUAL_REGISTER + 1; 4977169699Skan last_location = UNKNOWN_LOCATION; 497818334Speter first_label_num = label_num; 497990075Sobrien seq_stack = NULL; 498018334Speter 498118334Speter /* Init the tables that describe all the pseudo regs. */ 498218334Speter 498390075Sobrien f->emit->regno_pointer_align_length = LAST_VIRTUAL_REGISTER + 101; 498418334Speter 498590075Sobrien f->emit->regno_pointer_align 4986132727Skan = ggc_alloc_cleared (f->emit->regno_pointer_align_length 4987132727Skan * sizeof (unsigned char)); 498818334Speter 498990075Sobrien regno_reg_rtx 4990132727Skan = ggc_alloc (f->emit->regno_pointer_align_length * sizeof (rtx)); 499150397Sobrien 4992117404Skan /* Put copies of all the hard registers into regno_reg_rtx. */ 4993117404Skan memcpy (regno_reg_rtx, 4994117404Skan static_regno_reg_rtx, 4995117404Skan FIRST_PSEUDO_REGISTER * sizeof (rtx)); 4996117404Skan 499718334Speter /* Put copies of all the virtual register rtx into regno_reg_rtx. */ 499890075Sobrien init_virtual_regs (f->emit); 499918334Speter 500018334Speter /* Indicate that the virtual registers and stack locations are 500118334Speter all pointers. */ 500290075Sobrien REG_POINTER (stack_pointer_rtx) = 1; 500390075Sobrien REG_POINTER (frame_pointer_rtx) = 1; 500490075Sobrien REG_POINTER (hard_frame_pointer_rtx) = 1; 500590075Sobrien REG_POINTER (arg_pointer_rtx) = 1; 500618334Speter 500790075Sobrien REG_POINTER (virtual_incoming_args_rtx) = 1; 500890075Sobrien REG_POINTER (virtual_stack_vars_rtx) = 1; 500990075Sobrien REG_POINTER (virtual_stack_dynamic_rtx) = 1; 501090075Sobrien REG_POINTER (virtual_outgoing_args_rtx) = 1; 501190075Sobrien REG_POINTER (virtual_cfa_rtx) = 1; 501218334Speter 501350397Sobrien#ifdef STACK_BOUNDARY 501490075Sobrien REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY; 501590075Sobrien REGNO_POINTER_ALIGN (FRAME_POINTER_REGNUM) = STACK_BOUNDARY; 501690075Sobrien REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY; 501790075Sobrien REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = STACK_BOUNDARY; 501850397Sobrien 501990075Sobrien REGNO_POINTER_ALIGN (VIRTUAL_INCOMING_ARGS_REGNUM) = STACK_BOUNDARY; 502090075Sobrien REGNO_POINTER_ALIGN (VIRTUAL_STACK_VARS_REGNUM) = STACK_BOUNDARY; 502190075Sobrien REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM) = STACK_BOUNDARY; 502290075Sobrien REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM) = STACK_BOUNDARY; 502390075Sobrien REGNO_POINTER_ALIGN (VIRTUAL_CFA_REGNUM) = BITS_PER_WORD; 502450397Sobrien#endif 502550397Sobrien 502618334Speter#ifdef INIT_EXPANDERS 502718334Speter INIT_EXPANDERS; 502818334Speter#endif 502918334Speter} 503018334Speter 5031169699Skan/* Generate a vector constant for mode MODE and constant value CONSTANT. */ 503296263Sobrien 503396263Sobrienstatic rtx 5034169699Skangen_const_vector (enum machine_mode mode, int constant) 503596263Sobrien{ 503696263Sobrien rtx tem; 503796263Sobrien rtvec v; 503896263Sobrien int units, i; 503996263Sobrien enum machine_mode inner; 504096263Sobrien 504196263Sobrien units = GET_MODE_NUNITS (mode); 504296263Sobrien inner = GET_MODE_INNER (mode); 504396263Sobrien 5044169699Skan gcc_assert (!DECIMAL_FLOAT_MODE_P (inner)); 5045169699Skan 504696263Sobrien v = rtvec_alloc (units); 504796263Sobrien 5048169699Skan /* We need to call this function after we set the scalar const_tiny_rtx 5049169699Skan entries. */ 5050169699Skan gcc_assert (const_tiny_rtx[constant][(int) inner]); 505196263Sobrien 505296263Sobrien for (i = 0; i < units; ++i) 5053169699Skan RTVEC_ELT (v, i) = const_tiny_rtx[constant][(int) inner]; 505496263Sobrien 5055117404Skan tem = gen_rtx_raw_CONST_VECTOR (mode, v); 505696263Sobrien return tem; 505796263Sobrien} 505896263Sobrien 5059117404Skan/* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when 5060169699Skan all elements are zero, and the one vector when all elements are one. */ 5061117404Skanrtx 5062132727Skangen_rtx_CONST_VECTOR (enum machine_mode mode, rtvec v) 5063117404Skan{ 5064169699Skan enum machine_mode inner = GET_MODE_INNER (mode); 5065169699Skan int nunits = GET_MODE_NUNITS (mode); 5066169699Skan rtx x; 5067117404Skan int i; 5068117404Skan 5069169699Skan /* Check to see if all of the elements have the same value. */ 5070169699Skan x = RTVEC_ELT (v, nunits - 1); 5071169699Skan for (i = nunits - 2; i >= 0; i--) 5072169699Skan if (RTVEC_ELT (v, i) != x) 5073169699Skan break; 5074169699Skan 5075169699Skan /* If the values are all the same, check to see if we can use one of the 5076169699Skan standard constant vectors. */ 5077169699Skan if (i == -1) 5078169699Skan { 5079169699Skan if (x == CONST0_RTX (inner)) 5080169699Skan return CONST0_RTX (mode); 5081169699Skan else if (x == CONST1_RTX (inner)) 5082169699Skan return CONST1_RTX (mode); 5083169699Skan } 5084169699Skan 5085169699Skan return gen_rtx_raw_CONST_VECTOR (mode, v); 5086117404Skan} 5087117404Skan 508818334Speter/* Create some permanent unique rtl objects shared between all functions. 508918334Speter LINE_NUMBERS is nonzero if line numbers are to be generated. */ 509018334Speter 509118334Spetervoid 5092132727Skaninit_emit_once (int line_numbers) 509318334Speter{ 509418334Speter int i; 509518334Speter enum machine_mode mode; 509650397Sobrien enum machine_mode double_mode; 509718334Speter 5098132727Skan /* We need reg_raw_mode, so initialize the modes now. */ 5099132727Skan init_reg_modes_once (); 5100132727Skan 5101117404Skan /* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash 5102117404Skan tables. */ 5103132727Skan const_int_htab = htab_create_ggc (37, const_int_htab_hash, 5104132727Skan const_int_htab_eq, NULL); 510590075Sobrien 5106132727Skan const_double_htab = htab_create_ggc (37, const_double_htab_hash, 5107132727Skan const_double_htab_eq, NULL); 5108117404Skan 5109132727Skan mem_attrs_htab = htab_create_ggc (37, mem_attrs_htab_hash, 5110132727Skan mem_attrs_htab_eq, NULL); 5111132727Skan reg_attrs_htab = htab_create_ggc (37, reg_attrs_htab_hash, 5112132727Skan reg_attrs_htab_eq, NULL); 511390075Sobrien 511418334Speter no_line_numbers = ! line_numbers; 511518334Speter 511618334Speter /* Compute the word and byte modes. */ 511718334Speter 511818334Speter byte_mode = VOIDmode; 511918334Speter word_mode = VOIDmode; 512050397Sobrien double_mode = VOIDmode; 512118334Speter 5122169699Skan for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); 5123169699Skan mode != VOIDmode; 512418334Speter mode = GET_MODE_WIDER_MODE (mode)) 512518334Speter { 512618334Speter if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT 512718334Speter && byte_mode == VOIDmode) 512818334Speter byte_mode = mode; 512918334Speter 513018334Speter if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD 513118334Speter && word_mode == VOIDmode) 513218334Speter word_mode = mode; 513318334Speter } 513418334Speter 5135169699Skan for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); 5136169699Skan mode != VOIDmode; 513750397Sobrien mode = GET_MODE_WIDER_MODE (mode)) 513850397Sobrien { 513950397Sobrien if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE 514050397Sobrien && double_mode == VOIDmode) 514150397Sobrien double_mode = mode; 514250397Sobrien } 514350397Sobrien 514418334Speter ptr_mode = mode_for_size (POINTER_SIZE, GET_MODE_CLASS (Pmode), 0); 514518334Speter 514690075Sobrien /* Assign register numbers to the globally defined register rtx. 514790075Sobrien This must be done at runtime because the register number field 514890075Sobrien is in a union and some compilers can't initialize unions. */ 514990075Sobrien 5150169699Skan pc_rtx = gen_rtx_PC (VOIDmode); 5151169699Skan cc0_rtx = gen_rtx_CC0 (VOIDmode); 515290075Sobrien stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM); 515390075Sobrien frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM); 515490075Sobrien if (hard_frame_pointer_rtx == 0) 515590075Sobrien hard_frame_pointer_rtx = gen_raw_REG (Pmode, 515690075Sobrien HARD_FRAME_POINTER_REGNUM); 515790075Sobrien if (arg_pointer_rtx == 0) 515890075Sobrien arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM); 515990075Sobrien virtual_incoming_args_rtx = 516090075Sobrien gen_raw_REG (Pmode, VIRTUAL_INCOMING_ARGS_REGNUM); 516190075Sobrien virtual_stack_vars_rtx = 516290075Sobrien gen_raw_REG (Pmode, VIRTUAL_STACK_VARS_REGNUM); 516390075Sobrien virtual_stack_dynamic_rtx = 516490075Sobrien gen_raw_REG (Pmode, VIRTUAL_STACK_DYNAMIC_REGNUM); 516590075Sobrien virtual_outgoing_args_rtx = 516690075Sobrien gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM); 516790075Sobrien virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM); 516890075Sobrien 5169117404Skan /* Initialize RTL for commonly used hard registers. These are 5170117404Skan copied into regno_reg_rtx as we begin to compile each function. */ 5171117404Skan for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 5172117404Skan static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i); 517390075Sobrien 517490075Sobrien#ifdef INIT_EXPANDERS 517590075Sobrien /* This is to initialize {init|mark|free}_machine_status before the first 517690075Sobrien call to push_function_context_to. This is needed by the Chill front 517790075Sobrien end which calls push_function_context_to before the first call to 517890075Sobrien init_function_start. */ 517990075Sobrien INIT_EXPANDERS; 518090075Sobrien#endif 518190075Sobrien 518218334Speter /* Create the unique rtx's for certain rtx codes and operand values. */ 518318334Speter 5184169699Skan /* Don't use gen_rtx_CONST_INT here since gen_rtx_CONST_INT in this case 518590075Sobrien tries to use these variables. */ 518618334Speter for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++) 518790075Sobrien const_int_rtx[i + MAX_SAVED_CONST_INT] = 5188102793Skan gen_rtx_raw_CONST_INT (VOIDmode, (HOST_WIDE_INT) i); 518918334Speter 519050397Sobrien if (STORE_FLAG_VALUE >= - MAX_SAVED_CONST_INT 519150397Sobrien && STORE_FLAG_VALUE <= MAX_SAVED_CONST_INT) 519290075Sobrien const_true_rtx = const_int_rtx[STORE_FLAG_VALUE + MAX_SAVED_CONST_INT]; 519350397Sobrien else 519450397Sobrien const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE); 519518334Speter 5196117404Skan REAL_VALUE_FROM_INT (dconst0, 0, 0, double_mode); 5197117404Skan REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode); 5198117404Skan REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode); 5199132727Skan REAL_VALUE_FROM_INT (dconst3, 3, 0, double_mode); 5200132727Skan REAL_VALUE_FROM_INT (dconst10, 10, 0, double_mode); 5201117404Skan REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode); 5202132727Skan REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode); 520318334Speter 5204132727Skan dconsthalf = dconst1; 5205169699Skan SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1); 5206132727Skan 5207132727Skan real_arithmetic (&dconstthird, RDIV_EXPR, &dconst1, &dconst3); 5208132727Skan 5209132727Skan /* Initialize mathematical constants for constant folding builtins. 5210132727Skan These constants need to be given to at least 160 bits precision. */ 5211132727Skan real_from_string (&dconstpi, 5212132727Skan "3.1415926535897932384626433832795028841971693993751058209749445923078"); 5213132727Skan real_from_string (&dconste, 5214132727Skan "2.7182818284590452353602874713526624977572470936999595749669676277241"); 5215132727Skan 5216132727Skan for (i = 0; i < (int) ARRAY_SIZE (const_tiny_rtx); i++) 521718334Speter { 5218117404Skan REAL_VALUE_TYPE *r = 5219117404Skan (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2); 5220117404Skan 5221169699Skan for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); 5222169699Skan mode != VOIDmode; 522318334Speter mode = GET_MODE_WIDER_MODE (mode)) 5224117404Skan const_tiny_rtx[i][(int) mode] = 5225117404Skan CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); 522618334Speter 5227169699Skan for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT); 5228169699Skan mode != VOIDmode; 5229169699Skan mode = GET_MODE_WIDER_MODE (mode)) 5230169699Skan const_tiny_rtx[i][(int) mode] = 5231169699Skan CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); 5232169699Skan 523318334Speter const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i); 523418334Speter 5235169699Skan for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); 5236169699Skan mode != VOIDmode; 523718334Speter mode = GET_MODE_WIDER_MODE (mode)) 523818334Speter const_tiny_rtx[i][(int) mode] = GEN_INT (i); 523918334Speter 524018334Speter for (mode = GET_CLASS_NARROWEST_MODE (MODE_PARTIAL_INT); 524118334Speter mode != VOIDmode; 524218334Speter mode = GET_MODE_WIDER_MODE (mode)) 524318334Speter const_tiny_rtx[i][(int) mode] = GEN_INT (i); 524418334Speter } 524518334Speter 524696263Sobrien for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); 524796263Sobrien mode != VOIDmode; 524896263Sobrien mode = GET_MODE_WIDER_MODE (mode)) 5249169699Skan { 5250169699Skan const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0); 5251169699Skan const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1); 5252169699Skan } 525396263Sobrien 525496263Sobrien for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT); 525596263Sobrien mode != VOIDmode; 525696263Sobrien mode = GET_MODE_WIDER_MODE (mode)) 5257169699Skan { 5258169699Skan const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0); 5259169699Skan const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1); 5260169699Skan } 526196263Sobrien 526290075Sobrien for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i) 526390075Sobrien if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC) 526490075Sobrien const_tiny_rtx[0][i] = const0_rtx; 526518334Speter 526690075Sobrien const_tiny_rtx[0][(int) BImode] = const0_rtx; 526790075Sobrien if (STORE_FLAG_VALUE == 1) 526890075Sobrien const_tiny_rtx[1][(int) BImode] = const1_rtx; 526918334Speter 527050397Sobrien#ifdef RETURN_ADDRESS_POINTER_REGNUM 527150397Sobrien return_address_pointer_rtx 527290075Sobrien = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM); 527350397Sobrien#endif 527450397Sobrien 527518334Speter#ifdef STATIC_CHAIN_REGNUM 527650397Sobrien static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); 527718334Speter 527818334Speter#ifdef STATIC_CHAIN_INCOMING_REGNUM 527918334Speter if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM) 528090075Sobrien static_chain_incoming_rtx 528190075Sobrien = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM); 528218334Speter else 528318334Speter#endif 528418334Speter static_chain_incoming_rtx = static_chain_rtx; 528518334Speter#endif 528618334Speter 528718334Speter#ifdef STATIC_CHAIN 528818334Speter static_chain_rtx = STATIC_CHAIN; 528918334Speter 529018334Speter#ifdef STATIC_CHAIN_INCOMING 529118334Speter static_chain_incoming_rtx = STATIC_CHAIN_INCOMING; 529218334Speter#else 529318334Speter static_chain_incoming_rtx = static_chain_rtx; 529418334Speter#endif 529518334Speter#endif 529618334Speter 5297132727Skan if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) 529890075Sobrien pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); 529918334Speter} 530050397Sobrien 5301117404Skan/* Produce exact duplicate of insn INSN after AFTER. 5302117404Skan Care updating of libcall regions if present. */ 5303117404Skan 5304117404Skanrtx 5305132727Skanemit_copy_of_insn_after (rtx insn, rtx after) 5306117404Skan{ 5307117404Skan rtx new; 5308117404Skan rtx note1, note2, link; 5309117404Skan 5310117404Skan switch (GET_CODE (insn)) 5311117404Skan { 5312117404Skan case INSN: 5313117404Skan new = emit_insn_after (copy_insn (PATTERN (insn)), after); 5314117404Skan break; 5315117404Skan 5316117404Skan case JUMP_INSN: 5317117404Skan new = emit_jump_insn_after (copy_insn (PATTERN (insn)), after); 5318117404Skan break; 5319117404Skan 5320117404Skan case CALL_INSN: 5321117404Skan new = emit_call_insn_after (copy_insn (PATTERN (insn)), after); 5322117404Skan if (CALL_INSN_FUNCTION_USAGE (insn)) 5323117404Skan CALL_INSN_FUNCTION_USAGE (new) 5324117404Skan = copy_insn (CALL_INSN_FUNCTION_USAGE (insn)); 5325117404Skan SIBLING_CALL_P (new) = SIBLING_CALL_P (insn); 5326117404Skan CONST_OR_PURE_CALL_P (new) = CONST_OR_PURE_CALL_P (insn); 5327117404Skan break; 5328117404Skan 5329117404Skan default: 5330169699Skan gcc_unreachable (); 5331117404Skan } 5332117404Skan 5333117404Skan /* Update LABEL_NUSES. */ 5334117404Skan mark_jump_label (PATTERN (new), new, 0); 5335117404Skan 5336132727Skan INSN_LOCATOR (new) = INSN_LOCATOR (insn); 5337117404Skan 5338169699Skan /* If the old insn is frame related, then so is the new one. This is 5339169699Skan primarily needed for IA-64 unwind info which marks epilogue insns, 5340169699Skan which may be duplicated by the basic block reordering code. */ 5341169699Skan RTX_FRAME_RELATED_P (new) = RTX_FRAME_RELATED_P (insn); 5342169699Skan 5343117404Skan /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will 5344117404Skan make them. */ 5345117404Skan for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) 5346117404Skan if (REG_NOTE_KIND (link) != REG_LABEL) 5347117404Skan { 5348117404Skan if (GET_CODE (link) == EXPR_LIST) 5349117404Skan REG_NOTES (new) 5350222207Sbenl = copy_insn_1 (gen_rtx_EXPR_LIST (GET_MODE (link), 5351117404Skan XEXP (link, 0), 5352117404Skan REG_NOTES (new))); 5353117404Skan else 5354117404Skan REG_NOTES (new) 5355222207Sbenl = copy_insn_1 (gen_rtx_INSN_LIST (GET_MODE (link), 5356117404Skan XEXP (link, 0), 5357117404Skan REG_NOTES (new))); 5358117404Skan } 5359117404Skan 5360117404Skan /* Fix the libcall sequences. */ 5361117404Skan if ((note1 = find_reg_note (new, REG_RETVAL, NULL_RTX)) != NULL) 5362117404Skan { 5363117404Skan rtx p = new; 5364117404Skan while ((note2 = find_reg_note (p, REG_LIBCALL, NULL_RTX)) == NULL) 5365117404Skan p = PREV_INSN (p); 5366117404Skan XEXP (note1, 0) = p; 5367117404Skan XEXP (note2, 0) = new; 5368117404Skan } 5369132727Skan INSN_CODE (new) = INSN_CODE (insn); 5370117404Skan return new; 5371117404Skan} 5372117404Skan 5373169699Skanstatic GTY((deletable)) rtx hard_reg_clobbers [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; 5374169699Skanrtx 5375169699Skangen_hard_reg_clobber (enum machine_mode mode, unsigned int regno) 5376169699Skan{ 5377169699Skan if (hard_reg_clobbers[mode][regno]) 5378169699Skan return hard_reg_clobbers[mode][regno]; 5379169699Skan else 5380169699Skan return (hard_reg_clobbers[mode][regno] = 5381169699Skan gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno))); 5382169699Skan} 5383169699Skan 5384117404Skan#include "gt-emit-rtl.h" 5385