00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "toplev.h"
00029 #include "rtl.h"
00030 #include "tree.h"
00031 #include "tm_p.h"
00032 #include "flags.h"
00033 #include "insn-config.h"
00034 #include "expr.h"
00035 #include "optabs.h"
00036 #include "real.h"
00037 #include "recog.h"
00038 #include "langhooks.h"
00039
00040 static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
00041 unsigned HOST_WIDE_INT,
00042 unsigned HOST_WIDE_INT, rtx);
00043 static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
00044 unsigned HOST_WIDE_INT, rtx);
00045 static rtx extract_fixed_bit_field (enum machine_mode, rtx,
00046 unsigned HOST_WIDE_INT,
00047 unsigned HOST_WIDE_INT,
00048 unsigned HOST_WIDE_INT, rtx, int);
00049 static rtx mask_rtx (enum machine_mode, int, int, int);
00050 static rtx lshift_value (enum machine_mode, rtx, int, int);
00051 static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
00052 unsigned HOST_WIDE_INT, int);
00053 static void do_cmp_and_jump (rtx, rtx, enum rtx_code, enum machine_mode, rtx);
00054 static rtx expand_smod_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
00055 static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
00056
00057
00058 #define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0)
00059
00060
00061
00062
00063
00064
00065 static bool sdiv_pow2_cheap[NUM_MACHINE_MODES];
00066 static bool smod_pow2_cheap[NUM_MACHINE_MODES];
00067
00068 #ifndef SLOW_UNALIGNED_ACCESS
00069 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
00070 #endif
00071
00072
00073
00074
00075
00076 #ifndef MAX_BITS_PER_WORD
00077 #define MAX_BITS_PER_WORD BITS_PER_WORD
00078 #endif
00079
00080
00081 #ifndef HAVE_insv
00082 #define HAVE_insv 0
00083 #define CODE_FOR_insv CODE_FOR_nothing
00084 #define gen_insv(a,b,c,d) NULL_RTX
00085 #endif
00086 #ifndef HAVE_extv
00087 #define HAVE_extv 0
00088 #define CODE_FOR_extv CODE_FOR_nothing
00089 #define gen_extv(a,b,c,d) NULL_RTX
00090 #endif
00091 #ifndef HAVE_extzv
00092 #define HAVE_extzv 0
00093 #define CODE_FOR_extzv CODE_FOR_nothing
00094 #define gen_extzv(a,b,c,d) NULL_RTX
00095 #endif
00096
00097
00098
00099 static int zero_cost;
00100 static int add_cost[NUM_MACHINE_MODES];
00101 static int neg_cost[NUM_MACHINE_MODES];
00102 static int shift_cost[NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
00103 static int shiftadd_cost[NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
00104 static int shiftsub_cost[NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
00105 static int mul_cost[NUM_MACHINE_MODES];
00106 static int div_cost[NUM_MACHINE_MODES];
00107 static int mul_widen_cost[NUM_MACHINE_MODES];
00108 static int mul_highpart_cost[NUM_MACHINE_MODES];
00109
00110 void
00111 init_expmed (void)
00112 {
00113 struct
00114 {
00115 struct rtx_def reg; rtunion reg_fld[2];
00116 struct rtx_def plus; rtunion plus_fld1;
00117 struct rtx_def neg;
00118 struct rtx_def udiv; rtunion udiv_fld1;
00119 struct rtx_def mult; rtunion mult_fld1;
00120 struct rtx_def div; rtunion div_fld1;
00121 struct rtx_def mod; rtunion mod_fld1;
00122 struct rtx_def zext;
00123 struct rtx_def wide_mult; rtunion wide_mult_fld1;
00124 struct rtx_def wide_lshr; rtunion wide_lshr_fld1;
00125 struct rtx_def wide_trunc;
00126 struct rtx_def shift; rtunion shift_fld1;
00127 struct rtx_def shift_mult; rtunion shift_mult_fld1;
00128 struct rtx_def shift_add; rtunion shift_add_fld1;
00129 struct rtx_def shift_sub; rtunion shift_sub_fld1;
00130 } all;
00131
00132 rtx pow2[MAX_BITS_PER_WORD];
00133 rtx cint[MAX_BITS_PER_WORD];
00134 int m, n;
00135 enum machine_mode mode, wider_mode;
00136
00137 zero_cost = rtx_cost (const0_rtx, 0);
00138
00139 for (m = 1; m < MAX_BITS_PER_WORD; m++)
00140 {
00141 pow2[m] = GEN_INT ((HOST_WIDE_INT) 1 << m);
00142 cint[m] = GEN_INT (m);
00143 }
00144
00145 memset (&all, 0, sizeof all);
00146
00147 PUT_CODE (&all.reg, REG);
00148
00149 REGNO (&all.reg) = LAST_VIRTUAL_REGISTER + 1;
00150
00151 PUT_CODE (&all.plus, PLUS);
00152 XEXP (&all.plus, 0) = &all.reg;
00153 XEXP (&all.plus, 1) = &all.reg;
00154
00155 PUT_CODE (&all.neg, NEG);
00156 XEXP (&all.neg, 0) = &all.reg;
00157
00158 PUT_CODE (&all.udiv, UDIV);
00159 XEXP (&all.udiv, 0) = &all.reg;
00160 XEXP (&all.udiv, 1) = &all.reg;
00161
00162 PUT_CODE (&all.mult, MULT);
00163 XEXP (&all.mult, 0) = &all.reg;
00164 XEXP (&all.mult, 1) = &all.reg;
00165
00166 PUT_CODE (&all.div, DIV);
00167 XEXP (&all.div, 0) = &all.reg;
00168 XEXP (&all.div, 1) = 32 < MAX_BITS_PER_WORD ? cint[32] : GEN_INT (32);
00169
00170 PUT_CODE (&all.mod, MOD);
00171 XEXP (&all.mod, 0) = &all.reg;
00172 XEXP (&all.mod, 1) = XEXP (&all.div, 1);
00173
00174 PUT_CODE (&all.zext, ZERO_EXTEND);
00175 XEXP (&all.zext, 0) = &all.reg;
00176
00177 PUT_CODE (&all.wide_mult, MULT);
00178 XEXP (&all.wide_mult, 0) = &all.zext;
00179 XEXP (&all.wide_mult, 1) = &all.zext;
00180
00181 PUT_CODE (&all.wide_lshr, LSHIFTRT);
00182 XEXP (&all.wide_lshr, 0) = &all.wide_mult;
00183
00184 PUT_CODE (&all.wide_trunc, TRUNCATE);
00185 XEXP (&all.wide_trunc, 0) = &all.wide_lshr;
00186
00187 PUT_CODE (&all.shift, ASHIFT);
00188 XEXP (&all.shift, 0) = &all.reg;
00189
00190 PUT_CODE (&all.shift_mult, MULT);
00191 XEXP (&all.shift_mult, 0) = &all.reg;
00192
00193 PUT_CODE (&all.shift_add, PLUS);
00194 XEXP (&all.shift_add, 0) = &all.shift_mult;
00195 XEXP (&all.shift_add, 1) = &all.reg;
00196
00197 PUT_CODE (&all.shift_sub, MINUS);
00198 XEXP (&all.shift_sub, 0) = &all.shift_mult;
00199 XEXP (&all.shift_sub, 1) = &all.reg;
00200
00201 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
00202 mode != VOIDmode;
00203 mode = GET_MODE_WIDER_MODE (mode))
00204 {
00205 PUT_MODE (&all.reg, mode);
00206 PUT_MODE (&all.plus, mode);
00207 PUT_MODE (&all.neg, mode);
00208 PUT_MODE (&all.udiv, mode);
00209 PUT_MODE (&all.mult, mode);
00210 PUT_MODE (&all.div, mode);
00211 PUT_MODE (&all.mod, mode);
00212 PUT_MODE (&all.wide_trunc, mode);
00213 PUT_MODE (&all.shift, mode);
00214 PUT_MODE (&all.shift_mult, mode);
00215 PUT_MODE (&all.shift_add, mode);
00216 PUT_MODE (&all.shift_sub, mode);
00217
00218 add_cost[mode] = rtx_cost (&all.plus, SET);
00219 neg_cost[mode] = rtx_cost (&all.neg, SET);
00220 div_cost[mode] = rtx_cost (&all.udiv, SET);
00221 mul_cost[mode] = rtx_cost (&all.mult, SET);
00222
00223 sdiv_pow2_cheap[mode] = (rtx_cost (&all.div, SET) <= 2 * add_cost[mode]);
00224 smod_pow2_cheap[mode] = (rtx_cost (&all.mod, SET) <= 4 * add_cost[mode]);
00225
00226 wider_mode = GET_MODE_WIDER_MODE (mode);
00227 if (wider_mode != VOIDmode)
00228 {
00229 PUT_MODE (&all.zext, wider_mode);
00230 PUT_MODE (&all.wide_mult, wider_mode);
00231 PUT_MODE (&all.wide_lshr, wider_mode);
00232 XEXP (&all.wide_lshr, 1) = GEN_INT (GET_MODE_BITSIZE (mode));
00233
00234 mul_widen_cost[wider_mode] = rtx_cost (&all.wide_mult, SET);
00235 mul_highpart_cost[mode] = rtx_cost (&all.wide_trunc, SET);
00236 }
00237
00238 shift_cost[mode][0] = 0;
00239 shiftadd_cost[mode][0] = shiftsub_cost[mode][0] = add_cost[mode];
00240
00241 n = MIN (MAX_BITS_PER_WORD, GET_MODE_BITSIZE (mode));
00242 for (m = 1; m < n; m++)
00243 {
00244 XEXP (&all.shift, 1) = cint[m];
00245 XEXP (&all.shift_mult, 1) = pow2[m];
00246
00247 shift_cost[mode][m] = rtx_cost (&all.shift, SET);
00248 shiftadd_cost[mode][m] = rtx_cost (&all.shift_add, SET);
00249 shiftsub_cost[mode][m] = rtx_cost (&all.shift_sub, SET);
00250 }
00251 }
00252 }
00253
00254
00255
00256
00257
00258 rtx
00259 negate_rtx (enum machine_mode mode, rtx x)
00260 {
00261 rtx result = simplify_unary_operation (NEG, mode, x, mode);
00262
00263 if (result == 0)
00264 result = expand_unop (mode, neg_optab, x, NULL_RTX, 0);
00265
00266 return result;
00267 }
00268
00269
00270
00271
00272
00273 enum machine_mode
00274 mode_for_extraction (enum extraction_pattern pattern, int opno)
00275 {
00276 const struct insn_data *data;
00277
00278 switch (pattern)
00279 {
00280 case EP_insv:
00281 if (HAVE_insv)
00282 {
00283 data = &insn_data[CODE_FOR_insv];
00284 break;
00285 }
00286 return MAX_MACHINE_MODE;
00287
00288 case EP_extv:
00289 if (HAVE_extv)
00290 {
00291 data = &insn_data[CODE_FOR_extv];
00292 break;
00293 }
00294 return MAX_MACHINE_MODE;
00295
00296 case EP_extzv:
00297 if (HAVE_extzv)
00298 {
00299 data = &insn_data[CODE_FOR_extzv];
00300 break;
00301 }
00302 return MAX_MACHINE_MODE;
00303
00304 default:
00305 gcc_unreachable ();
00306 }
00307
00308 if (opno == -1)
00309 return VOIDmode;
00310
00311
00312
00313 if (data->operand[opno].mode == VOIDmode)
00314 return word_mode;
00315 return data->operand[opno].mode;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 rtx
00335 store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
00336 unsigned HOST_WIDE_INT bitnum, enum machine_mode fieldmode,
00337 rtx value)
00338 {
00339 unsigned int unit
00340 = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
00341 unsigned HOST_WIDE_INT offset, bitpos;
00342 rtx op0 = str_rtx;
00343 int byte_offset;
00344 rtx orig_value;
00345
00346 enum machine_mode op_mode = mode_for_extraction (EP_insv, 3);
00347
00348 while (GET_CODE (op0) == SUBREG)
00349 {
00350
00351
00352
00353
00354
00355 bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
00356 op0 = SUBREG_REG (op0);
00357 }
00358
00359
00360
00361
00362 if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0)))
00363 return value;
00364
00365
00366
00367 if (VECTOR_MODE_P (GET_MODE (op0))
00368 && !MEM_P (op0)
00369 && (vec_set_optab->handlers[GET_MODE (op0)].insn_code
00370 != CODE_FOR_nothing)
00371 && fieldmode == GET_MODE_INNER (GET_MODE (op0))
00372 && bitsize == GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))
00373 && !(bitnum % GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))))
00374 {
00375 enum machine_mode outermode = GET_MODE (op0);
00376 enum machine_mode innermode = GET_MODE_INNER (outermode);
00377 int icode = (int) vec_set_optab->handlers[outermode].insn_code;
00378 int pos = bitnum / GET_MODE_BITSIZE (innermode);
00379 rtx rtxpos = GEN_INT (pos);
00380 rtx src = value;
00381 rtx dest = op0;
00382 rtx pat, seq;
00383 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
00384 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
00385 enum machine_mode mode2 = insn_data[icode].operand[2].mode;
00386
00387 start_sequence ();
00388
00389 if (! (*insn_data[icode].operand[1].predicate) (src, mode1))
00390 src = copy_to_mode_reg (mode1, src);
00391
00392 if (! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2))
00393 rtxpos = copy_to_mode_reg (mode1, rtxpos);
00394
00395
00396
00397 gcc_assert ((*insn_data[icode].operand[0].predicate) (dest, mode0)
00398 && (*insn_data[icode].operand[1].predicate) (src, mode1)
00399 && (*insn_data[icode].operand[2].predicate) (rtxpos, mode2));
00400 pat = GEN_FCN (icode) (dest, src, rtxpos);
00401 seq = get_insns ();
00402 end_sequence ();
00403 if (pat)
00404 {
00405 emit_insn (seq);
00406 emit_insn (pat);
00407 return dest;
00408 }
00409 }
00410
00411 if (flag_force_mem)
00412 {
00413 int old_generating_concat_p = generating_concat_p;
00414 generating_concat_p = 0;
00415 value = force_not_mem (value);
00416 generating_concat_p = old_generating_concat_p;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426 offset = bitnum / unit;
00427 bitpos = bitnum % unit;
00428 byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
00429 + (offset * UNITS_PER_WORD);
00430
00431 if (bitpos == 0
00432 && bitsize == GET_MODE_BITSIZE (fieldmode)
00433 && (!MEM_P (op0)
00434 ? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
00435 || GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
00436 && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
00437 : (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
00438 || (offset * BITS_PER_UNIT % bitsize == 0
00439 && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
00440 {
00441 if (GET_MODE (op0) != fieldmode)
00442 {
00443 if (MEM_P (op0))
00444 op0 = adjust_address (op0, fieldmode, offset);
00445 else
00446 op0 = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
00447 byte_offset);
00448 }
00449 emit_move_insn (op0, value);
00450 return value;
00451 }
00452
00453
00454
00455
00456
00457 {
00458 enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
00459 if (imode != GET_MODE (op0))
00460 {
00461 if (MEM_P (op0))
00462 op0 = adjust_address (op0, imode, 0);
00463 else
00464 {
00465 gcc_assert (imode != BLKmode);
00466 op0 = gen_lowpart (imode, op0);
00467 }
00468 }
00469 }
00470
00471
00472
00473 if (MEM_P (op0))
00474 {
00475 op0 = shallow_copy_rtx (op0);
00476 set_mem_alias_set (op0, 0);
00477 set_mem_expr (op0, 0);
00478 }
00479
00480
00481
00482
00483 if (BYTES_BIG_ENDIAN
00484 && !MEM_P (op0)
00485 && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
00486 bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
00487
00488
00489
00490
00491 if (!MEM_P (op0)
00492 && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0)
00493 && bitsize == GET_MODE_BITSIZE (fieldmode)
00494 && (movstrict_optab->handlers[fieldmode].insn_code
00495 != CODE_FOR_nothing))
00496 {
00497 int icode = movstrict_optab->handlers[fieldmode].insn_code;
00498
00499
00500 if (GET_CODE (value) == CONST_INT || REG_P (value))
00501 value = gen_lowpart (fieldmode, value);
00502 else if (!(GET_CODE (value) == SYMBOL_REF
00503 || GET_CODE (value) == LABEL_REF
00504 || GET_CODE (value) == CONST))
00505 value = convert_to_mode (fieldmode, value, 0);
00506
00507 if (! (*insn_data[icode].operand[1].predicate) (value, fieldmode))
00508 value = copy_to_mode_reg (fieldmode, value);
00509
00510 if (GET_CODE (op0) == SUBREG)
00511 {
00512
00513
00514
00515 gcc_assert (GET_MODE (SUBREG_REG (op0)) == fieldmode
00516 || GET_MODE_CLASS (fieldmode) == MODE_INT
00517 || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT);
00518 op0 = SUBREG_REG (op0);
00519 }
00520
00521 emit_insn (GEN_FCN (icode)
00522 (gen_rtx_SUBREG (fieldmode, op0,
00523 (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
00524 + (offset * UNITS_PER_WORD)),
00525 value));
00526
00527 return value;
00528 }
00529
00530
00531
00532 if (bitsize > BITS_PER_WORD)
00533 {
00534
00535
00536
00537
00538
00539
00540 unsigned int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
00541 unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
00542 unsigned int i;
00543
00544
00545
00546
00547
00548
00549 fieldmode = GET_MODE (value);
00550 if (fieldmode == VOIDmode)
00551 fieldmode = smallest_mode_for_size (nwords * BITS_PER_WORD, MODE_INT);
00552
00553 for (i = 0; i < nwords; i++)
00554 {
00555
00556
00557 unsigned int wordnum = (backwards ? nwords - i - 1 : i);
00558 unsigned int bit_offset = (backwards
00559 ? MAX ((int) bitsize - ((int) i + 1)
00560 * BITS_PER_WORD,
00561 0)
00562 : (int) i * BITS_PER_WORD);
00563
00564 store_bit_field (op0, MIN (BITS_PER_WORD,
00565 bitsize - i * BITS_PER_WORD),
00566 bitnum + bit_offset, word_mode,
00567 operand_subword_force (value, wordnum, fieldmode));
00568 }
00569 return value;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578 if (!MEM_P (op0))
00579 {
00580 if (offset != 0
00581 || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
00582 {
00583 if (!REG_P (op0))
00584 {
00585
00586
00587
00588
00589 gcc_assert (GET_CODE (op0) == SUBREG
00590 && (GET_MODE_SIZE (GET_MODE (op0))
00591 == GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))));
00592 op0 = SUBREG_REG (op0);
00593 }
00594 op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
00595 op0, (offset * UNITS_PER_WORD));
00596 }
00597 offset = 0;
00598 }
00599
00600
00601
00602
00603
00604 orig_value = value;
00605 if (GET_MODE (value) != VOIDmode
00606 && GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
00607 && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
00608 {
00609 value = gen_reg_rtx (int_mode_for_mode (GET_MODE (value)));
00610 emit_move_insn (gen_lowpart (GET_MODE (orig_value), value), orig_value);
00611 }
00612
00613
00614
00615
00616 if (HAVE_insv
00617 && GET_MODE (value) != BLKmode
00618 && !(bitsize == 1 && GET_CODE (value) == CONST_INT)
00619
00620 && (GET_MODE_BITSIZE (op_mode) >= bitsize)
00621 && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
00622 && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))))
00623 {
00624 int xbitpos = bitpos;
00625 rtx value1;
00626 rtx xop0 = op0;
00627 rtx last = get_last_insn ();
00628 rtx pat;
00629 enum machine_mode maxmode = mode_for_extraction (EP_insv, 3);
00630 int save_volatile_ok = volatile_ok;
00631
00632 volatile_ok = 1;
00633
00634
00635
00636
00637
00638 if (MEM_P (op0)
00639 && ! ((*insn_data[(int) CODE_FOR_insv].operand[0].predicate)
00640 (op0, VOIDmode)))
00641 {
00642 rtx tempreg;
00643 enum machine_mode bestmode;
00644
00645
00646
00647
00648
00649
00650 if (GET_MODE (op0) == BLKmode
00651 || GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (maxmode))
00652 bestmode
00653 = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0), maxmode,
00654 MEM_VOLATILE_P (op0));
00655 else
00656 bestmode = GET_MODE (op0);
00657
00658 if (bestmode == VOIDmode
00659 || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (op0))
00660 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (op0)))
00661 goto insv_loses;
00662
00663
00664
00665 unit = GET_MODE_BITSIZE (bestmode);
00666 offset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
00667 bitpos = bitnum % unit;
00668 op0 = adjust_address (op0, bestmode, offset);
00669
00670
00671
00672 tempreg = copy_to_reg (op0);
00673 store_bit_field (tempreg, bitsize, bitpos, fieldmode, orig_value);
00674 emit_move_insn (op0, tempreg);
00675 return value;
00676 }
00677 volatile_ok = save_volatile_ok;
00678
00679
00680 if (MEM_P (xop0))
00681 xop0 = adjust_address (xop0, byte_mode, offset);
00682
00683
00684
00685 if (GET_CODE (xop0) == SUBREG)
00686
00687
00688 xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
00689 if (REG_P (xop0) && GET_MODE (xop0) != maxmode)
00690 xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
00691
00692
00693
00694
00695 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
00696 xbitpos = unit - bitsize - xbitpos;
00697
00698
00699
00700 if (BITS_BIG_ENDIAN && !MEM_P (xop0))
00701 xbitpos += GET_MODE_BITSIZE (maxmode) - unit;
00702
00703 unit = GET_MODE_BITSIZE (maxmode);
00704
00705
00706 value1 = value;
00707 if (GET_MODE (value) != maxmode)
00708 {
00709 if (GET_MODE_BITSIZE (GET_MODE (value)) >= bitsize)
00710 {
00711
00712
00713
00714
00715 if (GET_MODE_SIZE (GET_MODE (value)) < GET_MODE_SIZE (maxmode))
00716 {
00717 rtx tmp;
00718
00719 tmp = simplify_subreg (maxmode, value1, GET_MODE (value), 0);
00720 if (! tmp)
00721 tmp = simplify_gen_subreg (maxmode,
00722 force_reg (GET_MODE (value),
00723 value1),
00724 GET_MODE (value), 0);
00725 value1 = tmp;
00726 }
00727 else
00728 value1 = gen_lowpart (maxmode, value1);
00729 }
00730 else if (GET_CODE (value) == CONST_INT)
00731 value1 = gen_int_mode (INTVAL (value), maxmode);
00732 else
00733
00734
00735
00736
00737 gcc_assert (CONSTANT_P (value));
00738 }
00739
00740
00741
00742 if (! ((*insn_data[(int) CODE_FOR_insv].operand[3].predicate)
00743 (value1, maxmode)))
00744 value1 = force_reg (maxmode, value1);
00745
00746 pat = gen_insv (xop0, GEN_INT (bitsize), GEN_INT (xbitpos), value1);
00747 if (pat)
00748 emit_insn (pat);
00749 else
00750 {
00751 delete_insns_since (last);
00752 store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
00753 }
00754 }
00755 else
00756 insv_loses:
00757
00758 store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
00759 return value;
00760 }
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 static void
00772 store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset,
00773 unsigned HOST_WIDE_INT bitsize,
00774 unsigned HOST_WIDE_INT bitpos, rtx value)
00775 {
00776 enum machine_mode mode;
00777 unsigned int total_bits = BITS_PER_WORD;
00778 rtx subtarget, temp;
00779 int all_zero = 0;
00780 int all_one = 0;
00781
00782
00783
00784
00785
00786
00787
00788
00789 if (REG_P (op0) || GET_CODE (op0) == SUBREG)
00790 {
00791 gcc_assert (!offset);
00792
00793 if (bitsize + bitpos > BITS_PER_WORD)
00794 {
00795 store_split_bit_field (op0, bitsize, bitpos, value);
00796 return;
00797 }
00798 }
00799 else
00800 {
00801
00802
00803
00804
00805
00806 mode = GET_MODE (op0);
00807 if (GET_MODE_BITSIZE (mode) == 0
00808 || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
00809 mode = word_mode;
00810 mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
00811 MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
00812
00813 if (mode == VOIDmode)
00814 {
00815
00816
00817 store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT,
00818 value);
00819 return;
00820 }
00821
00822 total_bits = GET_MODE_BITSIZE (mode);
00823
00824
00825
00826
00827 if (bitpos >= total_bits)
00828 {
00829 offset += (bitpos / total_bits) * (total_bits / BITS_PER_UNIT);
00830 bitpos -= ((bitpos / total_bits) * (total_bits / BITS_PER_UNIT)
00831 * BITS_PER_UNIT);
00832 }
00833
00834
00835
00836
00837
00838 bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
00839 offset -= (offset % (total_bits / BITS_PER_UNIT));
00840 op0 = adjust_address (op0, mode, offset);
00841 }
00842
00843 mode = GET_MODE (op0);
00844
00845
00846
00847
00848
00849
00850
00851 if (BYTES_BIG_ENDIAN)
00852
00853
00854
00855 bitpos = total_bits - bitsize - bitpos;
00856
00857
00858
00859
00860
00861
00862
00863 if (GET_CODE (value) == CONST_INT)
00864 {
00865 HOST_WIDE_INT v = INTVAL (value);
00866
00867 if (bitsize < HOST_BITS_PER_WIDE_INT)
00868 v &= ((HOST_WIDE_INT) 1 << bitsize) - 1;
00869
00870 if (v == 0)
00871 all_zero = 1;
00872 else if ((bitsize < HOST_BITS_PER_WIDE_INT
00873 && v == ((HOST_WIDE_INT) 1 << bitsize) - 1)
00874 || (bitsize == HOST_BITS_PER_WIDE_INT && v == -1))
00875 all_one = 1;
00876
00877 value = lshift_value (mode, value, bitpos, bitsize);
00878 }
00879 else
00880 {
00881 int must_and = (GET_MODE_BITSIZE (GET_MODE (value)) != bitsize
00882 && bitpos + bitsize != GET_MODE_BITSIZE (mode));
00883
00884 if (GET_MODE (value) != mode)
00885 {
00886 if ((REG_P (value) || GET_CODE (value) == SUBREG)
00887 && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (value)))
00888 value = gen_lowpart (mode, value);
00889 else
00890 value = convert_to_mode (mode, value, 1);
00891 }
00892
00893 if (must_and)
00894 value = expand_binop (mode, and_optab, value,
00895 mask_rtx (mode, 0, bitsize, 0),
00896 NULL_RTX, 1, OPTAB_LIB_WIDEN);
00897 if (bitpos > 0)
00898 value = expand_shift (LSHIFT_EXPR, mode, value,
00899 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
00900 }
00901
00902
00903
00904
00905 subtarget = (REG_P (op0) || ! flag_force_mem) ? op0 : 0;
00906
00907 if (! all_one)
00908 {
00909 temp = expand_binop (mode, and_optab, op0,
00910 mask_rtx (mode, bitpos, bitsize, 1),
00911 subtarget, 1, OPTAB_LIB_WIDEN);
00912 subtarget = temp;
00913 }
00914 else
00915 temp = op0;
00916
00917
00918
00919 if (! all_zero)
00920 temp = expand_binop (mode, ior_optab, temp, value,
00921 subtarget, 1, OPTAB_LIB_WIDEN);
00922 if (op0 != temp)
00923 emit_move_insn (op0, temp);
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 static void
00936 store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
00937 unsigned HOST_WIDE_INT bitpos, rtx value)
00938 {
00939 unsigned int unit;
00940 unsigned int bitsdone = 0;
00941
00942
00943
00944 if (REG_P (op0) || GET_CODE (op0) == SUBREG)
00945 unit = BITS_PER_WORD;
00946 else
00947 unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
00948
00949
00950
00951
00952 if (CONSTANT_P (value) && GET_CODE (value) != CONST_INT)
00953 {
00954 rtx word = gen_lowpart_common (word_mode, value);
00955
00956 if (word && (value != word))
00957 value = word;
00958 else
00959 value = gen_lowpart_common (word_mode,
00960 force_reg (GET_MODE (value) != VOIDmode
00961 ? GET_MODE (value)
00962 : word_mode, value));
00963 }
00964
00965 while (bitsdone < bitsize)
00966 {
00967 unsigned HOST_WIDE_INT thissize;
00968 rtx part, word;
00969 unsigned HOST_WIDE_INT thispos;
00970 unsigned HOST_WIDE_INT offset;
00971
00972 offset = (bitpos + bitsdone) / unit;
00973 thispos = (bitpos + bitsdone) % unit;
00974
00975
00976
00977
00978 thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);
00979 thissize = MIN (thissize, unit - thispos);
00980
00981 if (BYTES_BIG_ENDIAN)
00982 {
00983 int total_bits;
00984
00985
00986
00987
00988 if (!MEM_P (value) || GET_MODE (value) == BLKmode)
00989 total_bits = BITS_PER_WORD;
00990 else
00991 total_bits = GET_MODE_BITSIZE (GET_MODE (value));
00992
00993
00994 if (GET_CODE (value) == CONST_INT)
00995 part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
00996 >> (bitsize - bitsdone - thissize))
00997 & (((HOST_WIDE_INT) 1 << thissize) - 1));
00998 else
00999
01000
01001
01002 part = extract_fixed_bit_field (word_mode, value, 0, thissize,
01003 total_bits - bitsize + bitsdone,
01004 NULL_RTX, 1);
01005 }
01006 else
01007 {
01008
01009 if (GET_CODE (value) == CONST_INT)
01010 part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
01011 >> bitsdone)
01012 & (((HOST_WIDE_INT) 1 << thissize) - 1));
01013 else
01014 part = extract_fixed_bit_field (word_mode, value, 0, thissize,
01015 bitsdone, NULL_RTX, 1);
01016 }
01017
01018
01019
01020
01021
01022
01023
01024 if (GET_CODE (op0) == SUBREG)
01025 {
01026 int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
01027 word = operand_subword_force (SUBREG_REG (op0), word_offset,
01028 GET_MODE (SUBREG_REG (op0)));
01029 offset = 0;
01030 }
01031 else if (REG_P (op0))
01032 {
01033 word = operand_subword_force (op0, offset, GET_MODE (op0));
01034 offset = 0;
01035 }
01036 else
01037 word = op0;
01038
01039
01040
01041 store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize,
01042 thispos, part);
01043 bitsdone += thissize;
01044 }
01045 }
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066 rtx
01067 extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
01068 unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
01069 enum machine_mode mode, enum machine_mode tmode)
01070 {
01071 unsigned int unit
01072 = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
01073 unsigned HOST_WIDE_INT offset, bitpos;
01074 rtx op0 = str_rtx;
01075 rtx spec_target = target;
01076 rtx spec_target_subreg = 0;
01077 enum machine_mode int_mode;
01078 enum machine_mode extv_mode = mode_for_extraction (EP_extv, 0);
01079 enum machine_mode extzv_mode = mode_for_extraction (EP_extzv, 0);
01080 enum machine_mode mode1;
01081 int byte_offset;
01082
01083 if (tmode == VOIDmode)
01084 tmode = mode;
01085
01086 while (GET_CODE (op0) == SUBREG)
01087 {
01088 bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
01089 op0 = SUBREG_REG (op0);
01090 }
01091
01092
01093
01094
01095 if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0)))
01096 return gen_reg_rtx (tmode);
01097
01098 if (REG_P (op0)
01099 && mode == GET_MODE (op0)
01100 && bitnum == 0
01101 && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
01102 {
01103
01104 return op0;
01105 }
01106
01107
01108
01109 if (VECTOR_MODE_P (GET_MODE (op0))
01110 && !MEM_P (op0)
01111 && (vec_extract_optab->handlers[GET_MODE (op0)].insn_code
01112 != CODE_FOR_nothing)
01113 && ((bitnum + bitsize - 1) / GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))
01114 == bitnum / GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))))
01115 {
01116 enum machine_mode outermode = GET_MODE (op0);
01117 enum machine_mode innermode = GET_MODE_INNER (outermode);
01118 int icode = (int) vec_extract_optab->handlers[outermode].insn_code;
01119 unsigned HOST_WIDE_INT pos = bitnum / GET_MODE_BITSIZE (innermode);
01120 rtx rtxpos = GEN_INT (pos);
01121 rtx src = op0;
01122 rtx dest = NULL, pat, seq;
01123 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
01124 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
01125 enum machine_mode mode2 = insn_data[icode].operand[2].mode;
01126
01127 if (innermode == tmode || innermode == mode)
01128 dest = target;
01129
01130 if (!dest)
01131 dest = gen_reg_rtx (innermode);
01132
01133 start_sequence ();
01134
01135 if (! (*insn_data[icode].operand[0].predicate) (dest, mode0))
01136 dest = copy_to_mode_reg (mode0, dest);
01137
01138 if (! (*insn_data[icode].operand[1].predicate) (src, mode1))
01139 src = copy_to_mode_reg (mode1, src);
01140
01141 if (! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2))
01142 rtxpos = copy_to_mode_reg (mode1, rtxpos);
01143
01144
01145
01146 gcc_assert ((*insn_data[icode].operand[0].predicate) (dest, mode0)
01147 && (*insn_data[icode].operand[1].predicate) (src, mode1)
01148 && (*insn_data[icode].operand[2].predicate) (rtxpos, mode2));
01149
01150 pat = GEN_FCN (icode) (dest, src, rtxpos);
01151 seq = get_insns ();
01152 end_sequence ();
01153 if (pat)
01154 {
01155 emit_insn (seq);
01156 emit_insn (pat);
01157 return dest;
01158 }
01159 }
01160
01161
01162
01163 {
01164 enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
01165 if (imode != GET_MODE (op0))
01166 {
01167 if (MEM_P (op0))
01168 op0 = adjust_address (op0, imode, 0);
01169 else
01170 {
01171 gcc_assert (imode != BLKmode);
01172 op0 = gen_lowpart (imode, op0);
01173
01174
01175
01176 if (GET_CODE (op0) == SUBREG)
01177 op0 = force_reg (imode, op0);
01178 }
01179 }
01180 }
01181
01182
01183
01184 if (MEM_P (op0))
01185 {
01186 op0 = shallow_copy_rtx (op0);
01187 set_mem_alias_set (op0, 0);
01188 set_mem_expr (op0, 0);
01189 }
01190
01191
01192
01193
01194
01195
01196
01197 bitpos = bitnum % unit;
01198 offset = bitnum / unit;
01199 byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD;
01200
01201
01202
01203
01204 if (BYTES_BIG_ENDIAN
01205 && !MEM_P (op0)
01206 && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
01207 bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 mode1 = (SCALAR_INT_MODE_P (tmode)
01219 ? mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0)
01220 : mode);
01221
01222 if (((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
01223 && bitpos % BITS_PER_WORD == 0)
01224 || (mode1 != BLKmode
01225
01226
01227
01228
01229 && (BYTES_BIG_ENDIAN
01230 ? bitpos + bitsize == BITS_PER_WORD
01231 : bitpos == 0)))
01232 && ((!MEM_P (op0)
01233 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01234 GET_MODE_BITSIZE (GET_MODE (op0)))
01235 && GET_MODE_SIZE (mode1) != 0
01236 && byte_offset % GET_MODE_SIZE (mode1) == 0)
01237 || (MEM_P (op0)
01238 && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
01239 || (offset * BITS_PER_UNIT % bitsize == 0
01240 && MEM_ALIGN (op0) % bitsize == 0)))))
01241 {
01242 if (mode1 != GET_MODE (op0))
01243 {
01244 if (MEM_P (op0))
01245 op0 = adjust_address (op0, mode1, offset);
01246 else
01247 {
01248 rtx sub = simplify_gen_subreg (mode1, op0, GET_MODE (op0),
01249 byte_offset);
01250 if (sub == NULL)
01251 goto no_subreg_mode_swap;
01252 op0 = sub;
01253 }
01254 }
01255 if (mode1 != mode)
01256 return convert_to_mode (tmode, op0, unsignedp);
01257 return op0;
01258 }
01259 no_subreg_mode_swap:
01260
01261
01262
01263 if (bitsize > BITS_PER_WORD)
01264 {
01265
01266
01267
01268
01269
01270 unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
01271 unsigned int i;
01272
01273 if (target == 0 || !REG_P (target))
01274 target = gen_reg_rtx (mode);
01275
01276
01277 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
01278
01279 for (i = 0; i < nwords; i++)
01280 {
01281
01282
01283
01284 unsigned int wordnum
01285 = (WORDS_BIG_ENDIAN
01286 ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1
01287 : i);
01288
01289 unsigned int bit_offset = (WORDS_BIG_ENDIAN
01290 ? MAX (0, ((int) bitsize - ((int) i + 1)
01291 * (int) BITS_PER_WORD))
01292 : (int) i * BITS_PER_WORD);
01293 rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);
01294 rtx result_part
01295 = extract_bit_field (op0, MIN (BITS_PER_WORD,
01296 bitsize - i * BITS_PER_WORD),
01297 bitnum + bit_offset, 1, target_part, mode,
01298 word_mode);
01299
01300 gcc_assert (target_part);
01301
01302 if (result_part != target_part)
01303 emit_move_insn (target_part, result_part);
01304 }
01305
01306 if (unsignedp)
01307 {
01308
01309
01310 if (GET_MODE_SIZE (GET_MODE (target)) > nwords * UNITS_PER_WORD)
01311 {
01312 unsigned int i, total_words;
01313
01314 total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD;
01315 for (i = nwords; i < total_words; i++)
01316 emit_move_insn
01317 (operand_subword (target,
01318 WORDS_BIG_ENDIAN ? total_words - i - 1 : i,
01319 1, VOIDmode),
01320 const0_rtx);
01321 }
01322 return target;
01323 }
01324
01325
01326 target = expand_shift (LSHIFT_EXPR, mode, target,
01327 build_int_cst (NULL_TREE,
01328 GET_MODE_BITSIZE (mode) - bitsize),
01329 NULL_RTX, 0);
01330 return expand_shift (RSHIFT_EXPR, mode, target,
01331 build_int_cst (NULL_TREE,
01332 GET_MODE_BITSIZE (mode) - bitsize),
01333 NULL_RTX, 0);
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343 int_mode = int_mode_for_mode (tmode);
01344 if (int_mode == BLKmode)
01345 int_mode = int_mode_for_mode (mode);
01346
01347 gcc_assert (int_mode != BLKmode);
01348
01349
01350
01351 if (!MEM_P (op0))
01352 {
01353 if (offset != 0
01354 || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
01355 {
01356 if (!REG_P (op0))
01357 op0 = copy_to_reg (op0);
01358 op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
01359 op0, (offset * UNITS_PER_WORD));
01360 }
01361 offset = 0;
01362 }
01363
01364
01365
01366 if (unsignedp)
01367 {
01368 if (HAVE_extzv
01369 && (GET_MODE_BITSIZE (extzv_mode) >= bitsize)
01370 && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
01371 && (bitsize + bitpos > GET_MODE_BITSIZE (extzv_mode))))
01372 {
01373 unsigned HOST_WIDE_INT xbitpos = bitpos, xoffset = offset;
01374 rtx bitsize_rtx, bitpos_rtx;
01375 rtx last = get_last_insn ();
01376 rtx xop0 = op0;
01377 rtx xtarget = target;
01378 rtx xspec_target = spec_target;
01379 rtx xspec_target_subreg = spec_target_subreg;
01380 rtx pat;
01381 enum machine_mode maxmode = mode_for_extraction (EP_extzv, 0);
01382
01383 if (MEM_P (xop0))
01384 {
01385 int save_volatile_ok = volatile_ok;
01386 volatile_ok = 1;
01387
01388
01389 if (! ((*insn_data[(int) CODE_FOR_extzv].operand[1].predicate)
01390 (xop0, GET_MODE (xop0))))
01391 {
01392
01393 enum machine_mode bestmode;
01394
01395
01396
01397
01398
01399
01400
01401 if (GET_MODE (xop0) == BLKmode
01402 || (GET_MODE_SIZE (GET_MODE (op0))
01403 > GET_MODE_SIZE (maxmode)))
01404 bestmode = get_best_mode (bitsize, bitnum,
01405 MEM_ALIGN (xop0), maxmode,
01406 MEM_VOLATILE_P (xop0));
01407 else
01408 bestmode = GET_MODE (xop0);
01409
01410 if (bestmode == VOIDmode
01411 || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
01412 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
01413 goto extzv_loses;
01414
01415
01416
01417 unit = GET_MODE_BITSIZE (bestmode);
01418 xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
01419 xbitpos = bitnum % unit;
01420 xop0 = adjust_address (xop0, bestmode, xoffset);
01421
01422
01423 xop0 = force_reg (bestmode, xop0);
01424
01425
01426 }
01427 else
01428
01429 xop0 = adjust_address (xop0, byte_mode, xoffset);
01430
01431 volatile_ok = save_volatile_ok;
01432 }
01433
01434
01435
01436 if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode)
01437 goto extzv_loses;
01438 if (REG_P (xop0) && GET_MODE (xop0) != maxmode)
01439 xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
01440
01441
01442
01443 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
01444 xbitpos = unit - bitsize - xbitpos;
01445
01446
01447 if (BITS_BIG_ENDIAN && !MEM_P (xop0))
01448 xbitpos += GET_MODE_BITSIZE (maxmode) - unit;
01449
01450 unit = GET_MODE_BITSIZE (maxmode);
01451
01452 if (xtarget == 0
01453 || (flag_force_mem && MEM_P (xtarget)))
01454 xtarget = xspec_target = gen_reg_rtx (tmode);
01455
01456 if (GET_MODE (xtarget) != maxmode)
01457 {
01458 if (REG_P (xtarget))
01459 {
01460 int wider = (GET_MODE_SIZE (maxmode)
01461 > GET_MODE_SIZE (GET_MODE (xtarget)));
01462 xtarget = gen_lowpart (maxmode, xtarget);
01463 if (wider)
01464 xspec_target_subreg = xtarget;
01465 }
01466 else
01467 xtarget = gen_reg_rtx (maxmode);
01468 }
01469
01470
01471
01472 if (! ((*insn_data[(int) CODE_FOR_extzv].operand[0].predicate)
01473 (xtarget, maxmode)))
01474 xtarget = gen_reg_rtx (maxmode);
01475
01476 bitsize_rtx = GEN_INT (bitsize);
01477 bitpos_rtx = GEN_INT (xbitpos);
01478
01479 pat = gen_extzv (xtarget, xop0, bitsize_rtx, bitpos_rtx);
01480 if (pat)
01481 {
01482 emit_insn (pat);
01483 target = xtarget;
01484 spec_target = xspec_target;
01485 spec_target_subreg = xspec_target_subreg;
01486 }
01487 else
01488 {
01489 delete_insns_since (last);
01490 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01491 bitpos, target, 1);
01492 }
01493 }
01494 else
01495 extzv_loses:
01496 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01497 bitpos, target, 1);
01498 }
01499 else
01500 {
01501 if (HAVE_extv
01502 && (GET_MODE_BITSIZE (extv_mode) >= bitsize)
01503 && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
01504 && (bitsize + bitpos > GET_MODE_BITSIZE (extv_mode))))
01505 {
01506 int xbitpos = bitpos, xoffset = offset;
01507 rtx bitsize_rtx, bitpos_rtx;
01508 rtx last = get_last_insn ();
01509 rtx xop0 = op0, xtarget = target;
01510 rtx xspec_target = spec_target;
01511 rtx xspec_target_subreg = spec_target_subreg;
01512 rtx pat;
01513 enum machine_mode maxmode = mode_for_extraction (EP_extv, 0);
01514
01515 if (MEM_P (xop0))
01516 {
01517
01518 if (! ((*insn_data[(int) CODE_FOR_extv].operand[1].predicate)
01519 (xop0, GET_MODE (xop0))))
01520 {
01521
01522 enum machine_mode bestmode;
01523
01524
01525
01526
01527
01528
01529
01530 if (GET_MODE (xop0) == BLKmode
01531 || (GET_MODE_SIZE (GET_MODE (op0))
01532 > GET_MODE_SIZE (maxmode)))
01533 bestmode = get_best_mode (bitsize, bitnum,
01534 MEM_ALIGN (xop0), maxmode,
01535 MEM_VOLATILE_P (xop0));
01536 else
01537 bestmode = GET_MODE (xop0);
01538
01539 if (bestmode == VOIDmode
01540 || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
01541 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
01542 goto extv_loses;
01543
01544
01545
01546 unit = GET_MODE_BITSIZE (bestmode);
01547 xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
01548 xbitpos = bitnum % unit;
01549 xop0 = adjust_address (xop0, bestmode, xoffset);
01550
01551
01552 xop0 = force_reg (bestmode, xop0);
01553
01554
01555 }
01556 else
01557
01558 xop0 = adjust_address (xop0, byte_mode, xoffset);
01559 }
01560
01561
01562
01563 if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode)
01564 goto extv_loses;
01565 if (REG_P (xop0) && GET_MODE (xop0) != maxmode)
01566 xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
01567
01568
01569
01570 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
01571 xbitpos = unit - bitsize - xbitpos;
01572
01573
01574
01575 if (BITS_BIG_ENDIAN && !MEM_P (xop0))
01576 xbitpos += (GET_MODE_BITSIZE (maxmode) - unit);
01577
01578 unit = GET_MODE_BITSIZE (maxmode);
01579
01580 if (xtarget == 0
01581 || (flag_force_mem && MEM_P (xtarget)))
01582 xtarget = xspec_target = gen_reg_rtx (tmode);
01583
01584 if (GET_MODE (xtarget) != maxmode)
01585 {
01586 if (REG_P (xtarget))
01587 {
01588 int wider = (GET_MODE_SIZE (maxmode)
01589 > GET_MODE_SIZE (GET_MODE (xtarget)));
01590 xtarget = gen_lowpart (maxmode, xtarget);
01591 if (wider)
01592 xspec_target_subreg = xtarget;
01593 }
01594 else
01595 xtarget = gen_reg_rtx (maxmode);
01596 }
01597
01598
01599
01600 if (! ((*insn_data[(int) CODE_FOR_extv].operand[0].predicate)
01601 (xtarget, maxmode)))
01602 xtarget = gen_reg_rtx (maxmode);
01603
01604 bitsize_rtx = GEN_INT (bitsize);
01605 bitpos_rtx = GEN_INT (xbitpos);
01606
01607 pat = gen_extv (xtarget, xop0, bitsize_rtx, bitpos_rtx);
01608 if (pat)
01609 {
01610 emit_insn (pat);
01611 target = xtarget;
01612 spec_target = xspec_target;
01613 spec_target_subreg = xspec_target_subreg;
01614 }
01615 else
01616 {
01617 delete_insns_since (last);
01618 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01619 bitpos, target, 0);
01620 }
01621 }
01622 else
01623 extv_loses:
01624 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01625 bitpos, target, 0);
01626 }
01627 if (target == spec_target)
01628 return target;
01629 if (target == spec_target_subreg)
01630 return spec_target;
01631 if (GET_MODE (target) != tmode && GET_MODE (target) != mode)
01632 {
01633
01634
01635
01636 if (!SCALAR_INT_MODE_P (tmode))
01637 {
01638 enum machine_mode smode
01639 = mode_for_size (GET_MODE_BITSIZE (tmode), MODE_INT, 0);
01640 target = convert_to_mode (smode, target, unsignedp);
01641 target = force_reg (smode, target);
01642 return gen_lowpart (tmode, target);
01643 }
01644
01645 return convert_to_mode (tmode, target, unsignedp);
01646 }
01647 return target;
01648 }
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 static rtx
01667 extract_fixed_bit_field (enum machine_mode tmode, rtx op0,
01668 unsigned HOST_WIDE_INT offset,
01669 unsigned HOST_WIDE_INT bitsize,
01670 unsigned HOST_WIDE_INT bitpos, rtx target,
01671 int unsignedp)
01672 {
01673 unsigned int total_bits = BITS_PER_WORD;
01674 enum machine_mode mode;
01675
01676 if (GET_CODE (op0) == SUBREG || REG_P (op0))
01677 {
01678
01679 if (bitsize + bitpos > BITS_PER_WORD)
01680 return extract_split_bit_field (op0, bitsize, bitpos, unsignedp);
01681 }
01682 else
01683 {
01684
01685
01686
01687
01688 mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
01689 MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
01690
01691 if (mode == VOIDmode)
01692
01693
01694 return extract_split_bit_field (op0, bitsize,
01695 bitpos + offset * BITS_PER_UNIT,
01696 unsignedp);
01697
01698 total_bits = GET_MODE_BITSIZE (mode);
01699
01700
01701
01702
01703 if (bitpos >= total_bits)
01704 {
01705 offset += (bitpos / total_bits) * (total_bits / BITS_PER_UNIT);
01706 bitpos -= ((bitpos / total_bits) * (total_bits / BITS_PER_UNIT)
01707 * BITS_PER_UNIT);
01708 }
01709
01710
01711
01712
01713
01714 bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
01715 offset -= (offset % (total_bits / BITS_PER_UNIT));
01716 op0 = adjust_address (op0, mode, offset);
01717 }
01718
01719 mode = GET_MODE (op0);
01720
01721 if (BYTES_BIG_ENDIAN)
01722
01723
01724 bitpos = total_bits - bitsize - bitpos;
01725
01726
01727
01728
01729 if (unsignedp)
01730 {
01731 if (bitpos)
01732 {
01733
01734
01735 tree amount = build_int_cst (NULL_TREE, bitpos);
01736
01737
01738 rtx subtarget = (target != 0 && REG_P (target) ? target : 0);
01739 if (tmode != mode) subtarget = 0;
01740 op0 = expand_shift (RSHIFT_EXPR, mode, op0, amount, subtarget, 1);
01741 }
01742
01743 if (mode != tmode)
01744 op0 = convert_to_mode (tmode, op0, 1);
01745
01746
01747
01748
01749 if (GET_MODE_BITSIZE (mode) != bitpos + bitsize)
01750 return expand_binop (GET_MODE (op0), and_optab, op0,
01751 mask_rtx (GET_MODE (op0), 0, bitsize, 0),
01752 target, 1, OPTAB_LIB_WIDEN);
01753 return op0;
01754 }
01755
01756
01757
01758 op0 = force_reg (mode, op0);
01759 if (mode != tmode)
01760 target = 0;
01761
01762
01763
01764 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
01765 mode = GET_MODE_WIDER_MODE (mode))
01766 if (GET_MODE_BITSIZE (mode) >= bitsize + bitpos)
01767 {
01768 op0 = convert_to_mode (mode, op0, 0);
01769 break;
01770 }
01771
01772 if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos))
01773 {
01774 tree amount
01775 = build_int_cst (NULL_TREE,
01776 GET_MODE_BITSIZE (mode) - (bitsize + bitpos));
01777
01778 rtx subtarget = (target != 0 && REG_P (target) ? target : 0);
01779 op0 = expand_shift (LSHIFT_EXPR, mode, op0, amount, subtarget, 1);
01780 }
01781
01782 return expand_shift (RSHIFT_EXPR, mode, op0,
01783 build_int_cst (NULL_TREE,
01784 GET_MODE_BITSIZE (mode) - bitsize),
01785 target, 0);
01786 }
01787
01788
01789
01790
01791
01792
01793
01794 static rtx
01795 mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement)
01796 {
01797 HOST_WIDE_INT masklow, maskhigh;
01798
01799 if (bitsize == 0)
01800 masklow = 0;
01801 else if (bitpos < HOST_BITS_PER_WIDE_INT)
01802 masklow = (HOST_WIDE_INT) -1 << bitpos;
01803 else
01804 masklow = 0;
01805
01806 if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT)
01807 masklow &= ((unsigned HOST_WIDE_INT) -1
01808 >> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
01809
01810 if (bitpos <= HOST_BITS_PER_WIDE_INT)
01811 maskhigh = -1;
01812 else
01813 maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT);
01814
01815 if (bitsize == 0)
01816 maskhigh = 0;
01817 else if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT)
01818 maskhigh &= ((unsigned HOST_WIDE_INT) -1
01819 >> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
01820 else
01821 maskhigh = 0;
01822
01823 if (complement)
01824 {
01825 maskhigh = ~maskhigh;
01826 masklow = ~masklow;
01827 }
01828
01829 return immed_double_const (masklow, maskhigh, mode);
01830 }
01831
01832
01833
01834
01835 static rtx
01836 lshift_value (enum machine_mode mode, rtx value, int bitpos, int bitsize)
01837 {
01838 unsigned HOST_WIDE_INT v = INTVAL (value);
01839 HOST_WIDE_INT low, high;
01840
01841 if (bitsize < HOST_BITS_PER_WIDE_INT)
01842 v &= ~((HOST_WIDE_INT) -1 << bitsize);
01843
01844 if (bitpos < HOST_BITS_PER_WIDE_INT)
01845 {
01846 low = v << bitpos;
01847 high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0);
01848 }
01849 else
01850 {
01851 low = 0;
01852 high = v << (bitpos - HOST_BITS_PER_WIDE_INT);
01853 }
01854
01855 return immed_double_const (low, high, mode);
01856 }
01857
01858
01859
01860
01861
01862
01863
01864
01865 static rtx
01866 extract_force_align_mem_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
01867 unsigned HOST_WIDE_INT bitpos,
01868 int unsignedp)
01869 {
01870 enum machine_mode mode, dmode;
01871 unsigned int m_bitsize, m_size;
01872 unsigned int sign_shift_up, sign_shift_dn;
01873 rtx base, a1, a2, v1, v2, comb, shift, result, start;
01874
01875
01876 mode = smallest_mode_for_size (bitsize, MODE_INT);
01877 m_size = GET_MODE_SIZE (mode);
01878 m_bitsize = GET_MODE_BITSIZE (mode);
01879
01880
01881 dmode = mode_for_size (m_bitsize * 2, MODE_INT, false);
01882 if (dmode == BLKmode)
01883 return NULL;
01884
01885 do_pending_stack_adjust ();
01886 start = get_last_insn ();
01887
01888
01889
01890
01891 sign_shift_up = sign_shift_dn = m_bitsize - bitsize;
01892
01893 if (STRICT_ALIGNMENT)
01894 {
01895 base = plus_constant (XEXP (op0, 0), bitpos / BITS_PER_UNIT);
01896 bitpos %= BITS_PER_UNIT;
01897
01898
01899
01900
01901
01902
01903
01904
01905 a1 = expand_simple_binop (Pmode, AND, force_operand (base, NULL),
01906 GEN_INT (-(HOST_WIDE_INT)m_size),
01907 NULL, true, OPTAB_LIB_WIDEN);
01908 mark_reg_pointer (a1, m_bitsize);
01909 v1 = gen_rtx_MEM (mode, a1);
01910 set_mem_align (v1, m_bitsize);
01911 v1 = force_reg (mode, validize_mem (v1));
01912
01913 a2 = plus_constant (base, GET_MODE_SIZE (mode) - 1);
01914 a2 = expand_simple_binop (Pmode, AND, force_operand (a2, NULL),
01915 GEN_INT (-(HOST_WIDE_INT)m_size),
01916 NULL, true, OPTAB_LIB_WIDEN);
01917 v2 = gen_rtx_MEM (mode, a2);
01918 set_mem_align (v2, m_bitsize);
01919 v2 = force_reg (mode, validize_mem (v2));
01920
01921
01922 if (m_bitsize == BITS_PER_WORD)
01923 {
01924 comb = gen_reg_rtx (dmode);
01925 emit_insn (gen_rtx_CLOBBER (VOIDmode, comb));
01926 emit_move_insn (gen_rtx_SUBREG (mode, comb, 0), v1);
01927 emit_move_insn (gen_rtx_SUBREG (mode, comb, m_size), v2);
01928 }
01929 else
01930 {
01931 if (BYTES_BIG_ENDIAN)
01932 comb = v1, v1 = v2, v2 = comb;
01933 v1 = convert_modes (dmode, mode, v1, true);
01934 if (v1 == NULL)
01935 goto fail;
01936 v2 = convert_modes (dmode, mode, v2, true);
01937 v2 = expand_simple_binop (dmode, ASHIFT, v2, GEN_INT (m_bitsize),
01938 NULL, true, OPTAB_LIB_WIDEN);
01939 if (v2 == NULL)
01940 goto fail;
01941 comb = expand_simple_binop (dmode, IOR, v1, v2, NULL,
01942 true, OPTAB_LIB_WIDEN);
01943 if (comb == NULL)
01944 goto fail;
01945 }
01946
01947 shift = expand_simple_binop (Pmode, AND, base, GEN_INT (m_size - 1),
01948 NULL, true, OPTAB_LIB_WIDEN);
01949 shift = expand_mult (Pmode, shift, GEN_INT (BITS_PER_UNIT), NULL, 1);
01950
01951 if (bitpos != 0)
01952 {
01953 if (sign_shift_up <= bitpos)
01954 bitpos -= sign_shift_up, sign_shift_up = 0;
01955 shift = expand_simple_binop (Pmode, PLUS, shift, GEN_INT (bitpos),
01956 NULL, true, OPTAB_LIB_WIDEN);
01957 }
01958 }
01959 else
01960 {
01961 unsigned HOST_WIDE_INT offset = bitpos / BITS_PER_UNIT;
01962 bitpos %= BITS_PER_UNIT;
01963
01964
01965
01966
01967
01968 if (bitpos + bitsize <= m_bitsize)
01969 dmode = mode;
01970 comb = adjust_address (op0, dmode, offset);
01971
01972 if (sign_shift_up <= bitpos)
01973 bitpos -= sign_shift_up, sign_shift_up = 0;
01974 shift = GEN_INT (bitpos);
01975 }
01976
01977
01978 if (shift != const0_rtx)
01979 comb = expand_simple_binop (dmode, unsignedp ? LSHIFTRT : ASHIFTRT,
01980 comb, shift, NULL, unsignedp, OPTAB_LIB_WIDEN);
01981 if (comb == NULL)
01982 goto fail;
01983
01984
01985
01986 result = force_reg (mode, gen_lowpart (mode, comb));
01987
01988 if (sign_shift_up)
01989 result = expand_simple_binop (mode, ASHIFT, result,
01990 GEN_INT (sign_shift_up),
01991 NULL_RTX, 0, OPTAB_LIB_WIDEN);
01992 if (sign_shift_dn)
01993 result = expand_simple_binop (mode, unsignedp ? LSHIFTRT : ASHIFTRT,
01994 result, GEN_INT (sign_shift_dn),
01995 NULL_RTX, 0, OPTAB_LIB_WIDEN);
01996
01997 return result;
01998
01999 fail:
02000 delete_insns_since (start);
02001 return NULL;
02002 }
02003
02004
02005
02006
02007
02008
02009
02010
02011 static rtx
02012 extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
02013 unsigned HOST_WIDE_INT bitpos, int unsignedp)
02014 {
02015 unsigned int unit;
02016 unsigned int bitsdone = 0;
02017 rtx result = NULL_RTX;
02018 int first = 1;
02019
02020
02021
02022 if (REG_P (op0) || GET_CODE (op0) == SUBREG)
02023 unit = BITS_PER_WORD;
02024 else
02025 {
02026 unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
02027 if (0 && bitsize / unit > 2)
02028 {
02029 rtx tmp = extract_force_align_mem_bit_field (op0, bitsize, bitpos,
02030 unsignedp);
02031 if (tmp)
02032 return tmp;
02033 }
02034 }
02035
02036 while (bitsdone < bitsize)
02037 {
02038 unsigned HOST_WIDE_INT thissize;
02039 rtx part, word;
02040 unsigned HOST_WIDE_INT thispos;
02041 unsigned HOST_WIDE_INT offset;
02042
02043 offset = (bitpos + bitsdone) / unit;
02044 thispos = (bitpos + bitsdone) % unit;
02045
02046
02047
02048
02049 thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);
02050 thissize = MIN (thissize, unit - thispos);
02051
02052
02053
02054
02055
02056
02057
02058 if (GET_CODE (op0) == SUBREG)
02059 {
02060 int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
02061 word = operand_subword_force (SUBREG_REG (op0), word_offset,
02062 GET_MODE (SUBREG_REG (op0)));
02063 offset = 0;
02064 }
02065 else if (REG_P (op0))
02066 {
02067 word = operand_subword_force (op0, offset, GET_MODE (op0));
02068 offset = 0;
02069 }
02070 else
02071 word = op0;
02072
02073
02074
02075
02076
02077 part = extract_fixed_bit_field (word_mode, word,
02078 offset * unit / BITS_PER_UNIT,
02079 thissize, thispos, 0, 1);
02080 bitsdone += thissize;
02081
02082
02083 if (BYTES_BIG_ENDIAN)
02084 {
02085 if (bitsize != bitsdone)
02086 part = expand_shift (LSHIFT_EXPR, word_mode, part,
02087 build_int_cst (NULL_TREE, bitsize - bitsdone),
02088 0, 1);
02089 }
02090 else
02091 {
02092 if (bitsdone != thissize)
02093 part = expand_shift (LSHIFT_EXPR, word_mode, part,
02094 build_int_cst (NULL_TREE,
02095 bitsdone - thissize), 0, 1);
02096 }
02097
02098 if (first)
02099 result = part;
02100 else
02101
02102
02103 result = expand_binop (word_mode, ior_optab, part, result, NULL_RTX, 1,
02104 OPTAB_LIB_WIDEN);
02105
02106 first = 0;
02107 }
02108
02109
02110 if (unsignedp)
02111 return result;
02112
02113 result = expand_shift (LSHIFT_EXPR, word_mode, result,
02114 build_int_cst (NULL_TREE, BITS_PER_WORD - bitsize),
02115 NULL_RTX, 0);
02116 return expand_shift (RSHIFT_EXPR, word_mode, result,
02117 build_int_cst (NULL_TREE, BITS_PER_WORD - bitsize),
02118 NULL_RTX, 0);
02119 }
02120
02121
02122
02123 void
02124 expand_inc (rtx target, rtx inc)
02125 {
02126 rtx value = expand_binop (GET_MODE (target), add_optab,
02127 target, inc,
02128 target, 0, OPTAB_LIB_WIDEN);
02129 if (value != target)
02130 emit_move_insn (target, value);
02131 }
02132
02133
02134
02135 void
02136 expand_dec (rtx target, rtx dec)
02137 {
02138 rtx value = expand_binop (GET_MODE (target), sub_optab,
02139 target, dec,
02140 target, 0, OPTAB_LIB_WIDEN);
02141 if (value != target)
02142 emit_move_insn (target, value);
02143 }
02144
02145
02146
02147
02148
02149
02150
02151
02152 rtx
02153 expand_shift (enum tree_code code, enum machine_mode mode, rtx shifted,
02154 tree amount, rtx target, int unsignedp)
02155 {
02156 rtx op1, temp = 0;
02157 int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR);
02158 int rotate = (code == LROTATE_EXPR || code == RROTATE_EXPR);
02159 int try;
02160
02161
02162
02163
02164
02165 op1 = expand_expr (amount, NULL_RTX, VOIDmode, 0);
02166
02167 if (SHIFT_COUNT_TRUNCATED)
02168 {
02169 if (GET_CODE (op1) == CONST_INT
02170 && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
02171 (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (mode)))
02172 op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
02173 % GET_MODE_BITSIZE (mode));
02174 else if (GET_CODE (op1) == SUBREG
02175 && subreg_lowpart_p (op1))
02176 op1 = SUBREG_REG (op1);
02177 }
02178
02179 if (op1 == const0_rtx)
02180 return shifted;
02181
02182
02183
02184 if (code == LSHIFT_EXPR
02185 && GET_CODE (op1) == CONST_INT
02186 && INTVAL (op1) > 0
02187 && INTVAL (op1) < GET_MODE_BITSIZE (mode)
02188 && shift_cost[mode][INTVAL (op1)] > INTVAL (op1) * add_cost[mode])
02189 {
02190 int i;
02191 for (i = 0; i < INTVAL (op1); i++)
02192 {
02193 temp = force_reg (mode, shifted);
02194 shifted = expand_binop (mode, add_optab, temp, temp, NULL_RTX,
02195 unsignedp, OPTAB_LIB_WIDEN);
02196 }
02197 return shifted;
02198 }
02199
02200 for (try = 0; temp == 0 && try < 3; try++)
02201 {
02202 enum optab_methods methods;
02203
02204 if (try == 0)
02205 methods = OPTAB_DIRECT;
02206 else if (try == 1)
02207 methods = OPTAB_WIDEN;
02208 else
02209 methods = OPTAB_LIB_WIDEN;
02210
02211 if (rotate)
02212 {
02213
02214 if (methods == OPTAB_WIDEN)
02215 continue;
02216 else if (methods == OPTAB_LIB_WIDEN)
02217 {
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230 rtx subtarget = target == shifted ? 0 : target;
02231 rtx temp1;
02232 tree type = TREE_TYPE (amount);
02233 tree new_amount = make_tree (type, op1);
02234 tree other_amount
02235 = fold (build2 (MINUS_EXPR, type,
02236 build_int_cst (type, GET_MODE_BITSIZE (mode)),
02237 amount));
02238
02239 shifted = force_reg (mode, shifted);
02240
02241 temp = expand_shift (left ? LSHIFT_EXPR : RSHIFT_EXPR,
02242 mode, shifted, new_amount, subtarget, 1);
02243 temp1 = expand_shift (left ? RSHIFT_EXPR : LSHIFT_EXPR,
02244 mode, shifted, other_amount, 0, 1);
02245 return expand_binop (mode, ior_optab, temp, temp1, target,
02246 unsignedp, methods);
02247 }
02248
02249 temp = expand_binop (mode,
02250 left ? rotl_optab : rotr_optab,
02251 shifted, op1, target, unsignedp, methods);
02252
02253
02254
02255
02256 if (temp == 0 && GET_CODE (op1) == CONST_INT
02257 && INTVAL (op1) > 0
02258 && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
02259 temp = expand_binop (mode,
02260 left ? rotr_optab : rotl_optab,
02261 shifted,
02262 GEN_INT (GET_MODE_BITSIZE (mode)
02263 - INTVAL (op1)),
02264 target, unsignedp, methods);
02265 }
02266 else if (unsignedp)
02267 temp = expand_binop (mode,
02268 left ? ashl_optab : lshr_optab,
02269 shifted, op1, target, unsignedp, methods);
02270
02271
02272
02273
02274 if (temp == 0 && ! rotate
02275 && (! unsignedp || (! left && methods == OPTAB_WIDEN)))
02276 {
02277 enum optab_methods methods1 = methods;
02278
02279
02280
02281 if (unsignedp)
02282 methods1 = OPTAB_MUST_WIDEN;
02283
02284
02285
02286 temp = expand_binop (mode,
02287 left ? ashl_optab : ashr_optab,
02288 shifted, op1, target, unsignedp, methods1);
02289 }
02290
02291
02292
02293
02294
02295 }
02296
02297 gcc_assert (temp);
02298 return temp;
02299 }
02300
02301 enum alg_code { alg_unknown, alg_zero, alg_m, alg_shift,
02302 alg_add_t_m2, alg_sub_t_m2,
02303 alg_add_factor, alg_sub_factor,
02304 alg_add_t2_m, alg_sub_t2_m };
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317 struct mult_cost {
02318 short cost;
02319 short latency;
02320 };
02321
02322
02323
02324
02325 #define MULT_COST_LESS(X,Y) ((X)->cost < (Y) \
02326 || ((X)->cost == (Y) && (X)->latency < (Y)))
02327
02328
02329
02330
02331
02332 #define CHEAPER_MULT_COST(X,Y) ((X)->cost < (Y)->cost \
02333 || ((X)->cost == (Y)->cost \
02334 && (X)->latency < (Y)->latency))
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355 struct algorithm
02356 {
02357 struct mult_cost cost;
02358 short ops;
02359
02360
02361
02362
02363
02364 enum alg_code op[MAX_BITS_PER_WORD];
02365 char log[MAX_BITS_PER_WORD];
02366 };
02367
02368
02369 struct alg_hash_entry {
02370
02371 unsigned int t;
02372
02373
02374 enum machine_mode mode;
02375
02376
02377 enum alg_code alg;
02378 };
02379
02380
02381 #define NUM_ALG_HASH_ENTRIES 307
02382
02383
02384
02385
02386 static struct alg_hash_entry alg_hash[NUM_ALG_HASH_ENTRIES];
02387
02388
02389
02390
02391
02392 enum mult_variant {basic_variant, negate_variant, add_variant};
02393
02394 static void synth_mult (struct algorithm *, unsigned HOST_WIDE_INT,
02395 const struct mult_cost *, enum machine_mode mode);
02396 static bool choose_mult_variant (enum machine_mode, HOST_WIDE_INT,
02397 struct algorithm *, enum mult_variant *, int);
02398 static rtx expand_mult_const (enum machine_mode, rtx, HOST_WIDE_INT, rtx,
02399 const struct algorithm *, enum mult_variant);
02400 static unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
02401 int, rtx *, int *, int *);
02402 static unsigned HOST_WIDE_INT invert_mod2n (unsigned HOST_WIDE_INT, int);
02403 static rtx extract_high_half (enum machine_mode, rtx);
02404 static rtx expand_mult_highpart (enum machine_mode, rtx, rtx, rtx, int, int);
02405 static rtx expand_mult_highpart_optab (enum machine_mode, rtx, rtx, rtx,
02406 int, int);
02407
02408
02409
02410
02411
02412
02413 static void
02414 synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
02415 const struct mult_cost *cost_limit, enum machine_mode mode)
02416 {
02417 int m;
02418 struct algorithm *alg_in, *best_alg;
02419 struct mult_cost best_cost;
02420 struct mult_cost new_limit;
02421 int op_cost, op_latency;
02422 unsigned HOST_WIDE_INT q;
02423 int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode));
02424 int hash_index;
02425 bool cache_hit = false;
02426 enum alg_code cache_alg = alg_zero;
02427
02428
02429
02430 alg_out->cost.cost = cost_limit->cost + 1;
02431 alg_out->cost.latency = cost_limit->latency + 1;
02432
02433 if (cost_limit->cost < 0
02434 || (cost_limit->cost == 0 && cost_limit->latency <= 0))
02435 return;
02436
02437
02438 t &= GET_MODE_MASK (mode);
02439
02440
02441 if (t == 1)
02442 {
02443 alg_out->ops = 1;
02444 alg_out->cost.cost = 0;
02445 alg_out->cost.latency = 0;
02446 alg_out->op[0] = alg_m;
02447 return;
02448 }
02449
02450
02451
02452 if (t == 0)
02453 {
02454 if (MULT_COST_LESS (cost_limit, zero_cost))
02455 return;
02456 else
02457 {
02458 alg_out->ops = 1;
02459 alg_out->cost.cost = zero_cost;
02460 alg_out->cost.latency = zero_cost;
02461 alg_out->op[0] = alg_zero;
02462 return;
02463 }
02464 }
02465
02466
02467
02468 alg_in = alloca (sizeof (struct algorithm));
02469 best_alg = alloca (sizeof (struct algorithm));
02470 best_cost = *cost_limit;
02471
02472
02473 hash_index = (t ^ (unsigned int) mode) % NUM_ALG_HASH_ENTRIES;
02474
02475
02476 if (alg_hash[hash_index].t == t
02477 && alg_hash[hash_index].mode == mode
02478 && alg_hash[hash_index].alg != alg_unknown)
02479 {
02480 cache_hit = true;
02481 cache_alg = alg_hash[hash_index].alg;
02482 switch (cache_alg)
02483 {
02484 case alg_shift:
02485 goto do_alg_shift;
02486
02487 case alg_add_t_m2:
02488 case alg_sub_t_m2:
02489 goto do_alg_addsub_t_m2;
02490
02491 case alg_add_factor:
02492 case alg_sub_factor:
02493 goto do_alg_addsub_factor;
02494
02495 case alg_add_t2_m:
02496 goto do_alg_add_t2_m;
02497
02498 case alg_sub_t2_m:
02499 goto do_alg_sub_t2_m;
02500
02501 default:
02502 gcc_unreachable ();
02503 }
02504 }
02505
02506
02507
02508
02509 if ((t & 1) == 0)
02510 {
02511 do_alg_shift:
02512 m = floor_log2 (t & -t);
02513 if (m < maxm)
02514 {
02515 q = t >> m;
02516
02517
02518
02519 op_cost = m * add_cost[mode];
02520 if (shift_cost[mode][m] < op_cost)
02521 op_cost = shift_cost[mode][m];
02522 new_limit.cost = best_cost.cost - op_cost;
02523 new_limit.latency = best_cost.latency - op_cost;
02524 synth_mult (alg_in, q, &new_limit, mode);
02525
02526 alg_in->cost.cost += op_cost;
02527 alg_in->cost.latency += op_cost;
02528 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02529 {
02530 struct algorithm *x;
02531 best_cost = alg_in->cost;
02532 x = alg_in, alg_in = best_alg, best_alg = x;
02533 best_alg->log[best_alg->ops] = m;
02534 best_alg->op[best_alg->ops] = alg_shift;
02535 }
02536 }
02537 if (cache_hit)
02538 goto done;
02539 }
02540
02541
02542 if ((t & 1) != 0)
02543 {
02544 unsigned HOST_WIDE_INT w;
02545
02546 do_alg_addsub_t_m2:
02547 for (w = 1; (w & t) != 0; w <<= 1)
02548 ;
02549
02550
02551
02552
02553
02554 if (w == 0
02555 || (w > 2
02556
02557
02558 && t != 3))
02559 {
02560
02561
02562 op_cost = add_cost[mode];
02563 new_limit.cost = best_cost.cost - op_cost;
02564 new_limit.latency = best_cost.latency - op_cost;
02565 synth_mult (alg_in, t + 1, &new_limit, mode);
02566
02567 alg_in->cost.cost += op_cost;
02568 alg_in->cost.latency += op_cost;
02569 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02570 {
02571 struct algorithm *x;
02572 best_cost = alg_in->cost;
02573 x = alg_in, alg_in = best_alg, best_alg = x;
02574 best_alg->log[best_alg->ops] = 0;
02575 best_alg->op[best_alg->ops] = alg_sub_t_m2;
02576 }
02577 }
02578 else
02579 {
02580
02581
02582 op_cost = add_cost[mode];
02583 new_limit.cost = best_cost.cost - op_cost;
02584 new_limit.latency = best_cost.latency - op_cost;
02585 synth_mult (alg_in, t - 1, &new_limit, mode);
02586
02587 alg_in->cost.cost += op_cost;
02588 alg_in->cost.latency += op_cost;
02589 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02590 {
02591 struct algorithm *x;
02592 best_cost = alg_in->cost;
02593 x = alg_in, alg_in = best_alg, best_alg = x;
02594 best_alg->log[best_alg->ops] = 0;
02595 best_alg->op[best_alg->ops] = alg_add_t_m2;
02596 }
02597 }
02598 if (cache_hit)
02599 goto done;
02600 }
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612 do_alg_addsub_factor:
02613 for (m = floor_log2 (t - 1); m >= 2; m--)
02614 {
02615 unsigned HOST_WIDE_INT d;
02616
02617 d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
02618 if (t % d == 0 && t > d && m < maxm
02619 && (!cache_hit || cache_alg == alg_add_factor))
02620 {
02621
02622
02623
02624
02625
02626
02627 op_cost = add_cost[mode] + shift_cost[mode][m];
02628 if (shiftadd_cost[mode][m] < op_cost)
02629 {
02630 op_cost = shiftadd_cost[mode][m];
02631 op_latency = op_cost;
02632 }
02633 else
02634 op_latency = add_cost[mode];
02635
02636 new_limit.cost = best_cost.cost - op_cost;
02637 new_limit.latency = best_cost.latency - op_latency;
02638 synth_mult (alg_in, t / d, &new_limit, mode);
02639
02640 alg_in->cost.cost += op_cost;
02641 alg_in->cost.latency += op_latency;
02642 if (alg_in->cost.latency < op_cost)
02643 alg_in->cost.latency = op_cost;
02644 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02645 {
02646 struct algorithm *x;
02647 best_cost = alg_in->cost;
02648 x = alg_in, alg_in = best_alg, best_alg = x;
02649 best_alg->log[best_alg->ops] = m;
02650 best_alg->op[best_alg->ops] = alg_add_factor;
02651 }
02652
02653 break;
02654 }
02655
02656 d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
02657 if (t % d == 0 && t > d && m < maxm
02658 && (!cache_hit || cache_alg == alg_sub_factor))
02659 {
02660
02661
02662
02663
02664
02665
02666 op_cost = add_cost[mode] + shift_cost[mode][m];
02667 if (shiftsub_cost[mode][m] < op_cost)
02668 {
02669 op_cost = shiftsub_cost[mode][m];
02670 op_latency = op_cost;
02671 }
02672 else
02673 op_latency = add_cost[mode];
02674
02675 new_limit.cost = best_cost.cost - op_cost;
02676 new_limit.latency = best_cost.latency - op_latency;
02677 synth_mult (alg_in, t / d, &new_limit, mode);
02678
02679 alg_in->cost.cost += op_cost;
02680 alg_in->cost.latency += op_latency;
02681 if (alg_in->cost.latency < op_cost)
02682 alg_in->cost.latency = op_cost;
02683 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02684 {
02685 struct algorithm *x;
02686 best_cost = alg_in->cost;
02687 x = alg_in, alg_in = best_alg, best_alg = x;
02688 best_alg->log[best_alg->ops] = m;
02689 best_alg->op[best_alg->ops] = alg_sub_factor;
02690 }
02691 break;
02692 }
02693 }
02694 if (cache_hit)
02695 goto done;
02696
02697
02698
02699 if ((t & 1) != 0)
02700 {
02701 do_alg_add_t2_m:
02702 q = t - 1;
02703 q = q & -q;
02704 m = exact_log2 (q);
02705 if (m >= 0 && m < maxm)
02706 {
02707 op_cost = shiftadd_cost[mode][m];
02708 new_limit.cost = best_cost.cost - op_cost;
02709 new_limit.latency = best_cost.latency - op_cost;
02710 synth_mult (alg_in, (t - 1) >> m, &new_limit, mode);
02711
02712 alg_in->cost.cost += op_cost;
02713 alg_in->cost.latency += op_cost;
02714 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02715 {
02716 struct algorithm *x;
02717 best_cost = alg_in->cost;
02718 x = alg_in, alg_in = best_alg, best_alg = x;
02719 best_alg->log[best_alg->ops] = m;
02720 best_alg->op[best_alg->ops] = alg_add_t2_m;
02721 }
02722 }
02723 if (cache_hit)
02724 goto done;
02725
02726 do_alg_sub_t2_m:
02727 q = t + 1;
02728 q = q & -q;
02729 m = exact_log2 (q);
02730 if (m >= 0 && m < maxm)
02731 {
02732 op_cost = shiftsub_cost[mode][m];
02733 new_limit.cost = best_cost.cost - op_cost;
02734 new_limit.latency = best_cost.latency - op_cost;
02735 synth_mult (alg_in, (t + 1) >> m, &new_limit, mode);
02736
02737 alg_in->cost.cost += op_cost;
02738 alg_in->cost.latency += op_cost;
02739 if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
02740 {
02741 struct algorithm *x;
02742 best_cost = alg_in->cost;
02743 x = alg_in, alg_in = best_alg, best_alg = x;
02744 best_alg->log[best_alg->ops] = m;
02745 best_alg->op[best_alg->ops] = alg_sub_t2_m;
02746 }
02747 }
02748 if (cache_hit)
02749 goto done;
02750 }
02751
02752 done:
02753
02754 if (!CHEAPER_MULT_COST (&best_cost, cost_limit))
02755 return;
02756
02757
02758 if (!cache_hit)
02759 {
02760 alg_hash[hash_index].t = t;
02761 alg_hash[hash_index].mode = mode;
02762 alg_hash[hash_index].alg = best_alg->op[best_alg->ops];
02763 }
02764
02765
02766
02767 if (best_alg->ops == MAX_BITS_PER_WORD)
02768 return;
02769
02770
02771
02772
02773 alg_out->ops = best_alg->ops + 1;
02774 alg_out->cost = best_cost;
02775 memcpy (alg_out->op, best_alg->op,
02776 alg_out->ops * sizeof *alg_out->op);
02777 memcpy (alg_out->log, best_alg->log,
02778 alg_out->ops * sizeof *alg_out->log);
02779 }
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791 static bool
02792 choose_mult_variant (enum machine_mode mode, HOST_WIDE_INT val,
02793 struct algorithm *alg, enum mult_variant *variant,
02794 int mult_cost)
02795 {
02796 struct algorithm alg2;
02797 struct mult_cost limit;
02798 int op_cost;
02799
02800 *variant = basic_variant;
02801 limit.cost = mult_cost;
02802 limit.latency = mult_cost;
02803 synth_mult (alg, val, &limit, mode);
02804
02805
02806
02807 if (HOST_BITS_PER_INT >= GET_MODE_BITSIZE (mode))
02808 {
02809 op_cost = neg_cost[mode];
02810 if (MULT_COST_LESS (&alg->cost, mult_cost))
02811 {
02812 limit.cost = alg->cost.cost - op_cost;
02813 limit.latency = alg->cost.latency - op_cost;
02814 }
02815 else
02816 {
02817 limit.cost = mult_cost - op_cost;
02818 limit.latency = mult_cost - op_cost;
02819 }
02820
02821 synth_mult (&alg2, -val, &limit, mode);
02822 alg2.cost.cost += op_cost;
02823 alg2.cost.latency += op_cost;
02824 if (CHEAPER_MULT_COST (&alg2.cost, &alg->cost))
02825 *alg = alg2, *variant = negate_variant;
02826 }
02827
02828
02829 op_cost = add_cost[mode];
02830 if (MULT_COST_LESS (&alg->cost, mult_cost))
02831 {
02832 limit.cost = alg->cost.cost - op_cost;
02833 limit.latency = alg->cost.latency - op_cost;
02834 }
02835 else
02836 {
02837 limit.cost = mult_cost - op_cost;
02838 limit.latency = mult_cost - op_cost;
02839 }
02840
02841 synth_mult (&alg2, val - 1, &limit, mode);
02842 alg2.cost.cost += op_cost;
02843 alg2.cost.latency += op_cost;
02844 if (CHEAPER_MULT_COST (&alg2.cost, &alg->cost))
02845 *alg = alg2, *variant = add_variant;
02846
02847 return MULT_COST_LESS (&alg->cost, mult_cost);
02848 }
02849
02850
02851
02852
02853
02854
02855 static rtx
02856 expand_mult_const (enum machine_mode mode, rtx op0, HOST_WIDE_INT val,
02857 rtx target, const struct algorithm *alg,
02858 enum mult_variant variant)
02859 {
02860 HOST_WIDE_INT val_so_far;
02861 rtx insn, accum, tem;
02862 int opno;
02863 enum machine_mode nmode;
02864
02865
02866
02867 if (MEM_P (op0))
02868 op0 = force_reg (mode, op0);
02869
02870
02871
02872
02873 if (alg->op[0] == alg_zero)
02874 {
02875 accum = copy_to_mode_reg (mode, const0_rtx);
02876 val_so_far = 0;
02877 }
02878 else if (alg->op[0] == alg_m)
02879 {
02880 accum = copy_to_mode_reg (mode, op0);
02881 val_so_far = 1;
02882 }
02883 else
02884 gcc_unreachable ();
02885
02886 for (opno = 1; opno < alg->ops; opno++)
02887 {
02888 int log = alg->log[opno];
02889 rtx shift_subtarget = optimize ? 0 : accum;
02890 rtx add_target
02891 = (opno == alg->ops - 1 && target != 0 && variant != add_variant
02892 && !optimize)
02893 ? target : 0;
02894 rtx accum_target = optimize ? 0 : accum;
02895
02896 switch (alg->op[opno])
02897 {
02898 case alg_shift:
02899 accum = expand_shift (LSHIFT_EXPR, mode, accum,
02900 build_int_cst (NULL_TREE, log),
02901 NULL_RTX, 0);
02902 val_so_far <<= log;
02903 break;
02904
02905 case alg_add_t_m2:
02906 tem = expand_shift (LSHIFT_EXPR, mode, op0,
02907 build_int_cst (NULL_TREE, log),
02908 NULL_RTX, 0);
02909 accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
02910 add_target ? add_target : accum_target);
02911 val_so_far += (HOST_WIDE_INT) 1 << log;
02912 break;
02913
02914 case alg_sub_t_m2:
02915 tem = expand_shift (LSHIFT_EXPR, mode, op0,
02916 build_int_cst (NULL_TREE, log),
02917 NULL_RTX, 0);
02918 accum = force_operand (gen_rtx_MINUS (mode, accum, tem),
02919 add_target ? add_target : accum_target);
02920 val_so_far -= (HOST_WIDE_INT) 1 << log;
02921 break;
02922
02923 case alg_add_t2_m:
02924 accum = expand_shift (LSHIFT_EXPR, mode, accum,
02925 build_int_cst (NULL_TREE, log),
02926 shift_subtarget,
02927 0);
02928 accum = force_operand (gen_rtx_PLUS (mode, accum, op0),
02929 add_target ? add_target : accum_target);
02930 val_so_far = (val_so_far << log) + 1;
02931 break;
02932
02933 case alg_sub_t2_m:
02934 accum = expand_shift (LSHIFT_EXPR, mode, accum,
02935 build_int_cst (NULL_TREE, log),
02936 shift_subtarget, 0);
02937 accum = force_operand (gen_rtx_MINUS (mode, accum, op0),
02938 add_target ? add_target : accum_target);
02939 val_so_far = (val_so_far << log) - 1;
02940 break;
02941
02942 case alg_add_factor:
02943 tem = expand_shift (LSHIFT_EXPR, mode, accum,
02944 build_int_cst (NULL_TREE, log),
02945 NULL_RTX, 0);
02946 accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
02947 add_target ? add_target : accum_target);
02948 val_so_far += val_so_far << log;
02949 break;
02950
02951 case alg_sub_factor:
02952 tem = expand_shift (LSHIFT_EXPR, mode, accum,
02953 build_int_cst (NULL_TREE, log),
02954 NULL_RTX, 0);
02955 accum = force_operand (gen_rtx_MINUS (mode, tem, accum),
02956 (add_target
02957 ? add_target : (optimize ? 0 : tem)));
02958 val_so_far = (val_so_far << log) - val_so_far;
02959 break;
02960
02961 default:
02962 gcc_unreachable ();
02963 }
02964
02965
02966
02967
02968
02969
02970 tem = op0, nmode = mode;
02971 if (GET_CODE (accum) == SUBREG)
02972 {
02973 nmode = GET_MODE (SUBREG_REG (accum));
02974 tem = gen_lowpart (nmode, op0);
02975 }
02976
02977 insn = get_last_insn ();
02978 set_unique_reg_note (insn, REG_EQUAL,
02979 gen_rtx_MULT (nmode, tem, GEN_INT (val_so_far)));
02980 }
02981
02982 if (variant == negate_variant)
02983 {
02984 val_so_far = -val_so_far;
02985 accum = expand_unop (mode, neg_optab, accum, target, 0);
02986 }
02987 else if (variant == add_variant)
02988 {
02989 val_so_far = val_so_far + 1;
02990 accum = force_operand (gen_rtx_PLUS (mode, accum, op0), target);
02991 }
02992
02993
02994
02995 val &= GET_MODE_MASK (mode);
02996 val_so_far &= GET_MODE_MASK (mode);
02997 gcc_assert (val == val_so_far);
02998
02999 return accum;
03000 }
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010 rtx
03011 expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
03012 int unsignedp)
03013 {
03014 rtx const_op1 = op1;
03015 enum mult_variant variant;
03016 struct algorithm algorithm;
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027 if (GET_CODE (op1) == CONST_DOUBLE
03028 && GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT
03029 && HOST_BITS_PER_INT >= BITS_PER_WORD
03030 && CONST_DOUBLE_HIGH (op1) == 0)
03031 const_op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
03032 else if (HOST_BITS_PER_INT < GET_MODE_BITSIZE (mode)
03033 && GET_CODE (op1) == CONST_INT
03034 && INTVAL (op1) < 0)
03035 const_op1 = 0;
03036
03037
03038
03039
03040
03041
03042 if (const_op1 && GET_CODE (const_op1) == CONST_INT
03043 && (unsignedp || !flag_trapv))
03044 {
03045 HOST_WIDE_INT coeff = INTVAL (const_op1);
03046 int mult_cost;
03047
03048
03049 if (EXACT_POWER_OF_2_OR_ZERO_P (coeff))
03050 {
03051 if (coeff == 0)
03052 return const0_rtx;
03053 if (coeff == 1)
03054 return op0;
03055 return expand_shift (LSHIFT_EXPR, mode, op0,
03056 build_int_cst (NULL_TREE, floor_log2 (coeff)),
03057 target, unsignedp);
03058 }
03059
03060 mult_cost = rtx_cost (gen_rtx_MULT (mode, op0, op1), SET);
03061 if (choose_mult_variant (mode, coeff, &algorithm, &variant,
03062 mult_cost))
03063 return expand_mult_const (mode, op0, coeff, target,
03064 &algorithm, variant);
03065 }
03066
03067 if (GET_CODE (op0) == CONST_DOUBLE)
03068 {
03069 rtx temp = op0;
03070 op0 = op1;
03071 op1 = temp;
03072 }
03073
03074
03075 if (GET_CODE (op1) == CONST_DOUBLE
03076 && GET_MODE_CLASS (mode) == MODE_FLOAT)
03077 {
03078 REAL_VALUE_TYPE d;
03079 REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
03080
03081 if (REAL_VALUES_EQUAL (d, dconst2))
03082 {
03083 op0 = force_reg (GET_MODE (op0), op0);
03084 return expand_binop (mode, add_optab, op0, op0,
03085 target, unsignedp, OPTAB_LIB_WIDEN);
03086 }
03087 }
03088
03089
03090
03091 op0 = expand_binop (mode,
03092 ! unsignedp
03093 && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
03094 ? smulv_optab : smul_optab,
03095 op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
03096 gcc_assert (op0);
03097 return op0;
03098 }
03099
03100
03101
03102 int
03103 ceil_log2 (unsigned HOST_WIDE_INT x)
03104 {
03105 return floor_log2 (x - 1) + 1;
03106 }
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124 static
03125 unsigned HOST_WIDE_INT
03126 choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
03127 rtx *multiplier_ptr, int *post_shift_ptr, int *lgup_ptr)
03128 {
03129 HOST_WIDE_INT mhigh_hi, mlow_hi;
03130 unsigned HOST_WIDE_INT mhigh_lo, mlow_lo;
03131 int lgup, post_shift;
03132 int pow, pow2;
03133 unsigned HOST_WIDE_INT nl, dummy1;
03134 HOST_WIDE_INT nh, dummy2;
03135
03136
03137 lgup = ceil_log2 (d);
03138
03139 gcc_assert (lgup <= n);
03140
03141 pow = n + lgup;
03142 pow2 = n + lgup - precision;
03143
03144
03145
03146
03147 gcc_assert (pow != 2 * HOST_BITS_PER_WIDE_INT);
03148
03149
03150 if (pow >= HOST_BITS_PER_WIDE_INT)
03151 {
03152 nh = (HOST_WIDE_INT) 1 << (pow - HOST_BITS_PER_WIDE_INT);
03153 nl = 0;
03154 }
03155 else
03156 {
03157 nh = 0;
03158 nl = (unsigned HOST_WIDE_INT) 1 << pow;
03159 }
03160 div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
03161 &mlow_lo, &mlow_hi, &dummy1, &dummy2);
03162
03163
03164 if (pow2 >= HOST_BITS_PER_WIDE_INT)
03165 nh |= (HOST_WIDE_INT) 1 << (pow2 - HOST_BITS_PER_WIDE_INT);
03166 else
03167 nl |= (unsigned HOST_WIDE_INT) 1 << pow2;
03168 div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
03169 &mhigh_lo, &mhigh_hi, &dummy1, &dummy2);
03170
03171 gcc_assert (!mhigh_hi || nh - d < d);
03172 gcc_assert (mhigh_hi <= 1 && mlow_hi <= 1);
03173
03174 gcc_assert (mlow_hi < mhigh_hi
03175 || (mlow_hi == mhigh_hi && mlow_lo < mhigh_lo));
03176
03177
03178
03179
03180
03181 for (post_shift = lgup; post_shift > 0; post_shift--)
03182 {
03183 unsigned HOST_WIDE_INT ml_lo = (mlow_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mlow_lo >> 1);
03184 unsigned HOST_WIDE_INT mh_lo = (mhigh_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mhigh_lo >> 1);
03185 if (ml_lo >= mh_lo)
03186 break;
03187
03188 mlow_hi = 0;
03189 mlow_lo = ml_lo;
03190 mhigh_hi = 0;
03191 mhigh_lo = mh_lo;
03192 }
03193
03194 *post_shift_ptr = post_shift;
03195 *lgup_ptr = lgup;
03196 if (n < HOST_BITS_PER_WIDE_INT)
03197 {
03198 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT) 1 << n) - 1;
03199 *multiplier_ptr = GEN_INT (mhigh_lo & mask);
03200 return mhigh_lo >= mask;
03201 }
03202 else
03203 {
03204 *multiplier_ptr = GEN_INT (mhigh_lo);
03205 return mhigh_hi;
03206 }
03207 }
03208
03209
03210
03211
03212 static unsigned HOST_WIDE_INT
03213 invert_mod2n (unsigned HOST_WIDE_INT x, int n)
03214 {
03215
03216
03217
03218
03219
03220
03221 unsigned HOST_WIDE_INT mask;
03222 unsigned HOST_WIDE_INT y = x;
03223 int nbit = 3;
03224
03225 mask = (n == HOST_BITS_PER_WIDE_INT
03226 ? ~(unsigned HOST_WIDE_INT) 0
03227 : ((unsigned HOST_WIDE_INT) 1 << n) - 1);
03228
03229 while (nbit < n)
03230 {
03231 y = y * (2 - x*y) & mask;
03232 nbit *= 2;
03233 }
03234 return y;
03235 }
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247 rtx
03248 expand_mult_highpart_adjust (enum machine_mode mode, rtx adj_operand, rtx op0,
03249 rtx op1, rtx target, int unsignedp)
03250 {
03251 rtx tem;
03252 enum rtx_code adj_code = unsignedp ? PLUS : MINUS;
03253
03254 tem = expand_shift (RSHIFT_EXPR, mode, op0,
03255 build_int_cst (NULL_TREE, GET_MODE_BITSIZE (mode) - 1),
03256 NULL_RTX, 0);
03257 tem = expand_and (mode, tem, op1, NULL_RTX);
03258 adj_operand
03259 = force_operand (gen_rtx_fmt_ee (adj_code, mode, adj_operand, tem),
03260 adj_operand);
03261
03262 tem = expand_shift (RSHIFT_EXPR, mode, op1,
03263 build_int_cst (NULL_TREE, GET_MODE_BITSIZE (mode) - 1),
03264 NULL_RTX, 0);
03265 tem = expand_and (mode, tem, op0, NULL_RTX);
03266 target = force_operand (gen_rtx_fmt_ee (adj_code, mode, adj_operand, tem),
03267 target);
03268
03269 return target;
03270 }
03271
03272
03273
03274 static rtx
03275 extract_high_half (enum machine_mode mode, rtx op)
03276 {
03277 enum machine_mode wider_mode;
03278
03279 if (mode == word_mode)
03280 return gen_highpart (mode, op);
03281
03282 wider_mode = GET_MODE_WIDER_MODE (mode);
03283 op = expand_shift (RSHIFT_EXPR, wider_mode, op,
03284 build_int_cst (NULL_TREE, GET_MODE_BITSIZE (mode)), 0, 1);
03285 return convert_modes (mode, wider_mode, op, 0);
03286 }
03287
03288
03289
03290
03291 static rtx
03292 expand_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1,
03293 rtx target, int unsignedp, int max_cost)
03294 {
03295 rtx narrow_op1 = gen_int_mode (INTVAL (op1), mode);
03296 enum machine_mode wider_mode;
03297 optab moptab;
03298 rtx tem;
03299 int size;
03300
03301 wider_mode = GET_MODE_WIDER_MODE (mode);
03302 size = GET_MODE_BITSIZE (mode);
03303
03304
03305
03306 if (mul_highpart_cost[mode] < max_cost)
03307 {
03308 moptab = unsignedp ? umul_highpart_optab : smul_highpart_optab;
03309 tem = expand_binop (mode, moptab, op0, narrow_op1, target,
03310 unsignedp, OPTAB_DIRECT);
03311 if (tem)
03312 return tem;
03313 }
03314
03315
03316
03317 if (size - 1 < BITS_PER_WORD
03318 && (mul_highpart_cost[mode] + 2 * shift_cost[mode][size-1]
03319 + 4 * add_cost[mode] < max_cost))
03320 {
03321 moptab = unsignedp ? smul_highpart_optab : umul_highpart_optab;
03322 tem = expand_binop (mode, moptab, op0, narrow_op1, target,
03323 unsignedp, OPTAB_DIRECT);
03324 if (tem)
03325
03326 return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1,
03327 tem, unsignedp);
03328 }
03329
03330
03331 moptab = unsignedp ? umul_widen_optab : smul_widen_optab;
03332 if (moptab->handlers[wider_mode].insn_code != CODE_FOR_nothing
03333 && mul_widen_cost[wider_mode] < max_cost)
03334 {
03335 tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0,
03336 unsignedp, OPTAB_WIDEN);
03337 if (tem)
03338 return extract_high_half (mode, tem);
03339 }
03340
03341
03342 if (smul_optab->handlers[wider_mode].insn_code != CODE_FOR_nothing
03343 && size - 1 < BITS_PER_WORD
03344 && mul_cost[wider_mode] + shift_cost[mode][size-1] < max_cost)
03345 {
03346 rtx insns, wop0, wop1;
03347
03348
03349
03350
03351
03352 start_sequence ();
03353 wop0 = convert_modes (wider_mode, mode, op0, unsignedp);
03354 wop1 = convert_modes (wider_mode, mode, op1, unsignedp);
03355 tem = expand_binop (wider_mode, smul_optab, wop0, wop1, 0,
03356 unsignedp, OPTAB_WIDEN);
03357 insns = get_insns ();
03358 end_sequence ();
03359
03360 if (tem)
03361 {
03362 emit_insn (insns);
03363 return extract_high_half (mode, tem);
03364 }
03365 }
03366
03367
03368 moptab = unsignedp ? smul_widen_optab : umul_widen_optab;
03369 if (moptab->handlers[wider_mode].insn_code != CODE_FOR_nothing
03370 && size - 1 < BITS_PER_WORD
03371 && (mul_widen_cost[wider_mode] + 2 * shift_cost[mode][size-1]
03372 + 4 * add_cost[mode] < max_cost))
03373 {
03374 tem = expand_binop (wider_mode, moptab, op0, narrow_op1,
03375 NULL_RTX, ! unsignedp, OPTAB_WIDEN);
03376 if (tem != 0)
03377 {
03378 tem = extract_high_half (mode, tem);
03379
03380 return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1,
03381 target, unsignedp);
03382 }
03383 }
03384
03385 return 0;
03386 }
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399 static rtx
03400 expand_mult_highpart (enum machine_mode mode, rtx op0, rtx op1,
03401 rtx target, int unsignedp, int max_cost)
03402 {
03403 enum machine_mode wider_mode = GET_MODE_WIDER_MODE (mode);
03404 unsigned HOST_WIDE_INT cnst1;
03405 int extra_cost;
03406 bool sign_adjust = false;
03407 enum mult_variant variant;
03408 struct algorithm alg;
03409 rtx tem;
03410
03411
03412 gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT);
03413
03414 cnst1 = INTVAL (op1) & GET_MODE_MASK (mode);
03415
03416
03417
03418
03419
03420 if (GET_MODE_BITSIZE (wider_mode) > BITS_PER_WORD)
03421 return expand_mult_highpart_optab (mode, op0, op1, target,
03422 unsignedp, max_cost);
03423
03424 extra_cost = shift_cost[mode][GET_MODE_BITSIZE (mode) - 1];
03425
03426
03427 if (!unsignedp && ((cnst1 >> (GET_MODE_BITSIZE (mode) - 1)) & 1))
03428 {
03429 sign_adjust = true;
03430 extra_cost += add_cost[mode];
03431 }
03432
03433
03434 if (choose_mult_variant (wider_mode, cnst1, &alg, &variant,
03435 max_cost - extra_cost))
03436 {
03437
03438
03439 tem = expand_mult_highpart_optab (mode, op0, op1, target, unsignedp,
03440 alg.cost.cost + extra_cost);
03441 if (tem)
03442 return tem;
03443
03444 tem = convert_to_mode (wider_mode, op0, unsignedp);
03445 tem = expand_mult_const (wider_mode, tem, cnst1, 0, &alg, variant);
03446 tem = extract_high_half (mode, tem);
03447
03448
03449 if (sign_adjust)
03450 tem = force_operand (gen_rtx_MINUS (mode, tem, op0), tem);
03451
03452 return tem;
03453 }
03454 return expand_mult_highpart_optab (mode, op0, op1, target,
03455 unsignedp, max_cost);
03456 }
03457
03458
03459
03460
03461 static rtx
03462 expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
03463 {
03464 unsigned HOST_WIDE_INT masklow, maskhigh;
03465 rtx result, temp, shift, label;
03466 int logd;
03467
03468 logd = floor_log2 (d);
03469 result = gen_reg_rtx (mode);
03470
03471
03472 if (BRANCH_COST >= 2
03473 && !optimize_size)
03474 {
03475 rtx signmask = emit_store_flag (result, LT, op0, const0_rtx,
03476 mode, 0, -1);
03477 if (signmask)
03478 {
03479 signmask = force_reg (mode, signmask);
03480 masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
03481 shift = GEN_INT (GET_MODE_BITSIZE (mode) - logd);
03482
03483
03484
03485
03486
03487
03488 temp = gen_rtx_LSHIFTRT (mode, result, shift);
03489 if (lshr_optab->handlers[mode].insn_code == CODE_FOR_nothing
03490 || rtx_cost (temp, SET) > COSTS_N_INSNS (2))
03491 {
03492 temp = expand_binop (mode, xor_optab, op0, signmask,
03493 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03494 temp = expand_binop (mode, sub_optab, temp, signmask,
03495 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03496 temp = expand_binop (mode, and_optab, temp, GEN_INT (masklow),
03497 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03498 temp = expand_binop (mode, xor_optab, temp, signmask,
03499 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03500 temp = expand_binop (mode, sub_optab, temp, signmask,
03501 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03502 }
03503 else
03504 {
03505 signmask = expand_binop (mode, lshr_optab, signmask, shift,
03506 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03507 signmask = force_reg (mode, signmask);
03508
03509 temp = expand_binop (mode, add_optab, op0, signmask,
03510 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03511 temp = expand_binop (mode, and_optab, temp, GEN_INT (masklow),
03512 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03513 temp = expand_binop (mode, sub_optab, temp, signmask,
03514 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03515 }
03516 return temp;
03517 }
03518 }
03519
03520
03521
03522
03523
03524
03525 masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
03526 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
03527 {
03528 masklow |= (HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) - 1);
03529 maskhigh = -1;
03530 }
03531 else
03532 maskhigh = (HOST_WIDE_INT) -1
03533 << (GET_MODE_BITSIZE (mode) - HOST_BITS_PER_WIDE_INT - 1);
03534
03535 temp = expand_binop (mode, and_optab, op0,
03536 immed_double_const (masklow, maskhigh, mode),
03537 result, 1, OPTAB_LIB_WIDEN);
03538 if (temp != result)
03539 emit_move_insn (result, temp);
03540
03541 label = gen_label_rtx ();
03542 do_cmp_and_jump (result, const0_rtx, GE, mode, label);
03543
03544 temp = expand_binop (mode, sub_optab, result, const1_rtx, result,
03545 0, OPTAB_LIB_WIDEN);
03546 masklow = (HOST_WIDE_INT) -1 << logd;
03547 maskhigh = -1;
03548 temp = expand_binop (mode, ior_optab, temp,
03549 immed_double_const (masklow, maskhigh, mode),
03550 result, 1, OPTAB_LIB_WIDEN);
03551 temp = expand_binop (mode, add_optab, temp, const1_rtx, result,
03552 0, OPTAB_LIB_WIDEN);
03553 if (temp != result)
03554 emit_move_insn (result, temp);
03555 emit_label (label);
03556 return result;
03557 }
03558
03559
03560
03561
03562 static rtx
03563 expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
03564 {
03565 rtx temp, label;
03566 tree shift;
03567 int logd;
03568
03569 logd = floor_log2 (d);
03570 shift = build_int_cst (NULL_TREE, logd);
03571
03572 if (d == 2 && BRANCH_COST >= 1)
03573 {
03574 temp = gen_reg_rtx (mode);
03575 temp = emit_store_flag (temp, LT, op0, const0_rtx, mode, 0, 1);
03576 temp = expand_binop (mode, add_optab, temp, op0, NULL_RTX,
03577 0, OPTAB_LIB_WIDEN);
03578 return expand_shift (RSHIFT_EXPR, mode, temp, shift, NULL_RTX, 0);
03579 }
03580
03581 #ifdef HAVE_conditional_move
03582 if (BRANCH_COST >= 2)
03583 {
03584 rtx temp2;
03585
03586
03587
03588
03589 do_pending_stack_adjust ();
03590
03591 start_sequence ();
03592 temp2 = copy_to_mode_reg (mode, op0);
03593 temp = expand_binop (mode, add_optab, temp2, GEN_INT (d-1),
03594 NULL_RTX, 0, OPTAB_LIB_WIDEN);
03595 temp = force_reg (mode, temp);
03596
03597
03598 temp2 = emit_conditional_move (temp2, LT, temp2, const0_rtx,
03599 mode, temp, temp2, mode, 0);
03600 if (temp2)
03601 {
03602 rtx seq = get_insns ();
03603 end_sequence ();
03604 emit_insn (seq);
03605 return expand_shift (RSHIFT_EXPR, mode, temp2, shift, NULL_RTX, 0);
03606 }
03607 end_sequence ();
03608 }
03609 #endif
03610
03611 if (BRANCH_COST >= 2)
03612 {
03613 int ushift = GET_MODE_BITSIZE (mode) - logd;
03614
03615 temp = gen_reg_rtx (mode);
03616 temp = emit_store_flag (temp, LT, op0, const0_rtx, mode, 0, -1);
03617 if (shift_cost[mode][ushift] > COSTS_N_INSNS (1))
03618 temp = expand_binop (mode, and_optab, temp, GEN_INT (d - 1),
03619 NULL_RTX, 0, OPTAB_LIB_WIDEN);
03620 else
03621 temp = expand_shift (RSHIFT_EXPR, mode, temp,
03622 build_int_cst (NULL_TREE, ushift),
03623 NULL_RTX, 1);
03624 temp = expand_binop (mode, add_optab, temp, op0, NULL_RTX,
03625 0, OPTAB_LIB_WIDEN);
03626 return expand_shift (RSHIFT_EXPR, mode, temp, shift, NULL_RTX, 0);
03627 }
03628
03629 label = gen_label_rtx ();
03630 temp = copy_to_mode_reg (mode, op0);
03631 do_cmp_and_jump (temp, const0_rtx, GE, mode, label);
03632 expand_inc (temp, GEN_INT (d - 1));
03633 emit_label (label);
03634 return expand_shift (RSHIFT_EXPR, mode, temp, shift, NULL_RTX, 0);
03635 }
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675 rtx
03676 expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
03677 rtx op0, rtx op1, rtx target, int unsignedp)
03678 {
03679 enum machine_mode compute_mode;
03680 rtx tquotient;
03681 rtx quotient = 0, remainder = 0;
03682 rtx last;
03683 int size;
03684 rtx insn, set;
03685 optab optab1, optab2;
03686 int op1_is_constant, op1_is_pow2 = 0;
03687 int max_cost, extra_cost;
03688 static HOST_WIDE_INT last_div_const = 0;
03689 static HOST_WIDE_INT ext_op1;
03690
03691 op1_is_constant = GET_CODE (op1) == CONST_INT;
03692 if (op1_is_constant)
03693 {
03694 ext_op1 = INTVAL (op1);
03695 if (unsignedp)
03696 ext_op1 &= GET_MODE_MASK (mode);
03697 op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1)
03698 || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-ext_op1))));
03699 }
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733 if (op1 == const1_rtx)
03734 return rem_flag ? const0_rtx : op0;
03735
03736
03737
03738 if (! unsignedp && op1 == constm1_rtx)
03739 {
03740 if (rem_flag)
03741 return const0_rtx;
03742 return expand_unop (mode, flag_trapv && GET_MODE_CLASS(mode) == MODE_INT
03743 ? negv_optab : neg_optab, op0, target, 0);
03744 }
03745
03746 if (target
03747
03748
03749
03750 && ((REG_P (target) && REG_FUNCTION_VALUE_P (target))
03751
03752 || ((rem_flag || op1_is_constant)
03753 && (reg_mentioned_p (target, op0)
03754 || (MEM_P (op0) && MEM_P (target))))
03755 || reg_mentioned_p (target, op1)
03756 || (MEM_P (op1) && MEM_P (target))))
03757 target = 0;
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779 optab1 = ((op1_is_pow2 && op1 != const0_rtx)
03780 ? (unsignedp ? lshr_optab : ashr_optab)
03781 : (unsignedp ? udiv_optab : sdiv_optab));
03782 optab2 = ((op1_is_pow2 && op1 != const0_rtx)
03783 ? optab1
03784 : (unsignedp ? udivmod_optab : sdivmod_optab));
03785
03786 for (compute_mode = mode; compute_mode != VOIDmode;
03787 compute_mode = GET_MODE_WIDER_MODE (compute_mode))
03788 if (optab1->handlers[compute_mode].insn_code != CODE_FOR_nothing
03789 || optab2->handlers[compute_mode].insn_code != CODE_FOR_nothing)
03790 break;
03791
03792 if (compute_mode == VOIDmode)
03793 for (compute_mode = mode; compute_mode != VOIDmode;
03794 compute_mode = GET_MODE_WIDER_MODE (compute_mode))
03795 if (optab1->handlers[compute_mode].libfunc
03796 || optab2->handlers[compute_mode].libfunc)
03797 break;
03798
03799
03800
03801 if (compute_mode == VOIDmode)
03802 compute_mode = mode;
03803
03804 if (target && GET_MODE (target) == compute_mode)
03805 tquotient = target;
03806 else
03807 tquotient = gen_reg_rtx (compute_mode);
03808
03809 size = GET_MODE_BITSIZE (compute_mode);
03810 #if 0
03811
03812
03813
03814 size = GET_MODE_BITSIZE (mode);
03815 #endif
03816
03817
03818
03819
03820 max_cost = div_cost[compute_mode]
03821 - (rem_flag && ! (last_div_const != 0 && op1_is_constant
03822 && INTVAL (op1) == last_div_const)
03823 ? mul_cost[compute_mode] + add_cost[compute_mode]
03824 : 0);
03825
03826 last_div_const = ! rem_flag && op1_is_constant ? INTVAL (op1) : 0;
03827
03828
03829 if (compute_mode != mode)
03830 {
03831 op0 = convert_modes (compute_mode, mode, op0, unsignedp);
03832 op1 = convert_modes (compute_mode, mode, op1, unsignedp);
03833
03834
03835
03836 op1_is_constant = GET_CODE (op1) == CONST_INT;
03837 op1_is_pow2 = (op1_is_constant
03838 && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
03839 || (! unsignedp
03840 && EXACT_POWER_OF_2_OR_ZERO_P (-INTVAL (op1)))))) ;
03841 }
03842
03843
03844
03845 if (MEM_P (op0) && MEM_VOLATILE_P (op0))
03846 op0 = force_reg (compute_mode, op0);
03847 if (MEM_P (op1) && MEM_VOLATILE_P (op1))
03848 op1 = force_reg (compute_mode, op1);
03849
03850
03851
03852 if (rem_flag || op1_is_constant)
03853 op0 = force_reg (compute_mode, op0);
03854
03855 last = get_last_insn ();
03856
03857
03858 if (unsignedp)
03859 {
03860 if (code == FLOOR_DIV_EXPR)
03861 code = TRUNC_DIV_EXPR;
03862 if (code == FLOOR_MOD_EXPR)
03863 code = TRUNC_MOD_EXPR;
03864 if (code == EXACT_DIV_EXPR && op1_is_pow2)
03865 code = TRUNC_DIV_EXPR;
03866 }
03867
03868 if (op1 != const0_rtx)
03869 switch (code)
03870 {
03871 case TRUNC_MOD_EXPR:
03872 case TRUNC_DIV_EXPR:
03873 if (op1_is_constant)
03874 {
03875 if (unsignedp)
03876 {
03877 unsigned HOST_WIDE_INT mh;
03878 int pre_shift, post_shift;
03879 int dummy;
03880 rtx ml;
03881 unsigned HOST_WIDE_INT d = (INTVAL (op1)
03882 & GET_MODE_MASK (compute_mode));
03883
03884 if (EXACT_POWER_OF_2_OR_ZERO_P (d))
03885 {
03886 pre_shift = floor_log2 (d);
03887 if (rem_flag)
03888 {
03889 remainder
03890 = expand_binop (compute_mode, and_optab, op0,
03891 GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
03892 remainder, 1,
03893 OPTAB_LIB_WIDEN);
03894 if (remainder)
03895 return gen_lowpart (mode, remainder);
03896 }
03897 quotient = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03898 build_int_cst (NULL_TREE,
03899 pre_shift),
03900 tquotient, 1);
03901 }
03902 else if (size <= HOST_BITS_PER_WIDE_INT)
03903 {
03904 if (d >= ((unsigned HOST_WIDE_INT) 1 << (size - 1)))
03905 {
03906
03907
03908 quotient = emit_store_flag (tquotient, GEU, op0, op1,
03909 compute_mode, 1, 1);
03910 if (quotient == 0)
03911 goto fail1;
03912 }
03913 else
03914 {
03915
03916
03917
03918 mh = choose_multiplier (d, size, size,
03919 &ml, &post_shift, &dummy);
03920
03921
03922
03923
03924 if (mh != 0 && (d & 1) == 0)
03925 {
03926 pre_shift = floor_log2 (d & -d);
03927 mh = choose_multiplier (d >> pre_shift, size,
03928 size - pre_shift,
03929 &ml, &post_shift, &dummy);
03930 gcc_assert (!mh);
03931 }
03932 else
03933 pre_shift = 0;
03934
03935 if (mh != 0)
03936 {
03937 rtx t1, t2, t3, t4;
03938
03939 if (post_shift - 1 >= BITS_PER_WORD)
03940 goto fail1;
03941
03942 extra_cost
03943 = (shift_cost[compute_mode][post_shift - 1]
03944 + shift_cost[compute_mode][1]
03945 + 2 * add_cost[compute_mode]);
03946 t1 = expand_mult_highpart (compute_mode, op0, ml,
03947 NULL_RTX, 1,
03948 max_cost - extra_cost);
03949 if (t1 == 0)
03950 goto fail1;
03951 t2 = force_operand (gen_rtx_MINUS (compute_mode,
03952 op0, t1),
03953 NULL_RTX);
03954 t3 = expand_shift
03955 (RSHIFT_EXPR, compute_mode, t2,
03956 build_int_cst (NULL_TREE, 1),
03957 NULL_RTX,1);
03958 t4 = force_operand (gen_rtx_PLUS (compute_mode,
03959 t1, t3),
03960 NULL_RTX);
03961 quotient = expand_shift
03962 (RSHIFT_EXPR, compute_mode, t4,
03963 build_int_cst (NULL_TREE, post_shift - 1),
03964 tquotient, 1);
03965 }
03966 else
03967 {
03968 rtx t1, t2;
03969
03970 if (pre_shift >= BITS_PER_WORD
03971 || post_shift >= BITS_PER_WORD)
03972 goto fail1;
03973
03974 t1 = expand_shift
03975 (RSHIFT_EXPR, compute_mode, op0,
03976 build_int_cst (NULL_TREE, pre_shift),
03977 NULL_RTX, 1);
03978 extra_cost
03979 = (shift_cost[compute_mode][pre_shift]
03980 + shift_cost[compute_mode][post_shift]);
03981 t2 = expand_mult_highpart (compute_mode, t1, ml,
03982 NULL_RTX, 1,
03983 max_cost - extra_cost);
03984 if (t2 == 0)
03985 goto fail1;
03986 quotient = expand_shift
03987 (RSHIFT_EXPR, compute_mode, t2,
03988 build_int_cst (NULL_TREE, post_shift),
03989 tquotient, 1);
03990 }
03991 }
03992 }
03993 else
03994 break;
03995
03996 insn = get_last_insn ();
03997 if (insn != last
03998 && (set = single_set (insn)) != 0
03999 && SET_DEST (set) == quotient)
04000 set_unique_reg_note (insn,
04001 REG_EQUAL,
04002 gen_rtx_UDIV (compute_mode, op0, op1));
04003 }
04004 else
04005 {
04006 unsigned HOST_WIDE_INT ml;
04007 int lgup, post_shift;
04008 rtx mlr;
04009 HOST_WIDE_INT d = INTVAL (op1);
04010 unsigned HOST_WIDE_INT abs_d = d >= 0 ? d : -d;
04011
04012
04013 if (rem_flag && d < 0)
04014 {
04015 d = abs_d;
04016 op1 = gen_int_mode (abs_d, compute_mode);
04017 }
04018
04019 if (d == 1)
04020 quotient = op0;
04021 else if (d == -1)
04022 quotient = expand_unop (compute_mode, neg_optab, op0,
04023 tquotient, 0);
04024 else if (abs_d == (unsigned HOST_WIDE_INT) 1 << (size - 1))
04025 {
04026
04027 quotient = emit_store_flag (tquotient, EQ, op0, op1,
04028 compute_mode, 1, 1);
04029 if (quotient == 0)
04030 goto fail1;
04031 }
04032 else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
04033 && (rem_flag ? smod_pow2_cheap[compute_mode]
04034 : sdiv_pow2_cheap[compute_mode])
04035
04036
04037 && (((rem_flag ? smod_optab : sdiv_optab)
04038 ->handlers[compute_mode].insn_code
04039 != CODE_FOR_nothing)
04040 || (sdivmod_optab->handlers[compute_mode]
04041 .insn_code != CODE_FOR_nothing)))
04042 ;
04043 else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d))
04044 {
04045 if (rem_flag)
04046 {
04047 remainder = expand_smod_pow2 (compute_mode, op0, d);
04048 if (remainder)
04049 return gen_lowpart (mode, remainder);
04050 }
04051
04052 if (sdiv_pow2_cheap[compute_mode]
04053 && ((sdiv_optab->handlers[compute_mode].insn_code
04054 != CODE_FOR_nothing)
04055 || (sdivmod_optab->handlers[compute_mode].insn_code
04056 != CODE_FOR_nothing)))
04057 quotient = expand_divmod (0, TRUNC_DIV_EXPR,
04058 compute_mode, op0,
04059 gen_int_mode (abs_d,
04060 compute_mode),
04061 NULL_RTX, 0);
04062 else
04063 quotient = expand_sdiv_pow2 (compute_mode, op0, abs_d);
04064
04065
04066
04067 if (d < 0)
04068 {
04069 insn = get_last_insn ();
04070 if (insn != last
04071 && (set = single_set (insn)) != 0
04072 && SET_DEST (set) == quotient
04073 && abs_d < ((unsigned HOST_WIDE_INT) 1
04074 << (HOST_BITS_PER_WIDE_INT - 1)))
04075 set_unique_reg_note (insn,
04076 REG_EQUAL,
04077 gen_rtx_DIV (compute_mode,
04078 op0,
04079 GEN_INT
04080 (trunc_int_for_mode
04081 (abs_d,
04082 compute_mode))));
04083
04084 quotient = expand_unop (compute_mode, neg_optab,
04085 quotient, quotient, 0);
04086 }
04087 }
04088 else if (size <= HOST_BITS_PER_WIDE_INT)
04089 {
04090 choose_multiplier (abs_d, size, size - 1,
04091 &mlr, &post_shift, &lgup);
04092 ml = (unsigned HOST_WIDE_INT) INTVAL (mlr);
04093 if (ml < (unsigned HOST_WIDE_INT) 1 << (size - 1))
04094 {
04095 rtx t1, t2, t3;
04096
04097 if (post_shift >= BITS_PER_WORD
04098 || size - 1 >= BITS_PER_WORD)
04099 goto fail1;
04100
04101 extra_cost = (shift_cost[compute_mode][post_shift]
04102 + shift_cost[compute_mode][size - 1]
04103 + add_cost[compute_mode]);
04104 t1 = expand_mult_highpart (compute_mode, op0, mlr,
04105 NULL_RTX, 0,
04106 max_cost - extra_cost);
04107 if (t1 == 0)
04108 goto fail1;
04109 t2 = expand_shift
04110 (RSHIFT_EXPR, compute_mode, t1,
04111 build_int_cst (NULL_TREE, post_shift),
04112 NULL_RTX, 0);
04113 t3 = expand_shift
04114 (RSHIFT_EXPR, compute_mode, op0,
04115 build_int_cst (NULL_TREE, size - 1),
04116 NULL_RTX, 0);
04117 if (d < 0)
04118 quotient
04119 = force_operand (gen_rtx_MINUS (compute_mode,
04120 t3, t2),
04121 tquotient);
04122 else
04123 quotient
04124 = force_operand (gen_rtx_MINUS (compute_mode,
04125 t2, t3),
04126 tquotient);
04127 }
04128 else
04129 {
04130 rtx t1, t2, t3, t4;
04131
04132 if (post_shift >= BITS_PER_WORD
04133 || size - 1 >= BITS_PER_WORD)
04134 goto fail1;
04135
04136 ml |= (~(unsigned HOST_WIDE_INT) 0) << (size - 1);
04137 mlr = gen_int_mode (ml, compute_mode);
04138 extra_cost = (shift_cost[compute_mode][post_shift]
04139 + shift_cost[compute_mode][size - 1]
04140 + 2 * add_cost[compute_mode]);
04141 t1 = expand_mult_highpart (compute_mode, op0, mlr,
04142 NULL_RTX, 0,
04143 max_cost - extra_cost);
04144 if (t1 == 0)
04145 goto fail1;
04146 t2 = force_operand (gen_rtx_PLUS (compute_mode,
04147 t1, op0),
04148 NULL_RTX);
04149 t3 = expand_shift
04150 (RSHIFT_EXPR, compute_mode, t2,
04151 build_int_cst (NULL_TREE, post_shift),
04152 NULL_RTX, 0);
04153 t4 = expand_shift
04154 (RSHIFT_EXPR, compute_mode, op0,
04155 build_int_cst (NULL_TREE, size - 1),
04156 NULL_RTX, 0);
04157 if (d < 0)
04158 quotient
04159 = force_operand (gen_rtx_MINUS (compute_mode,
04160 t4, t3),
04161 tquotient);
04162 else
04163 quotient
04164 = force_operand (gen_rtx_MINUS (compute_mode,
04165 t3, t4),
04166 tquotient);
04167 }
04168 }
04169 else
04170 break;
04171
04172 insn = get_last_insn ();
04173 if (insn != last
04174 && (set = single_set (insn)) != 0
04175 && SET_DEST (set) == quotient)
04176 set_unique_reg_note (insn,
04177 REG_EQUAL,
04178 gen_rtx_DIV (compute_mode, op0, op1));
04179 }
04180 break;
04181 }
04182 fail1:
04183 delete_insns_since (last);
04184 break;
04185
04186 case FLOOR_DIV_EXPR:
04187 case FLOOR_MOD_EXPR:
04188
04189 if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
04190 {
04191 unsigned HOST_WIDE_INT mh;
04192 int pre_shift, lgup, post_shift;
04193 HOST_WIDE_INT d = INTVAL (op1);
04194 rtx ml;
04195
04196 if (d > 0)
04197 {
04198
04199
04200 if (EXACT_POWER_OF_2_OR_ZERO_P (d))
04201 {
04202 pre_shift = floor_log2 (d);
04203 if (rem_flag)
04204 {
04205 remainder = expand_binop (compute_mode, and_optab, op0,
04206 GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
04207 remainder, 0, OPTAB_LIB_WIDEN);
04208 if (remainder)
04209 return gen_lowpart (mode, remainder);
04210 }
04211 quotient = expand_shift
04212 (RSHIFT_EXPR, compute_mode, op0,
04213 build_int_cst (NULL_TREE, pre_shift),
04214 tquotient, 0);
04215 }
04216 else
04217 {
04218 rtx t1, t2, t3, t4;
04219
04220 mh = choose_multiplier (d, size, size - 1,
04221 &ml, &post_shift, &lgup);
04222 gcc_assert (!mh);
04223
04224 if (post_shift < BITS_PER_WORD
04225 && size - 1 < BITS_PER_WORD)
04226 {
04227 t1 = expand_shift
04228 (RSHIFT_EXPR, compute_mode, op0,
04229 build_int_cst (NULL_TREE, size - 1),
04230 NULL_RTX, 0);
04231 t2 = expand_binop (compute_mode, xor_optab, op0, t1,
04232 NULL_RTX, 0, OPTAB_WIDEN);
04233 extra_cost = (shift_cost[compute_mode][post_shift]
04234 + shift_cost[compute_mode][size - 1]
04235 + 2 * add_cost[compute_mode]);
04236 t3 = expand_mult_highpart (compute_mode, t2, ml,
04237 NULL_RTX, 1,
04238 max_cost - extra_cost);
04239 if (t3 != 0)
04240 {
04241 t4 = expand_shift
04242 (RSHIFT_EXPR, compute_mode, t3,
04243 build_int_cst (NULL_TREE, post_shift),
04244 NULL_RTX, 1);
04245 quotient = expand_binop (compute_mode, xor_optab,
04246 t4, t1, tquotient, 0,
04247 OPTAB_WIDEN);
04248 }
04249 }
04250 }
04251 }
04252 else
04253 {
04254 rtx nsign, t1, t2, t3, t4;
04255 t1 = force_operand (gen_rtx_PLUS (compute_mode,
04256 op0, constm1_rtx), NULL_RTX);
04257 t2 = expand_binop (compute_mode, ior_optab, op0, t1, NULL_RTX,
04258 0, OPTAB_WIDEN);
04259 nsign = expand_shift
04260 (RSHIFT_EXPR, compute_mode, t2,
04261 build_int_cst (NULL_TREE, size - 1),
04262 NULL_RTX, 0);
04263 t3 = force_operand (gen_rtx_MINUS (compute_mode, t1, nsign),
04264 NULL_RTX);
04265 t4 = expand_divmod (0, TRUNC_DIV_EXPR, compute_mode, t3, op1,
04266 NULL_RTX, 0);
04267 if (t4)
04268 {
04269 rtx t5;
04270 t5 = expand_unop (compute_mode, one_cmpl_optab, nsign,
04271 NULL_RTX, 0);
04272 quotient = force_operand (gen_rtx_PLUS (compute_mode,
04273 t4, t5),
04274 tquotient);
04275 }
04276 }
04277 }
04278
04279 if (quotient != 0)
04280 break;
04281 delete_insns_since (last);
04282
04283
04284
04285
04286
04287
04288 if (target == 0 || GET_MODE (target) != compute_mode)
04289 target = gen_reg_rtx (compute_mode);
04290
04291 if (rem_flag)
04292 {
04293 remainder
04294 = REG_P (target) ? target : gen_reg_rtx (compute_mode);
04295 quotient = gen_reg_rtx (compute_mode);
04296 }
04297 else
04298 {
04299 quotient
04300 = REG_P (target) ? target : gen_reg_rtx (compute_mode);
04301 remainder = gen_reg_rtx (compute_mode);
04302 }
04303
04304 if (expand_twoval_binop (sdivmod_optab, op0, op1,
04305 quotient, remainder, 0))
04306 {
04307
04308
04309 rtx tem;
04310 rtx label = gen_label_rtx ();
04311 do_cmp_and_jump (remainder, const0_rtx, EQ, compute_mode, label);
04312 tem = expand_binop (compute_mode, xor_optab, op0, op1,
04313 NULL_RTX, 0, OPTAB_WIDEN);
04314 do_cmp_and_jump (tem, const0_rtx, GE, compute_mode, label);
04315 expand_dec (quotient, const1_rtx);
04316 expand_inc (remainder, op1);
04317 emit_label (label);
04318 return gen_lowpart (mode, rem_flag ? remainder : quotient);
04319 }
04320
04321
04322
04323 {
04324 rtx label1, label2, label3, label4, label5;
04325 rtx adjusted_op0;
04326 rtx tem;
04327
04328 quotient = gen_reg_rtx (compute_mode);
04329 adjusted_op0 = copy_to_mode_reg (compute_mode, op0);
04330 label1 = gen_label_rtx ();
04331 label2 = gen_label_rtx ();
04332 label3 = gen_label_rtx ();
04333 label4 = gen_label_rtx ();
04334 label5 = gen_label_rtx ();
04335 do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
04336 do_cmp_and_jump (adjusted_op0, const0_rtx, LT, compute_mode, label1);
04337 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
04338 quotient, 0, OPTAB_LIB_WIDEN);
04339 if (tem != quotient)
04340 emit_move_insn (quotient, tem);
04341 emit_jump_insn (gen_jump (label5));
04342 emit_barrier ();
04343 emit_label (label1);
04344 expand_inc (adjusted_op0, const1_rtx);
04345 emit_jump_insn (gen_jump (label4));
04346 emit_barrier ();
04347 emit_label (label2);
04348 do_cmp_and_jump (adjusted_op0, const0_rtx, GT, compute_mode, label3);
04349 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
04350 quotient, 0, OPTAB_LIB_WIDEN);
04351 if (tem != quotient)
04352 emit_move_insn (quotient, tem);
04353 emit_jump_insn (gen_jump (label5));
04354 emit_barrier ();
04355 emit_label (label3);
04356 expand_dec (adjusted_op0, const1_rtx);
04357 emit_label (label4);
04358 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
04359 quotient, 0, OPTAB_LIB_WIDEN);
04360 if (tem != quotient)
04361 emit_move_insn (quotient, tem);
04362 expand_dec (quotient, const1_rtx);
04363 emit_label (label5);
04364 }
04365 break;
04366
04367 case CEIL_DIV_EXPR:
04368 case CEIL_MOD_EXPR:
04369 if (unsignedp)
04370 {
04371 if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1)))
04372 {
04373 rtx t1, t2, t3;
04374 unsigned HOST_WIDE_INT d = INTVAL (op1);
04375 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
04376 build_int_cst (NULL_TREE, floor_log2 (d)),
04377 tquotient, 1);
04378 t2 = expand_binop (compute_mode, and_optab, op0,
04379 GEN_INT (d - 1),
04380 NULL_RTX, 1, OPTAB_LIB_WIDEN);
04381 t3 = gen_reg_rtx (compute_mode);
04382 t3 = emit_store_flag (t3, NE, t2, const0_rtx,
04383 compute_mode, 1, 1);
04384 if (t3 == 0)
04385 {
04386 rtx lab;
04387 lab = gen_label_rtx ();
04388 do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
04389 expand_inc (t1, const1_rtx);
04390 emit_label (lab);
04391 quotient = t1;
04392 }
04393 else
04394 quotient = force_operand (gen_rtx_PLUS (compute_mode,
04395 t1, t3),
04396 tquotient);
04397 break;
04398 }
04399
04400
04401
04402
04403
04404
04405 if (target == 0 || GET_MODE (target) != compute_mode)
04406 target = gen_reg_rtx (compute_mode);
04407
04408 if (rem_flag)
04409 {
04410 remainder = (REG_P (target)
04411 ? target : gen_reg_rtx (compute_mode));
04412 quotient = gen_reg_rtx (compute_mode);
04413 }
04414 else
04415 {
04416 quotient = (REG_P (target)
04417 ? target : gen_reg_rtx (compute_mode));
04418 remainder = gen_reg_rtx (compute_mode);
04419 }
04420
04421 if (expand_twoval_binop (udivmod_optab, op0, op1, quotient,
04422 remainder, 1))
04423 {
04424
04425
04426 rtx label = gen_label_rtx ();
04427 do_cmp_and_jump (remainder, const0_rtx, EQ,
04428 compute_mode, label);
04429 expand_inc (quotient, const1_rtx);
04430 expand_dec (remainder, op1);
04431 emit_label (label);
04432 return gen_lowpart (mode, rem_flag ? remainder : quotient);
04433 }
04434
04435
04436
04437 {
04438 rtx label1, label2;
04439 rtx adjusted_op0, tem;
04440
04441 quotient = gen_reg_rtx (compute_mode);
04442 adjusted_op0 = copy_to_mode_reg (compute_mode, op0);
04443 label1 = gen_label_rtx ();
04444 label2 = gen_label_rtx ();
04445 do_cmp_and_jump (adjusted_op0, const0_rtx, NE,
04446 compute_mode, label1);
04447 emit_move_insn (quotient, const0_rtx);
04448 emit_jump_insn (gen_jump (label2));
04449 emit_barrier ();
04450 emit_label (label1);
04451 expand_dec (adjusted_op0, const1_rtx);
04452 tem = expand_binop (compute_mode, udiv_optab, adjusted_op0, op1,
04453 quotient, 1, OPTAB_LIB_WIDEN);
04454 if (tem != quotient)
04455 emit_move_insn (quotient, tem);
04456 expand_inc (quotient, const1_rtx);
04457 emit_label (label2);
04458 }
04459 }
04460 else
04461 {
04462 if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
04463 && INTVAL (op1) >= 0)
04464 {
04465
04466
04467
04468
04469
04470
04471 rtx t1, t2, t3;
04472 unsigned HOST_WIDE_INT d = INTVAL (op1);
04473 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
04474 build_int_cst (NULL_TREE, floor_log2 (d)),
04475 tquotient, 0);
04476 t2 = expand_binop (compute_mode, and_optab, op0,
04477 GEN_INT (d - 1),
04478 NULL_RTX, 1, OPTAB_LIB_WIDEN);
04479 t3 = gen_reg_rtx (compute_mode);
04480 t3 = emit_store_flag (t3, NE, t2, const0_rtx,
04481 compute_mode, 1, 1);
04482 if (t3 == 0)
04483 {
04484 rtx lab;
04485 lab = gen_label_rtx ();
04486 do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
04487 expand_inc (t1, const1_rtx);
04488 emit_label (lab);
04489 quotient = t1;
04490 }
04491 else
04492 quotient = force_operand (gen_rtx_PLUS (compute_mode,
04493 t1, t3),
04494 tquotient);
04495 break;
04496 }
04497
04498
04499
04500
04501
04502
04503 if (target == 0 || GET_MODE (target) != compute_mode)
04504 target = gen_reg_rtx (compute_mode);
04505 if (rem_flag)
04506 {
04507 remainder= (REG_P (target)
04508 ? target : gen_reg_rtx (compute_mode));
04509 quotient = gen_reg_rtx (compute_mode);
04510 }
04511 else
04512 {
04513 quotient = (REG_P (target)
04514 ? target : gen_reg_rtx (compute_mode));
04515 remainder = gen_reg_rtx (compute_mode);
04516 }
04517
04518 if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient,
04519 remainder, 0))
04520 {
04521
04522
04523 rtx tem;
04524 rtx label = gen_label_rtx ();
04525 do_cmp_and_jump (remainder, const0_rtx, EQ,
04526 compute_mode, label);
04527 tem = expand_binop (compute_mode, xor_optab, op0, op1,
04528 NULL_RTX, 0, OPTAB_WIDEN);
04529 do_cmp_and_jump (tem, const0_rtx, LT, compute_mode, label);
04530 expand_inc (quotient, const1_rtx);
04531 expand_dec (remainder, op1);
04532 emit_label (label);
04533 return gen_lowpart (mode, rem_flag ? remainder : quotient);
04534 }
04535
04536
04537
04538 {
04539 rtx label1, label2, label3, label4, label5;
04540 rtx adjusted_op0;
04541 rtx tem;
04542
04543 quotient = gen_reg_rtx (compute_mode);
04544 adjusted_op0 = copy_to_mode_reg (compute_mode, op0);
04545 label1 = gen_label_rtx ();
04546 label2 = gen_label_rtx ();
04547 label3 = gen_label_rtx ();
04548 label4 = gen_label_rtx ();
04549 label5 = gen_label_rtx ();
04550 do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
04551 do_cmp_and_jump (adjusted_op0, const0_rtx, GT,
04552 compute_mode, label1);
04553 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
04554 quotient, 0, OPTAB_LIB_WIDEN);
04555 if (tem != quotient)
04556 emit_move_insn (quotient, tem);
04557 emit_jump_insn (gen_jump (label5));
04558 emit_barrier ();
04559 emit_label (label1);
04560 expand_dec (adjusted_op0, const1_rtx);
04561 emit_jump_insn (gen_jump (label4));
04562 emit_barrier ();
04563 emit_label (label2);
04564 do_cmp_and_jump (adjusted_op0, const0_rtx, LT,
04565 compute_mode, label3);
04566 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
04567 quotient, 0, OPTAB_LIB_WIDEN);
04568 if (tem != quotient)
04569 emit_move_insn (quotient, tem);
04570 emit_jump_insn (gen_jump (label5));
04571 emit_barrier ();
04572 emit_label (label3);
04573 expand_inc (adjusted_op0, const1_rtx);
04574 emit_label (label4);
04575 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
04576 quotient, 0, OPTAB_LIB_WIDEN);
04577 if (tem != quotient)
04578 emit_move_insn (quotient, tem);
04579 expand_inc (quotient, const1_rtx);
04580 emit_label (label5);
04581 }
04582 }
04583 break;
04584
04585 case EXACT_DIV_EXPR:
04586 if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
04587 {
04588 HOST_WIDE_INT d = INTVAL (op1);
04589 unsigned HOST_WIDE_INT ml;
04590 int pre_shift;
04591 rtx t1;
04592
04593 pre_shift = floor_log2 (d & -d);
04594 ml = invert_mod2n (d >> pre_shift, size);
04595 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
04596 build_int_cst (NULL_TREE, pre_shift),
04597 NULL_RTX, unsignedp);
04598 quotient = expand_mult (compute_mode, t1,
04599 gen_int_mode (ml, compute_mode),
04600 NULL_RTX, 1);
04601
04602 insn = get_last_insn ();
04603 set_unique_reg_note (insn,
04604 REG_EQUAL,
04605 gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
04606 compute_mode,
04607 op0, op1));
04608 }
04609 break;
04610
04611 case ROUND_DIV_EXPR:
04612 case ROUND_MOD_EXPR:
04613 if (unsignedp)
04614 {
04615 rtx tem;
04616 rtx label;
04617 label = gen_label_rtx ();
04618 quotient = gen_reg_rtx (compute_mode);
04619 remainder = gen_reg_rtx (compute_mode);
04620 if (expand_twoval_binop (udivmod_optab, op0, op1, quotient, remainder, 1) == 0)
04621 {
04622 rtx tem;
04623 quotient = expand_binop (compute_mode, udiv_optab, op0, op1,
04624 quotient, 1, OPTAB_LIB_WIDEN);
04625 tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 1);
04626 remainder = expand_binop (compute_mode, sub_optab, op0, tem,
04627 remainder, 1, OPTAB_LIB_WIDEN);
04628 }
04629 tem = plus_constant (op1, -1);
04630 tem = expand_shift (RSHIFT_EXPR, compute_mode, tem,
04631 build_int_cst (NULL_TREE, 1),
04632 NULL_RTX, 1);
04633 do_cmp_and_jump (remainder, tem, LEU, compute_mode, label);
04634 expand_inc (quotient, const1_rtx);
04635 expand_dec (remainder, op1);
04636 emit_label (label);
04637 }
04638 else
04639 {
04640 rtx abs_rem, abs_op1, tem, mask;
04641 rtx label;
04642 label = gen_label_rtx ();
04643 quotient = gen_reg_rtx (compute_mode);
04644 remainder = gen_reg_rtx (compute_mode);
04645 if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient, remainder, 0) == 0)
04646 {
04647 rtx tem;
04648 quotient = expand_binop (compute_mode, sdiv_optab, op0, op1,
04649 quotient, 0, OPTAB_LIB_WIDEN);
04650 tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 0);
04651 remainder = expand_binop (compute_mode, sub_optab, op0, tem,
04652 remainder, 0, OPTAB_LIB_WIDEN);
04653 }
04654 abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 1, 0);
04655 abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 1, 0);
04656 tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
04657 build_int_cst (NULL_TREE, 1),
04658 NULL_RTX, 1);
04659 do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label);
04660 tem = expand_binop (compute_mode, xor_optab, op0, op1,
04661 NULL_RTX, 0, OPTAB_WIDEN);
04662 mask = expand_shift (RSHIFT_EXPR, compute_mode, tem,
04663 build_int_cst (NULL_TREE, size - 1),
04664 NULL_RTX, 0);
04665 tem = expand_binop (compute_mode, xor_optab, mask, const1_rtx,
04666 NULL_RTX, 0, OPTAB_WIDEN);
04667 tem = expand_binop (compute_mode, sub_optab, tem, mask,
04668 NULL_RTX, 0, OPTAB_WIDEN);
04669 expand_inc (quotient, tem);
04670 tem = expand_binop (compute_mode, xor_optab, mask, op1,
04671 NULL_RTX, 0, OPTAB_WIDEN);
04672 tem = expand_binop (compute_mode, sub_optab, tem, mask,
04673 NULL_RTX, 0, OPTAB_WIDEN);
04674 expand_dec (remainder, tem);
04675 emit_label (label);
04676 }
04677 return gen_lowpart (mode, rem_flag ? remainder : quotient);
04678
04679 default:
04680 gcc_unreachable ();
04681 }
04682
04683 if (quotient == 0)
04684 {
04685 if (target && GET_MODE (target) != compute_mode)
04686 target = 0;
04687
04688 if (rem_flag)
04689 {
04690
04691
04692
04693
04694
04695
04696
04697
04698
04699 remainder
04700 = sign_expand_binop (compute_mode, umod_optab, smod_optab,
04701 op0, op1, target,
04702 unsignedp,
04703 ((optab2->handlers[compute_mode].insn_code
04704 != CODE_FOR_nothing)
04705 ? OPTAB_DIRECT : OPTAB_WIDEN));
04706 if (remainder == 0)
04707 {
04708
04709
04710 remainder = gen_reg_rtx (compute_mode);
04711 if (! expand_twoval_binop ((unsignedp
04712 ? udivmod_optab
04713 : sdivmod_optab),
04714 op0, op1,
04715 NULL_RTX, remainder, unsignedp))
04716 remainder = 0;
04717 }
04718
04719 if (remainder)
04720 return gen_lowpart (mode, remainder);
04721 }
04722
04723
04724
04725
04726
04727 quotient
04728 = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab,
04729 op0, op1, rem_flag ? NULL_RTX : target,
04730 unsignedp,
04731 ((optab2->handlers[compute_mode].insn_code
04732 != CODE_FOR_nothing)
04733 ? OPTAB_DIRECT : OPTAB_WIDEN));
04734
04735 if (quotient == 0)
04736 {
04737
04738
04739 quotient = gen_reg_rtx (compute_mode);
04740 if (! expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab,
04741 op0, op1,
04742 quotient, NULL_RTX, unsignedp))
04743 {
04744 quotient = 0;
04745 if (! rem_flag)
04746
04747
04748 quotient = sign_expand_binop (compute_mode,
04749 udiv_optab, sdiv_optab,
04750 op0, op1, target,
04751 unsignedp, OPTAB_LIB_WIDEN);
04752 }
04753 }
04754 }
04755
04756 if (rem_flag)
04757 {
04758 if (target && GET_MODE (target) != compute_mode)
04759 target = 0;
04760
04761 if (quotient == 0)
04762 {
04763
04764 remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
04765 op0, op1, target,
04766 unsignedp, OPTAB_LIB_WIDEN);
04767
04768
04769 if (!remainder)
04770 {
04771 remainder = gen_reg_rtx (compute_mode);
04772 if (!expand_twoval_binop_libfunc
04773 (unsignedp ? udivmod_optab : sdivmod_optab,
04774 op0, op1,
04775 NULL_RTX, remainder,
04776 unsignedp ? UMOD : MOD))
04777 remainder = NULL_RTX;
04778 }
04779 }
04780 else
04781 {
04782
04783 remainder = expand_mult (compute_mode, quotient, op1,
04784 NULL_RTX, unsignedp);
04785 remainder = expand_binop (compute_mode, sub_optab, op0,
04786 remainder, target, unsignedp,
04787 OPTAB_LIB_WIDEN);
04788 }
04789 }
04790
04791 return gen_lowpart (mode, rem_flag ? remainder : quotient);
04792 }
04793
04794
04795
04796
04797
04798
04799 tree
04800 make_tree (tree type, rtx x)
04801 {
04802 tree t;
04803
04804 switch (GET_CODE (x))
04805 {
04806 case CONST_INT:
04807 {
04808 HOST_WIDE_INT hi = 0;
04809
04810 if (INTVAL (x) < 0
04811 && !(TYPE_UNSIGNED (type)
04812 && (GET_MODE_BITSIZE (TYPE_MODE (type))
04813 < HOST_BITS_PER_WIDE_INT)))
04814 hi = -1;
04815
04816 t = build_int_cst_wide (type, INTVAL (x), hi);
04817
04818 return t;
04819 }
04820
04821 case CONST_DOUBLE:
04822 if (GET_MODE (x) == VOIDmode)
04823 t = build_int_cst_wide (type,
04824 CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x));
04825 else
04826 {
04827 REAL_VALUE_TYPE d;
04828
04829 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
04830 t = build_real (type, d);
04831 }
04832
04833 return t;
04834
04835 case CONST_VECTOR:
04836 {
04837 int i, units;
04838 rtx elt;
04839 tree t = NULL_TREE;
04840
04841 units = CONST_VECTOR_NUNITS (x);
04842
04843
04844 for (i = units - 1; i >= 0; --i)
04845 {
04846 elt = CONST_VECTOR_ELT (x, i);
04847 t = tree_cons (NULL_TREE, make_tree (type, elt), t);
04848 }
04849
04850 return build_vector (type, t);
04851 }
04852
04853 case PLUS:
04854 return fold (build2 (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)),
04855 make_tree (type, XEXP (x, 1))));
04856
04857 case MINUS:
04858 return fold (build2 (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)),
04859 make_tree (type, XEXP (x, 1))));
04860
04861 case NEG:
04862 return fold (build1 (NEGATE_EXPR, type, make_tree (type, XEXP (x, 0))));
04863
04864 case MULT:
04865 return fold (build2 (MULT_EXPR, type, make_tree (type, XEXP (x, 0)),
04866 make_tree (type, XEXP (x, 1))));
04867
04868 case ASHIFT:
04869 return fold (build2 (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)),
04870 make_tree (type, XEXP (x, 1))));
04871
04872 case LSHIFTRT:
04873 t = lang_hooks.types.unsigned_type (type);
04874 return fold_convert (type, build2 (RSHIFT_EXPR, t,
04875 make_tree (t, XEXP (x, 0)),
04876 make_tree (type, XEXP (x, 1))));
04877
04878 case ASHIFTRT:
04879 t = lang_hooks.types.signed_type (type);
04880 return fold_convert (type, build2 (RSHIFT_EXPR, t,
04881 make_tree (t, XEXP (x, 0)),
04882 make_tree (type, XEXP (x, 1))));
04883
04884 case DIV:
04885 if (TREE_CODE (type) != REAL_TYPE)
04886 t = lang_hooks.types.signed_type (type);
04887 else
04888 t = type;
04889
04890 return fold_convert (type, build2 (TRUNC_DIV_EXPR, t,
04891 make_tree (t, XEXP (x, 0)),
04892 make_tree (t, XEXP (x, 1))));
04893 case UDIV:
04894 t = lang_hooks.types.unsigned_type (type);
04895 return fold_convert (type, build2 (TRUNC_DIV_EXPR, t,
04896 make_tree (t, XEXP (x, 0)),
04897 make_tree (t, XEXP (x, 1))));
04898
04899 case SIGN_EXTEND:
04900 case ZERO_EXTEND:
04901 t = lang_hooks.types.type_for_mode (GET_MODE (XEXP (x, 0)),
04902 GET_CODE (x) == ZERO_EXTEND);
04903 return fold_convert (type, make_tree (t, XEXP (x, 0)));
04904
04905 default:
04906 t = build_decl (VAR_DECL, NULL_TREE, type);
04907
04908
04909
04910 if (POINTER_TYPE_P (type))
04911 x = convert_memory_address (TYPE_MODE (type), x);
04912
04913
04914
04915 t->decl.rtl = x;
04916
04917 return t;
04918 }
04919 }
04920
04921
04922
04923
04924
04925
04926
04927
04928 bool
04929 const_mult_add_overflow_p (rtx x, rtx mult, rtx add,
04930 enum machine_mode mode, int unsignedp)
04931 {
04932 tree type, mult_type, add_type, result;
04933
04934 type = lang_hooks.types.type_for_mode (mode, unsignedp);
04935
04936
04937
04938 mult_type = type;
04939 if (unsignedp)
04940 {
04941
04942
04943 mult_type = build_distinct_type_copy (type);
04944 TYPE_IS_SIZETYPE (mult_type) = 1;
04945 }
04946
04947 add_type = (GET_MODE (add) == VOIDmode ? mult_type
04948 : lang_hooks.types.type_for_mode (GET_MODE (add), unsignedp));
04949
04950 result = fold (build2 (PLUS_EXPR, mult_type,
04951 fold (build2 (MULT_EXPR, mult_type,
04952 make_tree (mult_type, x),
04953 make_tree (mult_type, mult))),
04954 make_tree (add_type, add)));
04955
04956 return TREE_CONSTANT_OVERFLOW (result);
04957 }
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967 rtx
04968 expand_mult_add (rtx x, rtx target, rtx mult, rtx add, enum machine_mode mode,
04969 int unsignedp)
04970 {
04971 tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
04972 tree add_type = (GET_MODE (add) == VOIDmode
04973 ? type: lang_hooks.types.type_for_mode (GET_MODE (add),
04974 unsignedp));
04975 tree result = fold (build2 (PLUS_EXPR, type,
04976 fold (build2 (MULT_EXPR, type,
04977 make_tree (type, x),
04978 make_tree (type, mult))),
04979 make_tree (add_type, add)));
04980
04981 return expand_expr (result, target, VOIDmode, 0);
04982 }
04983
04984
04985
04986
04987
04988
04989 rtx
04990 expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target)
04991 {
04992 rtx tem = 0;
04993
04994 if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
04995 tem = simplify_binary_operation (AND, mode, op0, op1);
04996 if (tem == 0)
04997 tem = expand_binop (mode, and_optab, op0, op1, target, 0, OPTAB_LIB_WIDEN);
04998
04999 if (target == 0)
05000 target = tem;
05001 else if (tem != target)
05002 emit_move_insn (target, tem);
05003 return target;
05004 }
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021 rtx
05022 emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
05023 enum machine_mode mode, int unsignedp, int normalizep)
05024 {
05025 rtx subtarget;
05026 enum insn_code icode;
05027 enum machine_mode compare_mode;
05028 enum machine_mode target_mode = GET_MODE (target);
05029 rtx tem;
05030 rtx last = get_last_insn ();
05031 rtx pattern, comparison;
05032
05033 if (unsignedp)
05034 code = unsigned_condition (code);
05035
05036
05037
05038
05039 if (swap_commutative_operands_p (op0, op1))
05040 {
05041 tem = op0;
05042 op0 = op1;
05043 op1 = tem;
05044 code = swap_condition (code);
05045 }
05046
05047 if (mode == VOIDmode)
05048 mode = GET_MODE (op0);
05049
05050
05051
05052
05053
05054 switch (code)
05055 {
05056 case LT:
05057 if (op1 == const1_rtx)
05058 op1 = const0_rtx, code = LE;
05059 break;
05060 case LE:
05061 if (op1 == constm1_rtx)
05062 op1 = const0_rtx, code = LT;
05063 break;
05064 case GE:
05065 if (op1 == const1_rtx)
05066 op1 = const0_rtx, code = GT;
05067 break;
05068 case GT:
05069 if (op1 == constm1_rtx)
05070 op1 = const0_rtx, code = GE;
05071 break;
05072 case GEU:
05073 if (op1 == const1_rtx)
05074 op1 = const0_rtx, code = NE;
05075 break;
05076 case LTU:
05077 if (op1 == const1_rtx)
05078 op1 = const0_rtx, code = EQ;
05079 break;
05080 default:
05081 break;
05082 }
05083
05084
05085
05086 if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD * 2
05087 && GET_MODE_CLASS (mode) == MODE_INT
05088 && (!MEM_P (op0) || ! MEM_VOLATILE_P (op0)))
05089 {
05090 if ((code == EQ || code == NE)
05091 && (op1 == const0_rtx || op1 == constm1_rtx))
05092 {
05093 rtx op00, op01, op0both;
05094
05095
05096 op00 = simplify_gen_subreg (word_mode, op0, mode, 0);
05097 op01 = simplify_gen_subreg (word_mode, op0, mode, UNITS_PER_WORD);
05098 op0both = expand_binop (word_mode,
05099 op1 == const0_rtx ? ior_optab : and_optab,
05100 op00, op01, NULL_RTX, unsignedp, OPTAB_DIRECT);
05101
05102 if (op0both != 0)
05103 return emit_store_flag (target, code, op0both, op1, word_mode,
05104 unsignedp, normalizep);
05105 }
05106 else if ((code == LT || code == GE) && op1 == const0_rtx)
05107 {
05108 rtx op0h;
05109
05110
05111 op0h = simplify_gen_subreg (word_mode, op0, mode,
05112 subreg_highpart_offset (word_mode, mode));
05113 return emit_store_flag (target, code, op0h, op1, word_mode,
05114 unsignedp, normalizep);
05115 }
05116 }
05117
05118
05119 icode = setcc_gen_code[(int) code];
05120
05121
05122
05123 if (op1 == const0_rtx && (code == LT || code == GE)
05124 && GET_MODE_CLASS (mode) == MODE_INT
05125 && (normalizep || STORE_FLAG_VALUE == 1
05126 || (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05127 && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
05128 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))))
05129 {
05130 subtarget = target;
05131
05132
05133
05134
05135 if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode))
05136 {
05137 op0 = convert_modes (target_mode, mode, op0, 0);
05138 mode = target_mode;
05139 }
05140
05141 if (target_mode != mode)
05142 subtarget = 0;
05143
05144 if (code == GE)
05145 op0 = expand_unop (mode, one_cmpl_optab, op0,
05146 ((STORE_FLAG_VALUE == 1 || normalizep)
05147 ? 0 : subtarget), 0);
05148
05149 if (STORE_FLAG_VALUE == 1 || normalizep)
05150
05151
05152
05153 op0 = expand_shift (RSHIFT_EXPR, mode, op0,
05154 size_int (GET_MODE_BITSIZE (mode) - 1),
05155 subtarget, normalizep != -1);
05156
05157 if (mode != target_mode)
05158 op0 = convert_modes (target_mode, mode, op0, 0);
05159
05160 return op0;
05161 }
05162
05163 if (icode != CODE_FOR_nothing)
05164 {
05165 insn_operand_predicate_fn pred;
05166
05167
05168
05169
05170 do_pending_stack_adjust ();
05171 last = get_last_insn ();
05172
05173 comparison
05174 = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX);
05175 if (CONSTANT_P (comparison))
05176 {
05177 switch (GET_CODE (comparison))
05178 {
05179 case CONST_INT:
05180 if (comparison == const0_rtx)
05181 return const0_rtx;
05182 break;
05183
05184 #ifdef FLOAT_STORE_FLAG_VALUE
05185 case CONST_DOUBLE:
05186 if (comparison == CONST0_RTX (GET_MODE (comparison)))
05187 return const0_rtx;
05188 break;
05189 #endif
05190 default:
05191 gcc_unreachable ();
05192 }
05193
05194 if (normalizep == 1)
05195 return const1_rtx;
05196 if (normalizep == -1)
05197 return constm1_rtx;
05198 return const_true_rtx;
05199 }
05200
05201
05202
05203
05204
05205
05206
05207 code = GET_CODE (comparison);
05208
05209
05210 compare_mode = insn_data[(int) icode].operand[0].mode;
05211 subtarget = target;
05212 pred = insn_data[(int) icode].operand[0].predicate;
05213 if (optimize || ! (*pred) (subtarget, compare_mode))
05214 subtarget = gen_reg_rtx (compare_mode);
05215
05216 pattern = GEN_FCN (icode) (subtarget);
05217 if (pattern)
05218 {
05219 emit_insn (pattern);
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229 if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (compare_mode))
05230 {
05231 convert_move (target, subtarget,
05232 (GET_MODE_BITSIZE (compare_mode)
05233 <= HOST_BITS_PER_WIDE_INT)
05234 && 0 == (STORE_FLAG_VALUE
05235 & ((HOST_WIDE_INT) 1
05236 << (GET_MODE_BITSIZE (compare_mode) -1))));
05237 op0 = target;
05238 compare_mode = target_mode;
05239 }
05240 else
05241 op0 = subtarget;
05242
05243
05244
05245
05246 if (optimize)
05247 subtarget = 0;
05248
05249
05250
05251 if (normalizep == 0 || normalizep == STORE_FLAG_VALUE)
05252 ;
05253
05254
05255 else if (- normalizep == STORE_FLAG_VALUE)
05256 op0 = expand_unop (compare_mode, neg_optab, op0, subtarget, 0);
05257
05258
05259
05260
05261 else if (GET_MODE_BITSIZE (compare_mode) <= HOST_BITS_PER_WIDE_INT
05262 && (STORE_FLAG_VALUE
05263 & ((HOST_WIDE_INT) 1
05264 << (GET_MODE_BITSIZE (compare_mode) - 1))))
05265 op0 = expand_shift (RSHIFT_EXPR, compare_mode, op0,
05266 size_int (GET_MODE_BITSIZE (compare_mode) - 1),
05267 subtarget, normalizep == 1);
05268 else
05269 {
05270 gcc_assert (STORE_FLAG_VALUE & 1);
05271
05272 op0 = expand_and (compare_mode, op0, const1_rtx, subtarget);
05273 if (normalizep == -1)
05274 op0 = expand_unop (compare_mode, neg_optab, op0, op0, 0);
05275 }
05276
05277
05278
05279 if (target_mode != compare_mode)
05280 {
05281 convert_move (target, op0, 0);
05282 return target;
05283 }
05284 else
05285 return op0;
05286 }
05287 }
05288
05289 delete_insns_since (last);
05290
05291
05292
05293
05294 subtarget = (!optimize
05295 && (target_mode == mode)) ? target : NULL_RTX;
05296
05297
05298
05299
05300
05301
05302
05303
05304 if (BRANCH_COST > 0
05305 && GET_MODE_CLASS (mode) == MODE_INT && (code == EQ || code == NE)
05306 && op1 != const0_rtx)
05307 {
05308 tem = expand_binop (mode, xor_optab, op0, op1, subtarget, 1,
05309 OPTAB_WIDEN);
05310
05311 if (tem == 0)
05312 tem = expand_binop (mode, sub_optab, op0, op1, subtarget, 1,
05313 OPTAB_WIDEN);
05314 if (tem != 0)
05315 tem = emit_store_flag (target, code, tem, const0_rtx,
05316 mode, unsignedp, normalizep);
05317 if (tem == 0)
05318 delete_insns_since (last);
05319 return tem;
05320 }
05321
05322
05323
05324
05325
05326
05327 if (BRANCH_COST == 0
05328 || GET_MODE_CLASS (mode) != MODE_INT || op1 != const0_rtx
05329 || (code != EQ && code != NE
05330 && (BRANCH_COST <= 1 || (code != LE && code != GT))))
05331 return 0;
05332
05333
05334
05335
05336 if (normalizep == 0)
05337 {
05338 if (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
05339 normalizep = STORE_FLAG_VALUE;
05340
05341 else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
05342 && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
05343 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))
05344 ;
05345 else
05346 return 0;
05347 }
05348
05349
05350
05351
05352 tem = 0;
05353
05354
05355
05356
05357 if (code == LE)
05358 {
05359
05360 if (rtx_equal_p (subtarget, op0))
05361 subtarget = 0;
05362
05363 tem = expand_binop (mode, sub_optab, op0, const1_rtx, subtarget, 0,
05364 OPTAB_WIDEN);
05365 if (tem)
05366 tem = expand_binop (mode, ior_optab, op0, tem, subtarget, 0,
05367 OPTAB_WIDEN);
05368 }
05369
05370
05371
05372
05373 if (code == GT)
05374 {
05375 if (rtx_equal_p (subtarget, op0))
05376 subtarget = 0;
05377
05378 tem = expand_shift (RSHIFT_EXPR, mode, op0,
05379 size_int (GET_MODE_BITSIZE (mode) - 1),
05380 subtarget, 0);
05381 tem = expand_binop (mode, sub_optab, tem, op0, subtarget, 0,
05382 OPTAB_WIDEN);
05383 }
05384
05385 if (code == EQ || code == NE)
05386 {
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402 if (abs_optab->handlers[mode].insn_code != CODE_FOR_nothing)
05403 tem = expand_unop (mode, abs_optab, op0, subtarget, 1);
05404 else if (ffs_optab->handlers[mode].insn_code != CODE_FOR_nothing)
05405 tem = expand_unop (mode, ffs_optab, op0, subtarget, 1);
05406 else if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
05407 {
05408 tem = convert_modes (word_mode, mode, op0, 1);
05409 mode = word_mode;
05410 }
05411
05412 if (tem != 0)
05413 {
05414 if (code == EQ)
05415 tem = expand_binop (mode, sub_optab, tem, const1_rtx, subtarget,
05416 0, OPTAB_WIDEN);
05417 else
05418 tem = expand_unop (mode, neg_optab, tem, subtarget, 0);
05419 }
05420
05421
05422
05423
05424
05425
05426 if (tem == 0 && (code == NE || BRANCH_COST > 1))
05427 {
05428 if (rtx_equal_p (subtarget, op0))
05429 subtarget = 0;
05430
05431 tem = expand_unop (mode, neg_optab, op0, subtarget, 0);
05432 tem = expand_binop (mode, ior_optab, tem, op0, subtarget, 0,
05433 OPTAB_WIDEN);
05434
05435 if (tem && code == EQ)
05436 tem = expand_unop (mode, one_cmpl_optab, tem, subtarget, 0);
05437 }
05438 }
05439
05440 if (tem && normalizep)
05441 tem = expand_shift (RSHIFT_EXPR, mode, tem,
05442 size_int (GET_MODE_BITSIZE (mode) - 1),
05443 subtarget, normalizep == 1);
05444
05445 if (tem)
05446 {
05447 if (GET_MODE (tem) != target_mode)
05448 {
05449 convert_move (target, tem, 0);
05450 tem = target;
05451 }
05452 else if (!subtarget)
05453 {
05454 emit_move_insn (target, tem);
05455 tem = target;
05456 }
05457 }
05458 else
05459 delete_insns_since (last);
05460
05461 return tem;
05462 }
05463
05464
05465
05466 rtx
05467 emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
05468 enum machine_mode mode, int unsignedp, int normalizep)
05469 {
05470 rtx tem, label;
05471
05472
05473 tem = emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep);
05474 if (tem != 0)
05475 return tem;
05476
05477 if (normalizep == 0)
05478 normalizep = 1;
05479
05480
05481
05482 if (!REG_P (target)
05483 || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
05484 target = gen_reg_rtx (GET_MODE (target));
05485
05486 emit_move_insn (target, const1_rtx);
05487 label = gen_label_rtx ();
05488 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX,
05489 NULL_RTX, label);
05490
05491 emit_move_insn (target, const0_rtx);
05492 emit_label (label);
05493
05494 return target;
05495 }
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506 static void
05507 do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode,
05508 rtx label)
05509 {
05510
05511
05512
05513 if (GET_MODE_CLASS (mode) == MODE_INT
05514 && ! can_compare_p (op, mode, ccp_jump))
05515 {
05516 rtx label2 = gen_label_rtx ();
05517
05518 switch (op)
05519 {
05520 case LTU:
05521 do_jump_by_parts_greater_rtx (mode, 1, arg2, arg1, label2, label);
05522 break;
05523
05524 case LEU:
05525 do_jump_by_parts_greater_rtx (mode, 1, arg1, arg2, label, label2);
05526 break;
05527
05528 case LT:
05529 do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label2, label);
05530 break;
05531
05532 case GT:
05533 do_jump_by_parts_greater_rtx (mode, 0, arg1, arg2, label2, label);
05534 break;
05535
05536 case GE:
05537 do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label, label2);
05538 break;
05539
05540
05541
05542 case EQ:
05543 gcc_assert (arg2 == const0_rtx && mode == GET_MODE(arg1));
05544 do_jump_by_parts_equality_rtx (arg1, label2, label);
05545 break;
05546
05547 case NE:
05548 gcc_assert (arg2 == const0_rtx && mode == GET_MODE(arg1));
05549 do_jump_by_parts_equality_rtx (arg1, label, label2);
05550 break;
05551
05552 default:
05553 gcc_unreachable ();
05554 }
05555
05556 emit_label (label2);
05557 }
05558 else
05559 emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, label);
05560 }