00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "machmode.h"
00029 #include "real.h"
00030 #include "rtl.h"
00031 #include "tree.h"
00032 #include "flags.h"
00033 #include "regs.h"
00034 #include "hard-reg-set.h"
00035 #include "except.h"
00036 #include "function.h"
00037 #include "insn-config.h"
00038 #include "insn-attr.h"
00039 #ifdef SGI_MONGOOSE
00040
00041 #include "insn-flags.h"
00042 #endif
00043
00044 #include "expr.h"
00045 #include "optabs.h"
00046 #include "libfuncs.h"
00047 #include "recog.h"
00048 #include "reload.h"
00049 #include "output.h"
00050 #include "typeclass.h"
00051 #include "toplev.h"
00052 #include "ggc.h"
00053 #include "langhooks.h"
00054 #include "intl.h"
00055 #include "tm_p.h"
00056 #ifdef SGI_MONGOOSE
00057
00058 #include "defaults.h"
00059 #endif
00060
00061
00062
00063
00064
00065
00066
00067 #ifdef PUSH_ROUNDING
00068
00069 #ifndef PUSH_ARGS_REVERSED
00070 #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
00071 #define PUSH_ARGS_REVERSED
00072 #endif
00073 #endif
00074
00075 #endif
00076
00077 #ifndef STACK_PUSH_CODE
00078 #ifdef STACK_GROWS_DOWNWARD
00079 #define STACK_PUSH_CODE PRE_DEC
00080 #else
00081 #define STACK_PUSH_CODE PRE_INC
00082 #endif
00083 #endif
00084
00085
00086 #ifndef CASE_VECTOR_PC_RELATIVE
00087 #define CASE_VECTOR_PC_RELATIVE 0
00088 #endif
00089
00090
00091 #ifdef TARGET_MEM_FUNCTIONS
00092 #undef TARGET_MEM_FUNCTIONS
00093 #define TARGET_MEM_FUNCTIONS 1
00094 #else
00095 #define TARGET_MEM_FUNCTIONS 0
00096 #endif
00097
00098
00099
00100
00101
00102
00103
00104
00105 int cse_not_expected;
00106
00107
00108 static tree placeholder_list = 0;
00109
00110
00111
00112 struct move_by_pieces
00113 {
00114 rtx to;
00115 rtx to_addr;
00116 int autinc_to;
00117 int explicit_inc_to;
00118 rtx from;
00119 rtx from_addr;
00120 int autinc_from;
00121 int explicit_inc_from;
00122 unsigned HOST_WIDE_INT len;
00123 HOST_WIDE_INT offset;
00124 int reverse;
00125 };
00126
00127
00128
00129
00130 struct store_by_pieces
00131 {
00132 rtx to;
00133 rtx to_addr;
00134 int autinc_to;
00135 int explicit_inc_to;
00136 unsigned HOST_WIDE_INT len;
00137 HOST_WIDE_INT offset;
00138 rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
00139 PTR constfundata;
00140 int reverse;
00141 };
00142
00143 static rtx enqueue_insn PARAMS ((rtx, rtx));
00144 static unsigned HOST_WIDE_INT move_by_pieces_ninsns
00145 PARAMS ((unsigned HOST_WIDE_INT,
00146 unsigned int));
00147 static void move_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
00148 struct move_by_pieces *));
00149 static bool block_move_libcall_safe_for_call_parm PARAMS ((void));
00150 static bool emit_block_move_via_movstr PARAMS ((rtx, rtx, rtx, unsigned));
00151 static rtx emit_block_move_via_libcall PARAMS ((rtx, rtx, rtx));
00152 static tree emit_block_move_libcall_fn PARAMS ((int));
00153 static void emit_block_move_via_loop PARAMS ((rtx, rtx, rtx, unsigned));
00154 static rtx clear_by_pieces_1 PARAMS ((PTR, HOST_WIDE_INT,
00155 enum machine_mode));
00156 static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
00157 unsigned int));
00158 static void store_by_pieces_1 PARAMS ((struct store_by_pieces *,
00159 unsigned int));
00160 static void store_by_pieces_2 PARAMS ((rtx (*) (rtx, ...),
00161 enum machine_mode,
00162 struct store_by_pieces *));
00163 static bool clear_storage_via_clrstr PARAMS ((rtx, rtx, unsigned));
00164 static rtx clear_storage_via_libcall PARAMS ((rtx, rtx));
00165 static tree clear_storage_libcall_fn PARAMS ((int));
00166 static rtx compress_float_constant PARAMS ((rtx, rtx));
00167 static rtx get_subtarget PARAMS ((rtx));
00168 static int is_zeros_p PARAMS ((tree));
00169 static int mostly_zeros_p PARAMS ((tree));
00170 static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
00171 HOST_WIDE_INT, enum machine_mode,
00172 tree, tree, int, int));
00173 static void store_constructor PARAMS ((tree, rtx, int, HOST_WIDE_INT));
00174 static rtx store_field PARAMS ((rtx, HOST_WIDE_INT,
00175 HOST_WIDE_INT, enum machine_mode,
00176 tree, enum machine_mode, int, tree,
00177 int));
00178 static rtx var_rtx PARAMS ((tree));
00179 static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
00180 static HOST_WIDE_INT highest_pow2_factor_for_type PARAMS ((tree, tree));
00181 static int is_aligning_offset PARAMS ((tree, tree));
00182 static rtx expand_increment PARAMS ((tree, int, int));
00183 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
00184 static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
00185 static void do_compare_and_jump PARAMS ((tree, enum rtx_code, enum rtx_code,
00186 rtx, rtx));
00187 static rtx do_store_flag PARAMS ((tree, rtx, enum machine_mode, int));
00188 #ifdef PUSH_ROUNDING
00189 static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
00190 #endif
00191 static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
00192 static rtx const_vector_from_tree PARAMS ((tree));
00193
00194
00195
00196
00197
00198 static char direct_load[NUM_MACHINE_MODES];
00199 static char direct_store[NUM_MACHINE_MODES];
00200
00201
00202
00203 static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
00204
00205
00206
00207
00208 #ifndef MOVE_RATIO
00209 #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
00210 #define MOVE_RATIO 2
00211 #else
00212
00213 #define MOVE_RATIO (optimize_size ? 3 : 15)
00214 #endif
00215 #endif
00216
00217
00218
00219 #ifndef MOVE_BY_PIECES_P
00220 #define MOVE_BY_PIECES_P(SIZE, ALIGN) \
00221 (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
00222 #endif
00223
00224
00225
00226
00227 #ifndef CLEAR_RATIO
00228 #if defined (HAVE_clrstrqi) || defined (HAVE_clrstrhi) || defined (HAVE_clrstrsi) || defined (HAVE_clrstrdi) || defined (HAVE_clrstrti)
00229 #define CLEAR_RATIO 2
00230 #else
00231
00232 #define CLEAR_RATIO (optimize_size ? 3 : 15)
00233 #endif
00234 #endif
00235
00236
00237
00238 #ifndef CLEAR_BY_PIECES_P
00239 #define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
00240 (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) CLEAR_RATIO)
00241 #endif
00242
00243
00244 enum insn_code movstr_optab[NUM_MACHINE_MODES];
00245
00246
00247 enum insn_code clrstr_optab[NUM_MACHINE_MODES];
00248
00249
00250
00251 #ifndef SLOW_UNALIGNED_ACCESS
00252 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
00253 #endif
00254
00255
00256
00257
00258 void
00259 init_expr_once ()
00260 {
00261 rtx insn, pat;
00262 enum machine_mode mode;
00263 int num_clobbers;
00264 rtx mem, mem1;
00265 rtx reg;
00266
00267
00268
00269
00270 mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
00271 mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
00272
00273
00274
00275 reg = gen_rtx_REG (VOIDmode, -1);
00276
00277 insn = rtx_alloc (INSN);
00278 pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
00279 PATTERN (insn) = pat;
00280
00281 for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
00282 mode = (enum machine_mode) ((int) mode + 1))
00283 {
00284 int regno;
00285
00286 direct_load[(int) mode] = direct_store[(int) mode] = 0;
00287 PUT_MODE (mem, mode);
00288 PUT_MODE (mem1, mode);
00289 PUT_MODE (reg, mode);
00290
00291
00292
00293
00294 if (mode != VOIDmode && mode != BLKmode)
00295 for (regno = 0; regno < FIRST_PSEUDO_REGISTER
00296 && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
00297 regno++)
00298 {
00299 if (! HARD_REGNO_MODE_OK (regno, mode))
00300 continue;
00301
00302 REGNO (reg) = regno;
00303
00304 SET_SRC (pat) = mem;
00305 SET_DEST (pat) = reg;
00306 if (recog (pat, insn, &num_clobbers) >= 0)
00307 direct_load[(int) mode] = 1;
00308
00309 SET_SRC (pat) = mem1;
00310 SET_DEST (pat) = reg;
00311 if (recog (pat, insn, &num_clobbers) >= 0)
00312 direct_load[(int) mode] = 1;
00313
00314 SET_SRC (pat) = reg;
00315 SET_DEST (pat) = mem;
00316 if (recog (pat, insn, &num_clobbers) >= 0)
00317 direct_store[(int) mode] = 1;
00318
00319 SET_SRC (pat) = reg;
00320 SET_DEST (pat) = mem1;
00321 if (recog (pat, insn, &num_clobbers) >= 0)
00322 direct_store[(int) mode] = 1;
00323 }
00324 }
00325
00326 mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
00327
00328 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
00329 mode = GET_MODE_WIDER_MODE (mode))
00330 {
00331 enum machine_mode srcmode;
00332 for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
00333 srcmode = GET_MODE_WIDER_MODE (srcmode))
00334 {
00335 enum insn_code ic;
00336
00337 ic = can_extend_p (mode, srcmode, 0);
00338 if (ic == CODE_FOR_nothing)
00339 continue;
00340
00341 PUT_MODE (mem, srcmode);
00342
00343 if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
00344 float_extend_from_mem[mode][srcmode] = true;
00345 }
00346 }
00347 }
00348
00349
00350
00351 void
00352 init_expr ()
00353 {
00354 cfun->expr = (struct expr_status *) ggc_alloc (sizeof (struct expr_status));
00355
00356 pending_chain = 0;
00357 pending_stack_adjust = 0;
00358 stack_pointer_delta = 0;
00359 inhibit_defer_pop = 0;
00360 saveregs_value = 0;
00361 apply_args_value = 0;
00362 forced_labels = 0;
00363 }
00364
00365
00366
00367 void
00368 finish_expr_for_function ()
00369 {
00370 if (pending_chain)
00371 abort ();
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 static rtx
00385 enqueue_insn (var, body)
00386 rtx var, body;
00387 {
00388 pending_chain = gen_rtx_QUEUED (GET_MODE (var), var, NULL_RTX, NULL_RTX,
00389 body, pending_chain);
00390 return pending_chain;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 rtx
00409 protect_from_queue (x, modify)
00410 rtx x;
00411 int modify;
00412 {
00413 RTX_CODE code = GET_CODE (x);
00414
00415 #if 0
00416
00417 if (pending_chain == 0)
00418 return x;
00419 #endif
00420
00421 if (code != QUEUED)
00422 {
00423
00424
00425
00426
00427
00428 if (code == MEM && GET_MODE (x) != BLKmode
00429 && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
00430 {
00431 rtx y = XEXP (x, 0);
00432 rtx new = replace_equiv_address_nv (x, QUEUED_VAR (y));
00433
00434 if (QUEUED_INSN (y))
00435 {
00436 rtx temp = gen_reg_rtx (GET_MODE (x));
00437
00438 emit_insn_before (gen_move_insn (temp, new),
00439 QUEUED_INSN (y));
00440 return temp;
00441 }
00442
00443
00444
00445 return replace_equiv_address (new, copy_to_reg (XEXP (new, 0)));
00446 }
00447
00448
00449
00450 if (code == MEM)
00451 {
00452 rtx tem = protect_from_queue (XEXP (x, 0), 0);
00453 if (tem != XEXP (x, 0))
00454 {
00455 x = copy_rtx (x);
00456 XEXP (x, 0) = tem;
00457 }
00458 }
00459 else if (code == PLUS || code == MULT)
00460 {
00461 rtx new0 = protect_from_queue (XEXP (x, 0), 0);
00462 rtx new1 = protect_from_queue (XEXP (x, 1), 0);
00463 if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
00464 {
00465 x = copy_rtx (x);
00466 XEXP (x, 0) = new0;
00467 XEXP (x, 1) = new1;
00468 }
00469 }
00470 return x;
00471 }
00472
00473
00474
00475 if (QUEUED_INSN (x) == 0)
00476 return copy_to_reg (QUEUED_VAR (x));
00477
00478
00479 if (QUEUED_COPY (x) != 0)
00480 return QUEUED_COPY (x);
00481
00482
00483 QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
00484 emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
00485 QUEUED_INSN (x));
00486 return QUEUED_COPY (x);
00487 }
00488
00489
00490
00491
00492
00493
00494 int
00495 queued_subexp_p (x)
00496 rtx x;
00497 {
00498 enum rtx_code code = GET_CODE (x);
00499 switch (code)
00500 {
00501 case QUEUED:
00502 return 1;
00503 case MEM:
00504 return queued_subexp_p (XEXP (x, 0));
00505 case MULT:
00506 case PLUS:
00507 case MINUS:
00508 return (queued_subexp_p (XEXP (x, 0))
00509 || queued_subexp_p (XEXP (x, 1)));
00510 default:
00511 return 0;
00512 }
00513 }
00514
00515
00516
00517 void
00518 emit_queue ()
00519 {
00520 rtx p;
00521 while ((p = pending_chain))
00522 {
00523 rtx body = QUEUED_BODY (p);
00524
00525 switch (GET_CODE (body))
00526 {
00527 case INSN:
00528 case JUMP_INSN:
00529 case CALL_INSN:
00530 case CODE_LABEL:
00531 case BARRIER:
00532 case NOTE:
00533 QUEUED_INSN (p) = body;
00534 emit_insn (body);
00535 break;
00536
00537 #ifdef ENABLE_CHECKING
00538 case SEQUENCE:
00539 abort ();
00540 break;
00541 #endif
00542
00543 default:
00544 QUEUED_INSN (p) = emit_insn (body);
00545 break;
00546 }
00547
00548 pending_chain = QUEUED_NEXT (p);
00549 }
00550 }
00551
00552
00553
00554
00555
00556
00557 void
00558 convert_move (to, from, unsignedp)
00559 rtx to, from;
00560 int unsignedp;
00561 {
00562 enum machine_mode to_mode = GET_MODE (to);
00563 enum machine_mode from_mode = GET_MODE (from);
00564 int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT;
00565 int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT;
00566 enum insn_code code;
00567 rtx libcall;
00568
00569
00570 enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
00571 : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
00572
00573 to = protect_from_queue (to, 1);
00574 from = protect_from_queue (from, 0);
00575
00576 if (to_real != from_real)
00577 abort ();
00578
00579
00580
00581
00582
00583 if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
00584 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from)))
00585 >= GET_MODE_SIZE (to_mode))
00586 && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
00587 from = gen_lowpart (to_mode, from), from_mode = to_mode;
00588
00589 if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to))
00590 abort ();
00591
00592 if (to_mode == from_mode
00593 || (from_mode == VOIDmode && CONSTANT_P (from)))
00594 {
00595 emit_move_insn (to, from);
00596 return;
00597 }
00598
00599 if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
00600 {
00601 if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode))
00602 abort ();
00603
00604 if (VECTOR_MODE_P (to_mode))
00605 from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0);
00606 else
00607 to = simplify_gen_subreg (from_mode, to, GET_MODE (to), 0);
00608
00609 emit_move_insn (to, from);
00610 return;
00611 }
00612
00613 if (to_real != from_real)
00614 abort ();
00615
00616 if (to_real)
00617 {
00618 rtx value, insns;
00619
00620 if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode))
00621 {
00622
00623 if ((code = can_extend_p (to_mode, from_mode, 0))
00624 != CODE_FOR_nothing)
00625 {
00626 emit_unop_insn (code, to, from, UNKNOWN);
00627 return;
00628 }
00629 }
00630
00631 #ifdef HAVE_trunchfqf2
00632 if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
00633 {
00634 emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN);
00635 return;
00636 }
00637 #endif
00638 #ifdef HAVE_trunctqfqf2
00639 if (HAVE_trunctqfqf2 && from_mode == TQFmode && to_mode == QFmode)
00640 {
00641 emit_unop_insn (CODE_FOR_trunctqfqf2, to, from, UNKNOWN);
00642 return;
00643 }
00644 #endif
00645 #ifdef HAVE_truncsfqf2
00646 if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode)
00647 {
00648 emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN);
00649 return;
00650 }
00651 #endif
00652 #ifdef HAVE_truncdfqf2
00653 if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode)
00654 {
00655 emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN);
00656 return;
00657 }
00658 #endif
00659 #ifdef HAVE_truncxfqf2
00660 if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode)
00661 {
00662 emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN);
00663 return;
00664 }
00665 #endif
00666 #ifdef HAVE_trunctfqf2
00667 if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode)
00668 {
00669 emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN);
00670 return;
00671 }
00672 #endif
00673
00674 #ifdef HAVE_trunctqfhf2
00675 if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode)
00676 {
00677 emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN);
00678 return;
00679 }
00680 #endif
00681 #ifdef HAVE_truncsfhf2
00682 if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode)
00683 {
00684 emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN);
00685 return;
00686 }
00687 #endif
00688 #ifdef HAVE_truncdfhf2
00689 if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode)
00690 {
00691 emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN);
00692 return;
00693 }
00694 #endif
00695 #ifdef HAVE_truncxfhf2
00696 if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode)
00697 {
00698 emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN);
00699 return;
00700 }
00701 #endif
00702 #ifdef HAVE_trunctfhf2
00703 if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode)
00704 {
00705 emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN);
00706 return;
00707 }
00708 #endif
00709
00710 #ifdef HAVE_truncsftqf2
00711 if (HAVE_truncsftqf2 && from_mode == SFmode && to_mode == TQFmode)
00712 {
00713 emit_unop_insn (CODE_FOR_truncsftqf2, to, from, UNKNOWN);
00714 return;
00715 }
00716 #endif
00717 #ifdef HAVE_truncdftqf2
00718 if (HAVE_truncdftqf2 && from_mode == DFmode && to_mode == TQFmode)
00719 {
00720 emit_unop_insn (CODE_FOR_truncdftqf2, to, from, UNKNOWN);
00721 return;
00722 }
00723 #endif
00724 #ifdef HAVE_truncxftqf2
00725 if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode)
00726 {
00727 emit_unop_insn (CODE_FOR_truncxftqf2, to, from, UNKNOWN);
00728 return;
00729 }
00730 #endif
00731 #ifdef HAVE_trunctftqf2
00732 if (HAVE_trunctftqf2 && from_mode == TFmode && to_mode == TQFmode)
00733 {
00734 emit_unop_insn (CODE_FOR_trunctftqf2, to, from, UNKNOWN);
00735 return;
00736 }
00737 #endif
00738
00739 #ifdef HAVE_truncdfsf2
00740 if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode)
00741 {
00742 emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
00743 return;
00744 }
00745 #endif
00746 #ifdef HAVE_truncxfsf2
00747 if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
00748 {
00749 emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN);
00750 return;
00751 }
00752 #endif
00753 #ifdef HAVE_trunctfsf2
00754 if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode)
00755 {
00756 emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN);
00757 return;
00758 }
00759 #endif
00760 #ifdef HAVE_truncxfdf2
00761 if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
00762 {
00763 emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN);
00764 return;
00765 }
00766 #endif
00767 #ifdef HAVE_trunctfdf2
00768 if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode)
00769 {
00770 emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN);
00771 return;
00772 }
00773 #endif
00774
00775 libcall = (rtx) 0;
00776 switch (from_mode)
00777 {
00778 case SFmode:
00779 switch (to_mode)
00780 {
00781 case DFmode:
00782 libcall = extendsfdf2_libfunc;
00783 break;
00784
00785 case XFmode:
00786 libcall = extendsfxf2_libfunc;
00787 break;
00788
00789 case TFmode:
00790 libcall = extendsftf2_libfunc;
00791 break;
00792
00793 default:
00794 break;
00795 }
00796 break;
00797
00798 case DFmode:
00799 switch (to_mode)
00800 {
00801 case SFmode:
00802 libcall = truncdfsf2_libfunc;
00803 break;
00804
00805 case XFmode:
00806 libcall = extenddfxf2_libfunc;
00807 break;
00808
00809 case TFmode:
00810 libcall = extenddftf2_libfunc;
00811 break;
00812
00813 default:
00814 break;
00815 }
00816 break;
00817
00818 case XFmode:
00819 switch (to_mode)
00820 {
00821 case SFmode:
00822 libcall = truncxfsf2_libfunc;
00823 break;
00824
00825 case DFmode:
00826 libcall = truncxfdf2_libfunc;
00827 break;
00828
00829 default:
00830 break;
00831 }
00832 break;
00833
00834 case TFmode:
00835 switch (to_mode)
00836 {
00837 case SFmode:
00838 libcall = trunctfsf2_libfunc;
00839 break;
00840
00841 case DFmode:
00842 libcall = trunctfdf2_libfunc;
00843 break;
00844
00845 default:
00846 break;
00847 }
00848 break;
00849
00850 default:
00851 break;
00852 }
00853
00854 if (libcall == (rtx) 0)
00855
00856 abort ();
00857
00858 start_sequence ();
00859 value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
00860 1, from, from_mode);
00861 insns = get_insns ();
00862 end_sequence ();
00863 emit_libcall_block (insns, to, value, gen_rtx_FLOAT_TRUNCATE (to_mode,
00864 from));
00865 return;
00866 }
00867
00868
00869
00870
00871 if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)
00872 && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD)
00873 {
00874 rtx insns;
00875 rtx lowpart;
00876 rtx fill_value;
00877 rtx lowfrom;
00878 int i;
00879 enum machine_mode lowpart_mode;
00880 int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
00881
00882
00883 if ((code = can_extend_p (to_mode, from_mode, unsignedp))
00884 != CODE_FOR_nothing)
00885 {
00886
00887
00888
00889
00890 if (optimize > 0 && GET_CODE (from) == SUBREG)
00891 from = force_reg (from_mode, from);
00892 emit_unop_insn (code, to, from, equiv_code);
00893 return;
00894 }
00895
00896 else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD
00897 && ((code = can_extend_p (to_mode, word_mode, unsignedp))
00898 != CODE_FOR_nothing))
00899 {
00900 if (GET_CODE (to) == REG)
00901 emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
00902 convert_move (gen_lowpart (word_mode, to), from, unsignedp);
00903 emit_unop_insn (code, to,
00904 gen_lowpart (word_mode, to), equiv_code);
00905 return;
00906 }
00907
00908
00909 start_sequence ();
00910
00911
00912
00913
00914 if (reg_overlap_mentioned_p (to, from))
00915 from = force_reg (from_mode, from);
00916
00917
00918 if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD)
00919 lowpart_mode = word_mode;
00920 else
00921 lowpart_mode = from_mode;
00922
00923 lowfrom = convert_to_mode (lowpart_mode, from, unsignedp);
00924
00925 lowpart = gen_lowpart (lowpart_mode, to);
00926 emit_move_insn (lowpart, lowfrom);
00927
00928
00929 if (unsignedp)
00930 fill_value = const0_rtx;
00931 else
00932 {
00933 #ifdef HAVE_slt
00934 if (HAVE_slt
00935 && insn_data[(int) CODE_FOR_slt].operand[0].mode == word_mode
00936 && STORE_FLAG_VALUE == -1)
00937 {
00938 emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
00939 lowpart_mode, 0);
00940 fill_value = gen_reg_rtx (word_mode);
00941 emit_insn (gen_slt (fill_value));
00942 }
00943 else
00944 #endif
00945 {
00946 fill_value
00947 = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
00948 size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
00949 NULL_RTX, 0);
00950 fill_value = convert_to_mode (word_mode, fill_value, 1);
00951 }
00952 }
00953
00954
00955 for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
00956 {
00957 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
00958 rtx subword = operand_subword (to, index, 1, to_mode);
00959
00960 if (subword == 0)
00961 abort ();
00962
00963 if (fill_value != subword)
00964 emit_move_insn (subword, fill_value);
00965 }
00966
00967 insns = get_insns ();
00968 end_sequence ();
00969
00970 emit_no_conflict_block (insns, to, from, NULL_RTX,
00971 gen_rtx_fmt_e (equiv_code, to_mode, copy_rtx (from)));
00972 return;
00973 }
00974
00975
00976 if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD
00977 && GET_MODE_BITSIZE (to_mode) <= BITS_PER_WORD)
00978 {
00979 if (!((GET_CODE (from) == MEM
00980 && ! MEM_VOLATILE_P (from)
00981 && direct_load[(int) to_mode]
00982 && ! mode_dependent_address_p (XEXP (from, 0)))
00983 || GET_CODE (from) == REG
00984 || GET_CODE (from) == SUBREG))
00985 from = force_reg (from_mode, from);
00986 convert_move (to, gen_lowpart (word_mode, from), 0);
00987 return;
00988 }
00989
00990
00991 if (to_mode == PQImode)
00992 {
00993 if (from_mode != QImode)
00994 from = convert_to_mode (QImode, from, unsignedp);
00995
00996 #ifdef HAVE_truncqipqi2
00997 if (HAVE_truncqipqi2)
00998 {
00999 emit_unop_insn (CODE_FOR_truncqipqi2, to, from, UNKNOWN);
01000 return;
01001 }
01002 #endif
01003 abort ();
01004 }
01005
01006 if (from_mode == PQImode)
01007 {
01008 if (to_mode != QImode)
01009 {
01010 from = convert_to_mode (QImode, from, unsignedp);
01011 from_mode = QImode;
01012 }
01013 else
01014 {
01015 #ifdef HAVE_extendpqiqi2
01016 if (HAVE_extendpqiqi2)
01017 {
01018 emit_unop_insn (CODE_FOR_extendpqiqi2, to, from, UNKNOWN);
01019 return;
01020 }
01021 #endif
01022 abort ();
01023 }
01024 }
01025
01026 if (to_mode == PSImode)
01027 {
01028 if (from_mode != SImode)
01029 from = convert_to_mode (SImode, from, unsignedp);
01030
01031 #ifdef HAVE_truncsipsi2
01032 if (HAVE_truncsipsi2)
01033 {
01034 emit_unop_insn (CODE_FOR_truncsipsi2, to, from, UNKNOWN);
01035 return;
01036 }
01037 #endif
01038 abort ();
01039 }
01040
01041 if (from_mode == PSImode)
01042 {
01043 if (to_mode != SImode)
01044 {
01045 from = convert_to_mode (SImode, from, unsignedp);
01046 from_mode = SImode;
01047 }
01048 else
01049 {
01050 #ifdef HAVE_extendpsisi2
01051 if (! unsignedp && HAVE_extendpsisi2)
01052 {
01053 emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
01054 return;
01055 }
01056 #endif
01057 #ifdef HAVE_zero_extendpsisi2
01058 if (unsignedp && HAVE_zero_extendpsisi2)
01059 {
01060 emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN);
01061 return;
01062 }
01063 #endif
01064 abort ();
01065 }
01066 }
01067
01068 if (to_mode == PDImode)
01069 {
01070 if (from_mode != DImode)
01071 from = convert_to_mode (DImode, from, unsignedp);
01072
01073 #ifdef HAVE_truncdipdi2
01074 if (HAVE_truncdipdi2)
01075 {
01076 emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN);
01077 return;
01078 }
01079 #endif
01080 abort ();
01081 }
01082
01083 if (from_mode == PDImode)
01084 {
01085 if (to_mode != DImode)
01086 {
01087 from = convert_to_mode (DImode, from, unsignedp);
01088 from_mode = DImode;
01089 }
01090 else
01091 {
01092 #ifdef HAVE_extendpdidi2
01093 if (HAVE_extendpdidi2)
01094 {
01095 emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN);
01096 return;
01097 }
01098 #endif
01099 abort ();
01100 }
01101 }
01102
01103
01104
01105
01106
01107 if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
01108 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
01109 GET_MODE_BITSIZE (from_mode)))
01110 {
01111 if (!((GET_CODE (from) == MEM
01112 && ! MEM_VOLATILE_P (from)
01113 && direct_load[(int) to_mode]
01114 && ! mode_dependent_address_p (XEXP (from, 0)))
01115 || GET_CODE (from) == REG
01116 || GET_CODE (from) == SUBREG))
01117 from = force_reg (from_mode, from);
01118 if (GET_CODE (from) == REG && REGNO (from) < FIRST_PSEUDO_REGISTER
01119 && ! HARD_REGNO_MODE_OK (REGNO (from), to_mode))
01120 from = copy_to_reg (from);
01121 emit_move_insn (to, gen_lowpart (to_mode, from));
01122 return;
01123 }
01124
01125
01126 if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
01127 {
01128
01129 if ((code = can_extend_p (to_mode, from_mode, unsignedp))
01130 != CODE_FOR_nothing)
01131 {
01132 if (flag_force_mem)
01133 from = force_not_mem (from);
01134
01135 emit_unop_insn (code, to, from, equiv_code);
01136 return;
01137 }
01138 else
01139 {
01140 enum machine_mode intermediate;
01141 rtx tmp;
01142 tree shift_amount;
01143
01144
01145 for (intermediate = from_mode; intermediate != VOIDmode;
01146 intermediate = GET_MODE_WIDER_MODE (intermediate))
01147 if (((can_extend_p (to_mode, intermediate, unsignedp)
01148 != CODE_FOR_nothing)
01149 || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
01150 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
01151 GET_MODE_BITSIZE (intermediate))))
01152 && (can_extend_p (intermediate, from_mode, unsignedp)
01153 != CODE_FOR_nothing))
01154 {
01155 convert_move (to, convert_to_mode (intermediate, from,
01156 unsignedp), unsignedp);
01157 return;
01158 }
01159
01160
01161
01162 shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
01163 - GET_MODE_BITSIZE (from_mode), 0);
01164 from = gen_lowpart (to_mode, force_reg (from_mode, from));
01165 tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
01166 to, unsignedp);
01167 tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
01168 to, unsignedp);
01169 if (tmp != to)
01170 emit_move_insn (to, tmp);
01171 return;
01172 }
01173 }
01174
01175
01176
01177 if (from_mode == DImode && to_mode == SImode)
01178 {
01179 #ifdef HAVE_truncdisi2
01180 if (HAVE_truncdisi2)
01181 {
01182 emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN);
01183 return;
01184 }
01185 #endif
01186 convert_move (to, force_reg (from_mode, from), unsignedp);
01187 return;
01188 }
01189
01190 if (from_mode == DImode && to_mode == HImode)
01191 {
01192 #ifdef HAVE_truncdihi2
01193 if (HAVE_truncdihi2)
01194 {
01195 emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN);
01196 return;
01197 }
01198 #endif
01199 convert_move (to, force_reg (from_mode, from), unsignedp);
01200 return;
01201 }
01202
01203 if (from_mode == DImode && to_mode == QImode)
01204 {
01205 #ifdef HAVE_truncdiqi2
01206 if (HAVE_truncdiqi2)
01207 {
01208 emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN);
01209 return;
01210 }
01211 #endif
01212 convert_move (to, force_reg (from_mode, from), unsignedp);
01213 return;
01214 }
01215
01216 if (from_mode == SImode && to_mode == HImode)
01217 {
01218 #ifdef HAVE_truncsihi2
01219 if (HAVE_truncsihi2)
01220 {
01221 emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
01222 return;
01223 }
01224 #endif
01225 convert_move (to, force_reg (from_mode, from), unsignedp);
01226 return;
01227 }
01228
01229 if (from_mode == SImode && to_mode == QImode)
01230 {
01231 #ifdef HAVE_truncsiqi2
01232 if (HAVE_truncsiqi2)
01233 {
01234 emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
01235 return;
01236 }
01237 #endif
01238 convert_move (to, force_reg (from_mode, from), unsignedp);
01239 return;
01240 }
01241
01242 if (from_mode == HImode && to_mode == QImode)
01243 {
01244 #ifdef HAVE_trunchiqi2
01245 if (HAVE_trunchiqi2)
01246 {
01247 emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
01248 return;
01249 }
01250 #endif
01251 convert_move (to, force_reg (from_mode, from), unsignedp);
01252 return;
01253 }
01254
01255 if (from_mode == TImode && to_mode == DImode)
01256 {
01257 #ifdef HAVE_trunctidi2
01258 if (HAVE_trunctidi2)
01259 {
01260 emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN);
01261 return;
01262 }
01263 #endif
01264 convert_move (to, force_reg (from_mode, from), unsignedp);
01265 return;
01266 }
01267
01268 if (from_mode == TImode && to_mode == SImode)
01269 {
01270 #ifdef HAVE_trunctisi2
01271 if (HAVE_trunctisi2)
01272 {
01273 emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN);
01274 return;
01275 }
01276 #endif
01277 convert_move (to, force_reg (from_mode, from), unsignedp);
01278 return;
01279 }
01280
01281 if (from_mode == TImode && to_mode == HImode)
01282 {
01283 #ifdef HAVE_trunctihi2
01284 if (HAVE_trunctihi2)
01285 {
01286 emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN);
01287 return;
01288 }
01289 #endif
01290 convert_move (to, force_reg (from_mode, from), unsignedp);
01291 return;
01292 }
01293
01294 if (from_mode == TImode && to_mode == QImode)
01295 {
01296 #ifdef HAVE_trunctiqi2
01297 if (HAVE_trunctiqi2)
01298 {
01299 emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN);
01300 return;
01301 }
01302 #endif
01303 convert_move (to, force_reg (from_mode, from), unsignedp);
01304 return;
01305 }
01306
01307
01308
01309
01310 if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
01311 {
01312 rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
01313 emit_move_insn (to, temp);
01314 return;
01315 }
01316
01317
01318 abort ();
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 rtx
01332 convert_to_mode (mode, x, unsignedp)
01333 enum machine_mode mode;
01334 rtx x;
01335 int unsignedp;
01336 {
01337 return convert_modes (mode, VOIDmode, x, unsignedp);
01338 }
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 rtx
01354 convert_modes (mode, oldmode, x, unsignedp)
01355 enum machine_mode mode, oldmode;
01356 rtx x;
01357 int unsignedp;
01358 {
01359 rtx temp;
01360
01361
01362
01363
01364 if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
01365 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
01366 && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)
01367 x = gen_lowpart (mode, x);
01368
01369 if (GET_MODE (x) != VOIDmode)
01370 oldmode = GET_MODE (x);
01371
01372 if (mode == oldmode)
01373 return x;
01374
01375
01376
01377
01378
01379
01380
01381 if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
01382 && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
01383 && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)
01384 {
01385 HOST_WIDE_INT val = INTVAL (x);
01386
01387 if (oldmode != VOIDmode
01388 && HOST_BITS_PER_WIDE_INT > GET_MODE_BITSIZE (oldmode))
01389 {
01390 int width = GET_MODE_BITSIZE (oldmode);
01391
01392
01393 val &= ((HOST_WIDE_INT) 1 << width) - 1;
01394 }
01395
01396 return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
01397 }
01398
01399
01400
01401
01402
01403
01404 if ((GET_CODE (x) == CONST_INT
01405 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
01406 || (GET_MODE_CLASS (mode) == MODE_INT
01407 && GET_MODE_CLASS (oldmode) == MODE_INT
01408 && (GET_CODE (x) == CONST_DOUBLE
01409 || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode)
01410 && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)
01411 && direct_load[(int) mode])
01412 || (GET_CODE (x) == REG
01413 && (! HARD_REGISTER_P (x)
01414 || HARD_REGNO_MODE_OK (REGNO (x), mode))
01415 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01416 GET_MODE_BITSIZE (GET_MODE (x)))))))))
01417 {
01418
01419
01420
01421 if (GET_CODE (x) == CONST_INT && oldmode != VOIDmode
01422 && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode))
01423 {
01424 HOST_WIDE_INT val = INTVAL (x);
01425 int width = GET_MODE_BITSIZE (oldmode);
01426
01427
01428
01429 val &= ((HOST_WIDE_INT) 1 << width) - 1;
01430 if (! unsignedp
01431 && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
01432 val |= (HOST_WIDE_INT) (-1) << width;
01433
01434 return gen_int_mode (val, mode);
01435 }
01436
01437 return gen_lowpart (mode, x);
01438 }
01439
01440
01441
01442 if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode)
01443 {
01444 if (GET_MODE_BITSIZE (mode) != GET_MODE_BITSIZE (oldmode))
01445 abort ();
01446 return simplify_gen_subreg (mode, x, oldmode, 0);
01447 }
01448
01449 temp = gen_reg_rtx (mode);
01450 convert_move (temp, x, unsignedp);
01451 return temp;
01452 }
01453
01454
01455
01456
01457
01458
01459
01460
01461 #ifndef MOVE_MAX_PIECES
01462 #define MOVE_MAX_PIECES MOVE_MAX
01463 #endif
01464
01465
01466
01467
01468
01469
01470 #define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
01471
01472
01473
01474
01475
01476 int
01477 can_move_by_pieces (len, align)
01478 unsigned HOST_WIDE_INT len;
01479 unsigned int align;
01480 {
01481 return MOVE_BY_PIECES_P (len, align);
01482 }
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497 rtx
01498 move_by_pieces (to, from, len, align, endp)
01499 rtx to, from;
01500 unsigned HOST_WIDE_INT len;
01501 unsigned int align;
01502 int endp;
01503 {
01504 struct move_by_pieces data;
01505 rtx to_addr, from_addr = XEXP (from, 0);
01506 unsigned int max_size = MOVE_MAX_PIECES + 1;
01507 enum machine_mode mode = VOIDmode, tmode;
01508 enum insn_code icode;
01509
01510 data.offset = 0;
01511 data.from_addr = from_addr;
01512 if (to)
01513 {
01514 to_addr = XEXP (to, 0);
01515 data.to = to;
01516 data.autinc_to
01517 = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
01518 || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
01519 data.reverse
01520 = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
01521 }
01522 else
01523 {
01524 to_addr = NULL_RTX;
01525 data.to = NULL_RTX;
01526 data.autinc_to = 1;
01527 #ifdef STACK_GROWS_DOWNWARD
01528 data.reverse = 1;
01529 #else
01530 data.reverse = 0;
01531 #endif
01532 }
01533 data.to_addr = to_addr;
01534 data.from = from;
01535 data.autinc_from
01536 = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
01537 || GET_CODE (from_addr) == POST_INC
01538 || GET_CODE (from_addr) == POST_DEC);
01539
01540 data.explicit_inc_from = 0;
01541 data.explicit_inc_to = 0;
01542 if (data.reverse) data.offset = len;
01543 data.len = len;
01544
01545
01546
01547
01548 if (!(data.autinc_from && data.autinc_to)
01549 && move_by_pieces_ninsns (len, align) > 2)
01550 {
01551
01552 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01553 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01554 if (GET_MODE_SIZE (tmode) < max_size)
01555 mode = tmode;
01556
01557 if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
01558 {
01559 data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
01560 data.autinc_from = 1;
01561 data.explicit_inc_from = -1;
01562 }
01563 if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
01564 {
01565 data.from_addr = copy_addr_to_reg (from_addr);
01566 data.autinc_from = 1;
01567 data.explicit_inc_from = 1;
01568 }
01569 if (!data.autinc_from && CONSTANT_P (from_addr))
01570 data.from_addr = copy_addr_to_reg (from_addr);
01571 if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
01572 {
01573 data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
01574 data.autinc_to = 1;
01575 data.explicit_inc_to = -1;
01576 }
01577 if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
01578 {
01579 data.to_addr = copy_addr_to_reg (to_addr);
01580 data.autinc_to = 1;
01581 data.explicit_inc_to = 1;
01582 }
01583 if (!data.autinc_to && CONSTANT_P (to_addr))
01584 data.to_addr = copy_addr_to_reg (to_addr);
01585 }
01586
01587 if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
01588 || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
01589 align = MOVE_MAX * BITS_PER_UNIT;
01590
01591
01592
01593
01594 while (max_size > 1)
01595 {
01596 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01597 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01598 if (GET_MODE_SIZE (tmode) < max_size)
01599 mode = tmode;
01600
01601 if (mode == VOIDmode)
01602 break;
01603
01604 icode = mov_optab->handlers[(int) mode].insn_code;
01605 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
01606 move_by_pieces_1 (GEN_FCN (icode), mode, &data);
01607
01608 max_size = GET_MODE_SIZE (mode);
01609 }
01610
01611
01612 if (data.len > 0)
01613 abort ();
01614
01615 if (endp)
01616 {
01617 rtx to1;
01618
01619 if (data.reverse)
01620 abort ();
01621 if (data.autinc_to)
01622 {
01623 if (endp == 2)
01624 {
01625 if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
01626 emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
01627 else
01628 data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
01629 -1));
01630 }
01631 to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
01632 data.offset);
01633 }
01634 else
01635 {
01636 if (endp == 2)
01637 --data.offset;
01638 to1 = adjust_address (data.to, QImode, data.offset);
01639 }
01640 return to1;
01641 }
01642 else
01643 return data.to;
01644 }
01645
01646
01647
01648
01649 static unsigned HOST_WIDE_INT
01650 move_by_pieces_ninsns (l, align)
01651 unsigned HOST_WIDE_INT l;
01652 unsigned int align;
01653 {
01654 unsigned HOST_WIDE_INT n_insns = 0;
01655 unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1;
01656
01657 if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
01658 || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
01659 align = MOVE_MAX * BITS_PER_UNIT;
01660
01661 while (max_size > 1)
01662 {
01663 enum machine_mode mode = VOIDmode, tmode;
01664 enum insn_code icode;
01665
01666 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01667 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
01668 if (GET_MODE_SIZE (tmode) < max_size)
01669 mode = tmode;
01670
01671 if (mode == VOIDmode)
01672 break;
01673
01674 icode = mov_optab->handlers[(int) mode].insn_code;
01675 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
01676 n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
01677
01678 max_size = GET_MODE_SIZE (mode);
01679 }
01680
01681 if (l)
01682 abort ();
01683 return n_insns;
01684 }
01685
01686
01687
01688
01689
01690 static void
01691 move_by_pieces_1 (genfun, mode, data)
01692 rtx (*genfun) PARAMS ((rtx, ...));
01693 enum machine_mode mode;
01694 struct move_by_pieces *data;
01695 {
01696 unsigned int size = GET_MODE_SIZE (mode);
01697 rtx to1 = NULL_RTX, from1;
01698
01699 while (data->len >= size)
01700 {
01701 if (data->reverse)
01702 data->offset -= size;
01703
01704 if (data->to)
01705 {
01706 if (data->autinc_to)
01707 to1 = adjust_automodify_address (data->to, mode, data->to_addr,
01708 data->offset);
01709 else
01710 to1 = adjust_address (data->to, mode, data->offset);
01711 }
01712
01713 if (data->autinc_from)
01714 from1 = adjust_automodify_address (data->from, mode, data->from_addr,
01715 data->offset);
01716 else
01717 from1 = adjust_address (data->from, mode, data->offset);
01718
01719 if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
01720 emit_insn (gen_add2_insn (data->to_addr,
01721 GEN_INT (-(HOST_WIDE_INT)size)));
01722 if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
01723 emit_insn (gen_add2_insn (data->from_addr,
01724 GEN_INT (-(HOST_WIDE_INT)size)));
01725
01726 if (data->to)
01727 emit_insn ((*genfun) (to1, from1));
01728 else
01729 {
01730 #ifdef PUSH_ROUNDING
01731 emit_single_push_insn (mode, from1, NULL);
01732 #else
01733 abort ();
01734 #endif
01735 }
01736
01737 if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
01738 emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
01739 if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
01740 emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
01741
01742 if (! data->reverse)
01743 data->offset += size;
01744
01745 data->len -= size;
01746 }
01747 }
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 rtx
01762 emit_block_move (x, y, size, method)
01763 rtx x, y, size;
01764 enum block_op_methods method;
01765 {
01766 bool may_use_call;
01767 rtx retval = 0;
01768 unsigned int align;
01769
01770 switch (method)
01771 {
01772 case BLOCK_OP_NORMAL:
01773 may_use_call = true;
01774 break;
01775
01776 case BLOCK_OP_CALL_PARM:
01777 may_use_call = block_move_libcall_safe_for_call_parm ();
01778
01779
01780
01781 NO_DEFER_POP;
01782 break;
01783
01784 case BLOCK_OP_NO_LIBCALL:
01785 may_use_call = false;
01786 break;
01787
01788 default:
01789 abort ();
01790 }
01791
01792 align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
01793
01794 if (GET_MODE (x) != BLKmode)
01795 abort ();
01796 if (GET_MODE (y) != BLKmode)
01797 abort ();
01798
01799 x = protect_from_queue (x, 1);
01800 y = protect_from_queue (y, 0);
01801 size = protect_from_queue (size, 0);
01802
01803 if (GET_CODE (x) != MEM)
01804 abort ();
01805 if (GET_CODE (y) != MEM)
01806 abort ();
01807 if (size == 0)
01808 abort ();
01809
01810
01811
01812 if (GET_CODE (size) == CONST_INT)
01813 {
01814 x = shallow_copy_rtx (x);
01815 y = shallow_copy_rtx (y);
01816 set_mem_size (x, size);
01817 set_mem_size (y, size);
01818 }
01819
01820 if (size == const0_rtx)
01821 ;
01822 else if (GET_CODE (size) == CONST_INT
01823 && MOVE_BY_PIECES_P (INTVAL (size), align))
01824 move_by_pieces (x, y, INTVAL (size), align, 0);
01825 else if (emit_block_move_via_movstr (x, y, size, align))
01826 ;
01827 else if (may_use_call)
01828 retval = emit_block_move_via_libcall (x, y, size);
01829 else
01830 emit_block_move_via_loop (x, y, size, align);
01831
01832 if (method == BLOCK_OP_CALL_PARM)
01833 OK_DEFER_POP;
01834
01835 return retval;
01836 }
01837
01838
01839
01840
01841
01842 static bool
01843 block_move_libcall_safe_for_call_parm ()
01844 {
01845 if (PUSH_ARGS)
01846 return true;
01847 else
01848 {
01849
01850 static enum {
01851 takes_regs_uninit, takes_regs_no, takes_regs_yes
01852 } takes_regs = takes_regs_uninit;
01853
01854 switch (takes_regs)
01855 {
01856 case takes_regs_uninit:
01857 {
01858 CUMULATIVE_ARGS args_so_far;
01859 tree fn, arg;
01860
01861 fn = emit_block_move_libcall_fn (false);
01862 INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0);
01863
01864 arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
01865 for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
01866 {
01867 enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
01868 rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
01869 if (!tmp || !REG_P (tmp))
01870 goto fail_takes_regs;
01871 #ifdef FUNCTION_ARG_PARTIAL_NREGS
01872 if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode,
01873 NULL_TREE, 1))
01874 goto fail_takes_regs;
01875 #endif
01876 FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
01877 }
01878 }
01879 takes_regs = takes_regs_yes;
01880
01881
01882 case takes_regs_yes:
01883 return true;
01884
01885 fail_takes_regs:
01886 takes_regs = takes_regs_no;
01887
01888 case takes_regs_no:
01889 return false;
01890
01891 default:
01892 abort ();
01893 }
01894 }
01895 }
01896
01897
01898
01899
01900 static bool
01901 emit_block_move_via_movstr (x, y, size, align)
01902 rtx x, y, size;
01903 unsigned int align;
01904 {
01905
01906
01907
01908
01909 rtx opalign = GEN_INT (align / BITS_PER_UNIT);
01910 enum machine_mode mode;
01911
01912
01913 volatile_ok = 1;
01914
01915 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
01916 mode = GET_MODE_WIDER_MODE (mode))
01917 {
01918 enum insn_code code = movstr_optab[(int) mode];
01919 insn_operand_predicate_fn pred;
01920
01921 if (code != CODE_FOR_nothing
01922
01923
01924
01925
01926 && ((GET_CODE (size) == CONST_INT
01927 && ((unsigned HOST_WIDE_INT) INTVAL (size)
01928 <= (GET_MODE_MASK (mode) >> 1)))
01929 || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
01930 && ((pred = insn_data[(int) code].operand[0].predicate) == 0
01931 || (*pred) (x, BLKmode))
01932 && ((pred = insn_data[(int) code].operand[1].predicate) == 0
01933 || (*pred) (y, BLKmode))
01934 && ((pred = insn_data[(int) code].operand[3].predicate) == 0
01935 || (*pred) (opalign, VOIDmode)))
01936 {
01937 rtx op2;
01938 rtx last = get_last_insn ();
01939 rtx pat;
01940
01941 op2 = convert_to_mode (mode, size, 1);
01942 pred = insn_data[(int) code].operand[2].predicate;
01943 if (pred != 0 && ! (*pred) (op2, mode))
01944 op2 = copy_to_mode_reg (mode, op2);
01945
01946
01947
01948
01949
01950
01951 pat = GEN_FCN ((int) code) (x, y, op2, opalign);
01952 if (pat)
01953 {
01954 emit_insn (pat);
01955 volatile_ok = 0;
01956 return true;
01957 }
01958 else
01959 delete_insns_since (last);
01960 }
01961 }
01962
01963 volatile_ok = 0;
01964 return false;
01965 }
01966
01967
01968
01969
01970 static rtx
01971 emit_block_move_via_libcall (dst, src, size)
01972 rtx dst, src, size;
01973 {
01974 tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree;
01975 enum machine_mode size_mode;
01976 rtx retval;
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999 dst = copy_to_mode_reg (Pmode, XEXP (dst, 0));
02000 src = copy_to_mode_reg (Pmode, XEXP (src, 0));
02001
02002 if (TARGET_MEM_FUNCTIONS)
02003 size_mode = TYPE_MODE (sizetype);
02004 else
02005 size_mode = TYPE_MODE (unsigned_type_node);
02006 size = convert_to_mode (size_mode, size, 1);
02007 size = copy_to_mode_reg (size_mode, size);
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017 dst_tree = make_tree (ptr_type_node, dst);
02018 src_tree = make_tree (ptr_type_node, src);
02019 if (TARGET_MEM_FUNCTIONS)
02020 size_tree = make_tree (sizetype, size);
02021 else
02022 size_tree = make_tree (unsigned_type_node, size);
02023
02024 fn = emit_block_move_libcall_fn (true);
02025 arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
02026 if (TARGET_MEM_FUNCTIONS)
02027 {
02028 arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
02029 arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
02030 }
02031 else
02032 {
02033 arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
02034 arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
02035 }
02036
02037
02038 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
02039 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
02040 call_expr, arg_list, NULL_TREE);
02041 TREE_SIDE_EFFECTS (call_expr) = 1;
02042
02043 retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
02044
02045
02046
02047
02048 if (RTX_UNCHANGING_P (dst))
02049 emit_insn (gen_rtx_CLOBBER (VOIDmode, dst));
02050
02051 return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
02052 }
02053
02054
02055
02056
02057
02058 static GTY(()) tree block_move_fn;
02059
02060 void
02061 init_block_move_fn (asmspec)
02062 const char *asmspec;
02063 {
02064 if (!block_move_fn)
02065 {
02066 tree args, fn;
02067
02068 if (TARGET_MEM_FUNCTIONS)
02069 {
02070 fn = get_identifier ("memcpy");
02071 args = build_function_type_list (ptr_type_node, ptr_type_node,
02072 const_ptr_type_node, sizetype,
02073 NULL_TREE);
02074 }
02075 else
02076 {
02077 fn = get_identifier ("bcopy");
02078 args = build_function_type_list (void_type_node, const_ptr_type_node,
02079 ptr_type_node, unsigned_type_node,
02080 NULL_TREE);
02081 }
02082
02083 fn = build_decl (FUNCTION_DECL, fn, args);
02084 DECL_EXTERNAL (fn) = 1;
02085 TREE_PUBLIC (fn) = 1;
02086 DECL_ARTIFICIAL (fn) = 1;
02087 TREE_NOTHROW (fn) = 1;
02088
02089 block_move_fn = fn;
02090 }
02091
02092 if (asmspec)
02093 {
02094 SET_DECL_RTL (block_move_fn, NULL_RTX);
02095 SET_DECL_ASSEMBLER_NAME (block_move_fn, get_identifier (asmspec));
02096 }
02097 }
02098
02099 static tree
02100 emit_block_move_libcall_fn (for_call)
02101 int for_call;
02102 {
02103 static bool emitted_extern;
02104
02105 if (!block_move_fn)
02106 init_block_move_fn (NULL);
02107
02108 if (for_call && !emitted_extern)
02109 {
02110 emitted_extern = true;
02111 make_decl_rtl (block_move_fn, NULL);
02112 assemble_external (block_move_fn);
02113 }
02114
02115 return block_move_fn;
02116 }
02117
02118
02119
02120
02121
02122 static void
02123 emit_block_move_via_loop (x, y, size, align)
02124 rtx x, y, size;
02125 unsigned int align ATTRIBUTE_UNUSED;
02126 {
02127 rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
02128 enum machine_mode iter_mode;
02129
02130 iter_mode = GET_MODE (size);
02131 if (iter_mode == VOIDmode)
02132 iter_mode = word_mode;
02133
02134 top_label = gen_label_rtx ();
02135 cmp_label = gen_label_rtx ();
02136 iter = gen_reg_rtx (iter_mode);
02137
02138 emit_move_insn (iter, const0_rtx);
02139
02140 x_addr = force_operand (XEXP (x, 0), NULL_RTX);
02141 y_addr = force_operand (XEXP (y, 0), NULL_RTX);
02142 do_pending_stack_adjust ();
02143
02144 emit_note (NULL, NOTE_INSN_LOOP_BEG);
02145
02146 emit_jump (cmp_label);
02147 emit_label (top_label);
02148
02149 tmp = convert_modes (Pmode, iter_mode, iter, true);
02150 x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
02151 y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
02152 x = change_address (x, QImode, x_addr);
02153 y = change_address (y, QImode, y_addr);
02154
02155 emit_move_insn (x, y);
02156
02157 tmp = expand_simple_binop (iter_mode, PLUS, iter, const1_rtx, iter,
02158 true, OPTAB_LIB_WIDEN);
02159 if (tmp != iter)
02160 emit_move_insn (iter, tmp);
02161
02162 emit_note (NULL, NOTE_INSN_LOOP_CONT);
02163 emit_label (cmp_label);
02164
02165 emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
02166 true, top_label);
02167
02168 emit_note (NULL, NOTE_INSN_LOOP_END);
02169 }
02170
02171
02172
02173
02174 void
02175 move_block_to_reg (regno, x, nregs, mode)
02176 int regno;
02177 rtx x;
02178 int nregs;
02179 enum machine_mode mode;
02180 {
02181 int i;
02182 #ifdef HAVE_load_multiple
02183 rtx pat;
02184 rtx last;
02185 #endif
02186
02187 if (nregs == 0)
02188 return;
02189
02190 if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
02191 x = validize_mem (force_const_mem (mode, x));
02192
02193
02194 #ifdef HAVE_load_multiple
02195 if (HAVE_load_multiple)
02196 {
02197 last = get_last_insn ();
02198 pat = gen_load_multiple (gen_rtx_REG (word_mode, regno), x,
02199 GEN_INT (nregs));
02200 if (pat)
02201 {
02202 emit_insn (pat);
02203 return;
02204 }
02205 else
02206 delete_insns_since (last);
02207 }
02208 #endif
02209
02210 for (i = 0; i < nregs; i++)
02211 emit_move_insn (gen_rtx_REG (word_mode, regno + i),
02212 operand_subword_force (x, i, mode));
02213 }
02214
02215
02216
02217
02218
02219 void
02220 move_block_from_reg (regno, x, nregs, size)
02221 int regno;
02222 rtx x;
02223 int nregs;
02224 int size;
02225 {
02226 int i;
02227 #ifdef HAVE_store_multiple
02228 rtx pat;
02229 rtx last;
02230 #endif
02231 enum machine_mode mode;
02232
02233 if (nregs == 0)
02234 return;
02235
02236
02237
02238 if (size <= UNITS_PER_WORD
02239 && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
02240 {
02241 emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
02242 return;
02243 }
02244
02245
02246
02247
02248 if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
02249 {
02250 rtx tem = operand_subword (x, 0, 1, BLKmode);
02251 rtx shift;
02252
02253 if (tem == 0)
02254 abort ();
02255
02256 shift = expand_shift (LSHIFT_EXPR, word_mode,
02257 gen_rtx_REG (word_mode, regno),
02258 build_int_2 ((UNITS_PER_WORD - size)
02259 * BITS_PER_UNIT, 0), NULL_RTX, 0);
02260 emit_move_insn (tem, shift);
02261 return;
02262 }
02263
02264
02265 #ifdef HAVE_store_multiple
02266 if (HAVE_store_multiple)
02267 {
02268 last = get_last_insn ();
02269 pat = gen_store_multiple (x, gen_rtx_REG (word_mode, regno),
02270 GEN_INT (nregs));
02271 if (pat)
02272 {
02273 emit_insn (pat);
02274 return;
02275 }
02276 else
02277 delete_insns_since (last);
02278 }
02279 #endif
02280
02281 for (i = 0; i < nregs; i++)
02282 {
02283 rtx tem = operand_subword (x, i, 1, BLKmode);
02284
02285 if (tem == 0)
02286 abort ();
02287
02288 emit_move_insn (tem, gen_rtx_REG (word_mode, regno + i));
02289 }
02290 }
02291
02292
02293
02294
02295
02296
02297
02298 rtx
02299 gen_group_rtx (orig)
02300 rtx orig;
02301 {
02302 int i, length;
02303 rtx *tmps;
02304
02305 if (GET_CODE (orig) != PARALLEL)
02306 abort ();
02307
02308 length = XVECLEN (orig, 0);
02309 tmps = (rtx *) alloca (sizeof (rtx) * length);
02310
02311
02312 i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1;
02313
02314 if (i)
02315 tmps[0] = 0;
02316
02317 for (; i < length; i++)
02318 {
02319 enum machine_mode mode = GET_MODE (XEXP (XVECEXP (orig, 0, i), 0));
02320 rtx offset = XEXP (XVECEXP (orig, 0, i), 1);
02321
02322 tmps[i] = gen_rtx_EXPR_LIST (VOIDmode, gen_reg_rtx (mode), offset);
02323 }
02324
02325 return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
02326 }
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338 void
02339 emit_group_load (dst, orig_src, ssize)
02340 rtx dst, orig_src;
02341 int ssize;
02342 {
02343 rtx *tmps, src;
02344 int start, i;
02345
02346 if (GET_CODE (dst) != PARALLEL)
02347 abort ();
02348
02349
02350
02351 if (XEXP (XVECEXP (dst, 0, 0), 0))
02352 start = 0;
02353 else
02354 start = 1;
02355
02356 tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
02357
02358
02359 for (i = start; i < XVECLEN (dst, 0); i++)
02360 {
02361 enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
02362 HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
02363 unsigned int bytelen = GET_MODE_SIZE (mode);
02364 int shift = 0;
02365
02366
02367 if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
02368 {
02369 shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
02370 bytelen = ssize - bytepos;
02371 if (bytelen <= 0)
02372 abort ();
02373 }
02374
02375
02376
02377
02378 src = orig_src;
02379 if (GET_CODE (orig_src) != MEM
02380 && (!CONSTANT_P (orig_src)
02381 || (GET_MODE (orig_src) != mode
02382 && GET_MODE (orig_src) != VOIDmode)))
02383 {
02384 if (GET_MODE (orig_src) == VOIDmode)
02385 src = gen_reg_rtx (mode);
02386 else
02387 src = gen_reg_rtx (GET_MODE (orig_src));
02388
02389 emit_move_insn (src, orig_src);
02390 }
02391
02392
02393 if (GET_CODE (src) == MEM
02394 && MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode)
02395 && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
02396 && bytelen == GET_MODE_SIZE (mode))
02397 {
02398 tmps[i] = gen_reg_rtx (mode);
02399 emit_move_insn (tmps[i], adjust_address (src, mode, bytepos));
02400 }
02401 else if (GET_CODE (src) == CONCAT)
02402 {
02403 unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
02404 unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
02405
02406 if ((bytepos == 0 && bytelen == slen0)
02407 || (bytepos != 0 && bytepos + bytelen <= slen))
02408 {
02409
02410
02411
02412
02413 tmps[i] = XEXP (src, bytepos / slen0);
02414 if (! CONSTANT_P (tmps[i])
02415 && (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode))
02416 tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
02417 (bytepos % slen0) * BITS_PER_UNIT,
02418 1, NULL_RTX, mode, mode, ssize);
02419 }
02420 else if (bytepos == 0)
02421 {
02422 rtx mem = assign_stack_temp (GET_MODE (src), slen, 0);
02423 emit_move_insn (mem, src);
02424 tmps[i] = adjust_address (mem, mode, 0);
02425 }
02426 else
02427 abort ();
02428 }
02429 else if (CONSTANT_P (src)
02430 || (GET_CODE (src) == REG && GET_MODE (src) == mode))
02431 tmps[i] = src;
02432 else
02433 tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
02434 bytepos * BITS_PER_UNIT, 1, NULL_RTX,
02435 mode, mode, ssize);
02436
02437 if (BYTES_BIG_ENDIAN && shift)
02438 expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
02439 tmps[i], 0, OPTAB_WIDEN);
02440 }
02441
02442 emit_queue ();
02443
02444
02445 for (i = start; i < XVECLEN (dst, 0); i++)
02446 emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
02447 }
02448
02449
02450
02451
02452 void
02453 emit_group_move (dst, src)
02454 rtx dst, src;
02455 {
02456 int i;
02457
02458 if (GET_CODE (src) != PARALLEL
02459 || GET_CODE (dst) != PARALLEL
02460 || XVECLEN (src, 0) != XVECLEN (dst, 0))
02461 abort ();
02462
02463
02464 for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
02465 emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0),
02466 XEXP (XVECEXP (src, 0, i), 0));
02467 }
02468
02469
02470
02471
02472
02473 void
02474 emit_group_store (orig_dst, src, ssize)
02475 rtx orig_dst, src;
02476 int ssize;
02477 {
02478 rtx *tmps, dst;
02479 int start, i;
02480
02481 if (GET_CODE (src) != PARALLEL)
02482 abort ();
02483
02484
02485
02486 if (XEXP (XVECEXP (src, 0, 0), 0))
02487 start = 0;
02488 else
02489 start = 1;
02490
02491 tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0));
02492
02493
02494 for (i = start; i < XVECLEN (src, 0); i++)
02495 {
02496 rtx reg = XEXP (XVECEXP (src, 0, i), 0);
02497 tmps[i] = gen_reg_rtx (GET_MODE (reg));
02498 emit_move_insn (tmps[i], reg);
02499 }
02500 emit_queue ();
02501
02502
02503
02504 dst = orig_dst;
02505 if (GET_CODE (dst) == PARALLEL)
02506 {
02507 rtx temp;
02508
02509
02510
02511
02512 if (rtx_equal_p (dst, src))
02513 return;
02514
02515
02516
02517
02518
02519 temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
02520 emit_group_store (temp, src, ssize);
02521 emit_group_load (dst, temp, ssize);
02522 return;
02523 }
02524 else if (GET_CODE (dst) != MEM && GET_CODE (dst) != CONCAT)
02525 {
02526 dst = gen_reg_rtx (GET_MODE (orig_dst));
02527
02528 emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
02529 }
02530
02531
02532 for (i = start; i < XVECLEN (src, 0); i++)
02533 {
02534 HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
02535 enum machine_mode mode = GET_MODE (tmps[i]);
02536 unsigned int bytelen = GET_MODE_SIZE (mode);
02537 rtx dest = dst;
02538
02539
02540 if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
02541 {
02542 if (BYTES_BIG_ENDIAN)
02543 {
02544 int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
02545 expand_binop (mode, ashr_optab, tmps[i], GEN_INT (shift),
02546 tmps[i], 0, OPTAB_WIDEN);
02547 }
02548 bytelen = ssize - bytepos;
02549 }
02550
02551 if (GET_CODE (dst) == CONCAT)
02552 {
02553 if (bytepos + bytelen <= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
02554 dest = XEXP (dst, 0);
02555 else if (bytepos >= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
02556 {
02557 bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
02558 dest = XEXP (dst, 1);
02559 }
02560 else if (bytepos == 0 && XVECLEN (src, 0))
02561 {
02562 dest = assign_stack_temp (GET_MODE (dest),
02563 GET_MODE_SIZE (GET_MODE (dest)), 0);
02564 emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos),
02565 tmps[i]);
02566 dst = dest;
02567 break;
02568 }
02569 else
02570 abort ();
02571 }
02572
02573
02574 if (GET_CODE (dest) == MEM
02575 && MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)
02576 && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
02577 && bytelen == GET_MODE_SIZE (mode))
02578 emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
02579 else
02580 store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
02581 mode, tmps[i], ssize);
02582 }
02583
02584 emit_queue ();
02585
02586
02587 if (orig_dst != dst)
02588 emit_move_insn (orig_dst, dst);
02589 }
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600 rtx
02601 copy_blkmode_from_reg (tgtblk, srcreg, type)
02602 rtx tgtblk;
02603 rtx srcreg;
02604 tree type;
02605 {
02606 unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
02607 rtx src = NULL, dst = NULL;
02608 unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
02609 unsigned HOST_WIDE_INT bitpos, xbitpos, big_endian_correction = 0;
02610
02611 if (tgtblk == 0)
02612 {
02613 tgtblk = assign_temp (build_qualified_type (type,
02614 (TYPE_QUALS (type)
02615 | TYPE_QUAL_CONST)),
02616 0, 1, 1);
02617 preserve_temp_slots (tgtblk);
02618 }
02619
02620
02621
02622
02623 if (GET_MODE (srcreg) != BLKmode
02624 && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
02625 srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
02626
02627
02628
02629
02630
02631 if (BYTES_BIG_ENDIAN
02632 && bytes % UNITS_PER_WORD)
02633 big_endian_correction
02634 = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
02635
02636
02637
02638
02639
02640
02641 for (bitpos = 0, xbitpos = big_endian_correction;
02642 bitpos < bytes * BITS_PER_UNIT;
02643 bitpos += bitsize, xbitpos += bitsize)
02644 {
02645
02646
02647
02648 if (xbitpos % BITS_PER_WORD == 0
02649 || xbitpos == big_endian_correction)
02650 src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
02651 GET_MODE (srcreg));
02652
02653
02654
02655 if (bitpos % BITS_PER_WORD == 0)
02656 dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
02657
02658
02659
02660 store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
02661 extract_bit_field (src, bitsize,
02662 xbitpos % BITS_PER_WORD, 1,
02663 NULL_RTX, word_mode, word_mode,
02664 BITS_PER_WORD),
02665 BITS_PER_WORD);
02666 }
02667
02668 return tgtblk;
02669 }
02670
02671
02672
02673
02674 void
02675 use_reg (call_fusage, reg)
02676 rtx *call_fusage, reg;
02677 {
02678 if (GET_CODE (reg) != REG
02679 || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
02680 abort ();
02681
02682 *call_fusage
02683 = gen_rtx_EXPR_LIST (VOIDmode,
02684 gen_rtx_USE (VOIDmode, reg), *call_fusage);
02685 }
02686
02687
02688
02689
02690 void
02691 use_regs (call_fusage, regno, nregs)
02692 rtx *call_fusage;
02693 int regno;
02694 int nregs;
02695 {
02696 int i;
02697
02698 if (regno + nregs > FIRST_PSEUDO_REGISTER)
02699 abort ();
02700
02701 for (i = 0; i < nregs; i++)
02702 use_reg (call_fusage, regno_reg_rtx[regno + i]);
02703 }
02704
02705
02706
02707
02708
02709 void
02710 use_group_regs (call_fusage, regs)
02711 rtx *call_fusage;
02712 rtx regs;
02713 {
02714 int i;
02715
02716 for (i = 0; i < XVECLEN (regs, 0); i++)
02717 {
02718 rtx reg = XEXP (XVECEXP (regs, 0, i), 0);
02719
02720
02721
02722
02723 if (reg != 0 && GET_CODE (reg) == REG)
02724 use_reg (call_fusage, reg);
02725 }
02726 }
02727
02728
02729
02730
02731
02732
02733
02734
02735 int
02736 can_store_by_pieces (len, constfun, constfundata, align)
02737 unsigned HOST_WIDE_INT len;
02738 rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
02739 PTR constfundata;
02740 unsigned int align;
02741 {
02742 unsigned HOST_WIDE_INT max_size, l;
02743 HOST_WIDE_INT offset = 0;
02744 enum machine_mode mode, tmode;
02745 enum insn_code icode;
02746 int reverse;
02747 rtx cst;
02748
02749 if (len == 0)
02750 return 1;
02751
02752 if (! MOVE_BY_PIECES_P (len, align))
02753 return 0;
02754
02755 if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
02756 || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
02757 align = MOVE_MAX * BITS_PER_UNIT;
02758
02759
02760
02761
02762 for (reverse = 0;
02763 reverse <= (HAVE_PRE_DECREMENT || HAVE_POST_DECREMENT);
02764 reverse++)
02765 {
02766 l = len;
02767 mode = VOIDmode;
02768 max_size = STORE_MAX_PIECES + 1;
02769 while (max_size > 1)
02770 {
02771 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02772 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02773 if (GET_MODE_SIZE (tmode) < max_size)
02774 mode = tmode;
02775
02776 if (mode == VOIDmode)
02777 break;
02778
02779 icode = mov_optab->handlers[(int) mode].insn_code;
02780 if (icode != CODE_FOR_nothing
02781 && align >= GET_MODE_ALIGNMENT (mode))
02782 {
02783 unsigned int size = GET_MODE_SIZE (mode);
02784
02785 while (l >= size)
02786 {
02787 if (reverse)
02788 offset -= size;
02789
02790 cst = (*constfun) (constfundata, offset, mode);
02791 if (!LEGITIMATE_CONSTANT_P (cst))
02792 return 0;
02793
02794 if (!reverse)
02795 offset += size;
02796
02797 l -= size;
02798 }
02799 }
02800
02801 max_size = GET_MODE_SIZE (mode);
02802 }
02803
02804
02805 if (l != 0)
02806 abort ();
02807 }
02808
02809 return 1;
02810 }
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820 rtx
02821 store_by_pieces (to, len, constfun, constfundata, align, endp)
02822 rtx to;
02823 unsigned HOST_WIDE_INT len;
02824 rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
02825 PTR constfundata;
02826 unsigned int align;
02827 int endp;
02828 {
02829 struct store_by_pieces data;
02830
02831 if (len == 0)
02832 {
02833 if (endp == 2)
02834 abort ();
02835 return to;
02836 }
02837
02838 if (! MOVE_BY_PIECES_P (len, align))
02839 abort ();
02840 to = protect_from_queue (to, 1);
02841 data.constfun = constfun;
02842 data.constfundata = constfundata;
02843 data.len = len;
02844 data.to = to;
02845 store_by_pieces_1 (&data, align);
02846 if (endp)
02847 {
02848 rtx to1;
02849
02850 if (data.reverse)
02851 abort ();
02852 if (data.autinc_to)
02853 {
02854 if (endp == 2)
02855 {
02856 if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
02857 emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
02858 else
02859 data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
02860 -1));
02861 }
02862 to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
02863 data.offset);
02864 }
02865 else
02866 {
02867 if (endp == 2)
02868 --data.offset;
02869 to1 = adjust_address (data.to, QImode, data.offset);
02870 }
02871 return to1;
02872 }
02873 else
02874 return data.to;
02875 }
02876
02877
02878
02879
02880
02881 static void
02882 clear_by_pieces (to, len, align)
02883 rtx to;
02884 unsigned HOST_WIDE_INT len;
02885 unsigned int align;
02886 {
02887 struct store_by_pieces data;
02888
02889 if (len == 0)
02890 return;
02891
02892 data.constfun = clear_by_pieces_1;
02893 data.constfundata = NULL;
02894 data.len = len;
02895 data.to = to;
02896 store_by_pieces_1 (&data, align);
02897 }
02898
02899
02900
02901
02902 static rtx
02903 clear_by_pieces_1 (data, offset, mode)
02904 PTR data ATTRIBUTE_UNUSED;
02905 HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
02906 enum machine_mode mode ATTRIBUTE_UNUSED;
02907 {
02908 return const0_rtx;
02909 }
02910
02911
02912
02913
02914
02915
02916 static void
02917 store_by_pieces_1 (data, align)
02918 struct store_by_pieces *data;
02919 unsigned int align;
02920 {
02921 rtx to_addr = XEXP (data->to, 0);
02922 unsigned HOST_WIDE_INT max_size = STORE_MAX_PIECES + 1;
02923 enum machine_mode mode = VOIDmode, tmode;
02924 enum insn_code icode;
02925
02926 data->offset = 0;
02927 data->to_addr = to_addr;
02928 data->autinc_to
02929 = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
02930 || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
02931
02932 data->explicit_inc_to = 0;
02933 data->reverse
02934 = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
02935 if (data->reverse)
02936 data->offset = data->len;
02937
02938
02939
02940
02941 if (!data->autinc_to
02942 && move_by_pieces_ninsns (data->len, align) > 2)
02943 {
02944
02945 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02946 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02947 if (GET_MODE_SIZE (tmode) < max_size)
02948 mode = tmode;
02949
02950 if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
02951 {
02952 data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
02953 data->autinc_to = 1;
02954 data->explicit_inc_to = -1;
02955 }
02956
02957 if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
02958 && ! data->autinc_to)
02959 {
02960 data->to_addr = copy_addr_to_reg (to_addr);
02961 data->autinc_to = 1;
02962 data->explicit_inc_to = 1;
02963 }
02964
02965 if ( !data->autinc_to && CONSTANT_P (to_addr))
02966 data->to_addr = copy_addr_to_reg (to_addr);
02967 }
02968
02969 if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
02970 || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
02971 align = MOVE_MAX * BITS_PER_UNIT;
02972
02973
02974
02975
02976 while (max_size > 1)
02977 {
02978 for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
02979 tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
02980 if (GET_MODE_SIZE (tmode) < max_size)
02981 mode = tmode;
02982
02983 if (mode == VOIDmode)
02984 break;
02985
02986 icode = mov_optab->handlers[(int) mode].insn_code;
02987 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
02988 store_by_pieces_2 (GEN_FCN (icode), mode, data);
02989
02990 max_size = GET_MODE_SIZE (mode);
02991 }
02992
02993
02994 if (data->len != 0)
02995 abort ();
02996 }
02997
02998
02999
03000
03001
03002 static void
03003 store_by_pieces_2 (genfun, mode, data)
03004 rtx (*genfun) PARAMS ((rtx, ...));
03005 enum machine_mode mode;
03006 struct store_by_pieces *data;
03007 {
03008 unsigned int size = GET_MODE_SIZE (mode);
03009 rtx to1, cst;
03010
03011 while (data->len >= size)
03012 {
03013 if (data->reverse)
03014 data->offset -= size;
03015
03016 if (data->autinc_to)
03017 to1 = adjust_automodify_address (data->to, mode, data->to_addr,
03018 data->offset);
03019 else
03020 to1 = adjust_address (data->to, mode, data->offset);
03021
03022 if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
03023 emit_insn (gen_add2_insn (data->to_addr,
03024 GEN_INT (-(HOST_WIDE_INT) size)));
03025
03026 cst = (*data->constfun) (data->constfundata, data->offset, mode);
03027 emit_insn ((*genfun) (to1, cst));
03028
03029 if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
03030 emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
03031
03032 if (! data->reverse)
03033 data->offset += size;
03034
03035 data->len -= size;
03036 }
03037 }
03038
03039
03040
03041
03042 rtx
03043 clear_storage (object, size)
03044 rtx object;
03045 rtx size;
03046 {
03047 rtx retval = 0;
03048 unsigned int align = (GET_CODE (object) == MEM ? MEM_ALIGN (object)
03049 : GET_MODE_ALIGNMENT (GET_MODE (object)));
03050
03051
03052
03053 if (GET_MODE (object) != BLKmode
03054 && GET_CODE (size) == CONST_INT
03055 && INTVAL (size) == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (object)))
03056 emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
03057 else
03058 {
03059 object = protect_from_queue (object, 1);
03060 size = protect_from_queue (size, 0);
03061
03062 if (size == const0_rtx)
03063 ;
03064 else if (GET_CODE (size) == CONST_INT
03065 && CLEAR_BY_PIECES_P (INTVAL (size), align))
03066 clear_by_pieces (object, INTVAL (size), align);
03067 else if (clear_storage_via_clrstr (object, size, align))
03068 ;
03069 else
03070 retval = clear_storage_via_libcall (object, size);
03071 }
03072
03073 return retval;
03074 }
03075
03076
03077
03078
03079 static bool
03080 clear_storage_via_clrstr (object, size, align)
03081 rtx object, size;
03082 unsigned int align;
03083 {
03084
03085
03086
03087
03088 rtx opalign = GEN_INT (align / BITS_PER_UNIT);
03089 enum machine_mode mode;
03090
03091 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
03092 mode = GET_MODE_WIDER_MODE (mode))
03093 {
03094 enum insn_code code = clrstr_optab[(int) mode];
03095 insn_operand_predicate_fn pred;
03096
03097 if (code != CODE_FOR_nothing
03098
03099
03100
03101
03102 && ((GET_CODE (size) == CONST_INT
03103 && ((unsigned HOST_WIDE_INT) INTVAL (size)
03104 <= (GET_MODE_MASK (mode) >> 1)))
03105 || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
03106 && ((pred = insn_data[(int) code].operand[0].predicate) == 0
03107 || (*pred) (object, BLKmode))
03108 && ((pred = insn_data[(int) code].operand[2].predicate) == 0
03109 || (*pred) (opalign, VOIDmode)))
03110 {
03111 rtx op1;
03112 rtx last = get_last_insn ();
03113 rtx pat;
03114
03115 op1 = convert_to_mode (mode, size, 1);
03116 pred = insn_data[(int) code].operand[1].predicate;
03117 if (pred != 0 && ! (*pred) (op1, mode))
03118 op1 = copy_to_mode_reg (mode, op1);
03119
03120 pat = GEN_FCN ((int) code) (object, op1, opalign);
03121 if (pat)
03122 {
03123 emit_insn (pat);
03124 return true;
03125 }
03126 else
03127 delete_insns_since (last);
03128 }
03129 }
03130
03131 return false;
03132 }
03133
03134
03135
03136
03137 static rtx
03138 clear_storage_via_libcall (object, size)
03139 rtx object, size;
03140 {
03141 tree call_expr, arg_list, fn, object_tree, size_tree;
03142 enum machine_mode size_mode;
03143 rtx retval;
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166 object = copy_to_mode_reg (Pmode, XEXP (object, 0));
03167
03168 if (TARGET_MEM_FUNCTIONS)
03169 size_mode = TYPE_MODE (sizetype);
03170 else
03171 size_mode = TYPE_MODE (unsigned_type_node);
03172 size = convert_to_mode (size_mode, size, 1);
03173 size = copy_to_mode_reg (size_mode, size);
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183 object_tree = make_tree (ptr_type_node, object);
03184 if (TARGET_MEM_FUNCTIONS)
03185 size_tree = make_tree (sizetype, size);
03186 else
03187 size_tree = make_tree (unsigned_type_node, size);
03188
03189 fn = clear_storage_libcall_fn (true);
03190 arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
03191 if (TARGET_MEM_FUNCTIONS)
03192 arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
03193 arg_list = tree_cons (NULL_TREE, object_tree, arg_list);
03194
03195
03196 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
03197 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
03198 call_expr, arg_list, NULL_TREE);
03199 TREE_SIDE_EFFECTS (call_expr) = 1;
03200
03201 retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
03202
03203
03204
03205
03206 if (RTX_UNCHANGING_P (object))
03207 emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
03208
03209 return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
03210 }
03211
03212
03213
03214
03215
03216 static GTY(()) tree block_clear_fn;
03217
03218 void
03219 init_block_clear_fn (asmspec)
03220 const char *asmspec;
03221 {
03222 if (!block_clear_fn)
03223 {
03224 tree fn, args;
03225
03226 if (TARGET_MEM_FUNCTIONS)
03227 {
03228 fn = get_identifier ("memset");
03229 args = build_function_type_list (ptr_type_node, ptr_type_node,
03230 integer_type_node, sizetype,
03231 NULL_TREE);
03232 }
03233 else
03234 {
03235 fn = get_identifier ("bzero");
03236 args = build_function_type_list (void_type_node, ptr_type_node,
03237 unsigned_type_node, NULL_TREE);
03238 }
03239
03240 fn = build_decl (FUNCTION_DECL, fn, args);
03241 DECL_EXTERNAL (fn) = 1;
03242 TREE_PUBLIC (fn) = 1;
03243 DECL_ARTIFICIAL (fn) = 1;
03244 TREE_NOTHROW (fn) = 1;
03245
03246 block_clear_fn = fn;
03247 }
03248
03249 if (asmspec)
03250 {
03251 SET_DECL_RTL (block_clear_fn, NULL_RTX);
03252 SET_DECL_ASSEMBLER_NAME (block_clear_fn, get_identifier (asmspec));
03253 }
03254 }
03255
03256 static tree
03257 clear_storage_libcall_fn (for_call)
03258 int for_call;
03259 {
03260 static bool emitted_extern;
03261
03262 if (!block_clear_fn)
03263 init_block_clear_fn (NULL);
03264
03265 if (for_call && !emitted_extern)
03266 {
03267 emitted_extern = true;
03268 make_decl_rtl (block_clear_fn, NULL);
03269 assemble_external (block_clear_fn);
03270 }
03271
03272 return block_clear_fn;
03273 }
03274
03275
03276
03277
03278
03279
03280
03281
03282 rtx
03283 emit_move_insn (x, y)
03284 rtx x, y;
03285 {
03286 enum machine_mode mode = GET_MODE (x);
03287 rtx y_cst = NULL_RTX;
03288 rtx last_insn;
03289
03290 x = protect_from_queue (x, 1);
03291 y = protect_from_queue (y, 0);
03292
03293 #ifndef KEY
03294 if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
03295 abort ();
03296 #endif
03297
03298
03299 if (GET_CODE (y) == CONSTANT_P_RTX)
03300 ;
03301 else if (CONSTANT_P (y))
03302 {
03303 if (optimize
03304 && SCALAR_FLOAT_MODE_P (GET_MODE (x))
03305 && (last_insn = compress_float_constant (x, y)))
03306 return last_insn;
03307
03308 if (!LEGITIMATE_CONSTANT_P (y))
03309 {
03310 y_cst = y;
03311 y = force_const_mem (mode, y);
03312
03313
03314
03315
03316 if (!y)
03317 y = y_cst;
03318 }
03319 }
03320
03321
03322
03323 if (GET_CODE (x) == MEM
03324 && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
03325 && ! push_operand (x, GET_MODE (x)))
03326 || (flag_force_addr
03327 && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
03328 x = validize_mem (x);
03329
03330 if (GET_CODE (y) == MEM
03331 && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
03332 || (flag_force_addr
03333 && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
03334 y = validize_mem (y);
03335
03336 if (mode == BLKmode)
03337 abort ();
03338
03339 last_insn = emit_move_insn_1 (x, y);
03340
03341 if (y_cst && GET_CODE (x) == REG)
03342 set_unique_reg_note (last_insn, REG_EQUAL, y_cst);
03343
03344 return last_insn;
03345 }
03346
03347
03348
03349
03350
03351 rtx
03352 emit_move_insn_1 (x, y)
03353 rtx x, y;
03354 {
03355 enum machine_mode mode = GET_MODE (x);
03356 enum machine_mode submode;
03357 enum mode_class class = GET_MODE_CLASS (mode);
03358
03359 if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
03360 abort ();
03361
03362 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
03363 return
03364 emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
03365
03366
03367 else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
03368 && BLKmode != (submode = GET_MODE_INNER (mode))
03369 && (mov_optab->handlers[(int) submode].insn_code
03370 != CODE_FOR_nothing))
03371 {
03372
03373 int stack = push_operand (x, GET_MODE (x));
03374
03375 #ifdef PUSH_ROUNDING
03376
03377
03378 if (stack
03379 && (PUSH_ROUNDING (GET_MODE_SIZE (submode))
03380 != GET_MODE_SIZE (submode)))
03381 {
03382 rtx temp;
03383 HOST_WIDE_INT offset1, offset2;
03384
03385
03386
03387 temp = expand_binop (Pmode,
03388 #ifdef STACK_GROWS_DOWNWARD
03389 sub_optab,
03390 #else
03391 add_optab,
03392 #endif
03393 stack_pointer_rtx,
03394 GEN_INT
03395 (PUSH_ROUNDING
03396 (GET_MODE_SIZE (GET_MODE (x)))),
03397 stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
03398
03399 if (temp != stack_pointer_rtx)
03400 emit_move_insn (stack_pointer_rtx, temp);
03401
03402 #ifdef STACK_GROWS_DOWNWARD
03403 offset1 = 0;
03404 offset2 = GET_MODE_SIZE (submode);
03405 #else
03406 offset1 = -PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)));
03407 offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
03408 + GET_MODE_SIZE (submode));
03409 #endif
03410
03411 emit_move_insn (change_address (x, submode,
03412 gen_rtx_PLUS (Pmode,
03413 stack_pointer_rtx,
03414 GEN_INT (offset1))),
03415 gen_realpart (submode, y));
03416 emit_move_insn (change_address (x, submode,
03417 gen_rtx_PLUS (Pmode,
03418 stack_pointer_rtx,
03419 GEN_INT (offset2))),
03420 gen_imagpart (submode, y));
03421 }
03422 else
03423 #endif
03424
03425
03426
03427
03428
03429 if (stack)
03430 {
03431
03432
03433 #ifdef STACK_GROWS_DOWNWARD
03434 emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03435 (gen_rtx_MEM (submode, XEXP (x, 0)),
03436 gen_imagpart (submode, y)));
03437 emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03438 (gen_rtx_MEM (submode, XEXP (x, 0)),
03439 gen_realpart (submode, y)));
03440 #else
03441 emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03442 (gen_rtx_MEM (submode, XEXP (x, 0)),
03443 gen_realpart (submode, y)));
03444 emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03445 (gen_rtx_MEM (submode, XEXP (x, 0)),
03446 gen_imagpart (submode, y)));
03447 #endif
03448 }
03449 else
03450 {
03451 rtx realpart_x, realpart_y;
03452 rtx imagpart_x, imagpart_y;
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463 if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
03464 && (reload_in_progress | reload_completed) == 0)
03465 {
03466 int packed_dest_p
03467 = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
03468 int packed_src_p
03469 = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
03470
03471 if (packed_dest_p || packed_src_p)
03472 {
03473 enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
03474 ? MODE_FLOAT : MODE_INT);
03475
03476 enum machine_mode reg_mode
03477 = mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
03478
03479 if (reg_mode != BLKmode)
03480 {
03481 rtx mem = assign_stack_temp (reg_mode,
03482 GET_MODE_SIZE (mode), 0);
03483 rtx cmem = adjust_address (mem, mode, 0);
03484
03485 cfun->cannot_inline
03486 = N_("function using short complex types cannot be inline");
03487
03488 if (packed_dest_p)
03489 {
03490 rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
03491
03492 emit_move_insn_1 (cmem, y);
03493 return emit_move_insn_1 (sreg, mem);
03494 }
03495 else
03496 {
03497 rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
03498
03499 emit_move_insn_1 (mem, sreg);
03500 return emit_move_insn_1 (x, cmem);
03501 }
03502 }
03503 }
03504 }
03505
03506 realpart_x = gen_realpart (submode, x);
03507 realpart_y = gen_realpart (submode, y);
03508 imagpart_x = gen_imagpart (submode, x);
03509 imagpart_y = gen_imagpart (submode, y);
03510
03511
03512
03513
03514
03515 if (x != y
03516 && ! (reload_in_progress || reload_completed)
03517 && (GET_CODE (realpart_x) == SUBREG
03518 || GET_CODE (imagpart_x) == SUBREG))
03519 emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
03520
03521 emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03522 (realpart_x, realpart_y));
03523 emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
03524 (imagpart_x, imagpart_y));
03525 }
03526
03527 return get_last_insn ();
03528 }
03529
03530
03531
03532
03533 else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
03534 {
03535 rtx last_insn = 0;
03536 rtx seq, inner;
03537 int need_clobber;
03538 int i;
03539
03540 #ifdef PUSH_ROUNDING
03541
03542
03543
03544 if (push_operand (x, GET_MODE (x)))
03545 {
03546 rtx temp;
03547 enum rtx_code code;
03548
03549
03550
03551 temp = expand_binop (Pmode,
03552 #ifdef STACK_GROWS_DOWNWARD
03553 sub_optab,
03554 #else
03555 add_optab,
03556 #endif
03557 stack_pointer_rtx,
03558 GEN_INT
03559 (PUSH_ROUNDING
03560 (GET_MODE_SIZE (GET_MODE (x)))),
03561 stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
03562
03563 if (temp != stack_pointer_rtx)
03564 emit_move_insn (stack_pointer_rtx, temp);
03565
03566 code = GET_CODE (XEXP (x, 0));
03567
03568
03569 if (code == POST_INC)
03570 temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03571 GEN_INT (-((HOST_WIDE_INT)
03572 GET_MODE_SIZE (GET_MODE (x)))));
03573 else if (code == POST_DEC)
03574 temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03575 GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
03576 else
03577 temp = stack_pointer_rtx;
03578
03579 x = change_address (x, VOIDmode, temp);
03580 }
03581 #endif
03582
03583
03584
03585 if (reload_in_progress && GET_CODE (x) == MEM
03586 && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
03587 x = replace_equiv_address_nv (x, inner);
03588 if (reload_in_progress && GET_CODE (y) == MEM
03589 && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
03590 y = replace_equiv_address_nv (y, inner);
03591
03592 start_sequence ();
03593
03594 need_clobber = 0;
03595 for (i = 0;
03596 i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
03597 i++)
03598 {
03599 rtx xpart = operand_subword (x, i, 1, mode);
03600 rtx ypart = operand_subword (y, i, 1, mode);
03601
03602
03603
03604
03605 if (ypart == 0 && CONSTANT_P (y))
03606 {
03607 y = force_const_mem (mode, y);
03608 ypart = operand_subword (y, i, 1, mode);
03609 }
03610 else if (ypart == 0)
03611 ypart = operand_subword_force (y, i, mode);
03612
03613 if (xpart == 0 || ypart == 0)
03614 abort ();
03615
03616 need_clobber |= (GET_CODE (xpart) == SUBREG);
03617
03618 last_insn = emit_move_insn (xpart, ypart);
03619 }
03620
03621 seq = get_insns ();
03622 end_sequence ();
03623
03624
03625
03626
03627
03628 if (x != y
03629 && ! (reload_in_progress || reload_completed)
03630 && need_clobber != 0)
03631 emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
03632
03633 emit_insn (seq);
03634
03635 return last_insn;
03636 }
03637 else
03638 abort ();
03639 }
03640
03641
03642
03643
03644
03645 static rtx
03646 compress_float_constant (x, y)
03647 rtx x, y;
03648 {
03649 enum machine_mode dstmode = GET_MODE (x);
03650 enum machine_mode orig_srcmode = GET_MODE (y);
03651 enum machine_mode srcmode;
03652 REAL_VALUE_TYPE r;
03653
03654 REAL_VALUE_FROM_CONST_DOUBLE (r, y);
03655
03656 for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
03657 srcmode != orig_srcmode;
03658 srcmode = GET_MODE_WIDER_MODE (srcmode))
03659 {
03660 enum insn_code ic;
03661 rtx trunc_y, last_insn;
03662
03663
03664 ic = can_extend_p (dstmode, srcmode, 0);
03665 if (ic == CODE_FOR_nothing)
03666 continue;
03667
03668
03669 if (! exact_real_truncate (srcmode, &r))
03670 continue;
03671
03672 trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
03673
03674 if (LEGITIMATE_CONSTANT_P (trunc_y))
03675 {
03676
03677
03678 if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
03679 continue;
03680 }
03681 else if (float_extend_from_mem[dstmode][srcmode])
03682 trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
03683 else
03684 continue;
03685
03686 emit_unop_insn (ic, x, trunc_y, UNKNOWN);
03687 last_insn = get_last_insn ();
03688
03689 if (GET_CODE (x) == REG)
03690 REG_NOTES (last_insn)
03691 = gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));
03692
03693 return last_insn;
03694 }
03695
03696 return NULL_RTX;
03697 }
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710 rtx
03711 push_block (size, extra, below)
03712 rtx size;
03713 int extra, below;
03714 {
03715 rtx temp;
03716
03717 size = convert_modes (Pmode, ptr_mode, size, 1);
03718 if (CONSTANT_P (size))
03719 anti_adjust_stack (plus_constant (size, extra));
03720 else if (GET_CODE (size) == REG && extra == 0)
03721 anti_adjust_stack (size);
03722 else
03723 {
03724 temp = copy_to_mode_reg (Pmode, size);
03725 if (extra != 0)
03726 temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
03727 temp, 0, OPTAB_LIB_WIDEN);
03728 anti_adjust_stack (temp);
03729 }
03730
03731 #ifndef STACK_GROWS_DOWNWARD
03732 if (0)
03733 #else
03734 if (1)
03735 #endif
03736 {
03737 temp = virtual_outgoing_args_rtx;
03738 if (extra != 0 && below)
03739 temp = plus_constant (temp, extra);
03740 }
03741 else
03742 {
03743 if (GET_CODE (size) == CONST_INT)
03744 temp = plus_constant (virtual_outgoing_args_rtx,
03745 -INTVAL (size) - (below ? 0 : extra));
03746 else if (extra != 0 && !below)
03747 temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
03748 negate_rtx (Pmode, plus_constant (size, extra)));
03749 else
03750 temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
03751 negate_rtx (Pmode, size));
03752 }
03753
03754 return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
03755 }
03756
03757 #ifdef PUSH_ROUNDING
03758
03759
03760
03761 static void
03762 emit_single_push_insn (mode, x, type)
03763 rtx x;
03764 enum machine_mode mode;
03765 tree type;
03766 {
03767 rtx dest_addr;
03768 unsigned rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
03769 rtx dest;
03770 enum insn_code icode;
03771 insn_operand_predicate_fn pred;
03772
03773 stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
03774
03775
03776 icode = push_optab->handlers[(int) mode].insn_code;
03777 if (icode != CODE_FOR_nothing)
03778 {
03779 if (((pred = insn_data[(int) icode].operand[0].predicate)
03780 && !((*pred) (x, mode))))
03781 x = force_reg (mode, x);
03782 emit_insn (GEN_FCN (icode) (x));
03783 return;
03784 }
03785 if (GET_MODE_SIZE (mode) == rounded_size)
03786 dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
03787 else
03788 {
03789 #ifdef STACK_GROWS_DOWNWARD
03790 dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03791 GEN_INT (-(HOST_WIDE_INT) rounded_size));
03792 #else
03793 dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
03794 GEN_INT (rounded_size));
03795 #endif
03796 dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
03797 }
03798
03799 dest = gen_rtx_MEM (mode, dest_addr);
03800
03801 if (type != 0)
03802 {
03803 set_mem_attributes (dest, type, 1);
03804
03805 if (flag_optimize_sibling_calls)
03806
03807
03808
03809
03810 set_mem_alias_set (dest, 0);
03811 }
03812 emit_move_insn (dest, x);
03813 }
03814 #endif
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848 void
03849 emit_push_insn (x, mode, type, size, align, partial, reg, extra,
03850 args_addr, args_so_far, reg_parm_stack_space,
03851 alignment_pad)
03852 rtx x;
03853 enum machine_mode mode;
03854 tree type;
03855 rtx size;
03856 unsigned int align;
03857 int partial;
03858 rtx reg;
03859 int extra;
03860 rtx args_addr;
03861 rtx args_so_far;
03862 int reg_parm_stack_space;
03863 rtx alignment_pad;
03864 {
03865 rtx xinner;
03866 enum direction stack_direction
03867 #ifdef STACK_GROWS_DOWNWARD
03868 = downward;
03869 #else
03870 = upward;
03871 #endif
03872
03873
03874
03875
03876 enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
03877
03878
03879
03880 if (STACK_PUSH_CODE == POST_DEC)
03881 if (where_pad != none)
03882 where_pad = (where_pad == downward ? upward : downward);
03883
03884 xinner = x = protect_from_queue (x, 0);
03885
03886 if (mode == BLKmode)
03887 {
03888
03889
03890 rtx temp;
03891 int used = partial * UNITS_PER_WORD;
03892 int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
03893 int skip;
03894
03895 if (size == 0)
03896 abort ();
03897
03898 used -= offset;
03899
03900
03901
03902
03903 if (partial != 0)
03904 xinner = adjust_address (xinner, BLKmode, used);
03905
03906
03907
03908
03909
03910 skip = (reg_parm_stack_space == 0) ? 0 : used;
03911
03912 #ifdef PUSH_ROUNDING
03913
03914
03915
03916 if (args_addr == 0
03917 && PUSH_ARGS
03918 && GET_CODE (size) == CONST_INT
03919 && skip == 0
03920 && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
03921
03922
03923
03924 && ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
03925 || align >= BIGGEST_ALIGNMENT
03926 || (PUSH_ROUNDING (align / BITS_PER_UNIT)
03927 == (align / BITS_PER_UNIT)))
03928 && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
03929 {
03930
03931
03932
03933 if (extra && args_addr == 0
03934 && where_pad != none && where_pad != stack_direction)
03935 anti_adjust_stack (GEN_INT (extra));
03936
03937 move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0);
03938 }
03939 else
03940 #endif
03941 {
03942 rtx target;
03943
03944
03945
03946
03947
03948 if (partial != 0)
03949 {
03950 if (GET_CODE (size) == CONST_INT)
03951 size = GEN_INT (INTVAL (size) - used);
03952 else
03953 size = expand_binop (GET_MODE (size), sub_optab, size,
03954 GEN_INT (used), NULL_RTX, 0,
03955 OPTAB_LIB_WIDEN);
03956 }
03957
03958
03959
03960
03961 if (! args_addr)
03962 {
03963 temp = push_block (size, extra, where_pad == downward);
03964 extra = 0;
03965 }
03966 else if (GET_CODE (args_so_far) == CONST_INT)
03967 temp = memory_address (BLKmode,
03968 plus_constant (args_addr,
03969 skip + INTVAL (args_so_far)));
03970 else
03971 temp = memory_address (BLKmode,
03972 plus_constant (gen_rtx_PLUS (Pmode,
03973 args_addr,
03974 args_so_far),
03975 skip));
03976
03977 if (!ACCUMULATE_OUTGOING_ARGS)
03978 {
03979
03980
03981
03982
03983 if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
03984 || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
03985 temp = copy_to_reg (temp);
03986 }
03987
03988 target = gen_rtx_MEM (BLKmode, temp);
03989
03990 if (type != 0)
03991 {
03992 set_mem_attributes (target, type, 1);
03993
03994
03995
03996
03997 set_mem_alias_set (target, 0);
03998 }
03999
04000
04001
04002 set_mem_align (target, align);
04003
04004 emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
04005 }
04006 }
04007 else if (partial > 0)
04008 {
04009
04010
04011 int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
04012 int i;
04013 int not_stack;
04014
04015
04016 int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
04017 int args_offset = INTVAL (args_so_far);
04018 int skip;
04019
04020
04021
04022
04023 if (extra && args_addr == 0
04024 && where_pad != none && where_pad != stack_direction)
04025 anti_adjust_stack (GEN_INT (extra));
04026
04027
04028
04029
04030 if (args_addr == 0)
04031 offset = 0;
04032
04033
04034
04035 not_stack = partial - offset;
04036
04037
04038
04039
04040
04041 skip = (reg_parm_stack_space == 0) ? 0 : not_stack;
04042
04043 if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
04044 x = validize_mem (force_const_mem (mode, x));
04045
04046
04047
04048 if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER
04049 && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))
04050 x = copy_to_reg (x);
04051
04052
04053
04054
04055 #ifndef PUSH_ARGS_REVERSED
04056 for (i = not_stack; i < size; i++)
04057 #else
04058 for (i = size - 1; i >= not_stack; i--)
04059 #endif
04060 if (i >= not_stack + offset)
04061 emit_push_insn (operand_subword_force (x, i, mode),
04062 word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
04063 0, args_addr,
04064 GEN_INT (args_offset + ((i - not_stack + skip)
04065 * UNITS_PER_WORD)),
04066 reg_parm_stack_space, alignment_pad);
04067 }
04068 else
04069 {
04070 rtx addr;
04071 rtx target = NULL_RTX;
04072 rtx dest;
04073
04074
04075
04076
04077 if (extra && args_addr == 0
04078 && where_pad != none && where_pad != stack_direction)
04079 anti_adjust_stack (GEN_INT (extra));
04080
04081 #ifdef PUSH_ROUNDING
04082 if (args_addr == 0 && PUSH_ARGS)
04083 emit_single_push_insn (mode, x, type);
04084 else
04085 #endif
04086 {
04087 if (GET_CODE (args_so_far) == CONST_INT)
04088 addr
04089 = memory_address (mode,
04090 plus_constant (args_addr,
04091 INTVAL (args_so_far)));
04092 else
04093 addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
04094 args_so_far));
04095 target = addr;
04096 dest = gen_rtx_MEM (mode, addr);
04097 if (type != 0)
04098 {
04099 set_mem_attributes (dest, type, 1);
04100
04101
04102
04103
04104 set_mem_alias_set (dest, 0);
04105 }
04106
04107 emit_move_insn (dest, x);
04108 }
04109 }
04110
04111
04112
04113
04114 if (partial > 0 && reg != 0)
04115 {
04116
04117
04118 if (GET_CODE (reg) == PARALLEL)
04119 emit_group_load (reg, x, -1);
04120 else
04121 move_block_to_reg (REGNO (reg), x, partial, mode);
04122 }
04123
04124 if (extra && args_addr == 0 && where_pad == stack_direction)
04125 anti_adjust_stack (GEN_INT (extra));
04126
04127 if (alignment_pad && args_addr == 0)
04128 anti_adjust_stack (alignment_pad);
04129 }
04130
04131
04132
04133
04134 static rtx
04135 get_subtarget (x)
04136 rtx x;
04137 {
04138 return ((x == 0
04139
04140 || GET_CODE (x) != REG
04141
04142 || RTX_UNCHANGING_P (x)
04143
04144 || REGNO (x) < FIRST_PSEUDO_REGISTER
04145
04146
04147 || preserve_subexpressions_p ())
04148 ? 0 : x);
04149 }
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162 rtx
04163 expand_assignment (to, from, want_value, suggest_reg)
04164 tree to, from;
04165 int want_value;
04166 int suggest_reg ATTRIBUTE_UNUSED;
04167 {
04168 rtx to_rtx = 0;
04169 rtx result;
04170
04171
04172
04173 if (TREE_CODE (to) == ERROR_MARK)
04174 {
04175 result = expand_expr (from, NULL_RTX, VOIDmode, 0);
04176 return want_value ? result : NULL_RTX;
04177 }
04178
04179
04180
04181
04182
04183
04184
04185 if (TREE_CODE (to) == COMPONENT_REF || TREE_CODE (to) == BIT_FIELD_REF
04186 || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF
04187 || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
04188 {
04189 enum machine_mode mode1;
04190 HOST_WIDE_INT bitsize, bitpos;
04191 rtx orig_to_rtx;
04192 tree offset;
04193 int unsignedp;
04194 int volatilep = 0;
04195 tree tem;
04196
04197 push_temp_slots ();
04198 tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
04199 &unsignedp, &volatilep);
04200
04201
04202
04203
04204 if (mode1 == VOIDmode && want_value)
04205 tem = stabilize_reference (tem);
04206
04207 orig_to_rtx = to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
04208
04209 if (offset != 0)
04210 {
04211 rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
04212
04213 if (GET_CODE (to_rtx) != MEM)
04214 abort ();
04215
04216 #ifdef POINTERS_EXTEND_UNSIGNED
04217 if (GET_MODE (offset_rtx) != Pmode)
04218 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
04219 #else
04220 if (GET_MODE (offset_rtx) != ptr_mode)
04221 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
04222 #endif
04223
04224
04225
04226 if (GET_CODE (to_rtx) == MEM
04227 && GET_MODE (to_rtx) == BLKmode
04228 && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
04229 && bitsize > 0
04230 && (bitpos % bitsize) == 0
04231 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
04232 && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
04233 {
04234 to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
04235 bitpos = 0;
04236 }
04237
04238 to_rtx = offset_address (to_rtx, offset_rtx,
04239 highest_pow2_factor_for_type (TREE_TYPE (to),
04240 offset));
04241 }
04242
04243 if (GET_CODE (to_rtx) == MEM)
04244 {
04245
04246
04247 to_rtx = shallow_copy_rtx (to_rtx);
04248
04249 set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
04250 }
04251
04252
04253
04254 if (volatilep && GET_CODE (to_rtx) == MEM)
04255 {
04256 if (to_rtx == orig_to_rtx)
04257 to_rtx = copy_rtx (to_rtx);
04258 MEM_VOLATILE_P (to_rtx) = 1;
04259 }
04260
04261 if (TREE_CODE (to) == COMPONENT_REF
04262 && TREE_READONLY (TREE_OPERAND (to, 1)))
04263 {
04264 if (to_rtx == orig_to_rtx)
04265 to_rtx = copy_rtx (to_rtx);
04266 RTX_UNCHANGING_P (to_rtx) = 1;
04267 }
04268
04269 if (GET_CODE (to_rtx) == MEM && ! can_address_p (to))
04270 {
04271 if (to_rtx == orig_to_rtx)
04272 to_rtx = copy_rtx (to_rtx);
04273 MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
04274 }
04275
04276 result = store_field (to_rtx, bitsize, bitpos, mode1, from,
04277 (want_value
04278
04279 ? ((enum machine_mode)
04280 TYPE_MODE (TREE_TYPE (to)))
04281 : VOIDmode),
04282 unsignedp, TREE_TYPE (tem), get_alias_set (to));
04283
04284 preserve_temp_slots (result);
04285 free_temp_slots ();
04286 pop_temp_slots ();
04287
04288
04289
04290 return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
04291 TYPE_MODE (TREE_TYPE (from)),
04292 result,
04293 TREE_UNSIGNED (TREE_TYPE (to)))
04294 : NULL_RTX);
04295 }
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307 if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from)
04308 && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
04309 && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
04310 && GET_CODE (DECL_RTL (to)) == REG))
04311 {
04312 rtx value;
04313
04314 push_temp_slots ();
04315 value = expand_expr (from, NULL_RTX, VOIDmode, 0);
04316 if (to_rtx == 0)
04317 to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
04318
04319
04320
04321 if (GET_CODE (to_rtx) == PARALLEL)
04322 emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
04323 else if (GET_MODE (to_rtx) == BLKmode)
04324 emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
04325 else
04326 {
04327 #ifdef POINTERS_EXTEND_UNSIGNED
04328 if (POINTER_TYPE_P (TREE_TYPE (to))
04329 && GET_MODE (to_rtx) != GET_MODE (value))
04330 value = convert_memory_address (GET_MODE (to_rtx), value);
04331 #endif
04332 emit_move_insn (to_rtx, value);
04333 }
04334 preserve_temp_slots (to_rtx);
04335 free_temp_slots ();
04336 pop_temp_slots ();
04337 return want_value ? to_rtx : NULL_RTX;
04338 }
04339
04340
04341
04342
04343 if (to_rtx == 0)
04344 to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
04345
04346
04347 if (TREE_CODE (to) == RESULT_DECL
04348 && (GET_CODE (to_rtx) == REG || GET_CODE (to_rtx) == PARALLEL))
04349 {
04350 rtx temp;
04351
04352 push_temp_slots ();
04353 temp = expand_expr (from, 0, GET_MODE (to_rtx), 0);
04354
04355 if (GET_CODE (to_rtx) == PARALLEL)
04356 emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)));
04357 else
04358 emit_move_insn (to_rtx, temp);
04359
04360 preserve_temp_slots (to_rtx);
04361 free_temp_slots ();
04362 pop_temp_slots ();
04363 return want_value ? to_rtx : NULL_RTX;
04364 }
04365
04366
04367
04368
04369 if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
04370 && current_function_returns_struct
04371 && !current_function_returns_pcc_struct)
04372 {
04373 rtx from_rtx, size;
04374
04375 push_temp_slots ();
04376 size = expr_size (from);
04377 from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
04378
04379 if (TARGET_MEM_FUNCTIONS)
04380 emit_library_call (memmove_libfunc, LCT_NORMAL,
04381 VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
04382 XEXP (from_rtx, 0), Pmode,
04383 convert_to_mode (TYPE_MODE (sizetype),
04384 size, TREE_UNSIGNED (sizetype)),
04385 TYPE_MODE (sizetype));
04386 else
04387 emit_library_call (bcopy_libfunc, LCT_NORMAL,
04388 VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
04389 XEXP (to_rtx, 0), Pmode,
04390 convert_to_mode (TYPE_MODE (integer_type_node),
04391 size,
04392 TREE_UNSIGNED (integer_type_node)),
04393 TYPE_MODE (integer_type_node));
04394
04395 preserve_temp_slots (to_rtx);
04396 free_temp_slots ();
04397 pop_temp_slots ();
04398 return want_value ? to_rtx : NULL_RTX;
04399 }
04400
04401
04402
04403 push_temp_slots ();
04404 result = store_expr (from, to_rtx, want_value);
04405 preserve_temp_slots (result);
04406 free_temp_slots ();
04407 pop_temp_slots ();
04408 return want_value ? result : NULL_RTX;
04409 }
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437 rtx
04438 store_expr (exp, target, want_value)
04439 tree exp;
04440 rtx target;
04441 int want_value;
04442 {
04443 rtx temp;
04444 int dont_return_target = 0;
04445 int dont_store_target = 0;
04446
04447 if (VOID_TYPE_P (TREE_TYPE (exp)))
04448 {
04449
04450
04451
04452 if (want_value)
04453 abort ();
04454 expand_expr (exp, const0_rtx, VOIDmode, 0);
04455 return NULL_RTX;
04456 }
04457 if (TREE_CODE (exp) == COMPOUND_EXPR)
04458 {
04459
04460
04461 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
04462 want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04463 emit_queue ();
04464 return store_expr (TREE_OPERAND (exp, 1), target, want_value);
04465 }
04466 else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
04467 {
04468
04469
04470
04471
04472
04473 rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
04474
04475 emit_queue ();
04476 target = protect_from_queue (target, 1);
04477
04478 do_pending_stack_adjust ();
04479 NO_DEFER_POP;
04480 jumpifnot (TREE_OPERAND (exp, 0), lab1);
04481 start_cleanup_deferral ();
04482 store_expr (TREE_OPERAND (exp, 1), target, want_value & 2);
04483 end_cleanup_deferral ();
04484 emit_queue ();
04485 emit_jump_insn (gen_jump (lab2));
04486 emit_barrier ();
04487 emit_label (lab1);
04488 start_cleanup_deferral ();
04489 store_expr (TREE_OPERAND (exp, 2), target, want_value & 2);
04490 end_cleanup_deferral ();
04491 emit_queue ();
04492 emit_label (lab2);
04493 OK_DEFER_POP;
04494
04495 return want_value & 1 ? target : NULL_RTX;
04496 }
04497 else if (queued_subexp_p (target))
04498
04499
04500 {
04501 if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
04502 {
04503
04504 temp = gen_reg_rtx (GET_MODE (target));
04505 temp = expand_expr (exp, temp, GET_MODE (target),
04506 (want_value & 2
04507 ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04508 }
04509 else
04510 temp = expand_expr (exp, NULL_RTX, GET_MODE (target),
04511 (want_value & 2
04512 ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04513
04514
04515
04516
04517 if (! MEM_VOLATILE_P (target) && (want_value & 1) != 0)
04518 dont_return_target = 1;
04519 }
04520 else if ((want_value & 1) != 0
04521 && GET_CODE (target) == MEM
04522 && ! MEM_VOLATILE_P (target)
04523 && GET_MODE (target) != BLKmode)
04524
04525
04526
04527
04528
04529
04530 {
04531 temp = expand_expr (exp, target, GET_MODE (target),
04532 want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04533 if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
04534 {
04535
04536
04537 if (temp == target
04538 || (rtx_equal_p (temp, target)
04539 && ! side_effects_p (temp) && ! side_effects_p (target)))
04540 dont_store_target = 1;
04541 temp = copy_to_reg (temp);
04542 }
04543 dont_return_target = 1;
04544 }
04545 else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
04546
04547
04548
04549
04550 {
04551 rtx inner_target = 0;
04552
04553
04554
04555
04556
04557
04558
04559 if ((want_value & 1) == 0
04560 && INTEGRAL_TYPE_P (TREE_TYPE (exp))
04561 && TREE_TYPE (TREE_TYPE (exp)) == 0)
04562 {
04563 if (TREE_UNSIGNED (TREE_TYPE (exp))
04564 != SUBREG_PROMOTED_UNSIGNED_P (target))
04565 exp = convert
04566 ((*lang_hooks.types.signed_or_unsigned_type)
04567 (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
04568
04569 exp = convert ((*lang_hooks.types.type_for_mode)
04570 (GET_MODE (SUBREG_REG (target)),
04571 SUBREG_PROMOTED_UNSIGNED_P (target)),
04572 exp);
04573
04574 inner_target = SUBREG_REG (target);
04575 }
04576
04577 temp = expand_expr (exp, inner_target, VOIDmode,
04578 want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04579
04580
04581
04582
04583 if (GET_CODE (temp) == MEM && (want_value & 1) != 0
04584 && (MEM_VOLATILE_P (temp)
04585 || reg_mentioned_p (SUBREG_REG (target), XEXP (temp, 0))))
04586 temp = copy_to_reg (temp);
04587
04588
04589
04590 if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
04591 {
04592 temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
04593 temp, SUBREG_PROMOTED_UNSIGNED_P (target));
04594 temp = convert_modes (GET_MODE (SUBREG_REG (target)),
04595 GET_MODE (target), temp,
04596 SUBREG_PROMOTED_UNSIGNED_P (target));
04597 }
04598
04599 convert_move (SUBREG_REG (target), temp,
04600 SUBREG_PROMOTED_UNSIGNED_P (target));
04601
04602
04603
04604
04605
04606 if ((want_value & 1) != 0 && GET_MODE (temp) != GET_MODE (target))
04607 {
04608 if (GET_MODE (temp) != VOIDmode)
04609 {
04610 temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
04611 SUBREG_PROMOTED_VAR_P (temp) = 1;
04612 SUBREG_PROMOTED_UNSIGNED_SET (temp,
04613 SUBREG_PROMOTED_UNSIGNED_P (target));
04614 }
04615 else
04616 temp = convert_modes (GET_MODE (target),
04617 GET_MODE (SUBREG_REG (target)),
04618 temp, SUBREG_PROMOTED_UNSIGNED_P (target));
04619 }
04620
04621 return want_value & 1 ? temp : NULL_RTX;
04622 }
04623 else
04624 {
04625 temp = expand_expr (exp, target, GET_MODE (target),
04626 want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
04627
04628
04629
04630
04631
04632
04633
04634 if (!(target && GET_CODE (target) == REG
04635 && REGNO (target) < FIRST_PSEUDO_REGISTER)
04636 && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
04637 && ! rtx_equal_p (temp, target)
04638 && (CONSTANT_P (temp) || (want_value & 1) != 0))
04639 dont_return_target = 1;
04640 }
04641
04642
04643
04644
04645
04646 if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
04647 && TREE_CODE (exp) != ERROR_MARK
04648 && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
04649 temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
04650 temp, TREE_UNSIGNED (TREE_TYPE (exp)));
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666 if ((! rtx_equal_p (temp, target)
04667 || (temp != target && (side_effects_p (temp)
04668 || side_effects_p (target))))
04669 && TREE_CODE (exp) != ERROR_MARK
04670 && ! dont_store_target
04671
04672
04673
04674 && (TREE_CODE_CLASS (TREE_CODE (exp)) != 'd'
04675 || target != DECL_RTL_IF_SET (exp))
04676
04677
04678
04679
04680 && expr_size (exp) != const0_rtx)
04681 {
04682 target = protect_from_queue (target, 1);
04683 if (GET_MODE (temp) != GET_MODE (target)
04684 && GET_MODE (temp) != VOIDmode)
04685 {
04686 int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
04687 if (dont_return_target)
04688 {
04689
04690
04691
04692 temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
04693 emit_move_insn (target, temp);
04694 }
04695 else
04696 convert_move (target, temp, unsignedp);
04697 }
04698
04699 else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
04700 {
04701
04702
04703
04704
04705 rtx size = expr_size (exp);
04706
04707 if (GET_CODE (size) == CONST_INT
04708 && INTVAL (size) < TREE_STRING_LENGTH (exp))
04709 emit_block_move (target, temp, size,
04710 (want_value & 2
04711 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04712 else
04713 {
04714
04715 tree copy_size
04716 = size_binop (MIN_EXPR,
04717 make_tree (sizetype, size),
04718 size_int (TREE_STRING_LENGTH (exp)));
04719 rtx copy_size_rtx
04720 = expand_expr (copy_size, NULL_RTX, VOIDmode,
04721 (want_value & 2
04722 ? EXPAND_STACK_PARM : EXPAND_NORMAL));
04723 rtx label = 0;
04724
04725
04726 copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
04727 TREE_UNSIGNED (sizetype));
04728 emit_block_move (target, temp, copy_size_rtx,
04729 (want_value & 2
04730 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04731
04732
04733
04734 if (GET_CODE (copy_size_rtx) == CONST_INT)
04735 {
04736 size = plus_constant (size, -INTVAL (copy_size_rtx));
04737 target = adjust_address (target, BLKmode,
04738 INTVAL (copy_size_rtx));
04739 }
04740 else
04741 {
04742 size = expand_binop (TYPE_MODE (sizetype), sub_optab, size,
04743 copy_size_rtx, NULL_RTX, 0,
04744 OPTAB_LIB_WIDEN);
04745
04746 #ifdef POINTERS_EXTEND_UNSIGNED
04747 if (GET_MODE (copy_size_rtx) != Pmode)
04748 copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx,
04749 TREE_UNSIGNED (sizetype));
04750 #endif
04751
04752 target = offset_address (target, copy_size_rtx,
04753 highest_pow2_factor (copy_size));
04754 label = gen_label_rtx ();
04755 emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
04756 GET_MODE (size), 0, label);
04757 }
04758
04759 if (size != const0_rtx)
04760 clear_storage (target, size);
04761
04762 if (label)
04763 emit_label (label);
04764 }
04765 }
04766
04767
04768 else if (GET_CODE (target) == PARALLEL)
04769 emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
04770 else if (GET_MODE (temp) == BLKmode)
04771 emit_block_move (target, temp, expr_size (exp),
04772 (want_value & 2
04773 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
04774 else
04775 emit_move_insn (target, temp);
04776 }
04777
04778
04779 if ((want_value & 1) == 0)
04780 return NULL_RTX;
04781
04782
04783
04784 else if (dont_return_target && GET_CODE (temp) != MEM)
04785 return temp;
04786
04787
04788 else if ((want_value & 1) != 0
04789 && GET_MODE (target) != BLKmode
04790 && ! (GET_CODE (target) == REG
04791 && REGNO (target) < FIRST_PSEUDO_REGISTER))
04792 return copy_to_reg (target);
04793
04794 else
04795 return target;
04796 }
04797
04798
04799
04800 static int
04801 is_zeros_p (exp)
04802 tree exp;
04803 {
04804 tree elt;
04805
04806 switch (TREE_CODE (exp))
04807 {
04808 case CONVERT_EXPR:
04809 case NOP_EXPR:
04810 case NON_LVALUE_EXPR:
04811 case VIEW_CONVERT_EXPR:
04812 return is_zeros_p (TREE_OPERAND (exp, 0));
04813
04814 case INTEGER_CST:
04815 return integer_zerop (exp);
04816
04817 case COMPLEX_CST:
04818 return
04819 is_zeros_p (TREE_REALPART (exp)) && is_zeros_p (TREE_IMAGPART (exp));
04820
04821 case REAL_CST:
04822 return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0);
04823
04824 case VECTOR_CST:
04825 for (elt = TREE_VECTOR_CST_ELTS (exp); elt;
04826 elt = TREE_CHAIN (elt))
04827 if (!is_zeros_p (TREE_VALUE (elt)))
04828 return 0;
04829
04830 return 1;
04831
04832 case CONSTRUCTOR:
04833 if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
04834 return CONSTRUCTOR_ELTS (exp) == NULL_TREE;
04835 for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
04836 if (! is_zeros_p (TREE_VALUE (elt)))
04837 return 0;
04838
04839 return 1;
04840
04841 default:
04842 return 0;
04843 }
04844 }
04845
04846
04847
04848 static int
04849 mostly_zeros_p (exp)
04850 tree exp;
04851 {
04852 if (TREE_CODE (exp) == CONSTRUCTOR)
04853 {
04854 int elts = 0, zeros = 0;
04855 tree elt = CONSTRUCTOR_ELTS (exp);
04856 if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
04857 {
04858
04859 return elt == NULL_TREE;
04860 }
04861 for (; elt; elt = TREE_CHAIN (elt))
04862 {
04863
04864
04865
04866
04867
04868 if (mostly_zeros_p (TREE_VALUE (elt)))
04869 zeros++;
04870 elts++;
04871 }
04872
04873 return 4 * zeros >= 3 * elts;
04874 }
04875
04876 return is_zeros_p (exp);
04877 }
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890 static void
04891 store_constructor_field (target, bitsize, bitpos, mode, exp, type, cleared,
04892 alias_set)
04893 rtx target;
04894 unsigned HOST_WIDE_INT bitsize;
04895 HOST_WIDE_INT bitpos;
04896 enum machine_mode mode;
04897 tree exp, type;
04898 int cleared;
04899 int alias_set;
04900 {
04901 if (TREE_CODE (exp) == CONSTRUCTOR
04902 && bitpos % BITS_PER_UNIT == 0
04903
04904
04905
04906 && (bitpos == 0 || GET_CODE (target) == MEM))
04907 {
04908 if (GET_CODE (target) == MEM)
04909 target
04910 = adjust_address (target,
04911 GET_MODE (target) == BLKmode
04912 || 0 != (bitpos
04913 % GET_MODE_ALIGNMENT (GET_MODE (target)))
04914 ? BLKmode : VOIDmode, bitpos / BITS_PER_UNIT);
04915
04916
04917
04918 if (GET_CODE (target) == MEM && ! MEM_KEEP_ALIAS_SET_P (target)
04919 && MEM_ALIAS_SET (target) != 0)
04920 {
04921 target = copy_rtx (target);
04922 set_mem_alias_set (target, alias_set);
04923 }
04924
04925 store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
04926 }
04927 else
04928 store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
04929 alias_set);
04930 }
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940 static void
04941 store_constructor (exp, target, cleared, size)
04942 tree exp;
04943 rtx target;
04944 int cleared;
04945 HOST_WIDE_INT size;
04946 {
04947 tree type = TREE_TYPE (exp);
04948 #ifdef WORD_REGISTER_OPERATIONS
04949 HOST_WIDE_INT exp_size = int_size_in_bytes (type);
04950 #endif
04951
04952 if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
04953 || TREE_CODE (type) == QUAL_UNION_TYPE)
04954 {
04955 tree elt;
04956
04957
04958 if (size == 0 || cleared)
04959 cleared = 1;
04960
04961 else if ((TREE_CODE (type) == UNION_TYPE
04962 || TREE_CODE (type) == QUAL_UNION_TYPE)
04963 && ! CONSTRUCTOR_ELTS (exp))
04964
04965 {
04966 clear_storage (target, expr_size (exp));
04967 cleared = 1;
04968 }
04969
04970
04971
04972
04973
04974 else if (GET_CODE (target) == REG && TREE_STATIC (exp)
04975 && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
04976 {
04977 emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
04978 cleared = 1;
04979 }
04980
04981
04982
04983
04984
04985
04986 else if (((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type))
04987 || mostly_zeros_p (exp))
04988 && (GET_CODE (target) != REG
04989 || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
04990 == size)))
04991 {
04992 clear_storage (target, GEN_INT (size));
04993 cleared = 1;
04994 }
04995
04996 if (! cleared)
04997 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
04998
04999
05000
05001
05002 for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
05003 {
05004 tree field = TREE_PURPOSE (elt);
05005 tree value = TREE_VALUE (elt);
05006 enum machine_mode mode;
05007 HOST_WIDE_INT bitsize;
05008 HOST_WIDE_INT bitpos = 0;
05009 int unsignedp;
05010 tree offset;
05011 rtx to_rtx = target;
05012
05013
05014
05015
05016 if (field == 0)
05017 continue;
05018
05019 if (cleared && is_zeros_p (value))
05020 continue;
05021
05022 if (host_integerp (DECL_SIZE (field), 1))
05023 bitsize = tree_low_cst (DECL_SIZE (field), 1);
05024 else
05025 bitsize = -1;
05026
05027 unsignedp = TREE_UNSIGNED (field);
05028 mode = DECL_MODE (field);
05029 if (DECL_BIT_FIELD (field))
05030 mode = VOIDmode;
05031
05032 offset = DECL_FIELD_OFFSET (field);
05033 if (host_integerp (offset, 0)
05034 && host_integerp (bit_position (field), 0))
05035 {
05036 bitpos = int_bit_position (field);
05037 offset = 0;
05038 }
05039 else
05040 bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
05041
05042 if (offset)
05043 {
05044 rtx offset_rtx;
05045
05046 if (contains_placeholder_p (offset))
05047 offset = build (WITH_RECORD_EXPR, sizetype,
05048 offset, make_tree (TREE_TYPE (exp), target));
05049
05050 offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
05051 if (GET_CODE (to_rtx) != MEM)
05052 abort ();
05053
05054 #ifdef POINTERS_EXTEND_UNSIGNED
05055 if (GET_MODE (offset_rtx) != Pmode)
05056 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
05057 #else
05058 if (GET_MODE (offset_rtx) != ptr_mode)
05059 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
05060 #endif
05061
05062 to_rtx = offset_address (to_rtx, offset_rtx,
05063 highest_pow2_factor (offset));
05064 }
05065
05066 if (TREE_READONLY (field))
05067 {
05068 if (GET_CODE (to_rtx) == MEM)
05069 to_rtx = copy_rtx (to_rtx);
05070
05071 RTX_UNCHANGING_P (to_rtx) = 1;
05072 }
05073
05074 #ifdef WORD_REGISTER_OPERATIONS
05075
05076
05077
05078
05079 if (GET_CODE (target) == REG
05080 && bitsize < BITS_PER_WORD
05081 && bitpos % BITS_PER_WORD == 0
05082 && GET_MODE_CLASS (mode) == MODE_INT
05083 && TREE_CODE (value) == INTEGER_CST
05084 && exp_size >= 0
05085 && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
05086 {
05087 tree type = TREE_TYPE (value);
05088
05089 if (TYPE_PRECISION (type) < BITS_PER_WORD)
05090 {
05091 type = (*lang_hooks.types.type_for_size)
05092 (BITS_PER_WORD, TREE_UNSIGNED (type));
05093 value = convert (type, value);
05094 }
05095
05096 if (BYTES_BIG_ENDIAN)
05097 value
05098 = fold (build (LSHIFT_EXPR, type, value,
05099 build_int_2 (BITS_PER_WORD - bitsize, 0)));
05100 bitsize = BITS_PER_WORD;
05101 mode = word_mode;
05102 }
05103 #endif
05104
05105 if (GET_CODE (to_rtx) == MEM && !MEM_KEEP_ALIAS_SET_P (to_rtx)
05106 && DECL_NONADDRESSABLE_P (field))
05107 {
05108 to_rtx = copy_rtx (to_rtx);
05109 MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
05110 }
05111
05112 store_constructor_field (to_rtx, bitsize, bitpos, mode,
05113 value, type, cleared,
05114 get_alias_set (TREE_TYPE (field)));
05115 }
05116 }
05117 else if (TREE_CODE (type) == ARRAY_TYPE
05118 || TREE_CODE (type) == VECTOR_TYPE)
05119 {
05120 tree elt;
05121 int i;
05122 int need_to_clear;
05123 tree domain = TYPE_DOMAIN (type);
05124 tree elttype = TREE_TYPE (type);
05125 int const_bounds_p;
05126 HOST_WIDE_INT minelt = 0;
05127 HOST_WIDE_INT maxelt = 0;
05128
05129
05130
05131 if (TREE_CODE (type) == VECTOR_TYPE)
05132 {
05133
05134
05135
05136 domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
05137 domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
05138 }
05139
05140 const_bounds_p = (TYPE_MIN_VALUE (domain)
05141 && TYPE_MAX_VALUE (domain)
05142 && host_integerp (TYPE_MIN_VALUE (domain), 0)
05143 && host_integerp (TYPE_MAX_VALUE (domain), 0));
05144
05145
05146 if (const_bounds_p)
05147 {
05148 minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
05149 maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
05150 }
05151
05152
05153
05154
05155 if (cleared || (GET_CODE (target) == REG && TREE_STATIC (exp)))
05156 need_to_clear = 1;
05157 else
05158 {
05159 HOST_WIDE_INT count = 0, zero_count = 0;
05160 need_to_clear = ! const_bounds_p;
05161
05162
05163
05164
05165 for (elt = CONSTRUCTOR_ELTS (exp);
05166 elt != NULL_TREE && ! need_to_clear;
05167 elt = TREE_CHAIN (elt))
05168 {
05169 tree index = TREE_PURPOSE (elt);
05170 HOST_WIDE_INT this_node_count;
05171
05172 if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
05173 {
05174 tree lo_index = TREE_OPERAND (index, 0);
05175 tree hi_index = TREE_OPERAND (index, 1);
05176
05177 if (! host_integerp (lo_index, 1)
05178 || ! host_integerp (hi_index, 1))
05179 {
05180 need_to_clear = 1;
05181 break;
05182 }
05183
05184 this_node_count = (tree_low_cst (hi_index, 1)
05185 - tree_low_cst (lo_index, 1) + 1);
05186 }
05187 else
05188 this_node_count = 1;
05189
05190 count += this_node_count;
05191 if (mostly_zeros_p (TREE_VALUE (elt)))
05192 zero_count += this_node_count;
05193 }
05194
05195
05196
05197 if (! need_to_clear
05198 && (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
05199 need_to_clear = 1;
05200 }
05201
05202 if (need_to_clear && size > 0)
05203 {
05204 if (! cleared)
05205 {
05206 if (REG_P (target))
05207 emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
05208 else
05209 clear_storage (target, GEN_INT (size));
05210 }
05211 cleared = 1;
05212 }
05213 else if (REG_P (target))
05214
05215 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
05216
05217
05218
05219
05220 for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
05221 elt;
05222 elt = TREE_CHAIN (elt), i++)
05223 {
05224 enum machine_mode mode;
05225 HOST_WIDE_INT bitsize;
05226 HOST_WIDE_INT bitpos;
05227 int unsignedp;
05228 tree value = TREE_VALUE (elt);
05229 tree index = TREE_PURPOSE (elt);
05230 rtx xtarget = target;
05231
05232 if (cleared && is_zeros_p (value))
05233 continue;
05234
05235 unsignedp = TREE_UNSIGNED (elttype);
05236 mode = TYPE_MODE (elttype);
05237 if (mode == BLKmode)
05238 bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
05239 ? tree_low_cst (TYPE_SIZE (elttype), 1)
05240 : -1);
05241 else
05242 bitsize = GET_MODE_BITSIZE (mode);
05243
05244 if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
05245 {
05246 tree lo_index = TREE_OPERAND (index, 0);
05247 tree hi_index = TREE_OPERAND (index, 1);
05248 rtx index_r, pos_rtx, hi_r, loop_top, loop_end;
05249 struct nesting *loop;
05250 HOST_WIDE_INT lo, hi, count;
05251 tree position;
05252
05253
05254 if (const_bounds_p
05255 && host_integerp (lo_index, 0)
05256 && host_integerp (hi_index, 0)
05257 && (lo = tree_low_cst (lo_index, 0),
05258 hi = tree_low_cst (hi_index, 0),
05259 count = hi - lo + 1,
05260 (GET_CODE (target) != MEM
05261 || count <= 2
05262 || (host_integerp (TYPE_SIZE (elttype), 1)
05263 && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
05264 <= 40 * 8)))))
05265 {
05266 lo -= minelt; hi -= minelt;
05267 for (; lo <= hi; lo++)
05268 {
05269 bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
05270
05271 if (GET_CODE (target) == MEM
05272 && !MEM_KEEP_ALIAS_SET_P (target)
05273 && TREE_CODE (type) == ARRAY_TYPE
05274 && TYPE_NONALIASED_COMPONENT (type))
05275 {
05276 target = copy_rtx (target);
05277 MEM_KEEP_ALIAS_SET_P (target) = 1;
05278 }
05279
05280 store_constructor_field
05281 (target, bitsize, bitpos, mode, value, type, cleared,
05282 get_alias_set (elttype));
05283 }
05284 }
05285 else
05286 {
05287 hi_r = expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
05288 loop_top = gen_label_rtx ();
05289 loop_end = gen_label_rtx ();
05290
05291 unsignedp = TREE_UNSIGNED (domain);
05292
05293 index = build_decl (VAR_DECL, NULL_TREE, domain);
05294
05295 index_r
05296 = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
05297 &unsignedp, 0));
05298 SET_DECL_RTL (index, index_r);
05299 if (TREE_CODE (value) == SAVE_EXPR
05300 && SAVE_EXPR_RTL (value) == 0)
05301 {
05302
05303
05304 expand_expr (value, const0_rtx, VOIDmode, 0);
05305 emit_queue ();
05306 }
05307 store_expr (lo_index, index_r, 0);
05308 loop = expand_start_loop (0);
05309
05310
05311 position
05312 = convert (ssizetype,
05313 fold (build (MINUS_EXPR, TREE_TYPE (index),
05314 index, TYPE_MIN_VALUE (domain))));
05315 position = size_binop (MULT_EXPR, position,
05316 convert (ssizetype,
05317 TYPE_SIZE_UNIT (elttype)));
05318
05319 pos_rtx = expand_expr (position, 0, VOIDmode, 0);
05320 xtarget = offset_address (target, pos_rtx,
05321 highest_pow2_factor (position));
05322 xtarget = adjust_address (xtarget, mode, 0);
05323 if (TREE_CODE (value) == CONSTRUCTOR)
05324 store_constructor (value, xtarget, cleared,
05325 bitsize / BITS_PER_UNIT);
05326 else
05327 store_expr (value, xtarget, 0);
05328
05329 expand_exit_loop_if_false (loop,
05330 build (LT_EXPR, integer_type_node,
05331 index, hi_index));
05332
05333 expand_increment (build (PREINCREMENT_EXPR,
05334 TREE_TYPE (index),
05335 index, integer_one_node), 0, 0);
05336 expand_end_loop ();
05337 emit_label (loop_end);
05338 }
05339 }
05340 else if ((index != 0 && ! host_integerp (index, 0))
05341 || ! host_integerp (TYPE_SIZE (elttype), 1))
05342 {
05343 tree position;
05344
05345 if (index == 0)
05346 index = ssize_int (1);
05347
05348 if (minelt)
05349 index = convert (ssizetype,
05350 fold (build (MINUS_EXPR, index,
05351 TYPE_MIN_VALUE (domain))));
05352
05353 position = size_binop (MULT_EXPR, index,
05354 convert (ssizetype,
05355 TYPE_SIZE_UNIT (elttype)));
05356 xtarget = offset_address (target,
05357 expand_expr (position, 0, VOIDmode, 0),
05358 highest_pow2_factor (position));
05359 xtarget = adjust_address (xtarget, mode, 0);
05360 store_expr (value, xtarget, 0);
05361 }
05362 else
05363 {
05364 if (index != 0)
05365 bitpos = ((tree_low_cst (index, 0) - minelt)
05366 * tree_low_cst (TYPE_SIZE (elttype), 1));
05367 else
05368 bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
05369
05370 if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target)
05371 && TREE_CODE (type) == ARRAY_TYPE
05372 && TYPE_NONALIASED_COMPONENT (type))
05373 {
05374 target = copy_rtx (target);
05375 MEM_KEEP_ALIAS_SET_P (target) = 1;
05376 }
05377
05378 store_constructor_field (target, bitsize, bitpos, mode, value,
05379 type, cleared, get_alias_set (elttype));
05380
05381 }
05382 }
05383 }
05384
05385
05386 else if (TREE_CODE (type) == SET_TYPE)
05387 {
05388 tree elt = CONSTRUCTOR_ELTS (exp);
05389 unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
05390 tree domain = TYPE_DOMAIN (type);
05391 tree domain_min, domain_max, bitlength;
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404 if (elt == NULL_TREE && size > 0)
05405 {
05406 if (!cleared)
05407 clear_storage (target, GEN_INT (size));
05408 return;
05409 }
05410
05411 domain_min = convert (sizetype, TYPE_MIN_VALUE (domain));
05412 domain_max = convert (sizetype, TYPE_MAX_VALUE (domain));
05413 bitlength = size_binop (PLUS_EXPR,
05414 size_diffop (domain_max, domain_min),
05415 ssize_int (1));
05416
05417 nbits = tree_low_cst (bitlength, 1);
05418
05419
05420
05421
05422 if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
05423 || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
05424 {
05425 unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
05426 enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
05427 char *bit_buffer = (char *) alloca (nbits);
05428 HOST_WIDE_INT word = 0;
05429 unsigned int bit_pos = 0;
05430 unsigned int ibit = 0;
05431 unsigned int offset = 0;
05432
05433 elt = get_set_constructor_bits (exp, bit_buffer, nbits);
05434 for (;;)
05435 {
05436 if (bit_buffer[ibit])
05437 {
05438 if (BYTES_BIG_ENDIAN)
05439 word |= (1 << (set_word_size - 1 - bit_pos));
05440 else
05441 word |= 1 << bit_pos;
05442 }
05443
05444 bit_pos++; ibit++;
05445 if (bit_pos >= set_word_size || ibit == nbits)
05446 {
05447 if (word != 0 || ! cleared)
05448 {
05449 rtx datum = GEN_INT (word);
05450 rtx to_rtx;
05451
05452
05453
05454
05455 if (GET_CODE (target) == MEM)
05456 to_rtx = adjust_address (target, mode, offset);
05457 else if (offset == 0)
05458 to_rtx = target;
05459 else
05460 abort ();
05461 emit_move_insn (to_rtx, datum);
05462 }
05463
05464 if (ibit == nbits)
05465 break;
05466 word = 0;
05467 bit_pos = 0;
05468 offset += set_word_size / BITS_PER_UNIT;
05469 }
05470 }
05471 }
05472 else if (!cleared)
05473
05474 if (TREE_CHAIN (elt) != NULL_TREE
05475 || (TREE_PURPOSE (elt) == NULL_TREE
05476 ? nbits != 1
05477 : ( ! host_integerp (TREE_VALUE (elt), 0)
05478 || ! host_integerp (TREE_PURPOSE (elt), 0)
05479 || (tree_low_cst (TREE_VALUE (elt), 0)
05480 - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
05481 != (HOST_WIDE_INT) nbits))))
05482 clear_storage (target, expr_size (exp));
05483
05484 for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
05485 {
05486
05487 tree startbit = TREE_PURPOSE (elt);
05488
05489 tree endbit = TREE_VALUE (elt);
05490 HOST_WIDE_INT startb, endb;
05491 rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
05492
05493 bitlength_rtx = expand_expr (bitlength,
05494 NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
05495
05496
05497 if (startbit == NULL_TREE)
05498 {
05499 startbit = save_expr (endbit);
05500 endbit = startbit;
05501 }
05502
05503 startbit = convert (sizetype, startbit);
05504 endbit = convert (sizetype, endbit);
05505 if (! integer_zerop (domain_min))
05506 {
05507 startbit = size_binop (MINUS_EXPR, startbit, domain_min);
05508 endbit = size_binop (MINUS_EXPR, endbit, domain_min);
05509 }
05510 startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
05511 EXPAND_CONST_ADDRESS);
05512 endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
05513 EXPAND_CONST_ADDRESS);
05514
05515 if (REG_P (target))
05516 {
05517 targetx
05518 = assign_temp
05519 ((build_qualified_type ((*lang_hooks.types.type_for_mode)
05520 (GET_MODE (target), 0),
05521 TYPE_QUAL_CONST)),
05522 0, 1, 1);
05523 emit_move_insn (targetx, target);
05524 }
05525
05526 else if (GET_CODE (target) == MEM)
05527 targetx = target;
05528 else
05529 abort ();
05530
05531
05532
05533 if (TARGET_MEM_FUNCTIONS
05534 && TREE_CODE (startbit) == INTEGER_CST
05535 && TREE_CODE (endbit) == INTEGER_CST
05536 && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
05537 && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
05538 {
05539 emit_library_call (memset_libfunc, LCT_NORMAL,
05540 VOIDmode, 3,
05541 plus_constant (XEXP (targetx, 0),
05542 startb / BITS_PER_UNIT),
05543 Pmode,
05544 constm1_rtx, TYPE_MODE (integer_type_node),
05545 GEN_INT ((endb - startb) / BITS_PER_UNIT),
05546 TYPE_MODE (sizetype));
05547 }
05548 else
05549 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
05550 LCT_NORMAL, VOIDmode, 4, XEXP (targetx, 0),
05551 Pmode, bitlength_rtx, TYPE_MODE (sizetype),
05552 startbit_rtx, TYPE_MODE (sizetype),
05553 endbit_rtx, TYPE_MODE (sizetype));
05554
05555 if (REG_P (target))
05556 emit_move_insn (target, targetx);
05557 }
05558 }
05559
05560 else
05561 abort ();
05562 }
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582 static rtx
05583 store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
05584 alias_set)
05585 rtx target;
05586 HOST_WIDE_INT bitsize;
05587 HOST_WIDE_INT bitpos;
05588 enum machine_mode mode;
05589 tree exp;
05590 enum machine_mode value_mode;
05591 int unsignedp;
05592 tree type;
05593 int alias_set;
05594 {
05595 HOST_WIDE_INT width_mask = 0;
05596
05597 if (TREE_CODE (exp) == ERROR_MARK)
05598 return const0_rtx;
05599
05600
05601
05602 if (bitsize == 0)
05603 return expand_expr (exp, const0_rtx, VOIDmode, 0);
05604 else if (bitsize >=0 && bitsize < HOST_BITS_PER_WIDE_INT)
05605 width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
05606
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618 if (mode == BLKmode
05619 && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
05620 {
05621 rtx object
05622 = assign_temp
05623 (build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST),
05624 0, 1, 1);
05625 rtx blk_object = adjust_address (object, BLKmode, 0);
05626
05627 if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
05628 emit_move_insn (object, target);
05629
05630 store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
05631 alias_set);
05632
05633 emit_move_insn (target, object);
05634
05635
05636 return blk_object;
05637 }
05638
05639 if (GET_CODE (target) == CONCAT)
05640 {
05641
05642
05643 if (bitpos != 0)
05644 abort ();
05645 return store_expr (exp, target, 0);
05646 }
05647
05648
05649
05650
05651
05652 if (mode == VOIDmode
05653 || (mode != BLKmode && ! direct_store[(int) mode]
05654 && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
05655 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
05656 || GET_CODE (target) == REG
05657 || GET_CODE (target) == SUBREG
05658
05659
05660 || (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target))
05661 && (MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode)
05662 || bitpos % GET_MODE_ALIGNMENT (mode)))
05663
05664
05665
05666 || (bitsize >= 0
05667 && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
05668 && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
05669 {
05670 rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
05671
05672
05673
05674
05675
05676 if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
05677 && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
05678 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
05679 temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
05680 size_int (GET_MODE_BITSIZE (GET_MODE (temp))
05681 - bitsize),
05682 temp, 1);
05683
05684
05685
05686 if (mode != VOIDmode && mode != BLKmode
05687 && mode != TYPE_MODE (TREE_TYPE (exp)))
05688 temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
05689
05690
05691
05692
05693 if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
05694 {
05695 if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM
05696 || bitpos % BITS_PER_UNIT != 0)
05697 abort ();
05698
05699 target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
05700 emit_block_move (target, temp,
05701 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
05702 / BITS_PER_UNIT),
05703 BLOCK_OP_NORMAL);
05704
05705 return value_mode == VOIDmode ? const0_rtx : target;
05706 }
05707
05708
05709 store_bit_field (target, bitsize, bitpos, mode, temp,
05710 int_size_in_bytes (type));
05711
05712 if (value_mode != VOIDmode)
05713 {
05714
05715
05716 if (width_mask != 0
05717 && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)))
05718 {
05719 tree count;
05720 enum machine_mode tmode;
05721
05722 tmode = GET_MODE (temp);
05723 if (tmode == VOIDmode)
05724 tmode = value_mode;
05725
05726 if (unsignedp)
05727 return expand_and (tmode, temp,
05728 gen_int_mode (width_mask, tmode),
05729 NULL_RTX);
05730
05731 count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
05732 temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
05733 return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
05734 }
05735
05736 return extract_bit_field (target, bitsize, bitpos, unsignedp,
05737 NULL_RTX, value_mode, VOIDmode,
05738 int_size_in_bytes (type));
05739 }
05740 return const0_rtx;
05741 }
05742 else
05743 {
05744 rtx addr = XEXP (target, 0);
05745 rtx to_rtx = target;
05746
05747
05748
05749
05750 if (value_mode != VOIDmode && GET_CODE (addr) != REG
05751 && ! CONSTANT_ADDRESS_P (addr)
05752
05753 && ! (GET_CODE (addr) == PLUS
05754 && GET_CODE (XEXP (addr, 1)) == CONST_INT
05755 && (XEXP (addr, 0) == virtual_incoming_args_rtx
05756 || XEXP (addr, 0) == virtual_stack_vars_rtx)))
05757 to_rtx = replace_equiv_address (to_rtx, copy_to_reg (addr));
05758
05759
05760
05761 to_rtx = adjust_address (target, mode, bitpos / BITS_PER_UNIT);
05762
05763 if (to_rtx == target)
05764 to_rtx = copy_rtx (to_rtx);
05765
05766 MEM_SET_IN_STRUCT_P (to_rtx, 1);
05767 if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
05768 set_mem_alias_set (to_rtx, alias_set);
05769
05770 return store_expr (exp, to_rtx, value_mode != VOIDmode);
05771 }
05772 }
05773
05774
05775
05776
05777
05778
05779
05780
05781
05782
05783
05784
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796 tree
05797 get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
05798 punsignedp, pvolatilep)
05799 tree exp;
05800 HOST_WIDE_INT *pbitsize;
05801 HOST_WIDE_INT *pbitpos;
05802 tree *poffset;
05803 enum machine_mode *pmode;
05804 int *punsignedp;
05805 int *pvolatilep;
05806 {
05807 tree size_tree = 0;
05808 enum machine_mode mode = VOIDmode;
05809 tree offset = size_zero_node;
05810 tree bit_offset = bitsize_zero_node;
05811 tree placeholder_ptr = 0;
05812 tree tem;
05813
05814
05815
05816 if (TREE_CODE (exp) == COMPONENT_REF)
05817 {
05818 size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
05819 if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
05820 mode = DECL_MODE (TREE_OPERAND (exp, 1));
05821
05822 *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1));
05823 }
05824 else if (TREE_CODE (exp) == BIT_FIELD_REF)
05825 {
05826 size_tree = TREE_OPERAND (exp, 1);
05827 *punsignedp = TREE_UNSIGNED (exp);
05828 }
05829 else
05830 {
05831 mode = TYPE_MODE (TREE_TYPE (exp));
05832 *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
05833
05834 if (mode == BLKmode)
05835 size_tree = TYPE_SIZE (TREE_TYPE (exp));
05836 else
05837 *pbitsize = GET_MODE_BITSIZE (mode);
05838 }
05839
05840 if (size_tree != 0)
05841 {
05842 if (! host_integerp (size_tree, 1))
05843 mode = BLKmode, *pbitsize = -1;
05844 else
05845 *pbitsize = tree_low_cst (size_tree, 1);
05846 }
05847
05848
05849
05850 while (1)
05851 {
05852 if (TREE_CODE (exp) == BIT_FIELD_REF)
05853 bit_offset = size_binop (PLUS_EXPR, bit_offset, TREE_OPERAND (exp, 2));
05854 else if (TREE_CODE (exp) == COMPONENT_REF)
05855 {
05856 tree field = TREE_OPERAND (exp, 1);
05857 tree this_offset = DECL_FIELD_OFFSET (field);
05858
05859
05860
05861
05862 if (this_offset == 0)
05863 break;
05864 else if (! TREE_CONSTANT (this_offset)
05865 && contains_placeholder_p (this_offset))
05866 this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
05867
05868 offset = size_binop (PLUS_EXPR, offset, this_offset);
05869 bit_offset = size_binop (PLUS_EXPR, bit_offset,
05870 DECL_FIELD_BIT_OFFSET (field));
05871
05872
05873 }
05874
05875 else if (TREE_CODE (exp) == ARRAY_REF
05876 || TREE_CODE (exp) == ARRAY_RANGE_REF)
05877 {
05878 tree index = TREE_OPERAND (exp, 1);
05879 tree array = TREE_OPERAND (exp, 0);
05880 tree domain = TYPE_DOMAIN (TREE_TYPE (array));
05881 tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
05882 tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
05883
05884
05885
05886
05887
05888 if (low_bound != 0 && ! integer_zerop (low_bound))
05889 index = fold (build (MINUS_EXPR, TREE_TYPE (index),
05890 index, low_bound));
05891
05892
05893
05894
05895 if (! TREE_CONSTANT (index)
05896 && contains_placeholder_p (index))
05897 index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
05898 if (! TREE_CONSTANT (unit_size)
05899 && contains_placeholder_p (unit_size))
05900 unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array);
05901
05902 offset = size_binop (PLUS_EXPR, offset,
05903 size_binop (MULT_EXPR,
05904 convert (sizetype, index),
05905 unit_size));
05906 }
05907
05908 else if (TREE_CODE (exp) == PLACEHOLDER_EXPR)
05909 {
05910 tree new = find_placeholder (exp, &placeholder_ptr);
05911
05912
05913
05914
05915 if (new == 0)
05916 break;
05917 else
05918 exp = new;
05919
05920 continue;
05921 }
05922 else if (TREE_CODE (exp) != NON_LVALUE_EXPR
05923 && TREE_CODE (exp) != VIEW_CONVERT_EXPR
05924 && ! ((TREE_CODE (exp) == NOP_EXPR
05925 || TREE_CODE (exp) == CONVERT_EXPR)
05926 && (TYPE_MODE (TREE_TYPE (exp))
05927 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
05928 break;
05929
05930
05931 if (TREE_THIS_VOLATILE (exp))
05932 *pvolatilep = 1;
05933
05934 exp = TREE_OPERAND (exp, 0);
05935 }
05936
05937
05938
05939 if (host_integerp (offset, 0)
05940 && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
05941 bitsize_unit_node))
05942 && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
05943 && host_integerp (tem, 0))
05944 *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
05945 else
05946 *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
05947
05948 *pmode = mode;
05949 return exp;
05950 }
05951
05952
05953
05954 int
05955 handled_component_p (t)
05956 tree t;
05957 {
05958 switch (TREE_CODE (t))
05959 {
05960 case BIT_FIELD_REF:
05961 case COMPONENT_REF:
05962 case ARRAY_REF:
05963 case ARRAY_RANGE_REF:
05964 case NON_LVALUE_EXPR:
05965 case VIEW_CONVERT_EXPR:
05966 return 1;
05967
05968 case NOP_EXPR:
05969 case CONVERT_EXPR:
05970 return (TYPE_MODE (TREE_TYPE (t))
05971 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
05972
05973 default:
05974 return 0;
05975 }
05976 }
05977
05978
05979
05980
05981
05982
05983
05984
05985 rtx
05986 force_operand (value, target)
05987 rtx value, target;
05988 {
05989 rtx op1, op2;
05990
05991 rtx subtarget = get_subtarget (target);
05992 enum rtx_code code = GET_CODE (value);
05993
05994
05995 if ((code == PLUS || code == MINUS)
05996 && XEXP (value, 0) == pic_offset_table_rtx
05997 && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
05998 || GET_CODE (XEXP (value, 1)) == LABEL_REF
05999 || GET_CODE (XEXP (value, 1)) == CONST))
06000 {
06001 if (!subtarget)
06002 subtarget = gen_reg_rtx (GET_MODE (value));
06003 emit_move_insn (subtarget, value);
06004 return subtarget;
06005 }
06006
06007 if (code == ZERO_EXTEND || code == SIGN_EXTEND)
06008 {
06009 if (!target)
06010 target = gen_reg_rtx (GET_MODE (value));
06011 convert_move (target, force_operand (XEXP (value, 0), NULL),
06012 code == ZERO_EXTEND);
06013 return target;
06014 }
06015
06016 if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
06017 {
06018 op2 = XEXP (value, 1);
06019 if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
06020 subtarget = 0;
06021 if (code == MINUS && GET_CODE (op2) == CONST_INT)
06022 {
06023 code = PLUS;
06024 op2 = negate_rtx (GET_MODE (value), op2);
06025 }
06026
06027
06028
06029
06030
06031
06032
06033 if (code == PLUS && GET_CODE (op2) == CONST_INT
06034 && GET_CODE (XEXP (value, 0)) == PLUS
06035 && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
06036 && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
06037 && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
06038 {
06039 rtx temp = expand_simple_binop (GET_MODE (value), code,
06040 XEXP (XEXP (value, 0), 0), op2,
06041 subtarget, 0, OPTAB_LIB_WIDEN);
06042 return expand_simple_binop (GET_MODE (value), code, temp,
06043 force_operand (XEXP (XEXP (value,
06044 0), 1), 0),
06045 target, 0, OPTAB_LIB_WIDEN);
06046 }
06047
06048 op1 = force_operand (XEXP (value, 0), subtarget);
06049 op2 = force_operand (op2, NULL_RTX);
06050 switch (code)
06051 {
06052 case MULT:
06053 return expand_mult (GET_MODE (value), op1, op2, target, 1);
06054 case DIV:
06055 if (!INTEGRAL_MODE_P (GET_MODE (value)))
06056 return expand_simple_binop (GET_MODE (value), code, op1, op2,
06057 target, 1, OPTAB_LIB_WIDEN);
06058 else
06059 return expand_divmod (0,
06060 FLOAT_MODE_P (GET_MODE (value))
06061 ? RDIV_EXPR : TRUNC_DIV_EXPR,
06062 GET_MODE (value), op1, op2, target, 0);
06063 break;
06064 case MOD:
06065 return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
06066 target, 0);
06067 break;
06068 case UDIV:
06069 return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
06070 target, 1);
06071 break;
06072 case UMOD:
06073 return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
06074 target, 1);
06075 break;
06076 case ASHIFTRT:
06077 return expand_simple_binop (GET_MODE (value), code, op1, op2,
06078 target, 0, OPTAB_LIB_WIDEN);
06079 break;
06080 default:
06081 return expand_simple_binop (GET_MODE (value), code, op1, op2,
06082 target, 1, OPTAB_LIB_WIDEN);
06083 }
06084 }
06085 if (GET_RTX_CLASS (code) == '1')
06086 {
06087 op1 = force_operand (XEXP (value, 0), NULL_RTX);
06088 return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
06089 }
06090
06091 #ifdef INSN_SCHEDULING
06092
06093
06094 if (GET_CODE (value) == SUBREG && GET_CODE (SUBREG_REG (value)) == MEM
06095 && (GET_MODE_SIZE (GET_MODE (value))
06096 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (value)))))
06097 value
06098 = simplify_gen_subreg (GET_MODE (value),
06099 force_reg (GET_MODE (SUBREG_REG (value)),
06100 force_operand (SUBREG_REG (value),
06101 NULL_RTX)),
06102 GET_MODE (SUBREG_REG (value)),
06103 SUBREG_BYTE (value));
06104 #endif
06105
06106 return value;
06107 }
06108
06109
06110
06111
06112
06113
06114
06115
06116
06117 int
06118 safe_from_p (x, exp, top_p)
06119 rtx x;
06120 tree exp;
06121 int top_p;
06122 {
06123 rtx exp_rtl = 0;
06124 int i, nops;
06125 static tree save_expr_list;
06126
06127 if (x == 0
06128
06129
06130
06131
06132
06133
06134 || (top_p && TREE_TYPE (exp) != 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
06135 && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
06136 && (TREE_CODE (TREE_TYPE (exp)) != ARRAY_TYPE
06137 || TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
06138 || TREE_CODE (TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)))
06139 != INTEGER_CST)
06140 && GET_MODE (x) == BLKmode)
06141
06142 || (GET_CODE (x) == MEM
06143 && (XEXP (x, 0) == virtual_outgoing_args_rtx
06144 || (GET_CODE (XEXP (x, 0)) == PLUS
06145 && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))))
06146 return 1;
06147
06148
06149
06150 if (GET_CODE (x) == SUBREG)
06151 {
06152 x = SUBREG_REG (x);
06153 if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
06154 return 0;
06155 }
06156
06157
06158
06159
06160
06161
06162
06163
06164
06165
06166 if (top_p)
06167 {
06168 int rtn;
06169 tree t;
06170
06171 save_expr_list = 0;
06172
06173 rtn = safe_from_p (x, exp, 0);
06174
06175 for (t = save_expr_list; t != 0; t = TREE_CHAIN (t))
06176 TREE_PRIVATE (TREE_PURPOSE (t)) = 0;
06177
06178 return rtn;
06179 }
06180
06181
06182 switch (TREE_CODE_CLASS (TREE_CODE (exp)))
06183 {
06184 case 'd':
06185 exp_rtl = DECL_RTL_IF_SET (exp);
06186 break;
06187
06188 case 'c':
06189 return 1;
06190
06191 case 'x':
06192 if (TREE_CODE (exp) == TREE_LIST)
06193 {
06194 while (1)
06195 {
06196 if (TREE_VALUE (exp) && !safe_from_p (x, TREE_VALUE (exp), 0))
06197 return 0;
06198 exp = TREE_CHAIN (exp);
06199 if (!exp)
06200 return 1;
06201 if (TREE_CODE (exp) != TREE_LIST)
06202 return safe_from_p (x, exp, 0);
06203 }
06204 }
06205 else if (TREE_CODE (exp) == ERROR_MARK)
06206 return 1;
06207 else
06208 return 0;
06209
06210 case '2':
06211 case '<':
06212 if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))
06213 return 0;
06214
06215
06216 case '1':
06217 return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
06218
06219 case 'e':
06220 case 'r':
06221
06222
06223
06224
06225
06226 switch (TREE_CODE (exp))
06227 {
06228 case ADDR_EXPR:
06229
06230
06231 if (staticp (TREE_OPERAND (exp, 0))
06232 || TREE_STATIC (exp)
06233 || safe_from_p (x, TREE_OPERAND (exp, 0), 0))
06234 return 1;
06235
06236
06237
06238
06239 exp = TREE_OPERAND (exp, 0);
06240 if (DECL_P (exp))
06241 {
06242 if (!DECL_RTL_SET_P (exp)
06243 || GET_CODE (DECL_RTL (exp)) != MEM)
06244 return 0;
06245 else
06246 exp_rtl = XEXP (DECL_RTL (exp), 0);
06247 }
06248 break;
06249
06250 case INDIRECT_REF:
06251 if (GET_CODE (x) == MEM
06252 && alias_sets_conflict_p (MEM_ALIAS_SET (x),
06253 get_alias_set (exp)))
06254 return 0;
06255 break;
06256
06257 case CALL_EXPR:
06258
06259
06260 if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
06261 || GET_CODE (x) == MEM)
06262 return 0;
06263 break;
06264
06265 case RTL_EXPR:
06266
06267
06268
06269 if (RTL_EXPR_SEQUENCE (exp))
06270 return 0;
06271
06272 exp_rtl = RTL_EXPR_RTL (exp);
06273 break;
06274
06275 case WITH_CLEANUP_EXPR:
06276 exp_rtl = WITH_CLEANUP_EXPR_RTL (exp);
06277 break;
06278
06279 case CLEANUP_POINT_EXPR:
06280 return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
06281
06282 case SAVE_EXPR:
06283 exp_rtl = SAVE_EXPR_RTL (exp);
06284 if (exp_rtl)
06285 break;
06286
06287
06288
06289
06290 if (TREE_PRIVATE (exp))
06291 return 1;
06292
06293 TREE_PRIVATE (exp) = 1;
06294 if (! safe_from_p (x, TREE_OPERAND (exp, 0), 0))
06295 {
06296 TREE_PRIVATE (exp) = 0;
06297 return 0;
06298 }
06299
06300 save_expr_list = tree_cons (exp, NULL_TREE, save_expr_list);
06301 return 1;
06302
06303 case BIND_EXPR:
06304
06305
06306 return safe_from_p (x, TREE_OPERAND (exp, 1), 0);
06307
06308 case METHOD_CALL_EXPR:
06309
06310 abort ();
06311
06312 default:
06313 break;
06314 }
06315
06316
06317 if (exp_rtl)
06318 break;
06319
06320 nops = first_rtl_op (TREE_CODE (exp));
06321 for (i = 0; i < nops; i++)
06322 if (TREE_OPERAND (exp, i) != 0
06323 && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
06324 return 0;
06325
06326
06327
06328 if ((unsigned int) TREE_CODE (exp)
06329 >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
06330 && !(*lang_hooks.safe_from_p) (x, exp))
06331 return 0;
06332 }
06333
06334
06335
06336 if (exp_rtl)
06337 {
06338 if (GET_CODE (exp_rtl) == SUBREG)
06339 {
06340 exp_rtl = SUBREG_REG (exp_rtl);
06341 if (GET_CODE (exp_rtl) == REG
06342 && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER)
06343 return 0;
06344 }
06345
06346
06347
06348 return ! (rtx_equal_p (x, exp_rtl)
06349 || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
06350 && true_dependence (exp_rtl, VOIDmode, x,
06351 rtx_addr_varies_p)));
06352 }
06353
06354
06355 return 1;
06356 }
06357
06358
06359
06360
06361 static rtx
06362 var_rtx (exp)
06363 tree exp;
06364 {
06365 STRIP_NOPS (exp);
06366 switch (TREE_CODE (exp))
06367 {
06368 case PARM_DECL:
06369 case VAR_DECL:
06370 return DECL_RTL (exp);
06371 default:
06372 return 0;
06373 }
06374 }
06375
06376 #ifdef MAX_INTEGER_COMPUTATION_MODE
06377
06378 void
06379 check_max_integer_computation_mode (exp)
06380 tree exp;
06381 {
06382 enum tree_code code;
06383 enum machine_mode mode;
06384
06385
06386 STRIP_NOPS (exp);
06387 code = TREE_CODE (exp);
06388
06389
06390 if (code == NOP_EXPR
06391 && TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
06392 return;
06393
06394
06395
06396 if (TREE_CODE_CLASS (code) == '1'
06397 || TREE_CODE_CLASS (code) == '2'
06398 || TREE_CODE_CLASS (code) == '<')
06399 {
06400 mode = TYPE_MODE (TREE_TYPE (exp));
06401 if (GET_MODE_CLASS (mode) == MODE_INT
06402 && mode > MAX_INTEGER_COMPUTATION_MODE)
06403 internal_error ("unsupported wide integer operation");
06404 }
06405
06406
06407 if (TREE_CODE_CLASS (code) == '1')
06408 {
06409 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
06410 if (GET_MODE_CLASS (mode) == MODE_INT
06411 && mode > MAX_INTEGER_COMPUTATION_MODE)
06412 internal_error ("unsupported wide integer operation");
06413 }
06414
06415
06416 if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
06417 {
06418 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
06419 if (GET_MODE_CLASS (mode) == MODE_INT
06420 && mode > MAX_INTEGER_COMPUTATION_MODE)
06421 internal_error ("unsupported wide integer operation");
06422
06423 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
06424 if (GET_MODE_CLASS (mode) == MODE_INT
06425 && mode > MAX_INTEGER_COMPUTATION_MODE)
06426 internal_error ("unsupported wide integer operation");
06427 }
06428 }
06429 #endif
06430
06431
06432
06433
06434 static HOST_WIDE_INT
06435 highest_pow2_factor (exp)
06436 tree exp;
06437 {
06438 HOST_WIDE_INT c0, c1;
06439
06440 switch (TREE_CODE (exp))
06441 {
06442 case INTEGER_CST:
06443
06444
06445
06446
06447
06448
06449 if (TREE_CONSTANT_OVERFLOW (exp))
06450 return BIGGEST_ALIGNMENT;
06451 else
06452 {
06453
06454
06455 c0 = TREE_INT_CST_LOW (exp);
06456 c0 &= -c0;
06457 return c0 ? c0 : BIGGEST_ALIGNMENT;
06458 }
06459 break;
06460
06461 case PLUS_EXPR: case MINUS_EXPR: case MIN_EXPR: case MAX_EXPR:
06462 c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
06463 c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06464 return MIN (c0, c1);
06465
06466 case MULT_EXPR:
06467 c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
06468 c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06469 return c0 * c1;
06470
06471 case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR:
06472 case CEIL_DIV_EXPR:
06473 if (integer_pow2p (TREE_OPERAND (exp, 1))
06474 && host_integerp (TREE_OPERAND (exp, 1), 1))
06475 {
06476 c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
06477 c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1);
06478 return MAX (1, c0 / c1);
06479 }
06480 break;
06481
06482 case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR:
06483 case SAVE_EXPR: case WITH_RECORD_EXPR:
06484 return highest_pow2_factor (TREE_OPERAND (exp, 0));
06485
06486 case COMPOUND_EXPR:
06487 return highest_pow2_factor (TREE_OPERAND (exp, 1));
06488
06489 case COND_EXPR:
06490 c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
06491 c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
06492 return MIN (c0, c1);
06493
06494 default:
06495 break;
06496 }
06497
06498 return 1;
06499 }
06500
06501
06502
06503
06504 static HOST_WIDE_INT
06505 highest_pow2_factor_for_type (type, exp)
06506 tree type;
06507 tree exp;
06508 {
06509 HOST_WIDE_INT type_align, factor;
06510
06511 factor = highest_pow2_factor (exp);
06512 type_align = TYPE_ALIGN (type) / BITS_PER_UNIT;
06513 return MAX (factor, type_align);
06514 }
06515
06516
06517
06518
06519
06520
06521
06522
06523
06524 tree
06525 find_placeholder (exp, plist)
06526 tree exp;
06527 tree *plist;
06528 {
06529 tree type = TREE_TYPE (exp);
06530 tree placeholder_expr;
06531
06532 for (placeholder_expr
06533 = plist && *plist ? TREE_CHAIN (*plist) : placeholder_list;
06534 placeholder_expr != 0;
06535 placeholder_expr = TREE_CHAIN (placeholder_expr))
06536 {
06537 tree need_type = TYPE_MAIN_VARIANT (type);
06538 tree elt;
06539
06540
06541
06542
06543 for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
06544 elt = ((TREE_CODE (elt) == COMPOUND_EXPR
06545 || TREE_CODE (elt) == COND_EXPR)
06546 ? TREE_OPERAND (elt, 1)
06547 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
06548 || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
06549 || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
06550 || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
06551 ? TREE_OPERAND (elt, 0) : 0))
06552 if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
06553 {
06554 if (plist)
06555 *plist = placeholder_expr;
06556 return elt;
06557 }
06558
06559 for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
06560 elt
06561 = ((TREE_CODE (elt) == COMPOUND_EXPR
06562 || TREE_CODE (elt) == COND_EXPR)
06563 ? TREE_OPERAND (elt, 1)
06564 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
06565 || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
06566 || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
06567 || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
06568 ? TREE_OPERAND (elt, 0) : 0))
06569 if (POINTER_TYPE_P (TREE_TYPE (elt))
06570 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
06571 == need_type))
06572 {
06573 if (plist)
06574 *plist = placeholder_expr;
06575 return build1 (INDIRECT_REF, need_type, elt);
06576 }
06577 }
06578
06579 return 0;
06580 }
06581
06582
06583
06584
06585
06586
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622
06623
06624 rtx
06625 expand_expr (exp, target, tmode, modifier)
06626 tree exp;
06627 rtx target;
06628 enum machine_mode tmode;
06629 enum expand_modifier modifier;
06630 {
06631 rtx op0, op1, temp;
06632 tree type = TREE_TYPE (exp);
06633 int unsignedp = TREE_UNSIGNED (type);
06634 enum machine_mode mode;
06635 enum tree_code code = TREE_CODE (exp);
06636 optab this_optab;
06637 rtx subtarget, original_target;
06638 int ignore;
06639 tree context;
06640
06641
06642 if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
06643 {
06644 op0 = CONST0_RTX (tmode);
06645 if (op0 != 0)
06646 return op0;
06647 return const0_rtx;
06648 }
06649
06650 mode = TYPE_MODE (type);
06651
06652 subtarget = get_subtarget (target);
06653 original_target = target;
06654 ignore = (target == const0_rtx
06655 || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
06656 || code == CONVERT_EXPR || code == REFERENCE_EXPR
06657 || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
06658 && TREE_CODE (type) == VOID_TYPE));
06659
06660
06661
06662
06663
06664
06665
06666 if (ignore)
06667 {
06668 if (! TREE_SIDE_EFFECTS (exp))
06669 return const0_rtx;
06670
06671
06672
06673 if (TREE_THIS_VOLATILE (exp)
06674 && TREE_CODE (exp) != FUNCTION_DECL
06675 && mode != VOIDmode && mode != BLKmode
06676 && modifier != EXPAND_CONST_ADDRESS)
06677 {
06678 temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
06679 if (GET_CODE (temp) == MEM)
06680 temp = copy_to_reg (temp);
06681 return const0_rtx;
06682 }
06683
06684 if (TREE_CODE_CLASS (code) == '1' || code == COMPONENT_REF
06685 || code == INDIRECT_REF || code == BUFFER_REF)
06686 return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
06687 modifier);
06688
06689 else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
06690 || code == ARRAY_REF || code == ARRAY_RANGE_REF)
06691 {
06692 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
06693 expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
06694 return const0_rtx;
06695 }
06696 else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
06697 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
06698
06699
06700 return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
06701 modifier);
06702 else if (code == BIT_FIELD_REF)
06703 {
06704 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
06705 expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
06706 expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, modifier);
06707 return const0_rtx;
06708 }
06709
06710 target = 0;
06711 }
06712
06713 #ifdef MAX_INTEGER_COMPUTATION_MODE
06714
06715
06716
06717
06718 if (target
06719 && GET_MODE (target) != mode
06720 && TREE_CODE (exp) != INTEGER_CST
06721 && TREE_CODE (exp) != PARM_DECL
06722 && TREE_CODE (exp) != ARRAY_REF
06723 && TREE_CODE (exp) != ARRAY_RANGE_REF
06724 && TREE_CODE (exp) != COMPONENT_REF
06725 && TREE_CODE (exp) != BIT_FIELD_REF
06726 && TREE_CODE (exp) != INDIRECT_REF
06727 && TREE_CODE (exp) != CALL_EXPR
06728 && TREE_CODE (exp) != VAR_DECL
06729 && TREE_CODE (exp) != RTL_EXPR)
06730 {
06731 enum machine_mode mode = GET_MODE (target);
06732
06733 if (GET_MODE_CLASS (mode) == MODE_INT
06734 && mode > MAX_INTEGER_COMPUTATION_MODE)
06735 internal_error ("unsupported wide integer operation");
06736 }
06737
06738 if (tmode != mode
06739 && TREE_CODE (exp) != INTEGER_CST
06740 && TREE_CODE (exp) != PARM_DECL
06741 && TREE_CODE (exp) != ARRAY_REF
06742 && TREE_CODE (exp) != ARRAY_RANGE_REF
06743 && TREE_CODE (exp) != COMPONENT_REF
06744 && TREE_CODE (exp) != BIT_FIELD_REF
06745 && TREE_CODE (exp) != INDIRECT_REF
06746 && TREE_CODE (exp) != VAR_DECL
06747 && TREE_CODE (exp) != CALL_EXPR
06748 && TREE_CODE (exp) != RTL_EXPR
06749 && GET_MODE_CLASS (tmode) == MODE_INT
06750 && tmode > MAX_INTEGER_COMPUTATION_MODE)
06751 internal_error ("unsupported wide integer operation");
06752
06753 check_max_integer_computation_mode (exp);
06754 #endif
06755
06756
06757
06758
06759
06760
06761
06762 if (! cse_not_expected && mode != BLKmode && target
06763 && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
06764 && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD))
06765 target = 0;
06766
06767 switch (code)
06768 {
06769 case LABEL_DECL:
06770 {
06771 tree function = decl_function_context (exp);
06772
06773 if (function != current_function_decl
06774 && function != inline_function_decl && function != 0)
06775 {
06776 struct function *p = find_function_data (function);
06777 p->expr->x_forced_labels
06778 = gen_rtx_EXPR_LIST (VOIDmode, label_rtx (exp),
06779 p->expr->x_forced_labels);
06780 }
06781 else
06782 {
06783 if (modifier == EXPAND_INITIALIZER)
06784 forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
06785 label_rtx (exp),
06786 forced_labels);
06787 }
06788
06789 temp = gen_rtx_MEM (FUNCTION_MODE,
06790 gen_rtx_LABEL_REF (Pmode, label_rtx (exp)));
06791 if (function != current_function_decl
06792 && function != inline_function_decl && function != 0)
06793 LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1;
06794 return temp;
06795 }
06796
06797 case PARM_DECL:
06798 if (!DECL_RTL_SET_P (exp))
06799 {
06800 error_with_decl (exp, "prior parameter's size depends on `%s'");
06801 return CONST0_RTX (mode);
06802 }
06803
06804
06805
06806 case VAR_DECL:
06807
06808
06809 if (DECL_SIZE (exp) == 0
06810 && COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (TREE_TYPE (exp))
06811 && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
06812 layout_decl (exp, 0);
06813
06814
06815
06816 case FUNCTION_DECL:
06817 case RESULT_DECL:
06818 if (DECL_RTL (exp) == 0)
06819 abort ();
06820
06821
06822
06823
06824 if (! TREE_USED (exp))
06825 {
06826 assemble_external (exp);
06827 TREE_USED (exp) = 1;
06828 }
06829
06830
06831 temp = 0;
06832
06833
06834 context = decl_function_context (exp);
06835
06836
06837
06838
06839
06840
06841 if (context != 0 && context != current_function_decl
06842 && context != inline_function_decl
06843
06844 && ! (GET_CODE (DECL_RTL (exp)) == MEM
06845 && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
06846 {
06847 rtx addr;
06848
06849
06850 DECL_NONLOCAL (exp) = 1;
06851 if (DECL_NO_STATIC_CHAIN (current_function_decl))
06852 abort ();
06853 (*lang_hooks.mark_addressable) (exp);
06854 if (GET_CODE (DECL_RTL (exp)) != MEM)
06855 abort ();
06856 addr = XEXP (DECL_RTL (exp), 0);
06857 if (GET_CODE (addr) == MEM)
06858 addr
06859 = replace_equiv_address (addr,
06860 fix_lexical_addr (XEXP (addr, 0), exp));
06861 else
06862 addr = fix_lexical_addr (addr, exp);
06863
06864 temp = replace_equiv_address (DECL_RTL (exp), addr);
06865 }
06866
06867
06868
06869
06870
06871 else if (GET_CODE (DECL_RTL (exp)) == MEM
06872 && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
06873 temp = validize_mem (DECL_RTL (exp));
06874
06875
06876
06877
06878
06879 else if (GET_CODE (DECL_RTL (exp)) == MEM
06880 && modifier != EXPAND_CONST_ADDRESS
06881 && modifier != EXPAND_SUM
06882 && modifier != EXPAND_INITIALIZER
06883 && (! memory_address_p (DECL_MODE (exp),
06884 XEXP (DECL_RTL (exp), 0))
06885 || (flag_force_addr
06886 && GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG)))
06887 temp = replace_equiv_address (DECL_RTL (exp),
06888 copy_rtx (XEXP (DECL_RTL (exp), 0)));
06889
06890
06891
06892 if (temp != 0)
06893 {
06894 if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG)
06895 mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp));
06896
06897 return temp;
06898 }
06899
06900
06901
06902
06903
06904 if (GET_CODE (DECL_RTL (exp)) == REG
06905 && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
06906 {
06907
06908
06909 if (GET_MODE (DECL_RTL (exp))
06910 != promote_mode (type, DECL_MODE (exp), &unsignedp,
06911 (TREE_CODE (exp) == RESULT_DECL ? 1 : 0)))
06912 abort ();
06913
06914 temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
06915 SUBREG_PROMOTED_VAR_P (temp) = 1;
06916 SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
06917 return temp;
06918 }
06919
06920 return DECL_RTL (exp);
06921
06922 case INTEGER_CST:
06923 temp = immed_double_const (TREE_INT_CST_LOW (exp),
06924 TREE_INT_CST_HIGH (exp), mode);
06925
06926
06927
06928
06929
06930
06931 if (TREE_CONSTANT_OVERFLOW (exp)
06932 && modifier != EXPAND_INITIALIZER)
06933 temp = force_reg (mode, temp);
06934
06935 return temp;
06936
06937 case VECTOR_CST:
06938 return const_vector_from_tree (exp);
06939
06940 case CONST_DECL:
06941 return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
06942
06943 case REAL_CST:
06944
06945
06946
06947
06948
06949
06950
06951
06952
06953
06954 return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp),
06955 TYPE_MODE (TREE_TYPE (exp)));
06956
06957 case COMPLEX_CST:
06958 case STRING_CST:
06959 if (! TREE_CST_RTL (exp))
06960 output_constant_def (exp, 1);
06961
06962
06963
06964
06965 if (GET_CODE (TREE_CST_RTL (exp)) == MEM
06966 && modifier != EXPAND_CONST_ADDRESS
06967 && modifier != EXPAND_INITIALIZER
06968 && modifier != EXPAND_SUM
06969 && (! memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))
06970 || (flag_force_addr
06971 && GET_CODE (XEXP (TREE_CST_RTL (exp), 0)) != REG)))
06972 return replace_equiv_address (TREE_CST_RTL (exp),
06973 copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
06974 return TREE_CST_RTL (exp);
06975
06976 case EXPR_WITH_FILE_LOCATION:
06977 {
06978 rtx to_return;
06979 const char *saved_input_filename = input_filename;
06980 int saved_lineno = lineno;
06981 input_filename = EXPR_WFL_FILENAME (exp);
06982 lineno = EXPR_WFL_LINENO (exp);
06983 if (EXPR_WFL_EMIT_LINE_NOTE (exp))
06984 emit_line_note (input_filename, lineno);
06985
06986 to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
06987 input_filename = saved_input_filename;
06988 lineno = saved_lineno;
06989 return to_return;
06990 }
06991
06992 case SAVE_EXPR:
06993 context = decl_function_context (exp);
06994
06995
06996
06997 if (context == 0)
06998 SAVE_EXPR_CONTEXT (exp) = current_function_decl;
06999
07000
07001
07002
07003
07004 if (context == current_function_decl || context == inline_function_decl)
07005 context = 0;
07006
07007
07008 if (context)
07009 {
07010
07011
07012 find_function_data (context);
07013
07014 temp = SAVE_EXPR_RTL (exp);
07015 if (temp && GET_CODE (temp) == REG)
07016 {
07017 put_var_into_stack (exp, true);
07018 temp = SAVE_EXPR_RTL (exp);
07019 }
07020 if (temp == 0 || GET_CODE (temp) != MEM)
07021 abort ();
07022 return
07023 replace_equiv_address (temp,
07024 fix_lexical_addr (XEXP (temp, 0), exp));
07025 }
07026 if (SAVE_EXPR_RTL (exp) == 0)
07027 {
07028 if (mode == VOIDmode)
07029 temp = const0_rtx;
07030 else
07031 temp = assign_temp (build_qualified_type (type,
07032 (TYPE_QUALS (type)
07033 | TYPE_QUAL_CONST)),
07034 3, 0, 0);
07035
07036 SAVE_EXPR_RTL (exp) = temp;
07037 if (!optimize && GET_CODE (temp) == REG)
07038 save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, temp,
07039 save_expr_regs);
07040
07041
07042
07043
07044
07045
07046 if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
07047 {
07048 temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
07049 promote_mode (type, mode, &unsignedp, 0);
07050 SUBREG_PROMOTED_VAR_P (temp) = 1;
07051 SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
07052 }
07053
07054 if (temp == const0_rtx)
07055 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
07056 else
07057 store_expr (TREE_OPERAND (exp, 0), temp,
07058 modifier == EXPAND_STACK_PARM ? 2 : 0);
07059
07060 TREE_USED (exp) = 1;
07061 }
07062
07063
07064
07065
07066
07067 if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG
07068 && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
07069 {
07070
07071 promote_mode (type, mode, &unsignedp, 0);
07072 temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
07073 SUBREG_PROMOTED_VAR_P (temp) = 1;
07074 SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
07075 return temp;
07076 }
07077
07078 return SAVE_EXPR_RTL (exp);
07079
07080 case UNSAVE_EXPR:
07081 {
07082 rtx temp;
07083 temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
07084 TREE_OPERAND (exp, 0)
07085 = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
07086 return temp;
07087 }
07088
07089 case PLACEHOLDER_EXPR:
07090 {
07091 tree old_list = placeholder_list;
07092 tree placeholder_expr = 0;
07093
07094 exp = find_placeholder (exp, &placeholder_expr);
07095 if (exp == 0)
07096 abort ();
07097
07098 placeholder_list = TREE_CHAIN (placeholder_expr);
07099 temp = expand_expr (exp, original_target, tmode, modifier);
07100 placeholder_list = old_list;
07101 return temp;
07102 }
07103
07104 case WITH_RECORD_EXPR:
07105
07106
07107 placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
07108 placeholder_list);
07109 target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode,
07110 modifier);
07111 placeholder_list = TREE_CHAIN (placeholder_list);
07112 return target;
07113
07114 case GOTO_EXPR:
07115 if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
07116 expand_goto (TREE_OPERAND (exp, 0));
07117 else
07118 expand_computed_goto (TREE_OPERAND (exp, 0));
07119 return const0_rtx;
07120
07121 case EXIT_EXPR:
07122 expand_exit_loop_if_false (NULL,
07123 invert_truthvalue (TREE_OPERAND (exp, 0)));
07124 return const0_rtx;
07125
07126 case LABELED_BLOCK_EXPR:
07127 if (LABELED_BLOCK_BODY (exp))
07128 expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1);
07129
07130 do_pending_stack_adjust ();
07131 emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
07132 return const0_rtx;
07133
07134 case EXIT_BLOCK_EXPR:
07135 if (EXIT_BLOCK_RETURN (exp))
07136 sorry ("returned value in block_exit_expr");
07137 expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp)));
07138 return const0_rtx;
07139
07140 case LOOP_EXPR:
07141 push_temp_slots ();
07142 expand_start_loop (1);
07143 expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
07144 expand_end_loop ();
07145 pop_temp_slots ();
07146
07147 return const0_rtx;
07148
07149 case BIND_EXPR:
07150 {
07151 tree vars = TREE_OPERAND (exp, 0);
07152 int vars_need_expansion = 0;
07153
07154
07155
07156 expand_start_bindings (2);
07157
07158
07159 if (TREE_OPERAND (exp, 2) != 0
07160 && ! TREE_USED (TREE_OPERAND (exp, 2)))
07161 (*lang_hooks.decls.insert_block) (TREE_OPERAND (exp, 2));
07162
07163
07164 while (vars)
07165 {
07166 if (!DECL_RTL_SET_P (vars))
07167 {
07168 vars_need_expansion = 1;
07169 expand_decl (vars);
07170 }
07171 expand_decl_init (vars);
07172 vars = TREE_CHAIN (vars);
07173 }
07174
07175 temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier);
07176
07177 expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
07178
07179 return temp;
07180 }
07181
07182 case RTL_EXPR:
07183 if (RTL_EXPR_SEQUENCE (exp))
07184 {
07185 if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
07186 abort ();
07187 emit_insn (RTL_EXPR_SEQUENCE (exp));
07188 RTL_EXPR_SEQUENCE (exp) = const0_rtx;
07189 }
07190 preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
07191 free_temps_for_rtl_expr (exp);
07192 return RTL_EXPR_RTL (exp);
07193
07194 case CONSTRUCTOR:
07195
07196
07197 if (ignore)
07198 {
07199 tree elt;
07200
07201 for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
07202 expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
07203
07204 return const0_rtx;
07205 }
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220 else if ((TREE_STATIC (exp)
07221 && ((mode == BLKmode
07222 && ! (target != 0 && safe_from_p (target, exp, 1)))
07223 || TREE_ADDRESSABLE (exp)
07224 || (host_integerp (TYPE_SIZE_UNIT (type), 1)
07225 && (! MOVE_BY_PIECES_P
07226 (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
07227 TYPE_ALIGN (type)))
07228 && ((TREE_CODE (type) == VECTOR_TYPE
07229 && !is_zeros_p (exp))
07230 || ! mostly_zeros_p (exp)))))
07231 || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
07232 {
07233 rtx constructor = output_constant_def (exp, 1);
07234
07235 if (modifier != EXPAND_CONST_ADDRESS
07236 && modifier != EXPAND_INITIALIZER
07237 && modifier != EXPAND_SUM)
07238 constructor = validize_mem (constructor);
07239
07240 return constructor;
07241 }
07242 else
07243 {
07244
07245
07246 if (target == 0 || ! safe_from_p (target, exp, 1)
07247 || GET_CODE (target) == PARALLEL
07248 || modifier == EXPAND_STACK_PARM)
07249 target
07250 = assign_temp (build_qualified_type (type,
07251 (TYPE_QUALS (type)
07252 | (TREE_READONLY (exp)
07253 * TYPE_QUAL_CONST))),
07254 0, TREE_ADDRESSABLE (exp), 1);
07255
07256 store_constructor (exp, target, 0, int_expr_size (exp));
07257 return target;
07258 }
07259
07260 case INDIRECT_REF:
07261 {
07262 tree exp1 = TREE_OPERAND (exp, 0);
07263 tree index;
07264 tree string = string_constant (exp1, &index);
07265
07266
07267 if (string
07268 && TREE_CODE (string) == STRING_CST
07269 && TREE_CODE (index) == INTEGER_CST
07270 && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
07271 && GET_MODE_CLASS (mode) == MODE_INT
07272 && GET_MODE_SIZE (mode) == 1
07273 && modifier != EXPAND_WRITE)
07274 return gen_int_mode (TREE_STRING_POINTER (string)
07275 [TREE_INT_CST_LOW (index)], mode);
07276
07277 op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
07278 op0 = memory_address (mode, op0);
07279 temp = gen_rtx_MEM (mode, op0);
07280 set_mem_attributes (temp, exp, 0);
07281
07282
07283
07284
07285 if (modifier == EXPAND_WRITE && readonly_fields_p (type))
07286 RTX_UNCHANGING_P (temp) = 1;
07287
07288 return temp;
07289 }
07290
07291 case ARRAY_REF:
07292 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
07293 abort ();
07294
07295 {
07296 tree array = TREE_OPERAND (exp, 0);
07297 tree domain = TYPE_DOMAIN (TREE_TYPE (array));
07298 tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
07299 tree index = convert (sizetype, TREE_OPERAND (exp, 1));
07300 HOST_WIDE_INT i;
07301
07302
07303
07304
07305
07306
07307
07308
07309
07310 if (! integer_zerop (low_bound))
07311 index = size_diffop (index, convert (sizetype, low_bound));
07312
07313
07314
07315
07316
07317
07318 if (modifier != EXPAND_CONST_ADDRESS
07319 && modifier != EXPAND_INITIALIZER
07320 && modifier != EXPAND_MEMORY
07321 && TREE_CODE (array) == STRING_CST
07322 && TREE_CODE (index) == INTEGER_CST
07323 && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
07324 && GET_MODE_CLASS (mode) == MODE_INT
07325 && GET_MODE_SIZE (mode) == 1)
07326 return gen_int_mode (TREE_STRING_POINTER (array)
07327 [TREE_INT_CST_LOW (index)], mode);
07328
07329
07330
07331
07332
07333
07334 if (modifier != EXPAND_CONST_ADDRESS
07335 && modifier != EXPAND_INITIALIZER
07336 && modifier != EXPAND_MEMORY
07337 && TREE_CODE (array) == CONSTRUCTOR
07338 && ! TREE_SIDE_EFFECTS (array)
07339 && TREE_CODE (index) == INTEGER_CST
07340 && 0 > compare_tree_int (index,
07341 list_length (CONSTRUCTOR_ELTS
07342 (TREE_OPERAND (exp, 0)))))
07343 {
07344 tree elem;
07345
07346 for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
07347 i = TREE_INT_CST_LOW (index);
07348 elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
07349 ;
07350
07351 if (elem)
07352 return expand_expr (fold (TREE_VALUE (elem)), target, tmode,
07353 modifier);
07354 }
07355
07356 else if (optimize >= 1
07357 && modifier != EXPAND_CONST_ADDRESS
07358 && modifier != EXPAND_INITIALIZER
07359 && modifier != EXPAND_MEMORY
07360 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
07361 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
07362 && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
07363 {
07364 if (TREE_CODE (index) == INTEGER_CST)
07365 {
07366 tree init = DECL_INITIAL (array);
07367
07368 if (TREE_CODE (init) == CONSTRUCTOR)
07369 {
07370 tree elem;
07371
07372 for (elem = CONSTRUCTOR_ELTS (init);
07373 (elem
07374 && !tree_int_cst_equal (TREE_PURPOSE (elem), index));
07375 elem = TREE_CHAIN (elem))
07376 ;
07377
07378 if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
07379 return expand_expr (fold (TREE_VALUE (elem)), target,
07380 tmode, modifier);
07381 }
07382 else if (TREE_CODE (init) == STRING_CST
07383 && 0 > compare_tree_int (index,
07384 TREE_STRING_LENGTH (init)))
07385 {
07386 tree type = TREE_TYPE (TREE_TYPE (init));
07387 enum machine_mode mode = TYPE_MODE (type);
07388
07389 if (GET_MODE_CLASS (mode) == MODE_INT
07390 && GET_MODE_SIZE (mode) == 1)
07391 return gen_int_mode (TREE_STRING_POINTER (init)
07392 [TREE_INT_CST_LOW (index)], mode);
07393 }
07394 }
07395 }
07396 }
07397
07398
07399 case COMPONENT_REF:
07400 case BIT_FIELD_REF:
07401 case ARRAY_RANGE_REF:
07402
07403
07404
07405
07406 if (code == COMPONENT_REF
07407 && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
07408 && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
07409 {
07410 tree elt;
07411
07412 for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
07413 elt = TREE_CHAIN (elt))
07414 if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1)
07415
07416
07417
07418
07419
07420
07421
07422 && (! DECL_BIT_FIELD (TREE_PURPOSE (elt))
07423 || ((GET_MODE_CLASS (DECL_MODE (TREE_PURPOSE (elt)))
07424 == MODE_INT)
07425 && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
07426 <= HOST_BITS_PER_WIDE_INT))))
07427 {
07428 if (DECL_BIT_FIELD (TREE_PURPOSE (elt))
07429 && modifier == EXPAND_STACK_PARM)
07430 target = 0;
07431 op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
07432 if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
07433 {
07434 HOST_WIDE_INT bitsize
07435 = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt)));
07436 enum machine_mode imode
07437 = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt)));
07438
07439 if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt))))
07440 {
07441 op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
07442 op0 = expand_and (imode, op0, op1, target);
07443 }
07444 else
07445 {
07446 tree count
07447 = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize,
07448 0);
07449
07450 op0 = expand_shift (LSHIFT_EXPR, imode, op0, count,
07451 target, 0);
07452 op0 = expand_shift (RSHIFT_EXPR, imode, op0, count,
07453 target, 0);
07454 }
07455 }
07456
07457 return op0;
07458 }
07459 }
07460
07461 {
07462 enum machine_mode mode1;
07463 HOST_WIDE_INT bitsize, bitpos;
07464 tree offset;
07465 int volatilep = 0;
07466 tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
07467 &mode1, &unsignedp, &volatilep);
07468 rtx orig_op0;
07469
07470
07471
07472
07473 if (tem == exp)
07474 abort ();
07475
07476
07477
07478
07479
07480 orig_op0 = op0
07481 = expand_expr (tem,
07482 (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
07483 && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
07484 != INTEGER_CST)
07485 && modifier != EXPAND_STACK_PARM
07486 ? target : NULL_RTX),
07487 VOIDmode,
07488 (modifier == EXPAND_INITIALIZER
07489 || modifier == EXPAND_CONST_ADDRESS
07490 || modifier == EXPAND_STACK_PARM)
07491 ? modifier : EXPAND_NORMAL);
07492
07493
07494
07495 if (CONSTANT_P (op0))
07496 {
07497 enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
07498 if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
07499 && offset == 0)
07500 op0 = force_reg (mode, op0);
07501 else
07502 op0 = validize_mem (force_const_mem (mode, op0));
07503 }
07504
07505 if (offset != 0)
07506 {
07507 rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
07508 EXPAND_SUM);
07509
07510
07511
07512
07513
07514 if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
07515 || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
07516 {
07517
07518
07519 if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
07520 {
07521 put_var_into_stack (TREE_OPERAND (exp, 0),
07522 true);
07523 op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
07524 }
07525 else
07526 {
07527 tree nt
07528 = build_qualified_type (TREE_TYPE (tem),
07529 (TYPE_QUALS (TREE_TYPE (tem))
07530 | TYPE_QUAL_CONST));
07531 rtx memloc = assign_temp (nt, 1, 1, 1);
07532
07533 emit_move_insn (memloc, op0);
07534 op0 = memloc;
07535 }
07536 }
07537
07538 if (GET_CODE (op0) != MEM)
07539 abort ();
07540
07541 #ifdef POINTERS_EXTEND_UNSIGNED
07542 if (GET_MODE (offset_rtx) != Pmode)
07543 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
07544 #else
07545 if (GET_MODE (offset_rtx) != ptr_mode)
07546 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
07547 #endif
07548
07549
07550
07551 if (GET_CODE (op0) == MEM
07552 && GET_MODE (op0) == BLKmode
07553 && GET_MODE (XEXP (op0, 0)) != VOIDmode
07554 && bitsize != 0
07555 && (bitpos % bitsize) == 0
07556 && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
07557 && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
07558 {
07559 op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
07560 bitpos = 0;
07561 }
07562
07563 op0 = offset_address (op0, offset_rtx,
07564 highest_pow2_factor (offset));
07565 }
07566
07567
07568
07569 if (GET_CODE (op0) == MEM && bitpos == 0 && offset != 0
07570 && is_aligning_offset (offset, tem))
07571 set_mem_align (op0, BIGGEST_ALIGNMENT);
07572
07573
07574 if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
07575 {
07576 if (op0 == orig_op0)
07577 op0 = copy_rtx (op0);
07578
07579 MEM_VOLATILE_P (op0) = 1;
07580 }
07581
07582
07583
07584
07585 if (GET_CODE (op0) == CONCAT)
07586 {
07587 if (bitpos != 0 || bitsize != GET_MODE_BITSIZE (GET_MODE (op0)))
07588 abort ();
07589 return op0;
07590 }
07591
07592
07593
07594
07595
07596
07597
07598 if (mode1 == VOIDmode
07599 || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
07600 || (mode1 != BLKmode && ! direct_load[(int) mode1]
07601 && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
07602 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
07603 && modifier != EXPAND_CONST_ADDRESS
07604 && modifier != EXPAND_INITIALIZER)
07605
07606
07607 || (mode1 != BLKmode
07608 && SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0))
07609 && ((TYPE_ALIGN (TREE_TYPE (tem))
07610 < GET_MODE_ALIGNMENT (mode))
07611 || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
07612
07613
07614
07615 || (bitsize >= 0
07616 && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
07617 == INTEGER_CST)
07618 && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
07619 bitsize)))
07620 {
07621 enum machine_mode ext_mode = mode;
07622
07623 if (ext_mode == BLKmode
07624 && ! (target != 0 && GET_CODE (op0) == MEM
07625 && GET_CODE (target) == MEM
07626 && bitpos % BITS_PER_UNIT == 0))
07627 ext_mode = mode_for_size (bitsize, MODE_INT, 1);
07628
07629 if (ext_mode == BLKmode)
07630 {
07631
07632
07633 if (GET_CODE (op0) != MEM
07634 || (target != 0 && GET_CODE (target) != MEM)
07635 || bitpos % BITS_PER_UNIT != 0)
07636 abort ();
07637
07638 op0 = adjust_address (op0, VOIDmode, bitpos / BITS_PER_UNIT);
07639 if (target == 0)
07640 target = assign_temp (type, 0, 1, 1);
07641
07642 emit_block_move (target, op0,
07643 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
07644 / BITS_PER_UNIT),
07645 (modifier == EXPAND_STACK_PARM
07646 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
07647
07648 return target;
07649 }
07650
07651 op0 = validize_mem (op0);
07652
07653 if (GET_CODE (op0) == MEM && GET_CODE (XEXP (op0, 0)) == REG)
07654 mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
07655
07656 op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
07657 (modifier == EXPAND_STACK_PARM
07658 ? NULL_RTX : target),
07659 ext_mode, ext_mode,
07660 int_size_in_bytes (TREE_TYPE (tem)));
07661
07662
07663
07664
07665 if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
07666 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
07667 && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
07668 op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
07669 size_int (GET_MODE_BITSIZE (GET_MODE (op0))
07670 - bitsize),
07671 op0, 1);
07672
07673 if (mode == BLKmode)
07674 {
07675 rtx new = assign_temp (build_qualified_type
07676 ((*lang_hooks.types.type_for_mode)
07677 (ext_mode, 0),
07678 TYPE_QUAL_CONST), 0, 1, 1);
07679
07680 emit_move_insn (new, op0);
07681 op0 = copy_rtx (new);
07682 PUT_MODE (op0, BLKmode);
07683 set_mem_attributes (op0, exp, 1);
07684 }
07685
07686 return op0;
07687 }
07688
07689
07690
07691 if (mode == BLKmode)
07692 mode1 = BLKmode;
07693
07694
07695 if (modifier == EXPAND_CONST_ADDRESS
07696 || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
07697 op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT);
07698 else
07699 op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
07700
07701 if (op0 == orig_op0)
07702 op0 = copy_rtx (op0);
07703
07704 set_mem_attributes (op0, exp, 0);
07705 if (GET_CODE (XEXP (op0, 0)) == REG)
07706 mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
07707
07708 MEM_VOLATILE_P (op0) |= volatilep;
07709 if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
07710 || modifier == EXPAND_CONST_ADDRESS
07711 || modifier == EXPAND_INITIALIZER)
07712 return op0;
07713 else if (target == 0)
07714 target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
07715
07716 convert_move (target, op0, unsignedp);
07717 return target;
07718 }
07719
07720 case VTABLE_REF:
07721 {
07722 rtx insn, before = get_last_insn (), vtbl_ref;
07723
07724
07725 subtarget = expand_expr (TREE_OPERAND (exp, 0), target,
07726 tmode, modifier);
07727
07728
07729 if (REG_P (subtarget))
07730 {
07731 target = subtarget;
07732 insn = get_last_insn ();
07733 if (insn == before)
07734 abort ();
07735 if (! INSN_P (insn))
07736 insn = prev_nonnote_insn (insn);
07737 }
07738 else
07739 {
07740 target = gen_reg_rtx (GET_MODE (subtarget));
07741 insn = emit_move_insn (target, subtarget);
07742 }
07743
07744
07745 vtbl_ref = XEXP (DECL_RTL (TREE_OPERAND (exp, 1)), 0);
07746 vtbl_ref = plus_constant (vtbl_ref,
07747 tree_low_cst (TREE_OPERAND (exp, 2), 0));
07748
07749 vtbl_ref = XEXP (vtbl_ref, 0);
07750
07751 REG_NOTES (insn)
07752 = gen_rtx_EXPR_LIST (REG_VTABLE_REF, vtbl_ref, REG_NOTES (insn));
07753
07754 return target;
07755 }
07756
07757
07758
07759
07760 case BUFFER_REF:
07761 abort ();
07762
07763 case IN_EXPR:
07764 {
07765
07766
07767
07768
07769
07770
07771
07772
07773
07774 tree set = TREE_OPERAND (exp, 0);
07775 tree index = TREE_OPERAND (exp, 1);
07776 int iunsignedp = TREE_UNSIGNED (TREE_TYPE (index));
07777 tree set_type = TREE_TYPE (set);
07778 tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type));
07779 tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type));
07780 rtx index_val = expand_expr (index, 0, VOIDmode, 0);
07781 rtx lo_r = expand_expr (set_low_bound, 0, VOIDmode, 0);
07782 rtx hi_r = expand_expr (set_high_bound, 0, VOIDmode, 0);
07783 rtx setval = expand_expr (set, 0, VOIDmode, 0);
07784 rtx setaddr = XEXP (setval, 0);
07785 enum machine_mode index_mode = TYPE_MODE (TREE_TYPE (index));
07786 rtx rlow;
07787 rtx diff, quo, rem, addr, bit, result;
07788
07789
07790
07791 if (((TREE_CODE (set_high_bound) == INTEGER_CST
07792 && TREE_CODE (set_low_bound) == INTEGER_CST
07793 && tree_int_cst_lt (set_high_bound, set_low_bound))
07794 || (TREE_CODE (index) == INTEGER_CST
07795 && TREE_CODE (set_low_bound) == INTEGER_CST
07796 && tree_int_cst_lt (index, set_low_bound))
07797 || (TREE_CODE (set_high_bound) == INTEGER_CST
07798 && TREE_CODE (index) == INTEGER_CST
07799 && tree_int_cst_lt (set_high_bound, index))))
07800 return const0_rtx;
07801
07802 if (target == 0)
07803 target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
07804
07805
07806
07807
07808 op0 = gen_label_rtx ();
07809 op1 = gen_label_rtx ();
07810
07811 if (! (GET_CODE (index_val) == CONST_INT
07812 && GET_CODE (lo_r) == CONST_INT))
07813 emit_cmp_and_jump_insns (index_val, lo_r, LT, NULL_RTX,
07814 GET_MODE (index_val), iunsignedp, op1);
07815
07816 if (! (GET_CODE (index_val) == CONST_INT
07817 && GET_CODE (hi_r) == CONST_INT))
07818 emit_cmp_and_jump_insns (index_val, hi_r, GT, NULL_RTX,
07819 GET_MODE (index_val), iunsignedp, op1);
07820
07821
07822
07823 if (GET_CODE (lo_r) == CONST_INT)
07824 rlow = GEN_INT (INTVAL (lo_r)
07825 & ~((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
07826 else
07827 rlow = expand_binop (index_mode, and_optab, lo_r,
07828 GEN_INT (~((HOST_WIDE_INT) 1 << BITS_PER_UNIT)),
07829 NULL_RTX, iunsignedp, OPTAB_LIB_WIDEN);
07830
07831 diff = expand_binop (index_mode, sub_optab, index_val, rlow,
07832 NULL_RTX, iunsignedp, OPTAB_LIB_WIDEN);
07833
07834 quo = expand_divmod (0, TRUNC_DIV_EXPR, index_mode, diff,
07835 GEN_INT (BITS_PER_UNIT), NULL_RTX, iunsignedp);
07836 rem = expand_divmod (1, TRUNC_MOD_EXPR, index_mode, index_val,
07837 GEN_INT (BITS_PER_UNIT), NULL_RTX, iunsignedp);
07838
07839 addr = memory_address (byte_mode,
07840 expand_binop (index_mode, add_optab, diff,
07841 setaddr, NULL_RTX, iunsignedp,
07842 OPTAB_LIB_WIDEN));
07843
07844
07845 bit = expand_shift (RSHIFT_EXPR, byte_mode,
07846 gen_rtx_MEM (byte_mode, addr),
07847 make_tree (TREE_TYPE (index), rem),
07848 NULL_RTX, 1);
07849 result = expand_binop (byte_mode, and_optab, bit, const1_rtx,
07850 GET_MODE (target) == byte_mode ? target : 0,
07851 1, OPTAB_LIB_WIDEN);
07852
07853 if (result != target)
07854 convert_move (target, result, 1);
07855
07856
07857 emit_jump (op0);
07858 emit_label (op1);
07859 emit_move_insn (target, const0_rtx);
07860 emit_label (op0);
07861 return target;
07862 }
07863
07864 case WITH_CLEANUP_EXPR:
07865 if (WITH_CLEANUP_EXPR_RTL (exp) == 0)
07866 {
07867 WITH_CLEANUP_EXPR_RTL (exp)
07868 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
07869 expand_decl_cleanup_eh (NULL_TREE, TREE_OPERAND (exp, 1),
07870 CLEANUP_EH_ONLY (exp));
07871
07872
07873 TREE_OPERAND (exp, 1) = 0;
07874 }
07875 return WITH_CLEANUP_EXPR_RTL (exp);
07876
07877 case CLEANUP_POINT_EXPR:
07878 {
07879
07880
07881 expand_start_bindings (2);
07882
07883 target_temp_slot_level = temp_slot_level;
07884
07885 op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
07886
07887 if (! ignore)
07888 op0 = force_not_mem (op0);
07889 preserve_temp_slots (op0);
07890 expand_end_bindings (NULL_TREE, 0, 0);
07891 }
07892 return op0;
07893
07894 case CALL_EXPR:
07895
07896 if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
07897 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
07898 == FUNCTION_DECL)
07899 && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
07900 {
07901 if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
07902 == BUILT_IN_FRONTEND)
07903 return (*lang_hooks.expand_expr) (exp, original_target,
07904 tmode, modifier);
07905 else
07906 return expand_builtin (exp, target, subtarget, tmode, ignore);
07907 }
07908
07909 return expand_call (exp, target, ignore);
07910
07911 case NON_LVALUE_EXPR:
07912 case NOP_EXPR:
07913 case CONVERT_EXPR:
07914 case REFERENCE_EXPR:
07915 if (TREE_OPERAND (exp, 0) == error_mark_node)
07916 return const0_rtx;
07917
07918 if (TREE_CODE (type) == UNION_TYPE)
07919 {
07920 tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
07921
07922
07923
07924 if (mode == BLKmode && TYPE_MODE (valtype) == BLKmode)
07925 {
07926 rtx result = expand_expr (TREE_OPERAND (exp, 0), target, tmode,
07927 modifier);
07928
07929 result = copy_rtx (result);
07930 set_mem_attributes (result, exp, 0);
07931 return result;
07932 }
07933
07934 if (target == 0)
07935 target = assign_temp (type, 0, 1, 1);
07936
07937 if (GET_CODE (target) == MEM)
07938
07939 store_expr (TREE_OPERAND (exp, 0),
07940 adjust_address (target, TYPE_MODE (valtype), 0),
07941 modifier == EXPAND_STACK_PARM ? 2 : 0);
07942
07943 else if (GET_CODE (target) == REG)
07944
07945 store_field (target,
07946 MIN ((int_size_in_bytes (TREE_TYPE
07947 (TREE_OPERAND (exp, 0)))
07948 * BITS_PER_UNIT),
07949 (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
07950 0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
07951 VOIDmode, 0, type, 0);
07952 else
07953 abort ();
07954
07955
07956 return target;
07957 }
07958
07959 if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
07960 {
07961 op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
07962 modifier);
07963
07964
07965
07966
07967 if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) != unsignedp
07968 && GET_CODE (op0) == SUBREG)
07969 SUBREG_PROMOTED_VAR_P (op0) = 0;
07970
07971 return op0;
07972 }
07973
07974 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
07975 if (GET_MODE (op0) == mode)
07976 return op0;
07977
07978
07979 if (CONSTANT_P (op0))
07980 {
07981 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
07982 enum machine_mode inner_mode = TYPE_MODE (inner_type);
07983
07984 if (modifier == EXPAND_INITIALIZER)
07985 return simplify_gen_subreg (mode, op0, inner_mode,
07986 subreg_lowpart_offset (mode,
07987 inner_mode));
07988 else
07989 return convert_modes (mode, inner_mode, op0,
07990 TREE_UNSIGNED (inner_type));
07991 }
07992
07993 if (modifier == EXPAND_INITIALIZER)
07994 return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
07995
07996 if (target == 0)
07997 return
07998 convert_to_mode (mode, op0,
07999 TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
08000 else
08001 convert_move (target, op0,
08002 TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
08003 return target;
08004
08005 case VIEW_CONVERT_EXPR:
08006 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
08007
08008
08009
08010
08011
08012 if (TYPE_MODE (type) == GET_MODE (op0))
08013 ;
08014 else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode
08015 && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD
08016 && GET_MODE_SIZE (GET_MODE (op0)) <= UNITS_PER_WORD)
08017 op0 = gen_lowpart (TYPE_MODE (type), op0);
08018 else if (GET_CODE (op0) != MEM)
08019 {
08020
08021
08022
08023
08024 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
08025
08026 if (TREE_ADDRESSABLE (exp))
08027 abort ();
08028
08029 if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
08030 target
08031 = assign_stack_temp_for_type
08032 (TYPE_MODE (inner_type),
08033 GET_MODE_SIZE (TYPE_MODE (inner_type)), 0, inner_type);
08034
08035 emit_move_insn (target, op0);
08036 op0 = target;
08037 }
08038
08039
08040
08041
08042
08043 if (GET_CODE (op0) == MEM)
08044 {
08045 op0 = copy_rtx (op0);
08046
08047 if (TYPE_ALIGN_OK (type))
08048 set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
08049 else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT
08050 && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
08051 {
08052 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
08053 HOST_WIDE_INT temp_size
08054 = MAX (int_size_in_bytes (inner_type),
08055 (HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type)));
08056 rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
08057 temp_size, 0, type);
08058 rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
08059
08060 if (TREE_ADDRESSABLE (exp))
08061 abort ();
08062
08063 if (GET_MODE (op0) == BLKmode)
08064 emit_block_move (new_with_op0_mode, op0,
08065 GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))),
08066 (modifier == EXPAND_STACK_PARM
08067 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
08068 else
08069 emit_move_insn (new_with_op0_mode, op0);
08070
08071 op0 = new;
08072 }
08073
08074 op0 = adjust_address (op0, TYPE_MODE (type), 0);
08075 }
08076
08077 return op0;
08078
08079 case PLUS_EXPR:
08080 this_optab = ! unsignedp && flag_trapv
08081 && (GET_MODE_CLASS (mode) == MODE_INT)
08082 ? addv_optab : add_optab;
08083
08084
08085
08086
08087
08088
08089
08090
08091
08092
08093
08094
08095 if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
08096 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
08097 && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR
08098 && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
08099 || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
08100 || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
08101 {
08102 tree t = TREE_OPERAND (exp, 1);
08103
08104 TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
08105 TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t;
08106 }
08107
08108
08109
08110
08111
08112
08113
08114
08115
08116 if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
08117 || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
08118 {
08119 if (modifier == EXPAND_STACK_PARM)
08120 target = 0;
08121 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
08122 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
08123 && TREE_CONSTANT (TREE_OPERAND (exp, 1)))
08124 {
08125 rtx constant_part;
08126
08127 op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode,
08128 EXPAND_SUM);
08129
08130
08131
08132
08133 constant_part
08134 = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)),
08135 (HOST_WIDE_INT) 0,
08136 TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))));
08137 op1 = plus_constant (op1, INTVAL (constant_part));
08138 if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
08139 op1 = force_operand (op1, target);
08140 return op1;
08141 }
08142
08143 else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
08144 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT
08145 && TREE_CONSTANT (TREE_OPERAND (exp, 0)))
08146 {
08147 rtx constant_part;
08148
08149 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
08150 (modifier == EXPAND_INITIALIZER
08151 ? EXPAND_INITIALIZER : EXPAND_SUM));
08152 if (! CONSTANT_P (op0))
08153 {
08154 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
08155 VOIDmode, modifier);
08156
08157
08158 if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
08159 goto binop2;
08160 goto both_summands;
08161 }
08162
08163
08164
08165
08166 constant_part
08167 = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)),
08168 (HOST_WIDE_INT) 0,
08169 TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))));
08170 op0 = plus_constant (op0, INTVAL (constant_part));
08171 if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
08172 op0 = force_operand (op0, target);
08173 return op0;
08174 }
08175 }
08176
08177 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
08178 subtarget = 0;
08179
08180
08181
08182
08183
08184 if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
08185 || mode != ptr_mode)
08186 {
08187 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08188 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
08189 if (op0 == const0_rtx)
08190 return op1;
08191 if (op1 == const0_rtx)
08192 return op0;
08193 goto binop2;
08194 }
08195
08196 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
08197 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
08198
08199
08200
08201 both_summands:
08202
08203 if (GET_CODE (op0) == PLUS
08204 && CONSTANT_P (XEXP (op0, 1)))
08205 {
08206 temp = op0;
08207 op0 = op1;
08208 op1 = temp;
08209 }
08210
08211
08212 if (GET_CODE (op1) == PLUS
08213 && CONSTANT_P (XEXP (op1, 1)))
08214 {
08215 rtx constant_term = const0_rtx;
08216
08217 temp = simplify_binary_operation (PLUS, mode, XEXP (op1, 0), op0);
08218 if (temp != 0)
08219 op0 = temp;
08220
08221 else if (GET_CODE (op0) == MULT)
08222 op0 = gen_rtx_PLUS (mode, op0, XEXP (op1, 0));
08223 else
08224 op0 = gen_rtx_PLUS (mode, XEXP (op1, 0), op0);
08225
08226
08227 op0 = eliminate_constant_term (op0, &constant_term);
08228
08229
08230
08231
08232
08233 temp = simplify_binary_operation (PLUS, mode, constant_term,
08234 XEXP (op1, 1));
08235 if (temp != 0)
08236 op1 = temp;
08237 else
08238 op1 = gen_rtx_PLUS (mode, constant_term, XEXP (op1, 1));
08239 }
08240
08241
08242 if (CONSTANT_P (op0) || GET_CODE (op1) == MULT)
08243 temp = op1, op1 = op0, op0 = temp;
08244
08245 temp = simplify_binary_operation (PLUS, mode, op0, op1);
08246 return temp ? temp : gen_rtx_PLUS (mode, op0, op1);
08247
08248 case MINUS_EXPR:
08249
08250
08251
08252
08253
08254 if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
08255 && really_constant_p (TREE_OPERAND (exp, 0))
08256 && really_constant_p (TREE_OPERAND (exp, 1)))
08257 {
08258 rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode,
08259 modifier);
08260 rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
08261 modifier);
08262
08263
08264
08265 if (GET_CODE (op1) == CONST_INT)
08266 return plus_constant (op0, - INTVAL (op1));
08267 else
08268 return gen_rtx_MINUS (mode, op0, op1);
08269 }
08270
08271 this_optab = ! unsignedp && flag_trapv
08272 && (GET_MODE_CLASS(mode) == MODE_INT)
08273 ? subv_optab : sub_optab;
08274
08275
08276
08277
08278
08279 if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
08280 || mode != ptr_mode)
08281 goto binop;
08282
08283 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
08284 subtarget = 0;
08285
08286 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
08287 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
08288
08289
08290 if (GET_CODE (op1) == CONST_INT)
08291 {
08292 op1 = negate_rtx (mode, op1);
08293 goto both_summands;
08294 }
08295
08296 goto binop2;
08297
08298 case MULT_EXPR:
08299
08300
08301
08302 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
08303 {
08304 tree t1 = TREE_OPERAND (exp, 0);
08305 TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
08306 TREE_OPERAND (exp, 1) = t1;
08307 }
08308
08309
08310
08311
08312 if (modifier == EXPAND_SUM && mode == ptr_mode
08313 && host_integerp (TREE_OPERAND (exp, 1), 0))
08314 {
08315 tree exp1 = TREE_OPERAND (exp, 1);
08316
08317 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
08318 EXPAND_SUM);
08319
08320
08321
08322
08323
08324
08325
08326
08327
08328
08329
08330 if (GET_CODE (op0) != REG)
08331 op0 = force_operand (op0, NULL_RTX);
08332 if (GET_CODE (op0) != REG)
08333 op0 = copy_to_mode_reg (mode, op0);
08334
08335 return gen_rtx_MULT (mode, op0,
08336 gen_int_mode (tree_low_cst (exp1, 0),
08337 TYPE_MODE (TREE_TYPE (exp1))));
08338 }
08339
08340 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
08341 subtarget = 0;
08342
08343 if (modifier == EXPAND_STACK_PARM)
08344 target = 0;
08345
08346
08347
08348
08349
08350 if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
08351 && TREE_CODE (type) == INTEGER_TYPE
08352 && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
08353 < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
08354 && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
08355 && int_fits_type_p (TREE_OPERAND (exp, 1),
08356 TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
08357
08358 && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))))
08359 > HOST_BITS_PER_WIDE_INT)
08360 || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
08361 ||
08362 (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
08363 && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
08364 ==
08365 TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
08366
08367
08368 && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
08369 ==
08370 TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
08371 {
08372 enum machine_mode innermode
08373 = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
08374 optab other_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
08375 ? smul_widen_optab : umul_widen_optab);
08376 this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
08377 ? umul_widen_optab : smul_widen_optab);
08378 if (mode == GET_MODE_WIDER_MODE (innermode))
08379 {
08380 if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
08381 {
08382 op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
08383 NULL_RTX, VOIDmode, 0);
08384 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
08385 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
08386 VOIDmode, 0);
08387 else
08388 op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
08389 NULL_RTX, VOIDmode, 0);
08390 goto binop2;
08391 }
08392 else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
08393 && innermode == word_mode)
08394 {
08395 rtx htem;
08396 op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
08397 NULL_RTX, VOIDmode, 0);
08398 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
08399 op1 = convert_modes (innermode, mode,
08400 expand_expr (TREE_OPERAND (exp, 1),
08401 NULL_RTX, VOIDmode, 0),
08402 unsignedp);
08403 else
08404 op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
08405 NULL_RTX, VOIDmode, 0);
08406 temp = expand_binop (mode, other_optab, op0, op1, target,
08407 unsignedp, OPTAB_LIB_WIDEN);
08408 htem = expand_mult_highpart_adjust (innermode,
08409 gen_highpart (innermode, temp),
08410 op0, op1,
08411 gen_highpart (innermode, temp),
08412 unsignedp);
08413 emit_move_insn (gen_highpart (innermode, temp), htem);
08414 return temp;
08415 }
08416 }
08417 }
08418 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08419 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
08420 return expand_mult (mode, op0, op1, target, unsignedp);
08421
08422 case TRUNC_DIV_EXPR:
08423 case FLOOR_DIV_EXPR:
08424 case CEIL_DIV_EXPR:
08425 case ROUND_DIV_EXPR:
08426 case EXACT_DIV_EXPR:
08427 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
08428 subtarget = 0;
08429 if (modifier == EXPAND_STACK_PARM)
08430 target = 0;
08431
08432
08433
08434 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08435 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
08436 return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
08437
08438 case RDIV_EXPR:
08439
08440
08441
08442 if (flag_unsafe_math_optimizations && optimize && !optimize_size
08443 && TREE_CODE (type) == REAL_TYPE
08444 && !real_onep (TREE_OPERAND (exp, 0)))
08445 return expand_expr (build (MULT_EXPR, type, TREE_OPERAND (exp, 0),
08446 build (RDIV_EXPR, type,
08447 build_real (type, dconst1),
08448 TREE_OPERAND (exp, 1))),
08449 target, tmode, modifier);
08450 this_optab = sdiv_optab;
08451 goto binop;
08452
08453 case TRUNC_MOD_EXPR:
08454 case FLOOR_MOD_EXPR:
08455 case CEIL_MOD_EXPR:
08456 case ROUND_MOD_EXPR:
08457 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
08458 subtarget = 0;
08459 if (modifier == EXPAND_STACK_PARM)
08460 target = 0;
08461 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08462 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
08463 return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
08464
08465 case FIX_ROUND_EXPR:
08466 case FIX_FLOOR_EXPR:
08467 case FIX_CEIL_EXPR:
08468 abort ();
08469
08470 case FIX_TRUNC_EXPR:
08471 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
08472 if (target == 0 || modifier == EXPAND_STACK_PARM)
08473 target = gen_reg_rtx (mode);
08474 expand_fix (target, op0, unsignedp);
08475 return target;
08476
08477 case FLOAT_EXPR:
08478 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
08479 if (target == 0 || modifier == EXPAND_STACK_PARM)
08480 target = gen_reg_rtx (mode);
08481
08482
08483 if (GET_MODE (op0) == VOIDmode)
08484 op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
08485 op0);
08486 expand_float (target, op0,
08487 TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
08488 return target;
08489
08490 case NEGATE_EXPR:
08491 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08492 if (modifier == EXPAND_STACK_PARM)
08493 target = 0;
08494 temp = expand_unop (mode,
08495 ! unsignedp && flag_trapv
08496 && (GET_MODE_CLASS(mode) == MODE_INT)
08497 ? negv_optab : neg_optab, op0, target, 0);
08498 if (temp == 0)
08499 abort ();
08500 return temp;
08501
08502 case ABS_EXPR:
08503 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08504 if (modifier == EXPAND_STACK_PARM)
08505 target = 0;
08506
08507
08508 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
08509 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
08510 return expand_complex_abs (mode, op0, target, unsignedp);
08511
08512
08513
08514 if (TREE_UNSIGNED (type))
08515 return op0;
08516
08517 return expand_abs (mode, op0, target, unsignedp,
08518 safe_from_p (target, TREE_OPERAND (exp, 0), 1));
08519
08520 case MAX_EXPR:
08521 case MIN_EXPR:
08522 target = original_target;
08523 if (target == 0
08524 || modifier == EXPAND_STACK_PARM
08525 || ! safe_from_p (target, TREE_OPERAND (exp, 1), 1)
08526 || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
08527 || GET_MODE (target) != mode
08528 || (GET_CODE (target) == REG
08529 && REGNO (target) < FIRST_PSEUDO_REGISTER))
08530 target = gen_reg_rtx (mode);
08531 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
08532 op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
08533
08534
08535
08536
08537 this_optab = (TREE_UNSIGNED (type)
08538 ? (code == MIN_EXPR ? umin_optab : umax_optab)
08539 : (code == MIN_EXPR ? smin_optab : smax_optab));
08540
08541 temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
08542 OPTAB_WIDEN);
08543 if (temp != 0)
08544 return temp;
08545
08546
08547
08548
08549 if (GET_CODE (target) == MEM)
08550 target = gen_reg_rtx (mode);
08551
08552 if (target != op0)
08553 emit_move_insn (target, op0);
08554
08555 op0 = gen_label_rtx ();
08556
08557
08558
08559 if (GET_MODE_CLASS (mode) == MODE_INT
08560 && ! can_compare_p (GE, mode, ccp_jump))
08561 {
08562 if (code == MAX_EXPR)
08563 do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
08564 target, op1, NULL_RTX, op0);
08565 else
08566 do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
08567 op1, target, NULL_RTX, op0);
08568 }
08569 else
08570 {
08571 int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)));
08572 do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE,
08573 unsignedp, mode, NULL_RTX, NULL_RTX,
08574 op0);
08575 }
08576 emit_move_insn (target, op1);
08577 emit_label (op0);
08578 return target;
08579
08580 case BIT_NOT_EXPR:
08581 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08582 if (modifier == EXPAND_STACK_PARM)
08583 target = 0;
08584 temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
08585 if (temp == 0)
08586 abort ();
08587 return temp;
08588
08589 case FFS_EXPR:
08590 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08591 if (modifier == EXPAND_STACK_PARM)
08592 target = 0;
08593 temp = expand_unop (mode, ffs_optab, op0, target, 1);
08594 if (temp == 0)
08595 abort ();
08596 return temp;
08597
08598
08599
08600
08601
08602
08603
08604
08605
08606
08607
08608
08609
08610
08611 case TRUTH_AND_EXPR:
08612 case BIT_AND_EXPR:
08613 this_optab = and_optab;
08614 goto binop;
08615
08616 case TRUTH_OR_EXPR:
08617 case BIT_IOR_EXPR:
08618 this_optab = ior_optab;
08619 goto binop;
08620
08621 case TRUTH_XOR_EXPR:
08622 case BIT_XOR_EXPR:
08623 this_optab = xor_optab;
08624 goto binop;
08625
08626 case LSHIFT_EXPR:
08627 case RSHIFT_EXPR:
08628 case LROTATE_EXPR:
08629 case RROTATE_EXPR:
08630 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
08631 subtarget = 0;
08632 if (modifier == EXPAND_STACK_PARM)
08633 target = 0;
08634 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
08635 return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
08636 unsignedp);
08637
08638
08639
08640 case LT_EXPR:
08641 case LE_EXPR:
08642 case GT_EXPR:
08643 case GE_EXPR:
08644 case EQ_EXPR:
08645 case NE_EXPR:
08646 case UNORDERED_EXPR:
08647 case ORDERED_EXPR:
08648 case UNLT_EXPR:
08649 case UNLE_EXPR:
08650 case UNGT_EXPR:
08651 case UNGE_EXPR:
08652 case UNEQ_EXPR:
08653 temp = do_store_flag (exp,
08654 modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
08655 tmode != VOIDmode ? tmode : mode, 0);
08656 if (temp != 0)
08657 return temp;
08658
08659
08660 if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
08661 && original_target
08662 && GET_CODE (original_target) == REG
08663 && (GET_MODE (original_target)
08664 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
08665 {
08666 temp = expand_expr (TREE_OPERAND (exp, 0), original_target,
08667 VOIDmode, 0);
08668
08669
08670 if (GET_CODE (temp) == CONST_INT)
08671 {
08672 if (INTVAL (temp) != 0)
08673 emit_move_insn (target, const1_rtx);
08674 else
08675 emit_move_insn (target, const0_rtx);
08676
08677 return target;
08678 }
08679
08680 if (temp != original_target)
08681 {
08682 enum machine_mode mode1 = GET_MODE (temp);
08683 if (mode1 == VOIDmode)
08684 mode1 = tmode != VOIDmode ? tmode : mode;
08685
08686 temp = copy_to_mode_reg (mode1, temp);
08687 }
08688
08689 op1 = gen_label_rtx ();
08690 emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
08691 GET_MODE (temp), unsignedp, op1);
08692 emit_move_insn (temp, const1_rtx);
08693 emit_label (op1);
08694 return temp;
08695 }
08696
08697
08698
08699
08700
08701 case TRUTH_ANDIF_EXPR:
08702 case TRUTH_ORIF_EXPR:
08703 if (! ignore
08704 && (target == 0
08705 || modifier == EXPAND_STACK_PARM
08706 || ! safe_from_p (target, exp, 1)
08707
08708
08709 || (!optimize && GET_CODE (target) == REG
08710 && REGNO (target) < FIRST_PSEUDO_REGISTER)))
08711 target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
08712
08713 if (target)
08714 emit_clr_insn (target);
08715
08716 op1 = gen_label_rtx ();
08717 jumpifnot (exp, op1);
08718
08719 if (target)
08720 emit_0_to_1_insn (target);
08721
08722 emit_label (op1);
08723 return ignore ? const0_rtx : target;
08724
08725 case TRUTH_NOT_EXPR:
08726 if (modifier == EXPAND_STACK_PARM)
08727 target = 0;
08728 op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
08729
08730
08731 temp = expand_binop (mode, xor_optab, op0, const1_rtx,
08732 target, 1, OPTAB_LIB_WIDEN);
08733 if (temp == 0)
08734 abort ();
08735 return temp;
08736
08737 case COMPOUND_EXPR:
08738 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
08739 emit_queue ();
08740 return expand_expr (TREE_OPERAND (exp, 1),
08741 (ignore ? const0_rtx : target),
08742 VOIDmode, modifier);
08743
08744 case COND_EXPR:
08745
08746
08747 if (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
08748 && TREE_CODE (TREE_OPERAND (exp, 2)) == NOP_EXPR
08749 && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))
08750 == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 2), 0))))
08751 {
08752 tree iftrue = TREE_OPERAND (TREE_OPERAND (exp, 1), 0);
08753 tree iffalse = TREE_OPERAND (TREE_OPERAND (exp, 2), 0);
08754
08755 if ((TREE_CODE_CLASS (TREE_CODE (iftrue)) == '2'
08756 && operand_equal_p (iffalse, TREE_OPERAND (iftrue, 0), 0))
08757 || (TREE_CODE_CLASS (TREE_CODE (iffalse)) == '2'
08758 && operand_equal_p (iftrue, TREE_OPERAND (iffalse, 0), 0))
08759 || (TREE_CODE_CLASS (TREE_CODE (iftrue)) == '1'
08760 && operand_equal_p (iffalse, TREE_OPERAND (iftrue, 0), 0))
08761 || (TREE_CODE_CLASS (TREE_CODE (iffalse)) == '1'
08762 && operand_equal_p (iftrue, TREE_OPERAND (iffalse, 0), 0)))
08763 return expand_expr (build1 (NOP_EXPR, type,
08764 build (COND_EXPR, TREE_TYPE (iftrue),
08765 TREE_OPERAND (exp, 0),
08766 iftrue, iffalse)),
08767 target, tmode, modifier);
08768 }
08769
08770 {
08771
08772
08773
08774
08775
08776
08777
08778
08779 tree singleton = 0;
08780 tree binary_op = 0, unary_op = 0;
08781
08782
08783
08784 if (integer_onep (TREE_OPERAND (exp, 1))
08785 && integer_zerop (TREE_OPERAND (exp, 2))
08786 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
08787 {
08788 if (ignore)
08789 {
08790 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
08791 modifier);
08792 return const0_rtx;
08793 }
08794
08795 if (modifier == EXPAND_STACK_PARM)
08796 target = 0;
08797 op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
08798 if (GET_MODE (op0) == mode)
08799 return op0;
08800
08801 if (target == 0)
08802 target = gen_reg_rtx (mode);
08803 convert_move (target, op0, unsignedp);
08804 return target;
08805 }
08806
08807
08808
08809
08810
08811
08812
08813 if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2'
08814 && operand_equal_p (TREE_OPERAND (exp, 2),
08815 TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
08816 singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1);
08817 else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2'
08818 && operand_equal_p (TREE_OPERAND (exp, 1),
08819 TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
08820 singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2);
08821 else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1'
08822 && operand_equal_p (TREE_OPERAND (exp, 2),
08823 TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
08824 singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1);
08825 else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1'
08826 && operand_equal_p (TREE_OPERAND (exp, 1),
08827 TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
08828 singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2);
08829
08830
08831
08832
08833
08834
08835 if (ignore)
08836 temp = 0;
08837 else if (modifier == EXPAND_STACK_PARM)
08838 temp = assign_temp (type, 0, 0, 1);
08839 else if (original_target
08840 && (safe_from_p (original_target, TREE_OPERAND (exp, 0), 1)
08841 || (singleton && GET_CODE (original_target) == REG
08842 && REGNO (original_target) >= FIRST_PSEUDO_REGISTER
08843 && original_target == var_rtx (singleton)))
08844 && GET_MODE (original_target) == mode
08845 #ifdef HAVE_conditional_move
08846 && (! can_conditionally_move_p (mode)
08847 || GET_CODE (original_target) == REG
08848 || TREE_ADDRESSABLE (type))
08849 #endif
08850 && (GET_CODE (original_target) != MEM
08851 || TREE_ADDRESSABLE (type)))
08852 temp = original_target;
08853 else if (TREE_ADDRESSABLE (type))
08854 abort ();
08855 else
08856 temp = assign_temp (type, 0, 0, 1);
08857
08858
08859
08860
08861
08862 if (temp && singleton && binary_op
08863 && (TREE_CODE (binary_op) == PLUS_EXPR
08864 || TREE_CODE (binary_op) == MINUS_EXPR
08865 || TREE_CODE (binary_op) == BIT_IOR_EXPR
08866 || TREE_CODE (binary_op) == BIT_XOR_EXPR)
08867 && (BRANCH_COST >= 3 ? integer_pow2p (TREE_OPERAND (binary_op, 1))
08868 : integer_onep (TREE_OPERAND (binary_op, 1)))
08869 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
08870 {
08871 rtx result;
08872 tree cond;
08873 optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
08874 ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
08875 ? addv_optab : add_optab)
08876 : TREE_CODE (binary_op) == MINUS_EXPR
08877 ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
08878 ? subv_optab : sub_optab)
08879 : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
08880 : xor_optab);
08881
08882
08883 if (singleton == TREE_OPERAND (exp, 1))
08884 cond = invert_truthvalue (TREE_OPERAND (exp, 0));
08885 else
08886 cond = TREE_OPERAND (exp, 0);
08887
08888 result = do_store_flag (cond, (safe_from_p (temp, singleton, 1)
08889 ? temp : NULL_RTX),
08890 mode, BRANCH_COST <= 1);
08891
08892 if (result != 0 && ! integer_onep (TREE_OPERAND (binary_op, 1)))
08893 result = expand_shift (LSHIFT_EXPR, mode, result,
08894 build_int_2 (tree_log2
08895 (TREE_OPERAND
08896 (binary_op, 1)),
08897 0),
08898 (safe_from_p (temp, singleton, 1)
08899 ? temp : NULL_RTX), 0);
08900
08901 if (result)
08902 {
08903 op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0);
08904 return expand_binop (mode, boptab, op1, result, temp,
08905 unsignedp, OPTAB_LIB_WIDEN);
08906 }
08907 }
08908
08909 do_pending_stack_adjust ();
08910 NO_DEFER_POP;
08911 op0 = gen_label_rtx ();
08912
08913 if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
08914 {
08915 if (temp != 0)
08916 {
08917
08918
08919
08920
08921 if ((binary_op
08922 && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1), 1))
08923 || (GET_CODE (temp) == REG
08924 && REGNO (temp) < FIRST_PSEUDO_REGISTER))
08925 temp = gen_reg_rtx (mode);
08926 store_expr (singleton, temp,
08927 modifier == EXPAND_STACK_PARM ? 2 : 0);
08928 }
08929 else
08930 expand_expr (singleton,
08931 ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
08932 if (singleton == TREE_OPERAND (exp, 1))
08933 jumpif (TREE_OPERAND (exp, 0), op0);
08934 else
08935 jumpifnot (TREE_OPERAND (exp, 0), op0);
08936
08937 start_cleanup_deferral ();
08938 if (binary_op && temp == 0)
08939
08940 expand_expr (TREE_OPERAND (binary_op, 1),
08941 ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
08942 else if (binary_op)
08943 store_expr (build (TREE_CODE (binary_op), type,
08944 make_tree (type, temp),
08945 TREE_OPERAND (binary_op, 1)),
08946 temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
08947 else
08948 store_expr (build1 (TREE_CODE (unary_op), type,
08949 make_tree (type, temp)),
08950 temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
08951 op1 = op0;
08952 }
08953
08954
08955
08956
08957 else if (temp
08958 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
08959 && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
08960 && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
08961 TREE_OPERAND (exp, 1), 0)
08962 && (! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
08963 || TREE_CODE (TREE_OPERAND (exp, 1)) == SAVE_EXPR)
08964 && safe_from_p (temp, TREE_OPERAND (exp, 2), 1))
08965 {
08966 if (GET_CODE (temp) == REG
08967 && REGNO (temp) < FIRST_PSEUDO_REGISTER)
08968 temp = gen_reg_rtx (mode);
08969 store_expr (TREE_OPERAND (exp, 1), temp,
08970 modifier == EXPAND_STACK_PARM ? 2 : 0);
08971 jumpif (TREE_OPERAND (exp, 0), op0);
08972
08973 start_cleanup_deferral ();
08974 store_expr (TREE_OPERAND (exp, 2), temp,
08975 modifier == EXPAND_STACK_PARM ? 2 : 0);
08976 op1 = op0;
08977 }
08978 else if (temp
08979 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
08980 && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
08981 && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
08982 TREE_OPERAND (exp, 2), 0)
08983 && (! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
08984 || TREE_CODE (TREE_OPERAND (exp, 2)) == SAVE_EXPR)
08985 && safe_from_p (temp, TREE_OPERAND (exp, 1), 1))
08986 {
08987 if (GET_CODE (temp) == REG
08988 && REGNO (temp) < FIRST_PSEUDO_REGISTER)
08989 temp = gen_reg_rtx (mode);
08990 store_expr (TREE_OPERAND (exp, 2), temp,
08991 modifier == EXPAND_STACK_PARM ? 2 : 0);
08992 jumpifnot (TREE_OPERAND (exp, 0), op0);
08993
08994 start_cleanup_deferral ();
08995 store_expr (TREE_OPERAND (exp, 1), temp,
08996 modifier == EXPAND_STACK_PARM ? 2 : 0);
08997 op1 = op0;
08998 }
08999 else
09000 {
09001 op1 = gen_label_rtx ();
09002 jumpifnot (TREE_OPERAND (exp, 0), op0);
09003
09004 start_cleanup_deferral ();
09005
09006
09007
09008 if (temp != 0
09009 && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
09010 store_expr (TREE_OPERAND (exp, 1), temp,
09011 modifier == EXPAND_STACK_PARM ? 2 : 0);
09012 else
09013 expand_expr (TREE_OPERAND (exp, 1),
09014 ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
09015 end_cleanup_deferral ();
09016 emit_queue ();
09017 emit_jump_insn (gen_jump (op1));
09018 emit_barrier ();
09019 emit_label (op0);
09020 start_cleanup_deferral ();
09021 if (temp != 0
09022 && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
09023 store_expr (TREE_OPERAND (exp, 2), temp,
09024 modifier == EXPAND_STACK_PARM ? 2 : 0);
09025 else
09026 expand_expr (TREE_OPERAND (exp, 2),
09027 ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
09028 }
09029
09030 end_cleanup_deferral ();
09031
09032 emit_queue ();
09033 emit_label (op1);
09034 OK_DEFER_POP;
09035
09036 return temp;
09037 }
09038
09039 case TARGET_EXPR:
09040 {
09041
09042
09043
09044
09045
09046
09047
09048
09049
09050 tree slot = TREE_OPERAND (exp, 0);
09051 tree cleanups = NULL_TREE;
09052 tree exp1;
09053
09054 if (TREE_CODE (slot) != VAR_DECL)
09055 abort ();
09056
09057 if (! ignore)
09058 target = original_target;
09059
09060
09061
09062
09063 TREE_USED (slot) = 1;
09064
09065 if (target == 0)
09066 {
09067 if (DECL_RTL_SET_P (slot))
09068 {
09069 target = DECL_RTL (slot);
09070
09071
09072 if (TREE_OPERAND (exp, 1) == NULL_TREE)
09073 return target;
09074 }
09075 else
09076 {
09077 target = assign_temp (type, 2, 0, 1);
09078
09079 preserve_temp_slots (target);
09080 SET_DECL_RTL (slot, target);
09081 if (TREE_ADDRESSABLE (slot))
09082 put_var_into_stack (slot, false);
09083
09084
09085
09086
09087
09088
09089
09090
09091 if (TREE_OPERAND (exp, 2) == 0)
09092 TREE_OPERAND (exp, 2)
09093 = (*lang_hooks.maybe_build_cleanup) (slot);
09094 cleanups = TREE_OPERAND (exp, 2);
09095 }
09096 }
09097 else
09098 {
09099
09100
09101
09102
09103
09104
09105
09106
09107 if (DECL_RTL_SET_P (slot))
09108 {
09109 target = DECL_RTL (slot);
09110
09111
09112 if (TREE_OPERAND (exp, 1) == NULL_TREE)
09113 return target;
09114 }
09115 else
09116 {
09117 SET_DECL_RTL (slot, target);
09118
09119
09120 if (TREE_ADDRESSABLE (slot))
09121 put_var_into_stack (slot, true);
09122 }
09123 }
09124
09125 exp1 = TREE_OPERAND (exp, 3) = TREE_OPERAND (exp, 1);
09126
09127 TREE_OPERAND (exp, 1) = NULL_TREE;
09128
09129 store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
09130
09131 #ifdef KEY
09132 if (cleanups)
09133 TREE_LANG_FLAG_7 (exp) = 1;
09134 #endif
09135 expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
09136
09137 return target;
09138 }
09139
09140 case INIT_EXPR:
09141 {
09142 tree lhs = TREE_OPERAND (exp, 0);
09143 tree rhs = TREE_OPERAND (exp, 1);
09144
09145 temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
09146 return temp;
09147 }
09148
09149 case MODIFY_EXPR:
09150 {
09151
09152
09153
09154
09155
09156
09157
09158
09159 tree lhs = TREE_OPERAND (exp, 0);
09160 tree rhs = TREE_OPERAND (exp, 1);
09161
09162 temp = 0;
09163
09164
09165
09166
09167
09168
09169
09170
09171
09172 if (ignore
09173 && TREE_CODE (lhs) == COMPONENT_REF
09174 && (TREE_CODE (rhs) == BIT_IOR_EXPR
09175 || TREE_CODE (rhs) == BIT_AND_EXPR)
09176 && TREE_OPERAND (rhs, 0) == lhs
09177 && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
09178 && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
09179 && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
09180 {
09181 rtx label = gen_label_rtx ();
09182
09183 do_jump (TREE_OPERAND (rhs, 1),
09184 TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
09185 TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
09186 expand_assignment (lhs, convert (TREE_TYPE (rhs),
09187 (TREE_CODE (rhs) == BIT_IOR_EXPR
09188 ? integer_one_node
09189 : integer_zero_node)),
09190 0, 0);
09191 do_pending_stack_adjust ();
09192 emit_label (label);
09193 return const0_rtx;
09194 }
09195
09196 temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
09197
09198 return temp;
09199 }
09200
09201 case RETURN_EXPR:
09202 if (!TREE_OPERAND (exp, 0))
09203 expand_null_return ();
09204 else
09205 expand_return (TREE_OPERAND (exp, 0));
09206 return const0_rtx;
09207
09208 case PREINCREMENT_EXPR:
09209 case PREDECREMENT_EXPR:
09210 return expand_increment (exp, 0, ignore);
09211
09212 case POSTINCREMENT_EXPR:
09213 case POSTDECREMENT_EXPR:
09214
09215 return expand_increment (exp, ! ignore, ignore);
09216
09217 case ADDR_EXPR:
09218 if (modifier == EXPAND_STACK_PARM)
09219 target = 0;
09220
09221 if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
09222 && decl_function_context (TREE_OPERAND (exp, 0)) != 0
09223 && ! DECL_NO_STATIC_CHAIN (TREE_OPERAND (exp, 0))
09224 && ! TREE_STATIC (exp))
09225 {
09226 op0 = trampoline_address (TREE_OPERAND (exp, 0));
09227 op0 = force_operand (op0, target);
09228 }
09229
09230
09231 else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
09232 return const0_rtx;
09233
09234
09235
09236 else if (cfun == 0
09237 && (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
09238 || (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0)))
09239 == 'c')))
09240 op0 = XEXP (output_constant_def (TREE_OPERAND (exp, 0), 0), 0);
09241 else
09242 {
09243
09244
09245 op0 = expand_expr (TREE_OPERAND (exp, 0),
09246 ignore ? const0_rtx : NULL_RTX, VOIDmode,
09247 (modifier == EXPAND_INITIALIZER
09248 ? modifier : EXPAND_CONST_ADDRESS));
09249
09250
09251
09252
09253 if (ignore)
09254 return op0;
09255
09256
09257
09258 op0 = protect_from_queue (op0, 1);
09259
09260
09261
09262
09263
09264 if (CONSTANT_P (op0))
09265 op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
09266 op0);
09267 else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
09268 || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
09269 || GET_CODE (op0) == PARALLEL)
09270 {
09271
09272
09273 if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
09274 {
09275 put_var_into_stack (TREE_OPERAND (exp, 0),
09276 true);
09277 op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
09278 }
09279 else
09280 {
09281
09282 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
09283 rtx memloc = assign_temp (inner_type, 1, 1, 1);
09284
09285 if (GET_CODE (op0) == PARALLEL)
09286
09287
09288
09289 emit_group_store (memloc, op0,
09290 int_size_in_bytes (inner_type));
09291 else
09292 emit_move_insn (memloc, op0);
09293
09294 op0 = memloc;
09295 }
09296 }
09297
09298 if (GET_CODE (op0) != MEM)
09299 abort ();
09300
09301 mark_temp_addr_taken (op0);
09302 if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
09303 {
09304 op0 = XEXP (op0, 0);
09305 #ifdef POINTERS_EXTEND_UNSIGNED
09306 if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
09307 && mode == ptr_mode)
09308 op0 = convert_memory_address (ptr_mode, op0);
09309 #endif
09310 return op0;
09311 }
09312
09313
09314
09315
09316
09317
09318
09319
09320
09321
09322
09323 if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
09324 && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
09325 > MEM_ALIGN (op0))
09326 && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
09327 {
09328 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
09329 rtx new;
09330
09331 if (TYPE_ALIGN_OK (inner_type))
09332 abort ();
09333
09334 if (TREE_ADDRESSABLE (inner_type))
09335 {
09336
09337 error ("cannot take the address of an unaligned member");
09338 return const0_rtx;
09339 }
09340
09341 new = assign_stack_temp_for_type
09342 (TYPE_MODE (inner_type),
09343 MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0))
09344 : int_size_in_bytes (inner_type),
09345 1, build_qualified_type (inner_type,
09346 (TYPE_QUALS (inner_type)
09347 | TYPE_QUAL_CONST)));
09348
09349 emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)),
09350 (modifier == EXPAND_STACK_PARM
09351 ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
09352
09353 op0 = new;
09354 }
09355
09356 op0 = force_operand (XEXP (op0, 0), target);
09357 }
09358
09359 if (flag_force_addr
09360 && GET_CODE (op0) != REG
09361 && modifier != EXPAND_CONST_ADDRESS
09362 && modifier != EXPAND_INITIALIZER
09363 && modifier != EXPAND_SUM)
09364 op0 = force_reg (Pmode, op0);
09365
09366 if (GET_CODE (op0) == REG
09367 && ! REG_USERVAR_P (op0))
09368 mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
09369
09370 #ifdef POINTERS_EXTEND_UNSIGNED
09371 if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
09372 && mode == ptr_mode)
09373 op0 = convert_memory_address (ptr_mode, op0);
09374 #endif
09375
09376 return op0;
09377
09378 case ENTRY_VALUE_EXPR:
09379 abort ();
09380
09381
09382 case COMPLEX_EXPR:
09383 {
09384 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
09385 rtx insns;
09386
09387
09388 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
09389 op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
09390
09391 if (! target)
09392 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
09393
09394 start_sequence ();
09395
09396
09397 emit_move_insn (gen_realpart (mode, target), op0);
09398 emit_move_insn (gen_imagpart (mode, target), op1);
09399
09400 insns = get_insns ();
09401 end_sequence ();
09402
09403
09404
09405
09406
09407 if (GET_CODE (target) != CONCAT)
09408 emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
09409 else
09410 emit_insn (insns);
09411
09412 return target;
09413 }
09414
09415 case REALPART_EXPR:
09416 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
09417 return gen_realpart (mode, op0);
09418
09419 case IMAGPART_EXPR:
09420 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
09421 return gen_imagpart (mode, op0);
09422
09423 case CONJ_EXPR:
09424 {
09425 enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
09426 rtx imag_t;
09427 rtx insns;
09428
09429 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
09430
09431 if (! target)
09432 target = gen_reg_rtx (mode);
09433
09434 start_sequence ();
09435
09436
09437 emit_move_insn (gen_realpart (partmode, target),
09438 gen_realpart (partmode, op0));
09439
09440 imag_t = gen_imagpart (partmode, target);
09441 temp = expand_unop (partmode,
09442 ! unsignedp && flag_trapv
09443 && (GET_MODE_CLASS(partmode) == MODE_INT)
09444 ? negv_optab : neg_optab,
09445 gen_imagpart (partmode, op0), imag_t, 0);
09446 if (temp != imag_t)
09447 emit_move_insn (imag_t, temp);
09448
09449 insns = get_insns ();
09450 end_sequence ();
09451
09452
09453
09454
09455
09456 if (GET_CODE (target) != CONCAT)
09457 emit_no_conflict_block (insns, target, op0, NULL_RTX, NULL_RTX);
09458 else
09459 emit_insn (insns);
09460
09461 return target;
09462 }
09463
09464 case TRY_CATCH_EXPR:
09465 {
09466 tree handler = TREE_OPERAND (exp, 1);
09467
09468 expand_eh_region_start ();
09469
09470 op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
09471
09472 expand_eh_region_end_cleanup (handler);
09473
09474 return op0;
09475 }
09476
09477 case TRY_FINALLY_EXPR:
09478 {
09479 tree try_block = TREE_OPERAND (exp, 0);
09480 tree finally_block = TREE_OPERAND (exp, 1);
09481
09482 if (!optimize || unsafe_for_reeval (finally_block) > 1)
09483 {
09484
09485
09486
09487
09488
09489
09490
09491
09492
09493
09494
09495 rtx finally_label = gen_label_rtx ();
09496 rtx done_label = gen_label_rtx ();
09497 rtx return_link = gen_reg_rtx (Pmode);
09498 tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
09499 (tree) finally_label, (tree) return_link);
09500 TREE_SIDE_EFFECTS (cleanup) = 1;
09501
09502
09503
09504 expand_start_bindings (2);
09505 target_temp_slot_level = temp_slot_level;
09506
09507 expand_decl_cleanup (NULL_TREE, cleanup);
09508 op0 = expand_expr (try_block, target, tmode, modifier);
09509
09510 preserve_temp_slots (op0);
09511 expand_end_bindings (NULL_TREE, 0, 0);
09512 emit_jump (done_label);
09513 emit_label (finally_label);
09514 expand_expr (finally_block, const0_rtx, VOIDmode, 0);
09515 emit_indirect_jump (return_link);
09516 emit_label (done_label);
09517 }
09518 else
09519 {
09520 expand_start_bindings (2);
09521 target_temp_slot_level = temp_slot_level;
09522
09523 expand_decl_cleanup (NULL_TREE, finally_block);
09524 op0 = expand_expr (try_block, target, tmode, modifier);
09525
09526 preserve_temp_slots (op0);
09527 expand_end_bindings (NULL_TREE, 0, 0);
09528 }
09529
09530 return op0;
09531 }
09532
09533 case GOTO_SUBROUTINE_EXPR:
09534 {
09535 rtx subr = (rtx) TREE_OPERAND (exp, 0);
09536 rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
09537 rtx return_address = gen_label_rtx ();
09538 emit_move_insn (return_link,
09539 gen_rtx_LABEL_REF (Pmode, return_address));
09540 emit_jump (subr);
09541 emit_label (return_address);
09542 return const0_rtx;
09543 }
09544
09545 case VA_ARG_EXPR:
09546 return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
09547
09548 case EXC_PTR_EXPR:
09549 return get_exception_pointer (cfun);
09550
09551 case FDESC_EXPR:
09552
09553
09554 abort ();
09555
09556 default:
09557 return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier);
09558 }
09559
09560
09561
09562 binop:
09563 if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
09564 subtarget = 0;
09565 op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
09566 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
09567 binop2:
09568 if (modifier == EXPAND_STACK_PARM)
09569 target = 0;
09570 temp = expand_binop (mode, this_optab, op0, op1, target,
09571 unsignedp, OPTAB_LIB_WIDEN);
09572 if (temp == 0)
09573 abort ();
09574 return temp;
09575 }
09576
09577
09578
09579
09580
09581 static int
09582 is_aligning_offset (offset, exp)
09583 tree offset;
09584 tree exp;
09585 {
09586
09587 while (TREE_CODE (offset) == NON_LVALUE_EXPR
09588 || TREE_CODE (offset) == NOP_EXPR
09589 || TREE_CODE (offset) == CONVERT_EXPR
09590 || TREE_CODE (offset) == WITH_RECORD_EXPR)
09591 offset = TREE_OPERAND (offset, 0);
09592
09593
09594
09595 if (TREE_CODE (offset) != BIT_AND_EXPR
09596 || !host_integerp (TREE_OPERAND (offset, 1), 1)
09597 || compare_tree_int (TREE_OPERAND (offset, 1), BIGGEST_ALIGNMENT) <= 0
09598 || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
09599 return 0;
09600
09601
09602
09603 offset = TREE_OPERAND (offset, 0);
09604 while (TREE_CODE (offset) == NON_LVALUE_EXPR
09605 || TREE_CODE (offset) == NOP_EXPR
09606 || TREE_CODE (offset) == CONVERT_EXPR)
09607 offset = TREE_OPERAND (offset, 0);
09608
09609 if (TREE_CODE (offset) != NEGATE_EXPR)
09610 return 0;
09611
09612 offset = TREE_OPERAND (offset, 0);
09613 while (TREE_CODE (offset) == NON_LVALUE_EXPR
09614 || TREE_CODE (offset) == NOP_EXPR
09615 || TREE_CODE (offset) == CONVERT_EXPR)
09616 offset = TREE_OPERAND (offset, 0);
09617
09618
09619
09620 return (TREE_CODE (offset) == ADDR_EXPR
09621 && (TREE_OPERAND (offset, 0) == exp
09622 || (TREE_CODE (TREE_OPERAND (offset, 0)) == PLACEHOLDER_EXPR
09623 && (TREE_TYPE (TREE_OPERAND (offset, 0))
09624 == TREE_TYPE (exp)))));
09625 }
09626
09627
09628
09629
09630
09631
09632 tree
09633 string_constant (arg, ptr_offset)
09634 tree arg;
09635 tree *ptr_offset;
09636 {
09637 STRIP_NOPS (arg);
09638
09639 if (TREE_CODE (arg) == ADDR_EXPR
09640 && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
09641 {
09642 *ptr_offset = size_zero_node;
09643 return TREE_OPERAND (arg, 0);
09644 }
09645 else if (TREE_CODE (arg) == PLUS_EXPR)
09646 {
09647 tree arg0 = TREE_OPERAND (arg, 0);
09648 tree arg1 = TREE_OPERAND (arg, 1);
09649
09650 STRIP_NOPS (arg0);
09651 STRIP_NOPS (arg1);
09652
09653 if (TREE_CODE (arg0) == ADDR_EXPR
09654 && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST)
09655 {
09656 *ptr_offset = convert (sizetype, arg1);
09657 return TREE_OPERAND (arg0, 0);
09658 }
09659 else if (TREE_CODE (arg1) == ADDR_EXPR
09660 && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST)
09661 {
09662 *ptr_offset = convert (sizetype, arg0);
09663 return TREE_OPERAND (arg1, 0);
09664 }
09665 }
09666
09667 return 0;
09668 }
09669
09670
09671
09672
09673
09674 static rtx
09675 expand_increment (exp, post, ignore)
09676 tree exp;
09677 int post, ignore;
09678 {
09679 rtx op0, op1;
09680 rtx temp, value;
09681 tree incremented = TREE_OPERAND (exp, 0);
09682 optab this_optab = add_optab;
09683 int icode;
09684 enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
09685 int op0_is_copy = 0;
09686 int single_insn = 0;
09687
09688
09689
09690 int bad_subreg = 0;
09691
09692
09693
09694 if (!post
09695 || TREE_CODE (incremented) == BIT_FIELD_REF
09696 || (TREE_CODE (incremented) == COMPONENT_REF
09697 && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
09698 || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1)))))
09699 incremented = stabilize_reference (incremented);
09700
09701
09702
09703 if (TREE_CODE (incremented) == PREINCREMENT_EXPR
09704 || TREE_CODE (incremented) == PREDECREMENT_EXPR)
09705 incremented = save_expr (incremented);
09706
09707
09708
09709
09710
09711
09712 temp = get_last_insn ();
09713 op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
09714
09715
09716
09717
09718
09719
09720
09721
09722
09723 if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0))
09724 {
09725 if (post)
09726 SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0));
09727 else
09728 bad_subreg = 1;
09729 }
09730 else if (GET_CODE (op0) == SUBREG
09731 && GET_MODE_BITSIZE (GET_MODE (op0)) < BITS_PER_WORD)
09732 {
09733
09734
09735
09736 if (post)
09737 op0 = copy_to_reg (op0);
09738 else
09739 bad_subreg = 1;
09740 }
09741
09742 op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
09743 && temp != get_last_insn ());
09744 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
09745
09746
09747 if (TREE_CODE (exp) == POSTDECREMENT_EXPR
09748 || TREE_CODE (exp) == PREDECREMENT_EXPR)
09749 this_optab = sub_optab;
09750
09751
09752 if (this_optab == sub_optab
09753 && GET_CODE (op1) == CONST_INT)
09754 {
09755 op1 = GEN_INT (-INTVAL (op1));
09756 this_optab = add_optab;
09757 }
09758
09759 if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
09760 this_optab = this_optab == add_optab ? addv_optab : subv_optab;
09761
09762
09763 if (!post)
09764 {
09765 icode = (int) this_optab->handlers[(int) mode].insn_code;
09766 if (icode != (int) CODE_FOR_nothing
09767
09768
09769 && (*insn_data[icode].operand[0].predicate) (op0, mode)
09770 && (*insn_data[icode].operand[1].predicate) (op0, mode)
09771 && (*insn_data[icode].operand[2].predicate) (op1, mode))
09772 single_insn = 1;
09773 }
09774
09775
09776
09777
09778
09779
09780
09781
09782
09783 if (op0_is_copy || (!post && !single_insn) || bad_subreg)
09784 {
09785
09786
09787
09788
09789
09790
09791 tree newexp = build (((TREE_CODE (exp) == POSTDECREMENT_EXPR
09792 || TREE_CODE (exp) == PREDECREMENT_EXPR)
09793 ? MINUS_EXPR : PLUS_EXPR),
09794 TREE_TYPE (exp),
09795 incremented,
09796 TREE_OPERAND (exp, 1));
09797
09798 while (TREE_CODE (incremented) == NOP_EXPR
09799 || TREE_CODE (incremented) == CONVERT_EXPR)
09800 {
09801 newexp = convert (TREE_TYPE (incremented), newexp);
09802 incremented = TREE_OPERAND (incremented, 0);
09803 }
09804
09805 temp = expand_assignment (incremented, newexp, ! post && ! ignore , 0);
09806 return post ? op0 : temp;
09807 }
09808
09809 if (post)
09810 {
09811
09812
09813
09814
09815
09816
09817 #if 0
09818 op0 = stabilize (op0);
09819 #endif
09820
09821 icode = (int) this_optab->handlers[(int) mode].insn_code;
09822 if (icode != (int) CODE_FOR_nothing
09823
09824
09825 && (*insn_data[icode].operand[0].predicate) (op0, mode)
09826 && (*insn_data[icode].operand[1].predicate) (op0, mode))
09827 {
09828 if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
09829 op1 = force_reg (mode, op1);
09830
09831 return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
09832 }
09833 if (icode != (int) CODE_FOR_nothing && GET_CODE (op0) == MEM)
09834 {
09835 rtx addr = (general_operand (XEXP (op0, 0), mode)
09836 ? force_reg (Pmode, XEXP (op0, 0))
09837 : copy_to_reg (XEXP (op0, 0)));
09838 rtx temp, result;
09839
09840 op0 = replace_equiv_address (op0, addr);
09841 temp = force_reg (GET_MODE (op0), op0);
09842 if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
09843 op1 = force_reg (mode, op1);
09844
09845
09846
09847 enqueue_insn (op0, gen_move_insn (op0, temp));
09848 result = enqueue_insn (temp, GEN_FCN (icode) (temp, temp, op1));
09849 return result;
09850 }
09851 }
09852
09853
09854 if (post)
09855
09856 temp = value = copy_to_reg (op0);
09857 else
09858
09859
09860
09861
09862 temp = copy_rtx (value = op0);
09863
09864
09865 op1 = expand_binop (mode, this_optab, value, op1, op0,
09866 TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
09867
09868
09869 if (op1 != op0)
09870 emit_move_insn (op0, op1);
09871
09872 return temp;
09873 }
09874
09875
09876
09877
09878 void
09879 init_pending_stack_adjust ()
09880 {
09881 pending_stack_adjust = 0;
09882 }
09883
09884
09885
09886
09887
09888
09889
09890 void
09891 clear_pending_stack_adjust ()
09892 {
09893 #ifdef EXIT_IGNORE_STACK
09894 if (optimize > 0
09895 && (! flag_omit_frame_pointer || current_function_calls_alloca)
09896 && EXIT_IGNORE_STACK
09897 && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
09898 && ! flag_inline_functions)
09899 {
09900 stack_pointer_delta -= pending_stack_adjust,
09901 pending_stack_adjust = 0;
09902 }
09903 #endif
09904 }
09905
09906
09907
09908 void
09909 do_pending_stack_adjust ()
09910 {
09911 if (inhibit_defer_pop == 0)
09912 {
09913 if (pending_stack_adjust != 0)
09914 adjust_stack (GEN_INT (pending_stack_adjust));
09915 pending_stack_adjust = 0;
09916 }
09917 }
09918
09919
09920
09921
09922
09923
09924
09925 void
09926 jumpifnot (exp, label)
09927 tree exp;
09928 rtx label;
09929 {
09930 do_jump (exp, label, NULL_RTX);
09931 }
09932
09933
09934
09935 void
09936 jumpif (exp, label)
09937 tree exp;
09938 rtx label;
09939 {
09940 do_jump (exp, NULL_RTX, label);
09941 }
09942
09943
09944
09945
09946
09947
09948
09949
09950
09951
09952
09953
09954
09955 void
09956 do_jump (exp, if_false_label, if_true_label)
09957 tree exp;
09958 rtx if_false_label, if_true_label;
09959 {
09960 enum tree_code code = TREE_CODE (exp);
09961
09962
09963
09964 rtx drop_through_label = 0;
09965 rtx temp;
09966 int i;
09967 tree type;
09968 enum machine_mode mode;
09969
09970 #ifdef MAX_INTEGER_COMPUTATION_MODE
09971 check_max_integer_computation_mode (exp);
09972 #endif
09973
09974 emit_queue ();
09975
09976 switch (code)
09977 {
09978 case ERROR_MARK:
09979 break;
09980
09981 case INTEGER_CST:
09982 temp = integer_zerop (exp) ? if_false_label : if_true_label;
09983 if (temp)
09984 emit_jump (temp);
09985 break;
09986
09987 #if 0
09988
09989 case ADDR_EXPR:
09990
09991 if (if_true_label)
09992 emit_jump (if_true_label);
09993 break;
09994 #endif
09995
09996 case UNSAVE_EXPR:
09997 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
09998 TREE_OPERAND (exp, 0)
09999 = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
10000 break;
10001
10002 case NOP_EXPR:
10003 if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
10004 || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
10005 || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
10006 || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
10007 goto normal;
10008 case CONVERT_EXPR:
10009
10010
10011 if ((TYPE_PRECISION (TREE_TYPE (exp))
10012 < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
10013 goto normal;
10014 case NON_LVALUE_EXPR:
10015 case REFERENCE_EXPR:
10016 case ABS_EXPR:
10017 case NEGATE_EXPR:
10018 case LROTATE_EXPR:
10019 case RROTATE_EXPR:
10020
10021 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
10022 break;
10023
10024 case WITH_RECORD_EXPR:
10025
10026
10027 placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
10028 placeholder_list);
10029 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
10030 placeholder_list = TREE_CHAIN (placeholder_list);
10031 break;
10032
10033 #if 0
10034
10035
10036 case PLUS_EXPR:
10037
10038 exp = build (MINUS_EXPR, TREE_TYPE (exp),
10039 TREE_OPERAND (exp, 0),
10040 fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
10041 TREE_OPERAND (exp, 1))));
10042
10043 #endif
10044
10045 case MINUS_EXPR:
10046
10047 do_compare_and_jump (build (NE_EXPR, TREE_TYPE (exp),
10048 TREE_OPERAND (exp, 0),
10049 TREE_OPERAND (exp, 1)),
10050 NE, NE, if_false_label, if_true_label);
10051 break;
10052
10053 case BIT_AND_EXPR:
10054
10055
10056
10057
10058
10059
10060
10061 if (! SLOW_BYTE_ACCESS
10062 && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
10063 && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
10064 && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
10065 && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
10066 && (type = (*lang_hooks.types.type_for_mode) (mode, 1)) != 0
10067 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
10068 && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
10069 != CODE_FOR_nothing))
10070 {
10071 do_jump (convert (type, exp), if_false_label, if_true_label);
10072 break;
10073 }
10074 goto normal;
10075
10076 case TRUTH_NOT_EXPR:
10077 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
10078 break;
10079
10080 case TRUTH_ANDIF_EXPR:
10081 if (if_false_label == 0)
10082 if_false_label = drop_through_label = gen_label_rtx ();
10083 do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
10084 start_cleanup_deferral ();
10085 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
10086 end_cleanup_deferral ();
10087 break;
10088
10089 case TRUTH_ORIF_EXPR:
10090 if (if_true_label == 0)
10091 if_true_label = drop_through_label = gen_label_rtx ();
10092 do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
10093 start_cleanup_deferral ();
10094 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
10095 end_cleanup_deferral ();
10096 break;
10097
10098 case COMPOUND_EXPR:
10099 push_temp_slots ();
10100 expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
10101 preserve_temp_slots (NULL_RTX);
10102 free_temp_slots ();
10103 pop_temp_slots ();
10104 emit_queue ();
10105 do_pending_stack_adjust ();
10106 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
10107 break;
10108
10109 case COMPONENT_REF:
10110 case BIT_FIELD_REF:
10111 case ARRAY_REF:
10112 case ARRAY_RANGE_REF:
10113 {
10114 HOST_WIDE_INT bitsize, bitpos;
10115 int unsignedp;
10116 enum machine_mode mode;
10117 tree type;
10118 tree offset;
10119 int volatilep = 0;
10120
10121
10122
10123 get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
10124 &unsignedp, &volatilep);
10125
10126 type = (*lang_hooks.types.type_for_size) (bitsize, unsignedp);
10127 if (! SLOW_BYTE_ACCESS
10128 && type != 0 && bitsize >= 0
10129 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
10130 && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
10131 != CODE_FOR_nothing))
10132 {
10133 do_jump (convert (type, exp), if_false_label, if_true_label);
10134 break;
10135 }
10136 goto normal;
10137 }
10138
10139 case COND_EXPR:
10140
10141 if (integer_onep (TREE_OPERAND (exp, 1))
10142 && integer_zerop (TREE_OPERAND (exp, 2)))
10143 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
10144
10145 else if (integer_zerop (TREE_OPERAND (exp, 1))
10146 && integer_onep (TREE_OPERAND (exp, 2)))
10147 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
10148
10149 else
10150 {
10151 rtx label1 = gen_label_rtx ();
10152 drop_through_label = gen_label_rtx ();
10153
10154 do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
10155
10156 start_cleanup_deferral ();
10157
10158 do_jump (TREE_OPERAND (exp, 1),
10159 if_false_label ? if_false_label : drop_through_label,
10160 if_true_label ? if_true_label : drop_through_label);
10161
10162 do_pending_stack_adjust ();
10163 emit_label (label1);
10164
10165
10166 do_jump (TREE_OPERAND (exp, 2),
10167 if_false_label ? if_false_label : drop_through_label,
10168 if_true_label ? if_true_label : drop_through_label);
10169 end_cleanup_deferral ();
10170 }
10171 break;
10172
10173 case EQ_EXPR:
10174 {
10175 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
10176
10177 if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
10178 || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
10179 {
10180 tree exp0 = save_expr (TREE_OPERAND (exp, 0));
10181 tree exp1 = save_expr (TREE_OPERAND (exp, 1));
10182 do_jump
10183 (fold
10184 (build (TRUTH_ANDIF_EXPR, TREE_TYPE (exp),
10185 fold (build (EQ_EXPR, TREE_TYPE (exp),
10186 fold (build1 (REALPART_EXPR,
10187 TREE_TYPE (inner_type),
10188 exp0)),
10189 fold (build1 (REALPART_EXPR,
10190 TREE_TYPE (inner_type),
10191 exp1)))),
10192 fold (build (EQ_EXPR, TREE_TYPE (exp),
10193 fold (build1 (IMAGPART_EXPR,
10194 TREE_TYPE (inner_type),
10195 exp0)),
10196 fold (build1 (IMAGPART_EXPR,
10197 TREE_TYPE (inner_type),
10198 exp1)))))),
10199 if_false_label, if_true_label);
10200 }
10201
10202 else if (integer_zerop (TREE_OPERAND (exp, 1)))
10203 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
10204
10205 else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
10206 && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
10207 do_jump_by_parts_equality (exp, if_false_label, if_true_label);
10208 else
10209 do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
10210 break;
10211 }
10212
10213 case NE_EXPR:
10214 {
10215 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
10216
10217 if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
10218 || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
10219 {
10220 tree exp0 = save_expr (TREE_OPERAND (exp, 0));
10221 tree exp1 = save_expr (TREE_OPERAND (exp, 1));
10222 do_jump
10223 (fold
10224 (build (TRUTH_ORIF_EXPR, TREE_TYPE (exp),
10225 fold (build (NE_EXPR, TREE_TYPE (exp),
10226 fold (build1 (REALPART_EXPR,
10227 TREE_TYPE (inner_type),
10228 exp0)),
10229 fold (build1 (REALPART_EXPR,
10230 TREE_TYPE (inner_type),
10231 exp1)))),
10232 fold (build (NE_EXPR, TREE_TYPE (exp),
10233 fold (build1 (IMAGPART_EXPR,
10234 TREE_TYPE (inner_type),
10235 exp0)),
10236 fold (build1 (IMAGPART_EXPR,
10237 TREE_TYPE (inner_type),
10238 exp1)))))),
10239 if_false_label, if_true_label);
10240 }
10241
10242 else if (integer_zerop (TREE_OPERAND (exp, 1)))
10243 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
10244
10245 else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
10246 && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
10247 do_jump_by_parts_equality (exp, if_true_label, if_false_label);
10248 else
10249 do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
10250 break;
10251 }
10252
10253 case LT_EXPR:
10254 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10255 if (GET_MODE_CLASS (mode) == MODE_INT
10256 && ! can_compare_p (LT, mode, ccp_jump))
10257 do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
10258 else
10259 do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
10260 break;
10261
10262 case LE_EXPR:
10263 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10264 if (GET_MODE_CLASS (mode) == MODE_INT
10265 && ! can_compare_p (LE, mode, ccp_jump))
10266 do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
10267 else
10268 do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
10269 break;
10270
10271 case GT_EXPR:
10272 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10273 if (GET_MODE_CLASS (mode) == MODE_INT
10274 && ! can_compare_p (GT, mode, ccp_jump))
10275 do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
10276 else
10277 do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
10278 break;
10279
10280 case GE_EXPR:
10281 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10282 if (GET_MODE_CLASS (mode) == MODE_INT
10283 && ! can_compare_p (GE, mode, ccp_jump))
10284 do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
10285 else
10286 do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
10287 break;
10288
10289 case UNORDERED_EXPR:
10290 case ORDERED_EXPR:
10291 {
10292 enum rtx_code cmp, rcmp;
10293 int do_rev;
10294
10295 if (code == UNORDERED_EXPR)
10296 cmp = UNORDERED, rcmp = ORDERED;
10297 else
10298 cmp = ORDERED, rcmp = UNORDERED;
10299 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10300
10301 do_rev = 0;
10302 if (! can_compare_p (cmp, mode, ccp_jump)
10303 && (can_compare_p (rcmp, mode, ccp_jump)
10304
10305
10306 || rcmp == UNORDERED))
10307 do_rev = 1;
10308
10309 if (! do_rev)
10310 do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
10311 else
10312 do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
10313 }
10314 break;
10315
10316 {
10317 enum rtx_code rcode1;
10318 enum tree_code tcode2;
10319
10320 case UNLT_EXPR:
10321 rcode1 = UNLT;
10322 tcode2 = LT_EXPR;
10323 goto unordered_bcc;
10324 case UNLE_EXPR:
10325 rcode1 = UNLE;
10326 tcode2 = LE_EXPR;
10327 goto unordered_bcc;
10328 case UNGT_EXPR:
10329 rcode1 = UNGT;
10330 tcode2 = GT_EXPR;
10331 goto unordered_bcc;
10332 case UNGE_EXPR:
10333 rcode1 = UNGE;
10334 tcode2 = GE_EXPR;
10335 goto unordered_bcc;
10336 case UNEQ_EXPR:
10337 rcode1 = UNEQ;
10338 tcode2 = EQ_EXPR;
10339 goto unordered_bcc;
10340
10341 unordered_bcc:
10342 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10343 if (can_compare_p (rcode1, mode, ccp_jump))
10344 do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
10345 if_true_label);
10346 else
10347 {
10348 tree op0 = save_expr (TREE_OPERAND (exp, 0));
10349 tree op1 = save_expr (TREE_OPERAND (exp, 1));
10350 tree cmp0, cmp1;
10351
10352
10353
10354 cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
10355 cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
10356 exp = build (TRUTH_ORIF_EXPR, TREE_TYPE (exp), cmp0, cmp1);
10357 do_jump (exp, if_false_label, if_true_label);
10358 }
10359 }
10360 break;
10361
10362
10363
10364
10365
10366
10367
10368
10369
10370 case CALL_EXPR:
10371
10372 if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
10373 {
10374 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
10375 tree arglist = TREE_OPERAND (exp, 1);
10376
10377 if (TREE_CODE (fndecl) == FUNCTION_DECL
10378 && DECL_BUILT_IN (fndecl)
10379 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
10380 && arglist != NULL_TREE
10381 && TREE_CHAIN (arglist) != NULL_TREE)
10382 {
10383 rtx seq = expand_builtin_expect_jump (exp, if_false_label,
10384 if_true_label);
10385
10386 if (seq != NULL_RTX)
10387 {
10388 emit_insn (seq);
10389 return;
10390 }
10391 }
10392 }
10393
10394
10395 default:
10396 normal:
10397 temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
10398 #if 0
10399
10400
10401
10402
10403
10404 if (!cse_not_expected && GET_CODE (temp) == MEM)
10405 temp = copy_to_reg (temp);
10406 #endif
10407 do_pending_stack_adjust ();
10408
10409 emit_queue ();
10410
10411 if (GET_CODE (temp) == CONST_INT
10412 || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
10413 || GET_CODE (temp) == LABEL_REF)
10414 {
10415 rtx target = temp == const0_rtx ? if_false_label : if_true_label;
10416 if (target)
10417 emit_jump (target);
10418 }
10419 else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
10420 && ! can_compare_p (NE, GET_MODE (temp), ccp_jump))
10421
10422 do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
10423 else if (GET_MODE (temp) != VOIDmode)
10424 do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
10425 NE, TREE_UNSIGNED (TREE_TYPE (exp)),
10426 GET_MODE (temp), NULL_RTX,
10427 if_false_label, if_true_label);
10428 else
10429 abort ();
10430 }
10431
10432 if (drop_through_label)
10433 {
10434
10435
10436
10437 do_pending_stack_adjust ();
10438 emit_label (drop_through_label);
10439 }
10440 }
10441
10442
10443
10444
10445
10446
10447 static void
10448 do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label)
10449 tree exp;
10450 int swap;
10451 rtx if_false_label, if_true_label;
10452 {
10453 rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
10454 rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
10455 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10456 int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
10457
10458 do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true_label);
10459 }
10460
10461
10462
10463
10464
10465 void
10466 do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true_label)
10467 enum machine_mode mode;
10468 int unsignedp;
10469 rtx op0, op1;
10470 rtx if_false_label, if_true_label;
10471 {
10472 int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
10473 rtx drop_through_label = 0;
10474 int i;
10475
10476 if (! if_true_label || ! if_false_label)
10477 drop_through_label = gen_label_rtx ();
10478 if (! if_true_label)
10479 if_true_label = drop_through_label;
10480 if (! if_false_label)
10481 if_false_label = drop_through_label;
10482
10483
10484 for (i = 0; i < nwords; i++)
10485 {
10486 rtx op0_word, op1_word;
10487
10488 if (WORDS_BIG_ENDIAN)
10489 {
10490 op0_word = operand_subword_force (op0, i, mode);
10491 op1_word = operand_subword_force (op1, i, mode);
10492 }
10493 else
10494 {
10495 op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
10496 op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
10497 }
10498
10499
10500 do_compare_rtx_and_jump (op0_word, op1_word, GT,
10501 (unsignedp || i > 0), word_mode, NULL_RTX,
10502 NULL_RTX, if_true_label);
10503
10504
10505 do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
10506 NULL_RTX, NULL_RTX, if_false_label);
10507 }
10508
10509 if (if_false_label)
10510 emit_jump (if_false_label);
10511 if (drop_through_label)
10512 emit_label (drop_through_label);
10513 }
10514
10515
10516
10517
10518 static void
10519 do_jump_by_parts_equality (exp, if_false_label, if_true_label)
10520 tree exp;
10521 rtx if_false_label, if_true_label;
10522 {
10523 rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
10524 rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
10525 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
10526 int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
10527 int i;
10528 rtx drop_through_label = 0;
10529
10530 if (! if_false_label)
10531 drop_through_label = if_false_label = gen_label_rtx ();
10532
10533 for (i = 0; i < nwords; i++)
10534 do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
10535 operand_subword_force (op1, i, mode),
10536 EQ, TREE_UNSIGNED (TREE_TYPE (exp)),
10537 word_mode, NULL_RTX, if_false_label, NULL_RTX);
10538
10539 if (if_true_label)
10540 emit_jump (if_true_label);
10541 if (drop_through_label)
10542 emit_label (drop_through_label);
10543 }
10544
10545
10546
10547
10548
10549 void
10550 do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
10551 rtx op0;
10552 rtx if_false_label, if_true_label;
10553 {
10554 int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD;
10555 rtx part;
10556 int i;
10557 rtx drop_through_label = 0;
10558
10559
10560
10561
10562
10563
10564 part = gen_reg_rtx (word_mode);
10565 emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
10566 for (i = 1; i < nwords && part != 0; i++)
10567 part = expand_binop (word_mode, ior_optab, part,
10568 operand_subword_force (op0, i, GET_MODE (op0)),
10569 part, 1, OPTAB_WIDEN);
10570
10571 if (part != 0)
10572 {
10573 do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
10574 NULL_RTX, if_false_label, if_true_label);
10575
10576 return;
10577 }
10578
10579
10580 if (! if_false_label)
10581 drop_through_label = if_false_label = gen_label_rtx ();
10582
10583 for (i = 0; i < nwords; i++)
10584 do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
10585 const0_rtx, EQ, 1, word_mode, NULL_RTX,
10586 if_false_label, NULL_RTX);
10587
10588 if (if_true_label)
10589 emit_jump (if_true_label);
10590
10591 if (drop_through_label)
10592 emit_label (drop_through_label);
10593 }
10594
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606 rtx
10607 compare_from_rtx (op0, op1, code, unsignedp, mode, size)
10608 rtx op0, op1;
10609 enum rtx_code code;
10610 int unsignedp;
10611 enum machine_mode mode;
10612 rtx size;
10613 {
10614 enum rtx_code ucode;
10615 rtx tem;
10616
10617
10618
10619
10620 if (swap_commutative_operands_p (op0, op1))
10621 {
10622 tem = op0;
10623 op0 = op1;
10624 op1 = tem;
10625 code = swap_condition (code);
10626 }
10627
10628 if (flag_force_mem)
10629 {
10630 op0 = force_not_mem (op0);
10631 op1 = force_not_mem (op1);
10632 }
10633
10634 do_pending_stack_adjust ();
10635
10636 ucode = unsignedp ? unsigned_condition (code) : code;
10637 if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
10638 return tem;
10639
10640 #if 0
10641
10642
10643
10644
10645
10646
10647
10648
10649
10650
10651
10652 if ((code == EQ || code == NE) && ! unsignedp
10653 && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
10654 {
10655 if (GET_CODE (op1) == CONST_INT
10656 && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
10657 op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
10658 unsignedp = 1;
10659 }
10660 #endif
10661
10662 emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
10663
10664 #if HAVE_cc0
10665 return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
10666 #else
10667 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
10668 #endif
10669 }
10670
10671
10672
10673
10674
10675
10676
10677 void
10678 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size,
10679 if_false_label, if_true_label)
10680 rtx op0, op1;
10681 enum rtx_code code;
10682 int unsignedp;
10683 enum machine_mode mode;
10684 rtx size;
10685 rtx if_false_label, if_true_label;
10686 {
10687 enum rtx_code ucode;
10688 rtx tem;
10689 int dummy_true_label = 0;
10690
10691
10692
10693 if (! if_true_label && ! FLOAT_MODE_P (mode))
10694 {
10695 if_true_label = if_false_label;
10696 if_false_label = 0;
10697 code = reverse_condition (code);
10698 }
10699
10700
10701
10702
10703 if (swap_commutative_operands_p (op0, op1))
10704 {
10705 tem = op0;
10706 op0 = op1;
10707 op1 = tem;
10708 code = swap_condition (code);
10709 }
10710
10711 if (flag_force_mem)
10712 {
10713 op0 = force_not_mem (op0);
10714 op1 = force_not_mem (op1);
10715 }
10716
10717 do_pending_stack_adjust ();
10718
10719 ucode = unsignedp ? unsigned_condition (code) : code;
10720 if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
10721 {
10722 if (tem == const_true_rtx)
10723 {
10724 if (if_true_label)
10725 emit_jump (if_true_label);
10726 }
10727 else
10728 {
10729 if (if_false_label)
10730 emit_jump (if_false_label);
10731 }
10732 return;
10733 }
10734
10735 #if 0
10736
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747 if ((code == EQ || code == NE) && ! unsignedp
10748 && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
10749 {
10750 if (GET_CODE (op1) == CONST_INT
10751 && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
10752 op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
10753 unsignedp = 1;
10754 }
10755 #endif
10756
10757 if (! if_true_label)
10758 {
10759 dummy_true_label = 1;
10760 if_true_label = gen_label_rtx ();
10761 }
10762
10763 emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
10764 if_true_label);
10765
10766 if (if_false_label)
10767 emit_jump (if_false_label);
10768 if (dummy_true_label)
10769 emit_label (if_true_label);
10770 }
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782 static void
10783 do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
10784 if_true_label)
10785 tree exp;
10786 enum rtx_code signed_code, unsigned_code;
10787 rtx if_false_label, if_true_label;
10788 {
10789 rtx op0, op1;
10790 tree type;
10791 enum machine_mode mode;
10792 int unsignedp;
10793 enum rtx_code code;
10794
10795
10796 op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
10797 if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
10798 return;
10799
10800 op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
10801 if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
10802 return;
10803
10804 type = TREE_TYPE (TREE_OPERAND (exp, 0));
10805 mode = TYPE_MODE (type);
10806 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
10807 && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
10808 || (GET_MODE_BITSIZE (mode)
10809 > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
10810 1)))))))
10811 {
10812
10813
10814 type = TREE_TYPE (TREE_OPERAND (exp, 1));
10815 mode = TYPE_MODE (type);
10816 }
10817 unsignedp = TREE_UNSIGNED (type);
10818 code = unsignedp ? unsigned_code : signed_code;
10819
10820 #ifdef HAVE_canonicalize_funcptr_for_compare
10821
10822
10823 if (HAVE_canonicalize_funcptr_for_compare
10824 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
10825 && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
10826 == FUNCTION_TYPE))
10827 {
10828 rtx new_op0 = gen_reg_rtx (mode);
10829
10830 emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
10831 op0 = new_op0;
10832 }
10833
10834 if (HAVE_canonicalize_funcptr_for_compare
10835 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
10836 && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
10837 == FUNCTION_TYPE))
10838 {
10839 rtx new_op1 = gen_reg_rtx (mode);
10840
10841 emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
10842 op1 = new_op1;
10843 }
10844 #endif
10845
10846
10847 emit_queue ();
10848
10849 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
10850 ((mode == BLKmode)
10851 ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
10852 if_false_label, if_true_label);
10853 }
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875 static rtx
10876 do_store_flag (exp, target, mode, only_cheap)
10877 tree exp;
10878 rtx target;
10879 enum machine_mode mode;
10880 int only_cheap;
10881 {
10882 enum rtx_code code;
10883 tree arg0, arg1, type;
10884 tree tem;
10885 enum machine_mode operand_mode;
10886 int invert = 0;
10887 int unsignedp;
10888 rtx op0, op1;
10889 enum insn_code icode;
10890 rtx subtarget = target;
10891 rtx result, label;
10892
10893
10894
10895
10896
10897
10898 if (TREE_CODE (exp) == TRUTH_NOT_EXPR)
10899 invert = 1, exp = TREE_OPERAND (exp, 0);
10900
10901 arg0 = TREE_OPERAND (exp, 0);
10902 arg1 = TREE_OPERAND (exp, 1);
10903
10904
10905 if (arg0 == error_mark_node || arg1 == error_mark_node)
10906 return const0_rtx;
10907
10908 type = TREE_TYPE (arg0);
10909 operand_mode = TYPE_MODE (type);
10910 unsignedp = TREE_UNSIGNED (type);
10911
10912
10913
10914 if (operand_mode == BLKmode)
10915 return 0;
10916
10917
10918
10919 #ifdef HAVE_canonicalize_funcptr_for_compare
10920 if (HAVE_canonicalize_funcptr_for_compare
10921 && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
10922 && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
10923 == FUNCTION_TYPE))
10924 || (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
10925 && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
10926 == FUNCTION_TYPE))))
10927 return 0;
10928 #endif
10929
10930 STRIP_NOPS (arg0);
10931 STRIP_NOPS (arg1);
10932
10933
10934
10935
10936
10937
10938
10939
10940 switch (TREE_CODE (exp))
10941 {
10942 case EQ_EXPR:
10943 code = EQ;
10944 break;
10945 case NE_EXPR:
10946 code = NE;
10947 break;
10948 case LT_EXPR:
10949 if (integer_onep (arg1))
10950 arg1 = integer_zero_node, code = unsignedp ? LEU : LE;
10951 else
10952 code = unsignedp ? LTU : LT;
10953 break;
10954 case LE_EXPR:
10955 if (! unsignedp && integer_all_onesp (arg1))
10956 arg1 = integer_zero_node, code = LT;
10957 else
10958 code = unsignedp ? LEU : LE;
10959 break;
10960 case GT_EXPR:
10961 if (! unsignedp && integer_all_onesp (arg1))
10962 arg1 = integer_zero_node, code = GE;
10963 else
10964 code = unsignedp ? GTU : GT;
10965 break;
10966 case GE_EXPR:
10967 if (integer_onep (arg1))
10968 arg1 = integer_zero_node, code = unsignedp ? GTU : GT;
10969 else
10970 code = unsignedp ? GEU : GE;
10971 break;
10972
10973 case UNORDERED_EXPR:
10974 code = UNORDERED;
10975 break;
10976 case ORDERED_EXPR:
10977 code = ORDERED;
10978 break;
10979 case UNLT_EXPR:
10980 code = UNLT;
10981 break;
10982 case UNLE_EXPR:
10983 code = UNLE;
10984 break;
10985 case UNGT_EXPR:
10986 code = UNGT;
10987 break;
10988 case UNGE_EXPR:
10989 code = UNGE;
10990 break;
10991 case UNEQ_EXPR:
10992 code = UNEQ;
10993 break;
10994
10995 default:
10996 abort ();
10997 }
10998
10999
11000 if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST)
11001 {
11002 tem = arg0; arg0 = arg1; arg1 = tem;
11003 code = swap_condition (code);
11004 }
11005
11006
11007
11008
11009
11010
11011
11012 if ((code == NE || code == EQ)
11013 && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
11014 && integer_pow2p (TREE_OPERAND (arg0, 1)))
11015 {
11016 tree inner = TREE_OPERAND (arg0, 0);
11017 int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
11018 int ops_unsignedp;
11019
11020
11021
11022
11023 if (TREE_CODE (inner) == RSHIFT_EXPR
11024 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
11025 && TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0
11026 && bitnum < TYPE_PRECISION (type)
11027 && 0 > compare_tree_int (TREE_OPERAND (inner, 1),
11028 bitnum - TYPE_PRECISION (type)))
11029 {
11030 bitnum += TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
11031 inner = TREE_OPERAND (inner, 0);
11032 }
11033
11034
11035
11036
11037 ops_unsignedp = (bitnum == TYPE_PRECISION (type) - 1 ? 1
11038 #ifdef LOAD_EXTEND_OP
11039 : (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1)
11040 #else
11041 : 1
11042 #endif
11043 );
11044
11045 if (! get_subtarget (subtarget)
11046 || GET_MODE (subtarget) != operand_mode
11047 || ! safe_from_p (subtarget, inner, 1))
11048 subtarget = 0;
11049
11050 op0 = expand_expr (inner, subtarget, VOIDmode, 0);
11051
11052 if (bitnum != 0)
11053 op0 = expand_shift (RSHIFT_EXPR, operand_mode, op0,
11054 size_int (bitnum), subtarget, ops_unsignedp);
11055
11056 if (GET_MODE (op0) != mode)
11057 op0 = convert_to_mode (mode, op0, ops_unsignedp);
11058
11059 if ((code == EQ && ! invert) || (code == NE && invert))
11060 op0 = expand_binop (mode, xor_optab, op0, const1_rtx, subtarget,
11061 ops_unsignedp, OPTAB_LIB_WIDEN);
11062
11063
11064 if (bitnum != TYPE_PRECISION (type) - 1)
11065 op0 = expand_and (mode, op0, const1_rtx, subtarget);
11066
11067 return op0;
11068 }
11069
11070
11071 if (! can_compare_p (code, operand_mode, ccp_store_flag))
11072 return 0;
11073
11074 icode = setcc_gen_code[(int) code];
11075 if (icode == CODE_FOR_nothing
11076 || (only_cheap && insn_data[(int) icode].operand[0].mode != mode))
11077 {
11078
11079
11080 if ((code == LT && integer_zerop (arg1))
11081 || (! only_cheap && code == GE && integer_zerop (arg1)))
11082 ;
11083 else if (BRANCH_COST >= 0
11084 && ! only_cheap && (code == NE || code == EQ)
11085 && TREE_CODE (type) != REAL_TYPE
11086 && ((abs_optab->handlers[(int) operand_mode].insn_code
11087 != CODE_FOR_nothing)
11088 || (ffs_optab->handlers[(int) operand_mode].insn_code
11089 != CODE_FOR_nothing)))
11090 ;
11091 else
11092 return 0;
11093 }
11094
11095 if (! get_subtarget (target)
11096 || GET_MODE (subtarget) != operand_mode
11097 || ! safe_from_p (subtarget, arg1, 1))
11098 subtarget = 0;
11099
11100 op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
11101 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
11102
11103 if (target == 0)
11104 target = gen_reg_rtx (mode);
11105
11106
11107
11108
11109
11110 result = emit_store_flag (target, code,
11111 queued_subexp_p (op0) ? copy_rtx (op0) : op0,
11112 queued_subexp_p (op1) ? copy_rtx (op1) : op1,
11113 operand_mode, unsignedp, 1);
11114
11115 if (result)
11116 {
11117 if (invert)
11118 result = expand_binop (mode, xor_optab, result, const1_rtx,
11119 result, 0, OPTAB_LIB_WIDEN);
11120 return result;
11121 }
11122
11123
11124 if (GET_CODE (target) != REG
11125 || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
11126 target = gen_reg_rtx (GET_MODE (target));
11127
11128 emit_move_insn (target, invert ? const0_rtx : const1_rtx);
11129 result = compare_from_rtx (op0, op1, code, unsignedp,
11130 operand_mode, NULL_RTX);
11131 if (GET_CODE (result) == CONST_INT)
11132 return (((result == const0_rtx && ! invert)
11133 || (result != const0_rtx && invert))
11134 ? const0_rtx : const1_rtx);
11135
11136
11137
11138
11139
11140
11141
11142 code = GET_CODE (result);
11143
11144 label = gen_label_rtx ();
11145 if (bcc_gen_fctn[(int) code] == 0)
11146 abort ();
11147
11148 emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
11149 emit_move_insn (target, invert ? const1_rtx : const0_rtx);
11150 emit_label (label);
11151
11152 return target;
11153 }
11154
11155
11156
11157 #ifndef HAVE_casesi
11158 # define HAVE_casesi 0
11159 # define gen_casesi(a, b, c, d, e) (0)
11160 # define CODE_FOR_casesi CODE_FOR_nothing
11161 #endif
11162
11163
11164
11165
11166 #ifndef CASE_VALUES_THRESHOLD
11167 #define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
11168 #endif
11169
11170 unsigned int
11171 case_values_threshold ()
11172 {
11173 return CASE_VALUES_THRESHOLD;
11174 }
11175
11176
11177
11178 int
11179 try_casesi (index_type, index_expr, minval, range,
11180 table_label, default_label)
11181 tree index_type, index_expr, minval, range;
11182 rtx table_label ATTRIBUTE_UNUSED;
11183 rtx default_label;
11184 {
11185 enum machine_mode index_mode = SImode;
11186 int index_bits = GET_MODE_BITSIZE (index_mode);
11187 rtx op1, op2, index;
11188 enum machine_mode op_mode;
11189
11190 if (! HAVE_casesi)
11191 return 0;
11192
11193
11194 if (GET_MODE_BITSIZE (TYPE_MODE (index_type)) > GET_MODE_BITSIZE (index_mode))
11195 {
11196 enum machine_mode omode = TYPE_MODE (index_type);
11197 rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
11198
11199
11200 index_expr = build (MINUS_EXPR, index_type,
11201 index_expr, minval);
11202 minval = integer_zero_node;
11203 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
11204 emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
11205 omode, 1, default_label);
11206
11207 index = convert_to_mode (index_mode, index, 0);
11208 }
11209 else
11210 {
11211 if (TYPE_MODE (index_type) != index_mode)
11212 {
11213 index_expr = convert ((*lang_hooks.types.type_for_size)
11214 (index_bits, 0), index_expr);
11215 index_type = TREE_TYPE (index_expr);
11216 }
11217
11218 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
11219 }
11220 emit_queue ();
11221 index = protect_from_queue (index, 0);
11222 do_pending_stack_adjust ();
11223
11224 op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
11225 if (! (*insn_data[(int) CODE_FOR_casesi].operand[0].predicate)
11226 (index, op_mode))
11227 index = copy_to_mode_reg (op_mode, index);
11228
11229 op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
11230
11231 op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
11232 op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
11233 op1, TREE_UNSIGNED (TREE_TYPE (minval)));
11234 if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
11235 (op1, op_mode))
11236 op1 = copy_to_mode_reg (op_mode, op1);
11237
11238 op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
11239
11240 op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
11241 op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
11242 op2, TREE_UNSIGNED (TREE_TYPE (range)));
11243 if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
11244 (op2, op_mode))
11245 op2 = copy_to_mode_reg (op_mode, op2);
11246
11247 emit_jump_insn (gen_casesi (index, op1, op2,
11248 table_label, default_label));
11249 return 1;
11250 }
11251
11252
11253 #ifndef HAVE_tablejump
11254 #define HAVE_tablejump 0
11255 #define gen_tablejump(x, y) (0)
11256 #endif
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269 static void
11270 do_tablejump (index, mode, range, table_label, default_label)
11271 rtx index, range, table_label, default_label;
11272 enum machine_mode mode;
11273 {
11274 rtx temp, vector;
11275
11276 if (INTVAL (range) > cfun->max_jumptable_ents)
11277 cfun->max_jumptable_ents = INTVAL (range);
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287 emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
11288 default_label);
11289
11290
11291
11292 if (mode != Pmode)
11293 index = convert_to_mode (Pmode, index, 1);
11294
11295
11296
11297
11298 #ifdef PIC_CASE_VECTOR_ADDRESS
11299 if (flag_pic && GET_CODE (index) != REG)
11300 index = copy_to_mode_reg (Pmode, index);
11301 #endif
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311 index = gen_rtx_PLUS (Pmode,
11312 gen_rtx_MULT (Pmode, index,
11313 GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))),
11314 gen_rtx_LABEL_REF (Pmode, table_label));
11315 #ifdef PIC_CASE_VECTOR_ADDRESS
11316 if (flag_pic)
11317 index = PIC_CASE_VECTOR_ADDRESS (index);
11318 else
11319 #endif
11320 index = memory_address_noforce (CASE_VECTOR_MODE, index);
11321 temp = gen_reg_rtx (CASE_VECTOR_MODE);
11322 vector = gen_rtx_MEM (CASE_VECTOR_MODE, index);
11323 RTX_UNCHANGING_P (vector) = 1;
11324 MEM_NOTRAP_P (vector) = 1;
11325 convert_move (temp, vector, 0);
11326
11327 emit_jump_insn (gen_tablejump (temp, table_label));
11328
11329
11330
11331 if (! CASE_VECTOR_PC_RELATIVE && ! flag_pic)
11332 emit_barrier ();
11333 }
11334
11335 int
11336 try_tablejump (index_type, index_expr, minval, range,
11337 table_label, default_label)
11338 tree index_type, index_expr, minval, range;
11339 rtx table_label, default_label;
11340 {
11341 rtx index;
11342
11343 if (! HAVE_tablejump)
11344 return 0;
11345
11346 index_expr = fold (build (MINUS_EXPR, index_type,
11347 convert (index_type, index_expr),
11348 convert (index_type, minval)));
11349 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
11350 emit_queue ();
11351 index = protect_from_queue (index, 0);
11352 do_pending_stack_adjust ();
11353
11354 do_tablejump (index, TYPE_MODE (index_type),
11355 convert_modes (TYPE_MODE (index_type),
11356 TYPE_MODE (TREE_TYPE (range)),
11357 expand_expr (range, NULL_RTX,
11358 VOIDmode, 0),
11359 TREE_UNSIGNED (TREE_TYPE (range))),
11360 table_label, default_label);
11361 return 1;
11362 }
11363
11364
11365
11366
11367
11368 int
11369 vector_mode_valid_p (mode)
11370 enum machine_mode mode;
11371 {
11372 enum mode_class class = GET_MODE_CLASS (mode);
11373 enum machine_mode innermode;
11374
11375
11376 if (class != MODE_VECTOR_INT
11377 && class != MODE_VECTOR_FLOAT)
11378 return 0;
11379
11380
11381 if (VECTOR_MODE_SUPPORTED_P (mode))
11382 return 1;
11383
11384 innermode = GET_MODE_INNER (mode);
11385
11386
11387
11388
11389
11390
11391 return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
11392 }
11393
11394
11395 static rtx
11396 const_vector_from_tree (exp)
11397 tree exp;
11398 {
11399 rtvec v;
11400 int units, i;
11401 tree link, elt;
11402 enum machine_mode inner, mode;
11403
11404 mode = TYPE_MODE (TREE_TYPE (exp));
11405
11406 if (is_zeros_p (exp))
11407 return CONST0_RTX (mode);
11408
11409 units = GET_MODE_NUNITS (mode);
11410 inner = GET_MODE_INNER (mode);
11411
11412 v = rtvec_alloc (units);
11413
11414 link = TREE_VECTOR_CST_ELTS (exp);
11415 for (i = 0; link; link = TREE_CHAIN (link), ++i)
11416 {
11417 elt = TREE_VALUE (link);
11418
11419 if (TREE_CODE (elt) == REAL_CST)
11420 RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
11421 inner);
11422 else
11423 RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
11424 TREE_INT_CST_HIGH (elt),
11425 inner);
11426 }
11427
11428 return gen_rtx_raw_CONST_VECTOR (mode, v);
11429 }
11430
11431 #include "gt-expr.h"