• Main Page
  • Modules
  • Data Types
  • Files

osprey/kg++fe/gnu/expr.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
00003  */
00004 
00005 /* Convert tree expression to rtl instructions, for GNU compiler.
00006    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00007    2000, 2001, 2002, 2003 Free Software Foundation, Inc.
00008 
00009 This file is part of GCC.
00010 
00011 GCC is free software; you can redistribute it and/or modify it under
00012 the terms of the GNU General Public License as published by the Free
00013 Software Foundation; either version 2, or (at your option) any later
00014 version.
00015 
00016 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
00017 WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019 for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with GCC; see the file COPYING.  If not, write to the Free
00023 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
00024 02111-1307, USA.  */
00025 
00026 #include "config.h"
00027 #include "system.h"
00028 #include "machmode.h"
00029 #include "real.h"
00030 #include "rtl.h"
00031 #include "tree.h"
00032 #include "flags.h"
00033 #include "regs.h"
00034 #include "hard-reg-set.h"
00035 #include "except.h"
00036 #include "function.h"
00037 #include "insn-config.h"
00038 #include "insn-attr.h"
00039 #ifdef SGI_MONGOOSE
00040 // To get HAVE_tablejump
00041 #include "insn-flags.h"
00042 #endif /* SGI_MONGOOSE */
00043 /* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
00044 #include "expr.h"
00045 #include "optabs.h"
00046 #include "libfuncs.h"
00047 #include "recog.h"
00048 #include "reload.h"
00049 #include "output.h"
00050 #include "typeclass.h"
00051 #include "toplev.h"
00052 #include "ggc.h"
00053 #include "langhooks.h"
00054 #include "intl.h"
00055 #include "tm_p.h"
00056 #ifdef SGI_MONGOOSE
00057 // To get FUNCTION_ARG_REG_LITTLE_ENDIAN, etc.
00058 #include "defaults.h"
00059 #endif /* SGI_MONGOOSE */
00060 
00061 /* Decide whether a function's arguments should be processed
00062    from first to last or from last to first.
00063 
00064    They should if the stack and args grow in opposite directions, but
00065    only if we have push insns.  */
00066 
00067 #ifdef PUSH_ROUNDING
00068 
00069 #ifndef PUSH_ARGS_REVERSED
00070 #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
00071 #define PUSH_ARGS_REVERSED  /* If it's last to first.  */
00072 #endif
00073 #endif
00074 
00075 #endif
00076 
00077 #ifndef STACK_PUSH_CODE
00078 #ifdef STACK_GROWS_DOWNWARD
00079 #define STACK_PUSH_CODE PRE_DEC
00080 #else
00081 #define STACK_PUSH_CODE PRE_INC
00082 #endif
00083 #endif
00084 
00085 /* Assume that case vectors are not pc-relative.  */
00086 #ifndef CASE_VECTOR_PC_RELATIVE
00087 #define CASE_VECTOR_PC_RELATIVE 0
00088 #endif
00089 
00090 /* Convert defined/undefined to boolean.  */
00091 #ifdef TARGET_MEM_FUNCTIONS
00092 #undef TARGET_MEM_FUNCTIONS
00093 #define TARGET_MEM_FUNCTIONS 1
00094 #else
00095 #define TARGET_MEM_FUNCTIONS 0
00096 #endif
00097 
00098 
00099 /* If this is nonzero, we do not bother generating VOLATILE
00100    around volatile memory references, and we are willing to
00101    output indirect addresses.  If cse is to follow, we reject
00102    indirect addresses so a useful potential cse is generated;
00103    if it is used only once, instruction combination will produce
00104    the same indirect address eventually.  */
00105 int cse_not_expected;
00106 
00107 /* Chain of pending expressions for PLACEHOLDER_EXPR to replace.  */
00108 static tree placeholder_list = 0;
00109 
00110 /* This structure is used by move_by_pieces to describe the move to
00111    be performed.  */
00112 struct move_by_pieces
00113 {
00114   rtx to;
00115   rtx to_addr;
00116   int autinc_to;
00117   int explicit_inc_to;
00118   rtx from;
00119   rtx from_addr;
00120   int autinc_from;
00121   int explicit_inc_from;
00122   unsigned HOST_WIDE_INT len;
00123   HOST_WIDE_INT offset;
00124   int reverse;
00125 };
00126 
00127 /* This structure is used by store_by_pieces to describe the clear to
00128    be performed.  */
00129 
00130 struct store_by_pieces
00131 {
00132   rtx to;
00133   rtx to_addr;
00134   int autinc_to;
00135   int explicit_inc_to;
00136   unsigned HOST_WIDE_INT len;
00137   HOST_WIDE_INT offset;
00138   rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
00139   PTR constfundata;
00140   int reverse;
00141 };
00142 
00143 static rtx enqueue_insn   PARAMS ((rtx, rtx));
00144 static unsigned HOST_WIDE_INT move_by_pieces_ninsns
00145         PARAMS ((unsigned HOST_WIDE_INT,
00146            unsigned int));
00147 static void move_by_pieces_1  PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
00148            struct move_by_pieces *));
00149 static bool block_move_libcall_safe_for_call_parm PARAMS ((void));
00150 static bool emit_block_move_via_movstr PARAMS ((rtx, rtx, rtx, unsigned));
00151 static rtx emit_block_move_via_libcall PARAMS ((rtx, rtx, rtx));
00152 static tree emit_block_move_libcall_fn PARAMS ((int));
00153 static void emit_block_move_via_loop PARAMS ((rtx, rtx, rtx, unsigned));
00154 static rtx clear_by_pieces_1  PARAMS ((PTR, HOST_WIDE_INT,
00155            enum machine_mode));
00156 static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
00157            unsigned int));
00158 static void store_by_pieces_1 PARAMS ((struct store_by_pieces *,
00159            unsigned int));
00160 static void store_by_pieces_2 PARAMS ((rtx (*) (rtx, ...),
00161            enum machine_mode,
00162            struct store_by_pieces *));
00163 static bool clear_storage_via_clrstr PARAMS ((rtx, rtx, unsigned));
00164 static rtx clear_storage_via_libcall PARAMS ((rtx, rtx));
00165 static tree clear_storage_libcall_fn PARAMS ((int));
00166 static rtx compress_float_constant PARAMS ((rtx, rtx));
00167 static rtx get_subtarget  PARAMS ((rtx));
00168 static int is_zeros_p         PARAMS ((tree));
00169 static int mostly_zeros_p PARAMS ((tree));
00170 static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
00171                HOST_WIDE_INT, enum machine_mode,
00172                tree, tree, int, int));
00173 static void store_constructor PARAMS ((tree, rtx, int, HOST_WIDE_INT));
00174 static rtx store_field    PARAMS ((rtx, HOST_WIDE_INT,
00175            HOST_WIDE_INT, enum machine_mode,
00176            tree, enum machine_mode, int, tree,
00177            int));
00178 static rtx var_rtx    PARAMS ((tree));
00179 static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
00180 static HOST_WIDE_INT highest_pow2_factor_for_type PARAMS ((tree, tree));
00181 static int is_aligning_offset PARAMS ((tree, tree));
00182 static rtx expand_increment PARAMS ((tree, int, int));
00183 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
00184 static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
00185 static void do_compare_and_jump PARAMS ((tree, enum rtx_code, enum rtx_code,
00186            rtx, rtx));
00187 static rtx do_store_flag  PARAMS ((tree, rtx, enum machine_mode, int));
00188 #ifdef PUSH_ROUNDING
00189 static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
00190 #endif
00191 static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
00192 static rtx const_vector_from_tree PARAMS ((tree));
00193 
00194 /* Record for each mode whether we can move a register directly to or
00195    from an object of that mode in memory.  If we can't, we won't try
00196    to use that mode directly when accessing a field of that mode.  */
00197 
00198 static char direct_load[NUM_MACHINE_MODES];
00199 static char direct_store[NUM_MACHINE_MODES];
00200 
00201 /* Record for each mode whether we can float-extend from memory.  */
00202 
00203 static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
00204 
00205 /* If a memory-to-memory move would take MOVE_RATIO or more simple
00206    move-instruction sequences, we will do a movstr or libcall instead.  */
00207 
00208 #ifndef MOVE_RATIO
00209 #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
00210 #define MOVE_RATIO 2
00211 #else
00212 /* If we are optimizing for space (-Os), cut down the default move ratio.  */
00213 #define MOVE_RATIO (optimize_size ? 3 : 15)
00214 #endif
00215 #endif
00216 
00217 /* This macro is used to determine whether move_by_pieces should be called
00218    to perform a structure copy.  */
00219 #ifndef MOVE_BY_PIECES_P
00220 #define MOVE_BY_PIECES_P(SIZE, ALIGN) \
00221   (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
00222 #endif
00223 
00224 /* If a clear memory operation would take CLEAR_RATIO or more simple
00225    move-instruction sequences, we will do a clrstr or libcall instead.  */
00226 
00227 #ifndef CLEAR_RATIO
00228 #if defined (HAVE_clrstrqi) || defined (HAVE_clrstrhi) || defined (HAVE_clrstrsi) || defined (HAVE_clrstrdi) || defined (HAVE_clrstrti)
00229 #define CLEAR_RATIO 2
00230 #else
00231 /* If we are optimizing for space, cut down the default clear ratio.  */
00232 #define CLEAR_RATIO (optimize_size ? 3 : 15)
00233 #endif
00234 #endif
00235 
00236 /* This macro is used to determine whether clear_by_pieces should be
00237    called to clear storage.  */
00238 #ifndef CLEAR_BY_PIECES_P
00239 #define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
00240   (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) CLEAR_RATIO)
00241 #endif
00242 
00243 /* This array records the insn_code of insns to perform block moves.  */
00244 enum insn_code movstr_optab[NUM_MACHINE_MODES];
00245 
00246 /* This array records the insn_code of insns to perform block clears.  */
00247 enum insn_code clrstr_optab[NUM_MACHINE_MODES];
00248 
00249 /* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow.  */
00250 
00251 #ifndef SLOW_UNALIGNED_ACCESS
00252 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
00253 #endif
00254 
00255 /* This is run once per compilation to set up which modes can be used
00256    directly in memory and to initialize the block move optab.  */
00257 
00258 void
00259 init_expr_once ()
00260 {
00261   rtx insn, pat;
00262   enum machine_mode mode;
00263   int num_clobbers;
00264   rtx mem, mem1;
00265   rtx reg;
00266 
00267   /* Try indexing by frame ptr and try by stack ptr.
00268      It is known that on the Convex the stack ptr isn't a valid index.
00269      With luck, one or the other is valid on any machine.  */
00270   mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
00271   mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
00272 
00273   /* A scratch register we can modify in-place below to avoid
00274      useless RTL allocations.  */
00275   reg = gen_rtx_REG (VOIDmode, -1);
00276 
00277   insn = rtx_alloc (INSN);
00278   pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
00279   PATTERN (insn) = pat;
00280 
00281   for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
00282        mode = (enum machine_mode) ((int) mode + 1))
00283     {
00284       int regno;
00285 
00286       direct_load[(int) mode] = direct_store[(int) mode] = 0;
00287       PUT_MODE (mem, mode);
00288       PUT_MODE (mem1, mode);
00289       PUT_MODE (reg, mode);
00290 
00291       /* See if there is some register that can be used in this mode and
00292    directly loaded or stored from memory.  */
00293 
00294       if (mode != VOIDmode && mode != BLKmode)
00295   for (regno = 0; regno < FIRST_PSEUDO_REGISTER
00296        && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
00297        regno++)
00298     {
00299       if (! HARD_REGNO_MODE_OK (regno, mode))
00300         continue;
00301 
00302       REGNO (reg) = regno;
00303 
00304       SET_SRC (pat) = mem;
00305       SET_DEST (pat) = reg;
00306       if (recog (pat, insn, &num_clobbers) >= 0)
00307         direct_load[(int) mode] = 1;
00308 
00309       SET_SRC (pat) = mem1;
00310       SET_DEST (pat) = reg;
00311       if (recog (pat, insn, &num_clobbers) >= 0)
00312         direct_load[(int) mode] = 1;
00313 
00314       SET_SRC (pat) = reg;
00315       SET_DEST (pat) = mem;
00316       if (recog (pat, insn, &num_clobbers) >= 0)
00317         direct_store[(int) mode] = 1;
00318 
00319       SET_SRC (pat) = reg;
00320       SET_DEST (pat) = mem1;
00321       if (recog (pat, insn, &num_clobbers) >= 0)
00322         direct_store[(int) mode] = 1;
00323     }
00324     }
00325 
00326   mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
00327 
00328   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
00329        mode = GET_MODE_WIDER_MODE (mode))
00330     {
00331       enum machine_mode srcmode;
00332       for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
00333      srcmode = GET_MODE_WIDER_MODE (srcmode))
00334   {
00335     enum insn_code ic;
00336 
00337     ic = can_extend_p (mode, srcmode, 0);
00338     if (ic == CODE_FOR_nothing)
00339       continue;
00340 
00341     PUT_MODE (mem, srcmode);
00342 
00343     if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
00344       float_extend_from_mem[mode][srcmode] = true;
00345   }
00346     }
00347 }
00348 
00349 /* This is run at the start of compiling a function.  */
00350 
00351 void
00352 init_expr ()
00353 {
00354   cfun->expr = (struct expr_status *) ggc_alloc (sizeof (struct expr_status));
00355 
00356   pending_chain = 0;
00357   pending_stack_adjust = 0;
00358   stack_pointer_delta = 0;
00359   inhibit_defer_pop = 0;
00360   saveregs_value = 0;
00361   apply_args_value = 0;
00362   forced_labels = 0;
00363 }
00364 
00365 /* Small sanity check that the queue is empty at the end of a function.  */
00366 
00367 void
00368 finish_expr_for_function ()
00369 {
00370   if (pending_chain)
00371     abort ();
00372 }
00373 
00374 /* Manage the queue of increment instructions to be output
00375    for POSTINCREMENT_EXPR expressions, etc.  */
00376 
00377 /* Queue up to increment (or change) VAR later.  BODY says how:
00378    BODY should be the same thing you would pass to emit_insn
00379    to increment right away.  It will go to emit_insn later on.
00380 
00381    The value is a QUEUED expression to be used in place of VAR
00382    where you want to guarantee the pre-incrementation value of VAR.  */
00383 
00384 static rtx
00385 enqueue_insn (var, body)
00386      rtx var, body;
00387 {
00388   pending_chain = gen_rtx_QUEUED (GET_MODE (var), var, NULL_RTX, NULL_RTX,
00389           body, pending_chain);
00390   return pending_chain;
00391 }
00392 
00393 /* Use protect_from_queue to convert a QUEUED expression
00394    into something that you can put immediately into an instruction.
00395    If the queued incrementation has not happened yet,
00396    protect_from_queue returns the variable itself.
00397    If the incrementation has happened, protect_from_queue returns a temp
00398    that contains a copy of the old value of the variable.
00399 
00400    Any time an rtx which might possibly be a QUEUED is to be put
00401    into an instruction, it must be passed through protect_from_queue first.
00402    QUEUED expressions are not meaningful in instructions.
00403 
00404    Do not pass a value through protect_from_queue and then hold
00405    on to it for a while before putting it in an instruction!
00406    If the queue is flushed in between, incorrect code will result.  */
00407 
00408 rtx
00409 protect_from_queue (x, modify)
00410      rtx x;
00411      int modify;
00412 {
00413   RTX_CODE code = GET_CODE (x);
00414 
00415 #if 0  /* A QUEUED can hang around after the queue is forced out.  */
00416   /* Shortcut for most common case.  */
00417   if (pending_chain == 0)
00418     return x;
00419 #endif
00420 
00421   if (code != QUEUED)
00422     {
00423       /* A special hack for read access to (MEM (QUEUED ...)) to facilitate
00424    use of autoincrement.  Make a copy of the contents of the memory
00425    location rather than a copy of the address, but not if the value is
00426    of mode BLKmode.  Don't modify X in place since it might be
00427    shared.  */
00428       if (code == MEM && GET_MODE (x) != BLKmode
00429     && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
00430   {
00431     rtx y = XEXP (x, 0);
00432     rtx new = replace_equiv_address_nv (x, QUEUED_VAR (y));
00433 
00434     if (QUEUED_INSN (y))
00435       {
00436         rtx temp = gen_reg_rtx (GET_MODE (x));
00437 
00438         emit_insn_before (gen_move_insn (temp, new),
00439         QUEUED_INSN (y));
00440         return temp;
00441       }
00442 
00443     /* Copy the address into a pseudo, so that the returned value
00444        remains correct across calls to emit_queue.  */
00445     return replace_equiv_address (new, copy_to_reg (XEXP (new, 0)));
00446   }
00447 
00448       /* Otherwise, recursively protect the subexpressions of all
00449    the kinds of rtx's that can contain a QUEUED.  */
00450       if (code == MEM)
00451   {
00452     rtx tem = protect_from_queue (XEXP (x, 0), 0);
00453     if (tem != XEXP (x, 0))
00454       {
00455         x = copy_rtx (x);
00456         XEXP (x, 0) = tem;
00457       }
00458   }
00459       else if (code == PLUS || code == MULT)
00460   {
00461     rtx new0 = protect_from_queue (XEXP (x, 0), 0);
00462     rtx new1 = protect_from_queue (XEXP (x, 1), 0);
00463     if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
00464       {
00465         x = copy_rtx (x);
00466         XEXP (x, 0) = new0;
00467         XEXP (x, 1) = new1;
00468       }
00469   }
00470       return x;
00471     }
00472   /* If the increment has not happened, use the variable itself.  Copy it
00473      into a new pseudo so that the value remains correct across calls to
00474      emit_queue.  */
00475   if (QUEUED_INSN (x) == 0)
00476     return copy_to_reg (QUEUED_VAR (x));
00477   /* If the increment has happened and a pre-increment copy exists,
00478      use that copy.  */
00479   if (QUEUED_COPY (x) != 0)
00480     return QUEUED_COPY (x);
00481   /* The increment has happened but we haven't set up a pre-increment copy.
00482      Set one up now, and use it.  */
00483   QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
00484   emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
00485         QUEUED_INSN (x));
00486   return QUEUED_COPY (x);
00487 }
00488 
00489 /* Return nonzero if X contains a QUEUED expression:
00490    if it contains anything that will be altered by a queued increment.
00491    We handle only combinations of MEM, PLUS, MINUS and MULT operators
00492    since memory addresses generally contain only those.  */
00493 
00494 int
00495 queued_subexp_p (x)
00496      rtx x;
00497 {
00498   enum rtx_code code = GET_CODE (x);
00499   switch (code)
00500     {
00501     case QUEUED:
00502       return 1;
00503     case MEM:
00504       return queued_subexp_p (XEXP (x, 0));
00505     case MULT:
00506     case PLUS:
00507     case MINUS:
00508       return (queued_subexp_p (XEXP (x, 0))
00509         || queued_subexp_p (XEXP (x, 1)));
00510     default:
00511       return 0;
00512     }
00513 }
00514 
00515 /* Perform all the pending incrementations.  */
00516 
00517 void
00518 emit_queue ()
00519 {
00520   rtx p;
00521   while ((p = pending_chain))
00522     {
00523       rtx body = QUEUED_BODY (p);
00524 
00525       switch (GET_CODE (body))
00526   {
00527   case INSN:
00528   case JUMP_INSN:
00529   case CALL_INSN:
00530   case CODE_LABEL:
00531   case BARRIER:
00532   case NOTE:
00533     QUEUED_INSN (p) = body;
00534     emit_insn (body);
00535     break;
00536 
00537 #ifdef ENABLE_CHECKING
00538   case SEQUENCE:
00539     abort ();
00540     break;
00541 #endif
00542 
00543   default:
00544     QUEUED_INSN (p) = emit_insn (body);
00545     break;
00546   }
00547 
00548       pending_chain = QUEUED_NEXT (p);
00549     }
00550 }
00551 
00552 /* Copy data from FROM to TO, where the machine modes are not the same.
00553    Both modes may be integer, or both may be floating.
00554    UNSIGNEDP should be nonzero if FROM is an unsigned type.
00555    This causes zero-extension instead of sign-extension.  */
00556 
00557 void
00558 convert_move (to, from, unsignedp)
00559      rtx to, from;
00560      int unsignedp;
00561 {
00562   enum machine_mode to_mode = GET_MODE (to);
00563   enum machine_mode from_mode = GET_MODE (from);
00564   int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT;
00565   int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT;
00566   enum insn_code code;
00567   rtx libcall;
00568 
00569   /* rtx code for making an equivalent value.  */
00570   enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
00571             : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
00572 
00573   to = protect_from_queue (to, 1);
00574   from = protect_from_queue (from, 0);
00575 
00576   if (to_real != from_real)
00577     abort ();
00578 
00579   /* If FROM is a SUBREG that indicates that we have already done at least
00580      the required extension, strip it.  We don't handle such SUBREGs as
00581      TO here.  */
00582 
00583   if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
00584       && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from)))
00585     >= GET_MODE_SIZE (to_mode))
00586       && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
00587     from = gen_lowpart (to_mode, from), from_mode = to_mode;
00588 
00589   if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to))
00590     abort ();
00591 
00592   if (to_mode == from_mode
00593       || (from_mode == VOIDmode && CONSTANT_P (from)))
00594     {
00595       emit_move_insn (to, from);
00596       return;
00597     }
00598 
00599   if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
00600     {
00601       if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode))
00602   abort ();
00603 
00604       if (VECTOR_MODE_P (to_mode))
00605   from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0);
00606       else
00607   to = simplify_gen_subreg (from_mode, to, GET_MODE (to), 0);
00608 
00609       emit_move_insn (to, from);
00610       return;
00611     }
00612 
00613   if (to_real != from_real)
00614     abort ();
00615 
00616   if (to_real)
00617     {
00618       rtx value, insns;
00619 
00620       if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode))
00621   {
00622     /* Try converting directly if the insn is supported.  */
00623     if ((code = can_extend_p (to_mode, from_mode, 0))
00624         != CODE_FOR_nothing)
00625       {
00626         emit_unop_insn (code, to, from, UNKNOWN);
00627         return;
00628       }
00629   }
00630 
00631 #ifdef HAVE_trunchfqf2
00632       if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
00633   {
00634     emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN);
00635     return;
00636   }
00637 #endif
00638 #ifdef HAVE_trunctqfqf2
00639       if (HAVE_trunctqfqf2 && from_mode == TQFmode && to_mode == QFmode)
00640   {
00641     emit_unop_insn (CODE_FOR_trunctqfqf2, to, from, UNKNOWN);
00642     return;
00643   }
00644 #endif
00645 #ifdef HAVE_truncsfqf2
00646       if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode)
00647   {
00648     emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN);
00649     return;
00650   }
00651 #endif
00652 #ifdef HAVE_truncdfqf2
00653       if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode)
00654   {
00655     emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN);
00656     return;
00657   }
00658 #endif
00659 #ifdef HAVE_truncxfqf2
00660       if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode)
00661   {
00662     emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN);
00663     return;
00664   }
00665 #endif
00666 #ifdef HAVE_trunctfqf2
00667       if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode)
00668   {
00669     emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN);
00670     return;
00671   }
00672 #endif
00673 
00674 #ifdef HAVE_trunctqfhf2
00675       if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode)
00676   {
00677     emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN);
00678     return;
00679   }
00680 #endif
00681 #ifdef HAVE_truncsfhf2
00682       if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode)
00683   {
00684     emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN);
00685     return;
00686   }
00687 #endif
00688 #ifdef HAVE_truncdfhf2
00689       if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode)
00690   {
00691     emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN);
00692     return;
00693   }
00694 #endif
00695 #ifdef HAVE_truncxfhf2
00696       if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode)
00697   {
00698     emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN);
00699     return;
00700   }
00701 #endif
00702 #ifdef HAVE_trunctfhf2
00703       if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode)
00704   {
00705     emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN);
00706     return;
00707   }
00708 #endif
00709 
00710 #ifdef HAVE_truncsftqf2
00711       if (HAVE_truncsftqf2 && from_mode == SFmode && to_mode == TQFmode)
00712   {
00713     emit_unop_insn (CODE_FOR_truncsftqf2, to, from, UNKNOWN);
00714     return;
00715   }
00716 #endif
00717 #ifdef HAVE_truncdftqf2
00718       if (HAVE_truncdftqf2 && from_mode == DFmode && to_mode == TQFmode)
00719   {
00720     emit_unop_insn (CODE_FOR_truncdftqf2, to, from, UNKNOWN);
00721     return;
00722   }
00723 #endif
00724 #ifdef HAVE_truncxftqf2
00725       if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode)
00726   {
00727     emit_unop_insn (CODE_FOR_truncxftqf2, to, from, UNKNOWN);
00728     return;
00729   }
00730 #endif
00731 #ifdef HAVE_trunctftqf2
00732       if (HAVE_trunctftqf2 && from_mode == TFmode && to_mode == TQFmode)
00733   {
00734     emit_unop_insn (CODE_FOR_trunctftqf2, to, from, UNKNOWN);
00735     return;
00736   }
00737 #endif
00738 
00739 #ifdef HAVE_truncdfsf2
00740       if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode)
00741   {
00742     emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
00743     return;
00744   }
00745 #endif
00746 #ifdef HAVE_truncxfsf2
00747       if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
00748   {
00749     emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN);
00750     return;
00751   }
00752 #endif
00753 #ifdef HAVE_trunctfsf2
00754       if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode)
00755   {
00756     emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN);
00757     return;
00758   }
00759 #endif
00760 #ifdef HAVE_truncxfdf2
00761       if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
00762   {
00763     emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN);
00764     return;
00765   }
00766 #endif
00767 #ifdef HAVE_trunctfdf2
00768       if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode)
00769   {
00770     emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN);
00771     return;
00772   }
00773 #endif
00774 
00775       libcall = (rtx) 0;
00776       switch (from_mode)
00777   {
00778   case SFmode:
00779     switch (to_mode)
00780       {
00781       case DFmode:
00782         libcall = extendsfdf2_libfunc;
00783         break;
00784 
00785       case XFmode:
00786         libcall = extendsfxf2_libfunc;
00787         break;
00788 
00789       case TFmode:
00790         libcall = extendsftf2_libfunc;
00791         break;
00792 
00793       default:
00794         break;
00795       }
00796     break;
00797 
00798   case DFmode:
00799     switch (to_mode)
00800       {
00801       case SFmode:
00802         libcall = truncdfsf2_libfunc;
00803         break;
00804 
00805       case XFmode:
00806         libcall = extenddfxf2_libfunc;
00807         break;
00808 
00809       case TFmode:
00810         libcall = extenddftf2_libfunc;
00811         break;
00812 
00813       default:
00814         break;
00815       }
00816     break;
00817 
00818   case XFmode:
00819     switch (to_mode)
00820       {
00821       case SFmode:
00822         libcall = truncxfsf2_libfunc;
00823         break;
00824 
00825       case DFmode:
00826         libcall = truncxfdf2_libfunc;
00827         break;
00828 
00829       default:
00830         break;
00831       }
00832     break;
00833 
00834   case TFmode:
00835     switch (to_mode)
00836       {
00837       case SFmode:
00838         libcall = trunctfsf2_libfunc;
00839         break;
00840 
00841       case DFmode:
00842         libcall = trunctfdf2_libfunc;
00843         break;
00844 
00845       default:
00846         break;
00847       }
00848     break;
00849 
00850   default:
00851     break;
00852   }
00853 
00854       if (libcall == (rtx) 0)
00855   /* This conversion is not implemented yet.  */
00856   abort ();
00857 
00858       start_sequence ();
00859       value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
00860                1, from, from_mode);
00861       insns = get_insns ();
00862       end_sequence ();
00863       emit_libcall_block (insns, to, value, gen_rtx_FLOAT_TRUNCATE (to_mode,
00864                     from));
00865       return;
00866     }
00867 
00868   /* Now both modes are integers.  */
00869 
00870   /* Handle expanding beyond a word.  */
00871   if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)
00872       && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD)
00873     {
00874       rtx insns;
00875       rtx lowpart;
00876       rtx fill_value;
00877       rtx lowfrom;
00878       int i;
00879       enum machine_mode lowpart_mode;
00880       int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
00881 
00882       /* Try converting directly if the insn is supported.  */
00883       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
00884     != CODE_FOR_nothing)
00885   {
00886     /* If FROM is a SUBREG, put it into a register.  Do this
00887        so that we always generate the same set of insns for
00888        better cse'ing; if an intermediate assignment occurred,
00889        we won't be doing the operation directly on the SUBREG.  */
00890     if (optimize > 0 && GET_CODE (from) == SUBREG)
00891       from = force_reg (from_mode, from);
00892     emit_unop_insn (code, to, from, equiv_code);
00893     return;
00894   }
00895       /* Next, try converting via full word.  */
00896       else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD
00897          && ((code = can_extend_p (to_mode, word_mode, unsignedp))
00898        != CODE_FOR_nothing))
00899   {
00900     if (GET_CODE (to) == REG)
00901       emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
00902     convert_move (gen_lowpart (word_mode, to), from, unsignedp);
00903     emit_unop_insn (code, to,
00904         gen_lowpart (word_mode, to), equiv_code);
00905     return;
00906   }
00907 
00908       /* No special multiword conversion insn; do it by hand.  */
00909       start_sequence ();
00910 
00911       /* Since we will turn this into a no conflict block, we must ensure
00912    that the source does not overlap the target.  */
00913 
00914       if (reg_overlap_mentioned_p (to, from))
00915   from = force_reg (from_mode, from);
00916 
00917       /* Get a copy of FROM widened to a word, if necessary.  */
00918       if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD)
00919   lowpart_mode = word_mode;
00920       else
00921   lowpart_mode = from_mode;
00922 
00923       lowfrom = convert_to_mode (lowpart_mode, from, unsignedp);
00924 
00925       lowpart = gen_lowpart (lowpart_mode, to);
00926       emit_move_insn (lowpart, lowfrom);
00927 
00928       /* Compute the value to put in each remaining word.  */
00929       if (unsignedp)
00930   fill_value = const0_rtx;
00931       else
00932   {
00933 #ifdef HAVE_slt
00934     if (HAVE_slt
00935         && insn_data[(int) CODE_FOR_slt].operand[0].mode == word_mode
00936         && STORE_FLAG_VALUE == -1)
00937       {
00938         emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
00939            lowpart_mode, 0);
00940         fill_value = gen_reg_rtx (word_mode);
00941         emit_insn (gen_slt (fill_value));
00942       }
00943     else
00944 #endif
00945       {
00946         fill_value
00947     = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
00948         size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
00949         NULL_RTX, 0);
00950         fill_value = convert_to_mode (word_mode, fill_value, 1);
00951       }
00952   }
00953 
00954       /* Fill the remaining words.  */
00955       for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
00956   {
00957     int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
00958     rtx subword = operand_subword (to, index, 1, to_mode);
00959 
00960     if (subword == 0)
00961       abort ();
00962 
00963     if (fill_value != subword)
00964       emit_move_insn (subword, fill_value);
00965   }
00966 
00967       insns = get_insns ();
00968       end_sequence ();
00969 
00970       emit_no_conflict_block (insns, to, from, NULL_RTX,
00971             gen_rtx_fmt_e (equiv_code, to_mode, copy_rtx (from)));
00972       return;
00973     }
00974 
00975   /* Truncating multi-word to a word or less.  */
00976   if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD
00977       && GET_MODE_BITSIZE (to_mode) <= BITS_PER_WORD)
00978     {
00979       if (!((GET_CODE (from) == MEM
00980        && ! MEM_VOLATILE_P (from)
00981        && direct_load[(int) to_mode]
00982        && ! mode_dependent_address_p (XEXP (from, 0)))
00983       || GET_CODE (from) == REG
00984       || GET_CODE (from) == SUBREG))
00985   from = force_reg (from_mode, from);
00986       convert_move (to, gen_lowpart (word_mode, from), 0);
00987       return;
00988     }
00989 
00990   /* Handle pointer conversion.  */     /* SPEE 900220.  */
00991   if (to_mode == PQImode)
00992     {
00993       if (from_mode != QImode)
00994   from = convert_to_mode (QImode, from, unsignedp);
00995 
00996 #ifdef HAVE_truncqipqi2
00997       if (HAVE_truncqipqi2)
00998   {
00999     emit_unop_insn (CODE_FOR_truncqipqi2, to, from, UNKNOWN);
01000     return;
01001   }
01002 #endif /* HAVE_truncqipqi2 */
01003       abort ();
01004     }
01005 
01006   if (from_mode == PQImode)
01007     {
01008       if (to_mode != QImode)
01009   {
01010     from = convert_to_mode (QImode, from, unsignedp);
01011     from_mode = QImode;
01012   }
01013       else
01014   {
01015 #ifdef HAVE_extendpqiqi2
01016     if (HAVE_extendpqiqi2)
01017       {
01018         emit_unop_insn (CODE_FOR_extendpqiqi2, to, from, UNKNOWN);
01019         return;
01020       }
01021 #endif /* HAVE_extendpqiqi2 */
01022     abort ();
01023   }
01024     }
01025 
01026   if (to_mode == PSImode)
01027     {
01028       if (from_mode != SImode)
01029   from = convert_to_mode (SImode, from, unsignedp);
01030 
01031 #ifdef HAVE_truncsipsi2
01032       if (HAVE_truncsipsi2)
01033   {
01034     emit_unop_insn (CODE_FOR_truncsipsi2, to, from, UNKNOWN);
01035     return;
01036   }
01037 #endif /* HAVE_truncsipsi2 */
01038       abort ();
01039     }
01040 
01041   if (from_mode == PSImode)
01042     {
01043       if (to_mode != SImode)
01044   {
01045     from = convert_to_mode (SImode, from, unsignedp);
01046     from_mode = SImode;
01047   }
01048       else
01049   {
01050 #ifdef HAVE_extendpsisi2
01051     if (! unsignedp && HAVE_extendpsisi2)
01052       {
01053         emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
01054         return;
01055       }
01056 #endif /* HAVE_extendpsisi2 */
01057 #ifdef HAVE_zero_extendpsisi2
01058     if (unsignedp && HAVE_zero_extendpsisi2)
01059       {
01060         emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN);
01061         return;
01062       }
01063 #endif /* HAVE_zero_extendpsisi2 */
01064     abort ();
01065   }
01066     }
01067 
01068   if (to_mode == PDImode)
01069     {
01070       if (from_mode != DImode)
01071   from = convert_to_mode (DImode, from, unsignedp);
01072 
01073 #ifdef HAVE_truncdipdi2
01074       if (HAVE_truncdipdi2)
01075   {
01076     emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN);
01077     return;
01078   }
01079 #endif /* HAVE_truncdipdi2 */
01080       abort ();
01081     }
01082 
01083   if (from_mode == PDImode)
01084     {
01085       if (to_mode != DImode)
01086   {
01087     from = convert_to_mode (DImode, from, unsignedp);
01088     from_mode = DImode;
01089   }
01090       else
01091   {
01092 #ifdef HAVE_extendpdidi2
01093     if (HAVE_extendpdidi2)
01094       {
01095         emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN);
01096         return;
01097       }
01098 #endif /* HAVE_extendpdidi2 */
01099     abort ();
01100   }
01101     }
01102 
01103   /* Now follow all the conversions between integers
01104      no more than a word long.  */
01105 
01106   /* For truncation, usually we can just refer to FROM in a narrower mode.  */
01107   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
01108       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
01109         GET_MODE_BITSIZE (from_mode)))
01110     {
01111       if (!((GET_CODE (from) == MEM
01112        && ! MEM_VOLATILE_P (from)
01113        && direct_load[(int) to_mode]
01114        && ! mode_dependent_address_p (XEXP (from, 0)))
01115       || GET_CODE (from) == REG
01116       || GET_CODE (from) == SUBREG))
01117   from = force_reg (from_mode, from);
01118       if (GET_CODE (from) == REG && REGNO (from) < FIRST_PSEUDO_REGISTER
01119     && ! HARD_REGNO_MODE_OK (REGNO (from), to_mode))
01120   from = copy_to_reg (from);
01121       emit_move_insn (to, gen_lowpart (to_mode, from));
01122       return;
01123     }
01124 
01125   /* Handle extension.  */
01126   if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
01127     {
01128       /* Convert directly if that works.  */
01129       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
01130     != CODE_FOR_nothing)
01131   {
01132     if (flag_force_mem)
01133       from = force_not_mem (from);
01134 
01135     emit_unop_insn (code, to, from, equiv_code);
01136     return;
01137   }
01138       else
01139   {
01140     enum machine_mode intermediate;
01141     rtx tmp;
01142     tree shift_amount;
01143 
01144     /* Search for a mode to convert via.  */
01145     for (intermediate = from_mode; intermediate != VOIDmode;
01146          intermediate = GET_MODE_WIDER_MODE (intermediate))
01147       if (((can_extend_p (to_mode, intermediate, unsignedp)
01148       != CODE_FOR_nothing)
01149      || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
01150          && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
01151                  GET_MODE_BITSIZE (intermediate))))
01152     && (can_extend_p (intermediate, from_mode, unsignedp)
01153         != CODE_FOR_nothing))
01154         {
01155     convert_move (to, convert_to_mode (intermediate, from,
01156                unsignedp), unsignedp);
01157     return;
01158         }
01159 
01160     /* No suitable intermediate mode.
01161        Generate what we need with shifts.  */
01162     shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
01163               - GET_MODE_BITSIZE (from_mode), 0);
01164     from = gen_lowpart (to_mode, force_reg (from_mode, from));
01165     tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
01166             to, unsignedp);
01167     tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
01168             to, unsignedp);
01169     if (tmp != to)
01170       emit_move_insn (to, tmp);
01171     return;
01172   }
01173     }
01174 
01175   /* Support special truncate insns for certain modes.  */
01176 
01177   if (from_mode == DImode && to_mode == SImode)
01178     {
01179 #ifdef HAVE_truncdisi2
01180       if (HAVE_truncdisi2)
01181   {
01182     emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN);
01183     return;
01184   }
01185 #endif
01186       convert_move (to, force_reg (from_mode, from), unsignedp);
01187       return;
01188     }
01189 
01190   if (from_mode == DImode && to_mode == HImode)
01191     {
01192 #ifdef HAVE_truncdihi2
01193       if (HAVE_truncdihi2)
01194   {
01195     emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN);
01196     return;
01197   }
01198 #endif
01199       convert_move (to, force_reg (from_mode, from), unsignedp);
01200       return;
01201     }
01202 
01203   if (from_mode == DImode && to_mode == QImode)
01204     {
01205 #ifdef HAVE_truncdiqi2
01206       if (HAVE_truncdiqi2)
01207   {
01208     emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN);
01209     return;
01210   }
01211 #endif
01212       convert_move (to, force_reg (from_mode, from), unsignedp);
01213       return;
01214     }
01215 
01216   if (from_mode == SImode && to_mode == HImode)
01217     {
01218 #ifdef HAVE_truncsihi2
01219       if (HAVE_truncsihi2)
01220   {
01221     emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
01222     return;
01223   }
01224 #endif
01225       convert_move (to, force_reg (from_mode, from), unsignedp);
01226       return;
01227     }
01228 
01229   if (from_mode == SImode && to_mode == QImode)
01230     {
01231 #ifdef HAVE_truncsiqi2
01232       if (HAVE_truncsiqi2)
01233   {
01234     emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
01235     return;
01236   }
01237 #endif
01238       convert_move (to, force_reg (from_mode, from), unsignedp);
01239       return;
01240     }
01241 
01242   if (from_mode == HImode && to_mode == QImode)
01243     {
01244 #ifdef HAVE_trunchiqi2
01245       if (HAVE_trunchiqi2)
01246   {
01247     emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
01248     return;
01249   }
01250 #endif
01251       convert_move (to, force_reg (from_mode, from), unsignedp);
01252       return;
01253     }
01254 
01255   if (from_mode == TImode && to_mode == DImode)
01256     {
01257 #ifdef HAVE_trunctidi2
01258       if (HAVE_trunctidi2)
01259   {
01260     emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN);
01261     return;
01262   }
01263 #endif
01264       convert_move (to, force_reg (from_mode, from), unsignedp);
01265       return;
01266     }
01267 
01268   if (from_mode == TImode && to_mode == SImode)
01269     {
01270 #ifdef HAVE_trunctisi2
01271       if (HAVE_trunctisi2)
01272   {
01273     emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN);
01274     return;
01275   }
01276 #endif
01277       convert_move (to, force_reg (from_mode, from), unsignedp);
01278       return;
01279     }
01280 
01281   if (from_mode == TImode && to_mode == HImode)
01282     {
01283 #ifdef HAVE_trunctihi2
01284       if (HAVE_trunctihi2)
01285   {
01286     emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN);
01287     return;
01288   }
01289 #endif
01290       convert_move (to, force_reg (from_mode, from), unsignedp);
01291       return;
01292     }
01293 
01294   if (from_mode == TImode && to_mode == QImode)
01295     {
01296 #ifdef HAVE_trunctiqi2
01297       if (HAVE_trunctiqi2)
01298   {
01299     emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN);
01300     return;
01301   }
01302 #endif
01303       convert_move (to, force_reg (from_mode, from), unsignedp);
01304       return;
01305     }
01306 
01307   /* Handle truncation of volatile memrefs, and so on;
01308      the things that couldn't be truncated directly,
01309      and for which there was no special instruction.  */
01310   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
01311     {
01312       rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
01313       emit_move_insn (to, temp);
01314       return;
01315     }
01316 
01317   /* Mode combination is not recognized.  */
01318   abort ();
01319 }
01320 
01321 /* Return an rtx for a value that would result
01322    from converting X to mode MODE.
01323    Both X and MODE may be floating, or both integer.
01324    UNSIGNEDP is nonzero if X is an unsigned value.
01325    This can be done by referring to a part of X in place
01326    or by copying to a new temporary with conversion.
01327 
01328    This function *must not* call protect_from_queue
01329    except when putting X into an insn (in which case convert_move does it).  */
01330 
01331 rtx
01332 convert_to_mode (mode, x, unsignedp)
01333      enum machine_mode mode;
01334      rtx x;
01335      int unsignedp;
01336 {
01337   return convert_modes (mode, VOIDmode, x, unsignedp);
01338 }
01339 
01340 /* Return an rtx for a value that would result
01341    from converting X from mode OLDMODE to mode MODE.
01342    Both modes may be floating, or both integer.
01343    UNSIGNEDP is nonzero if X is an unsigned value.
01344 
01345    This can be done by referring to a part of X in place
01346    or by copying to a new temporary with conversion.
01347 
01348    You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode.
01349 
01350    This function *must not* call protect_from_queue
01351    except when putting X into an insn (in which case convert_move does it).  */
01352 
01353 rtx
01354 convert_modes (mode, oldmode, x, unsignedp)
01355      enum machine_mode mode, oldmode;
01356      rtx x;
01357      int unsignedp;
01358 {
01359   rtx temp;
01360 
01361   /* If FROM is a SUBREG that indicates that we have already done at least
01362      the required extension, strip it.  */
01363 
01364   if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
01365       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
01366       && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)
01367     x = gen_lowpart (mode, x);
01368 
01369   if (GET_MODE (x) != VOIDmode)
01370     oldmode = GET_MODE (x);
01371 
01372   if (mode == oldmode)
01373     return x;
01374 
01375   /* There is one case that we must handle specially: If we are converting
01376      a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and
01377      we are to interpret the constant as unsigned, gen_lowpart will do
01378      the wrong if the constant appears negative.  What we want to do is
01379      make the high-order word of the constant zero, not all ones.  */
01380 
01381   if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
01382       && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
01383       && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)
01384     {
01385       HOST_WIDE_INT val = INTVAL (x);
01386 
01387       if (oldmode != VOIDmode
01388     && HOST_BITS_PER_WIDE_INT > GET_MODE_BITSIZE (oldmode))
01389   {
01390     int width = GET_MODE_BITSIZE (oldmode);
01391 
01392     /* We need to zero extend VAL.  */
01393     val &= ((HOST_WIDE_INT) 1 << width) - 1;
01394   }
01395 
01396       return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
01397     }
01398 
01399   /* We can do this with a gen_lowpart if both desired and current modes
01400      are integer, and this is either a constant integer, a register, or a
01401      non-volatile MEM.  Except for the constant case where MODE is no
01402      wider than HOST_BITS_PER_WIDE_INT, we must be narrowing the operand.  */
01403 
01404   if ((GET_CODE (x) == CONST_INT
01405        && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
01406       || (GET_MODE_CLASS (mode) == MODE_INT
01407     && GET_MODE_CLASS (oldmode) == MODE_INT
01408     && (GET_CODE (x) == CONST_DOUBLE
01409         || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode)
01410       && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)
01411            && direct_load[(int) mode])
01412           || (GET_CODE (x) == REG
01413         && (! HARD_REGISTER_P (x)
01414             || HARD_REGNO_MODE_OK (REGNO (x), mode))
01415         && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01416                 GET_MODE_BITSIZE (GET_MODE (x)))))))))
01417     {
01418       /* ?? If we don't know OLDMODE, we have to assume here that
01419    X does not need sign- or zero-extension.   This may not be
01420    the case, but it's the best we can do.  */
01421       if (GET_CODE (x) == CONST_INT && oldmode != VOIDmode
01422     && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode))
01423   {
01424     HOST_WIDE_INT val = INTVAL (x);
01425     int width = GET_MODE_BITSIZE (oldmode);
01426 
01427     /* We must sign or zero-extend in this case.  Start by
01428        zero-extending, then sign extend if we need to.  */
01429     val &= ((HOST_WIDE_INT) 1 << width) - 1;
01430     if (! unsignedp
01431         && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
01432       val |= (HOST_WIDE_INT) (-1) << width;
01433 
01434     return gen_int_mode (val, mode);
01435   }
01436 
01437       return gen_lowpart (mode, x);
01438     }
01439 
01440   /* Converting from integer constant into mode is always equivalent to an
01441      subreg operation.  */
01442   if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode)
01443     {
01444       if (GET_MODE_BITSIZE (mode) != GET_MODE_BITSIZE (oldmode))
01445   abort ();
01446       return simplify_gen_subreg (mode, x, oldmode, 0);
01447     }
01448 
01449   temp = gen_reg_rtx (mode);
01450   convert_move (temp, x, unsignedp);
01451   return temp;
01452 }
01453 
01454 /* This macro is used to determine what the largest unit size that
01455    move_by_pieces can use is.  */
01456 
01457 /* MOVE_MAX_PIECES is the number of bytes at a time which we can
01458    move efficiently, as opposed to  MOVE_MAX which is the maximum
01459    number of bytes we can move with a single instruction.  */
01460 
01461 #ifndef MOVE_MAX_PIECES
01462 #define MOVE_MAX_PIECES   MOVE_MAX
01463 #endif
01464 
01465 /* STORE_MAX_PIECES is the number of bytes at a time that we can
01466    store efficiently.  Due to internal GCC limitations, this is
01467    MOVE_MAX_PIECES limited by the number of bytes GCC can represent
01468    for an immediate constant.  */
01469 
01470 #define STORE_MAX_PIECES  MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
01471 
01472 /* Determine whether the LEN bytes can be moved by using several move
01473    instructions.  Return nonzero if a call to move_by_pieces should
01474    succeed.  */
01475 
01476 int
01477 can_move_by_pieces (len, align)
01478      unsigned HOST_WIDE_INT len;
01479      unsigned int align;
01480 {
01481   return MOVE_BY_PIECES_P (len, align);
01482 }
01483 
01484 /* Generate several move instructions to copy LEN bytes from block FROM to
01485    block TO.  (These are MEM rtx's with BLKmode).  The caller must pass FROM
01486    and TO through protect_from_queue before calling.
01487 
01488    If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is
01489    used to push FROM to the stack.
01490 
01491    ALIGN is maximum alignment we can assume.
01492 
01493    If ENDP is 0 return to, if ENDP is 1 return memory at the end ala
01494    mempcpy, and if ENDP is 2 return memory the end minus one byte ala
01495    stpcpy.  */
01496 
01497 rtx
01498 move_by_pieces (to, from, len, align, endp)
01499      rtx to, from;
01500      unsigned HOST_WIDE_INT len;
01501      unsigned int align;
01502      int endp;
01503 {
01504   struct move_by_pieces data;
01505   rtx to_addr, from_addr = XEXP (from, 0);
01506   unsigned int max_size = MOVE_MAX_PIECES + 1;
01507   enum machine_mode mode = VOIDmode, tmode;
01508   enum insn_code icode;
01509 
01510   data.offset = 0;
01511   data.from_addr = from_addr;
01512   if (to)
01513     {
01514       to_addr = XEXP (to, 0);
01515       data.to = to;
01516       data.autinc_to
01517   = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
01518      || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
01519       data.reverse
01520   = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
01521     }
01522   else
01523     {
01524       to_addr = NULL_RTX;
01525       data.to = NULL_RTX;
01526       data.autinc_to = 1;
01527 #ifdef STACK_GROWS_DOWNWARD
01528       data.reverse = 1;
01529 #else
01530       data.reverse = 0;
01531 #endif
01532     }
01533   data.to_addr = to_addr;
01534   data.from = from;
01535   data.autinc_from
01536     = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
01537        || GET_CODE (from_addr) == POST_INC
01538        || GET_CODE (from_addr) == POST_DEC);
01539 
01540   data.explicit_inc_from = 0;
01541   data.explicit_inc_to = 0;
01542   if (data.reverse) data.offset = len;
01543   data.len = len;
01544 
01545   /* If copying requires more than two move insns,
01546      copy addresses to registers (to make displacements shorter)
01547      and use post-increment if available.  */
01548   if (!(data.autinc_from && data.autinc_to)
01549       && move_by_pieces_ninsns (len, align) > 2)
01550     {
01551       /* Find the mode of the largest move...  */
01552       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01553      tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01554   if (GET_MODE_SIZE (tmode) < max_size)
01555     mode = tmode;
01556 
01557       if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
01558   {
01559     data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
01560     data.autinc_from = 1;
01561     data.explicit_inc_from = -1;
01562   }
01563       if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
01564   {
01565     data.from_addr = copy_addr_to_reg (from_addr);
01566     data.autinc_from = 1;
01567     data.explicit_inc_from = 1;
01568   }
01569       if (!data.autinc_from && CONSTANT_P (from_addr))
01570   data.from_addr = copy_addr_to_reg (from_addr);
01571       if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
01572   {
01573     data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
01574     data.autinc_to = 1;
01575     data.explicit_inc_to = -1;
01576   }
01577       if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
01578   {
01579     data.to_addr = copy_addr_to_reg (to_addr);
01580     data.autinc_to = 1;
01581     data.explicit_inc_to = 1;
01582   }
01583       if (!data.autinc_to && CONSTANT_P (to_addr))
01584   data.to_addr = copy_addr_to_reg (to_addr);
01585     }
01586 
01587   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
01588       || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
01589     align = MOVE_MAX * BITS_PER_UNIT;
01590 
01591   /* First move what we can in the largest integer mode, then go to
01592      successively smaller modes.  */
01593 
01594   while (max_size > 1)
01595     {
01596       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01597      tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01598   if (GET_MODE_SIZE (tmode) < max_size)
01599     mode = tmode;
01600 
01601       if (mode == VOIDmode)
01602   break;
01603 
01604       icode = mov_optab->handlers[(int) mode].insn_code;
01605       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
01606   move_by_pieces_1 (GEN_FCN (icode), mode, &data);
01607 
01608       max_size = GET_MODE_SIZE (mode);
01609     }
01610 
01611   /* The code above should have handled everything.  */
01612   if (data.len > 0)
01613     abort ();
01614 
01615   if (endp)
01616     {
01617       rtx to1;
01618 
01619       if (data.reverse)
01620   abort ();
01621       if (data.autinc_to)
01622   {
01623     if (endp == 2)
01624       {
01625         if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
01626     emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
01627         else
01628     data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
01629                 -1));
01630       }
01631     to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
01632              data.offset);
01633   }
01634       else
01635   {
01636     if (endp == 2)
01637       --data.offset;
01638     to1 = adjust_address (data.to, QImode, data.offset);
01639   }
01640       return to1;
01641     }
01642   else
01643     return data.to;
01644 }
01645 
01646 /* Return number of insns required to move L bytes by pieces.
01647    ALIGN (in bits) is maximum alignment we can assume.  */
01648 
01649 static unsigned HOST_WIDE_INT
01650 move_by_pieces_ninsns (l, align)
01651      unsigned HOST_WIDE_INT l;
01652      unsigned int align;
01653 {
01654   unsigned HOST_WIDE_INT n_insns = 0;
01655   unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1;
01656 
01657   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
01658       || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
01659     align = MOVE_MAX * BITS_PER_UNIT;
01660 
01661   while (max_size > 1)
01662     {
01663       enum machine_mode mode = VOIDmode, tmode;
01664       enum insn_code icode;
01665 
01666       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01667      tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01668   if (GET_MODE_SIZE (tmode) < max_size)
01669     mode = tmode;
01670 
01671       if (mode == VOIDmode)
01672   break;
01673 
01674       icode = mov_optab->handlers[(int) mode].insn_code;
01675       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
01676   n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
01677 
01678       max_size = GET_MODE_SIZE (mode);
01679     }
01680 
01681   if (l)
01682     abort ();
01683   return n_insns;
01684 }
01685 
01686 /* Subroutine of move_by_pieces.  Move as many bytes as appropriate
01687    with move instructions for mode MODE.  GENFUN is the gen_... function
01688    to make a move insn for that mode.  DATA has all the other info.  */
01689 
01690 static void
01691 move_by_pieces_1 (genfun, mode, data)
01692      rtx (*genfun) PARAMS ((rtx, ...));
01693      enum machine_mode mode;
01694      struct move_by_pieces *data;
01695 {
01696   unsigned int size = GET_MODE_SIZE (mode);
01697   rtx to1 = NULL_RTX, from1;
01698 
01699   while (data->len >= size)
01700     {
01701       if (data->reverse)
01702   data->offset -= size;
01703 
01704       if (data->to)
01705   {
01706     if (data->autinc_to)
01707       to1 = adjust_automodify_address (data->to, mode, data->to_addr,
01708                data->offset);
01709     else
01710       to1 = adjust_address (data->to, mode, data->offset);
01711   }
01712 
01713       if (data->autinc_from)
01714   from1 = adjust_automodify_address (data->from, mode, data->from_addr,
01715              data->offset);
01716       else
01717   from1 = adjust_address (data->from, mode, data->offset);
01718 
01719       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
01720   emit_insn (gen_add2_insn (data->to_addr,
01721           GEN_INT (-(HOST_WIDE_INT)size)));
01722       if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
01723   emit_insn (gen_add2_insn (data->from_addr,
01724           GEN_INT (-(HOST_WIDE_INT)size)));
01725 
01726       if (data->to)
01727   emit_insn ((*genfun) (to1, from1));
01728       else
01729   {
01730 #ifdef PUSH_ROUNDING
01731     emit_single_push_insn (mode, from1, NULL);
01732 #else
01733     abort ();
01734 #endif
01735   }
01736 
01737       if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
01738   emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
01739       if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
01740   emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
01741 
01742       if (! data->reverse)
01743   data->offset += size;
01744 
01745       data->len -= size;
01746     }
01747 }
01748 
01749 /* Emit code to move a block Y to a block X.  This may be done with
01750    string-move instructions, with multiple scalar move instructions,
01751    or with a library call.
01752 
01753    Both X and Y must be MEM rtx's (perhaps inside VOLATILE) with mode BLKmode.
01754    SIZE is an rtx that says how long they are.
01755    ALIGN is the maximum alignment we can assume they have.
01756    METHOD describes what kind of copy this is, and what mechanisms may be used.
01757 
01758    Return the address of the new block, if memcpy is called and returns it,
01759    0 otherwise.  */
01760 
01761 rtx
01762 emit_block_move (x, y, size, method)
01763      rtx x, y, size;
01764      enum block_op_methods method;
01765 {
01766   bool may_use_call;
01767   rtx retval = 0;
01768   unsigned int align;
01769 
01770   switch (method)
01771     {
01772     case BLOCK_OP_NORMAL:
01773       may_use_call = true;
01774       break;
01775 
01776     case BLOCK_OP_CALL_PARM:
01777       may_use_call = block_move_libcall_safe_for_call_parm ();
01778 
01779       /* Make inhibit_defer_pop nonzero around the library call
01780    to force it to pop the arguments right away.  */
01781       NO_DEFER_POP;
01782       break;
01783 
01784     case BLOCK_OP_NO_LIBCALL:
01785       may_use_call = false;
01786       break;
01787 
01788     default:
01789       abort ();
01790     }
01791 
01792   align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
01793 
01794   if (GET_MODE (x) != BLKmode)
01795     abort ();
01796   if (GET_MODE (y) != BLKmode)
01797     abort ();
01798 
01799   x = protect_from_queue (x, 1);
01800   y = protect_from_queue (y, 0);
01801   size = protect_from_queue (size, 0);
01802 
01803   if (GET_CODE (x) != MEM)
01804     abort ();
01805   if (GET_CODE (y) != MEM)
01806     abort ();
01807   if (size == 0)
01808     abort ();
01809 
01810   /* Set MEM_SIZE as appropriate for this block copy.  The main place this
01811      can be incorrect is coming from __builtin_memcpy.  */
01812   if (GET_CODE (size) == CONST_INT)
01813     {
01814       x = shallow_copy_rtx (x);
01815       y = shallow_copy_rtx (y);
01816       set_mem_size (x, size);
01817       set_mem_size (y, size);
01818     }
01819 
01820   if (size == const0_rtx)
01821     ;
01822   else if (GET_CODE (size) == CONST_INT
01823      && MOVE_BY_PIECES_P (INTVAL (size), align))
01824     move_by_pieces (x, y, INTVAL (size), align, 0);
01825   else if (emit_block_move_via_movstr (x, y, size, align))
01826     ;
01827   else if (may_use_call)
01828     retval = emit_block_move_via_libcall (x, y, size);
01829   else
01830     emit_block_move_via_loop (x, y, size, align);
01831 
01832   if (method == BLOCK_OP_CALL_PARM)
01833     OK_DEFER_POP;
01834 
01835   return retval;
01836 }
01837 
01838 /* A subroutine of emit_block_move.  Returns true if calling the 
01839    block move libcall will not clobber any parameters which may have
01840    already been placed on the stack.  */
01841 
01842 static bool
01843 block_move_libcall_safe_for_call_parm ()
01844 {
01845   if (PUSH_ARGS)
01846     return true;
01847   else
01848     {
01849       /* Check to see whether memcpy takes all register arguments.  */
01850       static enum {
01851   takes_regs_uninit, takes_regs_no, takes_regs_yes
01852       } takes_regs = takes_regs_uninit;
01853 
01854       switch (takes_regs)
01855   {
01856   case takes_regs_uninit:
01857     {
01858       CUMULATIVE_ARGS args_so_far;
01859       tree fn, arg;
01860 
01861       fn = emit_block_move_libcall_fn (false);
01862       INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0);
01863 
01864       arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
01865       for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
01866         {
01867     enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
01868     rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
01869     if (!tmp || !REG_P (tmp))
01870       goto fail_takes_regs;
01871 #ifdef FUNCTION_ARG_PARTIAL_NREGS
01872     if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode,
01873             NULL_TREE, 1))
01874       goto fail_takes_regs;
01875 #endif
01876     FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
01877         }
01878     }
01879     takes_regs = takes_regs_yes;
01880     /* FALLTHRU */
01881 
01882   case takes_regs_yes:
01883     return true;
01884 
01885   fail_takes_regs:
01886     takes_regs = takes_regs_no;
01887     /* FALLTHRU */
01888   case takes_regs_no:
01889     return false;
01890 
01891   default:
01892     abort ();
01893   }
01894     }
01895 }
01896 
01897 /* A subroutine of emit_block_move.  Expand a movstr pattern; 
01898    return true if successful.  */
01899 
01900 static bool
01901 emit_block_move_via_movstr (x, y, size, align)
01902      rtx x, y, size;
01903      unsigned int align;
01904 {
01905   /* Try the most limited insn first, because there's no point
01906      including more than one in the machine description unless
01907      the more limited one has some advantage.  */
01908 
01909   rtx opalign = GEN_INT (align / BITS_PER_UNIT);
01910   enum machine_mode mode;
01911 
01912   /* Since this is a move insn, we don't care about volatility.  */
01913   volatile_ok = 1;
01914 
01915   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
01916        mode = GET_MODE_WIDER_MODE (mode))
01917     {
01918       enum insn_code code = movstr_optab[(int) mode];
01919       insn_operand_predicate_fn pred;
01920 
01921       if (code != CODE_FOR_nothing
01922     /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
01923        here because if SIZE is less than the mode mask, as it is
01924        returned by the macro, it will definitely be less than the
01925        actual mode mask.  */
01926     && ((GET_CODE (size) == CONST_INT
01927          && ((unsigned HOST_WIDE_INT) INTVAL (size)
01928        <= (GET_MODE_MASK (mode) >> 1)))
01929         || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
01930     && ((pred = insn_data[(int) code].operand[0].predicate) == 0
01931         || (*pred) (x, BLKmode))
01932     && ((pred = insn_data[(int) code].operand[1].predicate) == 0
01933         || (*pred) (y, BLKmode))
01934     && ((pred = insn_data[(int) code].operand[3].predicate) == 0
01935         || (*pred) (opalign, VOIDmode)))
01936   {
01937     rtx op2;
01938     rtx last = get_last_insn ();
01939     rtx pat;
01940 
01941     op2 = convert_to_mode (mode, size, 1);
01942     pred = insn_data[(int) code].operand[2].predicate;
01943     if (pred != 0 && ! (*pred) (op2, mode))
01944       op2 = copy_to_mode_reg (mode, op2);
01945 
01946     /* ??? When called via emit_block_move_for_call, it'd be
01947        nice if there were some way to inform the backend, so
01948        that it doesn't fail the expansion because it thinks
01949        emitting the libcall would be more efficient.  */
01950 
01951     pat = GEN_FCN ((int) code) (x, y, op2, opalign);
01952     if (pat)
01953       {
01954         emit_insn (pat);
01955         volatile_ok = 0;
01956         return true;
01957       }
01958     else
01959       delete_insns_since (last);
01960   }
01961     }
01962 
01963   volatile_ok = 0;
01964   return false;
01965 }
01966 
01967 /* A subroutine of emit_block_move.  Expand a call to memcpy or bcopy.
01968    Return the return value from memcpy, 0 otherwise.  */
01969 
01970 static rtx
01971 emit_block_move_via_libcall (dst, src, size)
01972      rtx dst, src, size;
01973 {
01974   tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree;
01975   enum machine_mode size_mode;
01976   rtx retval;
01977 
01978   /* DST, SRC, or SIZE may have been passed through protect_from_queue.
01979 
01980      It is unsafe to save the value generated by protect_from_queue
01981      and reuse it later.  Consider what happens if emit_queue is
01982      called before the return value from protect_from_queue is used.
01983 
01984      Expansion of the CALL_EXPR below will call emit_queue before
01985      we are finished emitting RTL for argument setup.  So if we are
01986      not careful we could get the wrong value for an argument.
01987 
01988      To avoid this problem we go ahead and emit code to copy X, Y &
01989      SIZE into new pseudos.  We can then place those new pseudos
01990      into an RTL_EXPR and use them later, even after a call to
01991      emit_queue.
01992 
01993      Note this is not strictly needed for library calls since they
01994      do not call emit_queue before loading their arguments.  However,
01995      we may need to have library calls call emit_queue in the future
01996      since failing to do so could cause problems for targets which
01997      define SMALL_REGISTER_CLASSES and pass arguments in registers.  */
01998 
01999   dst = copy_to_mode_reg (Pmode, XEXP (dst, 0));
02000   src = copy_to_mode_reg (Pmode, XEXP (src, 0));
02001 
02002   if (TARGET_MEM_FUNCTIONS)
02003     size_mode = TYPE_MODE (sizetype);
02004   else
02005     size_mode = TYPE_MODE (unsigned_type_node);
02006   size = convert_to_mode (size_mode, size, 1);
02007   size = copy_to_mode_reg (size_mode, size);
02008 
02009   /* It is incorrect to use the libcall calling conventions to call
02010      memcpy in this context.  This could be a user call to memcpy and
02011      the user may wish to examine the return value from memcpy.  For
02012      targets where libcalls and normal calls have different conventions
02013      for returning pointers, we could end up generating incorrect code.
02014 
02015      For convenience, we generate the call to bcopy this way as well.  */
02016 
02017   dst_tree = make_tree (ptr_type_node, dst);
02018   src_tree = make_tree (ptr_type_node, src);
02019   if (TARGET_MEM_FUNCTIONS)
02020     size_tree = make_tree (sizetype, size);
02021   else
02022     size_tree = make_tree (unsigned_type_node, size);
02023 
02024   fn = emit_block_move_libcall_fn (true);
02025   arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
02026   if (TARGET_MEM_FUNCTIONS)
02027     {
02028       arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
02029       arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
02030     }
02031   else
02032     {
02033       arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
02034       arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
02035     }
02036 
02037   /* Now we have to build up the CALL_EXPR itself.  */
02038   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
02039   call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
02040          call_expr, arg_list, NULL_TREE);
02041   TREE_SIDE_EFFECTS (call_expr) = 1;
02042 
02043   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
02044 
02045   /* If we are initializing a readonly value, show the above call
02046      clobbered it.  Otherwise, a load from it may erroneously be
02047      hoisted from a loop.  */
02048   if (RTX_UNCHANGING_P (dst))
02049     emit_insn (gen_rtx_CLOBBER (VOIDmode, dst));
02050 
02051   return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
02052 }
02053 
02054 /* A subroutine of emit_block_move_via_libcall.  Create the tree node
02055    for the function we use for block copies.  The first time FOR_CALL
02056    is true, we call assemble_external.  */
02057 
02058 static GTY(()) tree block_move_fn;
02059 
02060 void
02061 init_block_move_fn (asmspec)
02062      const char *asmspec;
02063 {
02064   if (!block_move_fn)
02065     {
02066       tree args, fn;
02067 
02068       if (TARGET_MEM_FUNCTIONS)
02069   {
02070     fn = get_identifier ("memcpy");
02071     args = build_function_type_list (ptr_type_node, ptr_type_node,
02072              const_ptr_type_node, sizetype,
02073              NULL_TREE);
02074   }
02075       else
02076   {
02077     fn = get_identifier ("bcopy");
02078     args = build_function_type_list (void_type_node, const_ptr_type_node,
02079              ptr_type_node, unsigned_type_node,
02080              NULL_TREE);
02081   }
02082 
02083       fn = build_decl (FUNCTION_DECL, fn, args);
02084       DECL_EXTERNAL (fn) = 1;
02085       TREE_PUBLIC (fn) = 1;
02086       DECL_ARTIFICIAL (fn) = 1;
02087       TREE_NOTHROW (fn) = 1;
02088 
02089       block_move_fn = fn;
02090     }
02091 
02092   if (asmspec)
02093     {
02094       SET_DECL_RTL (block_move_fn, NULL_RTX);
02095       SET_DECL_ASSEMBLER_NAME (block_move_fn, get_identifier (asmspec));
02096     }
02097 }
02098 
02099 static tree
02100 emit_block_move_libcall_fn (for_call)
02101      int for_call;
02102 {
02103   static bool emitted_extern;
02104 
02105   if (!block_move_fn)
02106     init_block_move_fn (NULL);
02107 
02108   if (for_call && !emitted_extern)
02109     {
02110       emitted_extern = true;
02111       make_decl_rtl (block_move_fn, NULL);
02112       assemble_external (block_move_fn);
02113     }
02114 
02115   return block_move_fn;
02116 }
02117 
02118 /* A subroutine of emit_block_move.  Copy the data via an explicit
02119    loop.  This is used only when libcalls are forbidden.  */
02120 /* ??? It'd be nice to copy in hunks larger than QImode.  */
02121 
02122 static void
02123 emit_block_move_via_loop (x, y, size, align)
02124      rtx x, y, size;
02125      unsigned int align ATTRIBUTE_UNUSED;
02126 {
02127   rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
02128   enum machine_mode iter_mode;
02129 
02130   iter_mode = GET_MODE (size);
02131   if (iter_mode == VOIDmode)
02132     iter_mode = word_mode;
02133 
02134   top_label = gen_label_rtx ();
02135   cmp_label = gen_label_rtx ();
02136   iter = gen_reg_rtx (iter_mode);
02137 
02138   emit_move_insn (iter, const0_rtx);
02139 
02140   x_addr = force_operand (XEXP (x, 0), NULL_RTX);
02141   y_addr = force_operand (XEXP (y, 0), NULL_RTX);
02142   do_pending_stack_adjust ();
02143 
02144   emit_note (NULL, NOTE_INSN_LOOP_BEG);
02145 
02146   emit_jump (cmp_label);
02147   emit_label (top_label);
02148 
02149   tmp = convert_modes (Pmode, iter_mode, iter, true);
02150   x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
02151   y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
02152   x = change_address (x, QImode, x_addr);
02153   y = change_address (y, QImode, y_addr);
02154 
02155   emit_move_insn (x, y);
02156 
02157   tmp = expand_simple_binop (iter_mode, PLUS, iter, const1_rtx, iter,
02158            true, OPTAB_LIB_WIDEN);
02159   if (tmp != iter)
02160     emit_move_insn (iter, tmp);
02161 
02162   emit_note (NULL, NOTE_INSN_LOOP_CONT);
02163   emit_label (cmp_label);
02164 
02165   emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
02166          true, top_label);
02167 
02168   emit_note (NULL, NOTE_INSN_LOOP_END);
02169 }
02170 
02171 /* Copy all or part of a value X into registers starting at REGNO.
02172    The number of registers to be filled is NREGS.  */
02173 
02174 void
02175 move_block_to_reg (regno, x, nregs, mode)
02176      int regno;
02177      rtx x;
02178      int nregs;
02179      enum machine_mode mode;
02180 {
02181   int i;
02182 #ifdef HAVE_load_multiple
02183   rtx pat;
02184   rtx last;
02185 #endif
02186 
02187   if (nregs == 0)
02188     return;
02189 
02190   if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
02191     x = validize_mem (force_const_mem (mode, x));
02192 
02193   /* See if the machine can do this with a load multiple insn.  */
02194 #ifdef HAVE_load_multiple
02195   if (HAVE_load_multiple)
02196     {
02197       last = get_last_insn ();
02198       pat = gen_load_multiple (gen_rtx_REG (word_mode, regno), x,
02199              GEN_INT (nregs));
02200       if (pat)
02201   {
02202     emit_insn (pat);
02203     return;
02204   }
02205       else
02206   delete_insns_since (last);
02207     }
02208 #endif
02209 
02210   for (i = 0; i < nregs; i++)
02211     emit_move_insn (gen_rtx_REG (word_mode, regno + i),
02212         operand_subword_force (x, i, mode));
02213 }
02214 
02215 /* Copy all or part of a BLKmode value X out of registers starting at REGNO.
02216    The number of registers to be filled is NREGS.  SIZE indicates the number
02217    of bytes in the object X.  */
02218 
02219 void
02220 move_block_from_reg (regno, x, nregs, size)
02221      int regno;
02222      rtx x;
02223      int nregs;
02224      int size;
02225 {
02226   int i;
02227 #ifdef HAVE_store_multiple
02228   rtx pat;
02229   rtx last;
02230 #endif
02231   enum machine_mode mode;
02232 
02233   if (nregs == 0)
02234     return;
02235 
02236   /* If SIZE is that of a mode no bigger than a word, just use that
02237      mode's store operation.  */
02238   if (size <= UNITS_PER_WORD
02239       && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
02240     {
02241       emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
02242       return;
02243     }
02244 
02245   /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
02246      to the left before storing to memory.  Note that the previous test
02247      doesn't handle all cases (e.g. SIZE == 3).  */
02248   if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
02249     {
02250       rtx tem = operand_subword (x, 0, 1, BLKmode);
02251       rtx shift;
02252 
02253       if (tem == 0)
02254   abort ();
02255 
02256       shift = expand_shift (LSHIFT_EXPR, word_mode,
02257           gen_rtx_REG (word_mode, regno),
02258           build_int_2 ((UNITS_PER_WORD - size)
02259            * BITS_PER_UNIT, 0), NULL_RTX, 0);
02260       emit_move_insn (tem, shift);
02261       return;
02262     }
02263 
02264   /* See if the machine can do this with a store multiple insn.  */
02265 #ifdef HAVE_store_multiple
02266   if (HAVE_store_multiple)
02267     {
02268       last = get_last_insn ();
02269       pat = gen_store_multiple (x, gen_rtx_REG (word_mode, regno),
02270         GEN_INT (nregs));
02271       if (pat)
02272   {
02273     emit_insn (pat);
02274     return;
02275   }
02276       else
02277   delete_insns_since (last);
02278     }
02279 #endif
02280 
02281   for (i = 0; i < nregs; i++)
02282     {
02283       rtx tem = operand_subword (x, i, 1, BLKmode);
02284 
02285       if (tem == 0)
02286   abort ();
02287 
02288       emit_move_insn (tem, gen_rtx_REG (word_mode, regno + i));
02289     }
02290 }
02291 
02292 /* Generate a PARALLEL rtx for a new non-consecutive group of registers from
02293    ORIG, where ORIG is a non-consecutive group of registers represented by
02294    a PARALLEL.  The clone is identical to the original except in that the
02295    original set of registers is replaced by a new set of pseudo registers.
02296    The new set has the same modes as the original set.  */
02297 
02298 rtx
02299 gen_group_rtx (orig)
02300      rtx orig;
02301 {
02302   int i, length;
02303   rtx *tmps;
02304 
02305   if (GET_CODE (orig) != PARALLEL)
02306     abort ();
02307 
02308   length = XVECLEN (orig, 0);
02309   tmps = (rtx *) alloca (sizeof (rtx) * length);
02310 
02311   /* Skip a NULL entry in first slot.  */
02312   i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1;
02313 
02314   if (i)
02315     tmps[0] = 0;
02316 
02317   for (; i < length; i++)
02318     {
02319       enum machine_mode mode = GET_MODE (XEXP (XVECEXP (orig, 0, i), 0));
02320       rtx offset = XEXP (XVECEXP (orig, 0, i), 1);
02321 
02322       tmps[i] = gen_rtx_EXPR_LIST (VOIDmode, gen_reg_rtx (mode), offset);
02323     }
02324 
02325   return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
02326 }
02327 
02328 /* Emit code to move a block SRC to a block DST, where DST is non-consecutive
02329    registers represented by a PARALLEL.  SSIZE represents the total size of
02330    block SRC in bytes, or -1 if not known.  */
02331 /* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatant assumption that
02332    the balance will be in what would be the low-order memory addresses, i.e.
02333    left justified for big endian, right justified for little endian.  This
02334    happens to be true for the targets currently using this support.  If this
02335    ever changes, a new target macro along the lines of FUNCTION_ARG_PADDING
02336    would be needed.  */
02337 
02338 void
02339 emit_group_load (dst, orig_src, ssize)
02340      rtx dst, orig_src;
02341      int ssize;
02342 {
02343   rtx *tmps, src;
02344   int start, i;
02345 
02346   if (GET_CODE (dst) != PARALLEL)
02347     abort ();
02348 
02349   /* Check for a NULL entry, used to indicate that the parameter goes
02350      both on the stack and in registers.  */
02351   if (XEXP (XVECEXP (dst, 0, 0), 0))
02352     start = 0;
02353   else
02354     start = 1;
02355 
02356   tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
02357 
02358   /* Process the pieces.  */
02359   for (i = start; i < XVECLEN (dst, 0); i++)
02360     {
02361       enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
02362       HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
02363       unsigned int bytelen = GET_MODE_SIZE (mode);
02364       int shift = 0;
02365 
02366       /* Handle trailing fragments that run over the size of the struct.  */
02367       if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
02368   {
02369     shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
02370     bytelen = ssize - bytepos;
02371     if (bytelen <= 0)
02372       abort ();
02373   }
02374 
02375       /* If we won't be loading directly from memory, protect the real source
02376    from strange tricks we might play; but make sure that the source can
02377    be loaded directly into the destination.  */
02378       src = orig_src;
02379       if (GET_CODE (orig_src) != MEM
02380     && (!CONSTANT_P (orig_src)
02381         || (GET_MODE (orig_src) != mode
02382       && GET_MODE (orig_src) != VOIDmode)))
02383   {
02384     if (GET_MODE (orig_src) == VOIDmode)
02385       src = gen_reg_rtx (mode);
02386     else
02387       src = gen_reg_rtx (GET_MODE (orig_src));
02388 
02389     emit_move_insn (src, orig_src);
02390   }
02391 
02392       /* Optimize the access just a bit.  */
02393       if (GET_CODE (src) == MEM
02394     && MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode)
02395     && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
02396     && bytelen == GET_MODE_SIZE (mode))
02397   {
02398     tmps[i] = gen_reg_rtx (mode);
02399     emit_move_insn (tmps[i], adjust_address (src, mode, bytepos));
02400   }
02401       else if (GET_CODE (src) == CONCAT)
02402   {
02403     unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
02404     unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
02405 
02406     if ((bytepos == 0 && bytelen == slen0)
02407         || (bytepos != 0 && bytepos + bytelen <= slen))
02408       {
02409         /* The following assumes that the concatenated objects all
02410      have the same size.  In this case, a simple calculation
02411      can be used to determine the object and the bit field
02412      to be extracted.  */
02413         tmps[i] = XEXP (src, bytepos / slen0);
02414         if (! CONSTANT_P (tmps[i])
02415       && (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode))
02416     tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
02417                (bytepos % slen0) * BITS_PER_UNIT,
02418                1, NULL_RTX, mode, mode, ssize);
02419       }
02420     else if (bytepos == 0)
02421       {
02422         rtx mem = assign_stack_temp (GET_MODE (src), slen, 0);
02423         emit_move_insn (mem, src);
02424         tmps[i] = adjust_address (mem, mode, 0);
02425       }
02426     else
02427       abort ();
02428   }
02429       else if (CONSTANT_P (src)
02430          || (GET_CODE (src) == REG && GET_MODE (src) == mode))
02431   tmps[i] = src;
02432       else
02433   tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
02434              bytepos * BITS_PER_UNIT, 1, NULL_RTX,
02435              mode, mode, ssize);
02436 
02437       if (BYTES_BIG_ENDIAN && shift)
02438   expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
02439           tmps[i], 0, OPTAB_WIDEN);
02440     }
02441 
02442   emit_queue ();
02443 
02444   /* Copy the extracted pieces into the proper (probable) hard regs.  */
02445   for (i = start; i < XVECLEN (dst, 0); i++)
02446     emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
02447 }
02448 
02449 /* Emit code to move a block SRC to block DST, where SRC and DST are
02450    non-consecutive groups of registers, each represented by a PARALLEL.  */
02451 
02452 void
02453 emit_group_move (dst, src)
02454      rtx dst, src;
02455 {
02456   int i;
02457 
02458   if (GET_CODE (src) != PARALLEL
02459       || GET_CODE (dst) != PARALLEL
02460       || XVECLEN (src, 0) != XVECLEN (dst, 0))
02461     abort ();
02462 
02463   /* Skip first entry if NULL.  */
02464   for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
02465     emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0),
02466         XEXP (XVECEXP (src, 0, i), 0));
02467 }
02468 
02469 /* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
02470    registers represented by a PARALLEL.  SSIZE represents the total size of
02471    block DST, or -1 if not known.  */
02472 
02473 void
02474 emit_group_store (orig_dst, src, ssize)
02475      rtx orig_dst, src;
02476      int ssize;
02477 {
02478   rtx *tmps, dst;
02479   int start, i;
02480 
02481   if (GET_CODE (src) != PARALLEL)
02482     abort ();
02483 
02484   /* Check for a NULL entry, used to indicate that the parameter goes
02485      both on the stack and in registers.  */
02486   if (XEXP (XVECEXP (src, 0, 0), 0))
02487     start = 0;
02488   else
02489     start = 1;
02490 
02491   tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0));
02492 
02493   /* Copy the (probable) hard regs into pseudos.  */
02494   for (i = start; i < XVECLEN (src, 0); i++)
02495     {
02496       rtx reg = XEXP (XVECEXP (src, 0, i), 0);
02497       tmps[i] = gen_reg_rtx (GET_MODE (reg));
02498       emit_move_insn (tmps[i], reg);
02499     }
02500   emit_queue ();
02501 
02502   /* If we won't be storing directly into memory, protect the real destination
02503      from strange tricks we might play.  */
02504   dst = orig_dst;
02505   if (GET_CODE (dst) == PARALLEL)
02506     {
02507       rtx temp;
02508 
02509       /* We can get a PARALLEL dst if there is a conditional expression in
02510    a return statement.  In that case, the dst and src are the same,
02511    so no action is necessary.  */
02512       if (rtx_equal_p (dst, src))
02513   return;
02514 
02515       /* It is unclear if we can ever reach here, but we may as well handle
02516    it.  Allocate a temporary, and split this into a store/load to/from
02517    the temporary.  */
02518 
02519       temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
02520       emit_group_store (temp, src, ssize);
02521       emit_group_load (dst, temp, ssize);
02522       return;
02523     }
02524   else if (GET_CODE (dst) != MEM && GET_CODE (dst) != CONCAT)
02525     {
02526       dst = gen_reg_rtx (GET_MODE (orig_dst));
02527       /* Make life a bit easier for combine.  */
02528       emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
02529     }
02530 
02531   /* Process the pieces.  */
02532   for (i = start; i < XVECLEN (src, 0); i++)
02533     {
02534       HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
02535       enum machine_mode mode = GET_MODE (tmps[i]);
02536       unsigned int bytelen = GET_MODE_SIZE (mode);
02537       rtx dest = dst;
02538 
02539       /* Handle trailing fragments that run over the size of the struct.  */
02540       if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
02541   {
02542     if (BYTES_BIG_ENDIAN)
02543       {
02544         int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
02545         expand_binop (mode, ashr_optab, tmps[i], GEN_INT (shift),
02546           tmps[i], 0, OPTAB_WIDEN);
02547       }
02548     bytelen = ssize - bytepos;
02549   }
02550 
02551       if (GET_CODE (dst) == CONCAT)
02552   {
02553     if (bytepos + bytelen <= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
02554       dest = XEXP (dst, 0);
02555     else if (bytepos >= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
02556       {
02557         bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
02558         dest = XEXP (dst, 1);
02559       }
02560     else if (bytepos == 0 && XVECLEN (src, 0))
02561       {
02562         dest = assign_stack_temp (GET_MODE (dest),
02563                 GET_MODE_SIZE (GET_MODE (dest)), 0);
02564         emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos),
02565             tmps[i]);
02566         dst = dest;
02567         break;
02568       }
02569     else
02570       abort ();
02571   }
02572 
02573       /* Optimize the access just a bit.  */
02574       if (GET_CODE (dest) == MEM
02575     && MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)
02576     && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
02577     && bytelen == GET_MODE_SIZE (mode))
02578   emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
02579       else
02580   store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
02581        mode, tmps[i], ssize);
02582     }
02583 
02584   emit_queue ();
02585 
02586   /* Copy from the pseudo into the (probable) hard reg.  */
02587   if (orig_dst != dst)
02588     emit_move_insn (orig_dst, dst);
02589 }
02590 
02591 /* Generate code to copy a BLKmode object of TYPE out of a
02592    set of registers starting with SRCREG into TGTBLK.  If TGTBLK
02593    is null, a stack temporary is created.  TGTBLK is returned.
02594 
02595    The primary purpose of this routine is to handle functions
02596    that return BLKmode structures in registers.  Some machines
02597    (the PA for example) want to return all small structures
02598    in registers regardless of the structure's alignment.  */
02599 
02600 rtx
02601 copy_blkmode_from_reg (tgtblk, srcreg, type)
02602      rtx tgtblk;
02603      rtx srcreg;
02604      tree type;
02605 {
02606   unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
02607   rtx src = NULL, dst = NULL;
02608   unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
02609   unsigned HOST_WIDE_INT bitpos, xbitpos, big_endian_correction = 0;
02610 
02611   if (tgtblk == 0)
02612     {
02613       tgtblk = assign_temp (build_qualified_type (type,
02614               (TYPE_QUALS (type)
02615                | TYPE_QUAL_CONST)),
02616           0, 1, 1);
02617       preserve_temp_slots (tgtblk);
02618     }
02619 
02620   /* This code assumes srcreg is at least a full word.  If it isn't, copy it
02621      into a new pseudo which is a full word.  */
02622 
02623   if (GET_MODE (srcreg) != BLKmode
02624       && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
02625     srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
02626 
02627   /* Structures whose size is not a multiple of a word are aligned
02628      to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
02629      machine, this means we must skip the empty high order bytes when
02630      calculating the bit offset.  */
02631   if (BYTES_BIG_ENDIAN
02632       && bytes % UNITS_PER_WORD)
02633     big_endian_correction
02634       = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
02635 
02636   /* Copy the structure BITSIZE bites at a time.
02637 
02638      We could probably emit more efficient code for machines which do not use
02639      strict alignment, but it doesn't seem worth the effort at the current
02640      time.  */
02641   for (bitpos = 0, xbitpos = big_endian_correction;
02642        bitpos < bytes * BITS_PER_UNIT;
02643        bitpos += bitsize, xbitpos += bitsize)
02644     {
02645       /* We need a new source operand each time xbitpos is on a
02646    word boundary and when xbitpos == big_endian_correction
02647    (the first time through).  */
02648       if (xbitpos % BITS_PER_WORD == 0
02649     || xbitpos == big_endian_correction)
02650   src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
02651              GET_MODE (srcreg));
02652 
02653       /* We need a new destination operand each time bitpos is on
02654    a word boundary.  */
02655       if (bitpos % BITS_PER_WORD == 0)
02656   dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
02657 
02658       /* Use xbitpos for the source extraction (right justified) and
02659    xbitpos for the destination store (left justified).  */
02660       store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
02661            extract_bit_field (src, bitsize,
02662             xbitpos % BITS_PER_WORD, 1,
02663             NULL_RTX, word_mode, word_mode,
02664             BITS_PER_WORD),
02665            BITS_PER_WORD);
02666     }
02667 
02668   return tgtblk;
02669 }
02670 
02671 /* Add a USE expression for REG to the (possibly empty) list pointed
02672    to by CALL_FUSAGE.  REG must denote a hard register.  */
02673 
02674 void
02675 use_reg (call_fusage, reg)
02676      rtx *call_fusage, reg;
02677 {
02678   if (GET_CODE (reg) != REG
02679       || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
02680     abort ();
02681 
02682   *call_fusage
02683     = gen_rtx_EXPR_LIST (VOIDmode,
02684        gen_rtx_USE (VOIDmode, reg), *call_fusage);
02685 }
02686 
02687 /* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs,
02688    starting at REGNO.  All of these registers must be hard registers.  */
02689 
02690 void
02691 use_regs (call_fusage, regno, nregs)
02692      rtx *call_fusage;
02693      int regno;
02694      int nregs;
02695 {
02696   int i;
02697 
02698   if (regno + nregs > FIRST_PSEUDO_REGISTER)
02699     abort ();
02700 
02701   for (i = 0; i < nregs; i++)
02702     use_reg (call_fusage, regno_reg_rtx[regno + i]);
02703 }
02704 
02705 /* Add USE expressions to *CALL_FUSAGE for each REG contained in the
02706    PARALLEL REGS.  This is for calls that pass values in multiple
02707    non-contiguous locations.  The Irix 6 ABI has examples of this.  */
02708 
02709 void
02710 use_group_regs (call_fusage, regs)
02711      rtx *call_fusage;
02712      rtx regs;
02713 {
02714   int i;
02715 
02716   for (i = 0; i < XVECLEN (regs, 0); i++)
02717     {
02718       rtx reg = XEXP (XVECEXP (regs, 0, i), 0);
02719 
02720       /* A NULL entry means the parameter goes both on the stack and in
02721    registers.  This can also be a MEM for targets that pass values
02722    partially on the stack and partially in registers.  */
02723       if (reg != 0 && GET_CODE (reg) == REG)
02724   use_reg (call_fusage, reg);
02725     }
02726 }
02727 
02728 
02729 /* Determine whether the LEN bytes generated by CONSTFUN can be
02730    stored to memory using several move instructions.  CONSTFUNDATA is
02731    a pointer which will be passed as argument in every CONSTFUN call.
02732    ALIGN is maximum alignment we can assume.  Return nonzero if a
02733    call to store_by_pieces should succeed.  */
02734 
02735 int
02736 can_store_by_pieces (len, constfun, constfundata, align)
02737      unsigned HOST_WIDE_INT len;
02738      rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
02739      PTR constfundata;
02740      unsigned int align;
02741 {
02742   unsigned HOST_WIDE_INT max_size, l;
02743   HOST_WIDE_INT offset = 0;
02744   enum machine_mode mode, tmode;
02745   enum insn_code icode;
02746   int reverse;
02747   rtx cst;
02748 
02749   if (len == 0)
02750     return 1;
02751 
02752   if (! MOVE_BY_PIECES_P (len, align))
02753     return 0;
02754 
02755   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
02756       || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
02757     align = MOVE_MAX * BITS_PER_UNIT;
02758 
02759   /* We would first store what we can in the largest integer mode, then go to
02760      successively smaller modes.  */
02761 
02762   for (reverse = 0;
02763        reverse <= (HAVE_PRE_DECREMENT || HAVE_POST_DECREMENT);
02764        reverse++)
02765     {
02766       l = len;
02767       mode = VOIDmode;
02768       max_size = STORE_MAX_PIECES + 1;
02769       while (max_size > 1)
02770   {
02771     for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02772          tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02773       if (GET_MODE_SIZE (tmode) < max_size)
02774         mode = tmode;
02775 
02776     if (mode == VOIDmode)
02777       break;
02778 
02779     icode = mov_optab->handlers[(int) mode].insn_code;
02780     if (icode != CODE_FOR_nothing
02781         && align >= GET_MODE_ALIGNMENT (mode))
02782       {
02783         unsigned int size = GET_MODE_SIZE (mode);
02784 
02785         while (l >= size)
02786     {
02787       if (reverse)
02788         offset -= size;
02789 
02790       cst = (*constfun) (constfundata, offset, mode);
02791       if (!LEGITIMATE_CONSTANT_P (cst))
02792         return 0;
02793 
02794       if (!reverse)
02795         offset += size;
02796 
02797       l -= size;
02798     }
02799       }
02800 
02801     max_size = GET_MODE_SIZE (mode);
02802   }
02803 
02804       /* The code above should have handled everything.  */
02805       if (l != 0)
02806   abort ();
02807     }
02808 
02809   return 1;
02810 }
02811 
02812 /* Generate several move instructions to store LEN bytes generated by
02813    CONSTFUN to block TO.  (A MEM rtx with BLKmode).  CONSTFUNDATA is a
02814    pointer which will be passed as argument in every CONSTFUN call.
02815    ALIGN is maximum alignment we can assume.
02816    If ENDP is 0 return to, if ENDP is 1 return memory at the end ala
02817    mempcpy, and if ENDP is 2 return memory the end minus one byte ala
02818    stpcpy.  */
02819 
02820 rtx
02821 store_by_pieces (to, len, constfun, constfundata, align, endp)
02822      rtx to;
02823      unsigned HOST_WIDE_INT len;
02824      rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
02825      PTR constfundata;
02826      unsigned int align;
02827      int endp;
02828 {
02829   struct store_by_pieces data;
02830 
02831   if (len == 0)
02832     {
02833       if (endp == 2)
02834   abort ();
02835       return to;
02836     }
02837 
02838   if (! MOVE_BY_PIECES_P (len, align))
02839     abort ();
02840   to = protect_from_queue (to, 1);
02841   data.constfun = constfun;
02842   data.constfundata = constfundata;
02843   data.len = len;
02844   data.to = to;
02845   store_by_pieces_1 (&data, align);
02846   if (endp)
02847     {
02848       rtx to1;
02849 
02850       if (data.reverse)
02851   abort ();
02852       if (data.autinc_to)
02853   {
02854     if (endp == 2)
02855       {
02856         if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
02857     emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
02858         else
02859     data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
02860                 -1));
02861       }
02862     to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
02863              data.offset);
02864   }
02865       else
02866   {
02867     if (endp == 2)
02868       --data.offset;
02869     to1 = adjust_address (data.to, QImode, data.offset);
02870   }
02871       return to1;
02872     }
02873   else
02874     return data.to;
02875 }
02876 
02877 /* Generate several move instructions to clear LEN bytes of block TO.  (A MEM
02878    rtx with BLKmode).  The caller must pass TO through protect_from_queue
02879    before calling. ALIGN is maximum alignment we can assume.  */
02880 
02881 static void
02882 clear_by_pieces (to, len, align)
02883      rtx to;
02884      unsigned HOST_WIDE_INT len;
02885      unsigned int align;
02886 {
02887   struct store_by_pieces data;
02888 
02889   if (len == 0)
02890     return;
02891 
02892   data.constfun = clear_by_pieces_1;
02893   data.constfundata = NULL;
02894   data.len = len;
02895   data.to = to;
02896   store_by_pieces_1 (&data, align);
02897 }
02898 
02899 /* Callback routine for clear_by_pieces.
02900    Return const0_rtx unconditionally.  */
02901 
02902 static rtx
02903 clear_by_pieces_1 (data, offset, mode)
02904      PTR data ATTRIBUTE_UNUSED;
02905      HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
02906      enum machine_mode mode ATTRIBUTE_UNUSED;
02907 {
02908   return const0_rtx;
02909 }
02910 
02911 /* Subroutine of clear_by_pieces and store_by_pieces.
02912    Generate several move instructions to store LEN bytes of block TO.  (A MEM
02913    rtx with BLKmode).  The caller must pass TO through protect_from_queue
02914    before calling.  ALIGN is maximum alignment we can assume.  */
02915 
02916 static void
02917 store_by_pieces_1 (data, align)
02918      struct store_by_pieces *data;
02919      unsigned int align;
02920 {
02921   rtx to_addr = XEXP (data->to, 0);
02922   unsigned HOST_WIDE_INT max_size = STORE_MAX_PIECES + 1;
02923   enum machine_mode mode = VOIDmode, tmode;
02924   enum insn_code icode;
02925 
02926   data->offset = 0;
02927   data->to_addr = to_addr;
02928   data->autinc_to
02929     = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
02930        || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
02931 
02932   data->explicit_inc_to = 0;
02933   data->reverse
02934     = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
02935   if (data->reverse)
02936     data->offset = data->len;
02937 
02938   /* If storing requires more than two move insns,
02939      copy addresses to registers (to make displacements shorter)
02940      and use post-increment if available.  */
02941   if (!data->autinc_to
02942       && move_by_pieces_ninsns (data->len, align) > 2)
02943     {
02944       /* Determine the main mode we'll be using.  */
02945       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02946      tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02947   if (GET_MODE_SIZE (tmode) < max_size)
02948     mode = tmode;
02949 
02950       if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
02951   {
02952     data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
02953     data->autinc_to = 1;
02954     data->explicit_inc_to = -1;
02955   }
02956 
02957       if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
02958     && ! data->autinc_to)
02959   {
02960     data->to_addr = copy_addr_to_reg (to_addr);
02961     data->autinc_to = 1;
02962     data->explicit_inc_to = 1;
02963   }
02964 
02965       if ( !data->autinc_to && CONSTANT_P (to_addr))
02966   data->to_addr = copy_addr_to_reg (to_addr);
02967     }
02968 
02969   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
02970       || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
02971     align = MOVE_MAX * BITS_PER_UNIT;
02972 
02973   /* First store what we can in the largest integer mode, then go to
02974      successively smaller modes.  */
02975 
02976   while (max_size > 1)
02977     {
02978       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02979      tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02980   if (GET_MODE_SIZE (tmode) < max_size)
02981     mode = tmode;
02982 
02983       if (mode == VOIDmode)
02984   break;
02985 
02986       icode = mov_optab->handlers[(int) mode].insn_code;
02987       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
02988   store_by_pieces_2 (GEN_FCN (icode), mode, data);
02989 
02990       max_size = GET_MODE_SIZE (mode);
02991     }
02992 
02993   /* The code above should have handled everything.  */
02994   if (data->len != 0)
02995     abort ();
02996 }
02997 
02998 /* Subroutine of store_by_pieces_1.  Store as many bytes as appropriate
02999    with move instructions for mode MODE.  GENFUN is the gen_... function
03000    to make a move insn for that mode.  DATA has all the other info.  */
03001 
03002 static void
03003 store_by_pieces_2 (genfun, mode, data)
03004      rtx (*genfun) PARAMS ((rtx, ...));
03005      enum machine_mode mode;
03006      struct store_by_pieces *data;
03007 {
03008   unsigned int size = GET_MODE_SIZE (mode);
03009   rtx to1, cst;
03010 
03011   while (data->len >= size)
03012     {
03013       if (data->reverse)
03014   data->offset -= size;
03015 
03016       if (data->autinc_to)
03017   to1 = adjust_automodify_address (data->to, mode, data->to_addr,
03018            data->offset);
03019       else
03020   to1 = adjust_address (data->to, mode, data->offset);
03021 
03022       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
03023   emit_insn (gen_add2_insn (data->to_addr,
03024           GEN_INT (-(HOST_WIDE_INT) size)));
03025 
03026       cst = (*data->constfun) (data->constfundata, data->offset, mode);
03027       emit_insn ((*genfun) (to1, cst));
03028 
03029       if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
03030   emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
03031 
03032       if (! data->reverse)
03033   data->offset += size;
03034 
03035       data->len -= size;
03036     }
03037 }
03038 
03039 /* Write zeros through the storage of OBJECT.  If OBJECT has BLKmode, SIZE is
03040    its length in bytes.  */
03041 
03042 rtx
03043 clear_storage (object, size)
03044      rtx object;
03045      rtx size;
03046 {
03047   rtx retval = 0;
03048   unsigned int align = (GET_CODE (object) == MEM ? MEM_ALIGN (object)
03049       : GET_MODE_ALIGNMENT (GET_MODE (object)));
03050 
03051   /* If OBJECT is not BLKmode and SIZE is the same size as its mode,
03052      just move a zero.  Otherwise, do this a piece at a time.  */
03053   if (GET_MODE (object) != BLKmode
03054       && GET_CODE (size) == CONST_INT
03055       && INTVAL (size) == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (object)))
03056     emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
03057   else
03058     {
03059       object = protect_from_queue (object, 1);
03060       size = protect_from_queue (size, 0);
03061 
03062       if (size == const0_rtx)
03063   ;
03064       else if (GET_CODE (size) == CONST_INT
03065     && CLEAR_BY_PIECES_P (INTVAL (size), align))
03066   clear_by_pieces (object, INTVAL (size), align);
03067       else if (clear_storage_via_clrstr (object, size, align))
03068   ;
03069       else
03070   retval = clear_storage_via_libcall (object, size);
03071     }
03072 
03073   return retval;
03074 }
03075 
03076 /* A subroutine of clear_storage.  Expand a clrstr pattern;
03077    return true if successful.  */
03078 
03079 static bool
03080 clear_storage_via_clrstr (object, size, align)
03081      rtx object, size;
03082      unsigned int align;
03083 {
03084   /* Try the most limited insn first, because there's no point
03085      including more than one in the machine description unless
03086      the more limited one has some advantage.  */
03087 
03088   rtx opalign = GEN_INT (align / BITS_PER_UNIT);
03089   enum machine_mode mode;
03090 
03091   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
03092        mode = GET_MODE_WIDER_MODE (mode))
03093     {
03094       enum insn_code code = clrstr_optab[(int) mode];
03095       insn_operand_predicate_fn pred;
03096 
03097       if (code != CODE_FOR_nothing
03098     /* We don't need MODE to be narrower than
03099        BITS_PER_HOST_WIDE_INT here because if SIZE is less than
03100        the mode mask, as it is returned by the macro, it will
03101        definitely be less than the actual mode mask.  */
03102     && ((GET_CODE (size) == CONST_INT
03103          && ((unsigned HOST_WIDE_INT) INTVAL (size)
03104        <= (GET_MODE_MASK (mode) >> 1)))
03105         || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
03106     && ((pred = insn_data[(int) code].operand[0].predicate) == 0
03107         || (*pred) (object, BLKmode))
03108     && ((pred = insn_data[(int) code].operand[2].predicate) == 0
03109         || (*pred) (opalign, VOIDmode)))
03110   {
03111     rtx op1;
03112     rtx last = get_last_insn ();
03113     rtx pat;
03114 
03115     op1 = convert_to_mode (mode, size, 1);
03116     pred = insn_data[(int) code].operand[1].predicate;
03117     if (pred != 0 && ! (*pred) (op1, mode))
03118       op1 = copy_to_mode_reg (mode, op1);
03119 
03120     pat = GEN_FCN ((int) code) (object, op1, opalign);
03121     if (pat)
03122       {
03123         emit_insn (pat);
03124         return true;
03125       }
03126     else
03127       delete_insns_since (last);
03128   }
03129     }
03130 
03131   return false;
03132 }
03133 
03134 /* A subroutine of clear_storage.  Expand a call to memset or bzero.
03135    Return the return value of memset, 0 otherwise.  */
03136 
03137 static rtx
03138 clear_storage_via_libcall (object, size)
03139      rtx object, size;
03140 {
03141   tree call_expr, arg_list, fn, object_tree, size_tree;
03142   enum machine_mode size_mode;
03143   rtx retval;
03144 
03145   /* OBJECT or SIZE may have been passed through protect_from_queue.
03146 
03147      It is unsafe to save the value generated by protect_from_queue
03148      and reuse it later.  Consider what happens if emit_queue is
03149      called before the return value from protect_from_queue is used.
03150 
03151      Expansion of the CALL_EXPR below will call emit_queue before
03152      we are finished emitting RTL for argument setup.  So if we are
03153      not careful we could get the wrong value for an argument.
03154 
03155      To avoid this problem we go ahead and emit code to copy OBJECT
03156      and SIZE into new pseudos.  We can then place those new pseudos
03157      into an RTL_EXPR and use them later, even after a call to
03158      emit_queue.
03159 
03160      Note this is not strictly needed for library calls since they
03161      do not call emit_queue before loading their arguments.  However,
03162      we may need to have library calls call emit_queue in the future
03163      since failing to do so could cause problems for targets which
03164      define SMALL_REGISTER_CLASSES and pass arguments in registers.  */
03165 
03166   object = copy_to_mode_reg (Pmode, XEXP (object, 0));
03167 
03168   if (TARGET_MEM_FUNCTIONS)
03169     size_mode = TYPE_MODE (sizetype);
03170   else
03171     size_mode = TYPE_MODE (unsigned_type_node);
03172   size = convert_to_mode (size_mode, size, 1);
03173   size = copy_to_mode_reg (size_mode, size);
03174 
03175   /* It is incorrect to use the libcall calling conventions to call
03176      memset in this context.  This could be a user call to memset and
03177      the user may wish to examine the return value from memset.  For
03178      targets where libcalls and normal calls have different conventions
03179      for returning pointers, we could end up generating incorrect code.
03180 
03181      For convenience, we generate the call to bzero this way as well.  */
03182 
03183   object_tree = make_tree (ptr_type_node, object);
03184   if (TARGET_MEM_FUNCTIONS)
03185     size_tree = make_tree (sizetype, size);
03186   else
03187     size_tree = make_tree (unsigned_type_node, size);
03188 
03189   fn = clear_storage_libcall_fn (true);
03190   arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
03191   if (TARGET_MEM_FUNCTIONS)
03192     arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
03193   arg_list = tree_cons (NULL_TREE, object_tree, arg_list);
03194 
03195   /* Now we have to build up the CALL_EXPR itself.  */
03196   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
03197   call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
03198          call_expr, arg_list, NULL_TREE);
03199   TREE_SIDE_EFFECTS (call_expr) = 1;
03200 
03201   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
03202 
03203   /* If we are initializing a readonly value, show the above call
03204      clobbered it.  Otherwise, a load from it may erroneously be
03205      hoisted from a loop.  */
03206   if (RTX_UNCHANGING_P (object))
03207     emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
03208 
03209   return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
03210 }
03211 
03212 /* A subroutine of clear_storage_via_libcall.  Create the tree node
03213    for the function we use for block clears.  The first time FOR_CALL
03214    is true, we call assemble_external.  */
03215 
03216 static GTY(()) tree block_clear_fn;
03217 
03218 void
03219 init_block_clear_fn (asmspec)
03220      const char *asmspec;
03221 {
03222   if (!block_clear_fn)
03223     {
03224       tree fn, args;
03225 
03226       if (TARGET_MEM_FUNCTIONS)
03227   {
03228     fn = get_identifier ("memset");
03229     args = build_function_type_list (ptr_type_node, ptr_type_node,
03230              integer_type_node, sizetype,
03231              NULL_TREE);
03232   }
03233       else
03234   {
03235     fn = get_identifier ("bzero");
03236     args = build_function_type_list (void_type_node, ptr_type_node,
03237              unsigned_type_node, NULL_TREE);
03238   }
03239 
03240       fn = build_decl (FUNCTION_DECL, fn, args);
03241       DECL_EXTERNAL (fn) = 1;
03242       TREE_PUBLIC (fn) = 1;
03243       DECL_ARTIFICIAL (fn) = 1;
03244       TREE_NOTHROW (fn) = 1;
03245 
03246       block_clear_fn = fn;
03247     }
03248 
03249   if (asmspec)
03250     {
03251       SET_DECL_RTL (block_clear_fn, NULL_RTX);
03252       SET_DECL_ASSEMBLER_NAME (block_clear_fn, get_identifier (asmspec));
03253     }
03254 }
03255 
03256 static tree
03257 clear_storage_libcall_fn (for_call)
03258      int for_call;
03259 {
03260   static bool emitted_extern;
03261 
03262   if (!block_clear_fn)
03263     init_block_clear_fn (NULL);
03264 
03265   if (for_call && !emitted_extern)
03266     {
03267       emitted_extern = true;
03268       make_decl_rtl (block_clear_fn, NULL);
03269       assemble_external (block_clear_fn);
03270     }
03271 
03272   return block_clear_fn;
03273 }
03274 
03275 /* Generate code to copy Y into X.
03276    Both Y and X must have the same mode, except that
03277    Y can be a constant with VOIDmode.
03278    This mode cannot be BLKmode; use emit_block_move for that.
03279 
03280    Return the last instruction emitted.  */
03281 
03282 rtx
03283 emit_move_insn (x, y)
03284      rtx x, y;
03285 {
03286   enum machine_mode mode = GET_MODE (x);
03287   rtx y_cst = NULL_RTX;
03288   rtx last_insn;
03289 
03290   x = protect_from_queue (x, 1);
03291   y = protect_from_queue (y, 0);
03292 
03293 #ifndef KEY
03294   if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
03295     abort ();
03296 #endif
03297 
03298   /* Never force constant_p_rtx to memory.  */
03299   if (GET_CODE (y) == CONSTANT_P_RTX)
03300     ;
03301   else if (CONSTANT_P (y))
03302     {
03303       if (optimize
03304     && SCALAR_FLOAT_MODE_P (GET_MODE (x))
03305     && (last_insn = compress_float_constant (x, y)))
03306   return last_insn;
03307 
03308       if (!LEGITIMATE_CONSTANT_P (y))
03309   {
03310     y_cst = y;
03311     y = force_const_mem (mode, y);
03312 
03313     /* If the target's cannot_force_const_mem prevented the spill,
03314        assume that the target's move expanders will also take care
03315        of the non-legitimate constant.  */
03316     if (!y)
03317       y = y_cst;
03318   }
03319     }
03320 
03321   /* If X or Y are memory references, verify that their addresses are valid
03322      for the machine.  */
03323   if (GET_CODE (x) == MEM
03324       && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
03325      && ! push_operand (x, GET_MODE (x)))
03326     || (flag_force_addr
03327         && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
03328     x = validize_mem (x);
03329 
03330   if (GET_CODE (y) == MEM
03331       && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
03332     || (flag_force_addr
03333         && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
03334     y = validize_mem (y);
03335 
03336   if (mode == BLKmode)
03337     abort ();
03338 
03339   last_insn = emit_move_insn_1 (x, y);
03340 
03341   if (y_cst && GET_CODE (x) == REG)
03342     set_unique_reg_note (last_insn, REG_EQUAL, y_cst);
03343 
03344   return last_insn;
03345 }
03346 
03347 /* Low level part of emit_move_insn.
03348    Called just like emit_move_insn, but assumes X and Y
03349    are basically valid.  */
03350 
03351 rtx
03352 emit_move_insn_1 (x, y)
03353      rtx x, y;
03354 {
03355   enum machine_mode mode = GET_MODE (x);
03356   enum machine_mode submode;
03357   enum mode_class class = GET_MODE_CLASS (mode);
03358 
03359   if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
03360     abort ();
03361 
03362   if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
03363     return
03364       emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
03365 
03366   /* Expand complex moves by moving real part and imag part, if possible.  */
03367   else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
03368      && BLKmode != (submode = GET_MODE_INNER (mode))
03369      && (mov_optab->handlers[(int) submode].insn_code
03370          != CODE_FOR_nothing))
03371     {
03372       /* Don't split destination if it is a stack push.  */
03373       int stack = push_operand (x, GET_MODE (x));
03374 
03375 #ifdef PUSH_ROUNDING
03376       /* In case we output to the stack, but the size is smaller machine can
03377    push exactly, we need to use move instructions.  */
03378       if (stack
03379     && (PUSH_ROUNDING (GET_MODE_SIZE (submode))
03380         != GET_MODE_SIZE (submode)))
03381   {
03382     rtx temp;
03383     HOST_WIDE_INT offset1, offset2;
03384 
03385     /* Do not use anti_adjust_stack, since we don't want to update
03386        stack_pointer_delta.  */
03387     temp = expand_binop (Pmode,
03388 #ifdef STACK_GROWS_DOWNWARD
03389              sub_optab,
03390 #else
03391              add_optab,
03392 #endif
03393              stack_pointer_rtx,
03394              GEN_INT
03395          (PUSH_ROUNDING
03396           (GET_MODE_SIZE (GET_MODE (x)))),
03397              stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
03398 
03399     if (temp != stack_pointer_rtx)
03400       emit_move_insn (stack_pointer_rtx, temp);
03401 
03402 #ifdef STACK_GROWS_DOWNWARD
03403     offset1 = 0;
03404     offset2 = GET_MODE_SIZE (submode);
03405 #else
03406     offset1 = -PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)));
03407     offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
03408          + GET_MODE_SIZE (submode));
03409 #endif
03410 
03411     emit_move_insn (change_address (x, submode,
03412             gen_rtx_PLUS (Pmode,
03413                     stack_pointer_rtx,
03414               GEN_INT (offset1))),
03415         gen_realpart (submode, y));
03416     emit_move_insn (change_address (x, submode,
03417             gen_rtx_PLUS (Pmode,
03418                     stack_pointer_rtx,
03419               GEN_INT (offset2))),
03420         gen_imagpart (submode, y));
03421   }
03422       else
03423 #endif
03424       /* If this is a stack, push the highpart first, so it
03425    will be in the argument order.
03426 
03427    In that case, change_address is used only to convert
03428    the mode, not to change the address.  */
03429       if (stack)
03430   {
03431     /* Note that the real part always precedes the imag part in memory
03432        regardless of machine's endianness.  */
03433 #ifdef STACK_GROWS_DOWNWARD
03434     emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03435          (gen_rtx_MEM (submode, XEXP (x, 0)),
03436           gen_imagpart (submode, y)));
03437     emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03438          (gen_rtx_MEM (submode, XEXP (x, 0)),
03439           gen_realpart (submode, y)));
03440 #else
03441     emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03442          (gen_rtx_MEM (submode, XEXP (x, 0)),
03443           gen_realpart (submode, y)));
03444     emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03445          (gen_rtx_MEM (submode, XEXP (x, 0)),
03446           gen_imagpart (submode, y)));
03447 #endif
03448   }
03449       else
03450   {
03451     rtx realpart_x, realpart_y;
03452     rtx imagpart_x, imagpart_y;
03453 
03454     /* If this is a complex value with each part being smaller than a
03455        word, the usual calling sequence will likely pack the pieces into
03456        a single register.  Unfortunately, SUBREG of hard registers only
03457        deals in terms of words, so we have a problem converting input
03458        arguments to the CONCAT of two registers that is used elsewhere
03459        for complex values.  If this is before reload, we can copy it into
03460        memory and reload.  FIXME, we should see about using extract and
03461        insert on integer registers, but complex short and complex char
03462        variables should be rarely used.  */
03463     if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
03464         && (reload_in_progress | reload_completed) == 0)
03465       {
03466         int packed_dest_p
03467     = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
03468         int packed_src_p
03469     = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
03470 
03471         if (packed_dest_p || packed_src_p)
03472     {
03473       enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
03474                  ? MODE_FLOAT : MODE_INT);
03475 
03476       enum machine_mode reg_mode
03477         = mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
03478 
03479       if (reg_mode != BLKmode)
03480         {
03481           rtx mem = assign_stack_temp (reg_mode,
03482                GET_MODE_SIZE (mode), 0);
03483           rtx cmem = adjust_address (mem, mode, 0);
03484 
03485           cfun->cannot_inline
03486       = N_("function using short complex types cannot be inline");
03487 
03488           if (packed_dest_p)
03489       {
03490         rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
03491 
03492         emit_move_insn_1 (cmem, y);
03493         return emit_move_insn_1 (sreg, mem);
03494       }
03495           else
03496       {
03497         rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
03498 
03499         emit_move_insn_1 (mem, sreg);
03500         return emit_move_insn_1 (x, cmem);
03501       }
03502         }
03503     }
03504       }
03505 
03506     realpart_x = gen_realpart (submode, x);
03507     realpart_y = gen_realpart (submode, y);
03508     imagpart_x = gen_imagpart (submode, x);
03509     imagpart_y = gen_imagpart (submode, y);
03510 
03511     /* Show the output dies here.  This is necessary for SUBREGs
03512        of pseudos since we cannot track their lifetimes correctly;
03513        hard regs shouldn't appear here except as return values.
03514        We never want to emit such a clobber after reload.  */
03515     if (x != y
03516         && ! (reload_in_progress || reload_completed)
03517         && (GET_CODE (realpart_x) == SUBREG
03518       || GET_CODE (imagpart_x) == SUBREG))
03519       emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
03520 
03521     emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03522          (realpart_x, realpart_y));
03523     emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03524          (imagpart_x, imagpart_y));
03525   }
03526 
03527       return get_last_insn ();
03528     }
03529 
03530   /* This will handle any multi-word or full-word mode that lacks a move_insn
03531      pattern.  However, you will get better code if you define such patterns,
03532      even if they must turn into multiple assembler instructions.  */
03533   else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
03534     {
03535       rtx last_insn = 0;
03536       rtx seq, inner;
03537       int need_clobber;
03538       int i;
03539 
03540 #ifdef PUSH_ROUNDING
03541 
03542       /* If X is a push on the stack, do the push now and replace
03543    X with a reference to the stack pointer.  */
03544       if (push_operand (x, GET_MODE (x)))
03545   {
03546     rtx temp;
03547     enum rtx_code code;
03548 
03549     /* Do not use anti_adjust_stack, since we don't want to update
03550        stack_pointer_delta.  */
03551     temp = expand_binop (Pmode,
03552 #ifdef STACK_GROWS_DOWNWARD
03553              sub_optab,
03554 #else
03555              add_optab,
03556 #endif
03557              stack_pointer_rtx,
03558              GEN_INT
03559          (PUSH_ROUNDING
03560           (GET_MODE_SIZE (GET_MODE (x)))),
03561              stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
03562 
03563     if (temp != stack_pointer_rtx)
03564       emit_move_insn (stack_pointer_rtx, temp);
03565 
03566     code = GET_CODE (XEXP (x, 0));
03567 
03568     /* Just hope that small offsets off SP are OK.  */
03569     if (code == POST_INC)
03570       temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03571         GEN_INT (-((HOST_WIDE_INT)
03572              GET_MODE_SIZE (GET_MODE (x)))));
03573     else if (code == POST_DEC)
03574       temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03575         GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
03576     else
03577       temp = stack_pointer_rtx;
03578 
03579     x = change_address (x, VOIDmode, temp);
03580   }
03581 #endif
03582 
03583       /* If we are in reload, see if either operand is a MEM whose address
03584    is scheduled for replacement.  */
03585       if (reload_in_progress && GET_CODE (x) == MEM
03586     && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
03587   x = replace_equiv_address_nv (x, inner);
03588       if (reload_in_progress && GET_CODE (y) == MEM
03589     && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
03590   y = replace_equiv_address_nv (y, inner);
03591 
03592       start_sequence ();
03593 
03594       need_clobber = 0;
03595       for (i = 0;
03596      i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
03597      i++)
03598   {
03599     rtx xpart = operand_subword (x, i, 1, mode);
03600     rtx ypart = operand_subword (y, i, 1, mode);
03601 
03602     /* If we can't get a part of Y, put Y into memory if it is a
03603        constant.  Otherwise, force it into a register.  If we still
03604        can't get a part of Y, abort.  */
03605     if (ypart == 0 && CONSTANT_P (y))
03606       {
03607         y = force_const_mem (mode, y);
03608         ypart = operand_subword (y, i, 1, mode);
03609       }
03610     else if (ypart == 0)
03611       ypart = operand_subword_force (y, i, mode);
03612 
03613     if (xpart == 0 || ypart == 0)
03614       abort ();
03615 
03616     need_clobber |= (GET_CODE (xpart) == SUBREG);
03617 
03618     last_insn = emit_move_insn (xpart, ypart);
03619   }
03620 
03621       seq = get_insns ();
03622       end_sequence ();
03623 
03624       /* Show the output dies here.  This is necessary for SUBREGs
03625    of pseudos since we cannot track their lifetimes correctly;
03626    hard regs shouldn't appear here except as return values.
03627    We never want to emit such a clobber after reload.  */
03628       if (x != y
03629     && ! (reload_in_progress || reload_completed)
03630     && need_clobber != 0)
03631   emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
03632 
03633       emit_insn (seq);
03634 
03635       return last_insn;
03636     }
03637   else
03638     abort ();
03639 }
03640 
03641 /* If Y is representable exactly in a narrower mode, and the target can
03642    perform the extension directly from constant or memory, then emit the
03643    move as an extension.  */
03644 
03645 static rtx
03646 compress_float_constant (x, y)
03647      rtx x, y;
03648 {
03649   enum machine_mode dstmode = GET_MODE (x);
03650   enum machine_mode orig_srcmode = GET_MODE (y);
03651   enum machine_mode srcmode;
03652   REAL_VALUE_TYPE r;
03653 
03654   REAL_VALUE_FROM_CONST_DOUBLE (r, y);
03655 
03656   for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
03657        srcmode != orig_srcmode;
03658        srcmode = GET_MODE_WIDER_MODE (srcmode))
03659     {
03660       enum insn_code ic;
03661       rtx trunc_y, last_insn;
03662 
03663       /* Skip if the target can't extend this way.  */
03664       ic = can_extend_p (dstmode, srcmode, 0);
03665       if (ic == CODE_FOR_nothing)
03666   continue;
03667 
03668       /* Skip if the narrowed value isn't exact.  */
03669       if (! exact_real_truncate (srcmode, &r))
03670   continue;
03671 
03672       trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
03673 
03674       if (LEGITIMATE_CONSTANT_P (trunc_y))
03675   {
03676     /* Skip if the target needs extra instructions to perform
03677        the extension.  */
03678     if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
03679       continue;
03680   }
03681       else if (float_extend_from_mem[dstmode][srcmode])
03682   trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
03683       else
03684   continue;
03685 
03686       emit_unop_insn (ic, x, trunc_y, UNKNOWN);
03687       last_insn = get_last_insn ();
03688 
03689       if (GET_CODE (x) == REG)
03690   REG_NOTES (last_insn)
03691     = gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));
03692 
03693       return last_insn;
03694     }
03695 
03696   return NULL_RTX;
03697 }
03698 
03699 /* Pushing data onto the stack.  */
03700 
03701 /* Push a block of length SIZE (perhaps variable)
03702    and return an rtx to address the beginning of the block.
03703    Note that it is not possible for the value returned to be a QUEUED.
03704    The value may be virtual_outgoing_args_rtx.
03705 
03706    EXTRA is the number of bytes of padding to push in addition to SIZE.
03707    BELOW nonzero means this padding comes at low addresses;
03708    otherwise, the padding comes at high addresses.  */
03709 
03710 rtx
03711 push_block (size, extra, below)
03712      rtx size;
03713      int extra, below;
03714 {
03715   rtx temp;
03716 
03717   size = convert_modes (Pmode, ptr_mode, size, 1);
03718   if (CONSTANT_P (size))
03719     anti_adjust_stack (plus_constant (size, extra));
03720   else if (GET_CODE (size) == REG && extra == 0)
03721     anti_adjust_stack (size);
03722   else
03723     {
03724       temp = copy_to_mode_reg (Pmode, size);
03725       if (extra != 0)
03726   temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
03727            temp, 0, OPTAB_LIB_WIDEN);
03728       anti_adjust_stack (temp);
03729     }
03730 
03731 #ifndef STACK_GROWS_DOWNWARD
03732   if (0)
03733 #else
03734   if (1)
03735 #endif
03736     {
03737       temp = virtual_outgoing_args_rtx;
03738       if (extra != 0 && below)
03739   temp = plus_constant (temp, extra);
03740     }
03741   else
03742     {
03743       if (GET_CODE (size) == CONST_INT)
03744   temp = plus_constant (virtual_outgoing_args_rtx,
03745             -INTVAL (size) - (below ? 0 : extra));
03746       else if (extra != 0 && !below)
03747   temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
03748            negate_rtx (Pmode, plus_constant (size, extra)));
03749       else
03750   temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
03751            negate_rtx (Pmode, size));
03752     }
03753 
03754   return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
03755 }
03756 
03757 #ifdef PUSH_ROUNDING
03758 
03759 /* Emit single push insn.  */
03760 
03761 static void
03762 emit_single_push_insn (mode, x, type)
03763      rtx x;
03764      enum machine_mode mode;
03765      tree type;
03766 {
03767   rtx dest_addr;
03768   unsigned rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
03769   rtx dest;
03770   enum insn_code icode;
03771   insn_operand_predicate_fn pred;
03772 
03773   stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
03774   /* If there is push pattern, use it.  Otherwise try old way of throwing
03775      MEM representing push operation to move expander.  */
03776   icode = push_optab->handlers[(int) mode].insn_code;
03777   if (icode != CODE_FOR_nothing)
03778     {
03779       if (((pred = insn_data[(int) icode].operand[0].predicate)
03780      && !((*pred) (x, mode))))
03781   x = force_reg (mode, x);
03782       emit_insn (GEN_FCN (icode) (x));
03783       return;
03784     }
03785   if (GET_MODE_SIZE (mode) == rounded_size)
03786     dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
03787   else
03788     {
03789 #ifdef STACK_GROWS_DOWNWARD
03790       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03791         GEN_INT (-(HOST_WIDE_INT) rounded_size));
03792 #else
03793       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03794         GEN_INT (rounded_size));
03795 #endif
03796       dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
03797     }
03798 
03799   dest = gen_rtx_MEM (mode, dest_addr);
03800 
03801   if (type != 0)
03802     {
03803       set_mem_attributes (dest, type, 1);
03804 
03805       if (flag_optimize_sibling_calls)
03806   /* Function incoming arguments may overlap with sibling call
03807      outgoing arguments and we cannot allow reordering of reads
03808      from function arguments with stores to outgoing arguments
03809      of sibling calls.  */
03810   set_mem_alias_set (dest, 0);
03811     }
03812   emit_move_insn (dest, x);
03813 }
03814 #endif
03815 
03816 /* Generate code to push X onto the stack, assuming it has mode MODE and
03817    type TYPE.
03818    MODE is redundant except when X is a CONST_INT (since they don't
03819    carry mode info).
03820    SIZE is an rtx for the size of data to be copied (in bytes),
03821    needed only if X is BLKmode.
03822 
03823    ALIGN (in bits) is maximum alignment we can assume.
03824 
03825    If PARTIAL and REG are both nonzero, then copy that many of the first
03826    words of X into registers starting with REG, and push the rest of X.
03827    The amount of space pushed is decreased by PARTIAL words,
03828    rounded *down* to a multiple of PARM_BOUNDARY.
03829    REG must be a hard register in this case.
03830    If REG is zero but PARTIAL is not, take any all others actions for an
03831    argument partially in registers, but do not actually load any
03832    registers.
03833 
03834    EXTRA is the amount in bytes of extra space to leave next to this arg.
03835    This is ignored if an argument block has already been allocated.
03836 
03837    On a machine that lacks real push insns, ARGS_ADDR is the address of
03838    the bottom of the argument block for this call.  We use indexing off there
03839    to store the arg.  On machines with push insns, ARGS_ADDR is 0 when a
03840    argument block has not been preallocated.
03841 
03842    ARGS_SO_FAR is the size of args previously pushed for this call.
03843 
03844    REG_PARM_STACK_SPACE is nonzero if functions require stack space
03845    for arguments passed in registers.  If nonzero, it will be the number
03846    of bytes required.  */
03847 
03848 void
03849 emit_push_insn (x, mode, type, size, align, partial, reg, extra,
03850     args_addr, args_so_far, reg_parm_stack_space,
03851     alignment_pad)
03852      rtx x;
03853      enum machine_mode mode;
03854      tree type;
03855      rtx size;
03856      unsigned int align;
03857      int partial;
03858      rtx reg;
03859      int extra;
03860      rtx args_addr;
03861      rtx args_so_far;
03862      int reg_parm_stack_space;
03863      rtx alignment_pad;
03864 {
03865   rtx xinner;
03866   enum direction stack_direction
03867 #ifdef STACK_GROWS_DOWNWARD
03868     = downward;
03869 #else
03870     = upward;
03871 #endif
03872 
03873   /* Decide where to pad the argument: `downward' for below,
03874      `upward' for above, or `none' for don't pad it.
03875      Default is below for small data on big-endian machines; else above.  */
03876   enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
03877 
03878   /* Invert direction if stack is post-decrement.
03879      FIXME: why?  */
03880   if (STACK_PUSH_CODE == POST_DEC)
03881     if (where_pad != none)
03882       where_pad = (where_pad == downward ? upward : downward);
03883 
03884   xinner = x = protect_from_queue (x, 0);
03885 
03886   if (mode == BLKmode)
03887     {
03888       /* Copy a block into the stack, entirely or partially.  */
03889 
03890       rtx temp;
03891       int used = partial * UNITS_PER_WORD;
03892       int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
03893       int skip;
03894 
03895       if (size == 0)
03896   abort ();
03897 
03898       used -= offset;
03899 
03900       /* USED is now the # of bytes we need not copy to the stack
03901    because registers will take care of them.  */
03902 
03903       if (partial != 0)
03904   xinner = adjust_address (xinner, BLKmode, used);
03905 
03906       /* If the partial register-part of the arg counts in its stack size,
03907    skip the part of stack space corresponding to the registers.
03908    Otherwise, start copying to the beginning of the stack space,
03909    by setting SKIP to 0.  */
03910       skip = (reg_parm_stack_space == 0) ? 0 : used;
03911 
03912 #ifdef PUSH_ROUNDING
03913       /* Do it with several push insns if that doesn't take lots of insns
03914    and if there is no difficulty with push insns that skip bytes
03915    on the stack for alignment purposes.  */
03916       if (args_addr == 0
03917     && PUSH_ARGS
03918     && GET_CODE (size) == CONST_INT
03919     && skip == 0
03920     && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
03921     /* Here we avoid the case of a structure whose weak alignment
03922        forces many pushes of a small amount of data,
03923        and such small pushes do rounding that causes trouble.  */
03924     && ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
03925         || align >= BIGGEST_ALIGNMENT
03926         || (PUSH_ROUNDING (align / BITS_PER_UNIT)
03927       == (align / BITS_PER_UNIT)))
03928     && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
03929   {
03930     /* Push padding now if padding above and stack grows down,
03931        or if padding below and stack grows up.
03932        But if space already allocated, this has already been done.  */
03933     if (extra && args_addr == 0
03934         && where_pad != none && where_pad != stack_direction)
03935       anti_adjust_stack (GEN_INT (extra));
03936 
03937     move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0);
03938   }
03939       else
03940 #endif /* PUSH_ROUNDING  */
03941   {
03942     rtx target;
03943 
03944     /* Otherwise make space on the stack and copy the data
03945        to the address of that space.  */
03946 
03947     /* Deduct words put into registers from the size we must copy.  */
03948     if (partial != 0)
03949       {
03950         if (GET_CODE (size) == CONST_INT)
03951     size = GEN_INT (INTVAL (size) - used);
03952         else
03953     size = expand_binop (GET_MODE (size), sub_optab, size,
03954              GEN_INT (used), NULL_RTX, 0,
03955              OPTAB_LIB_WIDEN);
03956       }
03957 
03958     /* Get the address of the stack space.
03959        In this case, we do not deal with EXTRA separately.
03960        A single stack adjust will do.  */
03961     if (! args_addr)
03962       {
03963         temp = push_block (size, extra, where_pad == downward);
03964         extra = 0;
03965       }
03966     else if (GET_CODE (args_so_far) == CONST_INT)
03967       temp = memory_address (BLKmode,
03968            plus_constant (args_addr,
03969               skip + INTVAL (args_so_far)));
03970     else
03971       temp = memory_address (BLKmode,
03972            plus_constant (gen_rtx_PLUS (Pmode,
03973                 args_addr,
03974                 args_so_far),
03975               skip));
03976 
03977     if (!ACCUMULATE_OUTGOING_ARGS)
03978       {
03979         /* If the source is referenced relative to the stack pointer,
03980      copy it to another register to stabilize it.  We do not need
03981      to do this if we know that we won't be changing sp.  */
03982 
03983         if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
03984       || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
03985     temp = copy_to_reg (temp);
03986       }
03987 
03988     target = gen_rtx_MEM (BLKmode, temp);
03989 
03990     if (type != 0)
03991       {
03992         set_mem_attributes (target, type, 1);
03993         /* Function incoming arguments may overlap with sibling call
03994      outgoing arguments and we cannot allow reordering of reads
03995      from function arguments with stores to outgoing arguments
03996      of sibling calls.  */
03997         set_mem_alias_set (target, 0);
03998       }
03999 
04000     /* ALIGN may well be better aligned than TYPE, e.g. due to
04001        PARM_BOUNDARY.  Assume the caller isn't lying.  */
04002     set_mem_align (target, align);
04003 
04004     emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
04005   }
04006     }
04007   else if (partial > 0)
04008     {
04009       /* Scalar partly in registers.  */
04010 
04011       int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
04012       int i;
04013       int not_stack;
04014       /* # words of start of argument
04015    that we must make space for but need not store.  */
04016       int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
04017       int args_offset = INTVAL (args_so_far);
04018       int skip;
04019 
04020       /* Push padding now if padding above and stack grows down,
04021    or if padding below and stack grows up.
04022    But if space already allocated, this has already been done.  */
04023       if (extra && args_addr == 0
04024     && where_pad != none && where_pad != stack_direction)
04025   anti_adjust_stack (GEN_INT (extra));
04026 
04027       /* If we make space by pushing it, we might as well push
04028    the real data.  Otherwise, we can leave OFFSET nonzero
04029    and leave the space uninitialized.  */
04030       if (args_addr == 0)
04031   offset = 0;
04032 
04033       /* Now NOT_STACK gets the number of words that we don't need to
04034    allocate on the stack.  */
04035       not_stack = partial - offset;
04036 
04037       /* If the partial register-part of the arg counts in its stack size,
04038    skip the part of stack space corresponding to the registers.
04039    Otherwise, start copying to the beginning of the stack space,
04040    by setting SKIP to 0.  */
04041       skip = (reg_parm_stack_space == 0) ? 0 : not_stack;
04042 
04043       if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
04044   x = validize_mem (force_const_mem (mode, x));
04045 
04046       /* If X is a hard register in a non-integer mode, copy it into a pseudo;
04047    SUBREGs of such registers are not allowed.  */
04048       if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER
04049      && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))
04050   x = copy_to_reg (x);
04051 
04052       /* Loop over all the words allocated on the stack for this arg.  */
04053       /* We can do it by words, because any scalar bigger than a word
04054    has a size a multiple of a word.  */
04055 #ifndef PUSH_ARGS_REVERSED
04056       for (i = not_stack; i < size; i++)
04057 #else
04058       for (i = size - 1; i >= not_stack; i--)
04059 #endif
04060   if (i >= not_stack + offset)
04061     emit_push_insn (operand_subword_force (x, i, mode),
04062         word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
04063         0, args_addr,
04064         GEN_INT (args_offset + ((i - not_stack + skip)
04065               * UNITS_PER_WORD)),
04066         reg_parm_stack_space, alignment_pad);
04067     }
04068   else
04069     {
04070       rtx addr;
04071       rtx target = NULL_RTX;
04072       rtx dest;
04073 
04074       /* Push padding now if padding above and stack grows down,
04075    or if padding below and stack grows up.
04076    But if space already allocated, this has already been done.  */
04077       if (extra && args_addr == 0
04078     && where_pad != none && where_pad != stack_direction)
04079   anti_adjust_stack (GEN_INT (extra));
04080 
04081 #ifdef PUSH_ROUNDING
04082       if (args_addr == 0 && PUSH_ARGS)
04083   emit_single_push_insn (mode, x, type);
04084       else
04085 #endif
04086   {
04087     if (GET_CODE (args_so_far) == CONST_INT)
04088       addr
04089         = memory_address (mode,
04090         plus_constant (args_addr,
04091                  INTVAL (args_so_far)));
04092     else
04093       addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
04094                    args_so_far));
04095     target = addr;
04096     dest = gen_rtx_MEM (mode, addr);
04097     if (type != 0)
04098       {
04099         set_mem_attributes (dest, type, 1);
04100         /* Function incoming arguments may overlap with sibling call
04101      outgoing arguments and we cannot allow reordering of reads
04102      from function arguments with stores to outgoing arguments
04103      of sibling calls.  */
04104         set_mem_alias_set (dest, 0);
04105       }
04106 
04107     emit_move_insn (dest, x);
04108   }
04109     }
04110 
04111   /* If part should go in registers, copy that part
04112      into the appropriate registers.  Do this now, at the end,
04113      since mem-to-mem copies above may do function calls.  */
04114   if (partial > 0 && reg != 0)
04115     {
04116       /* Handle calls that pass values in multiple non-contiguous locations.
04117    The Irix 6 ABI has examples of this.  */
04118       if (GET_CODE (reg) == PARALLEL)
04119   emit_group_load (reg, x, -1);  /* ??? size? */
04120       else
04121   move_block_to_reg (REGNO (reg), x, partial, mode);
04122     }
04123 
04124   if (extra && args_addr == 0 && where_pad == stack_direction)
04125     anti_adjust_stack (GEN_INT (extra));
04126 
04127   if (alignment_pad && args_addr == 0)
04128     anti_adjust_stack (alignment_pad);
04129 }
04130 
04131 /* Return X if X can be used as a subtarget in a sequence of arithmetic
04132    operations.  */
04133 
04134 static rtx
04135 get_subtarget (x)
04136      rtx x;
04137 {
04138   return ((x == 0
04139      /* Only registers can be subtargets.  */
04140      || GET_CODE (x) != REG
04141      /* If the register is readonly, it can't be set more than once.  */
04142      || RTX_UNCHANGING_P (x)
04143      /* Don't use hard regs to avoid extending their life.  */
04144      || REGNO (x) < FIRST_PSEUDO_REGISTER
04145      /* Avoid subtargets inside loops,
04146         since they hide some invariant expressions.  */
04147      || preserve_subexpressions_p ())
04148     ? 0 : x);
04149 }
04150 
04151 /* Expand an assignment that stores the value of FROM into TO.
04152    If WANT_VALUE is nonzero, return an rtx for the value of TO.
04153    (This may contain a QUEUED rtx;
04154    if the value is constant, this rtx is a constant.)
04155    Otherwise, the returned value is NULL_RTX.
04156 
04157    SUGGEST_REG is no longer actually used.
04158    It used to mean, copy the value through a register
04159    and return that register, if that is possible.
04160    We now use WANT_VALUE to decide whether to do this.  */
04161 
04162 rtx
04163 expand_assignment (to, from, want_value, suggest_reg)
04164      tree to, from;
04165      int want_value;
04166      int suggest_reg ATTRIBUTE_UNUSED;
04167 {
04168   rtx to_rtx = 0;
04169   rtx result;
04170 
04171   /* Don't crash if the lhs of the assignment was erroneous.  */
04172 
04173   if (TREE_CODE (to) == ERROR_MARK)
04174     {
04175       result = expand_expr (from, NULL_RTX, VOIDmode, 0);
04176       return want_value ? result : NULL_RTX;
04177     }
04178 
04179   /* Assignment of a structure component needs special treatment
04180      if the structure component's rtx is not simply a MEM.
04181      Assignment of an array element at a constant index, and assignment of
04182      an array element in an unaligned packed structure field, has the same
04183      problem.  */
04184 
04185   if (TREE_CODE (to) == COMPONENT_REF || TREE_CODE (to) == BIT_FIELD_REF
04186       || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF
04187       || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
04188     {
04189       enum machine_mode mode1;
04190       HOST_WIDE_INT bitsize, bitpos;
04191       rtx orig_to_rtx;
04192       tree offset;
04193       int unsignedp;
04194       int volatilep = 0;
04195       tree tem;
04196 
04197       push_temp_slots ();
04198       tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
04199          &unsignedp, &volatilep);
04200 
04201       /* If we are going to use store_bit_field and extract_bit_field,
04202    make sure to_rtx will be safe for multiple use.  */
04203 
04204       if (mode1 == VOIDmode && want_value)
04205   tem = stabilize_reference (tem);
04206 
04207       orig_to_rtx = to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
04208 
04209       if (offset != 0)
04210   {
04211     rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
04212 
04213     if (GET_CODE (to_rtx) != MEM)
04214       abort ();
04215 
04216 #ifdef POINTERS_EXTEND_UNSIGNED
04217     if (GET_MODE (offset_rtx) != Pmode)
04218       offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
04219 #else
04220     if (GET_MODE (offset_rtx) != ptr_mode)
04221       offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
04222 #endif
04223 
04224     /* A constant address in TO_RTX can have VOIDmode, we must not try
04225        to call force_reg for that case.  Avoid that case.  */
04226     if (GET_CODE (to_rtx) == MEM
04227         && GET_MODE (to_rtx) == BLKmode
04228         && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
04229         && bitsize > 0
04230         && (bitpos % bitsize) == 0
04231         && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
04232         && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
04233       {
04234         to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
04235         bitpos = 0;
04236       }
04237 
04238     to_rtx = offset_address (to_rtx, offset_rtx,
04239            highest_pow2_factor_for_type (TREE_TYPE (to),
04240                  offset));
04241   }
04242 
04243       if (GET_CODE (to_rtx) == MEM)
04244   {
04245     /* If the field is at offset zero, we could have been given the
04246        DECL_RTX of the parent struct.  Don't munge it.  */
04247     to_rtx = shallow_copy_rtx (to_rtx);
04248 
04249     set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
04250   }
04251 
04252       /* Deal with volatile and readonly fields.  The former is only done
04253    for MEM.  Also set MEM_KEEP_ALIAS_SET_P if needed.  */
04254       if (volatilep && GET_CODE (to_rtx) == MEM)
04255   {
04256     if (to_rtx == orig_to_rtx)
04257       to_rtx = copy_rtx (to_rtx);
04258     MEM_VOLATILE_P (to_rtx) = 1;
04259   }
04260 
04261       if (TREE_CODE (to) == COMPONENT_REF
04262     && TREE_READONLY (TREE_OPERAND (to, 1)))
04263   {
04264     if (to_rtx == orig_to_rtx)
04265       to_rtx = copy_rtx (to_rtx);
04266     RTX_UNCHANGING_P (to_rtx) = 1;
04267   }
04268 
04269       if (GET_CODE (to_rtx) == MEM && ! can_address_p (to))
04270   {
04271     if (to_rtx == orig_to_rtx)
04272       to_rtx = copy_rtx (to_rtx);
04273     MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
04274   }
04275 
04276       result = store_field (to_rtx, bitsize, bitpos, mode1, from,
04277           (want_value
04278            /* Spurious cast for HPUX compiler.  */
04279            ? ((enum machine_mode)
04280         TYPE_MODE (TREE_TYPE (to)))
04281            : VOIDmode),
04282           unsignedp, TREE_TYPE (tem), get_alias_set (to));
04283 
04284       preserve_temp_slots (result);
04285       free_temp_slots ();
04286       pop_temp_slots ();
04287 
04288       /* If the value is meaningful, convert RESULT to the proper mode.
04289    Otherwise, return nothing.  */
04290       return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
04291             TYPE_MODE (TREE_TYPE (from)),
04292             result,
04293             TREE_UNSIGNED (TREE_TYPE (to)))
04294         : NULL_RTX);
04295     }
04296 
04297   /* If the rhs is a function call and its value is not an aggregate,
04298      call the function before we start to compute the lhs.
04299      This is needed for correct code for cases such as
04300      val = setjmp (buf) on machines where reference to val
04301      requires loading up part of an address in a separate insn.
04302 
04303      Don't do this if TO is a VAR_DECL or PARM_DECL whose DECL_RTL is REG
04304      since it might be a promoted variable where the zero- or sign- extension
04305      needs to be done.  Handling this in the normal way is safe because no
04306      computation is done before the call.  */
04307   if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from)
04308       && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
04309       && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
04310       && GET_CODE (DECL_RTL (to)) == REG))
04311     {
04312       rtx value;
04313 
04314       push_temp_slots ();
04315       value = expand_expr (from, NULL_RTX, VOIDmode, 0);
04316       if (to_rtx == 0)
04317   to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
04318 
04319       /* Handle calls that return values in multiple non-contiguous locations.
04320    The Irix 6 ABI has examples of this.  */
04321       if (GET_CODE (to_rtx) == PARALLEL)
04322   emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
04323       else if (GET_MODE (to_rtx) == BLKmode)
04324   emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
04325       else
04326   {
04327 #ifdef POINTERS_EXTEND_UNSIGNED
04328     if (POINTER_TYPE_P (TREE_TYPE (to))
04329         && GET_MODE (to_rtx) != GET_MODE (value))
04330       value = convert_memory_address (GET_MODE (to_rtx), value);
04331 #endif
04332     emit_move_insn (to_rtx, value);
04333   }
04334       preserve_temp_slots (to_rtx);
04335       free_temp_slots ();
04336       pop_temp_slots ();
04337       return want_value ? to_rtx : NULL_RTX;
04338     }
04339 
04340   /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.
04341      Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
04342 
04343   if (to_rtx == 0)
04344     to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
04345 
04346   /* Don't move directly into a return register.  */
04347   if (TREE_CODE (to) == RESULT_DECL
04348       && (GET_CODE (to_rtx) == REG || GET_CODE (to_rtx) == PARALLEL))
04349     {
04350       rtx temp;
04351 
04352       push_temp_slots ();
04353       temp = expand_expr (from, 0, GET_MODE (to_rtx), 0);
04354 
04355       if (GET_CODE (to_rtx) == PARALLEL)
04356   emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)));
04357       else
04358   emit_move_insn (to_rtx, temp);
04359 
04360       preserve_temp_slots (to_rtx);
04361       free_temp_slots ();
04362       pop_temp_slots ();
04363       return want_value ? to_rtx : NULL_RTX;
04364     }
04365 
04366   /* In case we are returning the contents of an object which overlaps
04367      the place the value is being stored, use a safe function when copying
04368      a value through a pointer into a structure value return block.  */
04369   if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
04370       && current_function_returns_struct
04371       && !current_function_returns_pcc_struct)
04372     {
04373       rtx from_rtx, size;
04374 
04375       push_temp_slots ();
04376       size = expr_size (from);
04377       from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
04378 
04379       if (TARGET_MEM_FUNCTIONS)
04380   emit_library_call (memmove_libfunc, LCT_NORMAL,
04381          VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
04382          XEXP (from_rtx, 0), Pmode,
04383          convert_to_mode (TYPE_MODE (sizetype),
04384               size, TREE_UNSIGNED (sizetype)),
04385          TYPE_MODE (sizetype));
04386       else
04387         emit_library_call (bcopy_libfunc, LCT_NORMAL,
04388          VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
04389          XEXP (to_rtx, 0), Pmode,
04390          convert_to_mode (TYPE_MODE (integer_type_node),
04391               size,
04392               TREE_UNSIGNED (integer_type_node)),
04393          TYPE_MODE (integer_type_node));
04394 
04395       preserve_temp_slots (to_rtx);
04396       free_temp_slots ();
04397       pop_temp_slots ();
04398       return want_value ? to_rtx : NULL_RTX;
04399     }
04400 
04401   /* Compute FROM and store the value in the rtx we got.  */
04402 
04403   push_temp_slots ();
04404   result = store_expr (from, to_rtx, want_value);
04405   preserve_temp_slots (result);
04406   free_temp_slots ();
04407   pop_temp_slots ();
04408   return want_value ? result : NULL_RTX;
04409 }
04410 
04411 /* Generate code for computing expression EXP,
04412    and storing the value into TARGET.
04413    TARGET may contain a QUEUED rtx.
04414 
04415    If WANT_VALUE & 1 is nonzero, return a copy of the value
04416    not in TARGET, so that we can be sure to use the proper
04417    value in a containing expression even if TARGET has something
04418    else stored in it.  If possible, we copy the value through a pseudo
04419    and return that pseudo.  Or, if the value is constant, we try to
04420    return the constant.  In some cases, we return a pseudo
04421    copied *from* TARGET.
04422 
04423    If the mode is BLKmode then we may return TARGET itself.
04424    It turns out that in BLKmode it doesn't cause a problem.
04425    because C has no operators that could combine two different
04426    assignments into the same BLKmode object with different values
04427    with no sequence point.  Will other languages need this to
04428    be more thorough?
04429 
04430    If WANT_VALUE & 1 is 0, we return NULL, to make sure
04431    to catch quickly any cases where the caller uses the value
04432    and fails to set WANT_VALUE.
04433 
04434    If WANT_VALUE & 2 is set, this is a store into a call param on the
04435    stack, and block moves may need to be treated specially.  */
04436 
04437 rtx
04438 store_expr (exp, target, want_value)
04439      tree exp;
04440      rtx target;
04441      int want_value;
04442 {
04443   rtx temp;
04444   int dont_return_target = 0;
04445   int dont_store_target = 0;
04446 
04447   if (VOID_TYPE_P (TREE_TYPE (exp)))
04448     {
04449       /* C++ can generate ?: expressions with a throw expression in one
04450    branch and an rvalue in the other. Here, we resolve attempts to
04451    store the throw expression's nonexistant result. */
04452       if (want_value)
04453   abort ();
04454       expand_expr (exp, const0_rtx, VOIDmode, 0);
04455       return NULL_RTX;
04456     }
04457   if (TREE_CODE (exp) == COMPOUND_EXPR)
04458     {
04459       /* Perform first part of compound expression, then assign from second
04460    part.  */
04461       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
04462        want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04463       emit_queue ();
04464       return store_expr (TREE_OPERAND (exp, 1), target, want_value);
04465     }
04466   else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
04467     {
04468       /* For conditional expression, get safe form of the target.  Then
04469    test the condition, doing the appropriate assignment on either
04470    side.  This avoids the creation of unnecessary temporaries.
04471    For non-BLKmode, it is more efficient not to do this.  */
04472 
04473       rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
04474 
04475       emit_queue ();
04476       target = protect_from_queue (target, 1);
04477 
04478       do_pending_stack_adjust ();
04479       NO_DEFER_POP;
04480       jumpifnot (TREE_OPERAND (exp, 0), lab1);
04481       start_cleanup_deferral ();
04482       store_expr (TREE_OPERAND (exp, 1), target, want_value & 2);
04483       end_cleanup_deferral ();
04484       emit_queue ();
04485       emit_jump_insn (gen_jump (lab2));
04486       emit_barrier ();
04487       emit_label (lab1);
04488       start_cleanup_deferral ();
04489       store_expr (TREE_OPERAND (exp, 2), target, want_value & 2);
04490       end_cleanup_deferral ();
04491       emit_queue ();
04492       emit_label (lab2);
04493       OK_DEFER_POP;
04494 
04495       return want_value & 1 ? target : NULL_RTX;
04496     }
04497   else if (queued_subexp_p (target))
04498     /* If target contains a postincrement, let's not risk
04499        using it as the place to generate the rhs.  */
04500     {
04501       if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
04502   {
04503     /* Expand EXP into a new pseudo.  */
04504     temp = gen_reg_rtx (GET_MODE (target));
04505     temp = expand_expr (exp, temp, GET_MODE (target),
04506             (want_value & 2
04507              ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04508   }
04509       else
04510   temp = expand_expr (exp, NULL_RTX, GET_MODE (target),
04511           (want_value & 2
04512            ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04513 
04514       /* If target is volatile, ANSI requires accessing the value
04515    *from* the target, if it is accessed.  So make that happen.
04516    In no case return the target itself.  */
04517       if (! MEM_VOLATILE_P (target) && (want_value & 1) != 0)
04518   dont_return_target = 1;
04519     }
04520   else if ((want_value & 1) != 0
04521      && GET_CODE (target) == MEM
04522      && ! MEM_VOLATILE_P (target)
04523      && GET_MODE (target) != BLKmode)
04524     /* If target is in memory and caller wants value in a register instead,
04525        arrange that.  Pass TARGET as target for expand_expr so that,
04526        if EXP is another assignment, WANT_VALUE will be nonzero for it.
04527        We know expand_expr will not use the target in that case.
04528        Don't do this if TARGET is volatile because we are supposed
04529        to write it and then read it.  */
04530     {
04531       temp = expand_expr (exp, target, GET_MODE (target),
04532         want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04533       if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
04534   {
04535     /* If TEMP is already in the desired TARGET, only copy it from
04536        memory and don't store it there again.  */
04537     if (temp == target
04538         || (rtx_equal_p (temp, target)
04539       && ! side_effects_p (temp) && ! side_effects_p (target)))
04540       dont_store_target = 1;
04541     temp = copy_to_reg (temp);
04542   }
04543       dont_return_target = 1;
04544     }
04545   else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
04546     /* If this is a scalar in a register that is stored in a wider mode
04547        than the declared mode, compute the result into its declared mode
04548        and then convert to the wider mode.  Our value is the computed
04549        expression.  */
04550     {
04551       rtx inner_target = 0;
04552 
04553       /* If we don't want a value, we can do the conversion inside EXP,
04554    which will often result in some optimizations.  Do the conversion
04555    in two steps: first change the signedness, if needed, then
04556    the extend.  But don't do this if the type of EXP is a subtype
04557    of something else since then the conversion might involve
04558    more than just converting modes.  */
04559       if ((want_value & 1) == 0
04560     && INTEGRAL_TYPE_P (TREE_TYPE (exp))
04561     && TREE_TYPE (TREE_TYPE (exp)) == 0)
04562   {
04563     if (TREE_UNSIGNED (TREE_TYPE (exp))
04564         != SUBREG_PROMOTED_UNSIGNED_P (target))
04565       exp = convert
04566         ((*lang_hooks.types.signed_or_unsigned_type)
04567          (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
04568 
04569     exp = convert ((*lang_hooks.types.type_for_mode)
04570        (GET_MODE (SUBREG_REG (target)),
04571         SUBREG_PROMOTED_UNSIGNED_P (target)),
04572        exp);
04573 
04574     inner_target = SUBREG_REG (target);
04575   }
04576 
04577       temp = expand_expr (exp, inner_target, VOIDmode,
04578         want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04579 
04580       /* If TEMP is a volatile MEM and we want a result value, make
04581    the access now so it gets done only once.  Likewise if
04582    it contains TARGET.  */
04583       if (GET_CODE (temp) == MEM && (want_value & 1) != 0
04584     && (MEM_VOLATILE_P (temp)
04585         || reg_mentioned_p (SUBREG_REG (target), XEXP (temp, 0))))
04586   temp = copy_to_reg (temp);
04587 
04588       /* If TEMP is a VOIDmode constant, use convert_modes to make
04589    sure that we properly convert it.  */
04590       if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
04591   {
04592     temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
04593         temp, SUBREG_PROMOTED_UNSIGNED_P (target));
04594     temp = convert_modes (GET_MODE (SUBREG_REG (target)),
04595               GET_MODE (target), temp,
04596               SUBREG_PROMOTED_UNSIGNED_P (target));
04597   }
04598 
04599       convert_move (SUBREG_REG (target), temp,
04600         SUBREG_PROMOTED_UNSIGNED_P (target));
04601 
04602       /* If we promoted a constant, change the mode back down to match
04603    target.  Otherwise, the caller might get confused by a result whose
04604    mode is larger than expected.  */
04605 
04606       if ((want_value & 1) != 0 && GET_MODE (temp) != GET_MODE (target))
04607   {
04608     if (GET_MODE (temp) != VOIDmode)
04609       {
04610         temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
04611         SUBREG_PROMOTED_VAR_P (temp) = 1;
04612         SUBREG_PROMOTED_UNSIGNED_SET (temp,
04613     SUBREG_PROMOTED_UNSIGNED_P (target));
04614       }
04615     else
04616       temp = convert_modes (GET_MODE (target),
04617           GET_MODE (SUBREG_REG (target)),
04618           temp, SUBREG_PROMOTED_UNSIGNED_P (target));
04619   }
04620 
04621       return want_value & 1 ? temp : NULL_RTX;
04622     }
04623   else
04624     {
04625       temp = expand_expr (exp, target, GET_MODE (target),
04626         want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04627       /* Return TARGET if it's a specified hardware register.
04628    If TARGET is a volatile mem ref, either return TARGET
04629    or return a reg copied *from* TARGET; ANSI requires this.
04630 
04631    Otherwise, if TEMP is not TARGET, return TEMP
04632    if it is constant (for efficiency),
04633    or if we really want the correct value.  */
04634       if (!(target && GET_CODE (target) == REG
04635       && REGNO (target) < FIRST_PSEUDO_REGISTER)
04636     && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
04637     && ! rtx_equal_p (temp, target)
04638     && (CONSTANT_P (temp) || (want_value & 1) != 0))
04639   dont_return_target = 1;
04640     }
04641 
04642   /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
04643      the same as that of TARGET, adjust the constant.  This is needed, for
04644      example, in case it is a CONST_DOUBLE and we want only a word-sized
04645      value.  */
04646   if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
04647       && TREE_CODE (exp) != ERROR_MARK
04648       && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
04649     temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
04650         temp, TREE_UNSIGNED (TREE_TYPE (exp)));
04651 
04652   /* If value was not generated in the target, store it there.
04653      Convert the value to TARGET's type first if necessary.
04654      If TEMP and TARGET compare equal according to rtx_equal_p, but
04655      one or both of them are volatile memory refs, we have to distinguish
04656      two cases:
04657      - expand_expr has used TARGET.  In this case, we must not generate
04658        another copy.  This can be detected by TARGET being equal according
04659        to == .
04660      - expand_expr has not used TARGET - that means that the source just
04661        happens to have the same RTX form.  Since temp will have been created
04662        by expand_expr, it will compare unequal according to == .
04663        We must generate a copy in this case, to reach the correct number
04664        of volatile memory references.  */
04665 
04666   if ((! rtx_equal_p (temp, target)
04667        || (temp != target && (side_effects_p (temp)
04668             || side_effects_p (target))))
04669       && TREE_CODE (exp) != ERROR_MARK
04670       && ! dont_store_target
04671    /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
04672       but TARGET is not valid memory reference, TEMP will differ
04673       from TARGET although it is really the same location.  */
04674       && (TREE_CODE_CLASS (TREE_CODE (exp)) != 'd'
04675     || target != DECL_RTL_IF_SET (exp))
04676       /* If there's nothing to copy, don't bother.  Don't call expr_size
04677    unless necessary, because some front-ends (C++) expr_size-hook
04678    aborts on objects that are not supposed to be bit-copied or
04679    bit-initialized.  */
04680       && expr_size (exp) != const0_rtx)
04681     {
04682       target = protect_from_queue (target, 1);
04683       if (GET_MODE (temp) != GET_MODE (target)
04684     && GET_MODE (temp) != VOIDmode)
04685   {
04686     int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
04687     if (dont_return_target)
04688       {
04689         /* In this case, we will return TEMP,
04690      so make sure it has the proper mode.
04691      But don't forget to store the value into TARGET.  */
04692         temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
04693         emit_move_insn (target, temp);
04694       }
04695     else
04696       convert_move (target, temp, unsignedp);
04697   }
04698 
04699       else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
04700   {
04701     /* Handle copying a string constant into an array.  The string
04702        constant may be shorter than the array.  So copy just the string's
04703        actual length, and clear the rest.  First get the size of the data
04704        type of the string, which is actually the size of the target.  */
04705     rtx size = expr_size (exp);
04706 
04707     if (GET_CODE (size) == CONST_INT
04708         && INTVAL (size) < TREE_STRING_LENGTH (exp))
04709       emit_block_move (target, temp, size,
04710            (want_value & 2
04711             ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04712     else
04713       {
04714         /* Compute the size of the data to copy from the string.  */
04715         tree copy_size
04716     = size_binop (MIN_EXPR,
04717             make_tree (sizetype, size),
04718             size_int (TREE_STRING_LENGTH (exp)));
04719         rtx copy_size_rtx
04720     = expand_expr (copy_size, NULL_RTX, VOIDmode,
04721              (want_value & 2
04722         ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04723         rtx label = 0;
04724 
04725         /* Copy that much.  */
04726         copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
04727                  TREE_UNSIGNED (sizetype));
04728         emit_block_move (target, temp, copy_size_rtx,
04729              (want_value & 2
04730         ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04731 
04732         /* Figure out how much is left in TARGET that we have to clear.
04733      Do all calculations in ptr_mode.  */
04734         if (GET_CODE (copy_size_rtx) == CONST_INT)
04735     {
04736       size = plus_constant (size, -INTVAL (copy_size_rtx));
04737       target = adjust_address (target, BLKmode,
04738              INTVAL (copy_size_rtx));
04739     }
04740         else
04741     {
04742       size = expand_binop (TYPE_MODE (sizetype), sub_optab, size,
04743                copy_size_rtx, NULL_RTX, 0,
04744                OPTAB_LIB_WIDEN);
04745 
04746 #ifdef POINTERS_EXTEND_UNSIGNED
04747       if (GET_MODE (copy_size_rtx) != Pmode)
04748         copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx,
04749                  TREE_UNSIGNED (sizetype));
04750 #endif
04751 
04752       target = offset_address (target, copy_size_rtx,
04753              highest_pow2_factor (copy_size));
04754       label = gen_label_rtx ();
04755       emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
04756              GET_MODE (size), 0, label);
04757     }
04758 
04759         if (size != const0_rtx)
04760     clear_storage (target, size);
04761 
04762         if (label)
04763     emit_label (label);
04764       }
04765   }
04766       /* Handle calls that return values in multiple non-contiguous locations.
04767    The Irix 6 ABI has examples of this.  */
04768       else if (GET_CODE (target) == PARALLEL)
04769   emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
04770       else if (GET_MODE (temp) == BLKmode)
04771   emit_block_move (target, temp, expr_size (exp),
04772        (want_value & 2
04773         ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04774       else
04775   emit_move_insn (target, temp);
04776     }
04777 
04778   /* If we don't want a value, return NULL_RTX.  */
04779   if ((want_value & 1) == 0)
04780     return NULL_RTX;
04781 
04782   /* If we are supposed to return TEMP, do so as long as it isn't a MEM.
04783      ??? The latter test doesn't seem to make sense.  */
04784   else if (dont_return_target && GET_CODE (temp) != MEM)
04785     return temp;
04786 
04787   /* Return TARGET itself if it is a hard register.  */
04788   else if ((want_value & 1) != 0
04789      && GET_MODE (target) != BLKmode
04790      && ! (GET_CODE (target) == REG
04791      && REGNO (target) < FIRST_PSEUDO_REGISTER))
04792     return copy_to_reg (target);
04793 
04794   else
04795     return target;
04796 }
04797 
04798 /* Return 1 if EXP just contains zeros.  */
04799 
04800 static int
04801 is_zeros_p (exp)
04802      tree exp;
04803 {
04804   tree elt;
04805 
04806   switch (TREE_CODE (exp))
04807     {
04808     case CONVERT_EXPR:
04809     case NOP_EXPR:
04810     case NON_LVALUE_EXPR:
04811     case VIEW_CONVERT_EXPR:
04812       return is_zeros_p (TREE_OPERAND (exp, 0));
04813 
04814     case INTEGER_CST:
04815       return integer_zerop (exp);
04816 
04817     case COMPLEX_CST:
04818       return
04819   is_zeros_p (TREE_REALPART (exp)) && is_zeros_p (TREE_IMAGPART (exp));
04820 
04821     case REAL_CST:
04822       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0);
04823 
04824     case VECTOR_CST:
04825       for (elt = TREE_VECTOR_CST_ELTS (exp); elt;
04826      elt = TREE_CHAIN (elt))
04827   if (!is_zeros_p (TREE_VALUE (elt)))
04828     return 0;
04829 
04830       return 1;
04831 
04832     case CONSTRUCTOR:
04833       if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
04834   return CONSTRUCTOR_ELTS (exp) == NULL_TREE;
04835       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
04836   if (! is_zeros_p (TREE_VALUE (elt)))
04837     return 0;
04838 
04839       return 1;
04840 
04841     default:
04842       return 0;
04843     }
04844 }
04845 
04846 /* Return 1 if EXP contains mostly (3/4)  zeros.  */
04847 
04848 static int
04849 mostly_zeros_p (exp)
04850      tree exp;
04851 {
04852   if (TREE_CODE (exp) == CONSTRUCTOR)
04853     {
04854       int elts = 0, zeros = 0;
04855       tree elt = CONSTRUCTOR_ELTS (exp);
04856       if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
04857   {
04858     /* If there are no ranges of true bits, it is all zero.  */
04859     return elt == NULL_TREE;
04860   }
04861       for (; elt; elt = TREE_CHAIN (elt))
04862   {
04863     /* We do not handle the case where the index is a RANGE_EXPR,
04864        so the statistic will be somewhat inaccurate.
04865        We do make a more accurate count in store_constructor itself,
04866        so since this function is only used for nested array elements,
04867        this should be close enough.  */
04868     if (mostly_zeros_p (TREE_VALUE (elt)))
04869       zeros++;
04870     elts++;
04871   }
04872 
04873       return 4 * zeros >= 3 * elts;
04874     }
04875 
04876   return is_zeros_p (exp);
04877 }
04878 
04879 /* Helper function for store_constructor.
04880    TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
04881    TYPE is the type of the CONSTRUCTOR, not the element type.
04882    CLEARED is as for store_constructor.
04883    ALIAS_SET is the alias set to use for any stores.
04884 
04885    This provides a recursive shortcut back to store_constructor when it isn't
04886    necessary to go through store_field.  This is so that we can pass through
04887    the cleared field to let store_constructor know that we may not have to
04888    clear a substructure if the outer structure has already been cleared.  */
04889 
04890 static void
04891 store_constructor_field (target, bitsize, bitpos, mode, exp, type, cleared,
04892        alias_set)
04893      rtx target;
04894      unsigned HOST_WIDE_INT bitsize;
04895      HOST_WIDE_INT bitpos;
04896      enum machine_mode mode;
04897      tree exp, type;
04898      int cleared;
04899      int alias_set;
04900 {
04901   if (TREE_CODE (exp) == CONSTRUCTOR
04902       && bitpos % BITS_PER_UNIT == 0
04903       /* If we have a nonzero bitpos for a register target, then we just
04904    let store_field do the bitfield handling.  This is unlikely to
04905    generate unnecessary clear instructions anyways.  */
04906       && (bitpos == 0 || GET_CODE (target) == MEM))
04907     {
04908       if (GET_CODE (target) == MEM)
04909   target
04910     = adjust_address (target,
04911           GET_MODE (target) == BLKmode
04912           || 0 != (bitpos
04913              % GET_MODE_ALIGNMENT (GET_MODE (target)))
04914           ? BLKmode : VOIDmode, bitpos / BITS_PER_UNIT);
04915 
04916 
04917       /* Update the alias set, if required.  */
04918       if (GET_CODE (target) == MEM && ! MEM_KEEP_ALIAS_SET_P (target)
04919     && MEM_ALIAS_SET (target) != 0)
04920   {
04921     target = copy_rtx (target);
04922     set_mem_alias_set (target, alias_set);
04923   }
04924 
04925       store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
04926     }
04927   else
04928     store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
04929      alias_set);
04930 }
04931 
04932 /* Store the value of constructor EXP into the rtx TARGET.
04933    TARGET is either a REG or a MEM; we know it cannot conflict, since
04934    safe_from_p has been called.
04935    CLEARED is true if TARGET is known to have been zero'd.
04936    SIZE is the number of bytes of TARGET we are allowed to modify: this
04937    may not be the same as the size of EXP if we are assigning to a field
04938    which has been packed to exclude padding bits.  */
04939 
04940 static void
04941 store_constructor (exp, target, cleared, size)
04942      tree exp;
04943      rtx target;
04944      int cleared;
04945      HOST_WIDE_INT size;
04946 {
04947   tree type = TREE_TYPE (exp);
04948 #ifdef WORD_REGISTER_OPERATIONS
04949   HOST_WIDE_INT exp_size = int_size_in_bytes (type);
04950 #endif
04951 
04952   if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
04953       || TREE_CODE (type) == QUAL_UNION_TYPE)
04954     {
04955       tree elt;
04956 
04957       /* If size is zero or the target is already cleared, do nothing.  */
04958       if (size == 0 || cleared)
04959   cleared = 1;
04960       /* We either clear the aggregate or indicate the value is dead.  */
04961       else if ((TREE_CODE (type) == UNION_TYPE
04962     || TREE_CODE (type) == QUAL_UNION_TYPE)
04963          && ! CONSTRUCTOR_ELTS (exp))
04964   /* If the constructor is empty, clear the union.  */
04965   {
04966     clear_storage (target, expr_size (exp));
04967     cleared = 1;
04968   }
04969 
04970       /* If we are building a static constructor into a register,
04971    set the initial value as zero so we can fold the value into
04972    a constant.  But if more than one register is involved,
04973    this probably loses.  */
04974       else if (GET_CODE (target) == REG && TREE_STATIC (exp)
04975          && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
04976   {
04977     emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
04978     cleared = 1;
04979   }
04980 
04981       /* If the constructor has fewer fields than the structure
04982    or if we are initializing the structure to mostly zeros,
04983    clear the whole structure first.  Don't do this if TARGET is a
04984    register whose mode size isn't equal to SIZE since clear_storage
04985    can't handle this case.  */
04986       else if (((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type))
04987     || mostly_zeros_p (exp))
04988          && (GET_CODE (target) != REG
04989        || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
04990            == size)))
04991   {
04992     clear_storage (target, GEN_INT (size));
04993     cleared = 1;
04994   }
04995 
04996       if (! cleared)
04997   emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
04998 
04999       /* Store each element of the constructor into
05000    the corresponding field of TARGET.  */
05001 
05002       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
05003   {
05004     tree field = TREE_PURPOSE (elt);
05005     tree value = TREE_VALUE (elt);
05006     enum machine_mode mode;
05007     HOST_WIDE_INT bitsize;
05008     HOST_WIDE_INT bitpos = 0;
05009     int unsignedp;
05010     tree offset;
05011     rtx to_rtx = target;
05012 
05013     /* Just ignore missing fields.
05014        We cleared the whole structure, above,
05015        if any fields are missing.  */
05016     if (field == 0)
05017       continue;
05018 
05019     if (cleared && is_zeros_p (value))
05020       continue;
05021 
05022     if (host_integerp (DECL_SIZE (field), 1))
05023       bitsize = tree_low_cst (DECL_SIZE (field), 1);
05024     else
05025       bitsize = -1;
05026 
05027     unsignedp = TREE_UNSIGNED (field);
05028     mode = DECL_MODE (field);
05029     if (DECL_BIT_FIELD (field))
05030       mode = VOIDmode;
05031 
05032     offset = DECL_FIELD_OFFSET (field);
05033     if (host_integerp (offset, 0)
05034         && host_integerp (bit_position (field), 0))
05035       {
05036         bitpos = int_bit_position (field);
05037         offset = 0;
05038       }
05039     else
05040       bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
05041 
05042     if (offset)
05043       {
05044         rtx offset_rtx;
05045 
05046         if (contains_placeholder_p (offset))
05047     offset = build (WITH_RECORD_EXPR, sizetype,
05048         offset, make_tree (TREE_TYPE (exp), target));
05049 
05050         offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
05051         if (GET_CODE (to_rtx) != MEM)
05052     abort ();
05053 
05054 #ifdef POINTERS_EXTEND_UNSIGNED
05055         if (GET_MODE (offset_rtx) != Pmode)
05056     offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
05057 #else
05058         if (GET_MODE (offset_rtx) != ptr_mode)
05059     offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
05060 #endif
05061 
05062         to_rtx = offset_address (to_rtx, offset_rtx,
05063                highest_pow2_factor (offset));
05064       }
05065 
05066     if (TREE_READONLY (field))
05067       {
05068         if (GET_CODE (to_rtx) == MEM)
05069     to_rtx = copy_rtx (to_rtx);
05070 
05071         RTX_UNCHANGING_P (to_rtx) = 1;
05072       }
05073 
05074 #ifdef WORD_REGISTER_OPERATIONS
05075     /* If this initializes a field that is smaller than a word, at the
05076        start of a word, try to widen it to a full word.
05077        This special case allows us to output C++ member function
05078        initializations in a form that the optimizers can understand.  */
05079     if (GET_CODE (target) == REG
05080         && bitsize < BITS_PER_WORD
05081         && bitpos % BITS_PER_WORD == 0
05082         && GET_MODE_CLASS (mode) == MODE_INT
05083         && TREE_CODE (value) == INTEGER_CST
05084         && exp_size >= 0
05085         && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
05086       {
05087         tree type = TREE_TYPE (value);
05088 
05089         if (TYPE_PRECISION (type) < BITS_PER_WORD)
05090     {
05091       type = (*lang_hooks.types.type_for_size)
05092         (BITS_PER_WORD, TREE_UNSIGNED (type));
05093       value = convert (type, value);
05094     }
05095 
05096         if (BYTES_BIG_ENDIAN)
05097     value
05098       = fold (build (LSHIFT_EXPR, type, value,
05099          build_int_2 (BITS_PER_WORD - bitsize, 0)));
05100         bitsize = BITS_PER_WORD;
05101         mode = word_mode;
05102       }
05103 #endif
05104 
05105     if (GET_CODE (to_rtx) == MEM && !MEM_KEEP_ALIAS_SET_P (to_rtx)
05106         && DECL_NONADDRESSABLE_P (field))
05107       {
05108         to_rtx = copy_rtx (to_rtx);
05109         MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
05110       }
05111 
05112     store_constructor_field (to_rtx, bitsize, bitpos, mode,
05113            value, type, cleared,
05114            get_alias_set (TREE_TYPE (field)));
05115   }
05116     }
05117   else if (TREE_CODE (type) == ARRAY_TYPE
05118      || TREE_CODE (type) == VECTOR_TYPE)
05119     {
05120       tree elt;
05121       int i;
05122       int need_to_clear;
05123       tree domain = TYPE_DOMAIN (type);
05124       tree elttype = TREE_TYPE (type);
05125       int const_bounds_p;
05126       HOST_WIDE_INT minelt = 0;
05127       HOST_WIDE_INT maxelt = 0;
05128 
05129       /* Vectors are like arrays, but the domain is stored via an array
05130    type indirectly.  */
05131       if (TREE_CODE (type) == VECTOR_TYPE)
05132   {
05133     /* Note that although TYPE_DEBUG_REPRESENTATION_TYPE uses
05134        the same field as TYPE_DOMAIN, we are not guaranteed that
05135        it always will.  */
05136     domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
05137     domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
05138   }
05139 
05140       const_bounds_p = (TYPE_MIN_VALUE (domain)
05141       && TYPE_MAX_VALUE (domain)
05142       && host_integerp (TYPE_MIN_VALUE (domain), 0)
05143       && host_integerp (TYPE_MAX_VALUE (domain), 0));
05144 
05145       /* If we have constant bounds for the range of the type, get them.  */
05146       if (const_bounds_p)
05147   {
05148     minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
05149     maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
05150   }
05151 
05152       /* If the constructor has fewer elements than the array,
05153          clear the whole array first.  Similarly if this is
05154          static constructor of a non-BLKmode object.  */
05155       if (cleared || (GET_CODE (target) == REG && TREE_STATIC (exp)))
05156   need_to_clear = 1;
05157       else
05158   {
05159     HOST_WIDE_INT count = 0, zero_count = 0;
05160     need_to_clear = ! const_bounds_p;
05161 
05162     /* This loop is a more accurate version of the loop in
05163        mostly_zeros_p (it handles RANGE_EXPR in an index).
05164        It is also needed to check for missing elements.  */
05165     for (elt = CONSTRUCTOR_ELTS (exp);
05166          elt != NULL_TREE && ! need_to_clear;
05167          elt = TREE_CHAIN (elt))
05168       {
05169         tree index = TREE_PURPOSE (elt);
05170         HOST_WIDE_INT this_node_count;
05171 
05172         if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
05173     {
05174       tree lo_index = TREE_OPERAND (index, 0);
05175       tree hi_index = TREE_OPERAND (index, 1);
05176 
05177       if (! host_integerp (lo_index, 1)
05178           || ! host_integerp (hi_index, 1))
05179         {
05180           need_to_clear = 1;
05181           break;
05182         }
05183 
05184       this_node_count = (tree_low_cst (hi_index, 1)
05185              - tree_low_cst (lo_index, 1) + 1);
05186     }
05187         else
05188     this_node_count = 1;
05189 
05190         count += this_node_count;
05191         if (mostly_zeros_p (TREE_VALUE (elt)))
05192     zero_count += this_node_count;
05193       }
05194 
05195     /* Clear the entire array first if there are any missing elements,
05196        or if the incidence of zero elements is >= 75%.  */
05197     if (! need_to_clear
05198         && (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
05199       need_to_clear = 1;
05200   }
05201 
05202       if (need_to_clear && size > 0)
05203   {
05204     if (! cleared)
05205       {
05206         if (REG_P (target))
05207     emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
05208         else
05209     clear_storage (target, GEN_INT (size));
05210       }
05211     cleared = 1;
05212   }
05213       else if (REG_P (target))
05214   /* Inform later passes that the old value is dead.  */
05215   emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
05216 
05217       /* Store each element of the constructor into
05218    the corresponding element of TARGET, determined
05219    by counting the elements.  */
05220       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
05221      elt;
05222      elt = TREE_CHAIN (elt), i++)
05223   {
05224     enum machine_mode mode;
05225     HOST_WIDE_INT bitsize;
05226     HOST_WIDE_INT bitpos;
05227     int unsignedp;
05228     tree value = TREE_VALUE (elt);
05229     tree index = TREE_PURPOSE (elt);
05230     rtx xtarget = target;
05231 
05232     if (cleared && is_zeros_p (value))
05233       continue;
05234 
05235     unsignedp = TREE_UNSIGNED (elttype);
05236     mode = TYPE_MODE (elttype);
05237     if (mode == BLKmode)
05238       bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
05239            ? tree_low_cst (TYPE_SIZE (elttype), 1)
05240            : -1);
05241     else
05242       bitsize = GET_MODE_BITSIZE (mode);
05243 
05244     if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
05245       {
05246         tree lo_index = TREE_OPERAND (index, 0);
05247         tree hi_index = TREE_OPERAND (index, 1);
05248         rtx index_r, pos_rtx, hi_r, loop_top, loop_end;
05249         struct nesting *loop;
05250         HOST_WIDE_INT lo, hi, count;
05251         tree position;
05252 
05253         /* If the range is constant and "small", unroll the loop.  */
05254         if (const_bounds_p
05255       && host_integerp (lo_index, 0)
05256       && host_integerp (hi_index, 0)
05257       && (lo = tree_low_cst (lo_index, 0),
05258           hi = tree_low_cst (hi_index, 0),
05259           count = hi - lo + 1,
05260           (GET_CODE (target) != MEM
05261            || count <= 2
05262            || (host_integerp (TYPE_SIZE (elttype), 1)
05263          && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
05264              <= 40 * 8)))))
05265     {
05266       lo -= minelt;  hi -= minelt;
05267       for (; lo <= hi; lo++)
05268         {
05269           bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
05270 
05271           if (GET_CODE (target) == MEM
05272         && !MEM_KEEP_ALIAS_SET_P (target)
05273         && TREE_CODE (type) == ARRAY_TYPE
05274         && TYPE_NONALIASED_COMPONENT (type))
05275       {
05276         target = copy_rtx (target);
05277         MEM_KEEP_ALIAS_SET_P (target) = 1;
05278       }
05279 
05280           store_constructor_field
05281       (target, bitsize, bitpos, mode, value, type, cleared,
05282        get_alias_set (elttype));
05283         }
05284     }
05285         else
05286     {
05287       hi_r = expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
05288       loop_top = gen_label_rtx ();
05289       loop_end = gen_label_rtx ();
05290 
05291       unsignedp = TREE_UNSIGNED (domain);
05292 
05293       index = build_decl (VAR_DECL, NULL_TREE, domain);
05294 
05295       index_r
05296         = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
05297              &unsignedp, 0));
05298       SET_DECL_RTL (index, index_r);
05299       if (TREE_CODE (value) == SAVE_EXPR
05300           && SAVE_EXPR_RTL (value) == 0)
05301         {
05302           /* Make sure value gets expanded once before the
05303                          loop.  */
05304           expand_expr (value, const0_rtx, VOIDmode, 0);
05305           emit_queue ();
05306         }
05307       store_expr (lo_index, index_r, 0);
05308       loop = expand_start_loop (0);
05309 
05310       /* Assign value to element index.  */
05311       position
05312         = convert (ssizetype,
05313              fold (build (MINUS_EXPR, TREE_TYPE (index),
05314               index, TYPE_MIN_VALUE (domain))));
05315       position = size_binop (MULT_EXPR, position,
05316            convert (ssizetype,
05317               TYPE_SIZE_UNIT (elttype)));
05318 
05319       pos_rtx = expand_expr (position, 0, VOIDmode, 0);
05320       xtarget = offset_address (target, pos_rtx,
05321               highest_pow2_factor (position));
05322       xtarget = adjust_address (xtarget, mode, 0);
05323       if (TREE_CODE (value) == CONSTRUCTOR)
05324         store_constructor (value, xtarget, cleared,
05325                bitsize / BITS_PER_UNIT);
05326       else
05327         store_expr (value, xtarget, 0);
05328 
05329       expand_exit_loop_if_false (loop,
05330                build (LT_EXPR, integer_type_node,
05331                 index, hi_index));
05332 
05333       expand_increment (build (PREINCREMENT_EXPR,
05334              TREE_TYPE (index),
05335              index, integer_one_node), 0, 0);
05336       expand_end_loop ();
05337       emit_label (loop_end);
05338     }
05339       }
05340     else if ((index != 0 && ! host_integerp (index, 0))
05341        || ! host_integerp (TYPE_SIZE (elttype), 1))
05342       {
05343         tree position;
05344 
05345         if (index == 0)
05346     index = ssize_int (1);
05347 
05348         if (minelt)
05349     index = convert (ssizetype,
05350          fold (build (MINUS_EXPR, index,
05351                 TYPE_MIN_VALUE (domain))));
05352 
05353         position = size_binop (MULT_EXPR, index,
05354              convert (ssizetype,
05355                 TYPE_SIZE_UNIT (elttype)));
05356         xtarget = offset_address (target,
05357           expand_expr (position, 0, VOIDmode, 0),
05358           highest_pow2_factor (position));
05359         xtarget = adjust_address (xtarget, mode, 0);
05360         store_expr (value, xtarget, 0);
05361       }
05362     else
05363       {
05364         if (index != 0)
05365     bitpos = ((tree_low_cst (index, 0) - minelt)
05366         * tree_low_cst (TYPE_SIZE (elttype), 1));
05367         else
05368     bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
05369 
05370         if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target)
05371       && TREE_CODE (type) == ARRAY_TYPE
05372       && TYPE_NONALIASED_COMPONENT (type))
05373     {
05374       target = copy_rtx (target);
05375       MEM_KEEP_ALIAS_SET_P (target) = 1;
05376     }
05377 
05378         store_constructor_field (target, bitsize, bitpos, mode, value,
05379                type, cleared, get_alias_set (elttype));
05380 
05381       }
05382   }
05383     }
05384 
05385   /* Set constructor assignments.  */
05386   else if (TREE_CODE (type) == SET_TYPE)
05387     {
05388       tree elt = CONSTRUCTOR_ELTS (exp);
05389       unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
05390       tree domain = TYPE_DOMAIN (type);
05391       tree domain_min, domain_max, bitlength;
05392 
05393       /* The default implementation strategy is to extract the constant
05394    parts of the constructor, use that to initialize the target,
05395    and then "or" in whatever non-constant ranges we need in addition.
05396 
05397    If a large set is all zero or all ones, it is
05398    probably better to set it using memset (if available) or bzero.
05399    Also, if a large set has just a single range, it may also be
05400    better to first clear all the first clear the set (using
05401    bzero/memset), and set the bits we want.  */
05402 
05403       /* Check for all zeros.  */
05404       if (elt == NULL_TREE && size > 0)
05405   {
05406     if (!cleared)
05407       clear_storage (target, GEN_INT (size));
05408     return;
05409   }
05410 
05411       domain_min = convert (sizetype, TYPE_MIN_VALUE (domain));
05412       domain_max = convert (sizetype, TYPE_MAX_VALUE (domain));
05413       bitlength = size_binop (PLUS_EXPR,
05414             size_diffop (domain_max, domain_min),
05415             ssize_int (1));
05416 
05417       nbits = tree_low_cst (bitlength, 1);
05418 
05419       /* For "small" sets, or "medium-sized" (up to 32 bytes) sets that
05420    are "complicated" (more than one range), initialize (the
05421    constant parts) by copying from a constant.  */
05422       if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
05423     || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
05424   {
05425     unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
05426     enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
05427     char *bit_buffer = (char *) alloca (nbits);
05428     HOST_WIDE_INT word = 0;
05429     unsigned int bit_pos = 0;
05430     unsigned int ibit = 0;
05431     unsigned int offset = 0;  /* In bytes from beginning of set.  */
05432 
05433     elt = get_set_constructor_bits (exp, bit_buffer, nbits);
05434     for (;;)
05435       {
05436         if (bit_buffer[ibit])
05437     {
05438       if (BYTES_BIG_ENDIAN)
05439         word |= (1 << (set_word_size - 1 - bit_pos));
05440       else
05441         word |= 1 << bit_pos;
05442     }
05443 
05444         bit_pos++;  ibit++;
05445         if (bit_pos >= set_word_size || ibit == nbits)
05446     {
05447       if (word != 0 || ! cleared)
05448         {
05449           rtx datum = GEN_INT (word);
05450           rtx to_rtx;
05451 
05452           /* The assumption here is that it is safe to use
05453        XEXP if the set is multi-word, but not if
05454        it's single-word.  */
05455           if (GET_CODE (target) == MEM)
05456       to_rtx = adjust_address (target, mode, offset);
05457           else if (offset == 0)
05458       to_rtx = target;
05459           else
05460       abort ();
05461           emit_move_insn (to_rtx, datum);
05462         }
05463 
05464       if (ibit == nbits)
05465         break;
05466       word = 0;
05467       bit_pos = 0;
05468       offset += set_word_size / BITS_PER_UNIT;
05469     }
05470       }
05471   }
05472       else if (!cleared)
05473   /* Don't bother clearing storage if the set is all ones.  */
05474   if (TREE_CHAIN (elt) != NULL_TREE
05475       || (TREE_PURPOSE (elt) == NULL_TREE
05476     ? nbits != 1
05477     : ( ! host_integerp (TREE_VALUE (elt), 0)
05478        || ! host_integerp (TREE_PURPOSE (elt), 0)
05479        || (tree_low_cst (TREE_VALUE (elt), 0)
05480            - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
05481            != (HOST_WIDE_INT) nbits))))
05482     clear_storage (target, expr_size (exp));
05483 
05484       for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
05485   {
05486     /* Start of range of element or NULL.  */
05487     tree startbit = TREE_PURPOSE (elt);
05488     /* End of range of element, or element value.  */
05489     tree endbit   = TREE_VALUE (elt);
05490     HOST_WIDE_INT startb, endb;
05491     rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
05492 
05493     bitlength_rtx = expand_expr (bitlength,
05494                NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
05495 
05496     /* Handle non-range tuple element like [ expr ].  */
05497     if (startbit == NULL_TREE)
05498       {
05499         startbit = save_expr (endbit);
05500         endbit = startbit;
05501       }
05502 
05503     startbit = convert (sizetype, startbit);
05504     endbit = convert (sizetype, endbit);
05505     if (! integer_zerop (domain_min))
05506       {
05507         startbit = size_binop (MINUS_EXPR, startbit, domain_min);
05508         endbit = size_binop (MINUS_EXPR, endbit, domain_min);
05509       }
05510     startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
05511               EXPAND_CONST_ADDRESS);
05512     endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
05513             EXPAND_CONST_ADDRESS);
05514 
05515     if (REG_P (target))
05516       {
05517         targetx
05518     = assign_temp
05519       ((build_qualified_type ((*lang_hooks.types.type_for_mode)
05520             (GET_MODE (target), 0),
05521             TYPE_QUAL_CONST)),
05522        0, 1, 1);
05523         emit_move_insn (targetx, target);
05524       }
05525 
05526     else if (GET_CODE (target) == MEM)
05527       targetx = target;
05528     else
05529       abort ();
05530 
05531     /* Optimization:  If startbit and endbit are constants divisible
05532        by BITS_PER_UNIT, call memset instead.  */
05533     if (TARGET_MEM_FUNCTIONS
05534         && TREE_CODE (startbit) == INTEGER_CST
05535         && TREE_CODE (endbit) == INTEGER_CST
05536         && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
05537         && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
05538       {
05539         emit_library_call (memset_libfunc, LCT_NORMAL,
05540          VOIDmode, 3,
05541          plus_constant (XEXP (targetx, 0),
05542             startb / BITS_PER_UNIT),
05543          Pmode,
05544          constm1_rtx, TYPE_MODE (integer_type_node),
05545          GEN_INT ((endb - startb) / BITS_PER_UNIT),
05546          TYPE_MODE (sizetype));
05547       }
05548     else
05549       emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
05550              LCT_NORMAL, VOIDmode, 4, XEXP (targetx, 0),
05551              Pmode, bitlength_rtx, TYPE_MODE (sizetype),
05552              startbit_rtx, TYPE_MODE (sizetype),
05553              endbit_rtx, TYPE_MODE (sizetype));
05554 
05555     if (REG_P (target))
05556       emit_move_insn (target, targetx);
05557   }
05558     }
05559 
05560   else
05561     abort ();
05562 }
05563 
05564 /* Store the value of EXP (an expression tree)
05565    into a subfield of TARGET which has mode MODE and occupies
05566    BITSIZE bits, starting BITPOS bits from the start of TARGET.
05567    If MODE is VOIDmode, it means that we are storing into a bit-field.
05568 
05569    If VALUE_MODE is VOIDmode, return nothing in particular.
05570    UNSIGNEDP is not used in this case.
05571 
05572    Otherwise, return an rtx for the value stored.  This rtx
05573    has mode VALUE_MODE if that is convenient to do.
05574    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
05575 
05576    TYPE is the type of the underlying object,
05577 
05578    ALIAS_SET is the alias set for the destination.  This value will
05579    (in general) be different from that for TARGET, since TARGET is a
05580    reference to the containing structure.  */
05581 
05582 static rtx
05583 store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
05584        alias_set)
05585      rtx target;
05586      HOST_WIDE_INT bitsize;
05587      HOST_WIDE_INT bitpos;
05588      enum machine_mode mode;
05589      tree exp;
05590      enum machine_mode value_mode;
05591      int unsignedp;
05592      tree type;
05593      int alias_set;
05594 {
05595   HOST_WIDE_INT width_mask = 0;
05596 
05597   if (TREE_CODE (exp) == ERROR_MARK)
05598     return const0_rtx;
05599 
05600   /* If we have nothing to store, do nothing unless the expression has
05601      side-effects.  */
05602   if (bitsize == 0)
05603     return expand_expr (exp, const0_rtx, VOIDmode, 0);
05604   else if (bitsize >=0 && bitsize < HOST_BITS_PER_WIDE_INT)
05605     width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
05606 
05607   /* If we are storing into an unaligned field of an aligned union that is
05608      in a register, we may have the mode of TARGET being an integer mode but
05609      MODE == BLKmode.  In that case, get an aligned object whose size and
05610      alignment are the same as TARGET and store TARGET into it (we can avoid
05611      the store if the field being stored is the entire width of TARGET).  Then
05612      call ourselves recursively to store the field into a BLKmode version of
05613      that object.  Finally, load from the object into TARGET.  This is not
05614      very efficient in general, but should only be slightly more expensive
05615      than the otherwise-required unaligned accesses.  Perhaps this can be
05616      cleaned up later.  */
05617 
05618   if (mode == BLKmode
05619       && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
05620     {
05621       rtx object
05622   = assign_temp
05623     (build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST),
05624      0, 1, 1);
05625       rtx blk_object = adjust_address (object, BLKmode, 0);
05626 
05627       if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
05628   emit_move_insn (object, target);
05629 
05630       store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
05631        alias_set);
05632 
05633       emit_move_insn (target, object);
05634 
05635       /* We want to return the BLKmode version of the data.  */
05636       return blk_object;
05637     }
05638 
05639   if (GET_CODE (target) == CONCAT)
05640     {
05641       /* We're storing into a struct containing a single __complex.  */
05642 
05643       if (bitpos != 0)
05644   abort ();
05645       return store_expr (exp, target, 0);
05646     }
05647 
05648   /* If the structure is in a register or if the component
05649      is a bit field, we cannot use addressing to access it.
05650      Use bit-field techniques or SUBREG to store in it.  */
05651 
05652   if (mode == VOIDmode
05653       || (mode != BLKmode && ! direct_store[(int) mode]
05654     && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
05655     && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
05656       || GET_CODE (target) == REG
05657       || GET_CODE (target) == SUBREG
05658       /* If the field isn't aligned enough to store as an ordinary memref,
05659    store it as a bit field.  */
05660       || (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target))
05661     && (MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode)
05662         || bitpos % GET_MODE_ALIGNMENT (mode)))
05663       /* If the RHS and field are a constant size and the size of the
05664    RHS isn't the same size as the bitfield, we must use bitfield
05665    operations.  */
05666       || (bitsize >= 0
05667     && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
05668     && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
05669     {
05670       rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
05671 
05672       /* If BITSIZE is narrower than the size of the type of EXP
05673    we will be narrowing TEMP.  Normally, what's wanted are the
05674    low-order bits.  However, if EXP's type is a record and this is
05675    big-endian machine, we want the upper BITSIZE bits.  */
05676       if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
05677     && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
05678     && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
05679   temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
05680            size_int (GET_MODE_BITSIZE (GET_MODE (temp))
05681                - bitsize),
05682            temp, 1);
05683 
05684       /* Unless MODE is VOIDmode or BLKmode, convert TEMP to
05685    MODE.  */
05686       if (mode != VOIDmode && mode != BLKmode
05687     && mode != TYPE_MODE (TREE_TYPE (exp)))
05688   temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
05689 
05690       /* If the modes of TARGET and TEMP are both BLKmode, both
05691    must be in memory and BITPOS must be aligned on a byte
05692    boundary.  If so, we simply do a block copy.  */
05693       if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
05694   {
05695     if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM
05696         || bitpos % BITS_PER_UNIT != 0)
05697       abort ();
05698 
05699     target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
05700     emit_block_move (target, temp,
05701          GEN_INT ((bitsize + BITS_PER_UNIT - 1)
05702             / BITS_PER_UNIT),
05703          BLOCK_OP_NORMAL);
05704 
05705     return value_mode == VOIDmode ? const0_rtx : target;
05706   }
05707 
05708       /* Store the value in the bitfield.  */
05709       store_bit_field (target, bitsize, bitpos, mode, temp,
05710            int_size_in_bytes (type));
05711 
05712       if (value_mode != VOIDmode)
05713   {
05714     /* The caller wants an rtx for the value.
05715        If possible, avoid refetching from the bitfield itself.  */
05716     if (width_mask != 0
05717         && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)))
05718       {
05719         tree count;
05720         enum machine_mode tmode;
05721 
05722         tmode = GET_MODE (temp);
05723         if (tmode == VOIDmode)
05724     tmode = value_mode;
05725 
05726         if (unsignedp)
05727     return expand_and (tmode, temp,
05728            gen_int_mode (width_mask, tmode),
05729            NULL_RTX);
05730 
05731         count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
05732         temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
05733         return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
05734       }
05735 
05736     return extract_bit_field (target, bitsize, bitpos, unsignedp,
05737             NULL_RTX, value_mode, VOIDmode,
05738             int_size_in_bytes (type));
05739   }
05740       return const0_rtx;
05741     }
05742   else
05743     {
05744       rtx addr = XEXP (target, 0);
05745       rtx to_rtx = target;
05746 
05747       /* If a value is wanted, it must be the lhs;
05748    so make the address stable for multiple use.  */
05749 
05750       if (value_mode != VOIDmode && GET_CODE (addr) != REG
05751     && ! CONSTANT_ADDRESS_P (addr)
05752     /* A frame-pointer reference is already stable.  */
05753     && ! (GET_CODE (addr) == PLUS
05754     && GET_CODE (XEXP (addr, 1)) == CONST_INT
05755     && (XEXP (addr, 0) == virtual_incoming_args_rtx
05756         || XEXP (addr, 0) == virtual_stack_vars_rtx)))
05757   to_rtx = replace_equiv_address (to_rtx, copy_to_reg (addr));
05758 
05759       /* Now build a reference to just the desired component.  */
05760 
05761       to_rtx = adjust_address (target, mode, bitpos / BITS_PER_UNIT);
05762 
05763       if (to_rtx == target)
05764   to_rtx = copy_rtx (to_rtx);
05765 
05766       MEM_SET_IN_STRUCT_P (to_rtx, 1);
05767       if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
05768   set_mem_alias_set (to_rtx, alias_set);
05769 
05770       return store_expr (exp, to_rtx, value_mode != VOIDmode);
05771     }
05772 }
05773 
05774 /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
05775    an ARRAY_REF, or an ARRAY_RANGE_REF, look for nested operations of these
05776    codes and find the ultimate containing object, which we return.
05777 
05778    We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
05779    bit position, and *PUNSIGNEDP to the signedness of the field.
05780    If the position of the field is variable, we store a tree
05781    giving the variable offset (in units) in *POFFSET.
05782    This offset is in addition to the bit position.
05783    If the position is not variable, we store 0 in *POFFSET.
05784 
05785    If any of the extraction expressions is volatile,
05786    we store 1 in *PVOLATILEP.  Otherwise we don't change that.
05787 
05788    If the field is a bit-field, *PMODE is set to VOIDmode.  Otherwise, it
05789    is a mode that can be used to access the field.  In that case, *PBITSIZE
05790    is redundant.
05791 
05792    If the field describes a variable-sized object, *PMODE is set to
05793    VOIDmode and *PBITSIZE is set to -1.  An access cannot be made in
05794    this case, but the address of the object can be found.  */
05795 
05796 tree
05797 get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
05798          punsignedp, pvolatilep)
05799      tree exp;
05800      HOST_WIDE_INT *pbitsize;
05801      HOST_WIDE_INT *pbitpos;
05802      tree *poffset;
05803      enum machine_mode *pmode;
05804      int *punsignedp;
05805      int *pvolatilep;
05806 {
05807   tree size_tree = 0;
05808   enum machine_mode mode = VOIDmode;
05809   tree offset = size_zero_node;
05810   tree bit_offset = bitsize_zero_node;
05811   tree placeholder_ptr = 0;
05812   tree tem;
05813 
05814   /* First get the mode, signedness, and size.  We do this from just the
05815      outermost expression.  */
05816   if (TREE_CODE (exp) == COMPONENT_REF)
05817     {
05818       size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
05819       if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
05820   mode = DECL_MODE (TREE_OPERAND (exp, 1));
05821 
05822       *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1));
05823     }
05824   else if (TREE_CODE (exp) == BIT_FIELD_REF)
05825     {
05826       size_tree = TREE_OPERAND (exp, 1);
05827       *punsignedp = TREE_UNSIGNED (exp);
05828     }
05829   else
05830     {
05831       mode = TYPE_MODE (TREE_TYPE (exp));
05832       *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
05833 
05834       if (mode == BLKmode)
05835   size_tree = TYPE_SIZE (TREE_TYPE (exp));
05836       else
05837   *pbitsize = GET_MODE_BITSIZE (mode);
05838     }
05839 
05840   if (size_tree != 0)
05841     {
05842       if (! host_integerp (size_tree, 1))
05843   mode = BLKmode, *pbitsize = -1;
05844       else
05845   *pbitsize = tree_low_cst (size_tree, 1);
05846     }
05847 
05848   /* Compute cumulative bit-offset for nested component-refs and array-refs,
05849      and find the ultimate containing object.  */
05850   while (1)
05851     {
05852       if (TREE_CODE (exp) == BIT_FIELD_REF)
05853   bit_offset = size_binop (PLUS_EXPR, bit_offset, TREE_OPERAND (exp, 2));
05854       else if (TREE_CODE (exp) == COMPONENT_REF)
05855   {
05856     tree field = TREE_OPERAND (exp, 1);
05857     tree this_offset = DECL_FIELD_OFFSET (field);
05858 
05859     /* If this field hasn't been filled in yet, don't go
05860        past it.  This should only happen when folding expressions
05861        made during type construction.  */
05862     if (this_offset == 0)
05863       break;
05864     else if (! TREE_CONSTANT (this_offset)
05865        && contains_placeholder_p (this_offset))
05866       this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
05867 
05868     offset = size_binop (PLUS_EXPR, offset, this_offset);
05869     bit_offset = size_binop (PLUS_EXPR, bit_offset,
05870            DECL_FIELD_BIT_OFFSET (field));
05871 
05872     /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
05873   }
05874 
05875       else if (TREE_CODE (exp) == ARRAY_REF
05876          || TREE_CODE (exp) == ARRAY_RANGE_REF)
05877   {
05878     tree index = TREE_OPERAND (exp, 1);
05879     tree array = TREE_OPERAND (exp, 0);
05880     tree domain = TYPE_DOMAIN (TREE_TYPE (array));
05881     tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
05882     tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
05883 
05884     /* We assume all arrays have sizes that are a multiple of a byte.
05885        First subtract the lower bound, if any, in the type of the
05886        index, then convert to sizetype and multiply by the size of the
05887        array element.  */
05888     if (low_bound != 0 && ! integer_zerop (low_bound))
05889       index = fold (build (MINUS_EXPR, TREE_TYPE (index),
05890          index, low_bound));
05891 
05892     /* If the index has a self-referential type, pass it to a
05893        WITH_RECORD_EXPR; if the component size is, pass our
05894        component to one.  */
05895     if (! TREE_CONSTANT (index)
05896         && contains_placeholder_p (index))
05897       index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
05898     if (! TREE_CONSTANT (unit_size)
05899         && contains_placeholder_p (unit_size))
05900       unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array);
05901 
05902     offset = size_binop (PLUS_EXPR, offset,
05903              size_binop (MULT_EXPR,
05904              convert (sizetype, index),
05905              unit_size));
05906   }
05907 
05908       else if (TREE_CODE (exp) == PLACEHOLDER_EXPR)
05909   {
05910     tree new = find_placeholder (exp, &placeholder_ptr);
05911 
05912     /* If we couldn't find the replacement, return the PLACEHOLDER_EXPR.
05913        We might have been called from tree optimization where we
05914        haven't set up an object yet.  */
05915     if (new == 0)
05916       break;
05917     else
05918       exp = new;
05919 
05920     continue;
05921   }
05922       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
05923          && TREE_CODE (exp) != VIEW_CONVERT_EXPR
05924          && ! ((TREE_CODE (exp) == NOP_EXPR
05925           || TREE_CODE (exp) == CONVERT_EXPR)
05926          && (TYPE_MODE (TREE_TYPE (exp))
05927        == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
05928   break;
05929 
05930       /* If any reference in the chain is volatile, the effect is volatile.  */
05931       if (TREE_THIS_VOLATILE (exp))
05932   *pvolatilep = 1;
05933 
05934       exp = TREE_OPERAND (exp, 0);
05935     }
05936 
05937   /* If OFFSET is constant, see if we can return the whole thing as a
05938      constant bit position.  Otherwise, split it up.  */
05939   if (host_integerp (offset, 0)
05940       && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
05941          bitsize_unit_node))
05942       && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
05943       && host_integerp (tem, 0))
05944     *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
05945   else
05946     *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
05947 
05948   *pmode = mode;
05949   return exp;
05950 }
05951 
05952 /* Return 1 if T is an expression that get_inner_reference handles.  */
05953 
05954 int
05955 handled_component_p (t)
05956      tree t;
05957 {
05958   switch (TREE_CODE (t))
05959     {
05960     case BIT_FIELD_REF:
05961     case COMPONENT_REF:
05962     case ARRAY_REF:
05963     case ARRAY_RANGE_REF:
05964     case NON_LVALUE_EXPR:
05965     case VIEW_CONVERT_EXPR:
05966       return 1;
05967 
05968     case NOP_EXPR:
05969     case CONVERT_EXPR:
05970       return (TYPE_MODE (TREE_TYPE (t))
05971         == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
05972 
05973     default:
05974       return 0;
05975     }
05976 }
05977 
05978 /* Given an rtx VALUE that may contain additions and multiplications, return
05979    an equivalent value that just refers to a register, memory, or constant.
05980    This is done by generating instructions to perform the arithmetic and
05981    returning a pseudo-register containing the value.
05982 
05983    The returned value may be a REG, SUBREG, MEM or constant.  */
05984 
05985 rtx
05986 force_operand (value, target)
05987      rtx value, target;
05988 {
05989   rtx op1, op2;
05990   /* Use subtarget as the target for operand 0 of a binary operation.  */
05991   rtx subtarget = get_subtarget (target);
05992   enum rtx_code code = GET_CODE (value);
05993 
05994   /* Check for a PIC address load.  */
05995   if ((code == PLUS || code == MINUS)
05996       && XEXP (value, 0) == pic_offset_table_rtx
05997       && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
05998     || GET_CODE (XEXP (value, 1)) == LABEL_REF
05999     || GET_CODE (XEXP (value, 1)) == CONST))
06000     {
06001       if (!subtarget)
06002   subtarget = gen_reg_rtx (GET_MODE (value));
06003       emit_move_insn (subtarget, value);
06004       return subtarget;
06005     }
06006 
06007   if (code == ZERO_EXTEND || code == SIGN_EXTEND)
06008     {
06009       if (!target)
06010   target = gen_reg_rtx (GET_MODE (value));
06011       convert_move (target, force_operand (XEXP (value, 0), NULL),
06012         code == ZERO_EXTEND);
06013       return target;
06014     }
06015 
06016   if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
06017     {
06018       op2 = XEXP (value, 1);
06019       if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
06020   subtarget = 0;
06021       if (code == MINUS && GET_CODE (op2) == CONST_INT)
06022   {
06023     code = PLUS;
06024     op2 = negate_rtx (GET_MODE (value), op2);
06025   }
06026 
06027       /* Check for an addition with OP2 a constant integer and our first
06028          operand a PLUS of a virtual register and something else.  In that
06029          case, we want to emit the sum of the virtual register and the
06030          constant first and then add the other value.  This allows virtual
06031          register instantiation to simply modify the constant rather than
06032          creating another one around this addition.  */
06033       if (code == PLUS && GET_CODE (op2) == CONST_INT
06034     && GET_CODE (XEXP (value, 0)) == PLUS
06035     && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
06036     && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
06037     && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
06038   {
06039     rtx temp = expand_simple_binop (GET_MODE (value), code,
06040             XEXP (XEXP (value, 0), 0), op2,
06041             subtarget, 0, OPTAB_LIB_WIDEN);
06042     return expand_simple_binop (GET_MODE (value), code, temp,
06043               force_operand (XEXP (XEXP (value,
06044                  0), 1), 0),
06045               target, 0, OPTAB_LIB_WIDEN);
06046   }
06047 
06048       op1 = force_operand (XEXP (value, 0), subtarget);
06049       op2 = force_operand (op2, NULL_RTX);
06050       switch (code)
06051   {
06052   case MULT:
06053     return expand_mult (GET_MODE (value), op1, op2, target, 1);
06054   case DIV:
06055     if (!INTEGRAL_MODE_P (GET_MODE (value)))
06056       return expand_simple_binop (GET_MODE (value), code, op1, op2,
06057           target, 1, OPTAB_LIB_WIDEN);
06058     else
06059       return expand_divmod (0,
06060           FLOAT_MODE_P (GET_MODE (value))
06061           ? RDIV_EXPR : TRUNC_DIV_EXPR,
06062           GET_MODE (value), op1, op2, target, 0);
06063     break;
06064   case MOD:
06065     return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
06066         target, 0);
06067     break;
06068   case UDIV:
06069     return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
06070         target, 1);
06071     break;
06072   case UMOD:
06073     return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
06074         target, 1);
06075     break;
06076   case ASHIFTRT:
06077     return expand_simple_binop (GET_MODE (value), code, op1, op2,
06078               target, 0, OPTAB_LIB_WIDEN);
06079     break;
06080   default:
06081     return expand_simple_binop (GET_MODE (value), code, op1, op2,
06082               target, 1, OPTAB_LIB_WIDEN);
06083   }
06084     }
06085   if (GET_RTX_CLASS (code) == '1')
06086     {
06087       op1 = force_operand (XEXP (value, 0), NULL_RTX);
06088       return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
06089     }
06090 
06091 #ifdef INSN_SCHEDULING
06092   /* On machines that have insn scheduling, we want all memory reference to be
06093      explicit, so we need to deal with such paradoxical SUBREGs.  */
06094   if (GET_CODE (value) == SUBREG && GET_CODE (SUBREG_REG (value)) == MEM
06095       && (GET_MODE_SIZE (GET_MODE (value))
06096     > GET_MODE_SIZE (GET_MODE (SUBREG_REG (value)))))
06097     value
06098       = simplify_gen_subreg (GET_MODE (value),
06099            force_reg (GET_MODE (SUBREG_REG (value)),
06100           force_operand (SUBREG_REG (value),
06101                    NULL_RTX)),
06102            GET_MODE (SUBREG_REG (value)),
06103            SUBREG_BYTE (value));
06104 #endif
06105 
06106   return value;
06107 }
06108 
06109 /* Subroutine of expand_expr: return nonzero iff there is no way that
06110    EXP can reference X, which is being modified.  TOP_P is nonzero if this
06111    call is going to be used to determine whether we need a temporary
06112    for EXP, as opposed to a recursive call to this function.
06113 
06114    It is always safe for this routine to return zero since it merely
06115    searches for optimization opportunities.  */
06116 
06117 int
06118 safe_from_p (x, exp, top_p)
06119      rtx x;
06120      tree exp;
06121      int top_p;
06122 {
06123   rtx exp_rtl = 0;
06124   int i, nops;
06125   static tree save_expr_list;
06126 
06127   if (x == 0
06128       /* If EXP has varying size, we MUST use a target since we currently
06129    have no way of allocating temporaries of variable size
06130    (except for arrays that have TYPE_ARRAY_MAX_SIZE set).
06131    So we assume here that something at a higher level has prevented a
06132    clash.  This is somewhat bogus, but the best we can do.  Only
06133    do this when X is BLKmode and when we are at the top level.  */
06134       || (top_p && TREE_TYPE (exp) != 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
06135     && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
06136     && (TREE_CODE (TREE_TYPE (exp)) != ARRAY_TYPE
06137         || TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
06138         || TREE_CODE (TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)))
06139         != INTEGER_CST)
06140     && GET_MODE (x) == BLKmode)
06141       /* If X is in the outgoing argument area, it is always safe.  */
06142       || (GET_CODE (x) == MEM
06143     && (XEXP (x, 0) == virtual_outgoing_args_rtx
06144         || (GET_CODE (XEXP (x, 0)) == PLUS
06145       && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))))
06146     return 1;
06147 
06148   /* If this is a subreg of a hard register, declare it unsafe, otherwise,
06149      find the underlying pseudo.  */
06150   if (GET_CODE (x) == SUBREG)
06151     {
06152       x = SUBREG_REG (x);
06153       if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
06154   return 0;
06155     }
06156 
06157   /* A SAVE_EXPR might appear many times in the expression passed to the
06158      top-level safe_from_p call, and if it has a complex subexpression,
06159      examining it multiple times could result in a combinatorial explosion.
06160      E.g. on an Alpha running at least 200MHz, a Fortran test case compiled
06161      with optimization took about 28 minutes to compile -- even though it was
06162      only a few lines long.  So we mark each SAVE_EXPR we see with TREE_PRIVATE
06163      and turn that off when we are done.  We keep a list of the SAVE_EXPRs
06164      we have processed.  Note that the only test of top_p was above.  */
06165 
06166   if (top_p)
06167     {
06168       int rtn;
06169       tree t;
06170 
06171       save_expr_list = 0;
06172 
06173       rtn = safe_from_p (x, exp, 0);
06174 
06175       for (t = save_expr_list; t != 0; t = TREE_CHAIN (t))
06176   TREE_PRIVATE (TREE_PURPOSE (t)) = 0;
06177 
06178       return rtn;
06179     }
06180 
06181   /* Now look at our tree code and possibly recurse.  */
06182   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
06183     {
06184     case 'd':
06185       exp_rtl = DECL_RTL_IF_SET (exp);
06186       break;
06187 
06188     case 'c':
06189       return 1;
06190 
06191     case 'x':
06192       if (TREE_CODE (exp) == TREE_LIST)
06193   {
06194     while (1)
06195       {
06196         if (TREE_VALUE (exp) && !safe_from_p (x, TREE_VALUE (exp), 0))
06197     return 0;
06198         exp = TREE_CHAIN (exp);
06199         if (!exp)
06200     return 1;
06201         if (TREE_CODE (exp) != TREE_LIST)
06202     return safe_from_p (x, exp, 0);
06203       }
06204   }
06205       else if (TREE_CODE (exp) == ERROR_MARK)
06206   return 1; /* An already-visited SAVE_EXPR? */
06207       else
06208   return 0;
06209 
06210     case '2':
06211     case '<':
06212       if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))
06213   return 0;
06214       /* FALLTHRU */
06215 
06216     case '1':
06217       return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
06218 
06219     case 'e':
06220     case 'r':
06221       /* Now do code-specific tests.  EXP_RTL is set to any rtx we find in
06222    the expression.  If it is set, we conflict iff we are that rtx or
06223    both are in memory.  Otherwise, we check all operands of the
06224    expression recursively.  */
06225 
06226       switch (TREE_CODE (exp))
06227   {
06228   case ADDR_EXPR:
06229     /* If the operand is static or we are static, we can't conflict.
06230        Likewise if we don't conflict with the operand at all.  */
06231     if (staticp (TREE_OPERAND (exp, 0))
06232         || TREE_STATIC (exp)
06233         || safe_from_p (x, TREE_OPERAND (exp, 0), 0))
06234       return 1;
06235 
06236     /* Otherwise, the only way this can conflict is if we are taking
06237        the address of a DECL a that address if part of X, which is
06238        very rare.  */
06239     exp = TREE_OPERAND (exp, 0);
06240     if (DECL_P (exp))
06241       {
06242         if (!DECL_RTL_SET_P (exp)
06243       || GET_CODE (DECL_RTL (exp)) != MEM)
06244     return 0;
06245         else
06246     exp_rtl = XEXP (DECL_RTL (exp), 0);
06247       }
06248     break;
06249 
06250   case INDIRECT_REF:
06251     if (GET_CODE (x) == MEM
06252         && alias_sets_conflict_p (MEM_ALIAS_SET (x),
06253           get_alias_set (exp)))
06254       return 0;
06255     break;
06256 
06257   case CALL_EXPR:
06258     /* Assume that the call will clobber all hard registers and
06259        all of memory.  */
06260     if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
06261         || GET_CODE (x) == MEM)
06262       return 0;
06263     break;
06264 
06265   case RTL_EXPR:
06266     /* If a sequence exists, we would have to scan every instruction
06267        in the sequence to see if it was safe.  This is probably not
06268        worthwhile.  */
06269     if (RTL_EXPR_SEQUENCE (exp))
06270       return 0;
06271 
06272     exp_rtl = RTL_EXPR_RTL (exp);
06273     break;
06274 
06275   case WITH_CLEANUP_EXPR:
06276     exp_rtl = WITH_CLEANUP_EXPR_RTL (exp);
06277     break;
06278 
06279   case CLEANUP_POINT_EXPR:
06280     return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
06281 
06282   case SAVE_EXPR:
06283     exp_rtl = SAVE_EXPR_RTL (exp);
06284     if (exp_rtl)
06285       break;
06286 
06287     /* If we've already scanned this, don't do it again.  Otherwise,
06288        show we've scanned it and record for clearing the flag if we're
06289        going on.  */
06290     if (TREE_PRIVATE (exp))
06291       return 1;
06292 
06293     TREE_PRIVATE (exp) = 1;
06294     if (! safe_from_p (x, TREE_OPERAND (exp, 0), 0))
06295       {
06296         TREE_PRIVATE (exp) = 0;
06297         return 0;
06298       }
06299 
06300     save_expr_list = tree_cons (exp, NULL_TREE, save_expr_list);
06301     return 1;
06302 
06303   case BIND_EXPR:
06304     /* The only operand we look at is operand 1.  The rest aren't
06305        part of the expression.  */
06306     return safe_from_p (x, TREE_OPERAND (exp, 1), 0);
06307 
06308   case METHOD_CALL_EXPR:
06309     /* This takes an rtx argument, but shouldn't appear here.  */
06310     abort ();
06311 
06312   default:
06313     break;
06314   }
06315 
06316       /* If we have an rtx, we do not need to scan our operands.  */
06317       if (exp_rtl)
06318   break;
06319 
06320       nops = first_rtl_op (TREE_CODE (exp));
06321       for (i = 0; i < nops; i++)
06322   if (TREE_OPERAND (exp, i) != 0
06323       && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
06324     return 0;
06325 
06326       /* If this is a language-specific tree code, it may require
06327    special handling.  */
06328       if ((unsigned int) TREE_CODE (exp)
06329     >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
06330     && !(*lang_hooks.safe_from_p) (x, exp))
06331   return 0;
06332     }
06333 
06334   /* If we have an rtl, find any enclosed object.  Then see if we conflict
06335      with it.  */
06336   if (exp_rtl)
06337     {
06338       if (GET_CODE (exp_rtl) == SUBREG)
06339   {
06340     exp_rtl = SUBREG_REG (exp_rtl);
06341     if (GET_CODE (exp_rtl) == REG
06342         && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER)
06343       return 0;
06344   }
06345 
06346       /* If the rtl is X, then it is not safe.  Otherwise, it is unless both
06347    are memory and they conflict.  */
06348       return ! (rtx_equal_p (x, exp_rtl)
06349     || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
06350         && true_dependence (exp_rtl, VOIDmode, x,
06351           rtx_addr_varies_p)));
06352     }
06353 
06354   /* If we reach here, it is safe.  */
06355   return 1;
06356 }
06357 
06358 /* Subroutine of expand_expr: return rtx if EXP is a
06359    variable or parameter; else return 0.  */
06360 
06361 static rtx
06362 var_rtx (exp)
06363      tree exp;
06364 {
06365   STRIP_NOPS (exp);
06366   switch (TREE_CODE (exp))
06367     {
06368     case PARM_DECL:
06369     case VAR_DECL:
06370       return DECL_RTL (exp);
06371     default:
06372       return 0;
06373     }
06374 }
06375 
06376 #ifdef MAX_INTEGER_COMPUTATION_MODE
06377 
06378 void
06379 check_max_integer_computation_mode (exp)
06380      tree exp;
06381 {
06382   enum tree_code code;
06383   enum machine_mode mode;
06384 
06385   /* Strip any NOPs that don't change the mode.  */
06386   STRIP_NOPS (exp);
06387   code = TREE_CODE (exp);
06388 
06389   /* We must allow conversions of constants to MAX_INTEGER_COMPUTATION_MODE.  */
06390   if (code == NOP_EXPR
06391       && TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
06392     return;
06393 
06394   /* First check the type of the overall operation.   We need only look at
06395      unary, binary and relational operations.  */
06396   if (TREE_CODE_CLASS (code) == '1'
06397       || TREE_CODE_CLASS (code) == '2'
06398       || TREE_CODE_CLASS (code) == '<')
06399     {
06400       mode = TYPE_MODE (TREE_TYPE (exp));
06401       if (GET_MODE_CLASS (mode) == MODE_INT
06402     && mode > MAX_INTEGER_COMPUTATION_MODE)
06403   internal_error ("unsupported wide integer operation");
06404     }
06405 
06406   /* Check operand of a unary op.  */
06407   if (TREE_CODE_CLASS (code) == '1')
06408     {
06409       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
06410       if (GET_MODE_CLASS (mode) == MODE_INT
06411     && mode > MAX_INTEGER_COMPUTATION_MODE)
06412   internal_error ("unsupported wide integer operation");
06413     }
06414 
06415   /* Check operands of a binary/comparison op.  */
06416   if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
06417     {
06418       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
06419       if (GET_MODE_CLASS (mode) == MODE_INT
06420     && mode > MAX_INTEGER_COMPUTATION_MODE)
06421   internal_error ("unsupported wide integer operation");
06422 
06423       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
06424       if (GET_MODE_CLASS (mode) == MODE_INT
06425     && mode > MAX_INTEGER_COMPUTATION_MODE)
06426   internal_error ("unsupported wide integer operation");
06427     }
06428 }
06429 #endif
06430 
06431 /* Return the highest power of two that EXP is known to be a multiple of.
06432    This is used in updating alignment of MEMs in array references.  */
06433 
06434 static HOST_WIDE_INT
06435 highest_pow2_factor (exp)
06436      tree exp;
06437 {
06438   HOST_WIDE_INT c0, c1;
06439 
06440   switch (TREE_CODE (exp))
06441     {
06442     case INTEGER_CST:
06443       /* We can find the lowest bit that's a one.  If the low
06444    HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT.
06445    We need to handle this case since we can find it in a COND_EXPR,
06446    a MIN_EXPR, or a MAX_EXPR.  If the constant overlows, we have an
06447    erroneous program, so return BIGGEST_ALIGNMENT to avoid any
06448    later ICE.  */
06449       if (TREE_CONSTANT_OVERFLOW (exp))
06450   return BIGGEST_ALIGNMENT;
06451       else
06452   {
06453     /* Note: tree_low_cst is intentionally not used here,
06454        we don't care about the upper bits.  */
06455     c0 = TREE_INT_CST_LOW (exp);
06456     c0 &= -c0;
06457     return c0 ? c0 : BIGGEST_ALIGNMENT;
06458   }
06459       break;
06460 
06461     case PLUS_EXPR:  case MINUS_EXPR:  case MIN_EXPR:  case MAX_EXPR:
06462       c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
06463       c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06464       return MIN (c0, c1);
06465 
06466     case MULT_EXPR:
06467       c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
06468       c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06469       return c0 * c1;
06470 
06471     case ROUND_DIV_EXPR:  case TRUNC_DIV_EXPR:  case FLOOR_DIV_EXPR:
06472     case CEIL_DIV_EXPR:
06473       if (integer_pow2p (TREE_OPERAND (exp, 1))
06474     && host_integerp (TREE_OPERAND (exp, 1), 1))
06475   {
06476     c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
06477     c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1);
06478     return MAX (1, c0 / c1);
06479   }
06480       break;
06481 
06482     case NON_LVALUE_EXPR:  case NOP_EXPR:  case CONVERT_EXPR:
06483     case SAVE_EXPR: case WITH_RECORD_EXPR:
06484       return highest_pow2_factor (TREE_OPERAND (exp, 0));
06485 
06486     case COMPOUND_EXPR:
06487       return highest_pow2_factor (TREE_OPERAND (exp, 1));
06488 
06489     case COND_EXPR:
06490       c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06491       c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
06492       return MIN (c0, c1);
06493 
06494     default:
06495       break;
06496     }
06497 
06498   return 1;
06499 }
06500 
06501 /* Similar, except that it is known that the expression must be a multiple
06502    of the alignment of TYPE.  */
06503 
06504 static HOST_WIDE_INT
06505 highest_pow2_factor_for_type (type, exp)
06506      tree type;
06507      tree exp;
06508 {
06509   HOST_WIDE_INT type_align, factor;
06510 
06511   factor = highest_pow2_factor (exp);
06512   type_align = TYPE_ALIGN (type) / BITS_PER_UNIT;
06513   return MAX (factor, type_align);
06514 }
06515 
06516 /* Return an object on the placeholder list that matches EXP, a
06517    PLACEHOLDER_EXPR.  An object "matches" if it is of the type of the
06518    PLACEHOLDER_EXPR or a pointer type to it.  For further information, see
06519    tree.def.  If no such object is found, return 0.  If PLIST is nonzero, it
06520    is a location which initially points to a starting location in the
06521    placeholder list (zero means start of the list) and where a pointer into
06522    the placeholder list at which the object is found is placed.  */
06523 
06524 tree
06525 find_placeholder (exp, plist)
06526      tree exp;
06527      tree *plist;
06528 {
06529   tree type = TREE_TYPE (exp);
06530   tree placeholder_expr;
06531 
06532   for (placeholder_expr
06533        = plist && *plist ? TREE_CHAIN (*plist) : placeholder_list;
06534        placeholder_expr != 0;
06535        placeholder_expr = TREE_CHAIN (placeholder_expr))
06536     {
06537       tree need_type = TYPE_MAIN_VARIANT (type);
06538       tree elt;
06539 
06540       /* Find the outermost reference that is of the type we want.  If none,
06541    see if any object has a type that is a pointer to the type we
06542    want.  */
06543       for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
06544      elt = ((TREE_CODE (elt) == COMPOUND_EXPR
06545        || TREE_CODE (elt) == COND_EXPR)
06546       ? TREE_OPERAND (elt, 1)
06547       : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
06548          || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
06549          || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
06550          || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
06551       ? TREE_OPERAND (elt, 0) : 0))
06552   if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
06553     {
06554       if (plist)
06555         *plist = placeholder_expr;
06556       return elt;
06557     }
06558 
06559       for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
06560      elt
06561      = ((TREE_CODE (elt) == COMPOUND_EXPR
06562          || TREE_CODE (elt) == COND_EXPR)
06563         ? TREE_OPERAND (elt, 1)
06564         : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
06565      || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
06566      || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
06567      || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
06568         ? TREE_OPERAND (elt, 0) : 0))
06569   if (POINTER_TYPE_P (TREE_TYPE (elt))
06570       && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
06571     == need_type))
06572     {
06573       if (plist)
06574         *plist = placeholder_expr;
06575       return build1 (INDIRECT_REF, need_type, elt);
06576     }
06577     }
06578 
06579   return 0;
06580 }
06581 
06582 /* expand_expr: generate code for computing expression EXP.
06583    An rtx for the computed value is returned.  The value is never null.
06584    In the case of a void EXP, const0_rtx is returned.
06585 
06586    The value may be stored in TARGET if TARGET is nonzero.
06587    TARGET is just a suggestion; callers must assume that
06588    the rtx returned may not be the same as TARGET.
06589 
06590    If TARGET is CONST0_RTX, it means that the value will be ignored.
06591 
06592    If TMODE is not VOIDmode, it suggests generating the
06593    result in mode TMODE.  But this is done only when convenient.
06594    Otherwise, TMODE is ignored and the value generated in its natural mode.
06595    TMODE is just a suggestion; callers must assume that
06596    the rtx returned may not have mode TMODE.
06597 
06598    Note that TARGET may have neither TMODE nor MODE.  In that case, it
06599    probably will not be used.
06600 
06601    If MODIFIER is EXPAND_SUM then when EXP is an addition
06602    we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
06603    or a nest of (PLUS ...) and (MINUS ...) where the terms are
06604    products as above, or REG or MEM, or constant.
06605    Ordinarily in such cases we would output mul or add instructions
06606    and then return a pseudo reg containing the sum.
06607 
06608    EXPAND_INITIALIZER is much like EXPAND_SUM except that
06609    it also marks a label as absolutely required (it can't be dead).
06610    It also makes a ZERO_EXTEND or SIGN_EXTEND instead of emitting extend insns.
06611    This is used for outputting expressions used in initializers.
06612 
06613    EXPAND_CONST_ADDRESS says that it is okay to return a MEM
06614    with a constant address even if that address is not normally legitimate.
06615    EXPAND_INITIALIZER and EXPAND_SUM also have this effect.
06616 
06617    EXPAND_STACK_PARM is used when expanding to a TARGET on the stack for
06618    a call parameter.  Such targets require special care as we haven't yet
06619    marked TARGET so that it's safe from being trashed by libcalls.  We
06620    don't want to use TARGET for anything but the final result;
06621    Intermediate values must go elsewhere.   Additionally, calls to
06622    emit_block_move will be flagged with BLOCK_OP_CALL_PARM.  */
06623 
06624 rtx
06625 expand_expr (exp, target, tmode, modifier)
06626      tree exp;
06627      rtx target;
06628      enum machine_mode tmode;
06629      enum expand_modifier modifier;
06630 {
06631   rtx op0, op1, temp;
06632   tree type = TREE_TYPE (exp);
06633   int unsignedp = TREE_UNSIGNED (type);
06634   enum machine_mode mode;
06635   enum tree_code code = TREE_CODE (exp);
06636   optab this_optab;
06637   rtx subtarget, original_target;
06638   int ignore;
06639   tree context;
06640 
06641   /* Handle ERROR_MARK before anybody tries to access its type.  */
06642   if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
06643     {
06644       op0 = CONST0_RTX (tmode);
06645       if (op0 != 0)
06646   return op0;
06647       return const0_rtx;
06648     }
06649 
06650   mode = TYPE_MODE (type);
06651   /* Use subtarget as the target for operand 0 of a binary operation.  */
06652   subtarget = get_subtarget (target);
06653   original_target = target;
06654   ignore = (target == const0_rtx
06655       || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
06656      || code == CONVERT_EXPR || code == REFERENCE_EXPR
06657      || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
06658     && TREE_CODE (type) == VOID_TYPE));
06659 
06660   /* If we are going to ignore this result, we need only do something
06661      if there is a side-effect somewhere in the expression.  If there
06662      is, short-circuit the most common cases here.  Note that we must
06663      not call expand_expr with anything but const0_rtx in case this
06664      is an initial expansion of a size that contains a PLACEHOLDER_EXPR.  */
06665 
06666   if (ignore)
06667     {
06668       if (! TREE_SIDE_EFFECTS (exp))
06669   return const0_rtx;
06670 
06671       /* Ensure we reference a volatile object even if value is ignored, but
06672    don't do this if all we are doing is taking its address.  */
06673       if (TREE_THIS_VOLATILE (exp)
06674     && TREE_CODE (exp) != FUNCTION_DECL
06675     && mode != VOIDmode && mode != BLKmode
06676     && modifier != EXPAND_CONST_ADDRESS)
06677   {
06678     temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
06679     if (GET_CODE (temp) == MEM)
06680       temp = copy_to_reg (temp);
06681     return const0_rtx;
06682   }
06683 
06684       if (TREE_CODE_CLASS (code) == '1' || code == COMPONENT_REF
06685     || code == INDIRECT_REF || code == BUFFER_REF)
06686   return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
06687           modifier);
06688 
06689       else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
06690          || code == ARRAY_REF || code == ARRAY_RANGE_REF)
06691   {
06692     expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
06693     expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
06694     return const0_rtx;
06695   }
06696       else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
06697          && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
06698   /* If the second operand has no side effects, just evaluate
06699      the first.  */
06700   return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
06701           modifier);
06702       else if (code == BIT_FIELD_REF)
06703   {
06704     expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
06705     expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
06706     expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, modifier);
06707     return const0_rtx;
06708   }
06709 
06710       target = 0;
06711     }
06712 
06713 #ifdef MAX_INTEGER_COMPUTATION_MODE
06714   /* Only check stuff here if the mode we want is different from the mode
06715      of the expression; if it's the same, check_max_integer_computiation_mode
06716      will handle it.  Do we really need to check this stuff at all?  */
06717 
06718   if (target
06719       && GET_MODE (target) != mode
06720       && TREE_CODE (exp) != INTEGER_CST
06721       && TREE_CODE (exp) != PARM_DECL
06722       && TREE_CODE (exp) != ARRAY_REF
06723       && TREE_CODE (exp) != ARRAY_RANGE_REF
06724       && TREE_CODE (exp) != COMPONENT_REF
06725       && TREE_CODE (exp) != BIT_FIELD_REF
06726       && TREE_CODE (exp) != INDIRECT_REF
06727       && TREE_CODE (exp) != CALL_EXPR
06728       && TREE_CODE (exp) != VAR_DECL
06729       && TREE_CODE (exp) != RTL_EXPR)
06730     {
06731       enum machine_mode mode = GET_MODE (target);
06732 
06733       if (GET_MODE_CLASS (mode) == MODE_INT
06734     && mode > MAX_INTEGER_COMPUTATION_MODE)
06735   internal_error ("unsupported wide integer operation");
06736     }
06737 
06738   if (tmode != mode
06739       && TREE_CODE (exp) != INTEGER_CST
06740       && TREE_CODE (exp) != PARM_DECL
06741       && TREE_CODE (exp) != ARRAY_REF
06742       && TREE_CODE (exp) != ARRAY_RANGE_REF
06743       && TREE_CODE (exp) != COMPONENT_REF
06744       && TREE_CODE (exp) != BIT_FIELD_REF
06745       && TREE_CODE (exp) != INDIRECT_REF
06746       && TREE_CODE (exp) != VAR_DECL
06747       && TREE_CODE (exp) != CALL_EXPR
06748       && TREE_CODE (exp) != RTL_EXPR
06749       && GET_MODE_CLASS (tmode) == MODE_INT
06750       && tmode > MAX_INTEGER_COMPUTATION_MODE)
06751     internal_error ("unsupported wide integer operation");
06752 
06753   check_max_integer_computation_mode (exp);
06754 #endif
06755 
06756   /* If will do cse, generate all results into pseudo registers
06757      since 1) that allows cse to find more things
06758      and 2) otherwise cse could produce an insn the machine
06759      cannot support.  And exception is a CONSTRUCTOR into a multi-word
06760      MEM: that's much more likely to be most efficient into the MEM.  */
06761 
06762   if (! cse_not_expected && mode != BLKmode && target
06763       && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
06764       && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD))
06765     target = 0;
06766 
06767   switch (code)
06768     {
06769     case LABEL_DECL:
06770       {
06771   tree function = decl_function_context (exp);
06772   /* Handle using a label in a containing function.  */
06773   if (function != current_function_decl
06774       && function != inline_function_decl && function != 0)
06775     {
06776       struct function *p = find_function_data (function);
06777       p->expr->x_forced_labels
06778         = gen_rtx_EXPR_LIST (VOIDmode, label_rtx (exp),
06779            p->expr->x_forced_labels);
06780     }
06781   else
06782     {
06783       if (modifier == EXPAND_INITIALIZER)
06784         forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
06785              label_rtx (exp),
06786              forced_labels);
06787     }
06788 
06789   temp = gen_rtx_MEM (FUNCTION_MODE,
06790           gen_rtx_LABEL_REF (Pmode, label_rtx (exp)));
06791   if (function != current_function_decl
06792       && function != inline_function_decl && function != 0)
06793     LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1;
06794   return temp;
06795       }
06796 
06797     case PARM_DECL:
06798       if (!DECL_RTL_SET_P (exp))
06799   {
06800     error_with_decl (exp, "prior parameter's size depends on `%s'");
06801     return CONST0_RTX (mode);
06802   }
06803 
06804       /* ... fall through ...  */
06805 
06806     case VAR_DECL:
06807       /* If a static var's type was incomplete when the decl was written,
06808    but the type is complete now, lay out the decl now.  */
06809       if (DECL_SIZE (exp) == 0
06810     && COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (TREE_TYPE (exp))
06811     && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
06812   layout_decl (exp, 0);
06813 
06814       /* ... fall through ...  */
06815 
06816     case FUNCTION_DECL:
06817     case RESULT_DECL:
06818       if (DECL_RTL (exp) == 0)
06819   abort ();
06820 
06821       /* Ensure variable marked as used even if it doesn't go through
06822    a parser.  If it hasn't be used yet, write out an external
06823    definition.  */
06824       if (! TREE_USED (exp))
06825   {
06826     assemble_external (exp);
06827     TREE_USED (exp) = 1;
06828   }
06829 
06830       /* Show we haven't gotten RTL for this yet.  */
06831       temp = 0;
06832 
06833       /* Handle variables inherited from containing functions.  */
06834       context = decl_function_context (exp);
06835 
06836       /* We treat inline_function_decl as an alias for the current function
06837    because that is the inline function whose vars, types, etc.
06838    are being merged into the current function.
06839    See expand_inline_function.  */
06840 
06841       if (context != 0 && context != current_function_decl
06842     && context != inline_function_decl
06843     /* If var is static, we don't need a static chain to access it.  */
06844     && ! (GET_CODE (DECL_RTL (exp)) == MEM
06845     && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
06846   {
06847     rtx addr;
06848 
06849     /* Mark as non-local and addressable.  */
06850     DECL_NONLOCAL (exp) = 1;
06851     if (DECL_NO_STATIC_CHAIN (current_function_decl))
06852       abort ();
06853     (*lang_hooks.mark_addressable) (exp);
06854     if (GET_CODE (DECL_RTL (exp)) != MEM)
06855       abort ();
06856     addr = XEXP (DECL_RTL (exp), 0);
06857     if (GET_CODE (addr) == MEM)
06858       addr
06859         = replace_equiv_address (addr,
06860                fix_lexical_addr (XEXP (addr, 0), exp));
06861     else
06862       addr = fix_lexical_addr (addr, exp);
06863 
06864     temp = replace_equiv_address (DECL_RTL (exp), addr);
06865   }
06866 
06867       /* This is the case of an array whose size is to be determined
06868    from its initializer, while the initializer is still being parsed.
06869    See expand_decl.  */
06870 
06871       else if (GET_CODE (DECL_RTL (exp)) == MEM
06872          && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
06873   temp = validize_mem (DECL_RTL (exp));
06874 
06875       /* If DECL_RTL is memory, we are in the normal case and either
06876    the address is not valid or it is not a register and -fforce-addr
06877    is specified, get the address into a register.  */
06878 
06879       else if (GET_CODE (DECL_RTL (exp)) == MEM
06880          && modifier != EXPAND_CONST_ADDRESS
06881          && modifier != EXPAND_SUM
06882          && modifier != EXPAND_INITIALIZER
06883          && (! memory_address_p (DECL_MODE (exp),
06884                XEXP (DECL_RTL (exp), 0))
06885        || (flag_force_addr
06886            && GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG)))
06887   temp = replace_equiv_address (DECL_RTL (exp),
06888               copy_rtx (XEXP (DECL_RTL (exp), 0)));
06889 
06890       /* If we got something, return it.  But first, set the alignment
06891    if the address is a register.  */
06892       if (temp != 0)
06893   {
06894     if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG)
06895       mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp));
06896 
06897     return temp;
06898   }
06899 
06900       /* If the mode of DECL_RTL does not match that of the decl, it
06901    must be a promoted value.  We return a SUBREG of the wanted mode,
06902    but mark it so that we know that it was already extended.  */
06903 
06904       if (GET_CODE (DECL_RTL (exp)) == REG
06905     && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
06906   {
06907     /* Get the signedness used for this variable.  Ensure we get the
06908        same mode we got when the variable was declared.  */
06909     if (GET_MODE (DECL_RTL (exp))
06910         != promote_mode (type, DECL_MODE (exp), &unsignedp,
06911              (TREE_CODE (exp) == RESULT_DECL ? 1 : 0)))
06912       abort ();
06913 
06914     temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
06915     SUBREG_PROMOTED_VAR_P (temp) = 1;
06916     SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
06917     return temp;
06918   }
06919 
06920       return DECL_RTL (exp);
06921 
06922     case INTEGER_CST:
06923       temp = immed_double_const (TREE_INT_CST_LOW (exp),
06924          TREE_INT_CST_HIGH (exp), mode);
06925 
06926       /* ??? If overflow is set, fold will have done an incomplete job,
06927    which can result in (plus xx (const_int 0)), which can get
06928    simplified by validate_replace_rtx during virtual register
06929    instantiation, which can result in unrecognizable insns.
06930    Avoid this by forcing all overflows into registers.  */
06931       if (TREE_CONSTANT_OVERFLOW (exp)
06932     && modifier != EXPAND_INITIALIZER)
06933   temp = force_reg (mode, temp);
06934 
06935       return temp;
06936 
06937     case VECTOR_CST:
06938       return const_vector_from_tree (exp);
06939 
06940     case CONST_DECL:
06941       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
06942 
06943     case REAL_CST:
06944       /* If optimized, generate immediate CONST_DOUBLE
06945    which will be turned into memory by reload if necessary.
06946 
06947    We used to force a register so that loop.c could see it.  But
06948    this does not allow gen_* patterns to perform optimizations with
06949    the constants.  It also produces two insns in cases like "x = 1.0;".
06950    On most machines, floating-point constants are not permitted in
06951    many insns, so we'd end up copying it to a register in any case.
06952 
06953    Now, we do the copying in expand_binop, if appropriate.  */
06954       return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp),
06955              TYPE_MODE (TREE_TYPE (exp)));
06956 
06957     case COMPLEX_CST:
06958     case STRING_CST:
06959       if (! TREE_CST_RTL (exp))
06960   output_constant_def (exp, 1);
06961 
06962       /* TREE_CST_RTL probably contains a constant address.
06963    On RISC machines where a constant address isn't valid,
06964    make some insns to get that address into a register.  */
06965       if (GET_CODE (TREE_CST_RTL (exp)) == MEM
06966     && modifier != EXPAND_CONST_ADDRESS
06967     && modifier != EXPAND_INITIALIZER
06968     && modifier != EXPAND_SUM
06969     && (! memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))
06970         || (flag_force_addr
06971       && GET_CODE (XEXP (TREE_CST_RTL (exp), 0)) != REG)))
06972   return replace_equiv_address (TREE_CST_RTL (exp),
06973               copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
06974       return TREE_CST_RTL (exp);
06975 
06976     case EXPR_WITH_FILE_LOCATION:
06977       {
06978   rtx to_return;
06979   const char *saved_input_filename = input_filename;
06980   int saved_lineno = lineno;
06981   input_filename = EXPR_WFL_FILENAME (exp);
06982   lineno = EXPR_WFL_LINENO (exp);
06983   if (EXPR_WFL_EMIT_LINE_NOTE (exp))
06984     emit_line_note (input_filename, lineno);
06985   /* Possibly avoid switching back and forth here.  */
06986   to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
06987   input_filename = saved_input_filename;
06988   lineno = saved_lineno;
06989   return to_return;
06990       }
06991 
06992     case SAVE_EXPR:
06993       context = decl_function_context (exp);
06994 
06995       /* If this SAVE_EXPR was at global context, assume we are an
06996    initialization function and move it into our context.  */
06997       if (context == 0)
06998   SAVE_EXPR_CONTEXT (exp) = current_function_decl;
06999 
07000       /* We treat inline_function_decl as an alias for the current function
07001    because that is the inline function whose vars, types, etc.
07002    are being merged into the current function.
07003    See expand_inline_function.  */
07004       if (context == current_function_decl || context == inline_function_decl)
07005   context = 0;
07006 
07007       /* If this is non-local, handle it.  */
07008       if (context)
07009   {
07010     /* The following call just exists to abort if the context is
07011        not of a containing function.  */
07012     find_function_data (context);
07013 
07014     temp = SAVE_EXPR_RTL (exp);
07015     if (temp && GET_CODE (temp) == REG)
07016       {
07017         put_var_into_stack (exp, /*rescan=*/true);
07018         temp = SAVE_EXPR_RTL (exp);
07019       }
07020     if (temp == 0 || GET_CODE (temp) != MEM)
07021       abort ();
07022     return
07023       replace_equiv_address (temp,
07024            fix_lexical_addr (XEXP (temp, 0), exp));
07025   }
07026       if (SAVE_EXPR_RTL (exp) == 0)
07027   {
07028     if (mode == VOIDmode)
07029       temp = const0_rtx;
07030     else
07031       temp = assign_temp (build_qualified_type (type,
07032                   (TYPE_QUALS (type)
07033                    | TYPE_QUAL_CONST)),
07034         3, 0, 0);
07035 
07036     SAVE_EXPR_RTL (exp) = temp;
07037     if (!optimize && GET_CODE (temp) == REG)
07038       save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, temp,
07039             save_expr_regs);
07040 
07041     /* If the mode of TEMP does not match that of the expression, it
07042        must be a promoted value.  We pass store_expr a SUBREG of the
07043        wanted mode but mark it so that we know that it was already
07044        extended.  */
07045 
07046     if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
07047       {
07048         temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
07049         promote_mode (type, mode, &unsignedp, 0);
07050         SUBREG_PROMOTED_VAR_P (temp) = 1;
07051         SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
07052       }
07053 
07054     if (temp == const0_rtx)
07055       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
07056     else
07057       store_expr (TREE_OPERAND (exp, 0), temp,
07058       modifier == EXPAND_STACK_PARM ? 2 : 0);
07059 
07060     TREE_USED (exp) = 1;
07061   }
07062 
07063       /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it
07064    must be a promoted value.  We return a SUBREG of the wanted mode,
07065    but mark it so that we know that it was already extended.  */
07066 
07067       if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG
07068     && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
07069   {
07070     /* Compute the signedness and make the proper SUBREG.  */
07071     promote_mode (type, mode, &unsignedp, 0);
07072     temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
07073     SUBREG_PROMOTED_VAR_P (temp) = 1;
07074     SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
07075     return temp;
07076   }
07077 
07078       return SAVE_EXPR_RTL (exp);
07079 
07080     case UNSAVE_EXPR:
07081       {
07082   rtx temp;
07083   temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
07084   TREE_OPERAND (exp, 0)
07085     = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
07086   return temp;
07087       }
07088 
07089     case PLACEHOLDER_EXPR:
07090       {
07091   tree old_list = placeholder_list;
07092   tree placeholder_expr = 0;
07093 
07094   exp = find_placeholder (exp, &placeholder_expr);
07095   if (exp == 0)
07096     abort ();
07097 
07098   placeholder_list = TREE_CHAIN (placeholder_expr);
07099   temp = expand_expr (exp, original_target, tmode, modifier);
07100   placeholder_list = old_list;
07101   return temp;
07102       }
07103 
07104     case WITH_RECORD_EXPR:
07105       /* Put the object on the placeholder list, expand our first operand,
07106    and pop the list.  */
07107       placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
07108             placeholder_list);
07109       target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode,
07110           modifier);
07111       placeholder_list = TREE_CHAIN (placeholder_list);
07112       return target;
07113 
07114     case GOTO_EXPR:
07115       if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
07116   expand_goto (TREE_OPERAND (exp, 0));
07117       else
07118   expand_computed_goto (TREE_OPERAND (exp, 0));
07119       return const0_rtx;
07120 
07121     case EXIT_EXPR:
07122       expand_exit_loop_if_false (NULL,
07123          invert_truthvalue (TREE_OPERAND (exp, 0)));
07124       return const0_rtx;
07125 
07126     case LABELED_BLOCK_EXPR:
07127       if (LABELED_BLOCK_BODY (exp))
07128   expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1);
07129       /* Should perhaps use expand_label, but this is simpler and safer.  */
07130       do_pending_stack_adjust ();
07131       emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
07132       return const0_rtx;
07133 
07134     case EXIT_BLOCK_EXPR:
07135       if (EXIT_BLOCK_RETURN (exp))
07136   sorry ("returned value in block_exit_expr");
07137       expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp)));
07138       return const0_rtx;
07139 
07140     case LOOP_EXPR:
07141       push_temp_slots ();
07142       expand_start_loop (1);
07143       expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
07144       expand_end_loop ();
07145       pop_temp_slots ();
07146 
07147       return const0_rtx;
07148 
07149     case BIND_EXPR:
07150       {
07151   tree vars = TREE_OPERAND (exp, 0);
07152   int vars_need_expansion = 0;
07153 
07154   /* Need to open a binding contour here because
07155      if there are any cleanups they must be contained here.  */
07156   expand_start_bindings (2);
07157 
07158   /* Mark the corresponding BLOCK for output in its proper place.  */
07159   if (TREE_OPERAND (exp, 2) != 0
07160       && ! TREE_USED (TREE_OPERAND (exp, 2)))
07161     (*lang_hooks.decls.insert_block) (TREE_OPERAND (exp, 2));
07162 
07163   /* If VARS have not yet been expanded, expand them now.  */
07164   while (vars)
07165     {
07166       if (!DECL_RTL_SET_P (vars))
07167         {
07168     vars_need_expansion = 1;
07169     expand_decl (vars);
07170         }
07171       expand_decl_init (vars);
07172       vars = TREE_CHAIN (vars);
07173     }
07174 
07175   temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier);
07176 
07177   expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
07178 
07179   return temp;
07180       }
07181 
07182     case RTL_EXPR:
07183       if (RTL_EXPR_SEQUENCE (exp))
07184   {
07185     if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
07186       abort ();
07187     emit_insn (RTL_EXPR_SEQUENCE (exp));
07188     RTL_EXPR_SEQUENCE (exp) = const0_rtx;
07189   }
07190       preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
07191       free_temps_for_rtl_expr (exp);
07192       return RTL_EXPR_RTL (exp);
07193 
07194     case CONSTRUCTOR:
07195       /* If we don't need the result, just ensure we evaluate any
07196    subexpressions.  */
07197       if (ignore)
07198   {
07199     tree elt;
07200 
07201     for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
07202       expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
07203 
07204     return const0_rtx;
07205   }
07206 
07207       /* All elts simple constants => refer to a constant in memory.  But
07208    if this is a non-BLKmode mode, let it store a field at a time
07209    since that should make a CONST_INT or CONST_DOUBLE when we
07210    fold.  Likewise, if we have a target we can use, it is best to
07211    store directly into the target unless the type is large enough
07212    that memcpy will be used.  If we are making an initializer and
07213    all operands are constant, put it in memory as well.
07214 
07215   FIXME: Avoid trying to fill vector constructors piece-meal.
07216   Output them with output_constant_def below unless we're sure
07217   they're zeros.  This should go away when vector initializers
07218   are treated like VECTOR_CST instead of arrays.
07219       */
07220       else if ((TREE_STATIC (exp)
07221     && ((mode == BLKmode
07222          && ! (target != 0 && safe_from_p (target, exp, 1)))
07223         || TREE_ADDRESSABLE (exp)
07224         || (host_integerp (TYPE_SIZE_UNIT (type), 1)
07225       && (! MOVE_BY_PIECES_P
07226           (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
07227            TYPE_ALIGN (type)))
07228       && ((TREE_CODE (type) == VECTOR_TYPE
07229            && !is_zeros_p (exp))
07230           || ! mostly_zeros_p (exp)))))
07231          || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
07232   {
07233     rtx constructor = output_constant_def (exp, 1);
07234 
07235     if (modifier != EXPAND_CONST_ADDRESS
07236         && modifier != EXPAND_INITIALIZER
07237         && modifier != EXPAND_SUM)
07238       constructor = validize_mem (constructor);
07239 
07240     return constructor;
07241   }
07242       else
07243   {
07244     /* Handle calls that pass values in multiple non-contiguous
07245        locations.  The Irix 6 ABI has examples of this.  */
07246     if (target == 0 || ! safe_from_p (target, exp, 1)
07247         || GET_CODE (target) == PARALLEL
07248         || modifier == EXPAND_STACK_PARM)
07249       target
07250         = assign_temp (build_qualified_type (type,
07251                (TYPE_QUALS (type)
07252                 | (TREE_READONLY (exp)
07253                    * TYPE_QUAL_CONST))),
07254            0, TREE_ADDRESSABLE (exp), 1);
07255 
07256     store_constructor (exp, target, 0, int_expr_size (exp));
07257     return target;
07258   }
07259 
07260     case INDIRECT_REF:
07261       {
07262   tree exp1 = TREE_OPERAND (exp, 0);
07263   tree index;
07264   tree string = string_constant (exp1, &index);
07265 
07266   /* Try to optimize reads from const strings.  */
07267   if (string
07268       && TREE_CODE (string) == STRING_CST
07269       && TREE_CODE (index) == INTEGER_CST
07270       && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
07271       && GET_MODE_CLASS (mode) == MODE_INT
07272       && GET_MODE_SIZE (mode) == 1
07273       && modifier != EXPAND_WRITE)
07274     return gen_int_mode (TREE_STRING_POINTER (string)
07275              [TREE_INT_CST_LOW (index)], mode);
07276 
07277   op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
07278   op0 = memory_address (mode, op0);
07279   temp = gen_rtx_MEM (mode, op0);
07280   set_mem_attributes (temp, exp, 0);
07281 
07282   /* If we are writing to this object and its type is a record with
07283      readonly fields, we must mark it as readonly so it will
07284      conflict with readonly references to those fields.  */
07285   if (modifier == EXPAND_WRITE && readonly_fields_p (type))
07286     RTX_UNCHANGING_P (temp) = 1;
07287 
07288   return temp;
07289       }
07290 
07291     case ARRAY_REF:
07292       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
07293   abort ();
07294 
07295       {
07296   tree array = TREE_OPERAND (exp, 0);
07297   tree domain = TYPE_DOMAIN (TREE_TYPE (array));
07298   tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
07299   tree index = convert (sizetype, TREE_OPERAND (exp, 1));
07300   HOST_WIDE_INT i;
07301 
07302   /* Optimize the special-case of a zero lower bound.
07303 
07304      We convert the low_bound to sizetype to avoid some problems
07305      with constant folding.  (E.g. suppose the lower bound is 1,
07306      and its mode is QI.  Without the conversion,  (ARRAY
07307      +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
07308      +INDEX), which becomes (ARRAY+255+INDEX).  Oops!)  */
07309 
07310   if (! integer_zerop (low_bound))
07311     index = size_diffop (index, convert (sizetype, low_bound));
07312 
07313   /* Fold an expression like: "foo"[2].
07314      This is not done in fold so it won't happen inside &.
07315      Don't fold if this is for wide characters since it's too
07316      difficult to do correctly and this is a very rare case.  */
07317 
07318   if (modifier != EXPAND_CONST_ADDRESS
07319       && modifier != EXPAND_INITIALIZER
07320       && modifier != EXPAND_MEMORY
07321       && TREE_CODE (array) == STRING_CST
07322       && TREE_CODE (index) == INTEGER_CST
07323       && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
07324       && GET_MODE_CLASS (mode) == MODE_INT
07325       && GET_MODE_SIZE (mode) == 1)
07326     return gen_int_mode (TREE_STRING_POINTER (array)
07327              [TREE_INT_CST_LOW (index)], mode);
07328 
07329   /* If this is a constant index into a constant array,
07330      just get the value from the array.  Handle both the cases when
07331      we have an explicit constructor and when our operand is a variable
07332      that was declared const.  */
07333 
07334   if (modifier != EXPAND_CONST_ADDRESS
07335       && modifier != EXPAND_INITIALIZER
07336       && modifier != EXPAND_MEMORY
07337       && TREE_CODE (array) == CONSTRUCTOR
07338       && ! TREE_SIDE_EFFECTS (array)
07339       && TREE_CODE (index) == INTEGER_CST
07340       && 0 > compare_tree_int (index,
07341              list_length (CONSTRUCTOR_ELTS
07342               (TREE_OPERAND (exp, 0)))))
07343     {
07344       tree elem;
07345 
07346       for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
07347      i = TREE_INT_CST_LOW (index);
07348      elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
07349         ;
07350 
07351       if (elem)
07352         return expand_expr (fold (TREE_VALUE (elem)), target, tmode,
07353           modifier);
07354     }
07355 
07356   else if (optimize >= 1
07357      && modifier != EXPAND_CONST_ADDRESS
07358      && modifier != EXPAND_INITIALIZER
07359      && modifier != EXPAND_MEMORY
07360      && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
07361      && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
07362      && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
07363     {
07364       if (TREE_CODE (index) == INTEGER_CST)
07365         {
07366     tree init = DECL_INITIAL (array);
07367 
07368     if (TREE_CODE (init) == CONSTRUCTOR)
07369       {
07370         tree elem;
07371 
07372         for (elem = CONSTRUCTOR_ELTS (init);
07373        (elem
07374         && !tree_int_cst_equal (TREE_PURPOSE (elem), index));
07375        elem = TREE_CHAIN (elem))
07376           ;
07377 
07378         if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
07379           return expand_expr (fold (TREE_VALUE (elem)), target,
07380             tmode, modifier);
07381       }
07382     else if (TREE_CODE (init) == STRING_CST
07383        && 0 > compare_tree_int (index,
07384               TREE_STRING_LENGTH (init)))
07385       {
07386         tree type = TREE_TYPE (TREE_TYPE (init));
07387         enum machine_mode mode = TYPE_MODE (type);
07388 
07389         if (GET_MODE_CLASS (mode) == MODE_INT
07390       && GET_MODE_SIZE (mode) == 1)
07391           return gen_int_mode (TREE_STRING_POINTER (init)
07392              [TREE_INT_CST_LOW (index)], mode);
07393       }
07394         }
07395     }
07396       }
07397       /* Fall through.  */
07398 
07399     case COMPONENT_REF:
07400     case BIT_FIELD_REF:
07401     case ARRAY_RANGE_REF:
07402       /* If the operand is a CONSTRUCTOR, we can just extract the
07403    appropriate field if it is present.  Don't do this if we have
07404    already written the data since we want to refer to that copy
07405    and varasm.c assumes that's what we'll do.  */
07406       if (code == COMPONENT_REF
07407     && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
07408     && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
07409   {
07410     tree elt;
07411 
07412     for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
07413          elt = TREE_CHAIN (elt))
07414       if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1)
07415     /* We can normally use the value of the field in the
07416        CONSTRUCTOR.  However, if this is a bitfield in
07417        an integral mode that we can fit in a HOST_WIDE_INT,
07418        we must mask only the number of bits in the bitfield,
07419        since this is done implicitly by the constructor.  If
07420        the bitfield does not meet either of those conditions,
07421        we can't do this optimization.  */
07422     && (! DECL_BIT_FIELD (TREE_PURPOSE (elt))
07423         || ((GET_MODE_CLASS (DECL_MODE (TREE_PURPOSE (elt)))
07424        == MODE_INT)
07425       && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
07426           <= HOST_BITS_PER_WIDE_INT))))
07427         {
07428     if (DECL_BIT_FIELD (TREE_PURPOSE (elt))
07429         && modifier == EXPAND_STACK_PARM)
07430       target = 0;
07431     op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
07432     if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
07433       {
07434         HOST_WIDE_INT bitsize
07435           = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt)));
07436         enum machine_mode imode
07437           = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt)));
07438 
07439         if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt))))
07440           {
07441       op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
07442       op0 = expand_and (imode, op0, op1, target);
07443           }
07444         else
07445           {
07446       tree count
07447         = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize,
07448            0);
07449 
07450       op0 = expand_shift (LSHIFT_EXPR, imode, op0, count,
07451               target, 0);
07452       op0 = expand_shift (RSHIFT_EXPR, imode, op0, count,
07453               target, 0);
07454           }
07455       }
07456 
07457     return op0;
07458         }
07459   }
07460 
07461       {
07462   enum machine_mode mode1;
07463   HOST_WIDE_INT bitsize, bitpos;
07464   tree offset;
07465   int volatilep = 0;
07466   tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
07467           &mode1, &unsignedp, &volatilep);
07468   rtx orig_op0;
07469 
07470   /* If we got back the original object, something is wrong.  Perhaps
07471      we are evaluating an expression too early.  In any event, don't
07472      infinitely recurse.  */
07473   if (tem == exp)
07474     abort ();
07475 
07476   /* If TEM's type is a union of variable size, pass TARGET to the inner
07477      computation, since it will need a temporary and TARGET is known
07478      to have to do.  This occurs in unchecked conversion in Ada.  */
07479 
07480   orig_op0 = op0
07481     = expand_expr (tem,
07482        (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
07483         && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
07484             != INTEGER_CST)
07485         && modifier != EXPAND_STACK_PARM
07486         ? target : NULL_RTX),
07487        VOIDmode,
07488        (modifier == EXPAND_INITIALIZER
07489         || modifier == EXPAND_CONST_ADDRESS
07490         || modifier == EXPAND_STACK_PARM)
07491        ? modifier : EXPAND_NORMAL);
07492 
07493   /* If this is a constant, put it into a register if it is a
07494      legitimate constant and OFFSET is 0 and memory if it isn't.  */
07495   if (CONSTANT_P (op0))
07496     {
07497       enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
07498       if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
07499     && offset == 0)
07500         op0 = force_reg (mode, op0);
07501       else
07502         op0 = validize_mem (force_const_mem (mode, op0));
07503     }
07504 
07505   if (offset != 0)
07506     {
07507       rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
07508             EXPAND_SUM);
07509 
07510       /* If this object is in a register, put it into memory.
07511          This case can't occur in C, but can in Ada if we have
07512          unchecked conversion of an expression from a scalar type to
07513          an array or record type.  */
07514       if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
07515     || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
07516         {
07517     /* If the operand is a SAVE_EXPR, we can deal with this by
07518        forcing the SAVE_EXPR into memory.  */
07519     if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
07520       {
07521         put_var_into_stack (TREE_OPERAND (exp, 0), 
07522           /*rescan=*/true);
07523         op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
07524       }
07525     else
07526       {
07527         tree nt
07528           = build_qualified_type (TREE_TYPE (tem),
07529                 (TYPE_QUALS (TREE_TYPE (tem))
07530                  | TYPE_QUAL_CONST));
07531         rtx memloc = assign_temp (nt, 1, 1, 1);
07532 
07533         emit_move_insn (memloc, op0);
07534         op0 = memloc;
07535       }
07536         }
07537 
07538       if (GET_CODE (op0) != MEM)
07539         abort ();
07540 
07541 #ifdef POINTERS_EXTEND_UNSIGNED
07542       if (GET_MODE (offset_rtx) != Pmode)
07543         offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
07544 #else
07545       if (GET_MODE (offset_rtx) != ptr_mode)
07546         offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
07547 #endif
07548 
07549       /* A constant address in OP0 can have VOIDmode, we must not try
07550          to call force_reg for that case.  Avoid that case.  */
07551       if (GET_CODE (op0) == MEM
07552     && GET_MODE (op0) == BLKmode
07553     && GET_MODE (XEXP (op0, 0)) != VOIDmode
07554     && bitsize != 0
07555     && (bitpos % bitsize) == 0
07556     && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
07557     && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
07558         {
07559     op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
07560     bitpos = 0;
07561         }
07562 
07563       op0 = offset_address (op0, offset_rtx,
07564           highest_pow2_factor (offset));
07565     }
07566 
07567   /* If OFFSET is making OP0 more aligned than BIGGEST_ALIGNMENT,
07568      record its alignment as BIGGEST_ALIGNMENT.  */
07569   if (GET_CODE (op0) == MEM && bitpos == 0 && offset != 0
07570       && is_aligning_offset (offset, tem))
07571     set_mem_align (op0, BIGGEST_ALIGNMENT);
07572 
07573   /* Don't forget about volatility even if this is a bitfield.  */
07574   if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
07575     {
07576       if (op0 == orig_op0)
07577         op0 = copy_rtx (op0);
07578 
07579       MEM_VOLATILE_P (op0) = 1;
07580     }
07581 
07582   /* The following code doesn't handle CONCAT.
07583      Assume only bitpos == 0 can be used for CONCAT, due to
07584      one element arrays having the same mode as its element.  */
07585   if (GET_CODE (op0) == CONCAT)
07586     {
07587       if (bitpos != 0 || bitsize != GET_MODE_BITSIZE (GET_MODE (op0)))
07588         abort ();
07589       return op0;
07590     }
07591 
07592   /* In cases where an aligned union has an unaligned object
07593      as a field, we might be extracting a BLKmode value from
07594      an integer-mode (e.g., SImode) object.  Handle this case
07595      by doing the extract into an object as wide as the field
07596      (which we know to be the width of a basic mode), then
07597      storing into memory, and changing the mode to BLKmode.  */
07598   if (mode1 == VOIDmode
07599       || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
07600       || (mode1 != BLKmode && ! direct_load[(int) mode1]
07601     && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
07602     && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
07603     && modifier != EXPAND_CONST_ADDRESS
07604     && modifier != EXPAND_INITIALIZER)
07605       /* If the field isn't aligned enough to fetch as a memref,
07606          fetch it as a bit field.  */
07607       || (mode1 != BLKmode
07608     && SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0))
07609     && ((TYPE_ALIGN (TREE_TYPE (tem))
07610          < GET_MODE_ALIGNMENT (mode))
07611         || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
07612       /* If the type and the field are a constant size and the
07613          size of the type isn't the same size as the bitfield,
07614 <