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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #include "config.h"
00074 #include "system.h"
00075 #include "coretypes.h"
00076 #include "tm.h"
00077 #include "rtl.h"
00078 #include "tree.h"
00079 #include "tm_p.h"
00080 #include "flags.h"
00081 #include "regs.h"
00082 #include "hard-reg-set.h"
00083 #include "basic-block.h"
00084 #include "insn-config.h"
00085 #include "function.h"
00086
00087 #include "expr.h"
00088 #include "insn-attr.h"
00089 #include "recog.h"
00090 #include "real.h"
00091 #include "toplev.h"
00092 #include "target.h"
00093 #include "optabs.h"
00094 #include "insn-codes.h"
00095 #include "rtlhooks-def.h"
00096
00097 #include "output.h"
00098 #include "params.h"
00099
00100
00101
00102 static int combine_attempts;
00103
00104
00105
00106 static int combine_merges;
00107
00108
00109
00110 static int combine_extras;
00111
00112
00113
00114 static int combine_successes;
00115
00116
00117
00118 static int total_attempts, total_merges, total_extras, total_successes;
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 static int *uid_cuid;
00129 static int max_uid_cuid;
00130
00131
00132
00133 #define INSN_CUID(INSN) \
00134 (INSN_UID (INSN) > max_uid_cuid ? insn_cuid (INSN) : uid_cuid[INSN_UID (INSN)])
00135
00136
00137
00138
00139 #define UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD(val) \
00140 (((unsigned HOST_WIDE_INT) (val) << (BITS_PER_WORD - 1)) << 1)
00141
00142
00143
00144 static unsigned int combine_max_regno;
00145
00146 struct reg_stat {
00147
00148 rtx last_death;
00149
00150
00151 rtx last_set;
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 rtx last_set_value;
00199
00200
00201
00202
00203 int last_set_table_tick;
00204
00205
00206
00207
00208 int last_set_label;
00209
00210
00211
00212
00213
00214
00215 unsigned HOST_WIDE_INT last_set_nonzero_bits;
00216 char last_set_sign_bit_copies;
00217 ENUM_BITFIELD(machine_mode) last_set_mode : 8;
00218
00219
00220
00221
00222
00223 char last_set_invalid;
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 unsigned char sign_bit_copies;
00238
00239 unsigned HOST_WIDE_INT nonzero_bits;
00240 };
00241
00242 static struct reg_stat *reg_stat;
00243
00244
00245
00246
00247 static int mem_last_set;
00248
00249
00250
00251
00252 static int last_call_cuid;
00253
00254
00255
00256
00257
00258
00259
00260 static rtx subst_insn;
00261
00262
00263
00264
00265
00266
00267
00268
00269 static int subst_low_cuid;
00270
00271
00272
00273
00274 static HARD_REG_SET newpat_used_regs;
00275
00276
00277
00278
00279
00280 static rtx added_links_insn;
00281
00282
00283 static basic_block this_basic_block;
00284
00285
00286
00287
00288 static sbitmap refresh_blocks;
00289
00290
00291
00292
00293 static int *uid_insn_cost;
00294
00295
00296
00297 static int last_insn_cost;
00298
00299
00300
00301 static int label_tick;
00302
00303
00304
00305
00306 static enum machine_mode nonzero_bits_mode;
00307
00308
00309
00310
00311
00312
00313
00314 static int nonzero_sign_valid;
00315
00316
00317
00318
00319
00320
00321 struct undo
00322 {
00323 struct undo *next;
00324 int is_int;
00325 union {rtx r; int i;} old_contents;
00326 union {rtx *r; int *i;} where;
00327 };
00328
00329
00330
00331
00332
00333
00334
00335 struct undobuf
00336 {
00337 struct undo *undos;
00338 struct undo *frees;
00339 rtx other_insn;
00340 };
00341
00342 static struct undobuf undobuf;
00343
00344
00345
00346
00347 static int n_occurrences;
00348
00349 static rtx reg_nonzero_bits_for_combine (rtx, enum machine_mode, rtx,
00350 enum machine_mode,
00351 unsigned HOST_WIDE_INT,
00352 unsigned HOST_WIDE_INT *);
00353 static rtx reg_num_sign_bit_copies_for_combine (rtx, enum machine_mode, rtx,
00354 enum machine_mode,
00355 unsigned int, unsigned int *);
00356 static void do_SUBST (rtx *, rtx);
00357 static void do_SUBST_INT (int *, int);
00358 static void init_reg_last (void);
00359 static void setup_incoming_promotions (void);
00360 static void set_nonzero_bits_and_sign_copies (rtx, rtx, void *);
00361 static int cant_combine_insn_p (rtx);
00362 static int can_combine_p (rtx, rtx, rtx, rtx, rtx *, rtx *);
00363 static int combinable_i3pat (rtx, rtx *, rtx, rtx, int, rtx *);
00364 static int contains_muldiv (rtx);
00365 static rtx try_combine (rtx, rtx, rtx, int *);
00366 static void undo_all (void);
00367 static void undo_commit (void);
00368 static rtx *find_split_point (rtx *, rtx);
00369 static rtx subst (rtx, rtx, rtx, int, int);
00370 static rtx combine_simplify_rtx (rtx, enum machine_mode, int);
00371 static rtx simplify_if_then_else (rtx);
00372 static rtx simplify_set (rtx);
00373 static rtx simplify_logical (rtx);
00374 static rtx expand_compound_operation (rtx);
00375 static rtx expand_field_assignment (rtx);
00376 static rtx make_extraction (enum machine_mode, rtx, HOST_WIDE_INT,
00377 rtx, unsigned HOST_WIDE_INT, int, int, int);
00378 static rtx extract_left_shift (rtx, int);
00379 static rtx make_compound_operation (rtx, enum rtx_code);
00380 static int get_pos_from_mask (unsigned HOST_WIDE_INT,
00381 unsigned HOST_WIDE_INT *);
00382 static rtx force_to_mode (rtx, enum machine_mode,
00383 unsigned HOST_WIDE_INT, rtx, int);
00384 static rtx if_then_else_cond (rtx, rtx *, rtx *);
00385 static rtx known_cond (rtx, enum rtx_code, rtx, rtx);
00386 static int rtx_equal_for_field_assignment_p (rtx, rtx);
00387 static rtx make_field_assignment (rtx);
00388 static rtx apply_distributive_law (rtx);
00389 static rtx distribute_and_simplify_rtx (rtx, int);
00390 static rtx simplify_and_const_int (rtx, enum machine_mode, rtx,
00391 unsigned HOST_WIDE_INT);
00392 static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code,
00393 HOST_WIDE_INT, enum machine_mode, int *);
00394 static rtx simplify_shift_const (rtx, enum rtx_code, enum machine_mode, rtx,
00395 int);
00396 static int recog_for_combine (rtx *, rtx, rtx *);
00397 static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
00398 static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
00399 static void update_table_tick (rtx);
00400 static void record_value_for_reg (rtx, rtx, rtx);
00401 static void check_promoted_subreg (rtx, rtx);
00402 static void record_dead_and_set_regs_1 (rtx, rtx, void *);
00403 static void record_dead_and_set_regs (rtx);
00404 static int get_last_value_validate (rtx *, rtx, int, int);
00405 static rtx get_last_value (rtx);
00406 static int use_crosses_set_p (rtx, int);
00407 static void reg_dead_at_p_1 (rtx, rtx, void *);
00408 static int reg_dead_at_p (rtx, rtx);
00409 static void move_deaths (rtx, rtx, int, rtx, rtx *);
00410 static int reg_bitfield_target_p (rtx, rtx);
00411 static void distribute_notes (rtx, rtx, rtx, rtx);
00412 static void distribute_links (rtx);
00413 static void mark_used_regs_combine (rtx);
00414 static int insn_cuid (rtx);
00415 static void record_promoted_value (rtx, rtx);
00416 static rtx reversed_comparison (rtx, enum machine_mode, rtx, rtx);
00417 static enum rtx_code combine_reversed_comparison_code (rtx);
00418 static int unmentioned_reg_p_1 (rtx *, void *);
00419 static bool unmentioned_reg_p (rtx, rtx);
00420
00421
00422
00423
00424 #undef RTL_HOOKS_GEN_LOWPART
00425 #define RTL_HOOKS_GEN_LOWPART gen_lowpart_for_combine
00426
00427 #undef RTL_HOOKS_REG_NONZERO_REG_BITS
00428 #define RTL_HOOKS_REG_NONZERO_REG_BITS reg_nonzero_bits_for_combine
00429
00430 #undef RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES
00431 #define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES reg_num_sign_bit_copies_for_combine
00432
00433 static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
00434
00435
00436
00437
00438
00439
00440
00441
00442 static void
00443 do_SUBST (rtx *into, rtx newval)
00444 {
00445 struct undo *buf;
00446 rtx oldval = *into;
00447
00448 if (oldval == newval)
00449 return;
00450
00451
00452
00453
00454
00455
00456 if (GET_MODE_CLASS (GET_MODE (oldval)) == MODE_INT
00457 && GET_CODE (newval) == CONST_INT)
00458 {
00459
00460
00461 gcc_assert (INTVAL (newval)
00462 == trunc_int_for_mode (INTVAL (newval), GET_MODE (oldval)));
00463
00464
00465
00466
00467
00468
00469
00470 gcc_assert (!(GET_CODE (oldval) == SUBREG
00471 && GET_CODE (SUBREG_REG (oldval)) == CONST_INT));
00472 gcc_assert (!(GET_CODE (oldval) == ZERO_EXTEND
00473 && GET_CODE (XEXP (oldval, 0)) == CONST_INT));
00474 }
00475
00476 if (undobuf.frees)
00477 buf = undobuf.frees, undobuf.frees = buf->next;
00478 else
00479 buf = xmalloc (sizeof (struct undo));
00480
00481 buf->is_int = 0;
00482 buf->where.r = into;
00483 buf->old_contents.r = oldval;
00484 *into = newval;
00485
00486 buf->next = undobuf.undos, undobuf.undos = buf;
00487 }
00488
00489 #define SUBST(INTO, NEWVAL) do_SUBST(&(INTO), (NEWVAL))
00490
00491
00492
00493
00494
00495 static void
00496 do_SUBST_INT (int *into, int newval)
00497 {
00498 struct undo *buf;
00499 int oldval = *into;
00500
00501 if (oldval == newval)
00502 return;
00503
00504 if (undobuf.frees)
00505 buf = undobuf.frees, undobuf.frees = buf->next;
00506 else
00507 buf = xmalloc (sizeof (struct undo));
00508
00509 buf->is_int = 1;
00510 buf->where.i = into;
00511 buf->old_contents.i = oldval;
00512 *into = newval;
00513
00514 buf->next = undobuf.undos, undobuf.undos = buf;
00515 }
00516
00517 #define SUBST_INT(INTO, NEWVAL) do_SUBST_INT(&(INTO), (NEWVAL))
00518
00519
00520
00521
00522
00523
00524
00525
00526 static bool
00527 combine_validate_cost (rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat)
00528 {
00529 int i1_cost, i2_cost, i3_cost;
00530 int new_i2_cost, new_i3_cost;
00531 int old_cost, new_cost;
00532
00533
00534 i2_cost = INSN_UID (i2) <= last_insn_cost
00535 ? uid_insn_cost[INSN_UID (i2)] : 0;
00536 i3_cost = INSN_UID (i3) <= last_insn_cost
00537 ? uid_insn_cost[INSN_UID (i3)] : 0;
00538
00539 if (i1)
00540 {
00541 i1_cost = INSN_UID (i1) <= last_insn_cost
00542 ? uid_insn_cost[INSN_UID (i1)] : 0;
00543 old_cost = (i1_cost > 0 && i2_cost > 0 && i3_cost > 0)
00544 ? i1_cost + i2_cost + i3_cost : 0;
00545 }
00546 else
00547 {
00548 old_cost = (i2_cost > 0 && i3_cost > 0) ? i2_cost + i3_cost : 0;
00549 i1_cost = 0;
00550 }
00551
00552
00553 new_i3_cost = insn_rtx_cost (newpat);
00554 if (newi2pat)
00555 {
00556 new_i2_cost = insn_rtx_cost (newi2pat);
00557 new_cost = (new_i2_cost > 0 && new_i3_cost > 0)
00558 ? new_i2_cost + new_i3_cost : 0;
00559 }
00560 else
00561 {
00562 new_cost = new_i3_cost;
00563 new_i2_cost = 0;
00564 }
00565
00566 if (undobuf.other_insn)
00567 {
00568 int old_other_cost, new_other_cost;
00569
00570 old_other_cost = (INSN_UID (undobuf.other_insn) <= last_insn_cost
00571 ? uid_insn_cost[INSN_UID (undobuf.other_insn)] : 0);
00572 new_other_cost = insn_rtx_cost (PATTERN (undobuf.other_insn));
00573 if (old_other_cost > 0 && new_other_cost > 0)
00574 {
00575 old_cost += old_other_cost;
00576 new_cost += new_other_cost;
00577 }
00578 else
00579 old_cost = 0;
00580 }
00581
00582
00583
00584 if (old_cost > 0
00585 && new_cost > old_cost)
00586 {
00587 if (dump_file)
00588 {
00589 if (i1)
00590 {
00591 fprintf (dump_file,
00592 "rejecting combination of insns %d, %d and %d\n",
00593 INSN_UID (i1), INSN_UID (i2), INSN_UID (i3));
00594 fprintf (dump_file, "original costs %d + %d + %d = %d\n",
00595 i1_cost, i2_cost, i3_cost, old_cost);
00596 }
00597 else
00598 {
00599 fprintf (dump_file,
00600 "rejecting combination of insns %d and %d\n",
00601 INSN_UID (i2), INSN_UID (i3));
00602 fprintf (dump_file, "original costs %d + %d = %d\n",
00603 i2_cost, i3_cost, old_cost);
00604 }
00605
00606 if (newi2pat)
00607 {
00608 fprintf (dump_file, "replacement costs %d + %d = %d\n",
00609 new_i2_cost, new_i3_cost, new_cost);
00610 }
00611 else
00612 fprintf (dump_file, "replacement cost %d\n", new_cost);
00613 }
00614
00615 return false;
00616 }
00617
00618
00619 uid_insn_cost[INSN_UID (i2)] = new_i2_cost;
00620 uid_insn_cost[INSN_UID (i3)] = new_i3_cost;
00621 if (i1)
00622 uid_insn_cost[INSN_UID (i1)] = 0;
00623
00624 return true;
00625 }
00626
00627
00628
00629
00630
00631
00632 int
00633 combine_instructions (rtx f, unsigned int nregs)
00634 {
00635 rtx insn, next;
00636 #ifdef HAVE_cc0
00637 rtx prev;
00638 #endif
00639 int i;
00640 rtx links, nextlinks;
00641
00642 int new_direct_jump_p = 0;
00643
00644 combine_attempts = 0;
00645 combine_merges = 0;
00646 combine_extras = 0;
00647 combine_successes = 0;
00648
00649 combine_max_regno = nregs;
00650
00651 rtl_hooks = combine_rtl_hooks;
00652
00653 reg_stat = xcalloc (nregs, sizeof (struct reg_stat));
00654
00655 init_recog_no_volatile ();
00656
00657
00658
00659 for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
00660 if (INSN_UID (insn) > i)
00661 i = INSN_UID (insn);
00662
00663 uid_cuid = xmalloc ((i + 1) * sizeof (int));
00664 max_uid_cuid = i;
00665
00666 nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
00667
00668
00669
00670
00671 nonzero_sign_valid = 0;
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 label_tick = 1;
00685
00686 setup_incoming_promotions ();
00687
00688 refresh_blocks = sbitmap_alloc (last_basic_block);
00689 sbitmap_zero (refresh_blocks);
00690
00691
00692 uid_insn_cost = xcalloc (max_uid_cuid + 1, sizeof (int));
00693 last_insn_cost = max_uid_cuid;
00694
00695 for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
00696 {
00697 uid_cuid[INSN_UID (insn)] = ++i;
00698 subst_low_cuid = i;
00699 subst_insn = insn;
00700
00701 if (INSN_P (insn))
00702 {
00703 note_stores (PATTERN (insn), set_nonzero_bits_and_sign_copies,
00704 NULL);
00705 record_dead_and_set_regs (insn);
00706
00707 #ifdef AUTO_INC_DEC
00708 for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
00709 if (REG_NOTE_KIND (links) == REG_INC)
00710 set_nonzero_bits_and_sign_copies (XEXP (links, 0), NULL_RTX,
00711 NULL);
00712 #endif
00713
00714
00715 if (NONJUMP_INSN_P (insn))
00716 uid_insn_cost[INSN_UID (insn)] = insn_rtx_cost (PATTERN (insn));
00717 if (dump_file)
00718 fprintf(dump_file, "insn_cost %d: %d\n",
00719 INSN_UID (insn), uid_insn_cost[INSN_UID (insn)]);
00720 }
00721
00722 if (LABEL_P (insn))
00723 label_tick++;
00724 }
00725
00726 nonzero_sign_valid = 1;
00727
00728
00729
00730 label_tick = 1;
00731 last_call_cuid = 0;
00732 mem_last_set = 0;
00733 init_reg_last ();
00734 setup_incoming_promotions ();
00735
00736 FOR_EACH_BB (this_basic_block)
00737 {
00738 for (insn = BB_HEAD (this_basic_block);
00739 insn != NEXT_INSN (BB_END (this_basic_block));
00740 insn = next ? next : NEXT_INSN (insn))
00741 {
00742 next = 0;
00743
00744 if (LABEL_P (insn))
00745 label_tick++;
00746
00747 else if (INSN_P (insn))
00748 {
00749
00750
00751 check_promoted_subreg (insn, PATTERN (insn));
00752
00753
00754
00755 for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
00756 if ((next = try_combine (insn, XEXP (links, 0),
00757 NULL_RTX, &new_direct_jump_p)) != 0)
00758 goto retry;
00759
00760
00761
00762 for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
00763 {
00764 rtx link = XEXP (links, 0);
00765
00766
00767
00768 if (NOTE_P (link))
00769 continue;
00770
00771 for (nextlinks = LOG_LINKS (link);
00772 nextlinks;
00773 nextlinks = XEXP (nextlinks, 1))
00774 if ((next = try_combine (insn, link,
00775 XEXP (nextlinks, 0),
00776 &new_direct_jump_p)) != 0)
00777 goto retry;
00778 }
00779
00780 #ifdef HAVE_cc0
00781
00782
00783
00784
00785
00786
00787
00788 if (JUMP_P (insn)
00789 && (prev = prev_nonnote_insn (insn)) != 0
00790 && NONJUMP_INSN_P (prev)
00791 && sets_cc0_p (PATTERN (prev)))
00792 {
00793 if ((next = try_combine (insn, prev,
00794 NULL_RTX, &new_direct_jump_p)) != 0)
00795 goto retry;
00796
00797 for (nextlinks = LOG_LINKS (prev); nextlinks;
00798 nextlinks = XEXP (nextlinks, 1))
00799 if ((next = try_combine (insn, prev,
00800 XEXP (nextlinks, 0),
00801 &new_direct_jump_p)) != 0)
00802 goto retry;
00803 }
00804
00805
00806 if (NONJUMP_INSN_P (insn)
00807 && (prev = prev_nonnote_insn (insn)) != 0
00808 && NONJUMP_INSN_P (prev)
00809 && sets_cc0_p (PATTERN (prev))
00810 && GET_CODE (PATTERN (insn)) == SET
00811 && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
00812 {
00813 if ((next = try_combine (insn, prev,
00814 NULL_RTX, &new_direct_jump_p)) != 0)
00815 goto retry;
00816
00817 for (nextlinks = LOG_LINKS (prev); nextlinks;
00818 nextlinks = XEXP (nextlinks, 1))
00819 if ((next = try_combine (insn, prev,
00820 XEXP (nextlinks, 0),
00821 &new_direct_jump_p)) != 0)
00822 goto retry;
00823 }
00824
00825
00826
00827
00828 for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
00829 if (NONJUMP_INSN_P (XEXP (links, 0))
00830 && GET_CODE (PATTERN (XEXP (links, 0))) == SET
00831 && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
00832 && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
00833 && NONJUMP_INSN_P (prev)
00834 && sets_cc0_p (PATTERN (prev))
00835 && (next = try_combine (insn, XEXP (links, 0),
00836 prev, &new_direct_jump_p)) != 0)
00837 goto retry;
00838 #endif
00839
00840
00841
00842 for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
00843 for (nextlinks = XEXP (links, 1); nextlinks;
00844 nextlinks = XEXP (nextlinks, 1))
00845 if ((next = try_combine (insn, XEXP (links, 0),
00846 XEXP (nextlinks, 0),
00847 &new_direct_jump_p)) != 0)
00848 goto retry;
00849
00850
00851 for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
00852 {
00853 rtx set, note;
00854 rtx temp = XEXP (links, 0);
00855 if ((set = single_set (temp)) != 0
00856 && (note = find_reg_equal_equiv_note (temp)) != 0
00857 && GET_CODE (XEXP (note, 0)) != EXPR_LIST
00858
00859
00860 && ! unmentioned_reg_p (XEXP (note, 0), SET_SRC (set)))
00861 {
00862
00863
00864
00865 rtx orig = SET_SRC (set);
00866 SET_SRC (set) = XEXP (note, 0);
00867 next = try_combine (insn, temp, NULL_RTX,
00868 &new_direct_jump_p);
00869 if (next)
00870 goto retry;
00871 SET_SRC (set) = orig;
00872 }
00873 }
00874
00875 if (!NOTE_P (insn))
00876 record_dead_and_set_regs (insn);
00877
00878 retry:
00879 ;
00880 }
00881 }
00882 }
00883 clear_bb_flags ();
00884
00885 EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, i,
00886 BASIC_BLOCK (i)->flags |= BB_DIRTY);
00887 new_direct_jump_p |= purge_all_dead_edges (0);
00888 delete_noop_moves ();
00889
00890 update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
00891 PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
00892 | PROP_KILL_DEAD_CODE);
00893
00894
00895 sbitmap_free (refresh_blocks);
00896 free (uid_insn_cost);
00897 free (reg_stat);
00898 free (uid_cuid);
00899
00900 {
00901 struct undo *undo, *next;
00902 for (undo = undobuf.frees; undo; undo = next)
00903 {
00904 next = undo->next;
00905 free (undo);
00906 }
00907 undobuf.frees = 0;
00908 }
00909
00910 total_attempts += combine_attempts;
00911 total_merges += combine_merges;
00912 total_extras += combine_extras;
00913 total_successes += combine_successes;
00914
00915 nonzero_sign_valid = 0;
00916 rtl_hooks = general_rtl_hooks;
00917
00918
00919 init_recog ();
00920
00921 return new_direct_jump_p;
00922 }
00923
00924
00925
00926 static void
00927 init_reg_last (void)
00928 {
00929 unsigned int i;
00930 for (i = 0; i < combine_max_regno; i++)
00931 memset (reg_stat + i, 0, offsetof (struct reg_stat, sign_bit_copies));
00932 }
00933
00934
00935
00936 static void
00937 setup_incoming_promotions (void)
00938 {
00939 unsigned int regno;
00940 rtx reg;
00941 enum machine_mode mode;
00942 int unsignedp;
00943 rtx first = get_insns ();
00944
00945 if (targetm.calls.promote_function_args (TREE_TYPE (cfun->decl)))
00946 {
00947 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00948
00949
00950
00951 if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (regno))
00952 && (reg = promoted_input_arg (regno, &mode, &unsignedp)) != 0)
00953 {
00954 record_value_for_reg
00955 (reg, first, gen_rtx_fmt_e ((unsignedp ? ZERO_EXTEND
00956 : SIGN_EXTEND),
00957 GET_MODE (reg),
00958 gen_rtx_CLOBBER (mode, const0_rtx)));
00959 }
00960 }
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 static void
00975 set_nonzero_bits_and_sign_copies (rtx x, rtx set,
00976 void *data ATTRIBUTE_UNUSED)
00977 {
00978 unsigned int num;
00979
00980 if (REG_P (x)
00981 && REGNO (x) >= FIRST_PSEUDO_REGISTER
00982
00983
00984 && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, REGNO (x))
00985 && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
00986 {
00987 if (set == 0 || GET_CODE (set) == CLOBBER)
00988 {
00989 reg_stat[REGNO (x)].nonzero_bits = GET_MODE_MASK (GET_MODE (x));
00990 reg_stat[REGNO (x)].sign_bit_copies = 1;
00991 return;
00992 }
00993
00994
00995
00996 set = expand_field_assignment (set);
00997
00998
00999
01000
01001 if (SET_DEST (set) == x
01002 || (GET_CODE (SET_DEST (set)) == SUBREG
01003 && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
01004 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (set)))))
01005 && SUBREG_REG (SET_DEST (set)) == x))
01006 {
01007 rtx src = SET_SRC (set);
01008
01009 #ifdef SHORT_IMMEDIATES_SIGN_EXTEND
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD
01020 && GET_CODE (src) == CONST_INT
01021 && INTVAL (src) > 0
01022 && 0 != (INTVAL (src)
01023 & ((HOST_WIDE_INT) 1
01024 << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
01025 src = GEN_INT (INTVAL (src)
01026 | ((HOST_WIDE_INT) (-1)
01027 << GET_MODE_BITSIZE (GET_MODE (x))));
01028 #endif
01029
01030
01031 if (reg_stat[REGNO (x)].nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
01032 reg_stat[REGNO (x)].nonzero_bits
01033 |= nonzero_bits (src, nonzero_bits_mode);
01034 num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));
01035 if (reg_stat[REGNO (x)].sign_bit_copies == 0
01036 || reg_stat[REGNO (x)].sign_bit_copies > num)
01037 reg_stat[REGNO (x)].sign_bit_copies = num;
01038 }
01039 else
01040 {
01041 reg_stat[REGNO (x)].nonzero_bits = GET_MODE_MASK (GET_MODE (x));
01042 reg_stat[REGNO (x)].sign_bit_copies = 1;
01043 }
01044 }
01045 }
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 static int
01058 can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
01059 rtx *pdest, rtx *psrc)
01060 {
01061 int i;
01062 rtx set = 0, src, dest;
01063 rtx p;
01064 #ifdef AUTO_INC_DEC
01065 rtx link;
01066 #endif
01067 int all_adjacent = (succ ? (next_active_insn (insn) == succ
01068 && next_active_insn (succ) == i3)
01069 : next_active_insn (insn) == i3);
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 if (GET_CODE (PATTERN (insn)) == SET)
01087 set = PATTERN (insn);
01088 else if (GET_CODE (PATTERN (insn)) == PARALLEL
01089 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
01090 {
01091 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
01092 {
01093 rtx elt = XVECEXP (PATTERN (insn), 0, i);
01094 rtx note;
01095
01096 switch (GET_CODE (elt))
01097 {
01098
01099
01100 case USE:
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114 if (REG_P (XEXP (elt, 0))
01115 && GET_CODE (PATTERN (i3)) == PARALLEL)
01116 {
01117 rtx i3pat = PATTERN (i3);
01118 int i = XVECLEN (i3pat, 0) - 1;
01119 unsigned int regno = REGNO (XEXP (elt, 0));
01120
01121 do
01122 {
01123 rtx i3elt = XVECEXP (i3pat, 0, i);
01124
01125 if (GET_CODE (i3elt) == USE
01126 && REG_P (XEXP (i3elt, 0))
01127 && (REGNO (XEXP (i3elt, 0)) == regno
01128 ? reg_set_between_p (XEXP (elt, 0),
01129 PREV_INSN (insn), i3)
01130 : regno >= FIRST_PSEUDO_REGISTER))
01131 return 0;
01132 }
01133 while (--i >= 0);
01134 }
01135 break;
01136
01137
01138 case CLOBBER:
01139 break;
01140
01141 case SET:
01142
01143
01144 if (find_reg_note (insn, REG_UNUSED, SET_DEST (elt))
01145 && (!(note = find_reg_note (insn, REG_EH_REGION, NULL_RTX))
01146 || INTVAL (XEXP (note, 0)) <= 0)
01147 && ! side_effects_p (elt))
01148 break;
01149
01150
01151
01152 if (set)
01153 return 0;
01154
01155 set = elt;
01156 break;
01157
01158 default:
01159
01160 return 0;
01161 }
01162 }
01163
01164 if (set == 0
01165
01166
01167 || GET_CODE (SET_SRC (set)) == ASM_OPERANDS)
01168 return 0;
01169 }
01170 else
01171 return 0;
01172
01173 if (set == 0)
01174 return 0;
01175
01176 set = expand_field_assignment (set);
01177 src = SET_SRC (set), dest = SET_DEST (set);
01178
01179
01180 if (dest == stack_pointer_rtx
01181
01182
01183 || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
01184
01185 || GET_CODE (src) == ASM_OPERANDS
01186
01187 || GET_CODE (src) == CALL
01188
01189 || (CALL_P (i3)
01190 && (find_reg_fusage (i3, USE, dest)
01191 || (REG_P (dest)
01192 && REGNO (dest) < FIRST_PSEUDO_REGISTER
01193 && global_regs[REGNO (dest)])))
01194
01195 || FIND_REG_INC_NOTE (i3, dest)
01196 || (succ && FIND_REG_INC_NOTE (succ, dest))
01197
01198 || (JUMP_P (i3) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX))
01199 #if 0
01200
01201
01202
01203
01204
01205 || find_reg_note (insn, REG_RETVAL, NULL_RTX)
01206 #endif
01207
01208 || (succ && ! all_adjacent
01209 && reg_used_between_p (dest, succ, i3))
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 || (! all_adjacent
01220 && (((!MEM_P (src)
01221 || ! find_reg_note (insn, REG_EQUIV, src))
01222 && use_crosses_set_p (src, INSN_CUID (insn)))
01223 || (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))
01224 || GET_CODE (src) == UNSPEC_VOLATILE))
01225
01226
01227 || find_reg_note (i3, REG_NO_CONFLICT, dest)
01228 || (succ && find_reg_note (succ, REG_NO_CONFLICT, dest))
01229
01230
01231
01232
01233
01234 || (INSN_CUID (insn) < last_call_cuid && ! CONSTANT_P (src)))
01235 return 0;
01236
01237
01238 if (REG_P (dest))
01239 {
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249 if (REG_P (src)
01250 && ((REGNO (dest) < FIRST_PSEUDO_REGISTER
01251 && ! HARD_REGNO_MODE_OK (REGNO (dest), GET_MODE (dest)))
01252
01253
01254
01255
01256
01257
01258
01259 || (REGNO (src) < FIRST_PSEUDO_REGISTER
01260 && ! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)))))
01261 return 0;
01262 }
01263 else if (GET_CODE (dest) != CC0)
01264 return 0;
01265
01266
01267 if (GET_CODE (PATTERN (i3)) == PARALLEL)
01268 for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--)
01269 if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER)
01270 {
01271
01272
01273 rtx reg = XEXP (XVECEXP (PATTERN (i3), 0, i), 0);
01274 if (rtx_equal_p (reg, dest))
01275 return 0;
01276
01277
01278
01279
01280
01281
01282
01283
01284 if (!REG_P (reg)
01285 || REGNO (reg) >= FIRST_PSEUDO_REGISTER
01286 || !fixed_regs[REGNO (reg)])
01287 if (reg_overlap_mentioned_p (reg, src))
01288 return 0;
01289 }
01290
01291
01292
01293
01294 if (GET_CODE (src) == ASM_OPERANDS || volatile_refs_p (src))
01295 {
01296
01297 if (succ != 0 && volatile_refs_p (PATTERN (succ)))
01298 return 0;
01299
01300 for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
01301 if (INSN_P (p) && p != succ && volatile_refs_p (PATTERN (p)))
01302 return 0;
01303 }
01304
01305
01306
01307
01308 if (GET_CODE (src) == ASM_OPERANDS
01309 && REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER)
01310 return 0;
01311
01312
01313
01314
01315 for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
01316 if (INSN_P (p) && p != succ && volatile_insn_p (PATTERN (p)))
01317 return 0;
01318
01319
01320
01321
01322
01323
01324
01325 #ifdef AUTO_INC_DEC
01326 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
01327 if (REG_NOTE_KIND (link) == REG_INC
01328 && (JUMP_P (i3)
01329 || reg_used_between_p (XEXP (link, 0), insn, i3)
01330 || (pred != NULL_RTX
01331 && reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (pred)))
01332 || (succ != NULL_RTX
01333 && reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (succ)))
01334 || reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i3))))
01335 return 0;
01336 #endif
01337
01338 #ifdef HAVE_cc0
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348 p = prev_nonnote_insn (insn);
01349 if (p && p != pred && NONJUMP_INSN_P (p) && sets_cc0_p (PATTERN (p))
01350 && ! all_adjacent)
01351 return 0;
01352 #endif
01353
01354
01355
01356
01357 *pdest = dest;
01358 *psrc = src;
01359
01360 return 1;
01361 }
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 static int
01401 combinable_i3pat (rtx i3, rtx *loc, rtx i2dest, rtx i1dest,
01402 int i1_not_in_src, rtx *pi3dest_killed)
01403 {
01404 rtx x = *loc;
01405
01406 if (GET_CODE (x) == SET)
01407 {
01408 rtx set = x ;
01409 rtx dest = SET_DEST (set);
01410 rtx src = SET_SRC (set);
01411 rtx inner_dest = dest;
01412
01413 while (GET_CODE (inner_dest) == STRICT_LOW_PART
01414 || GET_CODE (inner_dest) == SUBREG
01415 || GET_CODE (inner_dest) == ZERO_EXTRACT)
01416 inner_dest = XEXP (inner_dest, 0);
01417
01418
01419
01420
01421
01422 if ((inner_dest != dest &&
01423 (!MEM_P (inner_dest)
01424 || rtx_equal_p (i2dest, inner_dest)
01425 || (i1dest && rtx_equal_p (i1dest, inner_dest)))
01426 && (reg_overlap_mentioned_p (i2dest, inner_dest)
01427 || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest))))
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439 || (REG_P (inner_dest)
01440 && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
01441 && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),
01442 GET_MODE (inner_dest))))
01443 || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)))
01444 return 0;
01445
01446
01447
01448
01449
01450
01451 if (pi3dest_killed && REG_P (dest)
01452 && reg_referenced_p (dest, PATTERN (i3))
01453 && REGNO (dest) != FRAME_POINTER_REGNUM
01454 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
01455 && REGNO (dest) != HARD_FRAME_POINTER_REGNUM
01456 #endif
01457 #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
01458 && (REGNO (dest) != ARG_POINTER_REGNUM
01459 || ! fixed_regs [REGNO (dest)])
01460 #endif
01461 && REGNO (dest) != STACK_POINTER_REGNUM)
01462 {
01463 if (*pi3dest_killed)
01464 return 0;
01465
01466 *pi3dest_killed = dest;
01467 }
01468 }
01469
01470 else if (GET_CODE (x) == PARALLEL)
01471 {
01472 int i;
01473
01474 for (i = 0; i < XVECLEN (x, 0); i++)
01475 if (! combinable_i3pat (i3, &XVECEXP (x, 0, i), i2dest, i1dest,
01476 i1_not_in_src, pi3dest_killed))
01477 return 0;
01478 }
01479
01480 return 1;
01481 }
01482
01483
01484
01485
01486 static int
01487 contains_muldiv (rtx x)
01488 {
01489 switch (GET_CODE (x))
01490 {
01491 case MOD: case DIV: case UMOD: case UDIV:
01492 return 1;
01493
01494 case MULT:
01495 return ! (GET_CODE (XEXP (x, 1)) == CONST_INT
01496 && exact_log2 (INTVAL (XEXP (x, 1))) >= 0);
01497 default:
01498 if (BINARY_P (x))
01499 return contains_muldiv (XEXP (x, 0))
01500 || contains_muldiv (XEXP (x, 1));
01501
01502 if (UNARY_P (x))
01503 return contains_muldiv (XEXP (x, 0));
01504
01505 return 0;
01506 }
01507 }
01508
01509
01510
01511
01512
01513 static int
01514 cant_combine_insn_p (rtx insn)
01515 {
01516 rtx set;
01517 rtx src, dest;
01518
01519
01520
01521
01522 if (! INSN_P (insn))
01523 return 1;
01524
01525
01526
01527
01528
01529
01530
01531
01532 set = single_set (insn);
01533 if (! set)
01534 return 0;
01535 src = SET_SRC (set);
01536 dest = SET_DEST (set);
01537 if (GET_CODE (src) == SUBREG)
01538 src = SUBREG_REG (src);
01539 if (GET_CODE (dest) == SUBREG)
01540 dest = SUBREG_REG (dest);
01541 if (REG_P (src) && REG_P (dest)
01542 && ((REGNO (src) < FIRST_PSEUDO_REGISTER
01543 && ! fixed_regs[REGNO (src)]
01544 && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
01545 || (REGNO (dest) < FIRST_PSEUDO_REGISTER
01546 && ! fixed_regs[REGNO (dest)]
01547 && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
01548 return 1;
01549
01550 return 0;
01551 }
01552
01553
01554
01555
01556
01557
01558 static void
01559 adjust_for_new_dest (rtx insn)
01560 {
01561 rtx *loc;
01562
01563
01564 loc = ®_NOTES (insn);
01565 while (*loc)
01566 {
01567 enum reg_note kind = REG_NOTE_KIND (*loc);
01568 if (kind == REG_EQUAL || kind == REG_EQUIV)
01569 *loc = XEXP (*loc, 1);
01570 else
01571 loc = &XEXP (*loc, 1);
01572 }
01573
01574
01575
01576
01577 distribute_links (gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX));
01578 }
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596 static rtx
01597 try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
01598 {
01599
01600 rtx newpat, newi2pat = 0;
01601 int substed_i2 = 0, substed_i1 = 0;
01602
01603 int added_sets_1, added_sets_2;
01604
01605 int total_sets;
01606
01607 int i2_is_used;
01608
01609 int insn_code_number, i2_code_number = 0, other_code_number = 0;
01610
01611
01612
01613 rtx i3dest_killed = 0;
01614
01615 rtx i2dest, i2src, i1dest = 0, i1src = 0;
01616
01617 rtx i2pat;
01618
01619 int i2dest_in_i2src = 0, i1dest_in_i1src = 0, i2dest_in_i1src = 0;
01620 int i1_feeds_i3 = 0;
01621
01622 rtx new_i3_notes, new_i2_notes;
01623
01624 int i3_subst_into_i2 = 0;
01625
01626 int have_mult = 0;
01627 int swap_i2i3 = 0;
01628
01629 int maxreg;
01630 rtx temp;
01631 rtx link;
01632 int i;
01633
01634
01635
01636 if (cant_combine_insn_p (i3)
01637 || cant_combine_insn_p (i2)
01638 || (i1 && cant_combine_insn_p (i1))
01639
01640
01641
01642 #if 0
01643
01644
01645 || find_reg_note (i3, REG_LIBCALL, NULL_RTX)
01646 #endif
01647 )
01648 return 0;
01649
01650 combine_attempts++;
01651 undobuf.other_insn = 0;
01652
01653
01654 CLEAR_HARD_REG_SET (newpat_used_regs);
01655
01656
01657
01658 if (i1 && INSN_CUID (i1) > INSN_CUID (i2))
01659 temp = i1, i1 = i2, i2 = temp;
01660
01661 added_links_insn = 0;
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 if (i1 == 0 && NONJUMP_INSN_P (i3) && GET_CODE (PATTERN (i3)) == SET
01680 && REG_P (SET_SRC (PATTERN (i3)))
01681 && REGNO (SET_SRC (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER
01682 && find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3)))
01683 && GET_CODE (PATTERN (i2)) == PARALLEL
01684 && ! side_effects_p (SET_DEST (PATTERN (i3)))
01685
01686
01687
01688
01689 && GET_CODE (SET_DEST (PATTERN (i3))) != ZERO_EXTRACT
01690 && GET_CODE (SET_DEST (PATTERN (i3))) != STRICT_LOW_PART
01691 && ! reg_overlap_mentioned_p (SET_SRC (PATTERN (i3)),
01692 SET_DEST (PATTERN (i3)))
01693 && next_real_insn (i2) == i3)
01694 {
01695 rtx p2 = PATTERN (i2);
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707 for (i = 0; i < XVECLEN (p2, 0); i++)
01708 if ((GET_CODE (XVECEXP (p2, 0, i)) == SET
01709 || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER)
01710 && reg_overlap_mentioned_p (SET_DEST (PATTERN (i3)),
01711 SET_DEST (XVECEXP (p2, 0, i))))
01712 break;
01713
01714 if (i == XVECLEN (p2, 0))
01715 for (i = 0; i < XVECLEN (p2, 0); i++)
01716 if ((GET_CODE (XVECEXP (p2, 0, i)) == SET
01717 || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER)
01718 && SET_DEST (XVECEXP (p2, 0, i)) == SET_SRC (PATTERN (i3)))
01719 {
01720 combine_merges++;
01721
01722 subst_insn = i3;
01723 subst_low_cuid = INSN_CUID (i2);
01724
01725 added_sets_2 = added_sets_1 = 0;
01726 i2dest = SET_SRC (PATTERN (i3));
01727
01728
01729
01730
01731 SUBST (SET_DEST (XVECEXP (p2, 0, i)),
01732 SET_DEST (PATTERN (i3)));
01733
01734 newpat = p2;
01735 i3_subst_into_i2 = 1;
01736 goto validate_replacement;
01737 }
01738 }
01739
01740
01741
01742
01743 if (i1 == 0
01744 && (temp = single_set (i2)) != 0
01745 && (GET_CODE (SET_SRC (temp)) == CONST_INT
01746 || GET_CODE (SET_SRC (temp)) == CONST_DOUBLE)
01747 && REG_P (SET_DEST (temp))
01748 && GET_MODE_CLASS (GET_MODE (SET_DEST (temp))) == MODE_INT
01749 && GET_MODE_SIZE (GET_MODE (SET_DEST (temp))) == 2 * UNITS_PER_WORD
01750 && GET_CODE (PATTERN (i3)) == SET
01751 && GET_CODE (SET_DEST (PATTERN (i3))) == SUBREG
01752 && SUBREG_REG (SET_DEST (PATTERN (i3))) == SET_DEST (temp)
01753 && GET_MODE_CLASS (GET_MODE (SET_DEST (PATTERN (i3)))) == MODE_INT
01754 && GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (i3)))) == UNITS_PER_WORD
01755 && GET_CODE (SET_SRC (PATTERN (i3))) == CONST_INT)
01756 {
01757 HOST_WIDE_INT lo, hi;
01758
01759 if (GET_CODE (SET_SRC (temp)) == CONST_INT)
01760 lo = INTVAL (SET_SRC (temp)), hi = lo < 0 ? -1 : 0;
01761 else
01762 {
01763 lo = CONST_DOUBLE_LOW (SET_SRC (temp));
01764 hi = CONST_DOUBLE_HIGH (SET_SRC (temp));
01765 }
01766
01767 if (subreg_lowpart_p (SET_DEST (PATTERN (i3))))
01768 {
01769
01770
01771 gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD);
01772
01773 lo &= ~(UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1);
01774 lo |= (INTVAL (SET_SRC (PATTERN (i3)))
01775 & (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
01776 }
01777 else if (HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
01778 hi = INTVAL (SET_SRC (PATTERN (i3)));
01779 else if (HOST_BITS_PER_WIDE_INT >= 2 * BITS_PER_WORD)
01780 {
01781 int sign = -(int) ((unsigned HOST_WIDE_INT) lo
01782 >> (HOST_BITS_PER_WIDE_INT - 1));
01783
01784 lo &= ~ (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD
01785 (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
01786 lo |= (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD
01787 (INTVAL (SET_SRC (PATTERN (i3)))));
01788 if (hi == sign)
01789 hi = lo < 0 ? -1 : 0;
01790 }
01791 else
01792
01793
01794 gcc_unreachable ();
01795
01796 combine_merges++;
01797 subst_insn = i3;
01798 subst_low_cuid = INSN_CUID (i2);
01799 added_sets_2 = added_sets_1 = 0;
01800 i2dest = SET_DEST (temp);
01801
01802 SUBST (SET_SRC (temp),
01803 immed_double_const (lo, hi, GET_MODE (SET_DEST (temp))));
01804
01805 newpat = PATTERN (i2);
01806 goto validate_replacement;
01807 }
01808
01809 #ifndef HAVE_cc0
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823 if (i1 == 0 && GET_CODE (PATTERN (i2)) == PARALLEL
01824 && XVECLEN (PATTERN (i2), 0) >= 2
01825 && GET_CODE (XVECEXP (PATTERN (i2), 0, 0)) == SET
01826 && (GET_MODE_CLASS (GET_MODE (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))))
01827 == MODE_CC)
01828 && GET_CODE (SET_SRC (XVECEXP (PATTERN (i2), 0, 0))) == COMPARE
01829 && XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 1) == const0_rtx
01830 && GET_CODE (XVECEXP (PATTERN (i2), 0, 1)) == SET
01831 && REG_P (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)))
01832 && rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 0),
01833 SET_SRC (XVECEXP (PATTERN (i2), 0, 1))))
01834 {
01835 for (i = XVECLEN (PATTERN (i2), 0) - 1; i >= 2; i--)
01836 if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != CLOBBER)
01837 break;
01838
01839 if (i == 1)
01840 {
01841
01842
01843
01844
01845
01846 i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
01847 BLOCK_FOR_INSN (i2), INSN_LOCATOR (i2),
01848 XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
01849 NULL_RTX);
01850
01851 SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
01852 SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
01853 SET_DEST (PATTERN (i1)));
01854 }
01855 }
01856 #endif
01857
01858
01859 if (! can_combine_p (i2, i3, i1, NULL_RTX, &i2dest, &i2src)
01860 || (i1 && ! can_combine_p (i1, i3, NULL_RTX, i2, &i1dest, &i1src)))
01861 {
01862 undo_all ();
01863 return 0;
01864 }
01865
01866
01867
01868 i2dest_in_i2src = reg_overlap_mentioned_p (i2dest, i2src);
01869 i1dest_in_i1src = i1 && reg_overlap_mentioned_p (i1dest, i1src);
01870 i2dest_in_i1src = i1 && reg_overlap_mentioned_p (i2dest, i1src);
01871
01872
01873
01874 i1_feeds_i3 = i1 && ! reg_overlap_mentioned_p (i1dest, i2src);
01875
01876
01877 if (! combinable_i3pat (i3, &PATTERN (i3), i2dest, i1dest,
01878 i1 && i2dest_in_i1src && i1_feeds_i3,
01879 &i3dest_killed))
01880 {
01881 undo_all ();
01882 return 0;
01883 }
01884
01885
01886
01887
01888 if (GET_CODE (i2src) == MULT
01889 || (i1 != 0 && GET_CODE (i1src) == MULT)
01890 || (GET_CODE (PATTERN (i3)) == SET
01891 && GET_CODE (SET_SRC (PATTERN (i3))) == MULT))
01892 have_mult = 1;
01893
01894
01895
01896
01897
01898
01899
01900
01901 #if 0
01902 if (!(GET_CODE (PATTERN (i3)) == SET
01903 && REG_P (SET_SRC (PATTERN (i3)))
01904 && MEM_P (SET_DEST (PATTERN (i3)))
01905 && (GET_CODE (XEXP (SET_DEST (PATTERN (i3)), 0)) == POST_INC
01906 || GET_CODE (XEXP (SET_DEST (PATTERN (i3)), 0)) == POST_DEC)))
01907
01908 #endif
01909 #ifdef AUTO_INC_DEC
01910 for (link = REG_NOTES (i3); link; link = XEXP (link, 1))
01911 if (REG_NOTE_KIND (link) == REG_INC
01912 && (reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i2))
01913 || (i1 != 0
01914 && reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i1)))))
01915 {
01916 undo_all ();
01917 return 0;
01918 }
01919 #endif
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932 added_sets_2 = ! dead_or_set_p (i3, i2dest);
01933
01934 added_sets_1
01935 = i1 && ! (i1_feeds_i3 ? dead_or_set_p (i3, i1dest)
01936 : (dead_or_set_p (i3, i1dest) || dead_or_set_p (i2, i1dest)));
01937
01938
01939
01940
01941
01942
01943
01944
01945 i2pat = (GET_CODE (PATTERN (i2)) == PARALLEL
01946 ? gen_rtx_SET (VOIDmode, i2dest, i2src)
01947 : PATTERN (i2));
01948
01949 if (added_sets_2)
01950 i2pat = copy_rtx (i2pat);
01951
01952 combine_merges++;
01953
01954
01955
01956 maxreg = max_reg_num ();
01957
01958 subst_insn = i3;
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974 if (flag_expensive_optimizations)
01975 {
01976
01977 if (i1)
01978 {
01979 subst_low_cuid = INSN_CUID (i1);
01980 i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0);
01981 }
01982 else
01983 {
01984 subst_low_cuid = INSN_CUID (i2);
01985 i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0);
01986 }
01987 }
01988
01989 #ifndef HAVE_cc0
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001 if (i1 == 0 && added_sets_2 && GET_CODE (PATTERN (i3)) == SET
02002 && GET_CODE (SET_SRC (PATTERN (i3))) == COMPARE
02003 && XEXP (SET_SRC (PATTERN (i3)), 1) == const0_rtx
02004 && rtx_equal_p (XEXP (SET_SRC (PATTERN (i3)), 0), i2dest))
02005 {
02006 #ifdef SELECT_CC_MODE
02007 rtx *cc_use;
02008 enum machine_mode compare_mode;
02009 #endif
02010
02011 newpat = PATTERN (i3);
02012 SUBST (XEXP (SET_SRC (newpat), 0), i2src);
02013
02014 i2_is_used = 1;
02015
02016 #ifdef SELECT_CC_MODE
02017
02018
02019
02020
02021
02022 if (undobuf.other_insn == 0
02023 && (cc_use = find_single_use (SET_DEST (newpat), i3,
02024 &undobuf.other_insn))
02025 && ((compare_mode = SELECT_CC_MODE (GET_CODE (*cc_use),
02026 i2src, const0_rtx))
02027 != GET_MODE (SET_DEST (newpat))))
02028 {
02029 unsigned int regno = REGNO (SET_DEST (newpat));
02030 rtx new_dest = gen_rtx_REG (compare_mode, regno);
02031
02032 if (regno < FIRST_PSEUDO_REGISTER
02033 || (REG_N_SETS (regno) == 1 && ! added_sets_2
02034 && ! REG_USERVAR_P (SET_DEST (newpat))))
02035 {
02036 if (regno >= FIRST_PSEUDO_REGISTER)
02037 SUBST (regno_reg_rtx[regno], new_dest);
02038
02039 SUBST (SET_DEST (newpat), new_dest);
02040 SUBST (XEXP (*cc_use, 0), new_dest);
02041 SUBST (SET_SRC (newpat),
02042 gen_rtx_COMPARE (compare_mode, i2src, const0_rtx));
02043 }
02044 else
02045 undobuf.other_insn = 0;
02046 }
02047 #endif
02048 }
02049 else
02050 #endif
02051 {
02052 n_occurrences = 0;
02053
02054
02055
02056
02057
02058 subst_low_cuid = INSN_CUID (i2);
02059 newpat = subst (PATTERN (i3), i2dest, i2src, 0,
02060 ! i1_feeds_i3 && i1dest_in_i1src);
02061 substed_i2 = 1;
02062
02063
02064 i2_is_used = n_occurrences;
02065 }
02066
02067
02068
02069
02070 if (i1 && GET_CODE (newpat) != CLOBBER)
02071 {
02072
02073
02074
02075
02076 if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX,
02077 0, (rtx*) 0))
02078 {
02079 undo_all ();
02080 return 0;
02081 }
02082
02083 n_occurrences = 0;
02084 subst_low_cuid = INSN_CUID (i1);
02085 newpat = subst (newpat, i1dest, i1src, 0, 0);
02086 substed_i1 = 1;
02087 }
02088
02089
02090
02091 if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0
02092 && i2_is_used + added_sets_2 > 1)
02093 || (i1 != 0 && FIND_REG_INC_NOTE (i1, NULL_RTX) != 0
02094 && (n_occurrences + added_sets_1 + (added_sets_2 && ! i1_feeds_i3)
02095 > 1))
02096
02097
02098 || max_reg_num () != maxreg
02099
02100 || GET_CODE (newpat) == CLOBBER
02101
02102
02103 || (GET_CODE (newpat) == SET && GET_CODE (SET_SRC (newpat)) == MULT
02104 && ! have_mult))
02105 {
02106 undo_all ();
02107 return 0;
02108 }
02109
02110
02111
02112
02113
02114
02115 if (added_sets_1 || added_sets_2)
02116 {
02117 combine_extras++;
02118
02119 if (GET_CODE (newpat) == PARALLEL)
02120 {
02121 rtvec old = XVEC (newpat, 0);
02122 total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2;
02123 newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets));
02124 memcpy (XVEC (newpat, 0)->elem, &old->elem[0],
02125 sizeof (old->elem[0]) * old->num_elem);
02126 }
02127 else
02128 {
02129 rtx old = newpat;
02130 total_sets = 1 + added_sets_1 + added_sets_2;
02131 newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets));
02132 XVECEXP (newpat, 0, 0) = old;
02133 }
02134
02135 if (added_sets_1)
02136 XVECEXP (newpat, 0, --total_sets)
02137 = (GET_CODE (PATTERN (i1)) == PARALLEL
02138 ? gen_rtx_SET (VOIDmode, i1dest, i1src) : PATTERN (i1));
02139
02140 if (added_sets_2)
02141 {
02142
02143
02144
02145 if (i1 == 0)
02146 XVECEXP (newpat, 0, --total_sets) = i2pat;
02147 else
02148
02149 XVECEXP (newpat, 0, --total_sets)
02150 = subst (i2pat, i1dest, i1src, 0, 0);
02151 }
02152 }
02153
02154
02155
02156 validate_replacement:
02157
02158
02159 mark_used_regs_combine (newpat);
02160
02161
02162 insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182 if (insn_code_number < 0
02183 && !(added_sets_2 && i1 == 0)
02184 && GET_CODE (newpat) == PARALLEL
02185 && XVECLEN (newpat, 0) == 2
02186 && GET_CODE (XVECEXP (newpat, 0, 0)) == SET
02187 && GET_CODE (XVECEXP (newpat, 0, 1)) == SET
02188 && asm_noperands (newpat) < 0)
02189 {
02190 rtx set0 = XVECEXP (newpat, 0, 0);
02191 rtx set1 = XVECEXP (newpat, 0, 1);
02192 rtx note;
02193
02194 if (((REG_P (SET_DEST (set1))
02195 && find_reg_note (i3, REG_UNUSED, SET_DEST (set1)))
02196 || (GET_CODE (SET_DEST (set1)) == SUBREG
02197 && find_reg_note (i3, REG_UNUSED, SUBREG_REG (SET_DEST (set1)))))
02198 && (!(note = find_reg_note (i3, REG_EH_REGION, NULL_RTX))
02199 || INTVAL (XEXP (note, 0)) <= 0)
02200 && ! side_effects_p (SET_SRC (set1)))
02201 {
02202 newpat = set0;
02203 insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
02204 }
02205
02206 else if (((REG_P (SET_DEST (set0))
02207 && find_reg_note (i3, REG_UNUSED, SET_DEST (set0)))
02208 || (GET_CODE (SET_DEST (set0)) == SUBREG
02209 && find_reg_note (i3, REG_UNUSED,
02210 SUBREG_REG (SET_DEST (set0)))))
02211 && (!(note = find_reg_note (i3, REG_EH_REGION, NULL_RTX))
02212 || INTVAL (XEXP (note, 0)) <= 0)
02213 && ! side_effects_p (SET_SRC (set0)))
02214 {
02215 newpat = set1;
02216 insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
02217
02218 if (insn_code_number >= 0)
02219 {
02220
02221
02222
02223
02224 PATTERN (i3) = newpat;
02225 adjust_for_new_dest (i3);
02226 }
02227 }
02228 }
02229
02230
02231
02232
02233
02234
02235
02236 if (i1 && insn_code_number < 0 && GET_CODE (newpat) == SET
02237 && asm_noperands (newpat) < 0)
02238 {
02239 rtx m_split, *split;
02240 rtx ni2dest = i2dest;
02241
02242
02243
02244
02245
02246 m_split = split_insns (newpat, i3);
02247
02248
02249
02250
02251
02252
02253
02254
02255 if (m_split == 0 && ! reg_overlap_mentioned_p (ni2dest, newpat))
02256 {
02257
02258
02259 if (GET_MODE (SET_DEST (newpat)) != GET_MODE (i2dest)
02260 && GET_MODE (SET_DEST (newpat)) != VOIDmode
02261 && REG_P (i2dest)
02262 && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER
02263 || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2
02264 && ! REG_USERVAR_P (i2dest))))
02265 ni2dest = gen_rtx_REG (GET_MODE (SET_DEST (newpat)),
02266 REGNO (i2dest));
02267
02268 m_split = split_insns (gen_rtx_PARALLEL
02269 (VOIDmode,
02270 gen_rtvec (2, newpat,
02271 gen_rtx_CLOBBER (VOIDmode,
02272 ni2dest))),
02273 i3);
02274
02275
02276 if (! m_split && ni2dest != i2dest)
02277 {
02278 ni2dest = i2dest;
02279 m_split = split_insns (gen_rtx_PARALLEL
02280 (VOIDmode,
02281 gen_rtvec (2, newpat,
02282 gen_rtx_CLOBBER (VOIDmode,
02283 i2dest))),
02284 i3);
02285 }
02286 }
02287
02288 if (m_split && NEXT_INSN (m_split) == NULL_RTX)
02289 {
02290 m_split = PATTERN (m_split);
02291 insn_code_number = recog_for_combine (&m_split, i3, &new_i3_notes);
02292 if (insn_code_number >= 0)
02293 newpat = m_split;
02294 }
02295 else if (m_split && NEXT_INSN (NEXT_INSN (m_split)) == NULL_RTX
02296 && (next_real_insn (i2) == i3
02297 || ! use_crosses_set_p (PATTERN (m_split), INSN_CUID (i2))))
02298 {
02299 rtx i2set, i3set;
02300 rtx newi3pat = PATTERN (NEXT_INSN (m_split));
02301 newi2pat = PATTERN (m_split);
02302
02303 i3set = single_set (NEXT_INSN (m_split));
02304 i2set = single_set (m_split);
02305
02306
02307
02308
02309
02310 if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
02311 SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
02312
02313 i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
02314
02315
02316
02317
02318
02319 if (i2_code_number >= 0 && i2set && i3set
02320 && (next_real_insn (i2) == i3
02321 || ! reg_used_between_p (SET_DEST (i2set), i2, i3)))
02322 insn_code_number = recog_for_combine (&newi3pat, i3,
02323 &new_i3_notes);
02324 if (insn_code_number >= 0)
02325 newpat = newi3pat;
02326
02327
02328
02329
02330 if (insn_code_number >= 0)
02331 {
02332 rtx new_i3_dest = SET_DEST (i3set);
02333 rtx new_i2_dest = SET_DEST (i2set);
02334
02335 while (GET_CODE (new_i3_dest) == ZERO_EXTRACT
02336 || GET_CODE (new_i3_dest) == STRICT_LOW_PART
02337 || GET_CODE (new_i3_dest) == SUBREG)
02338 new_i3_dest = XEXP (new_i3_dest, 0);
02339
02340 while (GET_CODE (new_i2_dest) == ZERO_EXTRACT
02341 || GET_CODE (new_i2_dest) == STRICT_LOW_PART
02342 || GET_CODE (new_i2_dest) == SUBREG)
02343 new_i2_dest = XEXP (new_i2_dest, 0);
02344
02345 if (REG_P (new_i3_dest)
02346 && REG_P (new_i2_dest)
02347 && REGNO (new_i3_dest) == REGNO (new_i2_dest))
02348 REG_N_SETS (REGNO (new_i2_dest))++;
02349 }
02350 }
02351
02352
02353
02354
02355 if (insn_code_number < 0 && (split = find_split_point (&newpat, i3)) != 0
02356 #ifdef HAVE_cc0
02357 && REG_P (i2dest)
02358 #endif
02359
02360
02361 && (GET_MODE (*split) == GET_MODE (i2dest)
02362 || GET_MODE (*split) == VOIDmode
02363 || REGNO (i2dest) < FIRST_PSEUDO_REGISTER
02364 || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2
02365 && ! REG_USERVAR_P (i2dest)))
02366 && (next_real_insn (i2) == i3
02367 || ! use_crosses_set_p (*split, INSN_CUID (i2)))
02368
02369
02370 && ! reg_referenced_p (i2dest, newpat))
02371 {
02372 rtx newdest = i2dest;
02373 enum rtx_code split_code = GET_CODE (*split);
02374 enum machine_mode split_mode = GET_MODE (*split);
02375
02376
02377
02378 if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode)
02379 {
02380 newdest = gen_rtx_REG (split_mode, REGNO (i2dest));
02381
02382 if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
02383 SUBST (regno_reg_rtx[REGNO (i2dest)], newdest);
02384 }
02385
02386
02387
02388
02389 if (split_code == MULT
02390 && GET_CODE (XEXP (*split, 1)) == CONST_INT
02391 && INTVAL (XEXP (*split, 1)) > 0
02392 && (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0)
02393 {
02394 SUBST (*split, gen_rtx_ASHIFT (split_mode,
02395 XEXP (*split, 0), GEN_INT (i)));
02396
02397
02398 split_code = GET_CODE (*split);
02399 }
02400
02401 #ifdef INSN_SCHEDULING
02402
02403
02404 if (split_code == SUBREG && MEM_P (SUBREG_REG (*split)))
02405 {
02406 #ifdef LOAD_EXTEND_OP
02407
02408
02409 if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (*split)))
02410 == SIGN_EXTEND)
02411 SUBST (*split, gen_rtx_SIGN_EXTEND (split_mode,
02412 SUBREG_REG (*split)));
02413 else
02414 #endif
02415 SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
02416 SUBREG_REG (*split)));
02417 }
02418 #endif
02419
02420 newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
02421 SUBST (*split, newdest);
02422 i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
02423
02424
02425
02426 if (GET_CODE (newi2pat) == PARALLEL)
02427 for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--)
02428 if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER)
02429 {
02430 rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
02431 if (reg_overlap_mentioned_p (reg, newpat))
02432 {
02433 undo_all ();
02434 return 0;
02435 }
02436 }
02437
02438
02439
02440 if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
02441 insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
02442 }
02443 }
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460 else if (i1 && insn_code_number < 0 && asm_noperands (newpat) < 0
02461 && GET_CODE (newpat) == PARALLEL
02462 && XVECLEN (newpat, 0) == 2
02463 && GET_CODE (XVECEXP (newpat, 0, 0)) == SET
02464 && GET_CODE (SET_SRC (XVECEXP (newpat, 0, 0))) == SIGN_EXTEND
02465 && (GET_MODE (SET_DEST (XVECEXP (newpat, 0, 0)))
02466 == GET_MODE (SET_SRC (XVECEXP (newpat, 0, 0))))
02467 && GET_CODE (XVECEXP (newpat, 0, 1)) == SET
02468 && rtx_equal_p (SET_SRC (XVECEXP (newpat, 0, 1)),
02469 XEXP (SET_SRC (XVECEXP (newpat, 0, 0)), 0))
02470 && ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
02471 INSN_CUID (i2))
02472 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT
02473 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
02474 && ! (temp = SET_DEST (XVECEXP (newpat, 0, 1)),
02475 (REG_P (temp)
02476 && reg_stat[REGNO (temp)].nonzero_bits != 0
02477 && GET_MODE_BITSIZE (GET_MODE (temp)) < BITS_PER_WORD
02478 && GET_MODE_BITSIZE (GET_MODE (temp)) < HOST_BITS_PER_INT
02479 && (reg_stat[REGNO (temp)].nonzero_bits
02480 != GET_MODE_MASK (word_mode))))
02481 && ! (GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) == SUBREG
02482 && (temp = SUBREG_REG (SET_DEST (XVECEXP (newpat, 0, 1))),
02483 (REG_P (temp)
02484 && reg_stat[REGNO (temp)].nonzero_bits != 0
02485 && GET_MODE_BITSIZE (GET_MODE (temp)) < BITS_PER_WORD
02486 && GET_MODE_BITSIZE (GET_MODE (temp)) < HOST_BITS_PER_INT
02487 && (reg_stat[REGNO (temp)].nonzero_bits
02488 != GET_MODE_MASK (word_mode)))))
02489 && ! reg_overlap_mentioned_p (SET_DEST (XVECEXP (newpat, 0, 1)),
02490 SET_SRC (XVECEXP (newpat, 0, 1)))
02491 && ! find_reg_note (i3, REG_UNUSED,
02492 SET_DEST (XVECEXP (newpat, 0, 0))))
02493 {
02494 rtx ni2dest;
02495
02496 newi2pat = XVECEXP (newpat, 0, 0);
02497 ni2dest = SET_DEST (XVECEXP (newpat, 0, 0));
02498 newpat = XVECEXP (newpat, 0, 1);
02499 SUBST (SET_SRC (newpat),
02500 gen_lowpart (GET_MODE (SET_SRC (newpat)), ni2dest));
02501 i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
02502
02503 if (i2_code_number >= 0)
02504 insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
02505
02506 if (insn_code_number >= 0)
02507 swap_i2i3 = 1;
02508 }
02509
02510
02511
02512
02513
02514
02515 else if (i1 && insn_code_number < 0 && asm_noperands (newpat) < 0
02516 && GET_CODE (newpat) == PARALLEL
02517 && XVECLEN (newpat, 0) == 2
02518 && GET_CODE (XVECEXP (newpat, 0, 0)) == SET
02519 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != ZERO_EXTRACT
02520 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != STRICT_LOW_PART
02521 && GET_CODE (XVECEXP (newpat, 0, 1)) == SET
02522 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT
02523 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
02524 && ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
02525 INSN_CUID (i2))
02526
02527 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != USE
02528 && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != USE
02529 && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 1)),
02530 XVECEXP (newpat, 0, 0))
02531 && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0)),
02532 XVECEXP (newpat, 0, 1))
02533 && ! (contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 0)))
02534 && contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1)))))
02535 {
02536
02537
02538
02539 #ifdef HAVE_cc0
02540 if (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0)))
02541 {
02542 newi2pat = XVECEXP (newpat, 0, 0);
02543 newpat = XVECEXP (newpat, 0, 1);
02544 }
02545 else
02546 #endif
02547 {
02548 newi2pat = XVECEXP (newpat, 0, 1);
02549 newpat = XVECEXP (newpat, 0, 0);
02550 }
02551
02552 i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
02553
02554 if (i2_code_number >= 0)
02555 insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
02556 }
02557
02558
02559
02560 if ((insn_code_number < 0
02561
02562 && (! check_asm_operands (newpat) || added_sets_1 || added_sets_2)))
02563 {
02564 undo_all ();
02565 return 0;
02566 }
02567
02568
02569 if (undobuf.other_insn)
02570 {
02571 rtx other_pat = PATTERN (undobuf.other_insn);
02572 rtx new_other_notes;
02573 rtx note, next;
02574
02575 CLEAR_HARD_REG_SET (newpat_used_regs);
02576
02577 other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
02578 &new_other_notes);
02579
02580 if (other_code_number < 0 && ! check_asm_operands (other_pat))
02581 {
02582 undo_all ();
02583 return 0;
02584 }
02585
02586 PATTERN (undobuf.other_insn) = other_pat;
02587
02588
02589
02590
02591 for (note = REG_NOTES (undobuf.other_insn); note; note = next)
02592 {
02593 next = XEXP (note, 1);
02594
02595 if (REG_NOTE_KIND (note) == REG_UNUSED
02596 && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn)))
02597 {
02598 if (REG_P (XEXP (note, 0)))
02599 REG_N_DEATHS (REGNO (XEXP (note, 0)))--;
02600
02601 remove_note (undobuf.other_insn, note);
02602 }
02603 }
02604
02605 for (note = new_other_notes; note; note = XEXP (note, 1))
02606 if (REG_P (XEXP (note, 0)))
02607 REG_N_DEATHS (REGNO (XEXP (note, 0)))++;
02608
02609 distribute_notes (new_other_notes, undobuf.other_insn,
02610 undobuf.other_insn, NULL_RTX);
02611 }
02612 #ifdef HAVE_cc0
02613
02614
02615 {
02616 rtx p = prev_nonnote_insn (i3);
02617 if (p && p != i2 && NONJUMP_INSN_P (p) && newi2pat
02618 && sets_cc0_p (newi2pat))
02619 {
02620 undo_all ();
02621 return 0;
02622 }
02623 }
02624 #endif
02625
02626
02627
02628 if (!combine_validate_cost (i1, i2, i3, newpat, newi2pat))
02629 {
02630 undo_all ();
02631 return 0;
02632 }
02633
02634
02635
02636
02637 if (swap_i2i3)
02638 {
02639 rtx insn;
02640 rtx link;
02641 rtx ni2dest;
02642
02643
02644
02645 PATTERN (i3) = newpat;
02646 adjust_for_new_dest (i3);
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658 if (GET_CODE (newi2pat) == PARALLEL)
02659 ni2dest = SET_DEST (XVECEXP (newi2pat, 0, 0));
02660 else
02661 ni2dest = SET_DEST (newi2pat);
02662
02663 for (insn = NEXT_INSN (i3);
02664 insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
02665 || insn != BB_HEAD (this_basic_block->next_bb));
02666 insn = NEXT_INSN (insn))
02667 {
02668 if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn)))
02669 {
02670 for (link = LOG_LINKS (insn); link;
02671 link = XEXP (link, 1))
02672 if (XEXP (link, 0) == i3)
02673 XEXP (link, 0) = i1;
02674
02675 break;
02676 }
02677 }
02678 }
02679
02680 {
02681 rtx i3notes, i2notes, i1notes = 0;
02682 rtx i3links, i2links, i1links = 0;
02683 rtx midnotes = 0;
02684 unsigned int regno;
02685
02686
02687
02688 i3notes = REG_NOTES (i3), i3links = LOG_LINKS (i3);
02689 i2notes = REG_NOTES (i2), i2links = LOG_LINKS (i2);
02690 if (i1)
02691 i1notes = REG_NOTES (i1), i1links = LOG_LINKS (i1);
02692
02693
02694
02695
02696
02697 reset_used_flags (i3notes);
02698 reset_used_flags (i2notes);
02699 reset_used_flags (i1notes);
02700 reset_used_flags (newpat);
02701 reset_used_flags (newi2pat);
02702 if (undobuf.other_insn)
02703 reset_used_flags (PATTERN (undobuf.other_insn));
02704
02705 i3notes = copy_rtx_if_shared (i3notes);
02706 i2notes = copy_rtx_if_shared (i2notes);
02707 i1notes = copy_rtx_if_shared (i1notes);
02708 newpat = copy_rtx_if_shared (newpat);
02709 newi2pat = copy_rtx_if_shared (newi2pat);
02710 if (undobuf.other_insn)
02711 reset_used_flags (PATTERN (undobuf.other_insn));
02712
02713 INSN_CODE (i3) = insn_code_number;
02714 PATTERN (i3) = newpat;
02715
02716 if (CALL_P (i3) && CALL_INSN_FUNCTION_USAGE (i3))
02717 {
02718 rtx call_usage = CALL_INSN_FUNCTION_USAGE (i3);
02719
02720 reset_used_flags (call_usage);
02721 call_usage = copy_rtx (call_usage);
02722
02723 if (substed_i2)
02724 replace_rtx (call_usage, i2dest, i2src);
02725
02726 if (substed_i1)
02727 replace_rtx (call_usage, i1dest, i1src);
02728
02729 CALL_INSN_FUNCTION_USAGE (i3) = call_usage;
02730 }
02731
02732 if (undobuf.other_insn)
02733 INSN_CODE (undobuf.other_insn) = other_code_number;
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744 if (i3_subst_into_i2)
02745 {
02746 for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
02747 if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != USE
02748 && REG_P (SET_DEST (XVECEXP (PATTERN (i2), 0, i)))
02749 && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
02750 && ! find_reg_note (i2, REG_UNUSED,
02751 SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
02752 for (temp = NEXT_INSN (i2);
02753 temp && (this_basic_block->next_bb == EXIT_BLOCK_PTR
02754 || BB_HEAD (this_basic_block) != temp);
02755 temp = NEXT_INSN (temp))
02756 if (temp != i3 && INSN_P (temp))
02757 for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
02758 if (XEXP (link, 0) == i2)
02759 XEXP (link, 0) = i3;
02760
02761 if (i3notes)
02762 {
02763 rtx link = i3notes;
02764 while (XEXP (link, 1))
02765 link = XEXP (link, 1);
02766 XEXP (link, 1) = i2notes;
02767 }
02768 else
02769 i3notes = i2notes;
02770 i2notes = 0;
02771 }
02772
02773 LOG_LINKS (i3) = 0;
02774 REG_NOTES (i3) = 0;
02775 LOG_LINKS (i2) = 0;
02776 REG_NOTES (i2) = 0;
02777
02778 if (newi2pat)
02779 {
02780 INSN_CODE (i2) = i2_code_number;
02781 PATTERN (i2) = newi2pat;
02782 }
02783 else
02784 SET_INSN_DELETED (i2);
02785
02786 if (i1)
02787 {
02788 LOG_LINKS (i1) = 0;
02789 REG_NOTES (i1) = 0;
02790 SET_INSN_DELETED (i1);
02791 }
02792
02793
02794
02795
02796
02797
02798 if (newi2pat)
02799 {
02800 move_deaths (newi2pat, NULL_RTX, INSN_CUID (i1), i2, &midnotes);
02801 move_deaths (newpat, newi2pat, INSN_CUID (i1), i3, &midnotes);
02802 }
02803 else
02804 move_deaths (newpat, NULL_RTX, i1 ? INSN_CUID (i1) : INSN_CUID (i2),
02805 i3, &midnotes);
02806
02807
02808 if (i3notes)
02809 distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL_RTX);
02810 if (i2notes)
02811 distribute_notes (i2notes, i2, i3, newi2pat ? i2 : NULL_RTX);
02812 if (i1notes)
02813 distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL_RTX);
02814 if (midnotes)
02815 distribute_notes (midnotes, NULL_RTX, i3, newi2pat ? i2 : NULL_RTX);
02816
02817
02818
02819
02820
02821
02822 if (newi2pat && new_i2_notes)
02823 {
02824 for (temp = new_i2_notes; temp; temp = XEXP (temp, 1))
02825 if (REG_P (XEXP (temp, 0)))
02826 REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
02827
02828 distribute_notes (new_i2_notes, i2, i2, NULL_RTX);
02829 }
02830
02831 if (new_i3_notes)
02832 {
02833 for (temp = new_i3_notes; temp; temp = XEXP (temp, 1))
02834 if (REG_P (XEXP (temp, 0)))
02835 REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
02836
02837 distribute_notes (new_i3_notes, i3, i3, NULL_RTX);
02838 }
02839
02840
02841
02842
02843
02844
02845
02846
02847 if (i3dest_killed)
02848 {
02849 if (REG_P (i3dest_killed))
02850 REG_N_DEATHS (REGNO (i3dest_killed))++;
02851
02852 if (newi2pat && reg_set_p (i3dest_killed, newi2pat))
02853 distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed,
02854 NULL_RTX),
02855 NULL_RTX, i2, NULL_RTX);
02856 else
02857 distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed,
02858 NULL_RTX),
02859 NULL_RTX, i3, newi2pat ? i2 : NULL_RTX);
02860 }
02861
02862 if (i2dest_in_i2src)
02863 {
02864 if (REG_P (i2dest))
02865 REG_N_DEATHS (REGNO (i2dest))++;
02866
02867 if (newi2pat && reg_set_p (i2dest, newi2pat))
02868 distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX),
02869 NULL_RTX, i2, NULL_RTX);
02870 else
02871 distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX),
02872 NULL_RTX, i3, newi2pat ? i2 : NULL_RTX);
02873 }
02874
02875 if (i1dest_in_i1src)
02876 {
02877 if (REG_P (i1dest))
02878 REG_N_DEATHS (REGNO (i1dest))++;
02879
02880 if (newi2pat && reg_set_p (i1dest, newi2pat))
02881 distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX),
02882 NULL_RTX, i2, NULL_RTX);
02883 else
02884 distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX),
02885 NULL_RTX, i3, newi2pat ? i2 : NULL_RTX);
02886 }
02887
02888 distribute_links (i3links);
02889 distribute_links (i2links);
02890 distribute_links (i1links);
02891
02892 if (REG_P (i2dest))
02893 {
02894 rtx link;
02895 rtx i2_insn = 0, i2_val = 0, set;
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905 for (link = LOG_LINKS (i3); link; link = XEXP (link, 1))
02906 if ((set = single_set (XEXP (link, 0))) != 0
02907 && rtx_equal_p (i2dest, SET_DEST (set)))
02908 i2_insn = XEXP (link, 0), i2_val = SET_SRC (set);
02909
02910 record_value_for_reg (i2dest, i2_insn, i2_val);
02911
02912
02913
02914 if (! added_sets_2
02915 && (newi2pat == 0 || ! reg_mentioned_p (i2dest, newi2pat))
02916 && ! i2dest_in_i2src)
02917 {
02918 regno = REGNO (i2dest);
02919 REG_N_SETS (regno)--;
02920 }
02921 }
02922
02923 if (i1 && REG_P (i1dest))
02924 {
02925 rtx link;
02926 rtx i1_insn = 0, i1_val = 0, set;
02927
02928 for (link = LOG_LINKS (i3); link; link = XEXP (link, 1))
02929 if ((set = single_set (XEXP (link, 0))) != 0
02930 && rtx_equal_p (i1dest, SET_DEST (set)))
02931 i1_insn = XEXP (link, 0), i1_val = SET_SRC (set);
02932
02933 record_value_for_reg (i1dest, i1_insn, i1_val);
02934
02935 regno = REGNO (i1dest);
02936 if (! added_sets_1 && ! i1dest_in_i1src)
02937 REG_N_SETS (regno)--;
02938 }
02939
02940
02941
02942
02943
02944 if (newi2pat)
02945 note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
02946 note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
02947
02948
02949
02950
02951
02952
02953
02954
02955 if (returnjump_p (i3) || any_uncondjump_p (i3))
02956 {
02957 *new_direct_jump_p = 1;
02958 mark_jump_label (PATTERN (i3), i3, 0);
02959
02960 if ((temp = next_nonnote_insn (i3)) == NULL_RTX
02961 || !BARRIER_P (temp))
02962 emit_barrier_after (i3);
02963 }
02964
02965 if (undobuf.other_insn != NULL_RTX
02966 && (returnjump_p (undobuf.other_insn)
02967 || any_uncondjump_p (undobuf.other_insn)))
02968 {
02969 *new_direct_jump_p = 1;
02970
02971 if ((temp = next_nonnote_insn (undobuf.other_insn)) == NULL_RTX
02972 || !BARRIER_P (temp))
02973 emit_barrier_after (undobuf.other_insn);
02974 }
02975
02976
02977
02978 if (GET_CODE (newpat) == SET
02979 && SET_SRC (newpat) == pc_rtx
02980 && SET_DEST (newpat) == pc_rtx)
02981 *new_direct_jump_p = 1;
02982 }
02983
02984 combine_successes++;
02985 undo_commit ();
02986
02987 if (added_links_insn
02988 && (newi2pat == 0 || INSN_CUID (added_links_insn) < INSN_CUID (i2))
02989 && INSN_CUID (added_links_insn) < INSN_CUID (i3))
02990 return added_links_insn;
02991 else
02992 return newi2pat ? i2 : i3;
02993 }
02994
02995
02996
02997 static void
02998 undo_all (void)
02999 {
03000 struct undo *undo, *next;
03001
03002 for (undo = undobuf.undos; undo; undo = next)
03003 {
03004 next = undo->next;
03005 if (undo->is_int)
03006 *undo->where.i = undo->old_contents.i;
03007 else
03008 *undo->where.r = undo->old_contents.r;
03009
03010 undo->next = undobuf.frees;
03011 undobuf.frees = undo;
03012 }
03013
03014 undobuf.undos = 0;
03015 }
03016
03017
03018
03019
03020 static void
03021 undo_commit (void)
03022 {
03023 struct undo *undo, *next;
03024
03025 for (undo = undobuf.undos; undo; undo = next)
03026 {
03027 next = undo->next;
03028 undo->next = undobuf.frees;
03029 undobuf.frees = undo;
03030 }
03031 undobuf.undos = 0;
03032 }
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042 static rtx *
03043 find_split_point (rtx *loc, rtx insn)
03044 {
03045 rtx x = *loc;
03046 enum rtx_code code = GET_CODE (x);
03047 rtx *split;
03048 unsigned HOST_WIDE_INT len = 0;
03049 HOST_WIDE_INT pos = 0;
03050 int unsignedp = 0;
03051 rtx inner = NULL_RTX;
03052
03053
03054 switch (code)
03055 {
03056 case SUBREG:
03057 #ifdef INSN_SCHEDULING
03058
03059
03060 if (MEM_P (SUBREG_REG (x)))
03061 return loc;
03062 #endif
03063 return find_split_point (&SUBREG_REG (x), insn);
03064
03065 case MEM:
03066 #ifdef HAVE_lo_sum
03067
03068
03069 if (GET_CODE (XEXP (x, 0)) == CONST
03070 || GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
03071 {
03072 SUBST (XEXP (x, 0),
03073 gen_rtx_LO_SUM (Pmode,
03074 gen_rtx_HIGH (Pmode, XEXP (x, 0)),
03075 XEXP (x, 0)));
03076 return &XEXP (XEXP (x, 0), 0);
03077 }
03078 #endif
03079
03080
03081
03082
03083
03084
03085 if (GET_CODE (XEXP (x, 0)) == PLUS
03086 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
03087 && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
03088 {
03089 rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
03090 rtx seq = split_insns (gen_rtx_SET (VOIDmode, reg, XEXP (x, 0)),
03091 subst_insn);
03092
03093
03094
03095
03096
03097
03098 if (seq
03099 && NEXT_INSN (seq) != NULL_RTX
03100 && NEXT_INSN (NEXT_INSN (seq)) == NULL_RTX
03101 && NONJUMP_INSN_P (seq)
03102 && GET_CODE (PATTERN (seq)) == SET
03103 && SET_DEST (PATTERN (seq)) == reg
03104 && ! reg_mentioned_p (reg,
03105 SET_SRC (PATTERN (seq)))
03106 && NONJUMP_INSN_P (NEXT_INSN (seq))
03107 && GET_CODE (PATTERN (NEXT_INSN (seq))) == SET
03108 && SET_DEST (PATTERN (NEXT_INSN (seq))) == reg
03109 && memory_address_p (GET_MODE (x),
03110 SET_SRC (PATTERN (NEXT_INSN (seq)))))
03111 {
03112 rtx src1 = SET_SRC (PATTERN (seq));
03113 rtx src2 = SET_SRC (PATTERN (NEXT_INSN (seq)));
03114
03115
03116
03117
03118
03119
03120 src2 = replace_rtx (src2, reg, src1);
03121 split = 0;
03122 if (XEXP (src2, 0) == src1)
03123 split = &XEXP (src2, 0);
03124 else if (GET_RTX_FORMAT (GET_CODE (XEXP (src2, 0)))[0] == 'e'
03125 && XEXP (XEXP (src2, 0), 0) == src1)
03126 split = &XEXP (XEXP (src2, 0), 0);
03127
03128 if (split)
03129 {
03130 SUBST (XEXP (x, 0), src2);
03131 return split;
03132 }
03133 }
03134
03135
03136
03137
03138
03139
03140 else if (!OBJECT_P (XEXP (XEXP (x, 0), 0))
03141 && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
03142 && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
03143 return &XEXP (XEXP (x, 0), 0);
03144 }
03145 break;
03146
03147 case SET:
03148 #ifdef HAVE_cc0
03149
03150
03151
03152
03153
03154 if (SET_DEST (x) == cc0_rtx
03155 && GET_CODE (SET_SRC (x)) != COMPARE
03156 && GET_CODE (SET_SRC (x)) != ZERO_EXTRACT
03157 && !OBJECT_P (SET_SRC (x))
03158 && ! (GET_CODE (SET_SRC (x)) == SUBREG
03159 && OBJECT_P (SUBREG_REG (SET_SRC (x)))))
03160 return &SET_SRC (x);
03161 #endif
03162
03163
03164 split = find_split_point (&SET_SRC (x), insn);
03165 if (split && split != &SET_SRC (x))
03166 return split;
03167
03168
03169 split = find_split_point (&SET_DEST (x), insn);
03170 if (split && split != &SET_DEST (x))
03171 return split;
03172
03173
03174
03175 if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
03176 && (GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0)))
03177 <= HOST_BITS_PER_WIDE_INT)
03178 && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT
03179 && GET_CODE (XEXP (SET_DEST (x), 2)) == CONST_INT
03180 && GET_CODE (SET_SRC (x)) == CONST_INT
03181 && ((INTVAL (XEXP (SET_DEST (x), 1))
03182 + INTVAL (XEXP (SET_DEST (x), 2)))
03183 <= GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0))))
03184 && ! side_effects_p (XEXP (SET_DEST (x), 0)))
03185 {
03186 HOST_WIDE_INT pos = INTVAL (XEXP (SET_DEST (x), 2));
03187 unsigned HOST_WIDE_INT len = INTVAL (XEXP (SET_DEST (x), 1));
03188 unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
03189 rtx dest = XEXP (SET_DEST (x), 0);
03190 enum machine_mode mode = GET_MODE (dest);
03191 unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1;
03192
03193 if (BITS_BIG_ENDIAN)
03194 pos = GET_MODE_BITSIZE (mode) - len - pos;
03195
03196 if (src == mask)
03197 SUBST (SET_SRC (x),
03198 simplify_gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
03199 else
03200 {
03201 rtx negmask = gen_int_mode (~(mask << pos), mode);
03202 SUBST (SET_SRC (x),
03203 simplify_gen_binary (IOR, mode,
03204 simplify_gen_binary (AND, mode,
03205 dest, negmask),
03206 GEN_INT (src << pos)));
03207 }
03208
03209 SUBST (SET_DEST (x), dest);
03210
03211 split = find_split_point (&SET_SRC (x), insn);
03212 if (split && split != &SET_SRC (x))
03213 return split;
03214 }
03215
03216
03217
03218 code = GET_CODE (SET_SRC (x));
03219
03220 switch (code)
03221 {
03222 case AND:
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232 if (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
03233 && REG_P (XEXP (SET_SRC (x), 0))
03234 && (pos = exact_log2 (INTVAL (XEXP (SET_SRC (x), 1)))) >= 7
03235 && REG_P (SET_DEST (x))
03236 && (split = find_single_use (SET_DEST (x), insn, (rtx*) 0)) != 0
03237 && (GET_CODE (*split) == EQ || GET_CODE (*split) == NE)
03238 && XEXP (*split, 0) == SET_DEST (x)
03239 && XEXP (*split, 1) == const0_rtx)
03240 {
03241 rtx extraction = make_extraction (GET_MODE (SET_DEST (x)),
03242 XEXP (SET_SRC (x), 0),
03243 pos, NULL_RTX, 1, 1, 0, 0);
03244 if (extraction != 0)
03245 {
03246 SUBST (SET_SRC (x), extraction);
03247 return find_split_point (loc, insn);
03248 }
03249 }
03250 break;
03251
03252 case NE:
03253
03254
03255 if (STORE_FLAG_VALUE == -1 && XEXP (SET_SRC (x), 1) == const0_rtx
03256 && GET_MODE (SET_SRC (x)) == GET_MODE (XEXP (SET_SRC (x), 0))
03257 && 1 <= (pos = exact_log2
03258 (nonzero_bits (XEXP (SET_SRC (x), 0),
03259 GET_MODE (XEXP (SET_SRC (x), 0))))))
03260 {
03261 enum machine_mode mode = GET_MODE (XEXP (SET_SRC (x), 0));
03262
03263 SUBST (SET_SRC (x),
03264 gen_rtx_NEG (mode,
03265 gen_rtx_LSHIFTRT (mode,
03266 XEXP (SET_SRC (x), 0),
03267 GEN_INT (pos))));
03268
03269 split = find_split_point (&SET_SRC (x), insn);
03270 if (split && split != &SET_SRC (x))
03271 return split;
03272 }
03273 break;
03274
03275 case SIGN_EXTEND:
03276 inner = XEXP (SET_SRC (x), 0);
03277
03278
03279
03280
03281 if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_PARTIAL_INT
03282 || GET_MODE_CLASS (GET_MODE (SET_SRC (x))) == MODE_PARTIAL_INT)
03283 break;
03284
03285 pos = 0;
03286 len = GET_MODE_BITSIZE (GET_MODE (inner));
03287 unsignedp = 0;
03288 break;
03289
03290 case SIGN_EXTRACT:
03291 case ZERO_EXTRACT:
03292 if (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
03293 && GET_CODE (XEXP (SET_SRC (x), 2)) == CONST_INT)
03294 {
03295 inner = XEXP (SET_SRC (x), 0);
03296 len = INTVAL (XEXP (SET_SRC (x), 1));
03297 pos = INTVAL (XEXP (SET_SRC (x), 2));
03298
03299 if (BITS_BIG_ENDIAN)
03300 pos = GET_MODE_BITSIZE (GET_MODE (inner)) - len - pos;
03301 unsignedp = (code == ZERO_EXTRACT);
03302 }
03303 break;
03304
03305 default:
03306 break;
03307 }
03308
03309 if (len && pos >= 0 && pos + len <= GET_MODE_BITSIZE (GET_MODE (inner)))
03310 {
03311 enum machine_mode mode = GET_MODE (SET_SRC (x));
03312
03313
03314
03315
03316
03317
03318
03319 if (unsignedp && len <= 8)
03320 {
03321 SUBST (SET_SRC (x),
03322 gen_rtx_AND (mode,
03323 gen_rtx_LSHIFTRT
03324 (mode, gen_lowpart (mode, inner),
03325 GEN_INT (pos)),
03326 GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
03327
03328 split = find_split_point (&SET_SRC (x), insn);
03329 if (split && split != &SET_SRC (x))
03330 return split;
03331 }
03332 else
03333 {
03334 SUBST (SET_SRC (x),
03335 gen_rtx_fmt_ee
03336 (unsignedp ? LSHIFTRT : ASHIFTRT, mode,
03337 gen_rtx_ASHIFT (mode,
03338 gen_lowpart (mode, inner),
03339 GEN_INT (GET_MODE_BITSIZE (mode)
03340 - len - pos)),
03341 GEN_INT (GET_MODE_BITSIZE (mode) - len)));
03342
03343 split = find_split_point (&SET_SRC (x), insn);
03344 if (split && split != &SET_SRC (x))
03345 return split;
03346 }
03347 }
03348
03349
03350
03351
03352 if (BINARY_P (SET_SRC (x))
03353 && CONSTANT_P (XEXP (SET_SRC (x), 1))
03354 && (OBJECT_P (XEXP (SET_SRC (x), 0))
03355 || (GET_CODE (XEXP (SET_SRC (x), 0)) == SUBREG
03356 && OBJECT_P (SUBREG_REG (XEXP (SET_SRC (x), 0))))))
03357 return &XEXP (SET_SRC (x), 1);
03358
03359
03360
03361
03362
03363
03364 if ((BINARY_P (SET_SRC (x)) || UNARY_P (SET_SRC (x)))
03365 && ! register_operand (XEXP (SET_SRC (x), 0), VOIDmode))
03366 return &XEXP (SET_SRC (x), 0);
03367
03368 return 0;
03369
03370 case AND:
03371 case IOR:
03372
03373
03374
03375 if (GET_CODE (XEXP (x, 0)) == NOT && GET_CODE (XEXP (x, 1)) == NOT)
03376 {
03377 SUBST (*loc,
03378 gen_rtx_NOT (GET_MODE (x),
03379 gen_rtx_fmt_ee (code == IOR ? AND : IOR,
03380 GET_MODE (x),
03381 XEXP (XEXP (x, 0), 0),
03382 XEXP (XEXP (x, 1), 0))));
03383 return find_split_point (loc, insn);
03384 }
03385
03386
03387
03388
03389 if (GET_CODE (XEXP (x, 1)) == NOT)
03390 {
03391 rtx tem = XEXP (x, 0);
03392 SUBST (XEXP (x, 0), XEXP (x, 1));
03393 SUBST (XEXP (x, 1), tem);
03394 }
03395 break;
03396
03397 default:
03398 break;
03399 }
03400
03401
03402 switch (GET_RTX_CLASS (code))
03403 {
03404 case RTX_BITFIELD_OPS:
03405 case RTX_TERNARY:
03406 split = find_split_point (&XEXP (x, 2), insn);
03407 if (split)
03408 return split;
03409
03410 case RTX_BIN_ARITH:
03411 case RTX_COMM_ARITH:
03412 case RTX_COMPARE:
03413 case RTX_COMM_COMPARE:
03414 split = find_split_point (&XEXP (x, 1), insn);
03415 if (split)
03416 return split;
03417
03418 case RTX_UNARY:
03419
03420
03421 if (GET_CODE (x) != AND && GET_CODE (XEXP (x, 0)) == AND)
03422 return &XEXP (x, 0);
03423
03424 split = find_split_point (&XEXP (x, 0), insn);
03425 if (split)
03426 return split;
03427 return loc;
03428
03429 default:
03430
03431 return 0;
03432 }
03433 }
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454 static rtx
03455 subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
03456 {
03457 enum rtx_code code = GET_CODE (x);
03458 enum machine_mode op0_mode = VOIDmode;
03459 const char *fmt;
03460 int len, i;
03461 rtx new;
03462
03463
03464
03465
03466
03467 #define COMBINE_RTX_EQUAL_P(X,Y) \
03468 ((X) == (Y) \
03469 || (REG_P (X) && REG_P (Y) \
03470 && REGNO (X) == REGNO (Y) && GET_MODE (X) == GET_MODE (Y)))
03471
03472 if (! in_dest && COMBINE_RTX_EQUAL_P (x, from))
03473 {
03474 n_occurrences++;
03475 return (unique_copy && n_occurrences > 1 ? copy_rtx (to) : to);
03476 }
03477
03478
03479
03480
03481
03482
03483
03484
03485 if (! in_dest && code == REG && REG_P (from)
03486 && REGNO (x) == REGNO (from))
03487 return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
03488
03489
03490
03491 if (code != MEM && code != LO_SUM && OBJECT_P (x))
03492 return x;
03493
03494
03495
03496
03497
03498
03499
03500 if (COMBINE_RTX_EQUAL_P (x, to))
03501 return to;
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512 if (code == PARALLEL
03513 && GET_CODE (XVECEXP (x, 0, 0)) == SET
03514 && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS)
03515 {
03516 new = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy);
03517
03518
03519 if (GET_CODE (new) == CLOBBER
03520 && XEXP (new, 0) == const0_rtx)
03521 return new;
03522
03523 SUBST (XVECEXP (x, 0, 0), new);
03524
03525 for (i = XVECLEN (x, 0) - 1; i >= 1; i--)
03526 {
03527 rtx dest = SET_DEST (XVECEXP (x, 0, i));
03528
03529 if (!REG_P (dest)
03530 && GET_CODE (dest) != CC0
03531 && GET_CODE (dest) != PC)
03532 {
03533 new = subst (dest, from, to, 0, unique_copy);
03534
03535
03536 if (GET_CODE (new) == CLOBBER
03537 && XEXP (new, 0) == const0_rtx)
03538 return new;
03539
03540 SUBST (SET_DEST (XVECEXP (x, 0, i)), new);
03541 }
03542 }
03543 }
03544 else
03545 {
03546 len = GET_RTX_LENGTH (code);
03547 fmt = GET_RTX_FORMAT (code);
03548
03549
03550
03551
03552
03553 if (code == SET
03554 && (REG_P (SET_DEST (x))
03555 || GET_CODE (SET_DEST (x)) == CC0
03556 || GET_CODE (SET_DEST (x)) == PC))
03557 fmt = "ie";
03558
03559
03560
03561 if (fmt[0] == 'e')
03562 op0_mode = GET_MODE (XEXP (x, 0));
03563
03564 for (i = 0; i < len; i++)
03565 {
03566 if (fmt[i] == 'E')
03567 {
03568 int j;
03569 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
03570 {
03571 if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from))
03572 {
03573 new = (unique_copy && n_occurrences
03574 ? copy_rtx (to) : to);
03575 n_occurrences++;
03576 }
03577 else
03578 {
03579 new = subst (XVECEXP (x, i, j), from, to, 0,
03580 unique_copy);
03581
03582
03583
03584 if (GET_CODE (new) == CLOBBER
03585 && XEXP (new, 0) == const0_rtx)
03586 return new;
03587 }
03588
03589 SUBST (XVECEXP (x, i, j), new);
03590 }
03591 }
03592 else if (fmt[i] == 'e')
03593 {
03594
03595 new = XEXP (x, i);
03596 if (in_dest
03597 && i == 0
03598 && (((code == SUBREG || code == ZERO_EXTRACT)
03599 && REG_P (new))
03600 || code == STRICT_LOW_PART))
03601 ;
03602
03603 else if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from))
03604 {
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618 if (GET_CODE (to) == SUBREG
03619 && ! MODES_TIEABLE_P (GET_MODE (to),
03620 GET_MODE (SUBREG_REG (to)))
03621 && ! (code == SUBREG
03622 && MODES_TIEABLE_P (GET_MODE (x),
03623 GET_MODE (SUBREG_REG (to))))
03624 #ifdef HAVE_cc0
03625 && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx)
03626 #endif
03627 )
03628 return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
03629
03630 #ifdef CANNOT_CHANGE_MODE_CLASS
03631 if (code == SUBREG
03632 && REG_P (to)
03633 && REGNO (to) < FIRST_PSEUDO_REGISTER
03634 && REG_CANNOT_CHANGE_MODE_P (REGNO (to),
03635 GET_MODE (to),
03636 GET_MODE (x)))
03637 return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
03638 #endif
03639
03640 new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
03641 n_occurrences++;
03642 }
03643 else
03644
03645
03646
03647
03648
03649
03650
03651
03652 new = subst (XEXP (x, i), from, to,
03653 (((in_dest
03654 && (code == SUBREG || code == STRICT_LOW_PART
03655 || code == ZERO_EXTRACT))
03656 || code == SET)
03657 && i == 0), unique_copy);
03658
03659
03660
03661
03662
03663
03664
03665 if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
03666 return new;
03667
03668 if (GET_CODE (x) == SUBREG
03669 && (GET_CODE (new) == CONST_INT
03670 || GET_CODE (new) == CONST_DOUBLE))
03671 {
03672 enum machine_mode mode = GET_MODE (x);
03673
03674 x = simplify_subreg (GET_MODE (x), new,
03675 GET_MODE (SUBREG_REG (x)),
03676 SUBREG_BYTE (x));
03677 if (! x)
03678 x = gen_rtx_CLOBBER (mode, const0_rtx);
03679 }
03680 else if (GET_CODE (new) == CONST_INT
03681 && GET_CODE (x) == ZERO_EXTEND)
03682 {
03683 x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
03684 new, GET_MODE (XEXP (x, 0)));
03685 gcc_assert (x);
03686 }
03687 else
03688 SUBST (XEXP (x, i), new);
03689 }
03690 }
03691 }
03692
03693
03694
03695
03696
03697 for (i = 0; i < 4; i++)
03698 {
03699
03700
03701 if (code != CONST_INT && code != REG && code != CLOBBER)
03702 x = combine_simplify_rtx (x, op0_mode, in_dest);
03703
03704 if (GET_CODE (x) == code)
03705 break;
03706
03707 code = GET_CODE (x);
03708
03709
03710
03711 op0_mode = VOIDmode;
03712 }
03713
03714 return x;
03715 }
03716
03717
03718
03719
03720
03721
03722
03723
03724 static rtx
03725 combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
03726 {
03727 enum rtx_code code = GET_CODE (x);
03728 enum machine_mode mode = GET_MODE (x);
03729 rtx temp;
03730 rtx reversed;
03731 int i;
03732
03733
03734
03735 if (COMMUTATIVE_ARITH_P (x)
03736 && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
03737 {
03738 temp = XEXP (x, 0);
03739 SUBST (XEXP (x, 0), XEXP (x, 1));
03740 SUBST (XEXP (x, 1), temp);
03741 }
03742
03743
03744
03745
03746
03747
03748
03749
03750 if ((BINARY_P (x)
03751 && ((!OBJECT_P (XEXP (x, 0))
03752 && ! (GET_CODE (XEXP (x, 0)) == SUBREG
03753 && OBJECT_P (SUBREG_REG (XEXP (x, 0)))))
03754 || (!OBJECT_P (XEXP (x, 1))
03755 && ! (GET_CODE (XEXP (x, 1)) == SUBREG
03756 && OBJECT_P (SUBREG_REG (XEXP (x, 1)))))))
03757 || (UNARY_P (x)
03758 && (!OBJECT_P (XEXP (x, 0))
03759 && ! (GET_CODE (XEXP (x, 0)) == SUBREG
03760 && OBJECT_P (SUBREG_REG (XEXP (x, 0)))))))
03761 {
03762 rtx cond, true_rtx, false_rtx;
03763
03764 cond = if_then_else_cond (x, &true_rtx, &false_rtx);
03765 if (cond != 0
03766
03767
03768 && ! (COMPARISON_P (x)
03769 && (COMPARISON_P (true_rtx) || COMPARISON_P (false_rtx))))
03770 {
03771 rtx cop1 = const0_rtx;
03772 enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1);
03773
03774 if (cond_code == NE && COMPARISON_P (cond))
03775 return x;
03776
03777
03778
03779
03780
03781 true_rtx = subst (copy_rtx (true_rtx), pc_rtx, pc_rtx, 0, 0);
03782 false_rtx = subst (copy_rtx (false_rtx), pc_rtx, pc_rtx, 0, 0);
03783
03784
03785
03786 if (general_operand (true_rtx, VOIDmode)
03787 && general_operand (false_rtx, VOIDmode))
03788 {
03789 enum rtx_code reversed;
03790
03791
03792
03793
03794
03795
03796 if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
03797 x = simplify_gen_relational (cond_code, mode, VOIDmode,
03798 cond, cop1);
03799 else if (true_rtx == const0_rtx && false_rtx == const_true_rtx
03800 && ((reversed = reversed_comparison_code_parts
03801 (cond_code, cond, cop1, NULL))
03802 != UNKNOWN))
03803 x = simplify_gen_relational (reversed, mode, VOIDmode,
03804 cond, cop1);
03805
03806
03807
03808 else if (GET_CODE (true_rtx) == CONST_INT
03809 && INTVAL (true_rtx) == - STORE_FLAG_VALUE
03810 && false_rtx == const0_rtx)
03811 x = simplify_gen_unary (NEG, mode,
03812 simplify_gen_relational (cond_code,
03813 mode, VOIDmode,
03814 cond, cop1),
03815 mode);
03816 else if (GET_CODE (false_rtx) == CONST_INT
03817 && INTVAL (false_rtx) == - STORE_FLAG_VALUE
03818 && true_rtx == const0_rtx
03819 && ((reversed = reversed_comparison_code_parts
03820 (cond_code, cond, cop1, NULL))
03821 != UNKNOWN))
03822 x = simplify_gen_unary (NEG, mode,
03823 simplify_gen_relational (reversed,
03824 mode, VOIDmode,
03825 cond, cop1),
03826 mode);
03827 else
03828 return gen_rtx_IF_THEN_ELSE (mode,
03829 simplify_gen_relational (cond_code,
03830 mode,
03831 VOIDmode,
03832 cond,
03833 cop1),
03834 true_rtx, false_rtx);
03835
03836 code = GET_CODE (x);
03837 op0_mode = VOIDmode;
03838 }
03839 }
03840 }
03841
03842
03843
03844 temp = 0;
03845 switch (GET_RTX_CLASS (code))
03846 {
03847 case RTX_UNARY:
03848 if (op0_mode == VOIDmode)
03849 op0_mode = GET_MODE (XEXP (x, 0));
03850 temp = simplify_unary_operation (code, mode, XEXP (x, 0), op0_mode);
03851 break;
03852 case RTX_COMPARE:
03853 case RTX_COMM_COMPARE:
03854 {
03855 enum machine_mode cmp_mode = GET_MODE (XEXP (x, 0));
03856 if (cmp_mode == VOIDmode)
03857 {
03858 cmp_mode = GET_MODE (XEXP (x, 1));
03859 if (cmp_mode == VOIDmode)
03860 cmp_mode = op0_mode;
03861 }
03862 temp = simplify_relational_operation (code, mode, cmp_mode,
03863 XEXP (x, 0), XEXP (x, 1));
03864 }
03865 break;
03866 case RTX_COMM_ARITH:
03867 case RTX_BIN_ARITH:
03868 temp = simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1));
03869 break;
03870 case RTX_BITFIELD_OPS:
03871 case RTX_TERNARY:
03872 temp = simplify_ternary_operation (code, mode, op0_mode, XEXP (x, 0),
03873 XEXP (x, 1), XEXP (x, 2));
03874 break;
03875 default:
03876 break;
03877 }
03878
03879 if (temp)
03880 {
03881 x = temp;
03882 code = GET_CODE (temp);
03883 op0_mode = VOIDmode;
03884 mode = GET_MODE (temp);
03885 }
03886
03887
03888 if (code == PLUS || code == MINUS
03889 || code == AND || code == IOR || code == XOR)
03890 {
03891 x = apply_distributive_law (x);
03892 code = GET_CODE (x);
03893 op0_mode = VOIDmode;
03894 }
03895
03896
03897
03898
03899 if ((code == PLUS || code == MINUS || code == MULT || code == DIV
03900 || code == AND || code == IOR || code == XOR
03901 || code == SMAX || code == SMIN || code == UMAX || code == UMIN)
03902 && ((INTEGRAL_MODE_P (mode) && code != DIV)
03903 || (flag_unsafe_math_optimizations && FLOAT_MODE_P (mode))))
03904 {
03905 if (GET_CODE (XEXP (x, 0)) == code)
03906 {
03907 rtx other = XEXP (XEXP (x, 0), 0);
03908 rtx inner_op0 = XEXP (XEXP (x, 0), 1);
03909 rtx inner_op1 = XEXP (x, 1);
03910 rtx inner;
03911
03912
03913
03914 if (CONSTANT_P (inner_op0) && COMMUTATIVE_ARITH_P (x))
03915 {
03916 rtx tem = inner_op0;
03917 inner_op0 = inner_op1;
03918 inner_op1 = tem;
03919 }
03920 inner = simplify_binary_operation (code == MINUS ? PLUS
03921 : code == DIV ? MULT
03922 : code,
03923 mode, inner_op0, inner_op1);
03924
03925
03926
03927 if (inner == 0 && COMMUTATIVE_ARITH_P (x))
03928 {
03929 other = XEXP (XEXP (x, 0), 1);
03930 inner = simplify_binary_operation (code, mode,
03931 XEXP (XEXP (x, 0), 0),
03932 XEXP (x, 1));
03933 }
03934
03935 if (inner)
03936 return simplify_gen_binary (code, mode, other, inner);
03937 }
03938 }
03939
03940
03941 switch (code)
03942 {
03943 case MEM:
03944
03945
03946 temp = make_compound_operation (XEXP (x, 0), MEM);
03947 SUBST (XEXP (x, 0), temp);
03948 break;
03949
03950 case SUBREG:
03951 if (op0_mode == VOIDmode)
03952 op0_mode = GET_MODE (SUBREG_REG (x));
03953
03954
03955 if (CONSTANT_P (SUBREG_REG (x))
03956 && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
03957
03958
03959
03960 && (GET_MODE (SUBREG_REG (x)) != VOIDmode
03961 || gen_lowpart_common (mode, SUBREG_REG (x))))
03962 return gen_lowpart (mode, SUBREG_REG (x));
03963
03964 if (GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_CC)
03965 break;
03966 {
03967 rtx temp;
03968 temp = simplify_subreg (mode, SUBREG_REG (x), op0_mode,
03969 SUBREG_BYTE (x));
03970 if (temp)
03971 return temp;
03972 }
03973
03974
03975
03976 if (MEM_P (SUBREG_REG (x))
03977 && (MEM_VOLATILE_P (SUBREG_REG (x))
03978 || mode_dependent_address_p (XEXP (SUBREG_REG (x), 0))))
03979 return gen_rtx_CLOBBER (mode, const0_rtx);
03980
03981
03982
03983
03984
03985 break;
03986
03987 case NOT:
03988 if (GET_CODE (XEXP (x, 0)) == SUBREG
03989 && subreg_lowpart_p (XEXP (x, 0))
03990 && (GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))
03991 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (x, 0)))))
03992 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == ASHIFT
03993 && XEXP (SUBREG_REG (XEXP (x, 0)), 0) == const1_rtx)
03994 {
03995 enum machine_mode inner_mode = GET_MODE (SUBREG_REG (XEXP (x, 0)));
03996
03997 x = gen_rtx_ROTATE (inner_mode,
03998 simplify_gen_unary (NOT, inner_mode, const1_rtx,
03999 inner_mode),
04000 XEXP (SUBREG_REG (XEXP (x, 0)), 1));
04001 return gen_lowpart (mode, x);
04002 }
04003
04004
04005
04006
04007
04008
04009 if (GET_CODE (XEXP (x, 0)) == IOR || GET_CODE (XEXP (x, 0)) == AND)
04010 {
04011 rtx in1 = XEXP (XEXP (x, 0), 0), in2 = XEXP (XEXP (x, 0), 1);
04012 enum machine_mode op_mode;
04013
04014 op_mode = GET_MODE (in1);
04015 in1 = simplify_gen_unary (NOT, op_mode, in1, op_mode);
04016
04017 op_mode = GET_MODE (in2);
04018 if (op_mode == VOIDmode)
04019 op_mode = mode;
04020 in2 = simplify_gen_unary (NOT, op_mode, in2, op_mode);
04021
04022 if (GET_CODE (in2) == NOT && GET_CODE (in1) != NOT)
04023 {
04024 rtx tem = in2;
04025 in2 = in1; in1 = tem;
04026 }
04027
04028 return gen_rtx_fmt_ee (GET_CODE (XEXP (x, 0)) == IOR ? AND : IOR,
04029 mode, in1, in2);
04030 }
04031 break;
04032
04033 case NEG:
04034
04035 if (GET_CODE (XEXP (x, 0)) == XOR
04036 && XEXP (XEXP (x, 0), 1) == const1_rtx
04037 && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1)
04038 return simplify_gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
04039 constm1_rtx);
04040
04041 temp = expand_compound_operation (XEXP (x, 0));
04042
04043
04044
04045
04046
04047 if (GET_CODE (temp) == ASHIFTRT
04048 && GET_CODE (XEXP (temp, 1)) == CONST_INT
04049 && INTVAL (XEXP (temp, 1)) == GET_MODE_BITSIZE (mode) - 1)
04050 return simplify_shift_const (temp, LSHIFTRT, mode, XEXP (temp, 0),
04051 INTVAL (XEXP (temp, 1)));
04052
04053
04054
04055
04056
04057
04058
04059
04060 if (!REG_P (temp)
04061 && ! (GET_CODE (temp) == SUBREG
04062 && REG_P (SUBREG_REG (temp)))
04063 && (i = exact_log2 (nonzero_bits (temp, mode))) >= 0)
04064 {
04065 rtx temp1 = simplify_shift_const
04066 (NULL_RTX, ASHIFTRT, mode,
04067 simplify_shift_const (NULL_RTX, ASHIFT, mode, temp,
04068 GET_MODE_BITSIZE (mode) - 1 - i),
04069 GET_MODE_BITSIZE (mode) - 1 - i);
04070
04071
04072
04073
04074 if (GET_CODE (temp1) != ASHIFTRT
04075 || GET_CODE (XEXP (temp1, 0)) != ASHIFT
04076 || XEXP (XEXP (temp1, 0), 0) != temp)
04077 return temp1;
04078 }
04079 break;
04080
04081 case TRUNCATE:
04082
04083
04084
04085 if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
04086 break;
04087
04088 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04089 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
04090 GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))))
04091 SUBST (XEXP (x, 0),
04092 force_to_mode (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
04093 GET_MODE_MASK (mode), NULL_RTX, 0));
04094
04095
04096 if ((GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
04097 || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
04098 && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
04099 return XEXP (XEXP (x, 0), 0);
04100
04101
04102
04103 if ((GET_CODE (XEXP (x, 0)) == ABS
04104 || GET_CODE (XEXP (x, 0)) == NEG)
04105 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND
04106 || GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND)
04107 && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
04108 return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
04109 XEXP (XEXP (XEXP (x, 0), 0), 0), mode);
04110
04111
04112
04113 if (GET_CODE (XEXP (x, 0)) == SUBREG
04114 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == TRUNCATE
04115 && subreg_lowpart_p (XEXP (x, 0)))
04116 return SUBREG_REG (XEXP (x, 0));
04117
04118
04119
04120
04121
04122
04123 if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
04124 GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
04125 && num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
04126 >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
04127 && ! (GET_CODE (XEXP (x, 0)) == LSHIFTRT
04128 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT))
04129 return gen_lowpart (mode, XEXP (x, 0));
04130
04131
04132
04133
04134
04135 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04136 && COMPARISON_P (XEXP (x, 0))
04137 && ((HOST_WIDE_INT) STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0)
04138 return gen_lowpart (mode, XEXP (x, 0));
04139
04140
04141
04142
04143 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04144 && ((HOST_WIDE_INT) STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0
04145 && (temp = get_last_value (XEXP (x, 0)))
04146 && COMPARISON_P (temp))
04147 return gen_lowpart (mode, XEXP (x, 0));
04148
04149 break;
04150
04151 case FLOAT_TRUNCATE:
04152
04153 if (GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND
04154 && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
04155 return XEXP (XEXP (x, 0), 0);
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166 if ((GET_CODE (XEXP (x, 0)) == FLOAT_TRUNCATE
04167 && flag_unsafe_math_optimizations)
04168 || GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND)
04169 return simplify_gen_unary (GET_MODE_SIZE (GET_MODE (XEXP (XEXP (x, 0),
04170 0)))
04171 > GET_MODE_SIZE (mode)
04172 ? FLOAT_TRUNCATE : FLOAT_EXTEND,
04173 mode,
04174 XEXP (XEXP (x, 0), 0), mode);
04175
04176
04177 if (GET_CODE (XEXP (x, 0)) == FLOAT
04178 && (flag_unsafe_math_optimizations
04179 || ((unsigned)significand_size (GET_MODE (XEXP (x, 0)))
04180 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))
04181 - num_sign_bit_copies (XEXP (XEXP (x, 0), 0),
04182 GET_MODE (XEXP (XEXP (x, 0), 0)))))))
04183 return simplify_gen_unary (FLOAT, mode,
04184 XEXP (XEXP (x, 0), 0),
04185 GET_MODE (XEXP (XEXP (x, 0), 0)));
04186
04187
04188
04189 if ((GET_CODE (XEXP (x, 0)) == ABS
04190 || GET_CODE (XEXP (x, 0)) == NEG)
04191 && GET_CODE (XEXP (XEXP (x, 0), 0)) == FLOAT_EXTEND
04192 && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
04193 return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
04194 XEXP (XEXP (XEXP (x, 0), 0), 0), mode);
04195
04196
04197
04198 if (GET_CODE (XEXP (x, 0)) == SUBREG
04199 && subreg_lowpart_p (XEXP (x, 0))
04200 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == FLOAT_TRUNCATE)
04201 return SUBREG_REG (XEXP (x, 0));
04202 break;
04203 case FLOAT_EXTEND:
04204
04205
04206
04207
04208
04209 if (GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND
04210 || (GET_CODE (XEXP (x, 0)) == FLOAT
04211 && ((unsigned)significand_size (GET_MODE (XEXP (x, 0)))
04212 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))
04213 - num_sign_bit_copies (XEXP (XEXP (x, 0), 0),
04214 GET_MODE (XEXP (XEXP (x, 0), 0)))))))
04215 return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
04216 XEXP (XEXP (x, 0), 0),
04217 GET_MODE (XEXP (XEXP (x, 0), 0)));
04218
04219 break;
04220 #ifdef HAVE_cc0
04221 case COMPARE:
04222
04223
04224
04225 if (XEXP (x, 1) == const0_rtx)
04226 return XEXP (x, 0);
04227
04228
04229
04230
04231 if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
04232 && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
04233 && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
04234 return XEXP (x, 0);
04235 break;
04236 #endif
04237
04238 case CONST:
04239
04240
04241
04242 if (GET_CODE (XEXP (x, 0)) == CONST)
04243 SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
04244 break;
04245
04246 #ifdef HAVE_lo_sum
04247 case LO_SUM:
04248
04249
04250
04251 if (GET_CODE (XEXP (x, 0)) == HIGH
04252 && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1)))
04253 return XEXP (x, 1);
04254 break;
04255 #endif
04256
04257 case PLUS:
04258
04259
04260 if (GET_CODE (XEXP (x, 0)) == MULT
04261 && GET_CODE (XEXP (XEXP (x, 0), 0)) == NEG)
04262 {
04263 rtx in1, in2;
04264
04265 in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
04266 in2 = XEXP (XEXP (x, 0), 1);
04267 return simplify_gen_binary (MINUS, mode, XEXP (x, 1),
04268 simplify_gen_binary (MULT, mode,
04269 in1, in2));
04270 }
04271
04272
04273
04274
04275
04276 if (GET_CODE (XEXP (x, 0)) == PLUS
04277 && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
04278 return simplify_gen_binary (PLUS, mode,
04279 simplify_gen_binary (PLUS, mode,
04280 XEXP (XEXP (x, 0), 0),
04281 XEXP (x, 1)),
04282 XEXP (XEXP (x, 0), 1));
04283
04284
04285
04286
04287
04288
04289 if (GET_CODE (XEXP (x, 0)) == XOR
04290 && GET_CODE (XEXP (x, 1)) == CONST_INT
04291 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
04292 && INTVAL (XEXP (x, 1)) == -INTVAL (XEXP (XEXP (x, 0), 1))
04293 && ((i = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) >= 0
04294 || (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0)
04295 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04296 && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == AND
04297 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
04298 && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))
04299 == ((HOST_WIDE_INT) 1 << (i + 1)) - 1))
04300 || (GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND
04301 && (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)))
04302 == (unsigned int) i + 1))))
04303 return simplify_shift_const
04304 (NULL_RTX, ASHIFTRT, mode,
04305 simplify_shift_const (NULL_RTX, ASHIFT, mode,
04306 XEXP (XEXP (XEXP (x, 0), 0), 0),
04307 GET_MODE_BITSIZE (mode) - (i + 1)),
04308 GET_MODE_BITSIZE (mode) - (i + 1));
04309
04310
04311
04312
04313
04314 if (COMPARISON_P (XEXP (x, 0))
04315 && ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx)
04316 || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx))
04317 && (reversed = reversed_comparison (XEXP (x, 0), mode,
04318 XEXP (XEXP (x, 0), 0),
04319 XEXP (XEXP (x, 0), 1))))
04320 return
04321 simplify_gen_unary (NEG, mode, reversed, mode);
04322
04323
04324
04325
04326
04327 if (XEXP (x, 1) == constm1_rtx
04328 && !REG_P (XEXP (x, 0))
04329 && ! (GET_CODE (XEXP (x, 0)) == SUBREG
04330 && REG_P (SUBREG_REG (XEXP (x, 0))))
04331 && nonzero_bits (XEXP (x, 0), mode) == 1)
04332 return simplify_shift_const (NULL_RTX, ASHIFTRT, mode,
04333 simplify_shift_const (NULL_RTX, ASHIFT, mode,
04334 gen_rtx_XOR (mode, XEXP (x, 0), const1_rtx),
04335 GET_MODE_BITSIZE (mode) - 1),
04336 GET_MODE_BITSIZE (mode) - 1);
04337
04338
04339
04340
04341
04342
04343 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04344 && (nonzero_bits (XEXP (x, 0), mode)
04345 & nonzero_bits (XEXP (x, 1), mode)) == 0)
04346 {
04347
04348 rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
04349 temp = combine_simplify_rtx (tor, mode, in_dest);
04350
04351
04352
04353
04354 if (GET_CODE (temp) != CLOBBER && temp != tor)
04355 return temp;
04356 }
04357 break;
04358
04359 case MINUS:
04360
04361
04362 if (STORE_FLAG_VALUE == 1
04363 && XEXP (x, 0) == const1_rtx
04364 && COMPARISON_P (XEXP (x, 1))
04365 && (reversed = reversed_comparison (XEXP (x, 1), mode,
04366 XEXP (XEXP (x, 1), 0),
04367 XEXP (XEXP (x, 1), 1))))
04368 return reversed;
04369
04370
04371
04372 if (GET_CODE (XEXP (x, 1)) == AND
04373 && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
04374 && exact_log2 (-INTVAL (XEXP (XEXP (x, 1), 1))) >= 0
04375 && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
04376 return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0),
04377 -INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
04378
04379
04380
04381 if (GET_CODE (XEXP (x, 1)) == MULT
04382 && GET_CODE (XEXP (XEXP (x, 1), 0)) == NEG)
04383 {
04384 rtx in1, in2;
04385
04386 in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
04387 in2 = XEXP (XEXP (x, 1), 1);
04388 return simplify_gen_binary (PLUS, mode,
04389 simplify_gen_binary (MULT, mode,
04390 in1, in2),
04391 XEXP (x, 0));
04392 }
04393
04394
04395
04396 if (GET_CODE (XEXP (x, 1)) == MULT
04397 && GET_CODE (XEXP (x, 0)) == NEG)
04398 {
04399 rtx in1, in2;
04400
04401 in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
04402 in2 = XEXP (XEXP (x, 1), 1);
04403 return simplify_gen_binary (MINUS, mode,
04404 simplify_gen_binary (MULT, mode,
04405 in1, in2),
04406 XEXP (XEXP (x, 0), 0));
04407 }
04408
04409
04410
04411 if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
04412 return simplify_gen_binary (MINUS, mode,
04413 simplify_gen_binary (MINUS, mode,
04414 XEXP (x, 0),
04415 XEXP (XEXP (x, 1), 0)),
04416 XEXP (XEXP (x, 1), 1));
04417 break;
04418
04419 case MULT:
04420
04421
04422
04423
04424 if (GET_CODE (XEXP (x, 0)) == PLUS)
04425 {
04426 rtx result = distribute_and_simplify_rtx (x, 0);
04427 if (result)
04428 return result;
04429 }
04430
04431
04432 if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
04433 && GET_CODE (XEXP (x, 0)) == DIV)
04434 {
04435 rtx tem = simplify_binary_operation (MULT, mode,
04436 XEXP (XEXP (x, 0), 0),
04437 XEXP (x, 1));
04438 if (tem)
04439 return simplify_gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1));
04440 }
04441 break;
04442
04443 case UDIV:
04444
04445
04446 if (GET_CODE (XEXP (x, 1)) == CONST_INT
04447 && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0
04448 && (GET_CODE (XEXP (x, 0)) == ASHIFT
04449 || GET_CODE (XEXP (x, 0)) == LSHIFTRT
04450 || GET_CODE (XEXP (x, 0)) == ASHIFTRT
04451 || GET_CODE (XEXP (x, 0)) == ROTATE
04452 || GET_CODE (XEXP (x, 0)) == ROTATERT))
04453 return simplify_shift_const (NULL_RTX, LSHIFTRT, mode, XEXP (x, 0), i);
04454 break;
04455
04456 case EQ: case NE:
04457 case GT: case GTU: case GE: case GEU:
04458 case LT: case LTU: case LE: case LEU:
04459 case UNEQ: case LTGT:
04460 case UNGT: case UNGE:
04461 case UNLT: case UNLE:
04462 case UNORDERED: case ORDERED:
04463
04464
04465 if (GET_CODE (XEXP (x, 0)) == COMPARE
04466 || (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC
04467 && ! CC0_P (XEXP (x, 0))))
04468 {
04469 rtx op0 = XEXP (x, 0);
04470 rtx op1 = XEXP (x, 1);
04471 enum rtx_code new_code;
04472
04473 if (GET_CODE (op0) == COMPARE)
04474 op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
04475
04476
04477 new_code = simplify_comparison (code, &op0, &op1);
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491 if (STORE_FLAG_VALUE == 1
04492 && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
04493 && op1 == const0_rtx
04494 && mode == GET_MODE (op0)
04495 && nonzero_bits (op0, mode) == 1)
04496 return gen_lowpart (mode,
04497 expand_compound_operation (op0));
04498
04499 else if (STORE_FLAG_VALUE == 1
04500 && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
04501 && op1 == const0_rtx
04502 && mode == GET_MODE (op0)
04503 && (num_sign_bit_copies (op0, mode)
04504 == GET_MODE_BITSIZE (mode)))
04505 {
04506 op0 = expand_compound_operation (op0);
04507 return simplify_gen_unary (NEG, mode,
04508 gen_lowpart (mode, op0),
04509 mode);
04510 }
04511
04512 else if (STORE_FLAG_VALUE == 1
04513 && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
04514 && op1 == const0_rtx
04515 && mode == GET_MODE (op0)
04516 && nonzero_bits (op0, mode) == 1)
04517 {
04518 op0 = expand_compound_operation (op0);
04519 return simplify_gen_binary (XOR, mode,
04520 gen_lowpart (mode, op0),
04521 const1_rtx);
04522 }
04523
04524 else if (STORE_FLAG_VALUE == 1
04525 && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
04526 && op1 == const0_rtx
04527 && mode == GET_MODE (op0)
04528 && (num_sign_bit_copies (op0, mode)
04529 == GET_MODE_BITSIZE (mode)))
04530 {
04531 op0 = expand_compound_operation (op0);
04532 return plus_constant (gen_lowpart (mode, op0), 1);
04533 }
04534
04535
04536
04537 if (STORE_FLAG_VALUE == -1
04538 && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
04539 && op1 == const0_rtx
04540 && (num_sign_bit_copies (op0, mode)
04541 == GET_MODE_BITSIZE (mode)))
04542 return gen_lowpart (mode,
04543 expand_compound_operation (op0));
04544
04545 else if (STORE_FLAG_VALUE == -1
04546 && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
04547 && op1 == const0_rtx
04548 && mode == GET_MODE (op0)
04549 && nonzero_bits (op0, mode) == 1)
04550 {
04551 op0 = expand_compound_operation (op0);
04552 return simplify_gen_unary (NEG, mode,
04553 gen_lowpart (mode, op0),
04554 mode);
04555 }
04556
04557 else if (STORE_FLAG_VALUE == -1
04558 && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
04559 && op1 == const0_rtx
04560 && mode == GET_MODE (op0)
04561 && (num_sign_bit_copies (op0, mode)
04562 == GET_MODE_BITSIZE (mode)))
04563 {
04564 op0 = expand_compound_operation (op0);
04565 return simplify_gen_unary (NOT, mode,
04566 gen_lowpart (mode, op0),
04567 mode);
04568 }
04569
04570
04571 else if (STORE_FLAG_VALUE == -1
04572 && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
04573 && op1 == const0_rtx
04574 && mode == GET_MODE (op0)
04575 && nonzero_bits (op0, mode) == 1)
04576 {
04577 op0 = expand_compound_operation (op0);
04578 return plus_constant (gen_lowpart (mode, op0), -1);
04579 }
04580
04581
04582
04583
04584
04585
04586 if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
04587 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04588 && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
04589 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
04590 && op1 == const0_rtx
04591 && mode == GET_MODE (op0)
04592 && (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
04593 {
04594 x = simplify_shift_const (NULL_RTX, ASHIFT, mode,
04595 expand_compound_operation (op0),
04596 GET_MODE_BITSIZE (mode) - 1 - i);
04597 if (GET_CODE (x) == AND && XEXP (x, 1) == const_true_rtx)
04598 return XEXP (x, 0);
04599 else
04600 return x;
04601 }
04602
04603
04604 if (new_code != code)
04605 return gen_rtx_fmt_ee (new_code, mode, op0, op1);
04606
04607
04608
04609 SUBST (XEXP (x, 0), op0);
04610 SUBST (XEXP (x, 1), op1);
04611 }
04612 break;
04613
04614 case IF_THEN_ELSE:
04615 return simplify_if_then_else (x);
04616
04617 case ZERO_EXTRACT:
04618 case SIGN_EXTRACT:
04619 case ZERO_EXTEND:
04620 case SIGN_EXTEND:
04621
04622 if (in_dest)
04623 return x;
04624
04625 return expand_compound_operation (x);
04626
04627 case SET:
04628 return simplify_set (x);
04629
04630 case AND:
04631 case IOR:
04632 case XOR:
04633 return simplify_logical (x);
04634
04635 case ABS:
04636
04637 if (GET_CODE (XEXP (x, 0)) == NEG)
04638 SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
04639
04640
04641
04642 if (GET_MODE (XEXP (x, 0)) == VOIDmode)
04643 break;
04644
04645
04646 if (GET_CODE (XEXP (x, 0)) == FFS || GET_CODE (XEXP (x, 0)) == ABS
04647 || ((GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
04648 <= HOST_BITS_PER_WIDE_INT)
04649 && ((nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
04650 & ((HOST_WIDE_INT) 1
04651 << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1)))
04652 == 0)))
04653 return XEXP (x, 0);
04654
04655
04656 if (num_sign_bit_copies (XEXP (x, 0), mode) == GET_MODE_BITSIZE (mode))
04657 return gen_rtx_NEG (mode, XEXP (x, 0));
04658
04659 break;
04660
04661 case FFS:
04662
04663 if (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
04664 || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
04665 SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
04666 break;
04667
04668 case POPCOUNT:
04669 case PARITY:
04670
04671 if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
04672 SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
04673 break;
04674
04675 case FLOAT:
04676
04677 if (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
04678 SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
04679 break;
04680
04681 case ASHIFT:
04682 case LSHIFTRT:
04683 case ASHIFTRT:
04684 case ROTATE:
04685 case ROTATERT:
04686
04687 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
04688 return simplify_shift_const (x, code, mode, XEXP (x, 0),
04689 INTVAL (XEXP (x, 1)));
04690
04691 else if (SHIFT_COUNT_TRUNCATED && !REG_P (XEXP (x, 1)))
04692 SUBST (XEXP (x, 1),
04693 force_to_mode (XEXP (x, 1), GET_MODE (XEXP (x, 1)),
04694 ((HOST_WIDE_INT) 1
04695 << exact_log2 (GET_MODE_BITSIZE (GET_MODE (x))))
04696 - 1,
04697 NULL_RTX, 0));
04698 break;
04699
04700 case VEC_SELECT:
04701 {
04702 rtx op0 = XEXP (x, 0);
04703 rtx op1 = XEXP (x, 1);
04704 int len;
04705
04706 gcc_assert (GET_CODE (op1) == PARALLEL);
04707 len = XVECLEN (op1, 0);
04708 if (len == 1
04709 && GET_CODE (XVECEXP (op1, 0, 0)) == CONST_INT
04710 && GET_CODE (op0) == VEC_CONCAT)
04711 {
04712 int offset = INTVAL (XVECEXP (op1, 0, 0)) * GET_MODE_SIZE (GET_MODE (x));
04713
04714
04715 for (;;)
04716 {
04717 if (GET_MODE (op0) == GET_MODE (x))
04718 return op0;
04719 if (GET_CODE (op0) == VEC_CONCAT)
04720 {
04721 HOST_WIDE_INT op0_size = GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)));
04722 if (offset < op0_size)
04723 op0 = XEXP (op0, 0);
04724 else
04725 {
04726 offset -= op0_size;
04727 op0 = XEXP (op0, 1);
04728 }
04729 }
04730 else
04731 break;
04732 }
04733 }
04734 }
04735
04736 break;
04737
04738 default:
04739 break;
04740 }
04741
04742 return x;
04743 }
04744
04745
04746
04747 static rtx
04748 simplify_if_then_else (rtx x)
04749 {
04750 enum machine_mode mode = GET_MODE (x);
04751 rtx cond = XEXP (x, 0);
04752 rtx true_rtx = XEXP (x, 1);
04753 rtx false_rtx = XEXP (x, 2);
04754 enum rtx_code true_code = GET_CODE (cond);
04755 int comparison_p = COMPARISON_P (cond);
04756 rtx temp;
04757 int i;
04758 enum rtx_code false_code;
04759 rtx reversed;
04760
04761
04762 if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
04763 return simplify_gen_relational (true_code, mode, VOIDmode,
04764 XEXP (cond, 0), XEXP (cond, 1));
04765
04766
04767 if (comparison_p
04768 && true_rtx == const0_rtx && false_rtx == const_true_rtx
04769 && (reversed = reversed_comparison (cond, mode, XEXP (cond, 0),
04770 XEXP (cond, 1))))
04771 return reversed;
04772
04773
04774
04775
04776
04777 if (comparison_p
04778 && ((false_code = combine_reversed_comparison_code (cond))
04779 != UNKNOWN)
04780 && REG_P (XEXP (cond, 0)))
04781 {
04782 HOST_WIDE_INT nzb;
04783 rtx from = XEXP (cond, 0);
04784 rtx true_val = XEXP (cond, 1);
04785 rtx false_val = true_val;
04786 int swapped = 0;
04787
04788
04789
04790 if (false_code == EQ)
04791 {
04792 swapped = 1, true_code = EQ, false_code = NE;
04793 temp = true_rtx, true_rtx = false_rtx, false_rtx = temp;
04794 }
04795
04796
04797
04798
04799
04800 if (true_code == EQ && true_val == const0_rtx
04801 && exact_log2 (nzb = nonzero_bits (from, GET_MODE (from))) >= 0)
04802 false_code = EQ, false_val = GEN_INT (nzb);
04803 else if (true_code == EQ && true_val == const0_rtx
04804 && (num_sign_bit_copies (from, GET_MODE (from))
04805 == GET_MODE_BITSIZE (GET_MODE (from))))
04806 false_code = EQ, false_val = constm1_rtx;
04807
04808
04809
04810
04811
04812 if (reg_mentioned_p (from, true_rtx))
04813 true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code,
04814 from, true_val),
04815 pc_rtx, pc_rtx, 0, 0);
04816 if (reg_mentioned_p (from, false_rtx))
04817 false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code,
04818 from, false_val),
04819 pc_rtx, pc_rtx, 0, 0);
04820
04821 SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx);
04822 SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx);
04823
04824 true_rtx = XEXP (x, 1);
04825 false_rtx = XEXP (x, 2);
04826 true_code = GET_CODE (cond);
04827 }
04828
04829
04830
04831
04832
04833
04834
04835 if (comparison_p
04836 && combine_reversed_comparison_code (cond) != UNKNOWN
04837 && (true_rtx == pc_rtx
04838 || (CONSTANT_P (true_rtx)
04839 && GET_CODE (false_rtx) != CONST_INT && false_rtx != pc_rtx)
04840 || true_rtx == const0_rtx
04841 || (OBJECT_P (true_rtx) && !OBJECT_P (false_rtx))
04842 || (GET_CODE (true_rtx) == SUBREG && OBJECT_P (SUBREG_REG (true_rtx))
04843 && !OBJECT_P (false_rtx))
04844 || reg_mentioned_p (true_rtx, false_rtx)
04845 || rtx_equal_p (false_rtx, XEXP (cond, 0))))
04846 {
04847 true_code = reversed_comparison_code (cond, NULL);
04848 SUBST (XEXP (x, 0),
04849 reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0),
04850 XEXP (cond, 1)));
04851
04852 SUBST (XEXP (x, 1), false_rtx);
04853 SUBST (XEXP (x, 2), true_rtx);
04854
04855 temp = true_rtx, true_rtx = false_rtx, false_rtx = temp;
04856 cond = XEXP (x, 0);
04857
04858
04859 true_code = GET_CODE (cond);
04860 comparison_p = COMPARISON_P (cond);
04861 }
04862
04863
04864
04865 if (rtx_equal_p (true_rtx, false_rtx) && ! side_effects_p (cond))
04866 return true_rtx;
04867
04868
04869 if (true_code == EQ && ! side_effects_p (cond)
04870 && !HONOR_NANS (mode)
04871 && rtx_equal_p (XEXP (cond, 0), false_rtx)
04872 && rtx_equal_p (XEXP (cond, 1), true_rtx))
04873 return false_rtx;
04874 else if (true_code == NE && ! side_effects_p (cond)
04875 && !HONOR_NANS (mode)
04876 && rtx_equal_p (XEXP (cond, 0), true_rtx)
04877 && rtx_equal_p (XEXP (cond, 1), false_rtx))
04878 return true_rtx;
04879
04880
04881
04882 if (GET_MODE_CLASS (mode) == MODE_INT
04883 && GET_CODE (false_rtx) == NEG
04884 && rtx_equal_p (true_rtx, XEXP (false_rtx, 0))
04885 && comparison_p
04886 && rtx_equal_p (true_rtx, XEXP (cond, 0))
04887 && ! side_effects_p (true_rtx))
04888 switch (true_code)
04889 {
04890 case GT:
04891 case GE:
04892 return simplify_gen_unary (ABS, mode, true_rtx, mode);
04893 case LT:
04894 case LE:
04895 return
04896 simplify_gen_unary (NEG, mode,
04897 simplify_gen_unary (ABS, mode, true_rtx, mode),
04898 mode);
04899 default:
04900 break;
04901 }
04902
04903
04904
04905 if ((! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
04906 && comparison_p
04907 && rtx_equal_p (XEXP (cond, 0), true_rtx)
04908 && rtx_equal_p (XEXP (cond, 1), false_rtx)
04909 && ! side_effects_p (cond))
04910 switch (true_code)
04911 {
04912 case GE:
04913 case GT:
04914 return simplify_gen_binary (SMAX, mode, true_rtx, false_rtx);
04915 case LE:
04916 case LT:
04917 return simplify_gen_binary (SMIN, mode, true_rtx, false_rtx);
04918 case GEU:
04919 case GTU:
04920 return simplify_gen_binary (UMAX, mode, true_rtx, false_rtx);
04921 case LEU:
04922 case LTU:
04923 return simplify_gen_binary (UMIN, mode, true_rtx, false_rtx);
04924 default:
04925 break;
04926 }
04927
04928
04929
04930
04931
04932
04933
04934
04935 if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
04936 && comparison_p
04937 && GET_MODE_CLASS (mode) == MODE_INT
04938 && ! side_effects_p (x))
04939 {
04940 rtx t = make_compound_operation (true_rtx, SET);
04941 rtx f = make_compound_operation (false_rtx, SET);
04942 rtx cond_op0 = XEXP (cond, 0);
04943 rtx cond_op1 = XEXP (cond, 1);
04944 enum rtx_code op = UNKNOWN, extend_op = UNKNOWN;
04945 enum machine_mode m = mode;
04946 rtx z = 0, c1 = NULL_RTX;
04947
04948 if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
04949 || GET_CODE (t) == IOR || GET_CODE (t) == XOR
04950 || GET_CODE (t) == ASHIFT
04951 || GET_CODE (t) == LSHIFTRT || GET_CODE (t) == ASHIFTRT)
04952 && rtx_equal_p (XEXP (t, 0), f))
04953 c1 = XEXP (t, 1), op = GET_CODE (t), z = f;
04954
04955
04956
04957 else if ((GET_CODE (t) == PLUS || GET_CODE (t) == IOR
04958 || GET_CODE (t) == XOR)
04959 && rtx_equal_p (XEXP (t, 1), f))
04960 c1 = XEXP (t, 0), op = GET_CODE (t), z = f;
04961 else if (GET_CODE (t) == SIGN_EXTEND
04962 && (GET_CODE (XEXP (t, 0)) == PLUS
04963 || GET_CODE (XEXP (t, 0)) == MINUS
04964 || GET_CODE (XEXP (t, 0)) == IOR
04965 || GET_CODE (XEXP (t, 0)) == XOR
04966 || GET_CODE (XEXP (t, 0)) == ASHIFT
04967 || GET_CODE (XEXP (t, 0)) == LSHIFTRT
04968 || GET_CODE (XEXP (t, 0)) == ASHIFTRT)
04969 && GET_CODE (XEXP (XEXP (t, 0), 0)) == SUBREG
04970 && subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
04971 && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
04972 && (num_sign_bit_copies (f, GET_MODE (f))
04973 > (unsigned int)
04974 (GET_MODE_BITSIZE (mode)
04975 - GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 0))))))
04976 {
04977 c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
04978 extend_op = SIGN_EXTEND;
04979 m = GET_MODE (XEXP (t, 0));
04980 }
04981 else if (GET_CODE (t) == SIGN_EXTEND
04982 && (GET_CODE (XEXP (t, 0)) == PLUS
04983 || GET_CODE (XEXP (t, 0)) == IOR
04984 || GET_CODE (XEXP (t, 0)) == XOR)
04985 && GET_CODE (XEXP (XEXP (t, 0), 1)) == SUBREG
04986 && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
04987 && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
04988 && (num_sign_bit_copies (f, GET_MODE (f))
04989 > (unsigned int)
04990 (GET_MODE_BITSIZE (mode)
04991 - GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 1))))))
04992 {
04993 c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
04994 extend_op = SIGN_EXTEND;
04995 m = GET_MODE (XEXP (t, 0));
04996 }
04997 else if (GET_CODE (t) == ZERO_EXTEND
04998 && (GET_CODE (XEXP (t, 0)) == PLUS
04999 || GET_CODE (XEXP (t, 0)) == MINUS
05000 || GET_CODE (XEXP (t, 0)) == IOR
05001 || GET_CODE (XEXP (t, 0)) == XOR
05002 || GET_CODE (XEXP (t, 0)) == ASHIFT
05003 || GET_CODE (XEXP (t, 0)) == LSHIFTRT
05004 || GET_CODE (XEXP (t, 0)) == ASHIFTRT)
05005 && GET_CODE (XEXP (XEXP (t, 0), 0)) == SUBREG
05006 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05007 && subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
05008 && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
05009 && ((nonzero_bits (f, GET_MODE (f))
05010 & ~GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 0))))
05011 == 0))
05012 {
05013 c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
05014 extend_op = ZERO_EXTEND;
05015 m = GET_MODE (XEXP (t, 0));
05016 }
05017 else if (GET_CODE (t) == ZERO_EXTEND
05018 && (GET_CODE (XEXP (t, 0)) == PLUS
05019 || GET_CODE (XEXP (t, 0)) == IOR
05020 || GET_CODE (XEXP (t, 0)) == XOR)
05021 && GET_CODE (XEXP (XEXP (t, 0), 1)) == SUBREG
05022 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05023 && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
05024 && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
05025 && ((nonzero_bits (f, GET_MODE (f))
05026 & ~GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 1))))
05027 == 0))
05028 {
05029 c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
05030 extend_op = ZERO_EXTEND;
05031 m = GET_MODE (XEXP (t, 0));
05032 }
05033
05034 if (z)
05035 {
05036 temp = subst (simplify_gen_relational (true_code, m, VOIDmode,
05037 cond_op0, cond_op1),
05038 pc_rtx, pc_rtx, 0, 0);
05039 temp = simplify_gen_binary (MULT, m, temp,
05040 simplify_gen_binary (MULT, m, c1,
05041 const_true_rtx));
05042 temp = subst (temp, pc_rtx, pc_rtx, 0, 0);
05043 temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
05044
05045 if (extend_op != UNKNOWN)
05046 temp = simplify_gen_unary (extend_op, mode, temp, m);
05047
05048 return temp;
05049 }
05050 }
05051
05052
05053
05054
05055
05056
05057 if (true_code == NE && XEXP (cond, 1) == const0_rtx
05058 && false_rtx == const0_rtx && GET_CODE (true_rtx) == CONST_INT
05059 && ((1 == nonzero_bits (XEXP (cond, 0), mode)
05060 && (i = exact_log2 (INTVAL (true_rtx))) >= 0)
05061 || ((num_sign_bit_copies (XEXP (cond, 0), mode)
05062 == GET_MODE_BITSIZE (mode))
05063 && (i = exact_log2 (-INTVAL (true_rtx))) >= 0)))
05064 return
05065 simplify_shift_const (NULL_RTX, ASHIFT, mode,
05066 gen_lowpart (mode, XEXP (cond, 0)), i);
05067
05068
05069 if (true_code == NE && XEXP (cond, 1) == const0_rtx
05070 && false_rtx == const0_rtx && GET_CODE (true_rtx) == CONST_INT
05071 && GET_MODE (XEXP (cond, 0)) == mode
05072 && (INTVAL (true_rtx) & GET_MODE_MASK (mode))
05073 == nonzero_bits (XEXP (cond, 0), mode)
05074 && (i = exact_log2 (INTVAL (true_rtx) & GET_MODE_MASK (mode))) >= 0)
05075 return XEXP (cond, 0);
05076
05077 return x;
05078 }
05079
05080
05081
05082 static rtx
05083 simplify_set (rtx x)
05084 {
05085 rtx src = SET_SRC (x);
05086 rtx dest = SET_DEST (x);
05087 enum machine_mode mode
05088 = GET_MODE (src) != VOIDmode ? GET_MODE (src) : GET_MODE (dest);
05089 rtx other_insn;
05090 rtx *cc_use;
05091
05092
05093 if (GET_CODE (dest) == PC && GET_CODE (src) == RETURN)
05094 return src;
05095
05096
05097
05098
05099
05100 if (GET_MODE_CLASS (mode) == MODE_INT
05101 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
05102 {
05103 src = force_to_mode (src, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
05104 SUBST (SET_SRC (x), src);
05105 }
05106
05107
05108
05109
05110 if ((GET_MODE_CLASS (mode) == MODE_CC
05111 || GET_CODE (src) == COMPARE
05112 || CC0_P (dest))
05113 && (cc_use = find_single_use (dest, subst_insn, &other_insn)) != 0
05114 && (undobuf.other_insn == 0 || other_insn == undobuf.other_insn)
05115 && COMPARISON_P (*cc_use)
05116 && rtx_equal_p (XEXP (*cc_use, 0), dest))
05117 {
05118 enum rtx_code old_code = GET_CODE (*cc_use);
05119 enum rtx_code new_code;
05120 rtx op0, op1, tmp;
05121 int other_changed = 0;
05122 enum machine_mode compare_mode = GET_MODE (dest);
05123
05124 if (GET_CODE (src) == COMPARE)
05125 op0 = XEXP (src, 0), op1 = XEXP (src, 1);
05126 else
05127 op0 = src, op1 = CONST0_RTX (GET_MODE (src));
05128
05129 tmp = simplify_relational_operation (old_code, compare_mode, VOIDmode,
05130 op0, op1);
05131 if (!tmp)
05132 new_code = old_code;
05133 else if (!CONSTANT_P (tmp))
05134 {
05135 new_code = GET_CODE (tmp);
05136 op0 = XEXP (tmp, 0);
05137 op1 = XEXP (tmp, 1);
05138 }
05139 else
05140 {
05141 rtx pat = PATTERN (other_insn);
05142 undobuf.other_insn = other_insn;
05143 SUBST (*cc_use, tmp);
05144
05145
05146 if (GET_CODE (pat) == SET)
05147 {
05148 rtx new = simplify_rtx (SET_SRC (pat));
05149 if (new != NULL_RTX)
05150 SUBST (SET_SRC (pat), new);
05151 }
05152
05153
05154 SUBST (SET_DEST (x), pc_rtx);
05155 SUBST (SET_SRC (x), pc_rtx);
05156 return x;
05157 }
05158
05159
05160 new_code = simplify_comparison (new_code, &op0, &op1);
05161
05162 #ifdef SELECT_CC_MODE
05163
05164
05165 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
05166 compare_mode = GET_MODE (op0);
05167 else
05168 compare_mode = SELECT_CC_MODE (new_code, op0, op1);
05169
05170 #ifndef HAVE_cc0
05171
05172
05173
05174
05175
05176 if (compare_mode != GET_MODE (dest))
05177 {
05178 unsigned int regno = REGNO (dest);
05179 rtx new_dest = gen_rtx_REG (compare_mode, regno);
05180
05181 if (regno < FIRST_PSEUDO_REGISTER
05182 || (REG_N_SETS (regno) == 1 && ! REG_USERVAR_P (dest)))
05183 {
05184 if (regno >= FIRST_PSEUDO_REGISTER)
05185 SUBST (regno_reg_rtx[regno], new_dest);
05186
05187 SUBST (SET_DEST (x), new_dest);
05188 SUBST (XEXP (*cc_use, 0), new_dest);
05189 other_changed = 1;
05190
05191 dest = new_dest;
05192 }
05193 }
05194 #endif
05195 #endif
05196
05197
05198
05199 if (new_code != old_code)
05200 {
05201 int other_changed_previously = other_changed;
05202 unsigned HOST_WIDE_INT mask;
05203
05204 SUBST (*cc_use, gen_rtx_fmt_ee (new_code, GET_MODE (*cc_use),
05205 dest, const0_rtx));
05206 other_changed = 1;
05207
05208
05209
05210
05211
05212
05213
05214 if (((old_code == NE && new_code == EQ)
05215 || (old_code == EQ && new_code == NE))
05216 && ! other_changed_previously && op1 == const0_rtx
05217 && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
05218 && exact_log2 (mask = nonzero_bits (op0, GET_MODE (op0))) >= 0)
05219 {
05220 rtx pat = PATTERN (other_insn), note = 0;
05221
05222 if ((recog_for_combine (&pat, other_insn, ¬e) < 0
05223 && ! check_asm_operands (pat)))
05224 {
05225 PUT_CODE (*cc_use, old_code);
05226 other_changed = 0;
05227
05228 op0 = simplify_gen_binary (XOR, GET_MODE (op0),
05229 op0, GEN_INT (mask));
05230 }
05231 }
05232 }
05233
05234 if (other_changed)
05235 undobuf.other_insn = other_insn;
05236
05237 #ifdef HAVE_cc0
05238
05239
05240 if (op1 == const0_rtx && dest == cc0_rtx)
05241 {
05242 SUBST (SET_SRC (x), op0);
05243 src = op0;
05244 }
05245 else
05246 #endif
05247
05248
05249
05250 if (GET_CODE (src) != COMPARE || GET_MODE (src) != compare_mode)
05251 {
05252 SUBST (SET_SRC (x), gen_rtx_COMPARE (compare_mode, op0, op1));
05253 src = SET_SRC (x);
05254 }
05255 else
05256 {
05257
05258 SUBST (XEXP (src, 0), op0);
05259 SUBST (XEXP (src, 1), op1);
05260 }
05261 }
05262 else
05263 {
05264
05265
05266 src = make_compound_operation (src, SET);
05267 SUBST (SET_SRC (x), src);
05268 }
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282 if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
05283 && !OBJECT_P (SUBREG_REG (src))
05284 && (((GET_MODE_SIZE (GET_MODE (src)) + (UNITS_PER_WORD - 1))
05285 / UNITS_PER_WORD)
05286 == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
05287 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))
05288 #ifndef WORD_REGISTER_OPERATIONS
05289 && (GET_MODE_SIZE (GET_MODE (src))
05290 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
05291 #endif
05292 #ifdef CANNOT_CHANGE_MODE_CLASS
05293 && ! (REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER
05294 && REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
05295 GET_MODE (SUBREG_REG (src)),
05296 GET_MODE (src)))
05297 #endif
05298 && (REG_P (dest)
05299 || (GET_CODE (dest) == SUBREG
05300 && REG_P (SUBREG_REG (dest)))))
05301 {
05302 SUBST (SET_DEST (x),
05303 gen_lowpart (GET_MODE (SUBREG_REG (src)),
05304 dest));
05305 SUBST (SET_SRC (x), SUBREG_REG (src));
05306
05307 src = SET_SRC (x), dest = SET_DEST (x);
05308 }
05309
05310 #ifdef HAVE_cc0
05311
05312
05313 if (dest == cc0_rtx
05314 && GET_CODE (src) == SUBREG
05315 && subreg_lowpart_p (src)
05316 && (GET_MODE_BITSIZE (GET_MODE (src))
05317 < GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (src)))))
05318 {
05319 rtx inner = SUBREG_REG (src);
05320 enum machine_mode inner_mode = GET_MODE (inner);
05321
05322
05323 if (GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_WIDE_INT
05324 && (nonzero_bits (inner, inner_mode)
05325 < ((unsigned HOST_WIDE_INT) 1
05326 << (GET_MODE_BITSIZE (GET_MODE (src)) - 1))))
05327 {
05328 SUBST (SET_SRC (x), inner);
05329 src = SET_SRC (x);
05330 }
05331 }
05332 #endif
05333
05334 #ifdef LOAD_EXTEND_OP
05335
05336
05337
05338
05339 if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
05340 && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != UNKNOWN
05341 && SUBREG_BYTE (src) == 0
05342 && (GET_MODE_SIZE (GET_MODE (src))
05343 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
05344 && MEM_P (SUBREG_REG (src)))
05345 {
05346 SUBST (SET_SRC (x),
05347 gen_rtx_fmt_e (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
05348 GET_MODE (src), SUBREG_REG (src)));
05349
05350 src = SET_SRC (x);
05351 }
05352 #endif
05353
05354
05355
05356
05357
05358
05359
05360 if (GET_CODE (dest) != PC
05361 && GET_CODE (src) == IF_THEN_ELSE
05362 && GET_MODE_CLASS (GET_MODE (src)) == MODE_INT
05363 && (GET_CODE (XEXP (src, 0)) == EQ || GET_CODE (XEXP (src, 0)) == NE)
05364 && XEXP (XEXP (src, 0), 1) == const0_rtx
05365 && GET_MODE (src) == GET_MODE (XEXP (XEXP (src, 0), 0))
05366 #ifdef HAVE_conditional_move
05367 && ! can_conditionally_move_p (GET_MODE (src))
05368 #endif
05369 && (num_sign_bit_copies (XEXP (XEXP (src, 0), 0),
05370 GET_MODE (XEXP (XEXP (src, 0), 0)))
05371 == GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (src, 0), 0))))
05372 && ! side_effects_p (src))
05373 {
05374 rtx true_rtx = (GET_CODE (XEXP (src, 0)) == NE
05375 ? XEXP (src, 1) : XEXP (src, 2));
05376 rtx false_rtx = (GET_CODE (XEXP (src, 0)) == NE
05377 ? XEXP (src, 2) : XEXP (src, 1));
05378 rtx term1 = const0_rtx, term2, term3;
05379
05380 if (GET_CODE (true_rtx) == IOR
05381 && rtx_equal_p (XEXP (true_rtx, 0), false_rtx))
05382 term1 = false_rtx, true_rtx = XEXP (true_rtx, 1), false_rtx = const0_rtx;
05383 else if (GET_CODE (true_rtx) == IOR
05384 && rtx_equal_p (XEXP (true_rtx, 1), false_rtx))
05385 term1 = false_rtx, true_rtx = XEXP (true_rtx, 0), false_rtx = const0_rtx;
05386 else if (GET_CODE (false_rtx) == IOR
05387 && rtx_equal_p (XEXP (false_rtx, 0), true_rtx))
05388 term1 = true_rtx, false_rtx = XEXP (false_rtx, 1), true_rtx = const0_rtx;
05389 else if (GET_CODE (false_rtx) == IOR
05390 && rtx_equal_p (XEXP (false_rtx, 1), true_rtx))
05391 term1 = true_rtx, false_rtx = XEXP (false_rtx, 0), true_rtx = const0_rtx;
05392
05393 term2 = simplify_gen_binary (AND, GET_MODE (src),
05394 XEXP (XEXP (src, 0), 0), true_rtx);
05395 term3 = simplify_gen_binary (AND, GET_MODE (src),
05396 simplify_gen_unary (NOT, GET_MODE (src),
05397 XEXP (XEXP (src, 0), 0),
05398 GET_MODE (src)),
05399 false_rtx);
05400
05401 SUBST (SET_SRC (x),
05402 simplify_gen_binary (IOR, GET_MODE (src),
05403 simplify_gen_binary (IOR, GET_MODE (src),
05404 term1, term2),
05405 term3));
05406
05407 src = SET_SRC (x);
05408 }
05409
05410
05411
05412 if (GET_CODE (src) == CLOBBER && XEXP (src, 0) == const0_rtx)
05413 return src;
05414 else if (GET_CODE (dest) == CLOBBER && XEXP (dest, 0) == const0_rtx)
05415 return dest;
05416 else
05417
05418 return make_field_assignment (x);
05419 }
05420
05421
05422
05423
05424 static rtx
05425 simplify_logical (rtx x)
05426 {
05427 enum machine_mode mode = GET_MODE (x);
05428 rtx op0 = XEXP (x, 0);
05429 rtx op1 = XEXP (x, 1);
05430 rtx reversed;
05431
05432 switch (GET_CODE (x))
05433 {
05434 case AND:
05435
05436
05437 if (GET_CODE (op0) == XOR
05438 && rtx_equal_p (XEXP (op0, 0), op1)
05439 && ! side_effects_p (op1))
05440 x = simplify_gen_binary (AND, mode,
05441 simplify_gen_unary (NOT, mode,
05442 XEXP (op0, 1), mode),
05443 op1);
05444
05445 if (GET_CODE (op0) == XOR
05446 && rtx_equal_p (XEXP (op0, 1), op1)
05447 && ! side_effects_p (op1))
05448 x = simplify_gen_binary (AND, mode,
05449 simplify_gen_unary (NOT, mode,
05450 XEXP (op0, 0), mode),
05451 op1);
05452
05453
05454 if (GET_CODE (op0) == NOT
05455 && GET_CODE (XEXP (op0, 0)) == XOR
05456 && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1)
05457 && ! side_effects_p (op1))
05458 x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1);
05459
05460 if (GET_CODE (op0) == NOT
05461 && GET_CODE (XEXP (op0, 0)) == XOR
05462 && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1)
05463 && ! side_effects_p (op1))
05464 x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1);
05465
05466
05467
05468
05469 if (GET_CODE (op1) == CONST_INT
05470 && (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05471 || INTVAL (op1) > 0))
05472 {
05473 x = simplify_and_const_int (x, mode, op0, INTVAL (op1));
05474
05475
05476
05477
05478
05479
05480 if (GET_CODE (x) == IOR && GET_CODE (op0) == AND
05481 && GET_CODE (XEXP (op0, 1)) == CONST_INT
05482 && GET_CODE (op1) == CONST_INT
05483 && (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0)
05484 return simplify_gen_binary (IOR, mode,
05485 simplify_gen_binary
05486 (AND, mode, XEXP (op0, 0),
05487 GEN_INT (INTVAL (XEXP (op0, 1))
05488 & ~INTVAL (op1))), op1);
05489
05490 if (GET_CODE (x) != AND)
05491 return x;
05492
05493 op0 = XEXP (x, 0);
05494 op1 = XEXP (x, 1);
05495 }
05496
05497
05498 if (GET_CODE (op0) == IOR
05499 && (rtx_equal_p (XEXP (op0, 0), op1)
05500 || rtx_equal_p (XEXP (op0, 1), op1))
05501 && ! side_effects_p (XEXP (op0, 0))
05502 && ! side_effects_p (XEXP (op0, 1)))
05503 return op1;
05504
05505
05506
05507
05508 if (GET_CODE (op0) == IOR || GET_CODE (op0) == XOR)
05509 {
05510 rtx result = distribute_and_simplify_rtx (x, 0);
05511 if (result)
05512 return result;
05513 }
05514 if (GET_CODE (op1) == IOR || GET_CODE (op1) == XOR)
05515 {
05516 rtx result = distribute_and_simplify_rtx (x, 1);
05517 if (result)
05518 return result;
05519 }
05520 break;
05521
05522 case IOR:
05523
05524 if (GET_CODE (op1) == CONST_INT
05525 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05526 && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0)
05527 return op1;
05528
05529
05530 if (GET_CODE (op0) == AND
05531 && (rtx_equal_p (XEXP (op0, 0), op1)
05532 || rtx_equal_p (XEXP (op0, 1), op1))
05533 && ! side_effects_p (XEXP (op0, 0))
05534 && ! side_effects_p (XEXP (op0, 1)))
05535 return op1;
05536
05537
05538
05539
05540 if (GET_CODE (op0) == AND)
05541 {
05542 rtx result = distribute_and_simplify_rtx (x, 0);
05543 if (result)
05544 return result;
05545 }
05546
05547 if (GET_CODE (op1) == AND)
05548 {
05549 rtx result = distribute_and_simplify_rtx (x, 1);
05550 if (result)
05551 return result;
05552 }
05553
05554
05555
05556
05557 if (((GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
05558 || (GET_CODE (op1) == ASHIFT && GET_CODE (op0) == LSHIFTRT))
05559 && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
05560 && GET_CODE (XEXP (op0, 1)) == CONST_INT
05561 && GET_CODE (XEXP (op1, 1)) == CONST_INT
05562 && (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1))
05563 == GET_MODE_BITSIZE (mode)))
05564 return gen_rtx_ROTATE (mode, XEXP (op0, 0),
05565 (GET_CODE (op0) == ASHIFT
05566 ? XEXP (op0, 1) : XEXP (op1, 1)));
05567
05568
05569
05570
05571
05572
05573 if (GET_CODE (op1) == CONST_INT && GET_CODE (op0) == ASHIFTRT
05574 && GET_CODE (XEXP (op0, 0)) == PLUS
05575 && GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT
05576 && GET_CODE (XEXP (op0, 1)) == CONST_INT
05577 && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT)
05578 {
05579 int count = INTVAL (XEXP (op0, 1));
05580 HOST_WIDE_INT mask = INTVAL (op1) << count;
05581
05582 if (mask >> count == INTVAL (op1)
05583 && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0)
05584 {
05585 SUBST (XEXP (XEXP (op0, 0), 1),
05586 GEN_INT (INTVAL (XEXP (XEXP (op0, 0), 1)) | mask));
05587 return op0;
05588 }
05589 }
05590 break;
05591
05592 case XOR:
05593
05594
05595
05596
05597 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05598 && (nonzero_bits (op0, mode)
05599 & nonzero_bits (op1, mode)) == 0)
05600 return (simplify_gen_binary (IOR, mode, op0, op1));
05601
05602
05603
05604
05605 {
05606 int num_negated = 0;
05607
05608 if (GET_CODE (op0) == NOT)
05609 num_negated++, op0 = XEXP (op0, 0);
05610 if (GET_CODE (op1) == NOT)
05611 num_negated++, op1 = XEXP (op1, 0);
05612
05613 if (num_negated == 2)
05614 {
05615 SUBST (XEXP (x, 0), op0);
05616 SUBST (XEXP (x, 1), op1);
05617 }
05618 else if (num_negated == 1)
05619 return
05620 simplify_gen_unary (NOT, mode,
05621 simplify_gen_binary (XOR, mode, op0, op1),
05622 mode);
05623 }
05624
05625
05626
05627
05628
05629 if (GET_CODE (op0) == AND
05630 && rtx_equal_p (XEXP (op0, 1), op1)
05631 && ! side_effects_p (op1))
05632 return simplify_gen_binary (AND, mode,
05633 simplify_gen_unary (NOT, mode,
05634 XEXP (op0, 0), mode),
05635 op1);
05636
05637 else if (GET_CODE (op0) == AND
05638 && rtx_equal_p (XEXP (op0, 0), op1)
05639 && ! side_effects_p (op1))
05640 return simplify_gen_binary (AND, mode,
05641 simplify_gen_unary (NOT, mode,
05642 XEXP (op0, 1), mode),
05643 op1);
05644
05645
05646
05647 if (STORE_FLAG_VALUE == 1
05648 && op1 == const1_rtx
05649 && COMPARISON_P (op0)
05650 && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
05651 XEXP (op0, 1))))
05652 return reversed;
05653
05654
05655
05656
05657
05658 if (STORE_FLAG_VALUE == 1
05659 && op1 == const1_rtx
05660 && GET_CODE (op0) == LSHIFTRT
05661 && GET_CODE (XEXP (op0, 1)) == CONST_INT
05662 && INTVAL (XEXP (op0, 1)) == GET_MODE_BITSIZE (mode) - 1)
05663 return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx);
05664
05665
05666
05667 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05668 && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
05669 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
05670 && op1 == const_true_rtx
05671 && COMPARISON_P (op0)
05672 && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
05673 XEXP (op0, 1))))
05674 return reversed;
05675
05676 break;
05677
05678 default:
05679 gcc_unreachable ();
05680 }
05681
05682 return x;
05683 }
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698 static rtx
05699 expand_compound_operation (rtx x)
05700 {
05701 unsigned HOST_WIDE_INT pos = 0, len;
05702 int unsignedp = 0;
05703 unsigned int modewidth;
05704 rtx tem;
05705
05706 switch (GET_CODE (x))
05707 {
05708 case ZERO_EXTEND:
05709 unsignedp = 1;
05710 case SIGN_EXTEND:
05711
05712
05713
05714
05715
05716
05717
05718
05719 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
05720 return x;
05721
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731 if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) > UNITS_PER_WORD)
05732 return x;
05733
05734
05735
05736
05737 if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
05738 return x;
05739
05740 len = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)));
05741
05742
05743
05744 if (len == 0)
05745 return x;
05746
05747 break;
05748
05749 case ZERO_EXTRACT:
05750 unsignedp = 1;
05751
05752
05753
05754 case SIGN_EXTRACT:
05755
05756 if (GET_CODE (XEXP (x, 0)) == CLOBBER)
05757 return XEXP (x, 0);
05758
05759 if (GET_CODE (XEXP (x, 1)) != CONST_INT
05760 || GET_CODE (XEXP (x, 2)) != CONST_INT
05761 || GET_MODE (XEXP (x, 0)) == VOIDmode)
05762 return x;
05763
05764
05765
05766
05767 if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
05768 return x;
05769
05770 len = INTVAL (XEXP (x, 1));
05771 pos = INTVAL (XEXP (x, 2));
05772
05773
05774
05775
05776 if (len + pos > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
05777 SUBST (XEXP (x, 0), gen_rtx_USE (GET_MODE (x), XEXP (x, 0)));
05778
05779 if (BITS_BIG_ENDIAN)
05780 pos = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - len - pos;
05781
05782 break;
05783
05784 default:
05785 return x;
05786 }
05787
05788
05789
05790 if (GET_CODE (x) == SIGN_EXTEND
05791 && (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
05792 && ((nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
05793 & ~(((unsigned HOST_WIDE_INT)
05794 GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
05795 >> 1))
05796 == 0)))
05797 {
05798 rtx temp = gen_rtx_ZERO_EXTEND (GET_MODE (x), XEXP (x, 0));
05799 rtx temp2 = expand_compound_operation (temp);
05800
05801
05802 if (rtx_cost (x, SET) > rtx_cost (temp2, SET))
05803 return temp2;
05804 else if (rtx_cost (x, SET) > rtx_cost (temp, SET))
05805 return temp;
05806 else
05807 return x;
05808 }
05809
05810
05811 if (GET_CODE (x) == ZERO_EXTEND)
05812 {
05813
05814
05815
05816 if (GET_CODE (XEXP (x, 0)) == TRUNCATE
05817 && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
05818 && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
05819 && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x))
05820 & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
05821 return XEXP (XEXP (x, 0), 0);
05822
05823
05824 if (GET_CODE (XEXP (x, 0)) == SUBREG
05825 && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
05826 && subreg_lowpart_p (XEXP (x, 0))
05827 && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
05828 && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x))
05829 & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
05830 return SUBREG_REG (XEXP (x, 0));
05831
05832
05833
05834
05835
05836 if (GET_CODE (XEXP (x, 0)) == TRUNCATE
05837 && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
05838 && COMPARISON_P (XEXP (XEXP (x, 0), 0))
05839 && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
05840 <= HOST_BITS_PER_WIDE_INT)
05841 && ((HOST_WIDE_INT) STORE_FLAG_VALUE
05842 & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
05843 return XEXP (XEXP (x, 0), 0);
05844
05845
05846 if (GET_CODE (XEXP (x, 0)) == SUBREG
05847 && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
05848 && subreg_lowpart_p (XEXP (x, 0))
05849 && COMPARISON_P (SUBREG_REG (XEXP (x, 0)))
05850 && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
05851 <= HOST_BITS_PER_WIDE_INT)
05852 && ((HOST_WIDE_INT) STORE_FLAG_VALUE
05853 & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
05854 return SUBREG_REG (XEXP (x, 0));
05855
05856 }
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873 modewidth = GET_MODE_BITSIZE (GET_MODE (x));
05874 if (modewidth + len >= pos)
05875 tem = simplify_shift_const (NULL_RTX, unsignedp ? LSHIFTRT : ASHIFTRT,
05876 GET_MODE (x),
05877 simplify_shift_const (NULL_RTX, ASHIFT,
05878 GET_MODE (x),
05879 XEXP (x, 0),
05880 modewidth - pos - len),
05881 modewidth - len);
05882
05883 else if (unsignedp && len < HOST_BITS_PER_WIDE_INT)
05884 tem = simplify_and_const_int (NULL_RTX, GET_MODE (x),
05885 simplify_shift_const (NULL_RTX, LSHIFTRT,
05886 GET_MODE (x),
05887 XEXP (x, 0), pos),
05888 ((HOST_WIDE_INT) 1 << len) - 1);
05889 else
05890
05891 return x;
05892
05893
05894
05895 if (GET_CODE (tem) == CLOBBER)
05896 return x;
05897
05898 return tem;
05899 }
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909 static rtx
05910 expand_field_assignment (rtx x)
05911 {
05912 rtx inner;
05913 rtx pos;
05914 int len;
05915 rtx mask, cleared, masked;
05916 enum machine_mode compute_mode;
05917
05918
05919 while (1)
05920 {
05921 if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
05922 && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG)
05923 {
05924 inner = SUBREG_REG (XEXP (SET_DEST (x), 0));
05925 len = GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0)));
05926 pos = GEN_INT (subreg_lsb (XEXP (SET_DEST (x), 0)));
05927 }
05928 else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
05929 && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
05930 {
05931 inner = XEXP (SET_DEST (x), 0);
05932 len = INTVAL (XEXP (SET_DEST (x), 1));
05933 pos = XEXP (SET_DEST (x), 2);
05934
05935
05936
05937 if (GET_CODE (pos) == CONST_INT
05938 && INTVAL (pos) + len > GET_MODE_BITSIZE (GET_MODE (inner)))
05939 inner = gen_rtx_USE (GET_MODE (SET_DEST (x)), inner);
05940
05941 if (BITS_BIG_ENDIAN)
05942 {
05943 if (GET_CODE (pos) == CONST_INT)
05944 pos = GEN_INT (GET_MODE_BITSIZE (GET_MODE (inner)) - len
05945 - INTVAL (pos));
05946 else if (GET_CODE (pos) == MINUS
05947 && GET_CODE (XEXP (pos, 1)) == CONST_INT
05948 && (INTVAL (XEXP (pos, 1))
05949 == GET_MODE_BITSIZE (GET_MODE (inner)) - len))
05950
05951 pos = XEXP (pos, 0);
05952 else
05953 pos = simplify_gen_binary (MINUS, GET_MODE (pos),
05954 GEN_INT (GET_MODE_BITSIZE (
05955 GET_MODE (inner))
05956 - len),
05957 pos);
05958 }
05959 }
05960
05961
05962
05963 else if (GET_CODE (SET_DEST (x)) == SUBREG
05964
05965 && nonzero_sign_valid
05966 && (((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
05967 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
05968 == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
05969 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
05970 {
05971 x = gen_rtx_SET (VOIDmode, SUBREG_REG (SET_DEST (x)),
05972 gen_lowpart
05973 (GET_MODE (SUBREG_REG (SET_DEST (x))),
05974 SET_SRC (x)));
05975 continue;
05976 }
05977 else
05978 break;
05979
05980 while (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner))
05981 inner = SUBREG_REG (inner);
05982
05983 compute_mode = GET_MODE (inner);
05984
05985
05986 if (! SCALAR_INT_MODE_P (compute_mode))
05987 {
05988 enum machine_mode imode;
05989
05990
05991 if (! FLOAT_MODE_P (compute_mode))
05992 break;
05993
05994
05995 imode = mode_for_size (GET_MODE_BITSIZE (compute_mode), MODE_INT, 0);
05996 if (imode == BLKmode)
05997 break;
05998
05999 compute_mode = imode;
06000 inner = gen_lowpart (imode, inner);
06001 }
06002
06003
06004 if (len >= HOST_BITS_PER_WIDE_INT)
06005 break;
06006
06007
06008
06009
06010 mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
06011 cleared = simplify_gen_binary (AND, compute_mode,
06012 simplify_gen_unary (NOT, compute_mode,
06013 simplify_gen_binary (ASHIFT,
06014 compute_mode,
06015 mask, pos),
06016 compute_mode),
06017 inner);
06018 masked = simplify_gen_binary (ASHIFT, compute_mode,
06019 simplify_gen_binary (
06020 AND, compute_mode,
06021 gen_lowpart (compute_mode, SET_SRC (x)),
06022 mask),
06023 pos);
06024
06025 x = gen_rtx_SET (VOIDmode, copy_rtx (inner),
06026 simplify_gen_binary (IOR, compute_mode,
06027 cleared, masked));
06028 }
06029
06030 return x;
06031 }
06032
06033
06034
06035
06036
06037
06038
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060 static rtx
06061 make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
06062 rtx pos_rtx, unsigned HOST_WIDE_INT len, int unsignedp,
06063 int in_dest, int in_compare)
06064 {
06065
06066
06067
06068 enum machine_mode is_mode = GET_MODE (inner);
06069 enum machine_mode inner_mode;
06070 enum machine_mode wanted_inner_mode = byte_mode;
06071 enum machine_mode wanted_inner_reg_mode = word_mode;
06072 enum machine_mode pos_mode = word_mode;
06073 enum machine_mode extraction_mode = word_mode;
06074 enum machine_mode tmode = mode_for_size (len, MODE_INT, 1);
06075 int spans_byte = 0;
06076 rtx new = 0;
06077 rtx orig_pos_rtx = pos_rtx;
06078 HOST_WIDE_INT orig_pos;
06079
06080
06081 if (GET_CODE (inner) == USE)
06082
06083
06084
06085 spans_byte = 1, inner = XEXP (inner, 0);
06086 else if (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner))
06087 {
06088
06089
06090
06091
06092
06093 if (MEM_P (SUBREG_REG (inner)))
06094 is_mode = GET_MODE (SUBREG_REG (inner));
06095 inner = SUBREG_REG (inner);
06096 }
06097 else if (GET_CODE (inner) == ASHIFT
06098 && GET_CODE (XEXP (inner, 1)) == CONST_INT
06099 && pos_rtx == 0 && pos == 0
06100 && len > (unsigned HOST_WIDE_INT) INTVAL (XEXP (inner, 1)))
06101 {
06102
06103
06104
06105
06106 new = make_extraction (mode, XEXP (inner, 0),
06107 0, 0, len - INTVAL (XEXP (inner, 1)),
06108 unsignedp, in_dest, in_compare);
06109 if (new != 0)
06110 return gen_rtx_ASHIFT (mode, new, XEXP (inner, 1));
06111 }
06112
06113 inner_mode = GET_MODE (inner);
06114
06115 if (pos_rtx && GET_CODE (pos_rtx) == CONST_INT)
06116 pos = INTVAL (pos_rtx), pos_rtx = 0;
06117
06118
06119
06120
06121
06122
06123
06124
06125
06126
06127
06128
06129
06130
06131 if (tmode != BLKmode
06132 && ! (spans_byte && inner_mode != tmode)
06133 && ((pos_rtx == 0 && (pos % BITS_PER_WORD) == 0
06134 && !MEM_P (inner)
06135 && (! in_dest
06136 || (REG_P (inner)
06137 && have_insn_for (STRICT_LOW_PART, tmode))))
06138 || (MEM_P (inner) && pos_rtx == 0
06139 && (pos
06140 % (STRICT_ALIGNMENT ? GET_MODE_ALIGNMENT (tmode)
06141 : BITS_PER_UNIT)) == 0
06142
06143
06144 && GET_MODE_BITSIZE (inner_mode) >= GET_MODE_BITSIZE (tmode)
06145 && (inner_mode == tmode
06146 || (! mode_dependent_address_p (XEXP (inner, 0))
06147 && ! MEM_VOLATILE_P (inner))))))
06148 {
06149
06150
06151
06152
06153
06154
06155
06156 if (MEM_P (inner))
06157 {
06158 HOST_WIDE_INT offset;
06159
06160
06161 if (BYTES_BIG_ENDIAN)
06162 offset = (GET_MODE_BITSIZE (is_mode) - len - pos) / BITS_PER_UNIT;
06163 else
06164 offset = pos / BITS_PER_UNIT;
06165
06166 new = adjust_address_nv (inner, tmode, offset);
06167 }
06168 else if (REG_P (inner))
06169 {
06170 if (tmode != inner_mode)
06171 {
06172
06173
06174
06175 if (pos || in_dest)
06176 {
06177 HOST_WIDE_INT final_word = pos / BITS_PER_WORD;
06178
06179 if (WORDS_BIG_ENDIAN
06180 && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD)
06181 final_word = ((GET_MODE_SIZE (inner_mode)
06182 - GET_MODE_SIZE (tmode))
06183 / UNITS_PER_WORD) - final_word;
06184
06185 final_word *= UNITS_PER_WORD;
06186 if (BYTES_BIG_ENDIAN &&
06187 GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (tmode))
06188 final_word += (GET_MODE_SIZE (inner_mode)
06189 - GET_MODE_SIZE (tmode)) % UNITS_PER_WORD;
06190
06191
06192
06193 if (final_word >= GET_MODE_SIZE (inner_mode))
06194 return NULL_RTX;
06195
06196 new = gen_rtx_SUBREG (tmode, inner, final_word);
06197 }
06198 else
06199 new = gen_lowpart (tmode, inner);
06200 }
06201 else
06202 new = inner;
06203 }
06204 else
06205 new = force_to_mode (inner, tmode,
06206 len >= HOST_BITS_PER_WIDE_INT
06207 ? ~(unsigned HOST_WIDE_INT) 0
06208 : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
06209 NULL_RTX, 0);
06210
06211
06212
06213
06214 if (in_dest)
06215 return (MEM_P (new) ? new
06216 : (GET_CODE (new) != SUBREG
06217 ? gen_rtx_CLOBBER (tmode, const0_rtx)
06218 : gen_rtx_STRICT_LOW_PART (VOIDmode, new)));
06219
06220 if (mode == tmode)
06221 return new;
06222
06223 if (GET_CODE (new) == CONST_INT)
06224 return gen_int_mode (INTVAL (new), mode);
06225
06226
06227
06228
06229 if (flag_expensive_optimizations
06230 && (GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
06231 && ((nonzero_bits (new, tmode)
06232 & ~(((unsigned HOST_WIDE_INT)
06233 GET_MODE_MASK (tmode))
06234 >> 1))
06235 == 0)))
06236 {
06237 rtx temp = gen_rtx_ZERO_EXTEND (mode, new);
06238 rtx temp1 = gen_rtx_SIGN_EXTEND (mode, new);
06239
06240
06241
06242 if (rtx_cost (temp, SET) <= rtx_cost (temp1, SET))
06243 return temp;
06244 return temp1;
06245 }
06246
06247
06248
06249
06250 return (gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
06251 mode, new));
06252 }
06253
06254
06255
06256
06257 if (pos_rtx == 0 && pos == 0 && ! in_dest
06258 && ! in_compare && ! spans_byte && unsignedp)
06259 return 0;
06260
06261
06262
06263
06264
06265
06266 if (! spans_byte && MEM_P (inner)
06267 && ((pos_rtx == 0 && pos + len > GET_MODE_BITSIZE (is_mode))
06268 || (pos_rtx != 0 && len != 1)))
06269 return 0;
06270
06271
06272
06273 if (in_dest && mode_for_extraction (EP_insv, -1) != MAX_MACHINE_MODE)
06274 {
06275 wanted_inner_reg_mode = mode_for_extraction (EP_insv, 0);
06276 pos_mode = mode_for_extraction (EP_insv, 2);
06277 extraction_mode = mode_for_extraction (EP_insv, 3);
06278 }
06279
06280 if (! in_dest && unsignedp
06281 && mode_for_extraction (EP_extzv, -1) != MAX_MACHINE_MODE)
06282 {
06283 wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1);
06284 pos_mode = mode_for_extraction (EP_extzv, 3);
06285 extraction_mode = mode_for_extraction (EP_extzv, 0);
06286 }
06287
06288 if (! in_dest && ! unsignedp
06289 && mode_for_extraction (EP_extv, -1) != MAX_MACHINE_MODE)
06290 {
06291 wanted_inner_reg_mode = mode_for_extraction (EP_extv, 1);
06292 pos_mode = mode_for_extraction (EP_extv, 3);
06293 extraction_mode = mode_for_extraction (EP_extv, 0);
06294 }
06295
06296
06297
06298 if (mode != VOIDmode
06299 && GET_MODE_SIZE (extraction_mode) < GET_MODE_SIZE (mode))
06300 extraction_mode = mode;
06301
06302 if (pos_rtx && GET_MODE (pos_rtx) != VOIDmode
06303 && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx)))
06304 pos_mode = GET_MODE (pos_rtx);
06305
06306
06307
06308
06309 if (!MEM_P (inner))
06310 wanted_inner_mode = wanted_inner_reg_mode;
06311 else if (inner_mode != wanted_inner_mode
06312 && (mode_dependent_address_p (XEXP (inner, 0))
06313 || MEM_VOLATILE_P (inner)))
06314 wanted_inner_mode = extraction_mode;
06315
06316 orig_pos = pos;
06317
06318 if (BITS_BIG_ENDIAN)
06319 {
06320
06321
06322
06323
06324
06325
06326
06327 int width = (MEM_P (inner)
06328 ? GET_MODE_BITSIZE (is_mode)
06329 : GET_MODE_BITSIZE (wanted_inner_mode));
06330
06331 if (pos_rtx == 0)
06332 pos = width - len - pos;
06333 else
06334 pos_rtx
06335 = gen_rtx_MINUS (GET_MODE (pos_rtx), GEN_INT (width - len), pos_rtx);
06336
06337
06338 }
06339
06340
06341
06342
06343 if (wanted_inner_mode != VOIDmode
06344 && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode)
06345 && ((MEM_P (inner)
06346 && (inner_mode == wanted_inner_mode
06347 || (! mode_dependent_address_p (XEXP (inner, 0))
06348 && ! MEM_VOLATILE_P (inner))))))
06349 {
06350 int offset = 0;
06351
06352
06353
06354
06355
06356
06357
06358 if (BYTES_BIG_ENDIAN
06359 && ! spans_byte
06360 && GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (is_mode))
06361 offset -= GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (inner_mode);
06362
06363
06364
06365 if (pos_rtx == 0)
06366 {
06367 enum machine_mode bfmode = smallest_mode_for_size (len, MODE_INT);
06368 offset += pos / GET_MODE_BITSIZE (bfmode);
06369 pos %= GET_MODE_BITSIZE (bfmode);
06370 }
06371
06372 if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
06373 && ! spans_byte
06374 && is_mode != wanted_inner_mode)
06375 offset = (GET_MODE_SIZE (is_mode)
06376 - GET_MODE_SIZE (wanted_inner_mode) - offset);
06377
06378 if (offset != 0 || inner_mode != wanted_inner_mode)
06379 inner = adjust_address_nv (inner, wanted_inner_mode, offset);
06380 }
06381
06382
06383
06384
06385 else if (!MEM_P (inner))
06386 {
06387 if (GET_MODE (inner) != wanted_inner_mode
06388 && (pos_rtx != 0
06389 || orig_pos + len > GET_MODE_BITSIZE (wanted_inner_mode)))
06390 return 0;
06391
06392 inner = force_to_mode (inner, wanted_inner_mode,
06393 pos_rtx
06394 || len + orig_pos >= HOST_BITS_PER_WIDE_INT
06395 ? ~(unsigned HOST_WIDE_INT) 0
06396 : ((((unsigned HOST_WIDE_INT) 1 << len) - 1)
06397 << orig_pos),
06398 NULL_RTX, 0);
06399 }
06400
06401
06402
06403 if (pos_rtx != 0
06404 && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx)))
06405 {
06406 rtx temp = gen_rtx_ZERO_EXTEND (pos_mode, pos_rtx);
06407
06408
06409
06410
06411
06412 if (flag_expensive_optimizations
06413 && (GET_MODE_BITSIZE (GET_MODE (pos_rtx)) <= HOST_BITS_PER_WIDE_INT
06414 && ((nonzero_bits (pos_rtx, GET_MODE (pos_rtx))
06415 & ~(((unsigned HOST_WIDE_INT)
06416 GET_MODE_MASK (GET_MODE (pos_rtx)))
06417 >> 1))
06418 == 0)))
06419 {
06420 rtx temp1 = gen_rtx_SIGN_EXTEND (pos_mode, pos_rtx);
06421
06422
06423
06424 if (rtx_cost (temp1, SET) < rtx_cost (temp, SET))
06425 temp = temp1;
06426 }
06427 pos_rtx = temp;
06428 }
06429 else if (pos_rtx != 0
06430 && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx)))
06431 pos_rtx = gen_lowpart (pos_mode, pos_rtx);
06432
06433
06434
06435
06436 if (pos_rtx == 0 && orig_pos_rtx != 0 && INTVAL (orig_pos_rtx) == pos)
06437 pos_rtx = orig_pos_rtx;
06438
06439 else if (pos_rtx == 0)
06440 pos_rtx = GEN_INT (pos);
06441
06442
06443 new = gen_rtx_fmt_eee (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT,
06444 extraction_mode, inner, GEN_INT (len), pos_rtx);
06445 if (! in_dest)
06446 new = gen_lowpart (mode, new);
06447
06448 return new;
06449 }
06450
06451
06452
06453
06454 static <