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