00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00041 #include "insn-flags.h"
00042 #endif
00043
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
00058 #include "defaults.h"
00059 #endif
00060
00061
00062
00063
00064
00065
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
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
00086 #ifndef CASE_VECTOR_PC_RELATIVE
00087 #define CASE_VECTOR_PC_RELATIVE 0
00088 #endif
00089
00090
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
00100
00101
00102
00103
00104
00105 int cse_not_expected;
00106
00107
00108 static tree placeholder_list = 0;
00109
00110
00111
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
00128
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
00195
00196
00197
00198 static char direct_load[NUM_MACHINE_MODES];
00199 static char direct_store[NUM_MACHINE_MODES];
00200
00201
00202
00203 static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
00204
00205
00206
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
00213 #define MOVE_RATIO (optimize_size ? 3 : 15)
00214 #endif
00215 #endif
00216
00217
00218
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
00225
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
00232 #define CLEAR_RATIO (optimize_size ? 3 : 15)
00233 #endif
00234 #endif
00235
00236
00237
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
00244 enum insn_code movstr_optab[NUM_MACHINE_MODES];
00245
00246
00247 enum insn_code clrstr_optab[NUM_MACHINE_MODES];
00248
00249
00250
00251 #ifndef SLOW_UNALIGNED_ACCESS
00252 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
00253 #endif
00254
00255
00256
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
00268
00269
00270 mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
00271 mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
00272
00273
00274
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
00292
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
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
00366
00367 void
00368 finish_expr_for_function ()
00369 {
00370 if (pending_chain)
00371 abort ();
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
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
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
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
00416
00417 if (pending_chain == 0)
00418 return x;
00419 #endif
00420
00421 if (code != QUEUED)
00422 {
00423
00424
00425
00426
00427
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
00444
00445 return replace_equiv_address (new, copy_to_reg (XEXP (new, 0)));
00446 }
00447
00448
00449
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
00473
00474
00475 if (QUEUED_INSN (x) == 0)
00476 return copy_to_reg (QUEUED_VAR (x));
00477
00478
00479 if (QUEUED_COPY (x) != 0)
00480 return QUEUED_COPY (x);
00481
00482
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
00490
00491
00492
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
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
00553
00554
00555
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
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
00580
00581
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
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
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
00869
00870
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
00883 if ((code = can_extend_p (to_mode, from_mode, unsignedp))
00884 != CODE_FOR_nothing)
00885 {
00886
00887
00888
00889
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
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
00909 start_sequence ();
00910
00911
00912
00913
00914 if (reg_overlap_mentioned_p (to, from))
00915 from = force_reg (from_mode, from);
00916
00917
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
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
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
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
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
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
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
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
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
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
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
01099 abort ();
01100 }
01101 }
01102
01103
01104
01105
01106
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
01126 if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
01127 {
01128
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
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
01161
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
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
01308
01309
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
01318 abort ();
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
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
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
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
01362
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
01376
01377
01378
01379
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
01393 val &= ((HOST_WIDE_INT) 1 << width) - 1;
01394 }
01395
01396 return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
01397 }
01398
01399
01400
01401
01402
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
01419
01420
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
01428
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
01441
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
01455
01456
01457
01458
01459
01460
01461 #ifndef MOVE_MAX_PIECES
01462 #define MOVE_MAX_PIECES MOVE_MAX
01463 #endif
01464
01465
01466
01467
01468
01469
01470 #define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
01471
01472
01473
01474
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
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
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
01546
01547
01548 if (!(data.autinc_from && data.autinc_to)
01549 && move_by_pieces_ninsns (len, align) > 2)
01550 {
01551
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
01592
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
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
01647
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
01687
01688
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
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
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
01780
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
01811
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
01839
01840
01841
01842 static bool
01843 block_move_libcall_safe_for_call_parm ()
01844 {
01845 if (PUSH_ARGS)
01846 return true;
01847 else
01848 {
01849
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
01881
01882 case takes_regs_yes:
01883 return true;
01884
01885 fail_takes_regs:
01886 takes_regs = takes_regs_no;
01887
01888 case takes_regs_no:
01889 return false;
01890
01891 default:
01892 abort ();
01893 }
01894 }
01895 }
01896
01897
01898
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
01906
01907
01908
01909 rtx opalign = GEN_INT (align / BITS_PER_UNIT);
01910 enum machine_mode mode;
01911
01912
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
01923
01924
01925
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
01947
01948
01949
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
01968
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
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
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
02010
02011
02012
02013
02014
02015
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
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
02046
02047
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
02055
02056
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
02119
02120
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
02172
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
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
02216
02217
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
02237
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
02246
02247
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
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
02293
02294
02295
02296
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
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
02329
02330
02331
02332
02333
02334
02335
02336
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
02350
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
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
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
02376
02377
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
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
02410
02411
02412
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
02445 for (i = start; i < XVECLEN (dst, 0); i++)
02446 emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
02447 }
02448
02449
02450
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
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
02470
02471
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
02485
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
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
02503
02504 dst = orig_dst;
02505 if (GET_CODE (dst) == PARALLEL)
02506 {
02507 rtx temp;
02508
02509
02510
02511
02512 if (rtx_equal_p (dst, src))
02513 return;
02514
02515
02516
02517
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
02528 emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
02529 }
02530
02531
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
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
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
02587 if (orig_dst != dst)
02588 emit_move_insn (orig_dst, dst);
02589 }
02590
02591
02592
02593
02594
02595
02596
02597
02598
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
02621
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
02628
02629
02630
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
02637
02638
02639
02640
02641 for (bitpos = 0, xbitpos = big_endian_correction;
02642 bitpos < bytes * BITS_PER_UNIT;
02643 bitpos += bitsize, xbitpos += bitsize)
02644 {
02645
02646
02647
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
02654
02655 if (bitpos % BITS_PER_WORD == 0)
02656 dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
02657
02658
02659
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
02672
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
02688
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
02706
02707
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
02721
02722
02723 if (reg != 0 && GET_CODE (reg) == REG)
02724 use_reg (call_fusage, reg);
02725 }
02726 }
02727
02728
02729
02730
02731
02732
02733
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
02760
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
02805 if (l != 0)
02806 abort ();
02807 }
02808
02809 return 1;
02810 }
02811
02812
02813
02814
02815
02816
02817
02818
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
02878
02879
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
02900
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
02912
02913
02914
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
02939
02940
02941 if (!data->autinc_to
02942 && move_by_pieces_ninsns (data->len, align) > 2)
02943 {
02944
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
02974
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
02994 if (data->len != 0)
02995 abort ();
02996 }
02997
02998
02999
03000
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
03040
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
03052
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
03077
03078
03079 static bool
03080 clear_storage_via_clrstr (object, size, align)
03081 rtx object, size;
03082 unsigned int align;
03083 {
03084
03085
03086
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
03099
03100
03101
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
03135
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
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
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
03176
03177
03178
03179
03180
03181
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
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
03204
03205
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
03213
03214
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
03276
03277
03278
03279
03280
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
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
03314
03315
03316 if (!y)
03317 y = y_cst;
03318 }
03319 }
03320
03321
03322
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
03348
03349
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
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
03373 int stack = push_operand (x, GET_MODE (x));
03374
03375 #ifdef PUSH_ROUNDING
03376
03377
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
03386
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
03425
03426
03427
03428
03429 if (stack)
03430 {
03431
03432
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
03455
03456
03457
03458
03459
03460
03461
03462
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
03512
03513
03514
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
03531
03532
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
03543
03544 if (push_operand (x, GET_MODE (x)))
03545 {
03546 rtx temp;
03547 enum rtx_code code;
03548
03549
03550
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
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
03584
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
03603
03604
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
03625
03626
03627
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
03642
03643
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
03664 ic = can_extend_p (dstmode, srcmode, 0);
03665 if (ic == CODE_FOR_nothing)
03666 continue;
03667
03668
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
03677
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
03700
03701
03702
03703
03704
03705
03706
03707
03708
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
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
03775
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
03807
03808
03809
03810 set_mem_alias_set (dest, 0);
03811 }
03812 emit_move_insn (dest, x);
03813 }
03814 #endif
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
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
03874
03875
03876 enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
03877
03878
03879
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
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
03901
03902
03903 if (partial != 0)
03904 xinner = adjust_address (xinner, BLKmode, used);
03905
03906
03907
03908
03909
03910 skip = (reg_parm_stack_space == 0) ? 0 : used;
03911
03912 #ifdef PUSH_ROUNDING
03913
03914
03915
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
03922
03923
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
03931
03932
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
03941 {
03942 rtx target;
03943
03944
03945
03946
03947
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
03959
03960
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
03980
03981
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
03994
03995
03996
03997 set_mem_alias_set (target, 0);
03998 }
03999
04000
04001
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
04010
04011 int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
04012 int i;
04013 int not_stack;
04014
04015
04016 int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
04017 int args_offset = INTVAL (args_so_far);
04018 int skip;
04019
04020
04021
04022
04023 if (extra && args_addr == 0
04024 && where_pad != none && where_pad != stack_direction)
04025 anti_adjust_stack (GEN_INT (extra));
04026
04027
04028
04029
04030 if (args_addr == 0)
04031 offset = 0;
04032
04033
04034
04035 not_stack = partial - offset;
04036
04037
04038
04039
04040
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
04047
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
04053
04054
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
04075
04076
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
04101
04102
04103
04104 set_mem_alias_set (dest, 0);
04105 }
04106
04107 emit_move_insn (dest, x);
04108 }
04109 }
04110
04111
04112
04113
04114 if (partial > 0 && reg != 0)
04115 {
04116
04117
04118 if (GET_CODE (reg) == PARALLEL)
04119 emit_group_load (reg, x, -1);
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
04132
04133
04134 static rtx
04135 get_subtarget (x)
04136 rtx x;
04137 {
04138 return ((x == 0
04139
04140 || GET_CODE (x) != REG
04141
04142 || RTX_UNCHANGING_P (x)
04143
04144 || REGNO (x) < FIRST_PSEUDO_REGISTER
04145
04146
04147 || preserve_subexpressions_p ())
04148 ? 0 : x);
04149 }
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
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
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
04180
04181
04182
04183
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
04202
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
04225
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
04246
04247 to_rtx = shallow_copy_rtx (to_rtx);
04248
04249 set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
04250 }
04251
04252
04253
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
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
04289
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
04298
04299
04300
04301
04302
04303
04304
04305
04306
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
04320
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
04341
04342
04343 if (to_rtx == 0)
04344 to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
04345
04346
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
04367
04368
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
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
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
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
04450
04451
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
04460
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
04469
04470
04471
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
04499
04500 {
04501 if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
04502 {
04503
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
04515
04516
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
04525
04526
04527
04528
04529
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
04536
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
04547
04548
04549
04550 {
04551 rtx inner_target = 0;
04552
04553
04554
04555
04556
04557
04558
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
04581
04582
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
04589
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
04603
04604
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
04628
04629
04630
04631
04632
04633
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
04643
04644
04645
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
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
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
04672
04673
04674 && (TREE_CODE_CLASS (TREE_CODE (exp)) != 'd'
04675 || target != DECL_RTL_IF_SET (exp))
04676
04677
04678
04679
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
04690
04691
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
04702
04703
04704
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
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
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
04733
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
04767
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
04779 if ((want_value & 1) == 0)
04780 return NULL_RTX;
04781
04782
04783
04784 else if (dont_return_target && GET_CODE (temp) != MEM)
04785 return temp;
04786
04787
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
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
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
04859 return elt == NULL_TREE;
04860 }
04861 for (; elt; elt = TREE_CHAIN (elt))
04862 {
04863
04864
04865
04866
04867
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
04880
04881
04882
04883
04884
04885
04886
04887
04888
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
04904
04905
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
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
04933
04934
04935
04936
04937
04938
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
04958 if (size == 0 || cleared)
04959 cleared = 1;
04960
04961 else if ((TREE_CODE (type) == UNION_TYPE
04962 || TREE_CODE (type) == QUAL_UNION_TYPE)
04963 && ! CONSTRUCTOR_ELTS (exp))
04964
04965 {
04966 clear_storage (target, expr_size (exp));
04967 cleared = 1;
04968 }
04969
04970
04971
04972
04973
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
04982
04983
04984
04985
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
05000
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
05014
05015
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
05076
05077
05078
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
05130
05131 if (TREE_CODE (type) == VECTOR_TYPE)
05132 {
05133
05134
05135
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
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
05153
05154
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
05163
05164
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
05196
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
05215 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
05216
05217
05218
05219
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
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
05303
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
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
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
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
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
05420
05421
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;
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
05453
05454
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
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
05487 tree startbit = TREE_PURPOSE (elt);
05488
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
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
05532
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
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
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
05601
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
05608
05609
05610
05611
05612
05613
05614
05615
05616
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
05636 return blk_object;
05637 }
05638
05639 if (GET_CODE (target) == CONCAT)
05640 {
05641
05642
05643 if (bitpos != 0)
05644 abort ();
05645 return store_expr (exp, target, 0);
05646 }
05647
05648
05649
05650
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
05659
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
05664
05665
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
05673
05674
05675
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
05685
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
05691
05692
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
05709 store_bit_field (target, bitsize, bitpos, mode, temp,
05710 int_size_in_bytes (type));
05711
05712 if (value_mode != VOIDmode)
05713 {
05714
05715
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
05748
05749
05750 if (value_mode != VOIDmode && GET_CODE (addr) != REG
05751 && ! CONSTANT_ADDRESS_P (addr)
05752
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
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
05775
05776
05777
05778
05779
05780
05781
05782
05783
05784
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
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
05815
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
05849
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
05860
05861
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
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
05885
05886
05887
05888 if (low_bound != 0 && ! integer_zerop (low_bound))
05889 index = fold (build (MINUS_EXPR, TREE_TYPE (index),
05890 index, low_bound));
05891
05892
05893
05894
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
05913
05914
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
05931 if (TREE_THIS_VOLATILE (exp))
05932 *pvolatilep = 1;
05933
05934 exp = TREE_OPERAND (exp, 0);
05935 }
05936
05937
05938
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
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
05979
05980
05981
05982
05983
05984
05985 rtx
05986 force_operand (value, target)
05987 rtx value, target;
05988 {
05989 rtx op1, op2;
05990
05991 rtx subtarget = get_subtarget (target);
05992 enum rtx_code code = GET_CODE (value);
05993
05994
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
06028
06029
06030
06031
06032
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
06093
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
06110
06111
06112
06113
06114
06115
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
06129
06130
06131
06132
06133
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
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
06149
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
06158
06159
06160
06161
06162
06163
06164
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
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;
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
06215
06216 case '1':
06217 return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
06218
06219 case 'e':
06220 case 'r':
06221
06222
06223
06224
06225
06226 switch (TREE_CODE (exp))
06227 {
06228 case ADDR_EXPR:
06229
06230
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
06237
06238
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
06259
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
06267
06268
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
06288
06289
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
06305
06306 return safe_from_p (x, TREE_OPERAND (exp, 1), 0);
06307
06308 case METHOD_CALL_EXPR:
06309
06310 abort ();
06311
06312 default:
06313 break;
06314 }
06315
06316
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
06327
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
06335
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
06347
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
06355 return 1;
06356 }
06357
06358
06359
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
06386 STRIP_NOPS (exp);
06387 code = TREE_CODE (exp);
06388
06389
06390 if (code == NOP_EXPR
06391 && TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
06392 return;
06393
06394
06395
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
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
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
06432
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
06444
06445
06446
06447
06448
06449 if (TREE_CONSTANT_OVERFLOW (exp))
06450 return BIGGEST_ALIGNMENT;
06451 else
06452 {
06453
06454
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
06502
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
06517
06518
06519
06520
06521
06522
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
06541
06542
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
06583
06584
06585
06586
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622
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
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
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
06661
06662
06663
06664
06665
06666 if (ignore)
06667 {
06668 if (! TREE_SIDE_EFFECTS (exp))
06669 return const0_rtx;
06670
06671
06672
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
06699
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
06715
06716
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
06757
06758
06759
06760
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
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
06805
06806 case VAR_DECL:
06807
06808
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
06815
06816 case FUNCTION_DECL:
06817 case RESULT_DECL:
06818 if (DECL_RTL (exp) == 0)
06819 abort ();
06820
06821
06822
06823
06824 if (! TREE_USED (exp))
06825 {
06826 assemble_external (exp);
06827 TREE_USED (exp) = 1;
06828 }
06829
06830
06831 temp = 0;
06832
06833
06834 context = decl_function_context (exp);
06835
06836
06837
06838
06839
06840
06841 if (context != 0 && context != current_function_decl
06842 && context != inline_function_decl
06843
06844 && ! (GET_CODE (DECL_RTL (exp)) == MEM
06845 && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
06846 {
06847 rtx addr;
06848
06849
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
06868
06869
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
06876
06877
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
06891
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
06901
06902
06903
06904 if (GET_CODE (DECL_RTL (exp)) == REG
06905 && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
06906 {
06907
06908
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
06927
06928
06929
06930
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
06945
06946
06947
06948
06949
06950
06951
06952
06953
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
06963
06964
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
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
06996
06997 if (context == 0)
06998 SAVE_EXPR_CONTEXT (exp) = current_function_decl;
06999
07000
07001
07002
07003
07004 if (context == current_function_decl || context == inline_function_decl)
07005 context = 0;
07006
07007
07008 if (context)
07009 {
07010
07011
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, 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
07042
07043
07044
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
07064
07065
07066
07067 if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG
07068 && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
07069 {
07070
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
07106
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
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
07155
07156 expand_start_bindings (2);
07157
07158
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
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
07196
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
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
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
07245
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
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
07283
07284
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
07303
07304
07305
07306
07307
07308
07309
07310 if (! integer_zerop (low_bound))
07311 index = size_diffop (index, convert (sizetype, low_bound));
07312
07313
07314
07315
07316
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
07330
07331
07332
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
07398
07399 case COMPONENT_REF:
07400 case BIT_FIELD_REF:
07401 case ARRAY_RANGE_REF:
07402
07403
07404
07405
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
07416
07417
07418
07419
07420
07421
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
07471
07472
07473 if (tem == exp)
07474 abort ();
07475
07476
07477
07478
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
07494
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
07511
07512
07513
07514 if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
07515 || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
07516 {
07517
07518
07519 if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
07520 {
07521 put_var_into_stack (TREE_OPERAND (exp, 0),
07522 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
07550
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
07568
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
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
07583
07584
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
07593
07594
07595
07596
07597
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
07606
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
07613
07614 <