00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "machmode.h"
00027 #include "real.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "flags.h"
00031 #include "regs.h"
00032 #include "hard-reg-set.h"
00033 #include "except.h"
00034 #include "function.h"
00035 #include "insn-config.h"
00036 #include "insn-attr.h"
00037
00038 #include "expr.h"
00039 #include "optabs.h"
00040 #include "libfuncs.h"
00041 #include "recog.h"
00042 #include "reload.h"
00043 #include "output.h"
00044 #include "typeclass.h"
00045 #include "toplev.h"
00046 #include "ggc.h"
00047 #include "langhooks.h"
00048 #include "intl.h"
00049 #include "tm_p.h"
00050 #include "tree-iterator.h"
00051 #include "tree-pass.h"
00052 #include "tree-flow.h"
00053 #include "target.h"
00054 #include "timevar.h"
00055
00056
00057
00058
00059
00060
00061
00062 #ifdef PUSH_ROUNDING
00063
00064 #ifndef PUSH_ARGS_REVERSED
00065 #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
00066 #define PUSH_ARGS_REVERSED
00067 #endif
00068 #endif
00069
00070 #endif
00071
00072 #ifndef STACK_PUSH_CODE
00073 #ifdef STACK_GROWS_DOWNWARD
00074 #define STACK_PUSH_CODE PRE_DEC
00075 #else
00076 #define STACK_PUSH_CODE PRE_INC
00077 #endif
00078 #endif
00079
00080
00081
00082
00083
00084
00085
00086
00087 int cse_not_expected;
00088
00089
00090
00091 struct move_by_pieces
00092 {
00093 rtx to;
00094 rtx to_addr;
00095 int autinc_to;
00096 int explicit_inc_to;
00097 rtx from;
00098 rtx from_addr;
00099 int autinc_from;
00100 int explicit_inc_from;
00101 unsigned HOST_WIDE_INT len;
00102 HOST_WIDE_INT offset;
00103 int reverse;
00104 };
00105
00106
00107
00108
00109 struct store_by_pieces
00110 {
00111 rtx to;
00112 rtx to_addr;
00113 int autinc_to;
00114 int explicit_inc_to;
00115 unsigned HOST_WIDE_INT len;
00116 HOST_WIDE_INT offset;
00117 rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode);
00118 void *constfundata;
00119 int reverse;
00120 };
00121
00122 static unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT,
00123 unsigned int,
00124 unsigned int);
00125 static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
00126 struct move_by_pieces *);
00127 static bool block_move_libcall_safe_for_call_parm (void);
00128 static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned);
00129 static rtx emit_block_move_via_libcall (rtx, rtx, rtx, bool);
00130 static tree emit_block_move_libcall_fn (int);
00131 static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned);
00132 static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode);
00133 static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
00134 static void store_by_pieces_1 (struct store_by_pieces *, unsigned int);
00135 static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
00136 struct store_by_pieces *);
00137 static bool clear_storage_via_clrmem (rtx, rtx, unsigned);
00138 static rtx clear_storage_via_libcall (rtx, rtx, bool);
00139 static tree clear_storage_libcall_fn (int);
00140 static rtx compress_float_constant (rtx, rtx);
00141 static rtx get_subtarget (rtx);
00142 static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
00143 HOST_WIDE_INT, enum machine_mode,
00144 tree, tree, int, int);
00145 static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
00146 static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode,
00147 tree, tree, int);
00148
00149 static unsigned HOST_WIDE_INT highest_pow2_factor (tree);
00150 static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (tree, tree);
00151
00152 static int is_aligning_offset (tree, tree);
00153 static void expand_operands (tree, tree, rtx, rtx*, rtx*,
00154 enum expand_modifier);
00155 static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
00156 static rtx do_store_flag (tree, rtx, enum machine_mode, int);
00157 #ifdef PUSH_ROUNDING
00158 static void emit_single_push_insn (enum machine_mode, rtx, tree);
00159 #endif
00160 static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
00161 static rtx const_vector_from_tree (tree);
00162 static void write_complex_part (rtx, rtx, bool);
00163
00164
00165
00166
00167
00168 static char direct_load[NUM_MACHINE_MODES];
00169 static char direct_store[NUM_MACHINE_MODES];
00170
00171
00172
00173 static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
00174
00175
00176
00177 #ifndef MOVE_BY_PIECES_P
00178 #define MOVE_BY_PIECES_P(SIZE, ALIGN) \
00179 (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
00180 < (unsigned int) MOVE_RATIO)
00181 #endif
00182
00183
00184
00185 #ifndef CLEAR_BY_PIECES_P
00186 #define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
00187 (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
00188 < (unsigned int) CLEAR_RATIO)
00189 #endif
00190
00191
00192
00193
00194 #ifndef STORE_BY_PIECES_P
00195 #define STORE_BY_PIECES_P(SIZE, ALIGN) \
00196 (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
00197 < (unsigned int) MOVE_RATIO)
00198 #endif
00199
00200
00201 enum insn_code movmem_optab[NUM_MACHINE_MODES];
00202
00203
00204 enum insn_code clrmem_optab[NUM_MACHINE_MODES];
00205
00206
00207
00208 enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
00209 enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
00210
00211
00212
00213 #ifndef SLOW_UNALIGNED_ACCESS
00214 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
00215 #endif
00216
00217
00218
00219
00220 void
00221 init_expr_once (void)
00222 {
00223 rtx insn, pat;
00224 enum machine_mode mode;
00225 int num_clobbers;
00226 rtx mem, mem1;
00227 rtx reg;
00228
00229
00230
00231
00232 mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
00233 mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
00234
00235
00236
00237 reg = gen_rtx_REG (VOIDmode, -1);
00238
00239 insn = rtx_alloc (INSN);
00240 pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
00241 PATTERN (insn) = pat;
00242
00243 for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
00244 mode = (enum machine_mode) ((int) mode + 1))
00245 {
00246 int regno;
00247
00248 direct_load[(int) mode] = direct_store[(int) mode] = 0;
00249 PUT_MODE (mem, mode);
00250 PUT_MODE (mem1, mode);
00251 PUT_MODE (reg, mode);
00252
00253
00254
00255
00256 if (mode != VOIDmode && mode != BLKmode)
00257 for (regno = 0; regno < FIRST_PSEUDO_REGISTER
00258 && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
00259 regno++)
00260 {
00261 if (! HARD_REGNO_MODE_OK (regno, mode))
00262 continue;
00263
00264 REGNO (reg) = regno;
00265
00266 SET_SRC (pat) = mem;
00267 SET_DEST (pat) = reg;
00268 if (recog (pat, insn, &num_clobbers) >= 0)
00269 direct_load[(int) mode] = 1;
00270
00271 SET_SRC (pat) = mem1;
00272 SET_DEST (pat) = reg;
00273 if (recog (pat, insn, &num_clobbers) >= 0)
00274 direct_load[(int) mode] = 1;
00275
00276 SET_SRC (pat) = reg;
00277 SET_DEST (pat) = mem;
00278 if (recog (pat, insn, &num_clobbers) >= 0)
00279 direct_store[(int) mode] = 1;
00280
00281 SET_SRC (pat) = reg;
00282 SET_DEST (pat) = mem1;
00283 if (recog (pat, insn, &num_clobbers) >= 0)
00284 direct_store[(int) mode] = 1;
00285 }
00286 }
00287
00288 mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
00289
00290 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
00291 mode = GET_MODE_WIDER_MODE (mode))
00292 {
00293 enum machine_mode srcmode;
00294 for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
00295 srcmode = GET_MODE_WIDER_MODE (srcmode))
00296 {
00297 enum insn_code ic;
00298
00299 ic = can_extend_p (mode, srcmode, 0);
00300 if (ic == CODE_FOR_nothing)
00301 continue;
00302
00303 PUT_MODE (mem, srcmode);
00304
00305 if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
00306 float_extend_from_mem[mode][srcmode] = true;
00307 }
00308 }
00309 }
00310
00311
00312
00313 void
00314 init_expr (void)
00315 {
00316 cfun->expr = ggc_alloc_cleared (sizeof (struct expr_status));
00317 }
00318
00319
00320
00321
00322
00323
00324 void
00325 convert_move (rtx to, rtx from, int unsignedp)
00326 {
00327 enum machine_mode to_mode = GET_MODE (to);
00328 enum machine_mode from_mode = GET_MODE (from);
00329 int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT;
00330 int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT;
00331 enum insn_code code;
00332 rtx libcall;
00333
00334
00335 enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
00336 : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
00337
00338
00339 gcc_assert (to_real == from_real);
00340
00341
00342
00343 if (to == from)
00344 return;
00345
00346
00347
00348
00349
00350 if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
00351 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from)))
00352 >= GET_MODE_SIZE (to_mode))
00353 && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
00354 from = gen_lowpart (to_mode, from), from_mode = to_mode;
00355
00356 gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to));
00357
00358 if (to_mode == from_mode
00359 || (from_mode == VOIDmode && CONSTANT_P (from)))
00360 {
00361 emit_move_insn (to, from);
00362 return;
00363 }
00364
00365 if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
00366 {
00367 gcc_assert (GET_MODE_BITSIZE (from_mode) == GET_MODE_BITSIZE (to_mode));
00368
00369 if (VECTOR_MODE_P (to_mode))
00370 from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0);
00371 else
00372 to = simplify_gen_subreg (from_mode, to, GET_MODE (to), 0);
00373
00374 emit_move_insn (to, from);
00375 return;
00376 }
00377
00378 if (GET_CODE (to) == CONCAT && GET_CODE (from) == CONCAT)
00379 {
00380 convert_move (XEXP (to, 0), XEXP (from, 0), unsignedp);
00381 convert_move (XEXP (to, 1), XEXP (from, 1), unsignedp);
00382 return;
00383 }
00384
00385 if (to_real)
00386 {
00387 rtx value, insns;
00388 convert_optab tab;
00389
00390 gcc_assert (GET_MODE_PRECISION (from_mode)
00391 != GET_MODE_PRECISION (to_mode));
00392
00393 if (GET_MODE_PRECISION (from_mode) < GET_MODE_PRECISION (to_mode))
00394 tab = sext_optab;
00395 else
00396 tab = trunc_optab;
00397
00398
00399
00400 code = tab->handlers[to_mode][from_mode].insn_code;
00401 if (code != CODE_FOR_nothing)
00402 {
00403 emit_unop_insn (code, to, from,
00404 tab == sext_optab ? FLOAT_EXTEND : FLOAT_TRUNCATE);
00405 return;
00406 }
00407
00408
00409 libcall = tab->handlers[to_mode][from_mode].libfunc;
00410
00411
00412 gcc_assert (libcall);
00413
00414 start_sequence ();
00415 value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
00416 1, from, from_mode);
00417 insns = get_insns ();
00418 end_sequence ();
00419 emit_libcall_block (insns, to, value,
00420 tab == trunc_optab ? gen_rtx_FLOAT_TRUNCATE (to_mode,
00421 from)
00422 : gen_rtx_FLOAT_EXTEND (to_mode, from));
00423 return;
00424 }
00425
00426
00427
00428
00429 if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT)
00430 {
00431 enum machine_mode full_mode
00432 = smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
00433
00434 gcc_assert (trunc_optab->handlers[to_mode][full_mode].insn_code
00435 != CODE_FOR_nothing);
00436
00437 if (full_mode != from_mode)
00438 from = convert_to_mode (full_mode, from, unsignedp);
00439 emit_unop_insn (trunc_optab->handlers[to_mode][full_mode].insn_code,
00440 to, from, UNKNOWN);
00441 return;
00442 }
00443 if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT)
00444 {
00445 enum machine_mode full_mode
00446 = smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
00447
00448 gcc_assert (sext_optab->handlers[full_mode][from_mode].insn_code
00449 != CODE_FOR_nothing);
00450
00451 emit_unop_insn (sext_optab->handlers[full_mode][from_mode].insn_code,
00452 to, from, UNKNOWN);
00453 if (to_mode == full_mode)
00454 return;
00455
00456
00457 from_mode = full_mode;
00458 }
00459
00460
00461
00462
00463 if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)
00464 && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD)
00465 {
00466 rtx insns;
00467 rtx lowpart;
00468 rtx fill_value;
00469 rtx lowfrom;
00470 int i;
00471 enum machine_mode lowpart_mode;
00472 int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
00473
00474
00475 if ((code = can_extend_p (to_mode, from_mode, unsignedp))
00476 != CODE_FOR_nothing)
00477 {
00478
00479
00480
00481
00482 if (optimize > 0 && GET_CODE (from) == SUBREG)
00483 from = force_reg (from_mode, from);
00484 emit_unop_insn (code, to, from, equiv_code);
00485 return;
00486 }
00487
00488 else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD
00489 && ((code = can_extend_p (to_mode, word_mode, unsignedp))
00490 != CODE_FOR_nothing))
00491 {
00492 if (REG_P (to))
00493 {
00494 if (reg_overlap_mentioned_p (to, from))
00495 from = force_reg (from_mode, from);
00496 emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
00497 }
00498 convert_move (gen_lowpart (word_mode, to), from, unsignedp);
00499 emit_unop_insn (code, to,
00500 gen_lowpart (word_mode, to), equiv_code);
00501 return;
00502 }
00503
00504
00505 start_sequence ();
00506
00507
00508
00509
00510 if (reg_overlap_mentioned_p (to, from))
00511 from = force_reg (from_mode, from);
00512
00513
00514 if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD)
00515 lowpart_mode = word_mode;
00516 else
00517 lowpart_mode = from_mode;
00518
00519 lowfrom = convert_to_mode (lowpart_mode, from, unsignedp);
00520
00521 lowpart = gen_lowpart (lowpart_mode, to);
00522 emit_move_insn (lowpart, lowfrom);
00523
00524
00525 if (unsignedp)
00526 fill_value = const0_rtx;
00527 else
00528 {
00529 #ifdef HAVE_slt
00530 if (HAVE_slt
00531 && insn_data[(int) CODE_FOR_slt].operand[0].mode == word_mode
00532 && STORE_FLAG_VALUE == -1)
00533 {
00534 emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
00535 lowpart_mode, 0);
00536 fill_value = gen_reg_rtx (word_mode);
00537 emit_insn (gen_slt (fill_value));
00538 }
00539 else
00540 #endif
00541 {
00542 fill_value
00543 = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
00544 size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
00545 NULL_RTX, 0);
00546 fill_value = convert_to_mode (word_mode, fill_value, 1);
00547 }
00548 }
00549
00550
00551 for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
00552 {
00553 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
00554 rtx subword = operand_subword (to, index, 1, to_mode);
00555
00556 gcc_assert (subword);
00557
00558 if (fill_value != subword)
00559 emit_move_insn (subword, fill_value);
00560 }
00561
00562 insns = get_insns ();
00563 end_sequence ();
00564
00565 emit_no_conflict_block (insns, to, from, NULL_RTX,
00566 gen_rtx_fmt_e (equiv_code, to_mode, copy_rtx (from)));
00567 return;
00568 }
00569
00570
00571 if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD
00572 && GET_MODE_BITSIZE (to_mode) <= BITS_PER_WORD)
00573 {
00574 if (!((MEM_P (from)
00575 && ! MEM_VOLATILE_P (from)
00576 && direct_load[(int) to_mode]
00577 && ! mode_dependent_address_p (XEXP (from, 0)))
00578 || REG_P (from)
00579 || GET_CODE (from) == SUBREG))
00580 from = force_reg (from_mode, from);
00581 convert_move (to, gen_lowpart (word_mode, from), 0);
00582 return;
00583 }
00584
00585
00586
00587
00588
00589 if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
00590 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
00591 GET_MODE_BITSIZE (from_mode)))
00592 {
00593 if (!((MEM_P (from)
00594 && ! MEM_VOLATILE_P (from)
00595 && direct_load[(int) to_mode]
00596 && ! mode_dependent_address_p (XEXP (from, 0)))
00597 || REG_P (from)
00598 || GET_CODE (from) == SUBREG))
00599 from = force_reg (from_mode, from);
00600 if (REG_P (from) && REGNO (from) < FIRST_PSEUDO_REGISTER
00601 && ! HARD_REGNO_MODE_OK (REGNO (from), to_mode))
00602 from = copy_to_reg (from);
00603 emit_move_insn (to, gen_lowpart (to_mode, from));
00604 return;
00605 }
00606
00607
00608 if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
00609 {
00610
00611 if ((code = can_extend_p (to_mode, from_mode, unsignedp))
00612 != CODE_FOR_nothing)
00613 {
00614 if (flag_force_mem)
00615 from = force_not_mem (from);
00616
00617 emit_unop_insn (code, to, from, equiv_code);
00618 return;
00619 }
00620 else
00621 {
00622 enum machine_mode intermediate;
00623 rtx tmp;
00624 tree shift_amount;
00625
00626
00627 for (intermediate = from_mode; intermediate != VOIDmode;
00628 intermediate = GET_MODE_WIDER_MODE (intermediate))
00629 if (((can_extend_p (to_mode, intermediate, unsignedp)
00630 != CODE_FOR_nothing)
00631 || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
00632 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
00633 GET_MODE_BITSIZE (intermediate))))
00634 && (can_extend_p (intermediate, from_mode, unsignedp)
00635 != CODE_FOR_nothing))
00636 {
00637 convert_move (to, convert_to_mode (intermediate, from,
00638 unsignedp), unsignedp);
00639 return;
00640 }
00641
00642
00643
00644 shift_amount = build_int_cst (NULL_TREE,
00645 GET_MODE_BITSIZE (to_mode)
00646 - GET_MODE_BITSIZE (from_mode));
00647 from = gen_lowpart (to_mode, force_reg (from_mode, from));
00648 tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
00649 to, unsignedp);
00650 tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
00651 to, unsignedp);
00652 if (tmp != to)
00653 emit_move_insn (to, tmp);
00654 return;
00655 }
00656 }
00657
00658
00659 if (trunc_optab->handlers[to_mode][from_mode].insn_code != CODE_FOR_nothing)
00660 {
00661 emit_unop_insn (trunc_optab->handlers[to_mode][from_mode].insn_code,
00662 to, from, UNKNOWN);
00663 return;
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673 if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
00674 {
00675 rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
00676 emit_move_insn (to, temp);
00677 return;
00678 }
00679
00680
00681 gcc_unreachable ();
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691 rtx
00692 convert_to_mode (enum machine_mode mode, rtx x, int unsignedp)
00693 {
00694 return convert_modes (mode, VOIDmode, x, unsignedp);
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 rtx
00708 convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int unsignedp)
00709 {
00710 rtx temp;
00711
00712
00713
00714
00715 if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
00716 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
00717 && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)
00718 x = gen_lowpart (mode, x);
00719
00720 if (GET_MODE (x) != VOIDmode)
00721 oldmode = GET_MODE (x);
00722
00723 if (mode == oldmode)
00724 return x;
00725
00726
00727
00728
00729
00730
00731
00732 if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
00733 && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
00734 && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)
00735 {
00736 HOST_WIDE_INT val = INTVAL (x);
00737
00738 if (oldmode != VOIDmode
00739 && HOST_BITS_PER_WIDE_INT > GET_MODE_BITSIZE (oldmode))
00740 {
00741 int width = GET_MODE_BITSIZE (oldmode);
00742
00743
00744 val &= ((HOST_WIDE_INT) 1 << width) - 1;
00745 }
00746
00747 return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
00748 }
00749
00750
00751
00752
00753
00754
00755 if ((GET_CODE (x) == CONST_INT
00756 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
00757 || (GET_MODE_CLASS (mode) == MODE_INT
00758 && GET_MODE_CLASS (oldmode) == MODE_INT
00759 && (GET_CODE (x) == CONST_DOUBLE
00760 || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode)
00761 && ((MEM_P (x) && ! MEM_VOLATILE_P (x)
00762 && direct_load[(int) mode])
00763 || (REG_P (x)
00764 && (! HARD_REGISTER_P (x)
00765 || HARD_REGNO_MODE_OK (REGNO (x), mode))
00766 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
00767 GET_MODE_BITSIZE (GET_MODE (x)))))))))
00768 {
00769
00770
00771
00772 if (GET_CODE (x) == CONST_INT && oldmode != VOIDmode
00773 && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode))
00774 {
00775 HOST_WIDE_INT val = INTVAL (x);
00776 int width = GET_MODE_BITSIZE (oldmode);
00777
00778
00779
00780 val &= ((HOST_WIDE_INT) 1 << width) - 1;
00781 if (! unsignedp
00782 && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
00783 val |= (HOST_WIDE_INT) (-1) << width;
00784
00785 return gen_int_mode (val, mode);
00786 }
00787
00788 return gen_lowpart (mode, x);
00789 }
00790
00791
00792
00793 if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode)
00794 {
00795 gcc_assert (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (oldmode));
00796 return simplify_gen_subreg (mode, x, oldmode, 0);
00797 }
00798
00799 temp = gen_reg_rtx (mode);
00800 convert_move (temp, x, unsignedp);
00801 return temp;
00802 }
00803
00804
00805
00806
00807
00808
00809 #define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
00810
00811
00812
00813
00814
00815 int
00816 can_move_by_pieces (unsigned HOST_WIDE_INT len,
00817 unsigned int align ATTRIBUTE_UNUSED)
00818 {
00819 return MOVE_BY_PIECES_P (len, align);
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 rtx
00835 move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
00836 unsigned int align, int endp)
00837 {
00838 struct move_by_pieces data;
00839 rtx to_addr, from_addr = XEXP (from, 0);
00840 unsigned int max_size = MOVE_MAX_PIECES + 1;
00841 enum machine_mode mode = VOIDmode, tmode;
00842 enum insn_code icode;
00843
00844 align = MIN (to ? MEM_ALIGN (to) : align, MEM_ALIGN (from));
00845
00846 data.offset = 0;
00847 data.from_addr = from_addr;
00848 if (to)
00849 {
00850 to_addr = XEXP (to, 0);
00851 data.to = to;
00852 data.autinc_to
00853 = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
00854 || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
00855 data.reverse
00856 = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
00857 }
00858 else
00859 {
00860 to_addr = NULL_RTX;
00861 data.to = NULL_RTX;
00862 data.autinc_to = 1;
00863 #ifdef STACK_GROWS_DOWNWARD
00864 data.reverse = 1;
00865 #else
00866 data.reverse = 0;
00867 #endif
00868 }
00869 data.to_addr = to_addr;
00870 data.from = from;
00871 data.autinc_from
00872 = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
00873 || GET_CODE (from_addr) == POST_INC
00874 || GET_CODE (from_addr) == POST_DEC);
00875
00876 data.explicit_inc_from = 0;
00877 data.explicit_inc_to = 0;
00878 if (data.reverse) data.offset = len;
00879 data.len = len;
00880
00881
00882
00883
00884 if (!(data.autinc_from && data.autinc_to)
00885 && move_by_pieces_ninsns (len, align, max_size) > 2)
00886 {
00887
00888 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
00889 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
00890 if (GET_MODE_SIZE (tmode) < max_size)
00891 mode = tmode;
00892
00893 if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
00894 {
00895 data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
00896 data.autinc_from = 1;
00897 data.explicit_inc_from = -1;
00898 }
00899 if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
00900 {
00901 data.from_addr = copy_addr_to_reg (from_addr);
00902 data.autinc_from = 1;
00903 data.explicit_inc_from = 1;
00904 }
00905 if (!data.autinc_from && CONSTANT_P (from_addr))
00906 data.from_addr = copy_addr_to_reg (from_addr);
00907 if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
00908 {
00909 data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
00910 data.autinc_to = 1;
00911 data.explicit_inc_to = -1;
00912 }
00913 if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
00914 {
00915 data.to_addr = copy_addr_to_reg (to_addr);
00916 data.autinc_to = 1;
00917 data.explicit_inc_to = 1;
00918 }
00919 if (!data.autinc_to && CONSTANT_P (to_addr))
00920 data.to_addr = copy_addr_to_reg (to_addr);
00921 }
00922
00923 tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
00924 if (align >= GET_MODE_ALIGNMENT (tmode))
00925 align = GET_MODE_ALIGNMENT (tmode);
00926 else
00927 {
00928 enum machine_mode xmode;
00929
00930 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
00931 tmode != VOIDmode;
00932 xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
00933 if (GET_MODE_SIZE (tmode) > MOVE_MAX_PIECES
00934 || SLOW_UNALIGNED_ACCESS (tmode, align))
00935 break;
00936
00937 align = MAX (align, GET_MODE_ALIGNMENT (xmode));
00938 }
00939
00940
00941
00942
00943 while (max_size > 1)
00944 {
00945 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
00946 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
00947 if (GET_MODE_SIZE (tmode) < max_size)
00948 mode = tmode;
00949
00950 if (mode == VOIDmode)
00951 break;
00952
00953 icode = mov_optab->handlers[(int) mode].insn_code;
00954 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
00955 move_by_pieces_1 (GEN_FCN (icode), mode, &data);
00956
00957 max_size = GET_MODE_SIZE (mode);
00958 }
00959
00960
00961 gcc_assert (!data.len);
00962
00963 if (endp)
00964 {
00965 rtx to1;
00966
00967 gcc_assert (!data.reverse);
00968 if (data.autinc_to)
00969 {
00970 if (endp == 2)
00971 {
00972 if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
00973 emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
00974 else
00975 data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
00976 -1));
00977 }
00978 to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
00979 data.offset);
00980 }
00981 else
00982 {
00983 if (endp == 2)
00984 --data.offset;
00985 to1 = adjust_address (data.to, QImode, data.offset);
00986 }
00987 return to1;
00988 }
00989 else
00990 return data.to;
00991 }
00992
00993
00994
00995
00996 static unsigned HOST_WIDE_INT
00997 move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
00998 unsigned int max_size)
00999 {
01000 unsigned HOST_WIDE_INT n_insns = 0;
01001 enum machine_mode tmode;
01002
01003 tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
01004 if (align >= GET_MODE_ALIGNMENT (tmode))
01005 align = GET_MODE_ALIGNMENT (tmode);
01006 else
01007 {
01008 enum machine_mode tmode, xmode;
01009
01010 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
01011 tmode != VOIDmode;
01012 xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
01013 if (GET_MODE_SIZE (tmode) > MOVE_MAX_PIECES
01014 || SLOW_UNALIGNED_ACCESS (tmode, align))
01015 break;
01016
01017 align = MAX (align, GET_MODE_ALIGNMENT (xmode));
01018 }
01019
01020 while (max_size > 1)
01021 {
01022 enum machine_mode mode = VOIDmode;
01023 enum insn_code icode;
01024
01025 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01026 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01027 if (GET_MODE_SIZE (tmode) < max_size)
01028 mode = tmode;
01029
01030 if (mode == VOIDmode)
01031 break;
01032
01033 icode = mov_optab->handlers[(int) mode].insn_code;
01034 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
01035 n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
01036
01037 max_size = GET_MODE_SIZE (mode);
01038 }
01039
01040 gcc_assert (!l);
01041 return n_insns;
01042 }
01043
01044
01045
01046
01047
01048 static void
01049 move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
01050 struct move_by_pieces *data)
01051 {
01052 unsigned int size = GET_MODE_SIZE (mode);
01053 rtx to1 = NULL_RTX, from1;
01054
01055 while (data->len >= size)
01056 {
01057 if (data->reverse)
01058 data->offset -= size;
01059
01060 if (data->to)
01061 {
01062 if (data->autinc_to)
01063 to1 = adjust_automodify_address (data->to, mode, data->to_addr,
01064 data->offset);
01065 else
01066 to1 = adjust_address (data->to, mode, data->offset);
01067 }
01068
01069 if (data->autinc_from)
01070 from1 = adjust_automodify_address (data->from, mode, data->from_addr,
01071 data->offset);
01072 else
01073 from1 = adjust_address (data->from, mode, data->offset);
01074
01075 if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
01076 emit_insn (gen_add2_insn (data->to_addr,
01077 GEN_INT (-(HOST_WIDE_INT)size)));
01078 if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
01079 emit_insn (gen_add2_insn (data->from_addr,
01080 GEN_INT (-(HOST_WIDE_INT)size)));
01081
01082 if (data->to)
01083 emit_insn ((*genfun) (to1, from1));
01084 else
01085 {
01086 #ifdef PUSH_ROUNDING
01087 emit_single_push_insn (mode, from1, NULL);
01088 #else
01089 gcc_unreachable ();
01090 #endif
01091 }
01092
01093 if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
01094 emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
01095 if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
01096 emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
01097
01098 if (! data->reverse)
01099 data->offset += size;
01100
01101 data->len -= size;
01102 }
01103 }
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 rtx
01118 emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method)
01119 {
01120 bool may_use_call;
01121 rtx retval = 0;
01122 unsigned int align;
01123
01124 switch (method)
01125 {
01126 case BLOCK_OP_NORMAL:
01127 case BLOCK_OP_TAILCALL:
01128 may_use_call = true;
01129 break;
01130
01131 case BLOCK_OP_CALL_PARM:
01132 may_use_call = block_move_libcall_safe_for_call_parm ();
01133
01134
01135
01136 NO_DEFER_POP;
01137 break;
01138
01139 case BLOCK_OP_NO_LIBCALL:
01140 may_use_call = false;
01141 break;
01142
01143 default:
01144 gcc_unreachable ();
01145 }
01146
01147 align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
01148
01149 gcc_assert (MEM_P (x));
01150 gcc_assert (MEM_P (y));
01151 gcc_assert (size);
01152
01153
01154
01155 x = adjust_address (x, BLKmode, 0);
01156 y = adjust_address (y, BLKmode, 0);
01157
01158
01159
01160 if (GET_CODE (size) == CONST_INT)
01161 {
01162 if (INTVAL (size) == 0)
01163 return 0;
01164
01165 x = shallow_copy_rtx (x);
01166 y = shallow_copy_rtx (y);
01167 set_mem_size (x, size);
01168 set_mem_size (y, size);
01169 }
01170
01171 if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align))
01172 move_by_pieces (x, y, INTVAL (size), align, 0);
01173 else if (emit_block_move_via_movmem (x, y, size, align))
01174 ;
01175 else if (may_use_call)
01176 retval = emit_block_move_via_libcall (x, y, size,
01177 method == BLOCK_OP_TAILCALL);
01178 else
01179 emit_block_move_via_loop (x, y, size, align);
01180
01181 if (method == BLOCK_OP_CALL_PARM)
01182 OK_DEFER_POP;
01183
01184 return retval;
01185 }
01186
01187
01188
01189
01190
01191 static bool
01192 block_move_libcall_safe_for_call_parm (void)
01193 {
01194
01195 if (PUSH_ARGS)
01196 return true;
01197
01198
01199
01200 #if defined (REG_PARM_STACK_SPACE) && defined (OUTGOING_REG_PARM_STACK_SPACE)
01201 {
01202 tree fn = emit_block_move_libcall_fn (false);
01203 (void) fn;
01204 if (REG_PARM_STACK_SPACE (fn) != 0)
01205 return false;
01206 }
01207 #endif
01208
01209
01210
01211 {
01212 CUMULATIVE_ARGS args_so_far;
01213 tree fn, arg;
01214
01215 fn = emit_block_move_libcall_fn (false);
01216 INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0, 3);
01217
01218 arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
01219 for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
01220 {
01221 enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
01222 rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
01223 if (!tmp || !REG_P (tmp))
01224 return false;
01225 if (targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL, 1))
01226 return false;
01227 FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
01228 }
01229 }
01230 return true;
01231 }
01232
01233
01234
01235
01236 static bool
01237 emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align)
01238 {
01239 rtx opalign = GEN_INT (align / BITS_PER_UNIT);
01240 int save_volatile_ok = volatile_ok;
01241 enum machine_mode mode;
01242
01243
01244 volatile_ok = 1;
01245
01246
01247
01248
01249
01250 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
01251 mode = GET_MODE_WIDER_MODE (mode))
01252 {
01253 enum insn_code code = movmem_optab[(int) mode];
01254 insn_operand_predicate_fn pred;
01255
01256 if (code != CODE_FOR_nothing
01257
01258
01259
01260
01261 && ((GET_CODE (size) == CONST_INT
01262 && ((unsigned HOST_WIDE_INT) INTVAL (size)
01263 <= (GET_MODE_MASK (mode) >> 1)))
01264 || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
01265 && ((pred = insn_data[(int) code].operand[0].predicate) == 0
01266 || (*pred) (x, BLKmode))
01267 && ((pred = insn_data[(int) code].operand[1].predicate) == 0
01268 || (*pred) (y, BLKmode))
01269 && ((pred = insn_data[(int) code].operand[3].predicate) == 0
01270 || (*pred) (opalign, VOIDmode)))
01271 {
01272 rtx op2;
01273 rtx last = get_last_insn ();
01274 rtx pat;
01275
01276 op2 = convert_to_mode (mode, size, 1);
01277 pred = insn_data[(int) code].operand[2].predicate;
01278 if (pred != 0 && ! (*pred) (op2, mode))
01279 op2 = copy_to_mode_reg (mode, op2);
01280
01281
01282
01283
01284
01285
01286 pat = GEN_FCN ((int) code) (x, y, op2, opalign);
01287 if (pat)
01288 {
01289 emit_insn (pat);
01290 volatile_ok = save_volatile_ok;
01291 return true;
01292 }
01293 else
01294 delete_insns_since (last);
01295 }
01296 }
01297
01298 volatile_ok = save_volatile_ok;
01299 return false;
01300 }
01301
01302
01303
01304
01305 static rtx
01306 emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall)
01307 {
01308 rtx dst_addr, src_addr;
01309 tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree;
01310 enum machine_mode size_mode;
01311 rtx retval;
01312
01313
01314
01315
01316
01317 dst_addr = copy_to_mode_reg (Pmode, XEXP (dst, 0));
01318 src_addr = copy_to_mode_reg (Pmode, XEXP (src, 0));
01319
01320 dst_addr = convert_memory_address (ptr_mode, dst_addr);
01321 src_addr = convert_memory_address (ptr_mode, src_addr);
01322
01323 dst_tree = make_tree (ptr_type_node, dst_addr);
01324 src_tree = make_tree (ptr_type_node, src_addr);
01325
01326 size_mode = TYPE_MODE (sizetype);
01327
01328 size = convert_to_mode (size_mode, size, 1);
01329 size = copy_to_mode_reg (size_mode, size);
01330
01331
01332
01333
01334
01335
01336
01337 size_tree = make_tree (sizetype, size);
01338
01339 fn = emit_block_move_libcall_fn (true);
01340 arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
01341 arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
01342 arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
01343
01344
01345 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
01346 call_expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
01347 call_expr, arg_list, NULL_TREE);
01348 CALL_EXPR_TAILCALL (call_expr) = tailcall;
01349
01350 retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
01351
01352 return retval;
01353 }
01354
01355
01356
01357
01358
01359 static GTY(()) tree block_move_fn;
01360
01361 void
01362 init_block_move_fn (const char *asmspec)
01363 {
01364 if (!block_move_fn)
01365 {
01366 tree args, fn;
01367
01368 fn = get_identifier ("memcpy");
01369 args = build_function_type_list (ptr_type_node, ptr_type_node,
01370 const_ptr_type_node, sizetype,
01371 NULL_TREE);
01372
01373 fn = build_decl (FUNCTION_DECL, fn, args);
01374 DECL_EXTERNAL (fn) = 1;
01375 TREE_PUBLIC (fn) = 1;
01376 DECL_ARTIFICIAL (fn) = 1;
01377 TREE_NOTHROW (fn) = 1;
01378
01379 block_move_fn = fn;
01380 }
01381
01382 if (asmspec)
01383 set_user_assembler_name (block_move_fn, asmspec);
01384 }
01385
01386 static tree
01387 emit_block_move_libcall_fn (int for_call)
01388 {
01389 static bool emitted_extern;
01390
01391 if (!block_move_fn)
01392 init_block_move_fn (NULL);
01393
01394 if (for_call && !emitted_extern)
01395 {
01396 emitted_extern = true;
01397 make_decl_rtl (block_move_fn);
01398 assemble_external (block_move_fn);
01399 }
01400
01401 return block_move_fn;
01402 }
01403
01404
01405
01406
01407
01408 static void
01409 emit_block_move_via_loop (rtx x, rtx y, rtx size,
01410 unsigned int align ATTRIBUTE_UNUSED)
01411 {
01412 rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
01413 enum machine_mode iter_mode;
01414
01415 iter_mode = GET_MODE (size);
01416 if (iter_mode == VOIDmode)
01417 iter_mode = word_mode;
01418
01419 top_label = gen_label_rtx ();
01420 cmp_label = gen_label_rtx ();
01421 iter = gen_reg_rtx (iter_mode);
01422
01423 emit_move_insn (iter, const0_rtx);
01424
01425 x_addr = force_operand (XEXP (x, 0), NULL_RTX);
01426 y_addr = force_operand (XEXP (y, 0), NULL_RTX);
01427 do_pending_stack_adjust ();
01428
01429 emit_jump (cmp_label);
01430 emit_label (top_label);
01431
01432 tmp = convert_modes (Pmode, iter_mode, iter, true);
01433 x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
01434 y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
01435 x = change_address (x, QImode, x_addr);
01436 y = change_address (y, QImode, y_addr);
01437
01438 emit_move_insn (x, y);
01439
01440 tmp = expand_simple_binop (iter_mode, PLUS, iter, const1_rtx, iter,
01441 true, OPTAB_LIB_WIDEN);
01442 if (tmp != iter)
01443 emit_move_insn (iter, tmp);
01444
01445 emit_label (cmp_label);
01446
01447 emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
01448 true, top_label);
01449 }
01450
01451
01452
01453
01454 void
01455 move_block_to_reg (int regno, rtx x, int nregs, enum machine_mode mode)
01456 {
01457 int i;
01458 #ifdef HAVE_load_multiple
01459 rtx pat;
01460 rtx last;
01461 #endif
01462
01463 if (nregs == 0)
01464 return;
01465
01466 if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
01467 x = validize_mem (force_const_mem (mode, x));
01468
01469
01470 #ifdef HAVE_load_multiple
01471 if (HAVE_load_multiple)
01472 {
01473 last = get_last_insn ();
01474 pat = gen_load_multiple (gen_rtx_REG (word_mode, regno), x,
01475 GEN_INT (nregs));
01476 if (pat)
01477 {
01478 emit_insn (pat);
01479 return;
01480 }
01481 else
01482 delete_insns_since (last);
01483 }
01484 #endif
01485
01486 for (i = 0; i < nregs; i++)
01487 emit_move_insn (gen_rtx_REG (word_mode, regno + i),
01488 operand_subword_force (x, i, mode));
01489 }
01490
01491
01492
01493
01494 void
01495 move_block_from_reg (int regno, rtx x, int nregs)
01496 {
01497 int i;
01498
01499 if (nregs == 0)
01500 return;
01501
01502
01503 #ifdef HAVE_store_multiple
01504 if (HAVE_store_multiple)
01505 {
01506 rtx last = get_last_insn ();
01507 rtx pat = gen_store_multiple (x, gen_rtx_REG (word_mode, regno),
01508 GEN_INT (nregs));
01509 if (pat)
01510 {
01511 emit_insn (pat);
01512 return;
01513 }
01514 else
01515 delete_insns_since (last);
01516 }
01517 #endif
01518
01519 for (i = 0; i < nregs; i++)
01520 {
01521 rtx tem = operand_subword (x, i, 1, BLKmode);
01522
01523 gcc_assert (tem);
01524
01525 emit_move_insn (tem, gen_rtx_REG (word_mode, regno + i));
01526 }
01527 }
01528
01529
01530
01531
01532
01533
01534
01535 rtx
01536 gen_group_rtx (rtx orig)
01537 {
01538 int i, length;
01539 rtx *tmps;
01540
01541 gcc_assert (GET_CODE (orig) == PARALLEL);
01542
01543 length = XVECLEN (orig, 0);
01544 tmps = alloca (sizeof (rtx) * length);
01545
01546
01547 i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1;
01548
01549 if (i)
01550 tmps[0] = 0;
01551
01552 for (; i < length; i++)
01553 {
01554 enum machine_mode mode = GET_MODE (XEXP (XVECEXP (orig, 0, i), 0));
01555 rtx offset = XEXP (XVECEXP (orig, 0, i), 1);
01556
01557 tmps[i] = gen_rtx_EXPR_LIST (VOIDmode, gen_reg_rtx (mode), offset);
01558 }
01559
01560 return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
01561 }
01562
01563
01564
01565
01566
01567 static void
01568 emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
01569 {
01570 rtx src;
01571 int start, i;
01572 enum machine_mode m = GET_MODE (orig_src);
01573
01574 gcc_assert (GET_CODE (dst) == PARALLEL);
01575
01576 if (m != VOIDmode
01577 && !SCALAR_INT_MODE_P (m)
01578 && !MEM_P (orig_src)
01579 && GET_CODE (orig_src) != CONCAT)
01580 {
01581 enum machine_mode imode = int_mode_for_mode (GET_MODE (orig_src));
01582 if (imode == BLKmode)
01583 src = assign_stack_temp (GET_MODE (orig_src), ssize, 0);
01584 else
01585 src = gen_reg_rtx (imode);
01586 if (imode != BLKmode)
01587 src = gen_lowpart (GET_MODE (orig_src), src);
01588 emit_move_insn (src, orig_src);
01589
01590 if (imode != BLKmode)
01591 src = gen_lowpart (imode, src);
01592 emit_group_load_1 (tmps, dst, src, type, ssize);
01593 return;
01594 }
01595
01596
01597
01598 if (XEXP (XVECEXP (dst, 0, 0), 0))
01599 start = 0;
01600 else
01601 start = 1;
01602
01603
01604 for (i = start; i < XVECLEN (dst, 0); i++)
01605 {
01606 enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
01607 HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
01608 unsigned int bytelen = GET_MODE_SIZE (mode);
01609 int shift = 0;
01610
01611
01612 if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
01613 {
01614
01615
01616 if (
01617 #ifdef BLOCK_REG_PADDING
01618 BLOCK_REG_PADDING (GET_MODE (orig_src), type, i == start)
01619 == (BYTES_BIG_ENDIAN ? upward : downward)
01620 #else
01621 BYTES_BIG_ENDIAN
01622 #endif
01623 )
01624 shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
01625 bytelen = ssize - bytepos;
01626 gcc_assert (bytelen > 0);
01627 }
01628
01629
01630
01631
01632 src = orig_src;
01633 if (!MEM_P (orig_src)
01634 && (!CONSTANT_P (orig_src)
01635 || (GET_MODE (orig_src) != mode
01636 && GET_MODE (orig_src) != VOIDmode)))
01637 {
01638 if (GET_MODE (orig_src) == VOIDmode)
01639 src = gen_reg_rtx (mode);
01640 else
01641 src = gen_reg_rtx (GET_MODE (orig_src));
01642
01643 emit_move_insn (src, orig_src);
01644 }
01645
01646
01647 if (MEM_P (src)
01648 && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (src))
01649 || MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode))
01650 && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
01651 && bytelen == GET_MODE_SIZE (mode))
01652 {
01653 tmps[i] = gen_reg_rtx (mode);
01654 emit_move_insn (tmps[i], adjust_address (src, mode, bytepos));
01655 }
01656 else if (COMPLEX_MODE_P (mode)
01657 && GET_MODE (src) == mode
01658 && bytelen == GET_MODE_SIZE (mode))
01659
01660 tmps[i] = src;
01661 else if (GET_CODE (src) == CONCAT)
01662 {
01663 unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
01664 unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
01665
01666 if ((bytepos == 0 && bytelen == slen0)
01667 || (bytepos != 0 && bytepos + bytelen <= slen))
01668 {
01669
01670
01671
01672
01673 tmps[i] = XEXP (src, bytepos / slen0);
01674 if (! CONSTANT_P (tmps[i])
01675 && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
01676 tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
01677 (bytepos % slen0) * BITS_PER_UNIT,
01678 1, NULL_RTX, mode, mode);
01679 }
01680 else
01681 {
01682 rtx mem;
01683
01684 gcc_assert (!bytepos);
01685 mem = assign_stack_temp (GET_MODE (src), slen, 0);
01686 emit_move_insn (mem, src);
01687 tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
01688 0, 1, NULL_RTX, mode, mode);
01689 }
01690 }
01691
01692
01693
01694 else if (VECTOR_MODE_P (GET_MODE (dst))
01695 && REG_P (src))
01696 {
01697 int slen = GET_MODE_SIZE (GET_MODE (src));
01698 rtx mem;
01699
01700 mem = assign_stack_temp (GET_MODE (src), slen, 0);
01701 emit_move_insn (mem, src);
01702 tmps[i] = adjust_address (mem, mode, (int) bytepos);
01703 }
01704 else if (CONSTANT_P (src) && GET_MODE (dst) != BLKmode
01705 && XVECLEN (dst, 0) > 1)
01706 tmps[i] = simplify_gen_subreg (mode, src, GET_MODE(dst), bytepos);
01707 else if (CONSTANT_P (src)
01708 || (REG_P (src) && GET_MODE (src) == mode))
01709 tmps[i] = src;
01710 else
01711 tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
01712 bytepos * BITS_PER_UNIT, 1, NULL_RTX,
01713 mode, mode);
01714
01715 if (shift)
01716 tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
01717 build_int_cst (NULL_TREE, shift), tmps[i], 0);
01718 }
01719 }
01720
01721
01722
01723
01724
01725
01726 void
01727 emit_group_load (rtx dst, rtx src, tree type, int ssize)
01728 {
01729 rtx *tmps;
01730 int i;
01731
01732 tmps = alloca (sizeof (rtx) * XVECLEN (dst, 0));
01733 emit_group_load_1 (tmps, dst, src, type, ssize);
01734
01735
01736 for (i = 0; i < XVECLEN (dst, 0); i++)
01737 {
01738 rtx d = XEXP (XVECEXP (dst, 0, i), 0);
01739 if (d == NULL)
01740 continue;
01741 emit_move_insn (d, tmps[i]);
01742 }
01743 }
01744
01745
01746
01747
01748
01749 rtx
01750 emit_group_load_into_temps (rtx parallel, rtx src, tree type, int ssize)
01751 {
01752 rtvec vec;
01753 int i;
01754
01755 vec = rtvec_alloc (XVECLEN (parallel, 0));
01756 emit_group_load_1 (&RTVEC_ELT (vec, 0), parallel, src, type, ssize);
01757
01758
01759
01760 for (i = 0; i < XVECLEN (parallel, 0); i++)
01761 {
01762 rtx e = XVECEXP (parallel, 0, i);
01763 rtx d = XEXP (e, 0);
01764
01765 if (d)
01766 {
01767 d = force_reg (GET_MODE (d), RTVEC_ELT (vec, i));
01768 e = alloc_EXPR_LIST (REG_NOTE_KIND (e), d, XEXP (e, 1));
01769 }
01770 RTVEC_ELT (vec, i) = e;
01771 }
01772
01773 return gen_rtx_PARALLEL (GET_MODE (parallel), vec);
01774 }
01775
01776
01777
01778
01779 void
01780 emit_group_move (rtx dst, rtx src)
01781 {
01782 int i;
01783
01784 gcc_assert (GET_CODE (src) == PARALLEL
01785 && GET_CODE (dst) == PARALLEL
01786 && XVECLEN (src, 0) == XVECLEN (dst, 0));
01787
01788
01789 for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
01790 emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0),
01791 XEXP (XVECEXP (src, 0, i), 0));
01792 }
01793
01794
01795
01796 rtx
01797 emit_group_move_into_temps (rtx src)
01798 {
01799 rtvec vec = rtvec_alloc (XVECLEN (src, 0));
01800 int i;
01801
01802 for (i = 0; i < XVECLEN (src, 0); i++)
01803 {
01804 rtx e = XVECEXP (src, 0, i);
01805 rtx d = XEXP (e, 0);
01806
01807 if (d)
01808 e = alloc_EXPR_LIST (REG_NOTE_KIND (e), copy_to_reg (d), XEXP (e, 1));
01809 RTVEC_ELT (vec, i) = e;
01810 }
01811
01812 return gen_rtx_PARALLEL (GET_MODE (src), vec);
01813 }
01814
01815
01816
01817
01818
01819
01820 void
01821 emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
01822 {
01823 rtx *tmps, dst;
01824 int start, i;
01825 enum machine_mode m = GET_MODE (orig_dst);
01826
01827 gcc_assert (GET_CODE (src) == PARALLEL);
01828
01829 if (!SCALAR_INT_MODE_P (m)
01830 && !MEM_P (orig_dst) && GET_CODE (orig_dst) != CONCAT)
01831 {
01832 enum machine_mode imode = int_mode_for_mode (GET_MODE (orig_dst));
01833 if (imode == BLKmode)
01834 dst = assign_stack_temp (GET_MODE (orig_dst), ssize, 0);
01835 else
01836 dst = gen_reg_rtx (imode);
01837 emit_group_store (dst, src, type, ssize);
01838 if (imode != BLKmode)
01839 dst = gen_lowpart (GET_MODE (orig_dst), dst);
01840 emit_move_insn (orig_dst, dst);
01841 return;
01842 }
01843
01844
01845
01846 if (XEXP (XVECEXP (src, 0, 0), 0))
01847 start = 0;
01848 else
01849 start = 1;
01850
01851 tmps = alloca (sizeof (rtx) * XVECLEN (src, 0));
01852
01853
01854 for (i = start; i < XVECLEN (src, 0); i++)
01855 {
01856 rtx reg = XEXP (XVECEXP (src, 0, i), 0);
01857 tmps[i] = gen_reg_rtx (GET_MODE (reg));
01858 emit_move_insn (tmps[i], reg);
01859 }
01860
01861
01862
01863 dst = orig_dst;
01864 if (GET_CODE (dst) == PARALLEL)
01865 {
01866 rtx temp;
01867
01868
01869
01870
01871 if (rtx_equal_p (dst, src))
01872 return;
01873
01874
01875
01876
01877
01878 temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
01879 emit_group_store (temp, src, type, ssize);
01880 emit_group_load (dst, temp, type, ssize);
01881 return;
01882 }
01883 else if (!MEM_P (dst) && GET_CODE (dst) != CONCAT)
01884 {
01885 dst = gen_reg_rtx (GET_MODE (orig_dst));
01886
01887 emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
01888 }
01889
01890
01891 for (i = start; i < XVECLEN (src, 0); i++)
01892 {
01893 HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
01894 enum machine_mode mode = GET_MODE (tmps[i]);
01895 unsigned int bytelen = GET_MODE_SIZE (mode);
01896 rtx dest = dst;
01897
01898
01899 if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
01900 {
01901
01902
01903 if (
01904 #ifdef BLOCK_REG_PADDING
01905 BLOCK_REG_PADDING (GET_MODE (orig_dst), type, i == start)
01906 == (BYTES_BIG_ENDIAN ? upward : downward)
01907 #else
01908 BYTES_BIG_ENDIAN
01909 #endif
01910 )
01911 {
01912 int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
01913 tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i],
01914 build_int_cst (NULL_TREE, shift),
01915 tmps[i], 0);
01916 }
01917 bytelen = ssize - bytepos;
01918 }
01919
01920 if (GET_CODE (dst) == CONCAT)
01921 {
01922 if (bytepos + bytelen <= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
01923 dest = XEXP (dst, 0);
01924 else if (bytepos >= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
01925 {
01926 bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
01927 dest = XEXP (dst, 1);
01928 }
01929 else
01930 {
01931 gcc_assert (bytepos == 0 && XVECLEN (src, 0));
01932 dest = assign_stack_temp (GET_MODE (dest),
01933 GET_MODE_SIZE (GET_MODE (dest)), 0);
01934 emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos),
01935 tmps[i]);
01936 dst = dest;
01937 break;
01938 }
01939 }
01940
01941
01942 if (MEM_P (dest)
01943 && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest))
01944 || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode))
01945 && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
01946 && bytelen == GET_MODE_SIZE (mode))
01947 emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
01948 else
01949 store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
01950 mode, tmps[i]);
01951 }
01952
01953
01954 if (orig_dst != dst)
01955 emit_move_insn (orig_dst, dst);
01956 }
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967 rtx
01968 copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
01969 {
01970 unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
01971 rtx src = NULL, dst = NULL;
01972 unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
01973 unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0;
01974
01975 if (tgtblk == 0)
01976 {
01977 tgtblk = assign_temp (build_qualified_type (type,
01978 (TYPE_QUALS (type)
01979 | TYPE_QUAL_CONST)),
01980 0, 1, 1);
01981 preserve_temp_slots (tgtblk);
01982 }
01983
01984
01985
01986
01987 if (GET_MODE (srcreg) != BLKmode
01988 && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
01989 srcreg = convert_to_mode (word_mode, srcreg, TYPE_UNSIGNED (type));
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000 if (bytes % UNITS_PER_WORD != 0
02001 && (targetm.calls.return_in_msb (type)
02002 ? !BYTES_BIG_ENDIAN
02003 : BYTES_BIG_ENDIAN))
02004 padding_correction
02005 = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
02006
02007
02008
02009
02010
02011
02012 for (bitpos = 0, xbitpos = padding_correction;
02013 bitpos < bytes * BITS_PER_UNIT;
02014 bitpos += bitsize, xbitpos += bitsize)
02015 {
02016
02017
02018
02019 if (xbitpos % BITS_PER_WORD == 0
02020 || xbitpos == padding_correction)
02021 src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
02022 GET_MODE (srcreg));
02023
02024
02025
02026 if (bitpos % BITS_PER_WORD == 0)
02027 dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
02028
02029
02030
02031 store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
02032 extract_bit_field (src, bitsize,
02033 xbitpos % BITS_PER_WORD, 1,
02034 NULL_RTX, word_mode, word_mode));
02035 }
02036
02037 return tgtblk;
02038 }
02039
02040
02041
02042
02043 void
02044 use_reg (rtx *call_fusage, rtx reg)
02045 {
02046 gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER);
02047
02048 *call_fusage
02049 = gen_rtx_EXPR_LIST (VOIDmode,
02050 gen_rtx_USE (VOIDmode, reg), *call_fusage);
02051 }
02052
02053
02054
02055
02056 void
02057 use_regs (rtx *call_fusage, int regno, int nregs)
02058 {
02059 int i;
02060
02061 gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
02062
02063 for (i = 0; i < nregs; i++)
02064 use_reg (call_fusage, regno_reg_rtx[regno + i]);
02065 }
02066
02067
02068
02069
02070
02071 void
02072 use_group_regs (rtx *call_fusage, rtx regs)
02073 {
02074 int i;
02075
02076 for (i = 0; i < XVECLEN (regs, 0); i++)
02077 {
02078 rtx reg = XEXP (XVECEXP (regs, 0, i), 0);
02079
02080
02081
02082
02083 if (reg != 0 && REG_P (reg))
02084 use_reg (call_fusage, reg);
02085 }
02086 }
02087
02088
02089
02090
02091
02092
02093
02094
02095 int
02096 can_store_by_pieces (unsigned HOST_WIDE_INT len,
02097 rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode),
02098 void *constfundata, unsigned int align)
02099 {
02100 unsigned HOST_WIDE_INT l;
02101 unsigned int max_size;
02102 HOST_WIDE_INT offset = 0;
02103 enum machine_mode mode, tmode;
02104 enum insn_code icode;
02105 int reverse;
02106 rtx cst;
02107
02108 if (len == 0)
02109 return 1;
02110
02111 if (! STORE_BY_PIECES_P (len, align))
02112 return 0;
02113
02114 tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
02115 if (align >= GET_MODE_ALIGNMENT (tmode))
02116 align = GET_MODE_ALIGNMENT (tmode);
02117 else
02118 {
02119 enum machine_mode xmode;
02120
02121 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
02122 tmode != VOIDmode;
02123 xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
02124 if (GET_MODE_SIZE (tmode) > STORE_MAX_PIECES
02125 || SLOW_UNALIGNED_ACCESS (tmode, align))
02126 break;
02127
02128 align = MAX (align, GET_MODE_ALIGNMENT (xmode));
02129 }
02130
02131
02132
02133
02134 for (reverse = 0;
02135 reverse <= (HAVE_PRE_DECREMENT || HAVE_POST_DECREMENT);
02136 reverse++)
02137 {
02138 l = len;
02139 mode = VOIDmode;
02140 max_size = STORE_MAX_PIECES + 1;
02141 while (max_size > 1)
02142 {
02143 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02144 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02145 if (GET_MODE_SIZE (tmode) < max_size)
02146 mode = tmode;
02147
02148 if (mode == VOIDmode)
02149 break;
02150
02151 icode = mov_optab->handlers[(int) mode].insn_code;
02152 if (icode != CODE_FOR_nothing
02153 && align >= GET_MODE_ALIGNMENT (mode))
02154 {
02155 unsigned int size = GET_MODE_SIZE (mode);
02156
02157 while (l >= size)
02158 {
02159 if (reverse)
02160 offset -= size;
02161
02162 cst = (*constfun) (constfundata, offset, mode);
02163 if (!LEGITIMATE_CONSTANT_P (cst))
02164 return 0;
02165
02166 if (!reverse)
02167 offset += size;
02168
02169 l -= size;
02170 }
02171 }
02172
02173 max_size = GET_MODE_SIZE (mode);
02174 }
02175
02176
02177 gcc_assert (!l);
02178 }
02179
02180 return 1;
02181 }
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191 rtx
02192 store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
02193 rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode),
02194 void *constfundata, unsigned int align, int endp)
02195 {
02196 struct store_by_pieces data;
02197
02198 if (len == 0)
02199 {
02200 gcc_assert (endp != 2);
02201 return to;
02202 }
02203
02204 gcc_assert (STORE_BY_PIECES_P (len, align));
02205 data.constfun = constfun;
02206 data.constfundata = constfundata;
02207 data.len = len;
02208 data.to = to;
02209 store_by_pieces_1 (&data, align);
02210 if (endp)
02211 {
02212 rtx to1;
02213
02214 gcc_assert (!data.reverse);
02215 if (data.autinc_to)
02216 {
02217 if (endp == 2)
02218 {
02219 if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
02220 emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
02221 else
02222 data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
02223 -1));
02224 }
02225 to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
02226 data.offset);
02227 }
02228 else
02229 {
02230 if (endp == 2)
02231 --data.offset;
02232 to1 = adjust_address (data.to, QImode, data.offset);
02233 }
02234 return to1;
02235 }
02236 else
02237 return data.to;
02238 }
02239
02240
02241
02242
02243 static void
02244 clear_by_pieces (rtx to, unsigned HOST_WIDE_INT len, unsigned int align)
02245 {
02246 struct store_by_pieces data;
02247
02248 if (len == 0)
02249 return;
02250
02251 data.constfun = clear_by_pieces_1;
02252 data.constfundata = NULL;
02253 data.len = len;
02254 data.to = to;
02255 store_by_pieces_1 (&data, align);
02256 }
02257
02258
02259
02260
02261 static rtx
02262 clear_by_pieces_1 (void *data ATTRIBUTE_UNUSED,
02263 HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
02264 enum machine_mode mode ATTRIBUTE_UNUSED)
02265 {
02266 return const0_rtx;
02267 }
02268
02269
02270
02271
02272
02273 static void
02274 store_by_pieces_1 (struct store_by_pieces *data ATTRIBUTE_UNUSED,
02275 unsigned int align ATTRIBUTE_UNUSED)
02276 {
02277 rtx to_addr = XEXP (data->to, 0);
02278 unsigned int max_size = STORE_MAX_PIECES + 1;
02279 enum machine_mode mode = VOIDmode, tmode;
02280 enum insn_code icode;
02281
02282 data->offset = 0;
02283 data->to_addr = to_addr;
02284 data->autinc_to
02285 = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
02286 || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
02287
02288 data->explicit_inc_to = 0;
02289 data->reverse
02290 = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
02291 if (data->reverse)
02292 data->offset = data->len;
02293
02294
02295
02296
02297 if (!data->autinc_to
02298 && move_by_pieces_ninsns (data->len, align, max_size) > 2)
02299 {
02300
02301 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02302 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02303 if (GET_MODE_SIZE (tmode) < max_size)
02304 mode = tmode;
02305
02306 if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
02307 {
02308 data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
02309 data->autinc_to = 1;
02310 data->explicit_inc_to = -1;
02311 }
02312
02313 if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
02314 && ! data->autinc_to)
02315 {
02316 data->to_addr = copy_addr_to_reg (to_addr);
02317 data->autinc_to = 1;
02318 data->explicit_inc_to = 1;
02319 }
02320
02321 if ( !data->autinc_to && CONSTANT_P (to_addr))
02322 data->to_addr = copy_addr_to_reg (to_addr);
02323 }
02324
02325 tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
02326 if (align >= GET_MODE_ALIGNMENT (tmode))
02327 align = GET_MODE_ALIGNMENT (tmode);
02328 else
02329 {
02330 enum machine_mode xmode;
02331
02332 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
02333 tmode != VOIDmode;
02334 xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
02335 if (GET_MODE_SIZE (tmode) > STORE_MAX_PIECES
02336 || SLOW_UNALIGNED_ACCESS (tmode, align))
02337 break;
02338
02339 align = MAX (align, GET_MODE_ALIGNMENT (xmode));
02340 }
02341
02342
02343
02344
02345 while (max_size > 1)
02346 {
02347 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02348 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02349 if (GET_MODE_SIZE (tmode) < max_size)
02350 mode = tmode;
02351
02352 if (mode == VOIDmode)
02353 break;
02354
02355 icode = mov_optab->handlers[(int) mode].insn_code;
02356 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
02357 store_by_pieces_2 (GEN_FCN (icode), mode, data);
02358
02359 max_size = GET_MODE_SIZE (mode);
02360 }
02361
02362
02363 gcc_assert (!data->len);
02364 }
02365
02366
02367
02368
02369
02370 static void
02371 store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
02372 struct store_by_pieces *data)
02373 {
02374 unsigned int size = GET_MODE_SIZE (mode);
02375 rtx to1, cst;
02376
02377 while (data->len >= size)
02378 {
02379 if (data->reverse)
02380 data->offset -= size;
02381
02382 if (data->autinc_to)
02383 to1 = adjust_automodify_address (data->to, mode, data->to_addr,
02384 data->offset);
02385 else
02386 to1 = adjust_address (data->to, mode, data->offset);
02387
02388 if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
02389 emit_insn (gen_add2_insn (data->to_addr,
02390 GEN_INT (-(HOST_WIDE_INT) size)));
02391
02392 cst = (*data->constfun) (data->constfundata, data->offset, mode);
02393 emit_insn ((*genfun) (to1, cst));
02394
02395 if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
02396 emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
02397
02398 if (! data->reverse)
02399 data->offset += size;
02400
02401 data->len -= size;
02402 }
02403 }
02404
02405
02406
02407
02408 rtx
02409 clear_storage (rtx object, rtx size, enum block_op_methods method)
02410 {
02411 enum machine_mode mode = GET_MODE (object);
02412 unsigned int align;
02413
02414 gcc_assert (method == BLOCK_OP_NORMAL || method == BLOCK_OP_TAILCALL);
02415
02416
02417
02418 if (mode != BLKmode
02419 && GET_CODE (size) == CONST_INT
02420 && INTVAL (size) == (HOST_WIDE_INT) GET_MODE_SIZE (mode))
02421 {
02422 rtx zero = CONST0_RTX (mode);
02423 if (zero != NULL)
02424 {
02425 emit_move_insn (object, zero);
02426 return NULL;
02427 }
02428
02429 if (COMPLEX_MODE_P (mode))
02430 {
02431 zero = CONST0_RTX (GET_MODE_INNER (mode));
02432 if (zero != NULL)
02433 {
02434 write_complex_part (object, zero, 0);
02435 write_complex_part (object, zero, 1);
02436 return NULL;
02437 }
02438 }
02439 }
02440
02441 if (size == const0_rtx)
02442 return NULL;
02443
02444 align = MEM_ALIGN (object);
02445
02446 if (GET_CODE (size) == CONST_INT
02447 && CLEAR_BY_PIECES_P (INTVAL (size), align))
02448 clear_by_pieces (object, INTVAL (size), align);
02449 else if (clear_storage_via_clrmem (object, size, align))
02450 ;
02451 else
02452 return clear_storage_via_libcall (object, size,
02453 method == BLOCK_OP_TAILCALL);
02454
02455 return NULL;
02456 }
02457
02458
02459
02460
02461 static bool
02462 clear_storage_via_clrmem (rtx object, rtx size, unsigned int align)
02463 {
02464
02465
02466
02467
02468 rtx opalign = GEN_INT (align / BITS_PER_UNIT);
02469 enum machine_mode mode;
02470
02471 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
02472 mode = GET_MODE_WIDER_MODE (mode))
02473 {
02474 enum insn_code code = clrmem_optab[(int) mode];
02475 insn_operand_predicate_fn pred;
02476
02477 if (code != CODE_FOR_nothing
02478
02479
02480
02481
02482 && ((GET_CODE (size) == CONST_INT
02483 && ((unsigned HOST_WIDE_INT) INTVAL (size)
02484 <= (GET_MODE_MASK (mode) >> 1)))
02485 || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
02486 && ((pred = insn_data[(int) code].operand[0].predicate) == 0
02487 || (*pred) (object, BLKmode))
02488 && ((pred = insn_data[(int) code].operand[2].predicate) == 0
02489 || (*pred) (opalign, VOIDmode)))
02490 {
02491 rtx op1;
02492 rtx last = get_last_insn ();
02493 rtx pat;
02494
02495 op1 = convert_to_mode (mode, size, 1);
02496 pred = insn_data[(int) code].operand[1].predicate;
02497 if (pred != 0 && ! (*pred) (op1, mode))
02498 op1 = copy_to_mode_reg (mode, op1);
02499
02500 pat = GEN_FCN ((int) code) (object, op1, opalign);
02501 if (pat)
02502 {
02503 emit_insn (pat);
02504 return true;
02505 }
02506 else
02507 delete_insns_since (last);
02508 }
02509 }
02510
02511 return false;
02512 }
02513
02514
02515
02516
02517 static rtx
02518 clear_storage_via_libcall (rtx object, rtx size, bool tailcall)
02519 {
02520 tree call_expr, arg_list, fn, object_tree, size_tree;
02521 enum machine_mode size_mode;
02522 rtx retval;
02523
02524
02525
02526
02527 object = copy_to_mode_reg (Pmode, XEXP (object, 0));
02528
02529 size_mode = TYPE_MODE (sizetype);
02530 size = convert_to_mode (size_mode, size, 1);
02531 size = copy_to_mode_reg (size_mode, size);
02532
02533
02534
02535
02536
02537
02538
02539 object_tree = make_tree (ptr_type_node, object);
02540 size_tree = make_tree (sizetype, size);
02541
02542 fn = clear_storage_libcall_fn (true);
02543 arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
02544 arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
02545 arg_list = tree_cons (NULL_TREE, object_tree, arg_list);
02546
02547
02548 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
02549 call_expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
02550 call_expr, arg_list, NULL_TREE);
02551 CALL_EXPR_TAILCALL (call_expr) = tailcall;
02552
02553 retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
02554
02555 return retval;
02556 }
02557
02558
02559
02560
02561
02562 static GTY(()) tree block_clear_fn;
02563
02564 void
02565 init_block_clear_fn (const char *asmspec)
02566 {
02567 if (!block_clear_fn)
02568 {
02569 tree fn, args;
02570
02571 fn = get_identifier ("memset");
02572 args = build_function_type_list (ptr_type_node, ptr_type_node,
02573 integer_type_node, sizetype,
02574 NULL_TREE);
02575
02576 fn = build_decl (FUNCTION_DECL, fn, args);
02577 DECL_EXTERNAL (fn) = 1;
02578 TREE_PUBLIC (fn) = 1;
02579 DECL_ARTIFICIAL (fn) = 1;
02580 TREE_NOTHROW (fn) = 1;
02581
02582 block_clear_fn = fn;
02583 }
02584
02585 if (asmspec)
02586 set_user_assembler_name (block_clear_fn, asmspec);
02587 }
02588
02589 static tree
02590 clear_storage_libcall_fn (int for_call)
02591 {
02592 static bool emitted_extern;
02593
02594 if (!block_clear_fn)
02595 init_block_clear_fn (NULL);
02596
02597 if (for_call && !emitted_extern)
02598 {
02599 emitted_extern = true;
02600 make_decl_rtl (block_clear_fn);
02601 assemble_external (block_clear_fn);
02602 }
02603
02604 return block_clear_fn;
02605 }
02606
02607
02608
02609
02610 static void
02611 write_complex_part (rtx cplx, rtx val, bool imag_p)
02612 {
02613 enum machine_mode cmode;
02614 enum machine_mode imode;
02615 unsigned ibitsize;
02616
02617 if (GET_CODE (cplx) == CONCAT)
02618 {
02619 emit_move_insn (XEXP (cplx, imag_p), val);
02620 return;
02621 }
02622
02623 cmode = GET_MODE (cplx);
02624 imode = GET_MODE_INNER (cmode);
02625 ibitsize = GET_MODE_BITSIZE (imode);
02626
02627
02628
02629
02630
02631 if (ibitsize >= BITS_PER_WORD
02632
02633
02634
02635
02636 || (GET_CODE (cplx) == REG
02637 && REGNO (cplx) < FIRST_PSEUDO_REGISTER
02638 && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0)
02639
02640
02641
02642 || MEM_P (cplx))
02643 {
02644 rtx part = simplify_gen_subreg (imode, cplx, cmode,
02645 imag_p ? GET_MODE_SIZE (imode) : 0);
02646 if (part)
02647 {
02648 emit_move_insn (part, val);
02649 return;
02650 }
02651 else
02652
02653 gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
02654 }
02655
02656 store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, imode, val);
02657 }
02658
02659
02660
02661
02662 static rtx
02663 read_complex_part (rtx cplx, bool imag_p)
02664 {
02665 enum machine_mode cmode, imode;
02666 unsigned ibitsize;
02667
02668 if (GET_CODE (cplx) == CONCAT)
02669 return XEXP (cplx, imag_p);
02670
02671 cmode = GET_MODE (cplx);
02672 imode = GET_MODE_INNER (cmode);
02673 ibitsize = GET_MODE_BITSIZE (imode);
02674
02675
02676 if (MEM_P (cplx) && GET_CODE (XEXP (cplx, 0)) == SYMBOL_REF)
02677 {
02678 tree decl = SYMBOL_REF_DECL (XEXP (cplx, 0));
02679 if (decl && TREE_CODE (decl) == COMPLEX_CST)
02680 {
02681 tree part = imag_p ? TREE_IMAGPART (decl) : TREE_REALPART (decl);
02682 if (CONSTANT_CLASS_P (part))
02683 return expand_expr (part, NULL_RTX, imode, EXPAND_NORMAL);
02684 }
02685 }
02686
02687
02688
02689
02690
02691 if (ibitsize >= BITS_PER_WORD
02692
02693
02694
02695
02696 || (GET_CODE (cplx) == REG
02697 && REGNO (cplx) < FIRST_PSEUDO_REGISTER
02698 && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0)
02699
02700
02701
02702 || MEM_P (cplx))
02703 {
02704 rtx ret = simplify_gen_subreg (imode, cplx, cmode,
02705 imag_p ? GET_MODE_SIZE (imode) : 0);
02706 if (ret)
02707 return ret;
02708 else
02709
02710 gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
02711 }
02712
02713 return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,
02714 true, NULL_RTX, imode, imode);
02715 }
02716
02717
02718
02719
02720
02721
02722 static rtx
02723 emit_move_change_mode (enum machine_mode new_mode,
02724 enum machine_mode old_mode, rtx x, bool force)
02725 {
02726 rtx ret;
02727
02728 if (reload_in_progress && MEM_P (x))
02729 {
02730
02731
02732
02733
02734
02735
02736
02737 ret = adjust_address_nv (x, new_mode, 0);
02738 copy_replacements (x, ret);
02739 }
02740 else
02741 {
02742
02743
02744
02745
02746
02747
02748 if (force)
02749 ret = simplify_gen_subreg (new_mode, x, old_mode, 0);
02750 else
02751 ret = simplify_subreg (new_mode, x, old_mode, 0);
02752 }
02753
02754 return ret;
02755 }
02756
02757
02758
02759
02760
02761 static rtx
02762 emit_move_via_integer (enum machine_mode mode, rtx x, rtx y)
02763 {
02764 enum machine_mode imode;
02765 enum insn_code code;
02766
02767
02768 imode = int_mode_for_mode (mode);
02769 if (imode == BLKmode)
02770 return NULL_RTX;
02771
02772
02773 code = mov_optab->handlers[imode].insn_code;
02774 if (code == CODE_FOR_nothing)
02775 return NULL_RTX;
02776
02777 x = emit_move_change_mode (imode, mode, x, false);
02778 if (x == NULL_RTX)
02779 return NULL_RTX;
02780 y = emit_move_change_mode (imode, mode, y, false);
02781 if (y == NULL_RTX)
02782 return NULL_RTX;
02783 return emit_insn (GEN_FCN (code) (x, y));
02784 }
02785
02786
02787
02788
02789 static rtx
02790 emit_move_resolve_push (enum machine_mode mode, rtx x)
02791 {
02792 enum rtx_code code = GET_CODE (XEXP (x, 0));
02793 HOST_WIDE_INT adjust;
02794 rtx temp;
02795
02796 adjust = GET_MODE_SIZE (mode);
02797 #ifdef PUSH_ROUNDING
02798 adjust = PUSH_ROUNDING (adjust);
02799 #endif
02800 if (code == PRE_DEC || code == POST_DEC)
02801 adjust = -adjust;
02802
02803
02804
02805 temp = expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
02806 GEN_INT (adjust), stack_pointer_rtx,
02807 0, OPTAB_LIB_WIDEN);
02808 if (temp != stack_pointer_rtx)
02809 emit_move_insn (stack_pointer_rtx, temp);
02810
02811 switch (code)
02812 {
02813 case PRE_INC:
02814 case PRE_DEC:
02815 temp = stack_pointer_rtx;
02816 break;
02817 case POST_INC:
02818 temp = plus_constant (stack_pointer_rtx, -GET_MODE_SIZE (mode));
02819 break;
02820 case POST_DEC:
02821 temp = plus_constant (stack_pointer_rtx, GET_MODE_SIZE (mode));
02822 break;
02823 default:
02824 gcc_unreachable ();
02825 }
02826
02827 return replace_equiv_address (x, temp);
02828 }
02829
02830
02831
02832
02833
02834 static rtx
02835 emit_move_complex_push (enum machine_mode mode, rtx x, rtx y)
02836 {
02837 enum machine_mode submode = GET_MODE_INNER (mode);
02838 bool imag_first;
02839
02840 #ifdef PUSH_ROUNDING
02841 unsigned int submodesize = GET_MODE_SIZE (submode);
02842
02843
02844
02845 if (PUSH_ROUNDING (submodesize) != submodesize)
02846 {
02847 x = emit_move_resolve_push (mode, x);
02848 return emit_move_insn (x, y);
02849 }
02850 #endif
02851
02852
02853
02854 switch (GET_CODE (XEXP (x, 0)))
02855 {
02856 case PRE_DEC:
02857 case POST_DEC:
02858 imag_first = true;
02859 break;
02860 case PRE_INC:
02861 case POST_INC:
02862 imag_first = false;
02863 break;
02864 default:
02865 gcc_unreachable ();
02866 }
02867
02868 emit_move_insn (gen_rtx_MEM (submode, XEXP (x, 0)),
02869 read_complex_part (y, imag_first));
02870 return emit_move_insn (gen_rtx_MEM (submode, XEXP (x, 0)),
02871 read_complex_part (y, !imag_first));
02872 }
02873
02874
02875
02876
02877 static rtx
02878 emit_move_complex (enum machine_mode mode, rtx x, rtx y)
02879 {
02880 bool try_int;
02881
02882
02883
02884 if (push_operand (x, mode))
02885 return emit_move_complex_push (mode, x, y);
02886
02887
02888
02889
02890 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
02891 && mov_optab->handlers[GET_MODE_INNER (mode)].insn_code != CODE_FOR_nothing)
02892 try_int = false;
02893
02894 else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
02895 try_int = false;
02896
02897 else if (register_operand (x, mode) && register_operand (y, mode))
02898 try_int = true;
02899
02900
02901
02902
02903 else if ((MEM_P (x) ? !CONSTANT_P (y) : MEM_P (y))
02904 && (!STRICT_ALIGNMENT
02905 || get_mode_alignment (mode) == BIGGEST_ALIGNMENT))
02906 try_int = true;
02907 else
02908 try_int = false;
02909
02910 if (try_int)
02911 {
02912 rtx ret;
02913
02914
02915
02916 if (MEM_P (x) && MEM_P (y))
02917 {
02918 emit_block_move (x, y, GEN_INT (GET_MODE_SIZE (mode)),
02919 BLOCK_OP_NO_LIBCALL);
02920 return get_last_insn ();
02921 }
02922
02923 ret = emit_move_via_integer (mode, x, y);
02924 if (ret)
02925 return ret;
02926 }
02927
02928
02929
02930
02931 if (!reload_completed && !reload_in_progress
02932 && REG_P (x) && !reg_overlap_mentioned_p (x, y))
02933 emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
02934
02935 write_complex_part (x, read_complex_part (y, false), false);
02936 write_complex_part (x, read_complex_part (y, true), true);
02937 return get_last_insn ();
02938 }
02939
02940
02941
02942
02943 static rtx
02944 emit_move_ccmode (enum machine_mode mode, rtx x, rtx y)
02945 {
02946 rtx ret;
02947
02948
02949 if (mode != CCmode)
02950 {
02951 enum insn_code code = mov_optab->handlers[CCmode].insn_code;
02952 if (code != CODE_FOR_nothing)
02953 {
02954 x = emit_move_change_mode (CCmode, mode, x, true);
02955 y = emit_move_change_mode (CCmode, mode, y, true);
02956 return emit_insn (GEN_FCN (code) (x, y));
02957 }
02958 }
02959
02960
02961 ret = emit_move_via_integer (mode, x, y);
02962 gcc_assert (ret != NULL);
02963 return ret;
02964 }
02965
02966
02967
02968
02969
02970
02971 static rtx
02972 emit_move_multi_word (enum machine_mode mode, rtx x, rtx y)
02973 {
02974 rtx last_insn = 0;
02975 rtx seq, inner;
02976 bool need_clobber;
02977 int i;
02978
02979 gcc_assert (GET_MODE_SIZE (mode) >= UNITS_PER_WORD);
02980
02981
02982
02983 if (push_operand (x, mode))
02984 x = emit_move_resolve_push (mode, x);
02985
02986
02987
02988 if (reload_in_progress && MEM_P (x)
02989 && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
02990 x = replace_equiv_address_nv (x, inner);
02991 if (reload_in_progress && MEM_P (y)
02992 && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
02993 y = replace_equiv_address_nv (y, inner);
02994
02995 start_sequence ();
02996
02997 need_clobber = false;
02998 for (i = 0;
02999 i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
03000 i++)
03001 {
03002 rtx xpart = operand_subword (x, i, 1, mode);
03003 rtx ypart = operand_subword (y, i, 1, mode);
03004
03005
03006
03007
03008 if (ypart == 0 && CONSTANT_P (y))
03009 {
03010 y = force_const_mem (mode, y);
03011 ypart = operand_subword (y, i, 1, mode);
03012 }
03013 else if (ypart == 0)
03014 ypart = operand_subword_force (y, i, mode);
03015
03016 gcc_assert (xpart && ypart);
03017
03018 need_clobber |= (GET_CODE (xpart) == SUBREG);
03019
03020 last_insn = emit_move_insn (xpart, ypart);
03021 }
03022
03023 seq = get_insns ();
03024 end_sequence ();
03025
03026
03027
03028
03029
03030 if (x != y
03031 && ! (reload_in_progress || reload_completed)
03032 && need_clobber != 0)
03033 emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
03034
03035 emit_insn (seq);
03036
03037 return last_insn;
03038 }
03039
03040
03041
03042
03043
03044 rtx
03045 emit_move_insn_1 (rtx x, rtx y)
03046 {
03047 enum machine_mode mode = GET_MODE (x);
03048 enum insn_code code;
03049
03050 gcc_assert ((unsigned int) mode < (unsigned int) MAX_MACHINE_MODE);
03051
03052 code = mov_optab->handlers[mode].insn_code;
03053 if (code != CODE_FOR_nothing)
03054 return emit_insn (GEN_FCN (code) (x, y));
03055
03056
03057 if (COMPLEX_MODE_P (mode))
03058 return emit_move_complex (mode, x, y);
03059
03060 if (GET_MODE_CLASS (mode) == MODE_CC)
03061 return emit_move_ccmode (mode, x, y);
03062
03063
03064
03065
03066
03067 if (!CONSTANT_P (y) || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
03068 {
03069 rtx ret = emit_move_via_integer (mode, x, y);
03070 if (ret)
03071 return ret;
03072 }
03073
03074 return emit_move_multi_word (mode, x, y);
03075 }
03076
03077
03078
03079
03080
03081
03082
03083
03084 rtx
03085 emit_move_insn (rtx x, rtx y)
03086 {
03087 enum machine_mode mode = GET_MODE (x);
03088 rtx y_cst = NULL_RTX;
03089 rtx last_insn, set;
03090
03091 gcc_assert (mode != BLKmode
03092 && (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode));
03093
03094 if (CONSTANT_P (y))
03095 {
03096 if (optimize
03097 && SCALAR_FLOAT_MODE_P (GET_MODE (x))
03098 && (last_insn = compress_float_constant (x, y)))
03099 return last_insn;
03100
03101 y_cst = y;
03102
03103 if (!LEGITIMATE_CONSTANT_P (y))
03104 {
03105 y = force_const_mem (mode, y);
03106
03107
03108
03109
03110 if (!y)
03111 y = y_cst;
03112 }
03113 }
03114
03115
03116
03117 if (MEM_P (x)
03118 && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
03119 && ! push_operand (x, GET_MODE (x)))
03120 || (flag_force_addr
03121 && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
03122 x = validize_mem (x);
03123
03124 if (MEM_P (y)
03125 && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
03126 || (flag_force_addr
03127 && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
03128 y = validize_mem (y);
03129
03130 gcc_assert (mode != BLKmode);
03131
03132 last_insn = emit_move_insn_1 (x, y);
03133
03134 if (y_cst && REG_P (x)
03135 && (set = single_set (last_insn)) != NULL_RTX
03136 && SET_DEST (set) == x
03137 && ! rtx_equal_p (y_cst, SET_SRC (set)))
03138 set_unique_reg_note (last_insn, REG_EQUAL, y_cst);
03139
03140 return last_insn;
03141 }
03142
03143
03144
03145
03146
03147 static rtx
03148 compress_float_constant (rtx x, rtx y)
03149 {
03150 enum machine_mode dstmode = GET_MODE (x);
03151 enum machine_mode orig_srcmode = GET_MODE (y);
03152 enum machine_mode srcmode;
03153 REAL_VALUE_TYPE r;
03154
03155 REAL_VALUE_FROM_CONST_DOUBLE (r, y);
03156
03157 for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
03158 srcmode != orig_srcmode;
03159 srcmode = GET_MODE_WIDER_MODE (srcmode))
03160 {
03161 enum insn_code ic;
03162 rtx trunc_y, last_insn;
03163
03164
03165 ic = can_extend_p (dstmode, srcmode, 0);
03166 if (ic == CODE_FOR_nothing)
03167 continue;
03168
03169
03170 if (! exact_real_truncate (srcmode, &r))
03171 continue;
03172
03173 trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
03174
03175 if (LEGITIMATE_CONSTANT_P (trunc_y))
03176 {
03177
03178
03179 if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
03180 continue;
03181 }
03182 else if (float_extend_from_mem[dstmode][srcmode])
03183 trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
03184 else
03185 continue;
03186
03187 emit_unop_insn (ic, x, trunc_y, UNKNOWN);
03188 last_insn = get_last_insn ();
03189
03190 if (REG_P (x))
03191 set_unique_reg_note (last_insn, REG_EQUAL, y);
03192
03193 return last_insn;
03194 }
03195
03196 return NULL_RTX;
03197 }
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209 rtx
03210 push_block (rtx size, int extra, int below)
03211 {
03212 rtx temp;
03213
03214 size = convert_modes (Pmode, ptr_mode, size, 1);
03215 if (CONSTANT_P (size))
03216 anti_adjust_stack (plus_constant (size, extra));
03217 else if (REG_P (size) && extra == 0)
03218 anti_adjust_stack (size);
03219 else
03220 {
03221 temp = copy_to_mode_reg (Pmode, size);
03222 if (extra != 0)
03223 temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
03224 temp, 0, OPTAB_LIB_WIDEN);
03225 anti_adjust_stack (temp);
03226 }
03227
03228 #ifndef STACK_GROWS_DOWNWARD
03229 if (0)
03230 #else
03231 if (1)
03232 #endif
03233 {
03234 temp = virtual_outgoing_args_rtx;
03235 if (extra != 0 && below)
03236 temp = plus_constant (temp, extra);
03237 }
03238 else
03239 {
03240 if (GET_CODE (size) == CONST_INT)
03241 temp = plus_constant (virtual_outgoing_args_rtx,
03242 -INTVAL (size) - (below ? 0 : extra));
03243 else if (extra != 0 && !below)
03244 temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
03245 negate_rtx (Pmode, plus_constant (size, extra)));
03246 else
03247 temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
03248 negate_rtx (Pmode, size));
03249 }
03250
03251 return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
03252 }
03253
03254 #ifdef PUSH_ROUNDING
03255
03256
03257
03258 static void
03259 emit_single_push_insn (enum machine_mode mode, rtx x, tree type)
03260 {
03261 rtx dest_addr;
03262 unsigned rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
03263 rtx dest;
03264 enum insn_code icode;
03265 insn_operand_predicate_fn pred;
03266
03267 stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
03268
03269
03270 icode = push_optab->handlers[(int) mode].insn_code;
03271 if (icode != CODE_FOR_nothing)
03272 {
03273 if (((pred = insn_data[(int) icode].operand[0].predicate)
03274 && !((*pred) (x, mode))))
03275 x = force_reg (mode, x);
03276 emit_insn (GEN_FCN (icode) (x));
03277 return;
03278 }
03279 if (GET_MODE_SIZE (mode) == rounded_size)
03280 dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
03281
03282
03283
03284
03285 else if (FUNCTION_ARG_PADDING (mode, type) == downward)
03286 {
03287 unsigned padding_size = rounded_size - GET_MODE_SIZE (mode);
03288 HOST_WIDE_INT offset;
03289
03290 emit_move_insn (stack_pointer_rtx,
03291 expand_binop (Pmode,
03292 #ifdef STACK_GROWS_DOWNWARD
03293 sub_optab,
03294 #else
03295 add_optab,
03296 #endif
03297 stack_pointer_rtx,
03298 GEN_INT (rounded_size),
03299 NULL_RTX, 0, OPTAB_LIB_WIDEN));
03300
03301 offset = (HOST_WIDE_INT) padding_size;
03302 #ifdef STACK_GROWS_DOWNWARD
03303 if (STACK_PUSH_CODE == POST_DEC)
03304
03305
03306 offset += (HOST_WIDE_INT) rounded_size;
03307 #else
03308 if (STACK_PUSH_CODE == POST_INC)
03309
03310
03311 offset -= (HOST_WIDE_INT) rounded_size;
03312 #endif
03313 dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
03314 }
03315 else
03316 {
03317 #ifdef STACK_GROWS_DOWNWARD
03318
03319 dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03320 GEN_INT (-(HOST_WIDE_INT) rounded_size));
03321 #else
03322
03323 dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03324 GEN_INT (rounded_size));
03325 #endif
03326 dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
03327 }
03328
03329 dest = gen_rtx_MEM (mode, dest_addr);
03330
03331 if (type != 0)
03332 {
03333 set_mem_attributes (dest, type, 1);
03334
03335 if (flag_optimize_sibling_calls)
03336
03337
03338
03339
03340 set_mem_alias_set (dest, 0);
03341 }
03342 emit_move_insn (dest, x);
03343 }
03344 #endif
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377 void
03378 emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
03379 unsigned int align, int partial, rtx reg, int extra,
03380 rtx args_addr, rtx args_so_far, int reg_parm_stack_space,
03381 rtx alignment_pad)
03382 {
03383 rtx xinner;
03384 enum direction stack_direction
03385 #ifdef STACK_GROWS_DOWNWARD
03386 = downward;
03387 #else
03388 = upward;
03389 #endif
03390
03391
03392
03393
03394 enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
03395
03396
03397
03398 if (STACK_PUSH_CODE == POST_DEC)
03399 if (where_pad != none)
03400 where_pad = (where_pad == downward ? upward : downward);
03401
03402 xinner = x;
03403
03404 if (mode == BLKmode)
03405 {
03406
03407
03408 rtx temp;
03409 int used;
03410 int offset;
03411 int skip;
03412
03413 offset = partial % (PARM_BOUNDARY / BITS_PER_UNIT);
03414 used = partial - offset;
03415
03416 gcc_assert (size);
03417
03418
03419
03420
03421 if (partial != 0)
03422 xinner = adjust_address (xinner, BLKmode, used);
03423
03424
03425
03426
03427
03428 skip = (reg_parm_stack_space == 0) ? 0 : used;
03429
03430 #ifdef PUSH_ROUNDING
03431
03432
03433
03434 if (args_addr == 0
03435 && PUSH_ARGS
03436 && GET_CODE (size) == CONST_INT
03437 && skip == 0
03438 && MEM_ALIGN (xinner) >= align
03439 && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
03440
03441
03442
03443 && ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
03444 || align >= BIGGEST_ALIGNMENT
03445 || (PUSH_ROUNDING (align / BITS_PER_UNIT)
03446 == (align / BITS_PER_UNIT)))
03447 && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
03448 {
03449
03450
03451
03452 if (extra && args_addr == 0
03453 && where_pad != none && where_pad != stack_direction)
03454 anti_adjust_stack (GEN_INT (extra));
03455
03456 move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0);
03457 }
03458 else
03459 #endif
03460 {
03461 rtx target;
03462
03463
03464
03465
03466
03467 if (partial != 0)
03468 {
03469 if (GET_CODE (size) == CONST_INT)
03470 size = GEN_INT (INTVAL (size) - used);
03471 else
03472 size = expand_binop (GET_MODE (size), sub_optab, size,
03473 GEN_INT (used), NULL_RTX, 0,
03474 OPTAB_LIB_WIDEN);
03475 }
03476
03477
03478
03479
03480 if (! args_addr)
03481 {
03482 temp = push_block (size, extra, where_pad == downward);
03483 extra = 0;
03484 }
03485 else if (GET_CODE (args_so_far) == CONST_INT)
03486 temp = memory_address (BLKmode,
03487 plus_constant (args_addr,
03488 skip + INTVAL (args_so_far)));
03489 else
03490 temp = memory_address (BLKmode,
03491 plus_constant (gen_rtx_PLUS (Pmode,
03492 args_addr,
03493 args_so_far),
03494 skip));
03495
03496 if (!ACCUMULATE_OUTGOING_ARGS)
03497 {
03498
03499
03500
03501
03502 if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
03503 || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
03504 temp = copy_to_reg (temp);
03505 }
03506
03507 target = gen_rtx_MEM (BLKmode, temp);
03508
03509
03510
03511
03512
03513
03514
03515
03516 set_mem_align (target, align);
03517
03518 emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
03519 }
03520 }
03521 else if (partial > 0)
03522 {
03523
03524
03525 int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
03526 int i;
03527 int not_stack;
03528
03529
03530 int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
03531 int args_offset = INTVAL (args_so_far);
03532 int skip;
03533
03534
03535
03536
03537 if (extra && args_addr == 0
03538 && where_pad != none && where_pad != stack_direction)
03539 anti_adjust_stack (GEN_INT (extra));
03540
03541
03542
03543
03544 if (args_addr == 0)
03545 offset = 0;
03546
03547
03548
03549 not_stack = (partial - offset) / UNITS_PER_WORD;
03550
03551
03552
03553
03554
03555 skip = (reg_parm_stack_space == 0) ? 0 : not_stack;
03556
03557 if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
03558 x = validize_mem (force_const_mem (mode, x));
03559
03560
03561
03562 if ((REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER
03563 && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))
03564 x = copy_to_reg (x);
03565
03566
03567
03568
03569 #ifndef PUSH_ARGS_REVERSED
03570 for (i = not_stack; i < size; i++)
03571 #else
03572 for (i = size - 1; i >= not_stack; i--)
03573 #endif
03574 if (i >= not_stack + offset)
03575 emit_push_insn (operand_subword_force (x, i, mode),
03576 word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
03577 0, args_addr,
03578 GEN_INT (args_offset + ((i - not_stack + skip)
03579 * UNITS_PER_WORD)),
03580 reg_parm_stack_space, alignment_pad);
03581 }
03582 else
03583 {
03584 rtx addr;
03585 rtx dest;
03586
03587
03588
03589
03590 if (extra && args_addr == 0
03591 && where_pad != none && where_pad != stack_direction)
03592 anti_adjust_stack (GEN_INT (extra));
03593
03594 #ifdef PUSH_ROUNDING
03595 if (args_addr == 0 && PUSH_ARGS)
03596 emit_single_push_insn (mode, x, type);
03597 else
03598 #endif
03599 {
03600 if (GET_CODE (args_so_far) == CONST_INT)
03601 addr
03602 = memory_address (mode,
03603 plus_constant (args_addr,
03604 INTVAL (args_so_far)));
03605 else
03606 addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
03607 args_so_far));
03608 dest = gen_rtx_MEM (mode, addr);
03609
03610
03611
03612
03613
03614
03615
03616
03617 set_mem_align (dest, align);
03618
03619 emit_move_insn (dest, x);
03620 }
03621 }
03622
03623
03624
03625
03626 if (partial > 0 && reg != 0)
03627 {
03628
03629
03630 if (GET_CODE (reg) == PARALLEL)
03631 emit_group_load (reg, x, type, -1);
03632 else
03633 {
03634 gcc_assert (partial % UNITS_PER_WORD == 0);
03635 move_block_to_reg (REGNO (reg), x, partial / UNITS_PER_WORD, mode);
03636 }
03637 }
03638
03639 if (extra && args_addr == 0 && where_pad == stack_direction)
03640 anti_adjust_stack (GEN_INT (extra));
03641
03642 if (alignment_pad && args_addr == 0)
03643 anti_adjust_stack (alignment_pad);
03644 }
03645
03646
03647
03648
03649 static rtx
03650 get_subtarget (rtx x)
03651 {
03652 return (optimize
03653 || x == 0
03654
03655 || !REG_P (x)
03656
03657 || REGNO (x) < FIRST_PSEUDO_REGISTER
03658 ? 0 : x);
03659 }
03660
03661
03662
03663
03664
03665 static bool
03666 optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
03667 unsigned HOST_WIDE_INT bitpos,
03668 enum machine_mode mode1, rtx str_rtx,
03669 tree to, tree src)
03670 {
03671 enum machine_mode str_mode = GET_MODE (str_rtx);
03672 unsigned int str_bitsize = GET_MODE_BITSIZE (str_mode);
03673 tree op0, op1;
03674 rtx value, result;
03675 optab binop;
03676
03677 if (mode1 != VOIDmode
03678 || bitsize >= BITS_PER_WORD
03679 || str_bitsize > BITS_PER_WORD
03680 || TREE_SIDE_EFFECTS (to)
03681 || TREE_THIS_VOLATILE (to))
03682 return false;
03683
03684 STRIP_NOPS (src);
03685 if (!BINARY_CLASS_P (src)
03686 || TREE_CODE (TREE_TYPE (src)) != INTEGER_TYPE)
03687 return false;
03688
03689 op0 = TREE_OPERAND (src, 0);
03690 op1 = TREE_OPERAND (src, 1);
03691 STRIP_NOPS (op0);
03692
03693 if (!operand_equal_p (to, op0, 0))
03694 return false;
03695
03696 if (MEM_P (str_rtx))
03697 {
03698 unsigned HOST_WIDE_INT offset1;
03699
03700 if (str_bitsize == 0 || str_bitsize > BITS_PER_WORD)
03701 str_mode = word_mode;
03702 str_mode = get_best_mode (bitsize, bitpos,
03703 MEM_ALIGN (str_rtx), str_mode, 0);
03704 if (str_mode == VOIDmode)
03705 return false;
03706 str_bitsize = GET_MODE_BITSIZE (str_mode);
03707
03708 offset1 = bitpos;
03709 bitpos %= str_bitsize;
03710 offset1 = (offset1 - bitpos) / BITS_PER_UNIT;
03711 str_rtx = adjust_address (str_rtx, str_mode, offset1);
03712 }
03713 else if (!REG_P (str_rtx) && GET_CODE (str_rtx) != SUBREG)
03714 return false;
03715
03716
03717
03718 if (bitsize >= str_bitsize)
03719 return false;
03720
03721
03722 if (bitpos + bitsize > str_bitsize)
03723 return false;
03724
03725 if (BYTES_BIG_ENDIAN)
03726 bitpos = str_bitsize - bitpos - bitsize;
03727
03728 switch (TREE_CODE (src))
03729 {
03730 case PLUS_EXPR:
03731 case MINUS_EXPR:
03732
03733
03734
03735
03736
03737
03738 if (bitpos + bitsize != str_bitsize
03739 && (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST))
03740 break;
03741
03742 value = expand_expr (op1, NULL_RTX, str_mode, 0);
03743 value = convert_modes (str_mode,
03744 TYPE_MODE (TREE_TYPE (op1)), value,
03745 TYPE_UNSIGNED (TREE_TYPE (op1)));
03746
03747
03748
03749 if (MEM_P (str_rtx))
03750 {
03751 str_rtx = shallow_copy_rtx (str_rtx);
03752 set_mem_alias_set (str_rtx, 0);
03753 set_mem_expr (str_rtx, 0);
03754 }
03755
03756 binop = TREE_CODE (src) == PLUS_EXPR ? add_optab : sub_optab;
03757 if (bitsize == 1 && bitpos + bitsize != str_bitsize)
03758 {
03759 value = expand_and (str_mode, value, const1_rtx, NULL);
03760 binop = xor_optab;
03761 }
03762 value = expand_shift (LSHIFT_EXPR, str_mode, value,
03763 build_int_cst (NULL_TREE, bitpos),
03764 NULL_RTX, 1);
03765 result = expand_binop (str_mode, binop, str_rtx,
03766 value, str_rtx, 1, OPTAB_WIDEN);
03767 if (result != str_rtx)
03768 emit_move_insn (str_rtx, result);
03769 return true;
03770
03771 default:
03772 break;
03773 }
03774
03775 return false;
03776 }
03777
03778
03779
03780
03781 void
03782 expand_assignment (tree to, tree from)
03783 {
03784 rtx to_rtx = 0;
03785 rtx result;
03786
03787
03788
03789 if (TREE_CODE (to) == ERROR_MARK)
03790 {
03791 result = expand_expr (from, NULL_RTX, VOIDmode, 0);
03792 return;
03793 }
03794
03795
03796
03797
03798
03799
03800 if (handled_component_p (to)
03801 || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
03802 {
03803 enum machine_mode mode1;
03804 HOST_WIDE_INT bitsize, bitpos;
03805 rtx orig_to_rtx;
03806 tree offset;
03807 int unsignedp;
03808 int volatilep = 0;
03809 tree tem;
03810
03811 push_temp_slots ();
03812 tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
03813 &unsignedp, &volatilep, true);
03814
03815
03816
03817
03818 orig_to_rtx = to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
03819
03820 if (offset != 0)
03821 {
03822 rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
03823
03824 gcc_assert (MEM_P (to_rtx));
03825
03826 #ifdef POINTERS_EXTEND_UNSIGNED
03827 if (GET_MODE (offset_rtx) != Pmode)
03828 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
03829 #else
03830 if (GET_MODE (offset_rtx) != ptr_mode)
03831 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
03832 #endif
03833
03834
03835
03836 if (MEM_P (to_rtx)
03837 && GET_MODE (to_rtx) == BLKmode
03838 && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
03839 && bitsize > 0
03840 && (bitpos % bitsize) == 0
03841 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
03842 && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
03843 {
03844 to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
03845 bitpos = 0;
03846 }
03847
03848 to_rtx = offset_address (to_rtx, offset_rtx,
03849 highest_pow2_factor_for_target (to,
03850 offset));
03851 }
03852
03853
03854 if (GET_CODE (to_rtx) == CONCAT)
03855 {
03856 if (TREE_CODE (TREE_TYPE (from)) == COMPLEX_TYPE)
03857 {
03858 gcc_assert (bitpos == 0);
03859 result = store_expr (from, to_rtx, false);
03860 }
03861 else
03862 {
03863 gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1));
03864 result = store_expr (from, XEXP (to_rtx, bitpos != 0), false);
03865 }
03866 }
03867 else
03868 {
03869 if (MEM_P (to_rtx))
03870 {
03871
03872
03873 to_rtx = shallow_copy_rtx (to_rtx);
03874
03875 set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
03876
03877
03878
03879 if (volatilep)
03880 MEM_VOLATILE_P (to_rtx) = 1;
03881 if (component_uses_parent_alias_set (to))
03882 MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
03883 }
03884
03885 if (optimize_bitfield_assignment_op (bitsize, bitpos, mode1,
03886 to_rtx, to, from))
03887 result = NULL;
03888 else
03889 result = store_field (to_rtx, bitsize, bitpos, mode1, from,
03890 TREE_TYPE (tem), get_alias_set (to));
03891 }
03892
03893 if (result)
03894 preserve_temp_slots (result);
03895 free_temp_slots ();
03896 pop_temp_slots ();
03897 return;
03898 }
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910 if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from)
03911 && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
03912 && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
03913 && REG_P (DECL_RTL (to))))
03914 {
03915 rtx value;
03916
03917 push_temp_slots ();
03918 value = expand_expr (from, NULL_RTX, VOIDmode, 0);
03919 if (to_rtx == 0)
03920 to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
03921
03922
03923
03924 if (GET_CODE (to_rtx) == PARALLEL)
03925 emit_group_load (to_rtx, value, TREE_TYPE (from),
03926 int_size_in_bytes (TREE_TYPE (from)));
03927 else if (GET_MODE (to_rtx) == BLKmode)
03928 emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
03929 else
03930 {
03931 if (POINTER_TYPE_P (TREE_TYPE (to)))
03932 value = convert_memory_address (GET_MODE (to_rtx), value);
03933 emit_move_insn (to_rtx, value);
03934 }
03935 preserve_temp_slots (to_rtx);
03936 free_temp_slots ();
03937 pop_temp_slots ();
03938 return;
03939 }
03940
03941
03942
03943
03944 if (to_rtx == 0)
03945 to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
03946
03947
03948 if (TREE_CODE (to) == RESULT_DECL
03949 && (REG_P (to_rtx) || GET_CODE (to_rtx) == PARALLEL))
03950 {
03951 rtx temp;
03952
03953 push_temp_slots ();
03954 temp = expand_expr (from, 0, GET_MODE (to_rtx), 0);
03955
03956 if (GET_CODE (to_rtx) == PARALLEL)
03957 emit_group_load (to_rtx, temp, TREE_TYPE (from),
03958 int_size_in_bytes (TREE_TYPE (from)));
03959 else
03960 emit_move_insn (to_rtx, temp);
03961
03962 preserve_temp_slots (to_rtx);
03963 free_temp_slots ();
03964 pop_temp_slots ();
03965 return;
03966 }
03967
03968
03969
03970
03971 if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
03972 && current_function_returns_struct
03973 && !current_function_returns_pcc_struct)
03974 {
03975 rtx from_rtx, size;
03976
03977 push_temp_slots ();
03978 size = expr_size (from);
03979 from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
03980
03981 emit_library_call (memmove_libfunc, LCT_NORMAL,
03982 VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
03983 XEXP (from_rtx, 0), Pmode,
03984 convert_to_mode (TYPE_MODE (sizetype),
03985 size, TYPE_UNSIGNED (sizetype)),
03986 TYPE_MODE (sizetype));
03987
03988 preserve_temp_slots (to_rtx);
03989 free_temp_slots ();
03990 pop_temp_slots ();
03991 return;
03992 }
03993
03994
03995
03996 push_temp_slots ();
03997 result = store_expr (from, to_rtx, 0);
03998 preserve_temp_slots (result);
03999 free_temp_slots ();
04000 pop_temp_slots ();
04001 return;
04002 }
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017 rtx
04018 store_expr (tree exp, rtx target, int call_param_p)
04019 {
04020 rtx temp;
04021 rtx alt_rtl = NULL_RTX;
04022 int dont_return_target = 0;
04023
04024 if (VOID_TYPE_P (TREE_TYPE (exp)))
04025 {
04026
04027
04028
04029 gcc_assert (!call_param_p);
04030 expand_expr (exp, const0_rtx, VOIDmode, 0);
04031 return NULL_RTX;
04032 }
04033 if (TREE_CODE (exp) == COMPOUND_EXPR)
04034 {
04035
04036
04037 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
04038 call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04039 return store_expr (TREE_OPERAND (exp, 1), target, call_param_p);
04040 }
04041 else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
04042 {
04043
04044
04045
04046
04047
04048 rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
04049
04050 do_pending_stack_adjust ();
04051 NO_DEFER_POP;
04052 jumpifnot (TREE_OPERAND (exp, 0), lab1);
04053 store_expr (TREE_OPERAND (exp, 1), target, call_param_p);
04054 emit_jump_insn (gen_jump (lab2));
04055 emit_barrier ();
04056 emit_label (lab1);
04057 store_expr (TREE_OPERAND (exp, 2), target, call_param_p);
04058 emit_label (lab2);
04059 OK_DEFER_POP;
04060
04061 return NULL_RTX;
04062 }
04063 else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
04064
04065
04066
04067
04068 {
04069 rtx inner_target = 0;
04070
04071
04072
04073
04074
04075
04076
04077 if (INTEGRAL_TYPE_P (TREE_TYPE (exp))
04078 && TREE_TYPE (TREE_TYPE (exp)) == 0
04079 && (!lang_hooks.reduce_bit_field_operations
04080 || (GET_MODE_PRECISION (GET_MODE (target))
04081 == TYPE_PRECISION (TREE_TYPE (exp)))))
04082 {
04083 if (TYPE_UNSIGNED (TREE_TYPE (exp))
04084 != SUBREG_PROMOTED_UNSIGNED_P (target))
04085 exp = convert
04086 (lang_hooks.types.signed_or_unsigned_type
04087 (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
04088
04089 exp = convert (lang_hooks.types.type_for_mode
04090 (GET_MODE (SUBREG_REG (target)),
04091 SUBREG_PROMOTED_UNSIGNED_P (target)),
04092 exp);
04093
04094 inner_target = SUBREG_REG (target);
04095 }
04096
04097 temp = expand_expr (exp, inner_target, VOIDmode,
04098 call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04099
04100
04101
04102 if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
04103 {
04104 temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
04105 temp, SUBREG_PROMOTED_UNSIGNED_P (target));
04106 temp = convert_modes (GET_MODE (SUBREG_REG (target)),
04107 GET_MODE (target), temp,
04108 SUBREG_PROMOTED_UNSIGNED_P (target));
04109 }
04110
04111 convert_move (SUBREG_REG (target), temp,
04112 SUBREG_PROMOTED_UNSIGNED_P (target));
04113
04114 return NULL_RTX;
04115 }
04116 else
04117 {
04118 temp = expand_expr_real (exp, target, GET_MODE (target),
04119 (call_param_p
04120 ? EXPAND_STACK_PARM : EXPAND_NORMAL),
04121 &alt_rtl);
04122
04123
04124
04125
04126
04127
04128
04129 if (!(target && REG_P (target)
04130 && REGNO (target) < FIRST_PSEUDO_REGISTER)
04131 && !(MEM_P (target) && MEM_VOLATILE_P (target))
04132 && ! rtx_equal_p (temp, target)
04133 && CONSTANT_P (temp))
04134 dont_return_target = 1;
04135 }
04136
04137
04138
04139
04140
04141 if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
04142 && TREE_CODE (exp) != ERROR_MARK
04143 && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
04144 temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
04145 temp, TYPE_UNSIGNED (TREE_TYPE (exp)));
04146
04147
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165 if ((! rtx_equal_p (temp, target)
04166 || (temp != target && (side_effects_p (temp)
04167 || side_effects_p (target))))
04168 && TREE_CODE (exp) != ERROR_MARK
04169
04170
04171
04172 && !(alt_rtl && rtx_equal_p (alt_rtl, target))
04173
04174
04175
04176
04177 && expr_size (exp) != const0_rtx)
04178 {
04179 if (GET_MODE (temp) != GET_MODE (target)
04180 && GET_MODE (temp) != VOIDmode)
04181 {
04182 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
04183 if (dont_return_target)
04184 {
04185
04186
04187
04188 temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
04189 emit_move_insn (target, temp);
04190 }
04191 else
04192 convert_move (target, temp, unsignedp);
04193 }
04194
04195 else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
04196 {
04197
04198
04199
04200
04201 rtx size = expr_size (exp);
04202
04203 if (GET_CODE (size) == CONST_INT
04204 && INTVAL (size) < TREE_STRING_LENGTH (exp))
04205 emit_block_move (target, temp, size,
04206 (call_param_p
04207 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04208 else
04209 {
04210
04211 tree copy_size
04212 = size_binop (MIN_EXPR,
04213 make_tree (sizetype, size),
04214 size_int (TREE_STRING_LENGTH (exp)));
04215 rtx copy_size_rtx
04216 = expand_expr (copy_size, NULL_RTX, VOIDmode,
04217 (call_param_p
04218 ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04219 rtx label = 0;
04220
04221
04222 copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
04223 TYPE_UNSIGNED (sizetype));
04224 emit_block_move (target, temp, copy_size_rtx,
04225 (call_param_p
04226 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04227
04228
04229
04230 if (GET_CODE (copy_size_rtx) == CONST_INT)
04231 {
04232 size = plus_constant (size, -INTVAL (copy_size_rtx));
04233 target = adjust_address (target, BLKmode,
04234 INTVAL (copy_size_rtx));
04235 }
04236 else
04237 {
04238 size = expand_binop (TYPE_MODE (sizetype), sub_optab, size,
04239 copy_size_rtx, NULL_RTX, 0,
04240 OPTAB_LIB_WIDEN);
04241
04242 #ifdef POINTERS_EXTEND_UNSIGNED
04243 if (GET_MODE (copy_size_rtx) != Pmode)
04244 copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx,
04245 TYPE_UNSIGNED (sizetype));
04246 #endif
04247
04248 target = offset_address (target, copy_size_rtx,
04249 highest_pow2_factor (copy_size));
04250 label = gen_label_rtx ();
04251 emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
04252 GET_MODE (size), 0, label);
04253 }
04254
04255 if (size != const0_rtx)
04256 clear_storage (target, size, BLOCK_OP_NORMAL);
04257
04258 if (label)
04259 emit_label (label);
04260 }
04261 }
04262
04263
04264 else if (GET_CODE (target) == PARALLEL)
04265 emit_group_load (target, temp, TREE_TYPE (exp),
04266 int_size_in_bytes (TREE_TYPE (exp)));
04267 else if (GET_MODE (temp) == BLKmode)
04268 emit_block_move (target, temp, expr_size (exp),
04269 (call_param_p
04270 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04271 else
04272 {
04273 temp = force_operand (temp, target);
04274 if (temp != target)
04275 emit_move_insn (target, temp);
04276 }
04277 }
04278
04279 return NULL_RTX;
04280 }
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292 static void
04293 categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
04294 HOST_WIDE_INT *p_nc_elts,
04295 HOST_WIDE_INT *p_elt_count,
04296 bool *p_must_clear)
04297 {
04298 HOST_WIDE_INT nz_elts, nc_elts, elt_count;
04299 tree list;
04300
04301 nz_elts = 0;
04302 nc_elts = 0;
04303 elt_count = 0;
04304
04305 for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list))
04306 {
04307 tree value = TREE_VALUE (list);
04308 tree purpose = TREE_PURPOSE (list);
04309 HOST_WIDE_INT mult;
04310
04311 mult = 1;
04312 if (TREE_CODE (purpose) == RANGE_EXPR)
04313 {
04314 tree lo_index = TREE_OPERAND (purpose, 0);
04315 tree hi_index = TREE_OPERAND (purpose, 1);
04316
04317 if (host_integerp (lo_index, 1) && host_integerp (hi_index, 1))
04318 mult = (tree_low_cst (hi_index, 1)
04319 - tree_low_cst (lo_index, 1) + 1);
04320 }
04321
04322 switch (TREE_CODE (value))
04323 {
04324 case CONSTRUCTOR:
04325 {
04326 HOST_WIDE_INT nz = 0, nc = 0, ic = 0;
04327 categorize_ctor_elements_1 (value, &nz, &nc, &ic, p_must_clear);
04328 nz_elts += mult * nz;
04329 nc_elts += mult * nc;
04330 elt_count += mult * ic;
04331 }
04332 break;
04333
04334 case INTEGER_CST:
04335 case REAL_CST:
04336 if (!initializer_zerop (value))
04337 nz_elts += mult;
04338 elt_count += mult;
04339 break;
04340
04341 case STRING_CST:
04342 nz_elts += mult * TREE_STRING_LENGTH (value);
04343 elt_count += mult * TREE_STRING_LENGTH (value);
04344 break;
04345
04346 case COMPLEX_CST:
04347 if (!initializer_zerop (TREE_REALPART (value)))
04348 nz_elts += mult;
04349 if (!initializer_zerop (TREE_IMAGPART (value)))
04350 nz_elts += mult;
04351 elt_count += mult;
04352 break;
04353
04354 case VECTOR_CST:
04355 {
04356 tree v;
04357 for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v))
04358 {
04359 if (!initializer_zerop (TREE_VALUE (v)))
04360 nz_elts += mult;
04361 elt_count += mult;
04362 }
04363 }
04364 break;
04365
04366 default:
04367 nz_elts += mult;
04368 elt_count += mult;
04369 if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
04370 nc_elts += mult;
04371 break;
04372 }
04373 }
04374
04375 if (!*p_must_clear
04376 && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
04377 || TREE_CODE (TREE_TYPE (ctor)) == QUAL_UNION_TYPE))
04378 {
04379 tree init_sub_type;
04380 bool clear_this = true;
04381
04382 list = CONSTRUCTOR_ELTS (ctor);
04383 if (list)
04384 {
04385
04386
04387 gcc_assert (TREE_CHAIN (list) == NULL);
04388
04389 init_sub_type = TREE_TYPE (TREE_VALUE (list));
04390
04391
04392
04393
04394
04395 if (simple_cst_equal (TYPE_SIZE (TREE_TYPE (ctor)),
04396 TYPE_SIZE (init_sub_type)) == 1)
04397 {
04398
04399
04400
04401 if (elt_count == count_type_elements (init_sub_type))
04402 clear_this = false;
04403 }
04404 }
04405
04406 *p_must_clear = clear_this;
04407 }
04408
04409 *p_nz_elts += nz_elts;
04410 *p_nc_elts += nc_elts;
04411 *p_elt_count += elt_count;
04412 }
04413
04414 void
04415 categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
04416 HOST_WIDE_INT *p_nc_elts,
04417 HOST_WIDE_INT *p_elt_count,
04418 bool *p_must_clear)
04419 {
04420 *p_nz_elts = 0;
04421 *p_nc_elts = 0;
04422 *p_elt_count = 0;
04423 *p_must_clear = false;
04424 categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count,
04425 p_must_clear);
04426 }
04427
04428
04429
04430
04431 HOST_WIDE_INT
04432 count_type_elements (tree type)
04433 {
04434 const HOST_WIDE_INT max = ~((HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT-1));
04435 switch (TREE_CODE (type))
04436 {
04437 case ARRAY_TYPE:
04438 {
04439 tree telts = array_type_nelts (type);
04440 if (telts && host_integerp (telts, 1))
04441 {
04442 HOST_WIDE_INT n = tree_low_cst (telts, 1) + 1;
04443 HOST_WIDE_INT m = count_type_elements (TREE_TYPE (type));
04444 if (n == 0)
04445 return 0;
04446 else if (max / n > m)
04447 return n * m;
04448 }
04449 return -1;
04450 }
04451
04452 case RECORD_TYPE:
04453 {
04454 HOST_WIDE_INT n = 0, t;
04455 tree f;
04456
04457 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
04458 if (TREE_CODE (f) == FIELD_DECL)
04459 {
04460 t = count_type_elements (TREE_TYPE (f));
04461 if (t < 0)
04462 return -1;
04463 n += t;
04464 }
04465
04466 return n;
04467 }
04468
04469 case UNION_TYPE:
04470 case QUAL_UNION_TYPE:
04471 {
04472
04473
04474 HOST_WIDE_INT n = int_size_in_bytes (type);
04475 if (n < 0)
04476 return -1;
04477 return n / UNITS_PER_WORD;
04478 }
04479
04480 case COMPLEX_TYPE:
04481 return 2;
04482
04483 case VECTOR_TYPE:
04484 return TYPE_VECTOR_SUBPARTS (type);
04485
04486 case INTEGER_TYPE:
04487 case REAL_TYPE:
04488 case ENUMERAL_TYPE:
04489 case BOOLEAN_TYPE:
04490 case CHAR_TYPE:
04491 case POINTER_TYPE:
04492 case OFFSET_TYPE:
04493 case REFERENCE_TYPE:
04494 return 1;
04495
04496 case VOID_TYPE:
04497 case METHOD_TYPE:
04498 case FILE_TYPE:
04499 case FUNCTION_TYPE:
04500 case LANG_TYPE:
04501 default:
04502 gcc_unreachable ();
04503 }
04504 }
04505
04506
04507
04508 static int
04509 mostly_zeros_p (tree exp)
04510 {
04511 if (TREE_CODE (exp) == CONSTRUCTOR)
04512
04513 {
04514 HOST_WIDE_INT nz_elts, nc_elts, count, elts;
04515 bool must_clear;
04516
04517 categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear);
04518 if (must_clear)
04519 return 1;
04520
04521 elts = count_type_elements (TREE_TYPE (exp));
04522
04523 return nz_elts < elts / 4;
04524 }
04525
04526 return initializer_zerop (exp);
04527 }
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540 static void
04541 store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
04542 HOST_WIDE_INT bitpos, enum machine_mode mode,
04543 tree exp, tree type, int cleared, int alias_set)
04544 {
04545 if (TREE_CODE (exp) == CONSTRUCTOR
04546
04547
04548 && bitpos % BITS_PER_UNIT == 0
04549 && (bitsize > 0 && bitsize % BITS_PER_UNIT == 0)
04550
04551
04552
04553 && (bitpos == 0 || MEM_P (target)))
04554 {
04555 if (MEM_P (target))
04556 target
04557 = adjust_address (target,
04558 GET_MODE (target) == BLKmode
04559 || 0 != (bitpos
04560 % GET_MODE_ALIGNMENT (GET_MODE (target)))
04561 ? BLKmode : VOIDmode, bitpos / BITS_PER_UNIT);
04562
04563
04564
04565 if (MEM_P (target) && ! MEM_KEEP_ALIAS_SET_P (target)
04566 && MEM_ALIAS_SET (target) != 0)
04567 {
04568 target = copy_rtx (target);
04569 set_mem_alias_set (target, alias_set);
04570 }
04571
04572 store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
04573 }
04574 else
04575 store_field (target, bitsize, bitpos, mode, exp, type, alias_set);
04576 }
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586 static void
04587 store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
04588 {
04589 tree type = TREE_TYPE (exp);
04590 #ifdef WORD_REGISTER_OPERATIONS
04591 HOST_WIDE_INT exp_size = int_size_in_bytes (type);
04592 #endif
04593
04594 switch (TREE_CODE (type))
04595 {
04596 case RECORD_TYPE:
04597 case UNION_TYPE:
04598 case QUAL_UNION_TYPE:
04599 {
04600 tree elt;
04601
04602
04603 if (size == 0 || cleared)
04604 cleared = 1;
04605
04606 else if ((TREE_CODE (type) == UNION_TYPE
04607 || TREE_CODE (type) == QUAL_UNION_TYPE)
04608 && ! CONSTRUCTOR_ELTS (exp))
04609
04610 {
04611 clear_storage (target, expr_size (exp), BLOCK_OP_NORMAL);
04612 cleared = 1;
04613 }
04614
04615
04616
04617
04618
04619 else if (REG_P (target) && TREE_STATIC (exp)
04620 && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
04621 {
04622 emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
04623 cleared = 1;
04624 }
04625
04626
04627
04628
04629
04630
04631 else if (size > 0
04632 && ((list_length (CONSTRUCTOR_ELTS (exp))
04633 != fields_length (type))
04634 || mostly_zeros_p (exp))
04635 && (!REG_P (target)
04636 || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
04637 == size)))
04638 {
04639 clear_storage (target, GEN_INT (size), BLOCK_OP_NORMAL);
04640 cleared = 1;
04641 }
04642
04643 if (! cleared)
04644 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
04645
04646
04647
04648
04649 for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
04650 {
04651 tree field = TREE_PURPOSE (elt);
04652 tree value = TREE_VALUE (elt);
04653 enum machine_mode mode;
04654 HOST_WIDE_INT bitsize;
04655 HOST_WIDE_INT bitpos = 0;
04656 tree offset;
04657 rtx to_rtx = target;
04658
04659
04660
04661 if (field == 0)
04662 continue;
04663
04664 if (cleared && initializer_zerop (value))
04665 continue;
04666
04667 if (host_integerp (DECL_SIZE (field), 1))
04668 bitsize = tree_low_cst (DECL_SIZE (field), 1);
04669 else
04670 bitsize = -1;
04671
04672 mode = DECL_MODE (field);
04673 if (DECL_BIT_FIELD (field))
04674 mode = VOIDmode;
04675
04676 offset = DECL_FIELD_OFFSET (field);
04677 if (host_integerp (offset, 0)
04678 && host_integerp (bit_position (field), 0))
04679 {
04680 bitpos = int_bit_position (field);
04681 offset = 0;
04682 }
04683 else
04684 bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
04685
04686 if (offset)
04687 {
04688 rtx offset_rtx;
04689
04690 offset
04691 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (offset,
04692 make_tree (TREE_TYPE (exp),
04693 target));
04694
04695 offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
04696 gcc_assert (MEM_P (to_rtx));
04697
04698 #ifdef POINTERS_EXTEND_UNSIGNED
04699 if (GET_MODE (offset_rtx) != Pmode)
04700 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
04701 #else
04702 if (GET_MODE (offset_rtx) != ptr_mode)
04703 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
04704 #endif
04705
04706 to_rtx = offset_address (to_rtx, offset_rtx,
04707 highest_pow2_factor (offset));
04708 }
04709
04710 #ifdef WORD_REGISTER_OPERATIONS
04711
04712
04713
04714
04715
04716 if (REG_P (target)
04717 && bitsize < BITS_PER_WORD
04718 && bitpos % BITS_PER_WORD == 0
04719 && GET_MODE_CLASS (mode) == MODE_INT
04720 && TREE_CODE (value) == INTEGER_CST
04721 && exp_size >= 0
04722 && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
04723 {
04724 tree type = TREE_TYPE (value);
04725
04726 if (TYPE_PRECISION (type) < BITS_PER_WORD)
04727 {
04728 type = lang_hooks.types.type_for_size
04729 (BITS_PER_WORD, TYPE_UNSIGNED (type));
04730 value = convert (type, value);
04731 }
04732
04733 if (BYTES_BIG_ENDIAN)
04734 value
04735 = fold (build2 (LSHIFT_EXPR, type, value,
04736 build_int_cst (NULL_TREE,
04737 BITS_PER_WORD - bitsize)));
04738 bitsize = BITS_PER_WORD;
04739 mode = word_mode;
04740 }
04741 #endif
04742
04743 if (MEM_P (to_rtx) && !MEM_KEEP_ALIAS_SET_P (to_rtx)
04744 && DECL_NONADDRESSABLE_P (field))
04745 {
04746 to_rtx = copy_rtx (to_rtx);
04747 MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
04748 }
04749
04750 store_constructor_field (to_rtx, bitsize, bitpos, mode,
04751 value, type, cleared,
04752 get_alias_set (TREE_TYPE (field)));
04753 }
04754 break;
04755 }
04756 case ARRAY_TYPE:
04757 {
04758 tree elt;
04759 int i;
04760 int need_to_clear;
04761 tree domain;
04762 tree elttype = TREE_TYPE (type);
04763 int const_bounds_p;
04764 HOST_WIDE_INT minelt = 0;
04765 HOST_WIDE_INT maxelt = 0;
04766
04767 domain = TYPE_DOMAIN (type);
04768 const_bounds_p = (TYPE_MIN_VALUE (domain)
04769 && TYPE_MAX_VALUE (domain)
04770 && host_integerp (TYPE_MIN_VALUE (domain), 0)
04771 && host_integerp (TYPE_MAX_VALUE (domain), 0));
04772
04773
04774 if (const_bounds_p)
04775 {
04776 minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
04777 maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
04778 }
04779
04780
04781
04782
04783 if (cleared)
04784 need_to_clear = 0;
04785 else if (REG_P (target) && TREE_STATIC (exp))
04786 need_to_clear = 1;
04787 else
04788 {
04789 HOST_WIDE_INT count = 0, zero_count = 0;
04790 need_to_clear = ! const_bounds_p;
04791
04792
04793
04794
04795 for (elt = CONSTRUCTOR_ELTS (exp);
04796 elt != NULL_TREE && ! need_to_clear;
04797 elt = TREE_CHAIN (elt))
04798 {
04799 tree index = TREE_PURPOSE (elt);
04800 HOST_WIDE_INT this_node_count;
04801
04802 if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
04803 {
04804 tree lo_index = TREE_OPERAND (index, 0);
04805 tree hi_index = TREE_OPERAND (index, 1);
04806
04807 if (! host_integerp (lo_index, 1)
04808 || ! host_integerp (hi_index, 1))
04809 {
04810 need_to_clear = 1;
04811 break;
04812 }
04813
04814 this_node_count = (tree_low_cst (hi_index, 1)
04815 - tree_low_cst (lo_index, 1) + 1);
04816 }
04817 else
04818 this_node_count = 1;
04819
04820 count += this_node_count;
04821 if (mostly_zeros_p (TREE_VALUE (elt)))
04822 zero_count += this_node_count;
04823 }
04824
04825
04826
04827
04828 if (! need_to_clear
04829 && (count < maxelt - minelt + 1
04830 || 4 * zero_count >= 3 * count))
04831 need_to_clear = 1;
04832 }
04833
04834 if (need_to_clear && size > 0)
04835 {
04836 if (REG_P (target))
04837 emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
04838 else
04839 clear_storage (target, GEN_INT (size), BLOCK_OP_NORMAL);
04840 cleared = 1;
04841 }
04842
04843 if (!cleared && REG_P (target))
04844
04845 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
04846
04847
04848
04849
04850 for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
04851 elt;
04852 elt = TREE_CHAIN (elt), i++)
04853 {
04854 enum machine_mode mode;
04855 HOST_WIDE_INT bitsize;
04856 HOST_WIDE_INT bitpos;
04857 int unsignedp;
04858 tree value = TREE_VALUE (elt);
04859 tree index = TREE_PURPOSE (elt);
04860 rtx xtarget = target;
04861
04862 if (cleared && initializer_zerop (value))
04863 continue;
04864
04865 unsignedp = TYPE_UNSIGNED (elttype);
04866 mode = TYPE_MODE (elttype);
04867 if (mode == BLKmode)
04868 bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
04869 ? tree_low_cst (TYPE_SIZE (elttype), 1)
04870 : -1);
04871 else
04872 bitsize = GET_MODE_BITSIZE (mode);
04873
04874 if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
04875 {
04876 tree lo_index = TREE_OPERAND (index, 0);
04877 tree hi_index = TREE_OPERAND (index, 1);
04878 rtx index_r, pos_rtx;
04879 HOST_WIDE_INT lo, hi, count;
04880 tree position;
04881
04882
04883 if (const_bounds_p
04884 && host_integerp (lo_index, 0)
04885 && host_integerp (hi_index, 0)
04886 && (lo = tree_low_cst (lo_index, 0),
04887 hi = tree_low_cst (hi_index, 0),
04888 count = hi - lo + 1,
04889 (!MEM_P (target)
04890 || count <= 2
04891 || (host_integerp (TYPE_SIZE (elttype), 1)
04892 && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
04893 <= 40 * 8)))))
04894 {
04895 lo -= minelt; hi -= minelt;
04896 for (; lo <= hi; lo++)
04897 {
04898 bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
04899
04900 if (MEM_P (target)
04901 && !MEM_KEEP_ALIAS_SET_P (target)
04902 && TREE_CODE (type) == ARRAY_TYPE
04903 && TYPE_NONALIASED_COMPONENT (type))
04904 {
04905 target = copy_rtx (target);
04906 MEM_KEEP_ALIAS_SET_P (target) = 1;
04907 }
04908
04909 store_constructor_field
04910 (target, bitsize, bitpos, mode, value, type, cleared,
04911 get_alias_set (elttype));
04912 }
04913 }
04914 else
04915 {
04916 rtx loop_start = gen_label_rtx ();
04917 rtx loop_end = gen_label_rtx ();
04918 tree exit_cond;
04919
04920 expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
04921 unsignedp = TYPE_UNSIGNED (domain);
04922
04923 index = build_decl (VAR_DECL, NULL_TREE, domain);
04924
04925 index_r
04926 = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
04927 &unsignedp, 0));
04928 SET_DECL_RTL (index, index_r);
04929 store_expr (lo_index, index_r, 0);
04930
04931
04932 do_pending_stack_adjust ();
04933 emit_label (loop_start);
04934
04935
04936 position
04937 = convert (ssizetype,
04938 fold (build2 (MINUS_EXPR, TREE_TYPE (index),
04939 index, TYPE_MIN_VALUE (domain))));
04940 position = size_binop (MULT_EXPR, position,
04941 convert (ssizetype,
04942 TYPE_SIZE_UNIT (elttype)));
04943
04944 pos_rtx = expand_expr (position, 0, VOIDmode, 0);
04945 xtarget = offset_address (target, pos_rtx,
04946 highest_pow2_factor (position));
04947 xtarget = adjust_address (xtarget, mode, 0);
04948 if (TREE_CODE (value) == CONSTRUCTOR)
04949 store_constructor (value, xtarget, cleared,
04950 bitsize / BITS_PER_UNIT);
04951 else
04952 store_expr (value, xtarget, 0);
04953
04954
04955 exit_cond = build2 (LT_EXPR, integer_type_node,
04956 index, hi_index);
04957 jumpif (exit_cond, loop_end);
04958
04959
04960
04961 expand_assignment (index,
04962 build2 (PLUS_EXPR, TREE_TYPE (index),
04963 index, integer_one_node));
04964
04965 emit_jump (loop_start);
04966
04967
04968 emit_label (loop_end);
04969 }
04970 }
04971 else if ((index != 0 && ! host_integerp (index, 0))
04972 || ! host_integerp (TYPE_SIZE (elttype), 1))
04973 {
04974 tree position;
04975
04976 if (index == 0)
04977 index = ssize_int (1);
04978
04979 if (minelt)
04980 index = fold_convert (ssizetype,
04981 fold (build2 (MINUS_EXPR,
04982 TREE_TYPE (index),
04983 index,
04984 TYPE_MIN_VALUE (domain))));
04985
04986 position = size_binop (MULT_EXPR, index,
04987 convert (ssizetype,
04988 TYPE_SIZE_UNIT (elttype)));
04989 xtarget = offset_address (target,
04990 expand_expr (position, 0, VOIDmode, 0),
04991 highest_pow2_factor (position));
04992 xtarget = adjust_address (xtarget, mode, 0);
04993 store_expr (value, xtarget, 0);
04994 }
04995 else
04996 {
04997 if (index != 0)
04998 bitpos = ((tree_low_cst (index, 0) - minelt)
04999 * tree_low_cst (TYPE_SIZE (elttype), 1));
05000 else
05001 bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
05002
05003 if (MEM_P (target) && !MEM_KEEP_ALIAS_SET_P (target)
05004 && TREE_CODE (type) == ARRAY_TYPE
05005 && TYPE_NONALIASED_COMPONENT (type))
05006 {
05007 target = copy_rtx (target);
05008 MEM_KEEP_ALIAS_SET_P (target) = 1;
05009 }
05010 store_constructor_field (target, bitsize, bitpos, mode, value,
05011 type, cleared, get_alias_set (elttype));
05012 }
05013 }
05014 break;
05015 }
05016
05017 case VECTOR_TYPE:
05018 {
05019 tree elt;
05020 int i;
05021 int need_to_clear;
05022 int icode = 0;
05023 tree elttype = TREE_TYPE (type);
05024 int elt_size = tree_low_cst (TYPE_SIZE (elttype), 1);
05025 enum machine_mode eltmode = TYPE_MODE (elttype);
05026 HOST_WIDE_INT bitsize;
05027 HOST_WIDE_INT bitpos;
05028 rtvec vector = NULL;
05029 unsigned n_elts;
05030
05031 gcc_assert (eltmode != BLKmode);
05032
05033 n_elts = TYPE_VECTOR_SUBPARTS (type);
05034 if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target)))
05035 {
05036 enum machine_mode mode = GET_MODE (target);
05037
05038 icode = (int) vec_init_optab->handlers[mode].insn_code;
05039 if (icode != CODE_FOR_nothing)
05040 {
05041 unsigned int i;
05042
05043 vector = rtvec_alloc (n_elts);
05044 for (i = 0; i < n_elts; i++)
05045 RTVEC_ELT (vector, i) = CONST0_RTX (GET_MODE_INNER (mode));
05046 }
05047 }
05048
05049
05050
05051
05052 if (cleared)
05053 need_to_clear = 0;
05054 else if (REG_P (target) && TREE_STATIC (exp))
05055 need_to_clear = 1;
05056 else
05057 {
05058 unsigned HOST_WIDE_INT count = 0, zero_count = 0;
05059
05060 for (elt = CONSTRUCTOR_ELTS (exp);
05061 elt != NULL_TREE;
05062 elt = TREE_CHAIN (elt))
05063 {
05064 int n_elts_here = tree_low_cst
05065 (int_const_binop (TRUNC_DIV_EXPR,
05066 TYPE_SIZE (TREE_TYPE (TREE_VALUE (elt))),
05067 TYPE_SIZE (elttype), 0), 1);
05068
05069 count += n_elts_here;
05070 if (mostly_zeros_p (TREE_VALUE (elt)))
05071 zero_count += n_elts_here;
05072 }
05073
05074
05075
05076 need_to_clear = (count < n_elts || 4 * zero_count >= 3 * count);
05077 }
05078
05079 if (need_to_clear && size > 0 && !vector)
05080 {
05081 if (REG_P (target))
05082 emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
05083 else
05084 clear_storage (target, GEN_INT (size), BLOCK_OP_NORMAL);
05085 cleared = 1;
05086 }
05087
05088 if (!cleared && REG_P (target))
05089
05090 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
05091
05092
05093
05094 for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
05095 elt;
05096 elt = TREE_CHAIN (elt), i += bitsize / elt_size)
05097 {
05098 tree value = TREE_VALUE (elt);
05099 tree index = TREE_PURPOSE (elt);
05100 HOST_WIDE_INT eltpos;
05101
05102 bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1);
05103 if (cleared && initializer_zerop (value))
05104 continue;
05105
05106 if (index != 0)
05107 eltpos = tree_low_cst (index, 1);
05108 else
05109 eltpos = i;
05110
05111 if (vector)
05112 {
05113
05114
05115 gcc_assert (TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE);
05116 RTVEC_ELT (vector, eltpos)
05117 = expand_expr (value, NULL_RTX, VOIDmode, 0);
05118 }
05119 else
05120 {
05121 enum machine_mode value_mode =
05122 TREE_CODE (TREE_TYPE (value)) == VECTOR_TYPE
05123 ? TYPE_MODE (TREE_TYPE (value))
05124 : eltmode;
05125 bitpos = eltpos * elt_size;
05126 store_constructor_field (target, bitsize, bitpos,
05127 value_mode, value, type,
05128 cleared, get_alias_set (elttype));
05129 }
05130 }
05131
05132 if (vector)
05133 emit_insn (GEN_FCN (icode)
05134 (target,
05135 gen_rtx_PARALLEL (GET_MODE (target), vector)));
05136 break;
05137 }
05138
05139 default:
05140 gcc_unreachable ();
05141 }
05142 }
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158 static rtx
05159 store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
05160 enum machine_mode mode, tree exp, tree type, int alias_set)
05161 {
05162 HOST_WIDE_INT width_mask = 0;
05163
05164 if (TREE_CODE (exp) == ERROR_MARK)
05165 return const0_rtx;
05166
05167
05168
05169 if (bitsize == 0)
05170 return expand_expr (exp, const0_rtx, VOIDmode, 0);
05171 else if (bitsize >= 0 && bitsize < HOST_BITS_PER_WIDE_INT)
05172 width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186 if (mode == BLKmode
05187 && (REG_P (target) || GET_CODE (target) == SUBREG))
05188 {
05189 rtx object = assign_temp (type, 0, 1, 1);
05190 rtx blk_object = adjust_address (object, BLKmode, 0);
05191
05192 if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
05193 emit_move_insn (object, target);
05194
05195 store_field (blk_object, bitsize, bitpos, mode, exp, type, alias_set);
05196
05197 emit_move_insn (target, object);
05198
05199
05200 return blk_object;
05201 }
05202
05203 if (GET_CODE (target) == CONCAT)
05204 {
05205
05206
05207 gcc_assert (!bitpos);
05208 return store_expr (exp, target, 0);
05209 }
05210
05211
05212
05213
05214
05215 if (mode == VOIDmode
05216 || (mode != BLKmode && ! direct_store[(int) mode]
05217 && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
05218 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
05219 || REG_P (target)
05220 || GET_CODE (target) == SUBREG
05221
05222
05223 || (mode != BLKmode
05224 && ((((MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode))
05225 || bitpos % GET_MODE_ALIGNMENT (mode))
05226 && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target)))
05227 || (bitpos % BITS_PER_UNIT != 0)))
05228
05229
05230
05231 || (bitsize >= 0
05232 && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
05233 && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
05234 {
05235 rtx temp;
05236
05237
05238
05239
05240
05241
05242 if (TREE_CODE (exp) == NOP_EXPR)
05243 {
05244 tree type = TREE_TYPE (exp);
05245 if (INTEGRAL_TYPE_P (type)
05246 && TYPE_PRECISION (type) < GET_MODE_BITSIZE (TYPE_MODE (type))
05247 && bitsize == TYPE_PRECISION (type))
05248 {
05249 type = TREE_TYPE (TREE_OPERAND (exp, 0));
05250 if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) >= bitsize)
05251 exp = TREE_OPERAND (exp, 0);
05252 }
05253 }
05254
05255 temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
05256
05257
05258
05259
05260
05261 if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
05262 && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
05263 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
05264 temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
05265 size_int (GET_MODE_BITSIZE (GET_MODE (temp))
05266 - bitsize),
05267 NULL_RTX, 1);
05268
05269
05270
05271 if (mode != VOIDmode && mode != BLKmode
05272 && mode != TYPE_MODE (TREE_TYPE (exp)))
05273 temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
05274
05275
05276
05277
05278 if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
05279 {
05280 gcc_assert (MEM_P (target) && MEM_P (temp)
05281 && !(bitpos % BITS_PER_UNIT));
05282
05283 target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
05284 emit_block_move (target, temp,
05285 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
05286 / BITS_PER_UNIT),
05287 BLOCK_OP_NORMAL);
05288
05289 return const0_rtx;
05290 }
05291
05292
05293 store_bit_field (target, bitsize, bitpos, mode, temp);
05294
05295 return const0_rtx;
05296 }
05297 else
05298 {
05299
05300 rtx to_rtx = adjust_address (target, mode, bitpos / BITS_PER_UNIT);
05301
05302 if (to_rtx == target)
05303 to_rtx = copy_rtx (to_rtx);
05304
05305 MEM_SET_IN_STRUCT_P (to_rtx, 1);
05306 if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
05307 set_mem_alias_set (to_rtx, alias_set);
05308
05309 return store_expr (exp, to_rtx, 0);
05310 }
05311 }
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349 tree
05350 get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
05351 HOST_WIDE_INT *pbitpos, tree *poffset,
05352 enum machine_mode *pmode, int *punsignedp,
05353 int *pvolatilep, bool keep_aligning)
05354 {
05355 tree size_tree = 0;
05356 enum machine_mode mode = VOIDmode;
05357 tree offset = size_zero_node;
05358 tree bit_offset = bitsize_zero_node;
05359 tree tem;
05360
05361
05362
05363 if (TREE_CODE (exp) == COMPONENT_REF)
05364 {
05365 size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
05366 if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
05367 mode = DECL_MODE (TREE_OPERAND (exp, 1));
05368
05369 *punsignedp = DECL_UNSIGNED (TREE_OPERAND (exp, 1));
05370 }
05371 else if (TREE_CODE (exp) == BIT_FIELD_REF)
05372 {
05373 size_tree = TREE_OPERAND (exp, 1);
05374 *punsignedp = BIT_FIELD_REF_UNSIGNED (exp);
05375 }
05376 else
05377 {
05378 mode = TYPE_MODE (TREE_TYPE (exp));
05379 *punsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
05380
05381 if (mode == BLKmode)
05382 size_tree = TYPE_SIZE (TREE_TYPE (exp));
05383 else
05384 *pbitsize = GET_MODE_BITSIZE (mode);
05385 }
05386
05387 if (size_tree != 0)
05388 {
05389 if (! host_integerp (size_tree, 1))
05390 mode = BLKmode, *pbitsize = -1;
05391 else
05392 *pbitsize = tree_low_cst (size_tree, 1);
05393 }
05394
05395
05396
05397 while (1)
05398 {
05399 switch (TREE_CODE (exp))
05400 {
05401 case BIT_FIELD_REF:
05402 bit_offset = size_binop (PLUS_EXPR, bit_offset,
05403 TREE_OPERAND (exp, 2));
05404 break;
05405
05406 case COMPONENT_REF:
05407 {
05408 tree field = TREE_OPERAND (exp, 1);
05409 tree this_offset = component_ref_field_offset (exp);
05410
05411
05412
05413
05414 if (this_offset == 0)
05415 break;
05416
05417 offset = size_binop (PLUS_EXPR, offset, this_offset);
05418 bit_offset = size_binop (PLUS_EXPR, bit_offset,
05419 DECL_FIELD_BIT_OFFSET (field));
05420
05421
05422 }
05423 break;
05424
05425 case ARRAY_REF:
05426 case ARRAY_RANGE_REF:
05427 {
05428 tree index = TREE_OPERAND (exp, 1);
05429 tree low_bound = array_ref_low_bound (exp);
05430 tree unit_size = array_ref_element_size (exp);
05431
05432
05433
05434
05435
05436 if (! integer_zerop (low_bound))
05437 index = fold (build2 (MINUS_EXPR, TREE_TYPE (index),
05438 index, low_bound));
05439
05440 offset = size_binop (PLUS_EXPR, offset,
05441 size_binop (MULT_EXPR,
05442 convert (sizetype, index),
05443 unit_size));
05444 }
05445 break;
05446
05447 case REALPART_EXPR:
05448 break;
05449
05450 case IMAGPART_EXPR:
05451 bit_offset = size_binop (PLUS_EXPR, bit_offset,
05452 bitsize_int (*pbitsize));
05453 break;
05454
05455 case VIEW_CONVERT_EXPR:
05456 if (keep_aligning && STRICT_ALIGNMENT
05457 && (TYPE_ALIGN (TREE_TYPE (exp))
05458 > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))))
05459 && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
05460 < BIGGEST_ALIGNMENT)
05461 && (TYPE_ALIGN_OK (TREE_TYPE (exp))
05462 || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0)))))
05463 goto done;
05464 break;
05465
05466 default:
05467 goto done;
05468 }
05469
05470
05471 if (TREE_THIS_VOLATILE (exp))
05472 *pvolatilep = 1;
05473
05474 exp = TREE_OPERAND (exp, 0);
05475 }
05476 done:
05477
05478
05479
05480 if (host_integerp (offset, 0)
05481 && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
05482 bitsize_unit_node))
05483 && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
05484 && host_integerp (tem, 0))
05485 *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
05486 else
05487 *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
05488
05489 *pmode = mode;
05490 return exp;
05491 }
05492
05493
05494
05495
05496 tree
05497 array_ref_element_size (tree exp)
05498 {
05499 tree aligned_size = TREE_OPERAND (exp, 3);
05500 tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
05501
05502
05503
05504 if (aligned_size)
05505 {
05506
05507
05508 if (TREE_TYPE (aligned_size) != sizetype)
05509 aligned_size = fold_convert (sizetype, aligned_size);
05510 return size_binop (MULT_EXPR, aligned_size,
05511 size_int (TYPE_ALIGN_UNIT (elmt_type)));
05512 }
05513
05514
05515
05516 else
05517 return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
05518 }
05519
05520
05521
05522
05523 tree
05524 array_ref_low_bound (tree exp)
05525 {
05526 tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
05527
05528
05529 if (TREE_OPERAND (exp, 2))
05530 return TREE_OPERAND (exp, 2);
05531
05532
05533
05534 if (domain_type && TYPE_MIN_VALUE (domain_type))
05535 return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
05536
05537
05538 return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
05539 }
05540
05541
05542
05543
05544 tree
05545 array_ref_up_bound (tree exp)
05546 {
05547 tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
05548
05549
05550
05551 if (domain_type && TYPE_MAX_VALUE (domain_type))
05552 return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
05553
05554
05555 return NULL_TREE;
05556 }
05557
05558
05559
05560
05561 tree
05562 component_ref_field_offset (tree exp)
05563 {
05564 tree aligned_offset = TREE_OPERAND (exp, 2);
05565 tree field = TREE_OPERAND (exp, 1);
05566
05567
05568
05569
05570 if (aligned_offset)
05571 {
05572
05573
05574 if (TREE_TYPE (aligned_offset) != sizetype)
05575 aligned_offset = fold_convert (sizetype, aligned_offset);
05576 return size_binop (MULT_EXPR, aligned_offset,
05577 size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT));
05578 }
05579
05580
05581
05582 else
05583 return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
05584 }
05585
05586
05587
05588 int
05589 handled_component_p (tree t)
05590 {
05591 switch (TREE_CODE (t))
05592 {
05593 case BIT_FIELD_REF:
05594 case COMPONENT_REF:
05595 case ARRAY_REF:
05596 case ARRAY_RANGE_REF:
05597 case VIEW_CONVERT_EXPR:
05598 case REALPART_EXPR:
05599 case IMAGPART_EXPR:
05600 return 1;
05601
05602 default:
05603 return 0;
05604 }
05605 }
05606
05607
05608
05609
05610
05611
05612
05613
05614 rtx
05615 force_operand (rtx value, rtx target)
05616 {
05617 rtx op1, op2;
05618
05619 rtx subtarget = get_subtarget (target);
05620 enum rtx_code code = GET_CODE (value);
05621
05622
05623 if (code == SUBREG
05624 && !REG_P (SUBREG_REG (value))
05625 && !MEM_P (SUBREG_REG (value)))
05626 {
05627 value = simplify_gen_subreg (GET_MODE (value),
05628 force_reg (GET_MODE (SUBREG_REG (value)),
05629 force_operand (SUBREG_REG (value),
05630 NULL_RTX)),
05631 GET_MODE (SUBREG_REG (value)),
05632 SUBREG_BYTE (value));
05633 code = GET_CODE (value);
05634 }
05635
05636
05637 if ((code == PLUS || code == MINUS)
05638 && XEXP (value, 0) == pic_offset_table_rtx
05639 && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
05640 || GET_CODE (XEXP (value, 1)) == LABEL_REF
05641 || GET_CODE (XEXP (value, 1)) == CONST))
05642 {
05643 if (!subtarget)
05644 subtarget = gen_reg_rtx (GET_MODE (value));
05645 emit_move_insn (subtarget, value);
05646 return subtarget;
05647 }
05648
05649 if (code == ZERO_EXTEND || code == SIGN_EXTEND)
05650 {
05651 if (!target)
05652 target = gen_reg_rtx (GET_MODE (value));
05653 convert_move (target, force_operand (XEXP (value, 0), NULL),
05654 code == ZERO_EXTEND);
05655 return target;
05656 }
05657
05658 if (ARITHMETIC_P (value))
05659 {
05660 op2 = XEXP (value, 1);
05661 if (!CONSTANT_P (op2) && !(REG_P (op2) && op2 != subtarget))
05662 subtarget = 0;
05663 if (code == MINUS && GET_CODE (op2) == CONST_INT)
05664 {
05665 code = PLUS;
05666 op2 = negate_rtx (GET_MODE (value), op2);
05667 }
05668
05669
05670
05671
05672
05673
05674
05675 if (code == PLUS && GET_CODE (op2) == CONST_INT
05676 && GET_CODE (XEXP (value, 0)) == PLUS
05677 && REG_P (XEXP (XEXP (value, 0), 0))
05678 && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
05679 && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
05680 {
05681 rtx temp = expand_simple_binop (GET_MODE (value), code,
05682 XEXP (XEXP (value, 0), 0), op2,
05683 subtarget, 0, OPTAB_LIB_WIDEN);
05684 return expand_simple_binop (GET_MODE (value), code, temp,
05685 force_operand (XEXP (XEXP (value,
05686 0), 1), 0),
05687 target, 0, OPTAB_LIB_WIDEN);
05688 }
05689
05690 op1 = force_operand (XEXP (value, 0), subtarget);
05691 op2 = force_operand (op2, NULL_RTX);
05692 switch (code)
05693 {
05694 case MULT:
05695 return expand_mult (GET_MODE (value), op1, op2, target, 1);
05696 case DIV:
05697 if (!INTEGRAL_MODE_P (GET_MODE (value)))
05698 return expand_simple_binop (GET_MODE (value), code, op1, op2,
05699 target, 1, OPTAB_LIB_WIDEN);
05700 else
05701 return expand_divmod (0,
05702 FLOAT_MODE_P (GET_MODE (value))
05703 ? RDIV_EXPR : TRUNC_DIV_EXPR,
05704 GET_MODE (value), op1, op2, target, 0);
05705 break;
05706 case MOD:
05707 return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
05708 target, 0);
05709 break;
05710 case UDIV:
05711 return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
05712 target, 1);
05713 break;
05714 case UMOD:
05715 return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
05716 target, 1);
05717 break;
05718 case ASHIFTRT:
05719 return expand_simple_binop (GET_MODE (value), code, op1, op2,
05720 target, 0, OPTAB_LIB_WIDEN);
05721 break;
05722 default:
05723 return expand_simple_binop (GET_MODE (value), code, op1, op2,
05724 target, 1, OPTAB_LIB_WIDEN);
05725 }
05726 }
05727 if (UNARY_P (value))
05728 {
05729 op1 = force_operand (XEXP (value, 0), NULL_RTX);
05730 return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
05731 }
05732
05733 #ifdef INSN_SCHEDULING
05734
05735
05736 if (GET_CODE (value) == SUBREG && MEM_P (SUBREG_REG (value))
05737 && (GET_MODE_SIZE (GET_MODE (value))
05738 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (value)))))
05739 value
05740 = simplify_gen_subreg (GET_MODE (value),
05741 force_reg (GET_MODE (SUBREG_REG (value)),
05742 force_operand (SUBREG_REG (value),
05743 NULL_RTX)),
05744 GET_MODE (SUBREG_REG (value)),
05745 SUBREG_BYTE (value));
05746 #endif
05747
05748 return value;
05749 }
05750
05751
05752
05753
05754
05755
05756
05757
05758
05759 int
05760 safe_from_p (rtx x, tree exp, int top_p)
05761 {
05762 rtx exp_rtl = 0;
05763 int i, nops;
05764
05765 if (x == 0
05766
05767
05768
05769
05770
05771
05772 || (top_p && TREE_TYPE (exp) != 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
05773 && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
05774 && (TREE_CODE (TREE_TYPE (exp)) != ARRAY_TYPE
05775 || TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
05776 || TREE_CODE (TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)))
05777 != INTEGER_CST)
05778 && GET_MODE (x) == BLKmode)
05779
05780 || (MEM_P (x)
05781 && (XEXP (x, 0) == virtual_outgoing_args_rtx
05782 || (GET_CODE (XEXP (x, 0)) == PLUS
05783 && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))))
05784 return 1;
05785
05786
05787
05788 if (GET_CODE (x) == SUBREG)
05789 {
05790 x = SUBREG_REG (x);
05791 if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
05792 return 0;
05793 }
05794
05795
05796 switch (TREE_CODE_CLASS (TREE_CODE (exp)))
05797 {
05798 case tcc_declaration:
05799 exp_rtl = DECL_RTL_IF_SET (exp);
05800 break;
05801
05802 case tcc_constant:
05803 return 1;
05804
05805 case tcc_exceptional:
05806 if (TREE_CODE (exp) == TREE_LIST)
05807 {
05808 while (1)
05809 {
05810 if (TREE_VALUE (exp) && !safe_from_p (x, TREE_VALUE (exp), 0))
05811 return 0;
05812 exp = TREE_CHAIN (exp);
05813 if (!exp)
05814 return 1;
05815 if (TREE_CODE (exp) != TREE_LIST)
05816 return safe_from_p (x, exp, 0);
05817 }
05818 }
05819 else if (TREE_CODE (exp) == ERROR_MARK)
05820 return 1;
05821 else
05822 return 0;
05823
05824 case tcc_statement:
05825
05826
05827 return (TREE_CODE (exp) != DECL_EXPR
05828 || TREE_CODE (DECL_EXPR_DECL (exp)) != VAR_DECL
05829 || !DECL_INITIAL (DECL_EXPR_DECL (exp))
05830 || safe_from_p (x, DECL_INITIAL (DECL_EXPR_DECL (exp)), 0));
05831
05832 case tcc_binary:
05833 case tcc_comparison:
05834 if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))
05835 return 0;
05836
05837
05838 case tcc_unary:
05839 return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
05840
05841 case tcc_expression:
05842 case tcc_reference:
05843
05844
05845
05846
05847
05848 switch (TREE_CODE (exp))
05849 {
05850 case ADDR_EXPR:
05851
05852
05853 if (staticp (TREE_OPERAND (exp, 0))
05854 || TREE_STATIC (exp)
05855 || safe_from_p (x, TREE_OPERAND (exp, 0), 0))
05856 return 1;
05857
05858
05859
05860
05861 exp = TREE_OPERAND (exp, 0);
05862 if (DECL_P (exp))
05863 {
05864 if (!DECL_RTL_SET_P (exp)
05865 || !MEM_P (DECL_RTL (exp)))
05866 return 0;
05867 else
05868 exp_rtl = XEXP (DECL_RTL (exp), 0);
05869 }
05870 break;
05871
05872 case MISALIGNED_INDIRECT_REF:
05873 case ALIGN_INDIRECT_REF:
05874 case INDIRECT_REF:
05875 if (MEM_P (x)
05876 && alias_sets_conflict_p (MEM_ALIAS_SET (x),
05877 get_alias_set (exp)))
05878 return 0;
05879 break;
05880
05881 case CALL_EXPR:
05882
05883
05884 if ((REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
05885 || MEM_P (x))
05886 return 0;
05887 break;
05888
05889 case WITH_CLEANUP_EXPR:
05890 case CLEANUP_POINT_EXPR:
05891
05892 gcc_unreachable ();
05893
05894 case SAVE_EXPR:
05895 return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
05896
05897 default:
05898 break;
05899 }
05900
05901
05902 if (exp_rtl)
05903 break;
05904
05905 nops = TREE_CODE_LENGTH (TREE_CODE (exp));
05906 for (i = 0; i < nops; i++)
05907 if (TREE_OPERAND (exp, i) != 0
05908 && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
05909 return 0;
05910
05911
05912
05913 if ((unsigned int) TREE_CODE (exp)
05914 >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
05915 && !lang_hooks.safe_from_p (x, exp))
05916 return 0;
05917 break;
05918
05919 case tcc_type:
05920
05921 gcc_unreachable ();
05922 }
05923
05924
05925
05926 if (exp_rtl)
05927 {
05928 if (GET_CODE (exp_rtl) == SUBREG)
05929 {
05930 exp_rtl = SUBREG_REG (exp_rtl);
05931 if (REG_P (exp_rtl)
05932 && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER)
05933 return 0;
05934 }
05935
05936
05937
05938 return ! (rtx_equal_p (x, exp_rtl)
05939 || (MEM_P (x) && MEM_P (exp_rtl)
05940 && true_dependence (exp_rtl, VOIDmode, x,
05941 rtx_addr_varies_p)));
05942 }
05943
05944
05945 return 1;
05946 }
05947
05948
05949
05950
05951
05952 static unsigned HOST_WIDE_INT
05953 highest_pow2_factor (tree exp)
05954 {
05955 unsigned HOST_WIDE_INT c0, c1;
05956
05957 switch (TREE_CODE (exp))
05958 {
05959 case INTEGER_CST:
05960
05961
05962
05963
05964
05965
05966 if (TREE_CONSTANT_OVERFLOW (exp))
05967 return BIGGEST_ALIGNMENT;
05968 else
05969 {
05970
05971
05972 c0 = TREE_INT_CST_LOW (exp);
05973 c0 &= -c0;
05974 return c0 ? c0 : BIGGEST_ALIGNMENT;
05975 }
05976 break;
05977
05978 case PLUS_EXPR: case MINUS_EXPR: case MIN_EXPR: case MAX_EXPR:
05979 c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
05980 c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
05981 return MIN (c0, c1);
05982
05983 case MULT_EXPR:
05984 c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
05985 c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
05986 return c0 * c1;
05987
05988 case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR:
05989 case CEIL_DIV_EXPR:
05990 if (integer_pow2p (TREE_OPERAND (exp, 1))
05991 && host_integerp (TREE_OPERAND (exp, 1), 1))
05992 {
05993 c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
05994 c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1);
05995 return MAX (1, c0 / c1);
05996 }
05997 break;
05998
05999 case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR:
06000 case SAVE_EXPR:
06001 return highest_pow2_factor (TREE_OPERAND (exp, 0));
06002
06003 case COMPOUND_EXPR:
06004 return highest_pow2_factor (TREE_OPERAND (exp, 1));
06005
06006 case COND_EXPR:
06007 c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06008 c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
06009 return MIN (c0, c1);
06010
06011 default:
06012 break;
06013 }
06014
06015 return 1;
06016 }
06017
06018
06019
06020
06021
06022
06023 static unsigned HOST_WIDE_INT
06024 highest_pow2_factor_for_target (tree target, tree exp)
06025 {
06026 unsigned HOST_WIDE_INT target_align, factor;
06027
06028 factor = highest_pow2_factor (exp);
06029 if (TREE_CODE (target) == COMPONENT_REF)
06030 target_align = DECL_ALIGN_UNIT (TREE_OPERAND (target, 1));
06031 else
06032 target_align = TYPE_ALIGN_UNIT (TREE_TYPE (target));
06033 return MAX (factor, target_align);
06034 }
06035
06036
06037
06038 void
06039 expand_var (tree var)
06040 {
06041 if (DECL_EXTERNAL (var))
06042 return;
06043
06044 if (TREE_STATIC (var))
06045
06046
06047 var = DECL_ORIGIN (var);
06048
06049 if (TREE_STATIC (var)
06050 ? !TREE_ASM_WRITTEN (var)
06051 : !DECL_RTL_SET_P (var))
06052 {
06053 if (TREE_CODE (var) == VAR_DECL && DECL_VALUE_EXPR (var))
06054 ;
06055 else if (lang_hooks.expand_decl (var))
06056 ;
06057 else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
06058 expand_decl (var);
06059 else if (TREE_CODE (var) == VAR_DECL && TREE_STATIC (var))
06060 rest_of_decl_compilation (var, 0, 0);
06061 else
06062
06063 gcc_assert (TREE_CODE (var) == TYPE_DECL
06064 || TREE_CODE (var) == CONST_DECL
06065 || TREE_CODE (var) == FUNCTION_DECL
06066 || TREE_CODE (var) == LABEL_DECL);
06067 }
06068 }
06069
06070
06071
06072
06073
06074
06075 static void
06076 expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
06077 enum expand_modifier modifier)
06078 {
06079 if (! safe_from_p (target, exp1, 1))
06080 target = 0;
06081 if (operand_equal_p (exp0, exp1, 0))
06082 {
06083 *op0 = expand_expr (exp0, target, VOIDmode, modifier);
06084 *op1 = copy_rtx (*op0);
06085 }
06086 else
06087 {
06088
06089
06090 if (flag_evaluation_order && TREE_SIDE_EFFECTS (exp1))
06091 exp0 = save_expr (exp0);
06092 *op0 = expand_expr (exp0, target, VOIDmode, modifier);
06093 *op1 = expand_expr (exp1, NULL_RTX, VOIDmode, modifier);
06094 }
06095 }
06096
06097
06098
06099
06100
06101 static rtx
06102 expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
06103 enum expand_modifier modifier)
06104 {
06105 rtx result, subtarget;
06106 tree inner, offset;
06107 HOST_WIDE_INT bitsize, bitpos;
06108 int volatilep, unsignedp;
06109 enum machine_mode mode1;
06110
06111
06112
06113
06114
06115
06116
06117 if (TREE_CODE (exp) == CONSTRUCTOR
06118 || CONSTANT_CLASS_P (exp))
06119 return XEXP (output_constant_def (exp, 0), 0);
06120
06121
06122 switch (TREE_CODE (exp))
06123 {
06124 case INDIRECT_REF:
06125
06126 return expand_expr (TREE_OPERAND (exp, 0), target, tmode, EXPAND_NORMAL);
06127
06128 case CONST_DECL:
06129
06130 return expand_expr_addr_expr_1 (DECL_INITIAL (exp), target,
06131 tmode, modifier);
06132
06133 case REALPART_EXPR:
06134
06135
06136 offset = 0;
06137 bitpos = 0;
06138 inner = TREE_OPERAND (exp, 0);
06139 break;
06140
06141 case IMAGPART_EXPR:
06142
06143
06144
06145 offset = 0;
06146 bitpos = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)));
06147 inner = TREE_OPERAND (exp, 0);
06148 break;
06149
06150 default:
06151
06152
06153
06154
06155 if (DECL_P (exp)
06156 || TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE)
06157 {
06158 result = expand_expr (exp, target, tmode,
06159 modifier == EXPAND_INITIALIZER
06160 ? EXPAND_INITIALIZER : EXPAND_CONST_ADDRESS);
06161
06162
06163
06164
06165 gcc_assert (GET_CODE (result) == MEM);
06166 result = XEXP (result, 0);
06167
06168
06169 if (DECL_P (exp) && !TREE_USED (exp) == 0)
06170 {
06171 assemble_external (exp);
06172 TREE_USED (exp) = 1;
06173 }
06174
06175 if (modifier != EXPAND_INITIALIZER
06176 && modifier != EXPAND_CONST_ADDRESS)
06177 result = force_operand (result, target);
06178 return result;
06179 }
06180
06181
06182
06183
06184
06185
06186 inner = get_inner_reference (exp, &bitsize, &bitpos, &offset,
06187 &mode1, &unsignedp, &volatilep, false);
06188 break;
06189 }
06190
06191
06192 gcc_assert (inner != exp);
06193
06194 subtarget = offset || bitpos ? NULL_RTX : target;
06195 result = expand_expr_addr_expr_1 (inner, subtarget, tmode, modifier);
06196
06197 if (offset)
06198 {
06199 rtx tmp;
06200
06201 if (modifier != EXPAND_NORMAL)
06202 result = force_operand (result, NULL);
06203 tmp = expand_expr (offset, NULL, tmode, EXPAND_NORMAL);
06204
06205 result = convert_memory_address (tmode, result);
06206 tmp = convert_memory_address (tmode, tmp);
06207
06208 if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
06209 result = gen_rtx_PLUS (tmode, result, tmp);
06210 else
06211 {
06212 subtarget = bitpos ? NULL_RTX : target;
06213 result = expand_simple_binop (tmode, PLUS, result, tmp, subtarget,
06214 1, OPTAB_LIB_WIDEN);
06215 }
06216 }
06217
06218 if (bitpos)
06219 {
06220
06221
06222 gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
06223
06224 result = plus_constant (result, bitpos / BITS_PER_UNIT);
06225 if (modifier < EXPAND_SUM)
06226 result = force_operand (result, target);
06227 }
06228
06229 return result;
06230 }
06231
06232
06233
06234
06235 static rtx
06236 expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode,
06237 enum expand_modifier modifier)
06238 {
06239 enum machine_mode rmode;
06240 rtx result;
06241
06242
06243 if (tmode == VOIDmode)
06244 tmode = TYPE_MODE (TREE_TYPE (exp));
06245
06246
06247
06248
06249 if (tmode != Pmode && tmode != ptr_mode)
06250 tmode = Pmode;
06251
06252 result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
06253 tmode, modifier);
06254
06255
06256
06257
06258 rmode = GET_MODE (result);
06259 if (rmode == VOIDmode)
06260 rmode = tmode;
06261 if (rmode != tmode)
06262 result = convert_memory_address (tmode, result);
06263
06264 return result;
06265 }
06266
06267
06268
06269
06270
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316 static rtx expand_expr_real_1 (tree, rtx, enum machine_mode,
06317 enum expand_modifier, rtx *);
06318
06319 rtx
06320 expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
06321 enum expand_modifier modifier, rtx *alt_rtl)
06322 {
06323 int rn = -1;
06324 rtx ret, last = NULL;
06325
06326
06327 if (TREE_CODE (exp) == ERROR_MARK
06328 || TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK)
06329 {
06330 ret = CONST0_RTX (tmode);
06331 return ret ? ret : const0_rtx;
06332 }
06333
06334 if (flag_non_call_exceptions)
06335 {
06336 rn = lookup_stmt_eh_region (exp);
06337
06338 if (rn >= 0)
06339 last = get_last_insn ();
06340 }
06341
06342
06343
06344
06345
06346
06347
06348
06349
06350 if (cfun && EXPR_HAS_LOCATION (exp))
06351 {
06352 location_t saved_location = input_location;
06353 input_location = EXPR_LOCATION (exp);
06354 emit_line_note (input_location);
06355
06356
06357 record_block_change (TREE_BLOCK (exp));
06358
06359 ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
06360
06361 input_location = saved_location;
06362 }
06363 else
06364 {
06365 ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
06366 }
06367
06368
06369
06370
06371 if (rn >= 0)
06372 {
06373 rtx insn;
06374 for (insn = next_real_insn (last); insn;
06375 insn = next_real_insn (insn))
06376 {
06377 if (! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
06378
06379
06380 && GET_CODE (PATTERN (insn)) != CLOBBER
06381 && GET_CODE (PATTERN (insn)) != USE
06382 && (CALL_P (insn) || may_trap_p (PATTERN (insn))))
06383 {
06384 REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (rn),
06385 REG_NOTES (insn));
06386 }
06387 }
06388 }
06389
06390 return ret;
06391 }
06392
06393 static rtx
06394 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
06395 enum expand_modifier modifier, rtx *alt_rtl)
06396 {
06397 rtx op0, op1, temp;
06398 tree type = TREE_TYPE (exp);
06399 int unsignedp;
06400 enum machine_mode mode;
06401 enum tree_code code = TREE_CODE (exp);
06402 optab this_optab;
06403 rtx subtarget, original_target;
06404 int ignore;
06405 tree context;
06406 bool reduce_bit_field = false;
06407 #define REDUCE_BIT_FIELD(expr) (reduce_bit_field && !ignore \
06408 ? reduce_to_bit_field_precision ((expr), \
06409 target, \
06410 type) \
06411 : (expr))
06412
06413 mode = TYPE_MODE (type);
06414 unsignedp = TYPE_UNSIGNED (type);
06415 if (lang_hooks.reduce_bit_field_operations
06416 && TREE_CODE (type) == INTEGER_TYPE
06417 && GET_MODE_PRECISION (mode) > TYPE_PRECISION (type))
06418 {
06419
06420
06421
06422 reduce_bit_field = true;
06423 if (modifier == EXPAND_STACK_PARM)
06424 target = 0;
06425 }
06426
06427
06428 subtarget = get_subtarget (target);
06429 original_target = target;
06430 ignore = (target == const0_rtx
06431 || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
06432 || code == CONVERT_EXPR || code == COND_EXPR
06433 || code == VIEW_CONVERT_EXPR)
06434 && TREE_CODE (type) == VOID_TYPE));
06435
06436
06437
06438
06439
06440
06441
06442 if (ignore)
06443 {
06444 if (! TREE_SIDE_EFFECTS (exp))
06445 return const0_rtx;
06446
06447
06448
06449 if (TREE_THIS_VOLATILE (exp)
06450 && TREE_CODE (exp) != FUNCTION_DECL
06451 && mode != VOIDmode && mode != BLKmode
06452 && modifier != EXPAND_CONST_ADDRESS)
06453 {
06454 temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
06455 if (MEM_P (temp))
06456 temp = copy_to_reg (temp);
06457 return const0_rtx;
06458 }
06459
06460 if (TREE_CODE_CLASS (code) == tcc_unary
06461 || code == COMPONENT_REF || code == INDIRECT_REF)
06462 return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
06463 modifier);
06464
06465 else if (TREE_CODE_CLASS (code) == tcc_binary
06466 || TREE_CODE_CLASS (code) == tcc_comparison
06467 || code == ARRAY_REF || code == ARRAY_RANGE_REF)
06468 {
06469 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
06470 expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
06471 return const0_rtx;
06472 }
06473 else if (code == BIT_FIELD_REF)
06474 {
06475 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
06476 expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
06477 expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, modifier);
06478 return const0_rtx;
06479 }
06480
06481 target = 0;
06482 }
06483
06484
06485
06486
06487
06488
06489
06490
06491 if (! cse_not_expected && mode != BLKmode && target
06492 && (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
06493 && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
06494 && ! (code == CALL_EXPR && aggregate_value_p (exp, exp)))
06495 target = 0;
06496
06497 switch (code)
06498 {
06499 case LABEL_DECL:
06500 {
06501 tree function = decl_function_context (exp);
06502
06503 temp = label_rtx (exp);
06504 temp = gen_rtx_LABEL_REF (Pmode, temp);
06505
06506 if (function != current_function_decl
06507 && function != 0)
06508 LABEL_REF_NONLOCAL_P (temp) = 1;
06509
06510 temp = gen_rtx_MEM (FUNCTION_MODE, temp);
06511 return temp;
06512 }
06513
06514 case SSA_NAME:
06515 return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier,
06516 NULL);
06517
06518 case PARM_DECL:
06519 case VAR_DECL:
06520
06521
06522 if (DECL_SIZE (exp) == 0
06523 && COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (TREE_TYPE (exp))
06524 && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
06525 layout_decl (exp, 0);
06526
06527
06528
06529 case FUNCTION_DECL:
06530 case RESULT_DECL:
06531 gcc_assert (DECL_RTL (exp));
06532
06533
06534
06535
06536 if (! TREE_USED (exp))
06537 {
06538 assemble_external (exp);
06539 TREE_USED (exp) = 1;
06540 }
06541
06542
06543 temp = 0;
06544
06545
06546
06547 context = decl_function_context (exp);
06548 gcc_assert (!context
06549 || context == current_function_decl
06550 || TREE_STATIC (exp)
06551
06552 || TREE_CODE (exp) == FUNCTION_DECL);
06553
06554
06555
06556
06557
06558 if (MEM_P (DECL_RTL (exp))
06559 && REG_P (XEXP (DECL_RTL (exp), 0)))
06560 temp = validize_mem (DECL_RTL (exp));
06561
06562
06563
06564
06565
06566 else if (MEM_P (DECL_RTL (exp))
06567 && modifier != EXPAND_CONST_ADDRESS
06568 && modifier != EXPAND_SUM
06569 && modifier != EXPAND_INITIALIZER
06570 && (! memory_address_p (DECL_MODE (exp),
06571 XEXP (DECL_RTL (exp), 0))
06572 || (flag_force_addr
06573 && !REG_P (XEXP (DECL_RTL (exp), 0)))))
06574 {
06575 if (alt_rtl)
06576 *alt_rtl = DECL_RTL (exp);
06577 temp = replace_equiv_address (DECL_RTL (exp),
06578 copy_rtx (XEXP (DECL_RTL (exp), 0)));
06579 }
06580
06581
06582
06583 if (temp != 0)
06584 {
06585 if (MEM_P (temp) && REG_P (XEXP (temp, 0)))
06586 mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp));
06587
06588 return temp;
06589 }
06590
06591
06592
06593
06594
06595 if (REG_P (DECL_RTL (exp))
06596 && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
06597 {
06598 enum machine_mode pmode;
06599
06600
06601
06602 pmode = promote_mode (type, DECL_MODE (exp), &unsignedp,
06603 (TREE_CODE (exp) == RESULT_DECL ? 1 : 0));
06604 gcc_assert (GET_MODE (DECL_RTL (exp)) == pmode);
06605
06606 temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
06607 SUBREG_PROMOTED_VAR_P (temp) = 1;
06608 SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
06609 return temp;
06610 }
06611
06612 return DECL_RTL (exp);
06613
06614 case INTEGER_CST:
06615 temp = immed_double_const (TREE_INT_CST_LOW (exp),
06616 TREE_INT_CST_HIGH (exp), mode);
06617
06618
06619
06620
06621
06622
06623 if (TREE_CONSTANT_OVERFLOW (exp)
06624 && modifier != EXPAND_INITIALIZER)
06625 temp = force_reg (mode, temp);
06626
06627 return temp;
06628
06629 case VECTOR_CST:
06630 if (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_INT
06631 || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT)
06632 return const_vector_from_tree (exp);
06633 else
06634 return expand_expr (build1 (CONSTRUCTOR, TREE_TYPE (exp),
06635 TREE_VECTOR_CST_ELTS (exp)),
06636 ignore ? const0_rtx : target, tmode, modifier);
06637
06638 case CONST_DECL:
06639 return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
06640
06641 case REAL_CST:
06642
06643
06644
06645
06646
06647
06648
06649
06650
06651
06652 return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp),
06653 TYPE_MODE (TREE_TYPE (exp)));
06654
06655 case COMPLEX_CST:
06656
06657 if (original_target && GET_CODE (original_target) == CONCAT)
06658 {
06659 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
06660 rtx rtarg, itarg;
06661
06662 rtarg = XEXP (original_target, 0);
06663 itarg = XEXP (original_target, 1);
06664
06665
06666 op0 = expand_expr (TREE_REALPART (exp), rtarg, mode, 0);
06667 op1 = expand_expr (TREE_IMAGPART (exp), itarg, mode, 0);
06668
06669 if (op0 != rtarg)
06670 emit_move_insn (rtarg, op0);
06671 if (op1 != itarg)
06672 emit_move_insn (itarg, op1);
06673
06674 return original_target;
06675 }
06676
06677
06678
06679 case STRING_CST:
06680 temp = output_constant_def (exp, 1);
06681
06682
06683
06684
06685 if (modifier != EXPAND_CONST_ADDRESS
06686 && modifier != EXPAND_INITIALIZER
06687 && modifier != EXPAND_SUM
06688 && (! memory_address_p (mode, XEXP (temp, 0))
06689 || flag_force_addr))
06690 return replace_equiv_address (temp,
06691 copy_rtx (XEXP (temp, 0)));
06692 return temp;
06693
06694 case SAVE_EXPR:
06695 {
06696 tree val = TREE_OPERAND (exp, 0);
06697 rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl);
06698
06699 if (!SAVE_EXPR_RESOLVED_P (exp))
06700 {
06701
06702
06703
06704
06705 gcc_assert (GET_MODE (ret) != BLKmode);
06706
06707 val = build_decl (VAR_DECL, NULL, TREE_TYPE (exp));
06708 DECL_ARTIFICIAL (val) = 1;
06709 DECL_IGNORED_P (val) = 1;
06710 TREE_OPERAND (exp, 0) = val;
06711 SAVE_EXPR_RESOLVED_P (exp) = 1;
06712
06713 if (!CONSTANT_P (ret))
06714 ret = copy_to_reg (ret);
06715 SET_DECL_RTL (val, ret);
06716 }
06717
06718 return ret;
06719 }
06720
06721 case GOTO_EXPR:
06722 if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
06723 expand_goto (TREE_OPERAND (exp, 0));
06724 else
06725 expand_computed_goto (TREE_OPERAND (exp, 0));
06726 return const0_rtx;
06727
06728 case CONSTRUCTOR:
06729
06730
06731 if (ignore)
06732 {
06733 tree elt;
06734
06735 for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
06736 expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
06737
06738 return const0_rtx;
06739 }
06740
06741
06742
06743
06744
06745
06746
06747
06748
06749
06750
06751
06752
06753
06754 else if ((TREE_STATIC (exp)
06755 && ((mode == BLKmode
06756 && ! (target != 0 && safe_from_p (target, exp, 1)))
06757 || TREE_ADDRESSABLE (exp)
06758 || (host_integerp (TYPE_SIZE_UNIT (type), 1)
06759 && (! MOVE_BY_PIECES_P
06760 (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
06761 TYPE_ALIGN (type)))
06762 && ! mostly_zeros_p (exp))))
06763 || ((modifier == EXPAND_INITIALIZER
06764 || modifier == EXPAND_CONST_ADDRESS)
06765 && TREE_CONSTANT (exp)))
06766 {
06767 rtx constructor = output_constant_def (exp, 1);
06768
06769 if (modifier != EXPAND_CONST_ADDRESS
06770 && modifier != EXPAND_INITIALIZER
06771 && modifier != EXPAND_SUM)
06772 constructor = validize_mem (constructor);
06773
06774 return constructor;
06775 }
06776 else
06777 {
06778
06779
06780 if (target == 0 || ! safe_from_p (target, exp, 1)
06781 || GET_CODE (target) == PARALLEL
06782 || modifier == EXPAND_STACK_PARM)
06783 target
06784 = assign_temp (build_qualified_type (type,
06785 (TYPE_QUALS (type)
06786 | (TREE_READONLY (exp)
06787 * TYPE_QUAL_CONST))),
06788 0, TREE_ADDRESSABLE (exp), 1);
06789
06790 store_constructor (exp, target, 0, int_expr_size (exp));
06791 return target;
06792 }
06793
06794 case MISALIGNED_INDIRECT_REF:
06795 case ALIGN_INDIRECT_REF:
06796 case INDIRECT_REF:
06797 {
06798 tree exp1 = TREE_OPERAND (exp, 0);
06799 tree orig;
06800
06801 if (modifier != EXPAND_WRITE)
06802 {
06803 tree t;
06804
06805 t = fold_read_from_constant_string (exp);
06806 if (t)
06807 return expand_expr (t, target, tmode, modifier);
06808 }
06809
06810 op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
06811 op0 = memory_address (mode, op0);
06812
06813 if (code == ALIGN_INDIRECT_REF)
06814 {
06815 int align = TYPE_ALIGN_UNIT (type);
06816 op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
06817 op0 = memory_address (mode, op0);
06818 }
06819
06820 temp = gen_rtx_MEM (mode, op0);
06821
06822 orig = REF_ORIGINAL (exp);
06823 if (!orig)
06824 orig = exp;
06825 set_mem_attributes (temp, orig, 0);
06826
06827
06828
06829
06830
06831
06832 if (code == MISALIGNED_INDIRECT_REF)
06833 {
06834 int icode;
06835 rtx reg, insn;
06836
06837 gcc_assert (modifier == EXPAND_NORMAL);
06838
06839
06840 icode = movmisalign_optab->handlers[mode].insn_code;
06841 gcc_assert (icode != CODE_FOR_nothing);
06842
06843
06844
06845 reg = gen_reg_rtx (mode);
06846
06847
06848 insn = GEN_FCN (icode) (reg, temp);
06849 emit_insn (insn);
06850
06851 return reg;
06852 }
06853
06854 return temp;
06855 }
06856
06857 case ARRAY_REF:
06858
06859 {
06860 tree array = TREE_OPERAND (exp, 0);
06861 tree index = TREE_OPERAND (exp, 1);
06862
06863
06864
06865
06866
06867
06868 if (modifier != EXPAND_CONST_ADDRESS
06869 && modifier != EXPAND_INITIALIZER
06870 && modifier != EXPAND_MEMORY)
06871 {
06872 tree t = fold_read_from_constant_string (exp);
06873
06874 if (t)
06875 return expand_expr (t, target, tmode, modifier);
06876 }
06877
06878
06879
06880
06881
06882
06883 if (modifier != EXPAND_CONST_ADDRESS
06884 && modifier != EXPAND_INITIALIZER
06885 && modifier != EXPAND_MEMORY
06886 && TREE_CODE (array) == CONSTRUCTOR
06887 && ! TREE_SIDE_EFFECTS (array)
06888 && TREE_CODE (index) == INTEGER_CST)
06889 {
06890 tree elem;
06891
06892 for (elem = CONSTRUCTOR_ELTS (array);
06893 (elem && !tree_int_cst_equal (TREE_PURPOSE (elem), index));
06894 elem = TREE_CHAIN (elem))
06895 ;
06896
06897 if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
06898 return expand_expr (fold (TREE_VALUE (elem)), target, tmode,
06899 modifier);
06900 }
06901
06902 else if (optimize >= 1
06903 && modifier != EXPAND_CONST_ADDRESS
06904 && modifier != EXPAND_INITIALIZER
06905 && modifier != EXPAND_MEMORY
06906 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
06907 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
06908 && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK
06909 && targetm.binds_local_p (array))
06910 {
06911 if (TREE_CODE (index) == INTEGER_CST)
06912 {
06913 tree init = DECL_INITIAL (array);
06914
06915 if (TREE_CODE (init) == CONSTRUCTOR)
06916 {
06917 tree elem;
06918
06919 for (elem = CONSTRUCTOR_ELTS (init);
06920 (elem
06921 && !tree_int_cst_equal (TREE_PURPOSE (elem), index));
06922 elem = TREE_CHAIN (elem))
06923 ;
06924
06925 if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
06926 return expand_expr (fold (TREE_VALUE (elem)), target,
06927 tmode, modifier);
06928 }
06929 else if (TREE_CODE (init) == STRING_CST
06930 && 0 > compare_tree_int (index,
06931 TREE_STRING_LENGTH (init)))
06932 {
06933 tree type = TREE_TYPE (TREE_TYPE (init));
06934 enum machine_mode mode = TYPE_MODE (type);
06935
06936 if (GET_MODE_CLASS (mode) == MODE_INT
06937 && GET_MODE_SIZE (mode) == 1)
06938 return gen_int_mode (TREE_STRING_POINTER (init)
06939 [TREE_INT_CST_LOW (index)], mode);
06940 }
06941 }
06942 }
06943 }
06944 goto normal_inner_ref;
06945
06946 case COMPONENT_REF:
06947
06948
06949 if (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR)
06950 {
06951 tree elt;
06952
06953 for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
06954 elt = TREE_CHAIN (elt))
06955 if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1)
06956
06957
06958
06959
06960
06961
06962
06963 && (! DECL_BIT_FIELD (TREE_PURPOSE (elt))
06964 || ((GET_MODE_CLASS (DECL_MODE (TREE_PURPOSE (elt)))
06965 == MODE_INT)
06966 && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
06967 <= HOST_BITS_PER_WIDE_INT))))
06968 {
06969 if (DECL_BIT_FIELD (TREE_PURPOSE (elt))
06970 && modifier == EXPAND_STACK_PARM)
06971 target = 0;
06972 op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
06973 if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
06974 {
06975 HOST_WIDE_INT bitsize
06976 = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt)));
06977 enum machine_mode imode
06978 = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt)));
06979
06980 if (TYPE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt))))
06981 {
06982 op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
06983 op0 = expand_and (imode, op0, op1, target);
06984 }
06985 else
06986 {
06987 tree count
06988 = build_int_cst (NULL_TREE,
06989 GET_MODE_BITSIZE (imode) - bitsize);
06990
06991 op0 = expand_shift (LSHIFT_EXPR, imode, op0, count,
06992 target, 0);
06993 op0 = expand_shift (RSHIFT_EXPR, imode, op0, count,
06994 target, 0);
06995 }
06996 }
06997
06998 return op0;
06999 }
07000 }
07001 goto normal_inner_ref;
07002
07003 case BIT_FIELD_REF:
07004 case ARRAY_RANGE_REF:
07005 normal_inner_ref:
07006 {
07007 enum machine_mode mode1;
07008 HOST_WIDE_INT bitsize, bitpos;
07009 tree offset;
07010 int volatilep = 0;
07011 tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
07012 &mode1, &unsignedp, &volatilep, true);
07013 rtx orig_op0;
07014
07015
07016
07017
07018 gcc_assert (tem != exp);
07019
07020
07021
07022
07023
07024 orig_op0 = op0
07025 = expand_expr (tem,
07026 (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
07027 && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
07028 != INTEGER_CST)
07029 && modifier != EXPAND_STACK_PARM
07030 ? target : NULL_RTX),
07031 VOIDmode,
07032 (modifier == EXPAND_INITIALIZER
07033 || modifier == EXPAND_CONST_ADDRESS
07034 || modifier == EXPAND_STACK_PARM)
07035 ? modifier : EXPAND_NORMAL);
07036
07037
07038
07039 if (CONSTANT_P (op0))
07040 {
07041 enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
07042 if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
07043 && offset == 0)
07044 op0 = force_reg (mode, op0);
07045 else
07046 op0 = validize_mem (force_const_mem (mode, op0));
07047 }
07048
07049
07050
07051
07052
07053
07054 else if (!MEM_P (op0)
07055 && (offset != 0
07056 || (code == ARRAY_RANGE_REF && mode == BLKmode)))
07057 {
07058 tree nt = build_qualified_type (TREE_TYPE (tem),
07059 (TYPE_QUALS (TREE_TYPE (tem))
07060 | TYPE_QUAL_CONST));
07061 rtx memloc = assign_temp (nt, 1, 1, 1);
07062
07063 emit_move_insn (memloc, op0);
07064 op0 = memloc;
07065 }
07066
07067 if (offset != 0)
07068 {
07069 rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
07070 EXPAND_SUM);
07071
07072 gcc_assert (MEM_P (op0));
07073
07074 #ifdef POINTERS_EXTEND_UNSIGNED
07075 if (GET_MODE (offset_rtx) != Pmode)
07076 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
07077 #else
07078 if (GET_MODE (offset_rtx) != ptr_mode)
07079 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
07080 #endif
07081
07082 if (GET_MODE (op0) == BLKmode
07083
07084
07085 && GET_MODE (XEXP (op0, 0)) != VOIDmode
07086 && bitsize != 0
07087 && (bitpos % bitsize) == 0
07088 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
07089 && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
07090 {
07091 op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
07092 bitpos = 0;
07093 }
07094
07095 op0 = offset_address (op0, offset_rtx,
07096 highest_pow2_factor (offset));
07097 }
07098
07099
07100
07101 if (MEM_P (op0) && bitpos == 0 && offset != 0
07102 && is_aligning_offset (offset, tem))
07103 set_mem_align (op0, BIGGEST_ALIGNMENT);
07104
07105
07106 if (MEM_P (op0) && volatilep && ! MEM_VOLATILE_P (op0))
07107 {
07108 if (op0 == orig_op0)
07109 op0 = copy_rtx (op0);
07110
07111 MEM_VOLATILE_P (op0) = 1;
07112 }
07113
07114
07115
07116
07117 if (GET_CODE (op0) == CONCAT)
07118 {
07119 gcc_assert (bitpos == 0
07120 && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)));
07121 return op0;
07122 }
07123
07124
07125
07126
07127
07128
07129
07130 if (mode1 == VOIDmode
07131 || REG_P (op0) || GET_CODE (op0) == SUBREG
07132 || (mode1 != BLKmode && ! direct_load[(int) mode1]
07133 && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
07134 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
07135 && modifier != EXPAND_CONST_ADDRESS
07136 && modifier != EXPAND_INITIALIZER)
07137
07138
07139 || (mode1 != BLKmode
07140 && (((TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode)
07141 || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)
07142 || (MEM_P (op0)
07143 && (MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode1)
07144 || (bitpos % GET_MODE_ALIGNMENT (mode1) != 0))))
07145 && ((modifier == EXPAND_CONST_ADDRESS
07146 || modifier == EXPAND_INITIALIZER)
07147 ? STRICT_ALIGNMENT
07148 : SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0))))
07149 || (bitpos % BITS_PER_UNIT != 0)))
07150
07151
07152
07153 || (bitsize >= 0
07154 && TYPE_SIZE (TREE_TYPE (exp))
07155 && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
07156 && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
07157 bitsize)))
07158 {
07159 enum machine_mode ext_mode = mode;
07160
07161 if (ext_mode == BLKmode
07162 && ! (target != 0 && MEM_P (op0)
07163 && MEM_P (target)
07164 && bitpos % BITS_PER_UNIT == 0))
07165 ext_mode = mode_for_size (bitsize, MODE_INT, 1);
07166
07167 if (ext_mode == BLKmode)
07168 {
07169 if (target == 0)
07170 target = assign_temp (type, 0, 1, 1);
07171
07172 if (bitsize == 0)
07173 return target;
07174
07175
07176
07177 gcc_assert (MEM_P (op0)
07178 && (!target || MEM_P (target))
07179 && !(bitpos % BITS_PER_UNIT));
07180
07181 emit_block_move (target,
07182 adjust_address (op0, VOIDmode,
07183 bitpos / BITS_PER_UNIT),
07184 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
07185 / BITS_PER_UNIT),
07186 (modifier == EXPAND_STACK_PARM
07187 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
07188
07189 return target;
07190 }
07191
07192 op0 = validize_mem (op0);
07193
07194 if (MEM_P (op0) && REG_P (XEXP (op0, 0)))
07195 mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
07196
07197 op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
07198 (modifier == EXPAND_STACK_PARM
07199 ? NULL_RTX : target),
07200 ext_mode, ext_mode);
07201
07202
07203
07204
07205 if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
07206 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
07207 && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
07208 op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
07209 size_int (GET_MODE_BITSIZE (GET_MODE (op0))
07210 - bitsize),
07211 op0, 1);
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221 if (mode == BLKmode)
07222 {
07223 rtx new
07224 = assign_stack_temp_for_type
07225 (ext_mode, GET_MODE_BITSIZE (ext_mode), 0, type);
07226
07227 emit_move_insn (new, op0);
07228 op0 = copy_rtx (new);
07229 PUT_MODE (op0, BLKmode);
07230 set_mem_attributes (op0, exp, 1);
07231 }
07232
07233 return op0;
07234 }
07235
07236
07237
07238 if (mode == BLKmode)
07239 mode1 = BLKmode;
07240
07241
07242 if (modifier == EXPAND_CONST_ADDRESS
07243 || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
07244 op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT);
07245 else
07246 op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
07247
07248 if (op0 == orig_op0)
07249 op0 = copy_rtx (op0);
07250
07251 set_mem_attributes (op0, exp, 0);
07252 if (REG_P (XEXP (op0, 0)))
07253 mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
07254
07255 MEM_VOLATILE_P (op0) |= volatilep;
07256 if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
07257 || modifier == EXPAND_CONST_ADDRESS
07258 || modifier == EXPAND_INITIALIZER)
07259 return op0;
07260 else if (target == 0)
07261 target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
07262
07263 convert_move (target, op0, unsignedp);
07264 return target;
07265 }
07266
07267 case OBJ_TYPE_REF:
07268 return expand_expr (OBJ_TYPE_REF_EXPR (exp), target, tmode, modifier);
07269
07270 case CALL_EXPR:
07271
07272 if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
07273 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
07274 == FUNCTION_DECL)
07275 && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
07276 {
07277 if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
07278 == BUILT_IN_FRONTEND)
07279 return lang_hooks.expand_expr (exp, original_target,
07280 tmode, modifier,
07281 alt_rtl);
07282 else
07283 return expand_builtin (exp, target, subtarget, tmode, ignore);
07284 }
07285
07286 return expand_call (exp, target, ignore);
07287
07288 case NON_LVALUE_EXPR:
07289 case NOP_EXPR:
07290 case CONVERT_EXPR:
07291 if (TREE_OPERAND (exp, 0) == error_mark_node)
07292 return const0_rtx;
07293
07294 if (TREE_CODE (type) == UNION_TYPE)
07295 {
07296 tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
07297
07298
07299
07300 if (mode == BLKmode && TYPE_MODE (valtype) == BLKmode)
07301 {
07302 rtx result = expand_expr (TREE_OPERAND (exp, 0), target, tmode,
07303 modifier);
07304
07305 result = copy_rtx (result);
07306 set_mem_attributes (result, exp, 0);
07307 return result;
07308 }
07309
07310 if (target == 0)
07311 {
07312 if (TYPE_MODE (type) != BLKmode)
07313 target = gen_reg_rtx (TYPE_MODE (type));
07314 else
07315 target = assign_temp (type, 0, 1, 1);
07316 }
07317
07318 if (MEM_P (target))
07319
07320 store_expr (TREE_OPERAND (exp, 0),
07321 adjust_address (target, TYPE_MODE (valtype), 0),
07322 modifier == EXPAND_STACK_PARM);
07323
07324 else
07325 {
07326 gcc_assert (REG_P (target));
07327
07328
07329 store_field (target,
07330 MIN ((int_size_in_bytes (TREE_TYPE
07331 (TREE_OPERAND (exp, 0)))
07332 * BITS_PER_UNIT),
07333 (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
07334 0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
07335 type, 0);
07336 }
07337
07338
07339 return target;
07340 }
07341
07342 if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
07343 {
07344 op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
07345 modifier);
07346
07347
07348
07349
07350 if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) != unsignedp
07351 && GET_CODE (op0) == SUBREG)
07352 SUBREG_PROMOTED_VAR_P (op0) = 0;
07353
07354 return REDUCE_BIT_FIELD (op0);
07355 }
07356
07357 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
07358 if (GET_MODE (op0) == mode)
07359 ;
07360
07361
07362 else if (CONSTANT_P (op0))
07363 {
07364 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
07365 enum machine_mode inner_mode = TYPE_MODE (inner_type);
07366
07367 if (modifier == EXPAND_INITIALIZER)
07368 op0 = simplify_gen_subreg (mode, op0, inner_mode,
07369 subreg_lowpart_offset (mode,
07370 inner_mode));
07371 else
07372 op0= convert_modes (mode, inner_mode, op0,
07373 TYPE_UNSIGNED (inner_type));
07374 }
07375
07376 else if (modifier == EXPAND_INITIALIZER)
07377 op0 = gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
07378
07379 else if (target == 0)
07380 op0 = convert_to_mode (mode, op0,
07381 TYPE_UNSIGNED (TREE_TYPE
07382 (TREE_OPERAND (exp, 0))));
07383 else
07384 {
07385 convert_move (target, op0,
07386 TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
07387 op0 = target;
07388 }
07389
07390 return REDUCE_BIT_FIELD (op0);
07391
07392 case VIEW_CONVERT_EXPR:
07393 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
07394
07395
07396 if (TYPE_MODE (type) == GET_MODE (op0))
07397 ;
07398
07399
07400 else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode
07401 && GET_MODE_SIZE (TYPE_MODE (type))
07402 == GET_MODE_SIZE (GET_MODE (op0)))
07403 {
07404 if (GET_CODE (op0) == SUBREG)
07405 op0 = force_reg (GET_MODE (op0), op0);
07406 op0 = gen_lowpart (TYPE_MODE (type), op0);
07407 }
07408
07409
07410 else if (SCALAR_INT_MODE_P (GET_MODE (op0))
07411 && SCALAR_INT_MODE_P (TYPE_MODE (type)))
07412 op0 = convert_modes (TYPE_MODE (type), GET_MODE (op0), op0,
07413 TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
07414
07415
07416 else if (!MEM_P (op0))
07417 {
07418
07419
07420
07421
07422 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
07423
07424 gcc_assert (!TREE_ADDRESSABLE (exp));
07425
07426 if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
07427 target
07428 = assign_stack_temp_for_type
07429 (TYPE_MODE (inner_type),
07430 GET_MODE_SIZE (TYPE_MODE (inner_type)), 0, inner_type);
07431
07432 emit_move_insn (target, op0);
07433 op0 = target;
07434 }
07435
07436
07437
07438
07439
07440 if (MEM_P (op0))
07441 {
07442 op0 = copy_rtx (op0);
07443
07444 if (TYPE_ALIGN_OK (type))
07445 set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
07446 else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT
07447 && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
07448 {
07449 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
07450 HOST_WIDE_INT temp_size
07451 = MAX (int_size_in_bytes (inner_type),
07452 (HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type)));
07453 rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
07454 temp_size, 0, type);
07455 rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
07456
07457 gcc_assert (!TREE_ADDRESSABLE (exp));
07458
07459 if (GET_MODE (op0) == BLKmode)
07460 emit_block_move (new_with_op0_mode, op0,
07461 GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))),
07462 (modifier == EXPAND_STACK_PARM
07463 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
07464 else
07465 emit_move_insn (new_with_op0_mode, op0);
07466
07467 op0 = new;
07468 }
07469
07470 op0 = adjust_address (op0, TYPE_MODE (type), 0);
07471 }
07472
07473 return op0;
07474
07475 case PLUS_EXPR:
07476
07477
07478
07479
07480
07481
07482
07483
07484
07485
07486
07487 if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
07488 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
07489 && TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL
07490 && (DECL_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
07491 || DECL_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
07492 || DECL_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
07493 {
07494 tree t = TREE_OPERAND (exp, 1);
07495
07496 TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07497 TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t;
07498 }
07499
07500
07501
07502
07503
07504
07505
07506
07507
07508 if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
07509 || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
07510 {
07511 if (modifier == EXPAND_STACK_PARM)
07512 target = 0;
07513 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
07514 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
07515 && TREE_CONSTANT (TREE_OPERAND (exp, 1)))
07516 {
07517 rtx constant_part;
07518
07519 op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode,
07520 EXPAND_SUM);
07521
07522
07523
07524
07525 constant_part
07526 = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)),
07527 (HOST_WIDE_INT) 0,
07528 TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))));
07529 op1 = plus_constant (op1, INTVAL (constant_part));
07530 if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
07531 op1 = force_operand (op1, target);
07532 return REDUCE_BIT_FIELD (op1);
07533 }
07534
07535 else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
07536 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT
07537 && TREE_CONSTANT (TREE_OPERAND (exp, 0)))
07538 {
07539 rtx constant_part;
07540
07541 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
07542 (modifier == EXPAND_INITIALIZER
07543 ? EXPAND_INITIALIZER : EXPAND_SUM));
07544 if (! CONSTANT_P (op0))
07545 {
07546 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
07547 VOIDmode, modifier);
07548
07549 if (modifier == EXPAND_SUM
07550 || modifier == EXPAND_INITIALIZER)
07551 return simplify_gen_binary (PLUS, mode, op0, op1);
07552 goto binop2;
07553 }
07554
07555
07556
07557
07558 constant_part
07559 = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)),
07560 (HOST_WIDE_INT) 0,
07561 TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))));
07562 op0 = plus_constant (op0, INTVAL (constant_part));
07563 if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
07564 op0 = force_operand (op0, target);
07565 return REDUCE_BIT_FIELD (op0);
07566 }
07567 }
07568
07569
07570
07571
07572
07573 if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
07574 || mode != ptr_mode)
07575 {
07576 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07577 subtarget, &op0, &op1, 0);
07578 if (op0 == const0_rtx)
07579 return op1;
07580 if (op1 == const0_rtx)
07581 return op0;
07582 goto binop2;
07583 }
07584
07585 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07586 subtarget, &op0, &op1, modifier);
07587 return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
07588
07589 case MINUS_EXPR:
07590
07591
07592
07593
07594
07595 if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
07596 && really_constant_p (TREE_OPERAND (exp, 0))
07597 && really_constant_p (TREE_OPERAND (exp, 1)))
07598 {
07599 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07600 NULL_RTX, &op0, &op1, modifier);
07601
07602
07603
07604 if (GET_CODE (op1) == CONST_INT)
07605 return REDUCE_BIT_FIELD (plus_constant (op0, - INTVAL (op1)));
07606 else
07607 return REDUCE_BIT_FIELD (gen_rtx_MINUS (mode, op0, op1));
07608 }
07609
07610
07611
07612
07613
07614 if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
07615 || mode != ptr_mode)
07616 goto binop;
07617
07618 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07619 subtarget, &op0, &op1, modifier);
07620
07621
07622 if (GET_CODE (op1) == CONST_INT)
07623 {
07624 op1 = negate_rtx (mode, op1);
07625 return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
07626 }
07627
07628 goto binop2;
07629
07630 case MULT_EXPR:
07631
07632
07633
07634 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
07635 {
07636 tree t1 = TREE_OPERAND (exp, 0);
07637 TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
07638 TREE_OPERAND (exp, 1) = t1;
07639 }
07640
07641
07642
07643
07644 if (modifier == EXPAND_SUM && mode == ptr_mode
07645 && host_integerp (TREE_OPERAND (exp, 1), 0))
07646 {
07647 tree exp1 = TREE_OPERAND (exp, 1);
07648
07649 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
07650 EXPAND_SUM);
07651
07652 if (!REG_P (op0))
07653 op0 = force_operand (op0, NULL_RTX);
07654 if (!REG_P (op0))
07655 op0 = copy_to_mode_reg (mode, op0);
07656
07657 return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
07658 gen_int_mode (tree_low_cst (exp1, 0),
07659 TYPE_MODE (TREE_TYPE (exp1)))));
07660 }
07661
07662 if (modifier == EXPAND_STACK_PARM)
07663 target = 0;
07664
07665
07666
07667
07668
07669 if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
07670 && TREE_CODE (type) == INTEGER_TYPE
07671 && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
07672 < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
07673 && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
07674 && int_fits_type_p (TREE_OPERAND (exp, 1),
07675 TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
07676
07677 && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))))
07678 > HOST_BITS_PER_WIDE_INT)
07679 || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
07680 ||
07681 (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
07682 && (TYPE_PRECISION (TREE_TYPE
07683 (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
07684 == TYPE_PRECISION (TREE_TYPE
07685 (TREE_OPERAND
07686 (TREE_OPERAND (exp, 0), 0))))
07687
07688
07689 && (TYPE_UNSIGNED (TREE_TYPE
07690 (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
07691 == TYPE_UNSIGNED (TREE_TYPE
07692 (TREE_OPERAND
07693 (TREE_OPERAND (exp, 0), 0)))))))
07694 {
07695 tree op0type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
07696 enum machine_mode innermode = TYPE_MODE (op0type);
07697 bool zextend_p = TYPE_UNSIGNED (op0type);
07698 optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
07699 this_optab = zextend_p ? umul_widen_optab : smul_widen_optab;
07700
07701 if (mode == GET_MODE_WIDER_MODE (innermode))
07702 {
07703 if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
07704 {
07705 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
07706 expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
07707 TREE_OPERAND (exp, 1),
07708 NULL_RTX, &op0, &op1, 0);
07709 else
07710 expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
07711 TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
07712 NULL_RTX, &op0, &op1, 0);
07713 goto binop3;
07714 }
07715 else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
07716 && innermode == word_mode)
07717 {
07718 rtx htem, hipart;
07719 op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
07720 NULL_RTX, VOIDmode, 0);
07721 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
07722 op1 = convert_modes (innermode, mode,
07723 expand_expr (TREE_OPERAND (exp, 1),
07724 NULL_RTX, VOIDmode, 0),
07725 unsignedp);
07726 else
07727 op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
07728 NULL_RTX, VOIDmode, 0);
07729 temp = expand_binop (mode, other_optab, op0, op1, target,
07730 unsignedp, OPTAB_LIB_WIDEN);
07731 hipart = gen_highpart (innermode, temp);
07732 htem = expand_mult_highpart_adjust (innermode, hipart,
07733 op0, op1, hipart,
07734 zextend_p);
07735 if (htem != hipart)
07736 emit_move_insn (hipart, htem);
07737 return REDUCE_BIT_FIELD (temp);
07738 }
07739 }
07740 }
07741 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07742 subtarget, &op0, &op1, 0);
07743 return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
07744
07745 case TRUNC_DIV_EXPR:
07746 case FLOOR_DIV_EXPR:
07747 case CEIL_DIV_EXPR:
07748 case ROUND_DIV_EXPR:
07749 case EXACT_DIV_EXPR:
07750 if (modifier == EXPAND_STACK_PARM)
07751 target = 0;
07752
07753
07754
07755 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07756 subtarget, &op0, &op1, 0);
07757 return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
07758
07759 case RDIV_EXPR:
07760
07761
07762
07763 if (flag_unsafe_math_optimizations && optimize && !optimize_size
07764 && TREE_CODE (type) == REAL_TYPE
07765 && !real_onep (TREE_OPERAND (exp, 0)))
07766 return expand_expr (build2 (MULT_EXPR, type, TREE_OPERAND (exp, 0),
07767 build2 (RDIV_EXPR, type,
07768 build_real (type, dconst1),
07769 TREE_OPERAND (exp, 1))),
07770 target, tmode, modifier);
07771
07772 goto binop;
07773
07774 case TRUNC_MOD_EXPR:
07775 case FLOOR_MOD_EXPR:
07776 case CEIL_MOD_EXPR:
07777 case ROUND_MOD_EXPR:
07778 if (modifier == EXPAND_STACK_PARM)
07779 target = 0;
07780 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07781 subtarget, &op0, &op1, 0);
07782 return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
07783
07784 case FIX_ROUND_EXPR:
07785 case FIX_FLOOR_EXPR:
07786 case FIX_CEIL_EXPR:
07787 gcc_unreachable ();
07788
07789 case FIX_TRUNC_EXPR:
07790 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
07791 if (target == 0 || modifier == EXPAND_STACK_PARM)
07792 target = gen_reg_rtx (mode);
07793 expand_fix (target, op0, unsignedp);
07794 return target;
07795
07796 case FLOAT_EXPR:
07797 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
07798 if (target == 0 || modifier == EXPAND_STACK_PARM)
07799 target = gen_reg_rtx (mode);
07800
07801
07802 if (GET_MODE (op0) == VOIDmode)
07803 op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
07804 op0);
07805 expand_float (target, op0,
07806 TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
07807 return target;
07808
07809 case NEGATE_EXPR:
07810 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
07811 if (modifier == EXPAND_STACK_PARM)
07812 target = 0;
07813 temp = expand_unop (mode,
07814 optab_for_tree_code (NEGATE_EXPR, type),
07815 op0, target, 0);
07816 gcc_assert (temp);
07817 return REDUCE_BIT_FIELD (temp);
07818
07819 case ABS_EXPR:
07820 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
07821 if (modifier == EXPAND_STACK_PARM)
07822 target = 0;
07823
07824
07825 gcc_assert (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
07826 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT);
07827
07828
07829
07830 if (TYPE_UNSIGNED (type))
07831 return op0;
07832
07833 return expand_abs (mode, op0, target, unsignedp,
07834 safe_from_p (target, TREE_OPERAND (exp, 0), 1));
07835
07836 case MAX_EXPR:
07837 case MIN_EXPR:
07838 target = original_target;
07839 if (target == 0
07840 || modifier == EXPAND_STACK_PARM
07841 || (MEM_P (target) && MEM_VOLATILE_P (target))
07842 || GET_MODE (target) != mode
07843 || (REG_P (target)
07844 && REGNO (target) < FIRST_PSEUDO_REGISTER))
07845 target = gen_reg_rtx (mode);
07846 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
07847 target, &op0, &op1, 0);
07848
07849
07850
07851
07852 this_optab = optab_for_tree_code (code, type);
07853 temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
07854 OPTAB_WIDEN);
07855 if (temp != 0)
07856 return temp;
07857
07858
07859
07860
07861 if (! REG_P (target))
07862 target = gen_reg_rtx (mode);
07863
07864
07865 if (target != op0 && target == op1)
07866 {
07867 rtx tem = op0;
07868 op0 = op1;
07869 op1 = tem;
07870 }
07871
07872
07873
07874 if (! CONSTANT_P (op1))
07875 op1 = force_reg (mode, op1);
07876
07877 if (target != op0)
07878 emit_move_insn (target, op0);
07879
07880 op0 = gen_label_rtx ();
07881
07882
07883
07884 if (GET_MODE_CLASS (mode) == MODE_INT
07885 && ! can_compare_p (GE, mode, ccp_jump))
07886 {
07887 if (code == MAX_EXPR)
07888 do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1,
07889 NULL_RTX, op0);
07890 else
07891 do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target,
07892 NULL_RTX, op0);
07893 }
07894 else
07895 {
07896 do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE,
07897 unsignedp, mode, NULL_RTX, NULL_RTX, op0);
07898 }
07899 emit_move_insn (target, op1);
07900 emit_label (op0);
07901 return target;
07902
07903 case BIT_NOT_EXPR:
07904 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
07905 if (modifier == EXPAND_STACK_PARM)
07906 target = 0;
07907 temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
07908 gcc_assert (temp);
07909 return temp;
07910
07911
07912
07913
07914
07915
07916
07917
07918
07919
07920
07921
07922
07923
07924 case TRUTH_AND_EXPR:
07925 code = BIT_AND_EXPR;
07926 case BIT_AND_EXPR:
07927 goto binop;
07928
07929 case TRUTH_OR_EXPR:
07930 code = BIT_IOR_EXPR;
07931 case BIT_IOR_EXPR:
07932 goto binop;
07933
07934 case TRUTH_XOR_EXPR:
07935 code = BIT_XOR_EXPR;
07936 case BIT_XOR_EXPR:
07937 goto binop;
07938
07939 case LSHIFT_EXPR:
07940 case RSHIFT_EXPR:
07941 case LROTATE_EXPR:
07942 case RROTATE_EXPR:
07943 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
07944 subtarget = 0;
07945 if (modifier == EXPAND_STACK_PARM)
07946 target = 0;
07947 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
07948 return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
07949 unsignedp);
07950
07951
07952
07953 case LT_EXPR:
07954 case LE_EXPR:
07955 case GT_EXPR:
07956 case GE_EXPR:
07957 case EQ_EXPR:
07958 case NE_EXPR:
07959 case UNORDERED_EXPR:
07960 case ORDERED_EXPR:
07961 case UNLT_EXPR:
07962 case UNLE_EXPR:
07963 case UNGT_EXPR:
07964 case UNGE_EXPR:
07965 case UNEQ_EXPR:
07966 case LTGT_EXPR:
07967 temp = do_store_flag (exp,
07968 modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
07969 tmode != VOIDmode ? tmode : mode, 0);
07970 if (temp != 0)
07971 return temp;
07972
07973
07974 if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
07975 && original_target
07976 && REG_P (original_target)
07977 && (GET_MODE (original_target)
07978 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
07979 {
07980 temp = expand_expr (TREE_OPERAND (exp, 0), original_target,
07981 VOIDmode, 0);
07982
07983
07984 if (GET_CODE (temp) == CONST_INT)
07985 {
07986 if (INTVAL (temp) != 0)
07987 emit_move_insn (target, const1_rtx);
07988 else
07989 emit_move_insn (target, const0_rtx);
07990
07991 return target;
07992 }
07993
07994 if (temp != original_target)
07995 {
07996 enum machine_mode mode1 = GET_MODE (temp);
07997 if (mode1 == VOIDmode)
07998 mode1 = tmode != VOIDmode ? tmode : mode;
07999
08000 temp = copy_to_mode_reg (mode1, temp);
08001 }
08002
08003 op1 = gen_label_rtx ();
08004 emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
08005 GET_MODE (temp), unsignedp, op1);
08006 emit_move_insn (temp, const1_rtx);
08007 emit_label (op1);
08008 return temp;
08009 }
08010
08011
08012
08013
08014
08015 if (! ignore
08016 && (target == 0
08017 || modifier == EXPAND_STACK_PARM
08018 || ! safe_from_p (target, exp, 1)
08019
08020
08021 || (!optimize && REG_P (target)
08022 && REGNO (target) < FIRST_PSEUDO_REGISTER)))
08023 target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
08024
08025 if (target)
08026 emit_move_insn (target, const0_rtx);
08027
08028 op1 = gen_label_rtx ();
08029 jumpifnot (exp, op1);
08030
08031 if (target)
08032 emit_move_insn (target, const1_rtx);
08033
08034 emit_label (op1);
08035 return ignore ? const0_rtx : target;
08036
08037 case TRUTH_NOT_EXPR:
08038 if (modifier == EXPAND_STACK_PARM)
08039 target = 0;
08040 op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
08041
08042
08043 temp = expand_binop (mode, xor_optab, op0, const1_rtx,
08044 target, 1, OPTAB_LIB_WIDEN);
08045 gcc_assert (temp);
08046 return temp;
08047
08048 case STATEMENT_LIST:
08049 {
08050 tree_stmt_iterator iter;
08051
08052 gcc_assert (ignore);
08053
08054 for (iter = tsi_start (exp); !tsi_end_p (iter); tsi_next (&iter))
08055 expand_expr (tsi_stmt (iter), const0_rtx, VOIDmode, modifier);
08056 }
08057 return const0_rtx;
08058
08059 case COND_EXPR:
08060
08061
08062
08063 gcc_assert (!VOID_TYPE_P (TREE_TYPE (exp)));
08064
08065
08066
08067
08068
08069
08070 gcc_assert (!TREE_ADDRESSABLE (type)
08071 && !ignore
08072 && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node
08073 && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node);
08074
08075
08076
08077
08078
08079
08080 if (modifier != EXPAND_STACK_PARM
08081 && original_target
08082 && safe_from_p (original_target, TREE_OPERAND (exp, 0), 1)
08083 && GET_MODE (original_target) == mode
08084 #ifdef HAVE_conditional_move
08085 && (! can_conditionally_move_p (mode)
08086 || REG_P (original_target))
08087 #endif
08088 && !MEM_P (original_target))
08089 temp = original_target;
08090 else
08091 temp = assign_temp (type, 0, 0, 1);
08092
08093 do_pending_stack_adjust ();
08094 NO_DEFER_POP;
08095 op0 = gen_label_rtx ();
08096 op1 = gen_label_rtx ();
08097 jumpifnot (TREE_OPERAND (exp, 0), op0);
08098 store_expr (TREE_OPERAND (exp, 1), temp,
08099 modifier == EXPAND_STACK_PARM);
08100
08101 emit_jump_insn (gen_jump (op1));
08102 emit_barrier ();
08103 emit_label (op0);
08104 store_expr (TREE_OPERAND (exp, 2), temp,
08105 modifier == EXPAND_STACK_PARM);
08106
08107 emit_label (op1);
08108 OK_DEFER_POP;
08109 return temp;
08110
08111 case VEC_COND_EXPR:
08112 target = expand_vec_cond_expr (exp, target);
08113 return target;
08114
08115 case MODIFY_EXPR:
08116 {
08117 tree lhs = TREE_OPERAND (exp, 0);
08118 tree rhs = TREE_OPERAND (exp, 1);
08119
08120 gcc_assert (ignore);
08121
08122
08123
08124
08125
08126
08127
08128
08129
08130 if (TREE_CODE (lhs) == COMPONENT_REF
08131 && (TREE_CODE (rhs) == BIT_IOR_EXPR
08132 || TREE_CODE (rhs) == BIT_AND_EXPR)
08133 && TREE_OPERAND (rhs, 0) == lhs
08134 && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
08135 && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
08136 && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
08137 {
08138 rtx label = gen_label_rtx ();
08139
08140 do_jump (TREE_OPERAND (rhs, 1),
08141 TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
08142 TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
08143 expand_assignment (lhs, convert (TREE_TYPE (rhs),
08144 (TREE_CODE (rhs) == BIT_IOR_EXPR
08145 ? integer_one_node
08146 : integer_zero_node)));
08147 do_pending_stack_adjust ();
08148 emit_label (label);
08149 return const0_rtx;
08150 }
08151
08152 expand_assignment (lhs, rhs);
08153
08154 return const0_rtx;
08155 }
08156
08157 case RETURN_EXPR:
08158 if (!TREE_OPERAND (exp, 0))
08159 expand_null_return ();
08160 else
08161 expand_return (TREE_OPERAND (exp, 0));
08162 return const0_rtx;
08163
08164 case ADDR_EXPR:
08165 return expand_expr_addr_expr (exp, target, tmode, modifier);
08166
08167 case COMPLEX_EXPR:
08168
08169 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
08170 op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
08171
08172 if (!target)
08173 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
08174
08175
08176 write_complex_part (target, op0, false);
08177 write_complex_part (target, op1, true);
08178
08179 return target;
08180
08181 case REALPART_EXPR:
08182 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
08183 return read_complex_part (op0, false);
08184
08185 case IMAGPART_EXPR:
08186 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
08187 return read_complex_part (op0, true);
08188
08189 case RESX_EXPR:
08190 expand_resx_expr (exp);
08191 return const0_rtx;
08192
08193 case TRY_CATCH_EXPR:
08194 case CATCH_EXPR:
08195 case EH_FILTER_EXPR:
08196 case TRY_FINALLY_EXPR:
08197
08198 gcc_unreachable ();
08199
08200 case WITH_CLEANUP_EXPR:
08201 case CLEANUP_POINT_EXPR:
08202 case TARGET_EXPR:
08203 case CASE_LABEL_EXPR:
08204 case VA_ARG_EXPR:
08205 case BIND_EXPR:
08206 case INIT_EXPR:
08207 case CONJ_EXPR:
08208 case COMPOUND_EXPR:
08209 case PREINCREMENT_EXPR:
08210 case PREDECREMENT_EXPR:
08211 case POSTINCREMENT_EXPR:
08212 case POSTDECREMENT_EXPR:
08213 case LOOP_EXPR:
08214 case EXIT_EXPR:
08215 case TRUTH_ANDIF_EXPR:
08216 case TRUTH_ORIF_EXPR:
08217
08218 gcc_unreachable ();
08219
08220 case EXC_PTR_EXPR:
08221 return get_exception_pointer (cfun);
08222
08223 case FILTER_EXPR:
08224 return get_exception_filter (cfun);
08225
08226 case FDESC_EXPR:
08227
08228
08229 gcc_unreachable ();
08230
08231 case SWITCH_EXPR:
08232 expand_case (exp);
08233 return const0_rtx;
08234
08235 case LABEL_EXPR:
08236 expand_label (TREE_OPERAND (exp, 0));
08237 return const0_rtx;
08238
08239 case ASM_EXPR:
08240 expand_asm_expr (exp);
08241 return const0_rtx;
08242
08243 case WITH_SIZE_EXPR:
08244
08245
08246 return expand_expr_real (TREE_OPERAND (exp, 0), original_target, tmode,
08247 modifier, alt_rtl);
08248
08249 case REALIGN_LOAD_EXPR:
08250 {
08251 tree oprnd0 = TREE_OPERAND (exp, 0);
08252 tree oprnd1 = TREE_OPERAND (exp, 1);
08253 tree oprnd2 = TREE_OPERAND (exp, 2);
08254 rtx op2;
08255
08256 this_optab = optab_for_tree_code (code, type);
08257 expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, 0);
08258 op2 = expand_expr (oprnd2, NULL_RTX, VOIDmode, 0);
08259 temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
08260 target, unsignedp);
08261 if (temp == 0)
08262 abort ();
08263 return temp;
08264 }
08265
08266
08267 default:
08268 return lang_hooks.expand_expr (exp, original_target, tmode,
08269 modifier, alt_rtl);
08270 }
08271
08272
08273 binop:
08274 expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
08275 subtarget, &op0, &op1, 0);
08276 binop2:
08277 this_optab = optab_for_tree_code (code, type);
08278 binop3:
08279 if (modifier == EXPAND_STACK_PARM)
08280 target = 0;
08281 temp = expand_binop (mode, this_optab, op0, op1, target,
08282 unsignedp, OPTAB_LIB_WIDEN);
08283 gcc_assert (temp);
08284 return REDUCE_BIT_FIELD (temp);
08285 }
08286 #undef REDUCE_BIT_FIELD
08287
08288
08289
08290 static rtx
08291 reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
08292 {
08293 HOST_WIDE_INT prec = TYPE_PRECISION (type);
08294 if (target && GET_MODE (target) != GET_MODE (exp))
08295 target = 0;
08296 if (TYPE_UNSIGNED (type))
08297 {
08298 rtx mask;
08299 if (prec < HOST_BITS_PER_WIDE_INT)
08300 mask = immed_double_const (((unsigned HOST_WIDE_INT) 1 << prec) - 1, 0,
08301 GET_MODE (exp));
08302 else
08303 mask = immed_double_const ((unsigned HOST_WIDE_INT) -1,
08304 ((unsigned HOST_WIDE_INT) 1
08305 << (prec - HOST_BITS_PER_WIDE_INT)) - 1,
08306 GET_MODE (exp));
08307 return expand_and (GET_MODE (exp), exp, mask, target);
08308 }
08309 else
08310 {
08311 tree count = build_int_cst (NULL_TREE,
08312 GET_MODE_BITSIZE (GET_MODE (exp)) - prec);
08313 exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
08314 return expand_shift (RSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
08315 }
08316 }
08317
08318
08319
08320
08321
08322 static int
08323 is_aligning_offset (tree offset, tree exp)
08324 {
08325
08326 while (TREE_CODE (offset) == NON_LVALUE_EXPR
08327 || TREE_CODE (offset) == NOP_EXPR
08328 || TREE_CODE (offset) == CONVERT_EXPR)
08329 offset = TREE_OPERAND (offset, 0);
08330
08331
08332
08333 if (TREE_CODE (offset) != BIT_AND_EXPR
08334 || !host_integerp (TREE_OPERAND (offset, 1), 1)
08335 || compare_tree_int (TREE_OPERAND (offset, 1),
08336 BIGGEST_ALIGNMENT / BITS_PER_UNIT) <= 0
08337 || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
08338 return 0;
08339
08340
08341
08342 offset = TREE_OPERAND (offset, 0);
08343 while (TREE_CODE (offset) == NON_LVALUE_EXPR
08344 || TREE_CODE (offset) == NOP_EXPR
08345 || TREE_CODE (offset) == CONVERT_EXPR)
08346 offset = TREE_OPERAND (offset, 0);
08347
08348 if (TREE_CODE (offset) != NEGATE_EXPR)
08349 return 0;
08350
08351 offset = TREE_OPERAND (offset, 0);
08352 while (TREE_CODE (offset) == NON_LVALUE_EXPR
08353 || TREE_CODE (offset) == NOP_EXPR
08354 || TREE_CODE (offset) == CONVERT_EXPR)
08355 offset = TREE_OPERAND (offset, 0);
08356
08357
08358 return TREE_CODE (offset) == ADDR_EXPR && TREE_OPERAND (offset, 0) == exp;
08359 }
08360
08361
08362
08363
08364
08365
08366 tree
08367 string_constant (tree arg, tree *ptr_offset)
08368 {
08369 tree array, offset;
08370 STRIP_NOPS (arg);
08371
08372 if (TREE_CODE (arg) == ADDR_EXPR)
08373 {
08374 if (TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
08375 {
08376 *ptr_offset = size_zero_node;
08377 return TREE_OPERAND (arg, 0);
08378 }
08379 else if (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL)
08380 {
08381 array = TREE_OPERAND (arg, 0);
08382 offset = size_zero_node;
08383 }
08384 else if (TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
08385 {
08386 array = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
08387 offset = TREE_OPERAND (TREE_OPERAND (arg, 0), 1);
08388 if (TREE_CODE (array) != STRING_CST
08389 && TREE_CODE (array) != VAR_DECL)
08390 return 0;
08391 }
08392 else
08393 return 0;
08394 }
08395 else if (TREE_CODE (arg) == PLUS_EXPR)
08396 {
08397 tree arg0 = TREE_OPERAND (arg, 0);
08398 tree arg1 = TREE_OPERAND (arg, 1);
08399
08400 STRIP_NOPS (arg0);
08401 STRIP_NOPS (arg1);
08402
08403 if (TREE_CODE (arg0) == ADDR_EXPR
08404 && (TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST
08405 || TREE_CODE (TREE_OPERAND (arg0, 0)) == VAR_DECL))
08406 {
08407 array = TREE_OPERAND (arg0, 0);
08408 offset = arg1;
08409 }
08410 else if (TREE_CODE (arg1) == ADDR_EXPR
08411 && (TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST
08412 || TREE_CODE (TREE_OPERAND (arg1, 0)) == VAR_DECL))
08413 {
08414 array = TREE_OPERAND (arg1, 0);
08415 offset = arg0;
08416 }
08417 else
08418 return 0;
08419 }
08420 else
08421 return 0;
08422
08423 if (TREE_CODE (array) == STRING_CST)
08424 {
08425 *ptr_offset = convert (sizetype, offset);
08426 return array;
08427 }
08428 else if (TREE_CODE (array) == VAR_DECL)
08429 {
08430 int length;
08431
08432
08433 if (DECL_INITIAL (array) == NULL_TREE
08434 || TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
08435 return 0;
08436
08437
08438 if (! TREE_READONLY (array)
08439 || TREE_SIDE_EFFECTS (array)
08440 || ! targetm.binds_local_p (array))
08441 return 0;
08442
08443
08444 if (DECL_SIZE_UNIT (array) == NULL_TREE
08445 || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
08446 || (length = TREE_STRING_LENGTH (DECL_INITIAL (array))) <= 0
08447 || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
08448 return 0;
08449
08450
08451
08452 offset = convert (sizetype, offset);
08453 if (compare_tree_int (DECL_SIZE_UNIT (array), length) > 0
08454 && (! host_integerp (offset, 1)
08455 || compare_tree_int (offset, length) >= 0))
08456 return 0;
08457
08458 *ptr_offset = offset;
08459 return DECL_INITIAL (array);
08460 }
08461
08462 return 0;
08463 }
08464
08465
08466
08467
08468
08469
08470
08471
08472
08473
08474
08475
08476
08477
08478
08479
08480
08481
08482
08483
08484
08485 static rtx
08486 do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
08487 {
08488 enum rtx_code code;
08489 tree arg0, arg1, type;
08490 tree tem;
08491 enum machine_mode operand_mode;
08492 int invert = 0;
08493 int unsignedp;
08494 rtx op0, op1;
08495 enum insn_code icode;
08496 rtx subtarget = target;
08497 rtx result, label;
08498
08499
08500
08501
08502
08503
08504 if (TREE_CODE (exp) == TRUTH_NOT_EXPR)
08505 invert = 1, exp = TREE_OPERAND (exp, 0);
08506
08507 arg0 = TREE_OPERAND (exp, 0);
08508 arg1 = TREE_OPERAND (exp, 1);
08509
08510
08511 if (arg0 == error_mark_node || arg1 == error_mark_node)
08512 return const0_rtx;
08513
08514 type = TREE_TYPE (arg0);
08515 operand_mode = TYPE_MODE (type);
08516 unsignedp = TYPE_UNSIGNED (type);
08517
08518
08519
08520 if (operand_mode == BLKmode)
08521 return 0;
08522
08523
08524
08525 #ifdef HAVE_canonicalize_funcptr_for_compare
08526 if (HAVE_canonicalize_funcptr_for_compare
08527 && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
08528 && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
08529 == FUNCTION_TYPE))
08530 || (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
08531 && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
08532 == FUNCTION_TYPE))))
08533 return 0;
08534 #endif
08535
08536 STRIP_NOPS (arg0);
08537 STRIP_NOPS (arg1);
08538
08539
08540
08541
08542
08543
08544
08545
08546 switch (TREE_CODE (exp))
08547 {
08548 case EQ_EXPR:
08549 code = EQ;
08550 break;
08551 case NE_EXPR:
08552 code = NE;
08553 break;
08554 case LT_EXPR:
08555 if (integer_onep (arg1))
08556 arg1 = integer_zero_node, code = unsignedp ? LEU : LE;
08557 else
08558 code = unsignedp ? LTU : LT;
08559 break;
08560 case LE_EXPR:
08561 if (! unsignedp && integer_all_onesp (arg1))
08562 arg1 = integer_zero_node, code = LT;
08563 else
08564 code = unsignedp ? LEU : LE;
08565 break;
08566 case GT_EXPR:
08567 if (! unsignedp && integer_all_onesp (arg1))
08568 arg1 = integer_zero_node, code = GE;
08569 else
08570 code = unsignedp ? GTU : GT;
08571 break;
08572 case GE_EXPR:
08573 if (integer_onep (arg1))
08574 arg1 = integer_zero_node, code = unsignedp ? GTU : GT;
08575 else
08576 code = unsignedp ? GEU : GE;
08577 break;
08578
08579 case UNORDERED_EXPR:
08580 code = UNORDERED;
08581 break;
08582 case ORDERED_EXPR:
08583 code = ORDERED;
08584 break;
08585 case UNLT_EXPR:
08586 code = UNLT;
08587 break;
08588 case UNLE_EXPR:
08589 code = UNLE;
08590 break;
08591 case UNGT_EXPR:
08592 code = UNGT;
08593 break;
08594 case UNGE_EXPR:
08595 code = UNGE;
08596 break;
08597 case UNEQ_EXPR:
08598 code = UNEQ;
08599 break;
08600 case LTGT_EXPR:
08601 code = LTGT;
08602 break;
08603
08604 default:
08605 gcc_unreachable ();
08606 }
08607
08608
08609 if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST)
08610 {
08611 tem = arg0; arg0 = arg1; arg1 = tem;
08612 code = swap_condition (code);
08613 }
08614
08615
08616
08617
08618
08619
08620
08621
08622
08623
08624 if ((code == NE || code == EQ)
08625 && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
08626 && integer_pow2p (TREE_OPERAND (arg0, 1)))
08627 {
08628 tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
08629 return expand_expr (fold_single_bit_test (code == NE ? NE_EXPR : EQ_EXPR,
08630 arg0, arg1, type),
08631 target, VOIDmode, EXPAND_NORMAL);
08632 }
08633
08634
08635 if (! can_compare_p (code, operand_mode, ccp_store_flag))
08636 return 0;
08637
08638 icode = setcc_gen_code[(int) code];
08639 if (icode == CODE_FOR_nothing
08640 || (only_cheap && insn_data[(int) icode].operand[0].mode != mode))
08641 {
08642
08643
08644 if ((code == LT && integer_zerop (arg1))
08645 || (! only_cheap && code == GE && integer_zerop (arg1)))
08646 ;
08647 else if (BRANCH_COST >= 0
08648 && ! only_cheap && (code == NE || code == EQ)
08649 && TREE_CODE (type) != REAL_TYPE
08650 && ((abs_optab->handlers[(int) operand_mode].insn_code
08651 != CODE_FOR_nothing)
08652 || (ffs_optab->handlers[(int) operand_mode].insn_code
08653 != CODE_FOR_nothing)))
08654 ;
08655 else
08656 return 0;
08657 }
08658
08659 if (! get_subtarget (target)
08660 || GET_MODE (subtarget) != operand_mode)
08661 subtarget = 0;
08662
08663 expand_operands (arg0, arg1, subtarget, &op0, &op1, 0);
08664
08665 if (target == 0)
08666 target = gen_reg_rtx (mode);
08667
08668 result = emit_store_flag (target, code, op0, op1,
08669 operand_mode, unsignedp, 1);
08670
08671 if (result)
08672 {
08673 if (invert)
08674 result = expand_binop (mode, xor_optab, result, const1_rtx,
08675 result, 0, OPTAB_LIB_WIDEN);
08676 return result;
08677 }
08678
08679
08680 if (!REG_P (target)
08681 || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
08682 target = gen_reg_rtx (GET_MODE (target));
08683
08684 emit_move_insn (target, invert ? const0_rtx : const1_rtx);
08685 result = compare_from_rtx (op0, op1, code, unsignedp,
08686 operand_mode, NULL_RTX);
08687 if (GET_CODE (result) == CONST_INT)
08688 return (((result == const0_rtx && ! invert)
08689 || (result != const0_rtx && invert))
08690 ? const0_rtx : const1_rtx);
08691
08692
08693
08694
08695
08696
08697
08698 code = GET_CODE (result);
08699
08700 label = gen_label_rtx ();
08701 gcc_assert (bcc_gen_fctn[(int) code]);
08702
08703 emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
08704 emit_move_insn (target, invert ? const1_rtx : const0_rtx);
08705 emit_label (label);
08706
08707 return target;
08708 }
08709
08710
08711
08712 #ifndef HAVE_casesi
08713 # define HAVE_casesi 0
08714 # define gen_casesi(a, b, c, d, e) (0)
08715 # define CODE_FOR_casesi CODE_FOR_nothing
08716 #endif
08717
08718
08719
08720
08721 #ifndef CASE_VALUES_THRESHOLD
08722 #define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
08723 #endif
08724
08725 unsigned int
08726 case_values_threshold (void)
08727 {
08728 return CASE_VALUES_THRESHOLD;
08729 }
08730
08731
08732
08733 int
08734 try_casesi (tree index_type, tree index_expr, tree minval, tree range,
08735 rtx table_label ATTRIBUTE_UNUSED, rtx default_label)
08736 {
08737 enum machine_mode index_mode = SImode;
08738 int index_bits = GET_MODE_BITSIZE (index_mode);
08739 rtx op1, op2, index;
08740 enum machine_mode op_mode;
08741
08742 if (! HAVE_casesi)
08743 return 0;
08744
08745
08746 if (GET_MODE_BITSIZE (TYPE_MODE (index_type)) > GET_MODE_BITSIZE (index_mode))
08747 {
08748 enum machine_mode omode = TYPE_MODE (index_type);
08749 rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
08750
08751
08752 index_expr = build2 (MINUS_EXPR, index_type,
08753 index_expr, minval);
08754 minval = integer_zero_node;
08755 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
08756 emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
08757 omode, 1, default_label);
08758
08759 index = convert_to_mode (index_mode, index, 0);
08760 }
08761 else
08762 {
08763 if (TYPE_MODE (index_type) != index_mode)
08764 {
08765 index_expr = convert (lang_hooks.types.type_for_size
08766 (index_bits, 0), index_expr);
08767 index_type = TREE_TYPE (index_expr);
08768 }
08769
08770 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
08771 }
08772
08773 do_pending_stack_adjust ();
08774
08775 op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
08776 if (! (*insn_data[(int) CODE_FOR_casesi].operand[0].predicate)
08777 (index, op_mode))
08778 index = copy_to_mode_reg (op_mode, index);
08779
08780 op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
08781
08782 op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
08783 op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
08784 op1, TYPE_UNSIGNED (TREE_TYPE (minval)));
08785 if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
08786 (op1, op_mode))
08787 op1 = copy_to_mode_reg (op_mode, op1);
08788
08789 op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
08790
08791 op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
08792 op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
08793 op2, TYPE_UNSIGNED (TREE_TYPE (range)));
08794 if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
08795 (op2, op_mode))
08796 op2 = copy_to_mode_reg (op_mode, op2);
08797
08798 emit_jump_insn (gen_casesi (index, op1, op2,
08799 table_label, default_label));
08800 return 1;
08801 }
08802
08803
08804 #ifndef HAVE_tablejump
08805 #define HAVE_tablejump 0
08806 #define gen_tablejump(x, y) (0)
08807 #endif
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820 static void
08821 do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
08822 rtx default_label)
08823 {
08824 rtx temp, vector;
08825
08826 if (INTVAL (range) > cfun->max_jumptable_ents)
08827 cfun->max_jumptable_ents = INTVAL (range);
08828
08829
08830
08831
08832
08833
08834
08835
08836
08837 emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
08838 default_label);
08839
08840
08841
08842 if (mode != Pmode)
08843 index = convert_to_mode (Pmode, index, 1);
08844
08845
08846
08847
08848 #ifdef PIC_CASE_VECTOR_ADDRESS
08849 if (flag_pic && !REG_P (index))
08850 index = copy_to_mode_reg (Pmode, index);
08851 #endif
08852
08853
08854
08855
08856
08857
08858
08859
08860
08861 index = gen_rtx_PLUS (Pmode,
08862 gen_rtx_MULT (Pmode, index,
08863 GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))),
08864 gen_rtx_LABEL_REF (Pmode, table_label));
08865 #ifdef PIC_CASE_VECTOR_ADDRESS
08866 if (flag_pic)
08867 index = PIC_CASE_VECTOR_ADDRESS (index);
08868 else
08869 #endif
08870 index = memory_address_noforce (CASE_VECTOR_MODE, index);
08871 temp = gen_reg_rtx (CASE_VECTOR_MODE);
08872 vector = gen_const_mem (CASE_VECTOR_MODE, index);
08873 convert_move (temp, vector, 0);
08874
08875 emit_jump_insn (gen_tablejump (temp, table_label));
08876
08877
08878
08879 if (! CASE_VECTOR_PC_RELATIVE && ! flag_pic)
08880 emit_barrier ();
08881 }
08882
08883 int
08884 try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
08885 rtx table_label, rtx default_label)
08886 {
08887 rtx index;
08888
08889 if (! HAVE_tablejump)
08890 return 0;
08891
08892 index_expr = fold (build2 (MINUS_EXPR, index_type,
08893 convert (index_type, index_expr),
08894 convert (index_type, minval)));
08895 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
08896 do_pending_stack_adjust ();
08897
08898 do_tablejump (index, TYPE_MODE (index_type),
08899 convert_modes (TYPE_MODE (index_type),
08900 TYPE_MODE (TREE_TYPE (range)),
08901 expand_expr (range, NULL_RTX,
08902 VOIDmode, 0),
08903 TYPE_UNSIGNED (TREE_TYPE (range))),
08904 table_label, default_label);
08905 return 1;
08906 }
08907
08908
08909
08910
08911
08912 int
08913 vector_mode_valid_p (enum machine_mode mode)
08914 {
08915 enum mode_class class = GET_MODE_CLASS (mode);
08916 enum machine_mode innermode;
08917
08918
08919 if (class != MODE_VECTOR_INT
08920 && class != MODE_VECTOR_FLOAT)
08921 return 0;
08922
08923
08924 if (targetm.vector_mode_supported_p (mode))
08925 return 1;
08926
08927 innermode = GET_MODE_INNER (mode);
08928
08929
08930
08931
08932
08933
08934 return targetm.scalar_mode_supported_p (innermode);
08935 }
08936
08937
08938 static rtx
08939 const_vector_from_tree (tree exp)
08940 {
08941 rtvec v;
08942 int units, i;
08943 tree link, elt;
08944 enum machine_mode inner, mode;
08945
08946 mode = TYPE_MODE (TREE_TYPE (exp));
08947
08948 if (initializer_zerop (exp))
08949 return CONST0_RTX (mode);
08950
08951 units = GET_MODE_NUNITS (mode);
08952 inner = GET_MODE_INNER (mode);
08953
08954 v = rtvec_alloc (units);
08955
08956 link = TREE_VECTOR_CST_ELTS (exp);
08957 for (i = 0; link; link = TREE_CHAIN (link), ++i)
08958 {
08959 elt = TREE_VALUE (link);
08960
08961 if (TREE_CODE (elt) == REAL_CST)
08962 RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
08963 inner);
08964 else
08965 RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
08966 TREE_INT_CST_HIGH (elt),
08967 inner);
08968 }
08969
08970
08971 for (; i < units; ++i)
08972 RTVEC_ELT (v, i) = CONST0_RTX (inner);
08973
08974 return gen_rtx_CONST_VECTOR (mode, v);
08975 }
08976 #include "gt-expr.h"