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