From 465e27163d08d2e8b1d962fb2892ffd3eaf5dd90 Mon Sep 17 00:00:00 2001 From: Geoff Keating Date: Sun, 1 Aug 1999 16:14:58 +0000 Subject: rs6000.c (num_insns_constant_wide): Correct for type promotion. * config/rs6000/rs6000.c (num_insns_constant_wide): Correct for type promotion. (add_operand): Get test correct for 64-bit HOST_WIDE_INT. (non_add_cint_operand): Likewise. (logical_operand): Likewise. (non_logical_cint_operand): Likewise. (print_operand): Correct printf()s for 64-bit HOST_WIDE_INT. (print_operand_address): Correct printf() for 64-bit HOST_WIDE_INT. (rs6000_select_rtx_section): Suppress warning. (small_data_operand): Suppress warning. (rs6000_got_register): Suppress warning. * config/rs6000/rs6000.md (andsi3): HOST_WIDE_INT is a signed type, so `J' is generally the wrong constraint for a SImode value; use `L' instead. (andsi3_internal2): Likewise. (andsi3_internal3): Likewise. (iorsi3_internal1): Likewise. (xorsi3_internal1): Likewise. (movsi): Likewise. (movsf_softfloat): Likewise. various unnamed compare insns: Likewise. (movsi+2): Preserve sign bits of SImode constant. (floatsidf2_internal+1): Sign-extend SImode constant correctly. (movdf+1): Preserve high bits of DFmode constant. (movdi_32+1): Sign-extend properly. various unnamed compare insns: Sign-extend properly. * unroll.c (loop_iterations): Convert HOST_WIDE_INT to unsigned properly for mode. * expmed.c (expand_mult_highpart): Convert HOST_WIDE_INT from unsigned properly for mode. (expand_divmod): Likewise. * optabs.c (expand_fix): Keep HOST_WIDE_INT constants properly signed. (expand_binop): Sometimes there is work to do when changing the mode of a CONST_INT. From-SVN: r28375 --- gcc/ChangeLog | 38 +++++++++++++++++++++++++++++ gcc/config/rs6000/rs6000.c | 58 ++++++++++++++++++++++++--------------------- gcc/config/rs6000/rs6000.md | 41 ++++++++++++++++---------------- gcc/expmed.c | 8 ++++--- gcc/md.texi | 10 +++++--- gcc/optabs.c | 6 ++--- gcc/unroll.c | 6 +++++ 7 files changed, 111 insertions(+), 56 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 66da0db..5be789a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +Sun Jul 25 19:32:58 1999 Geoff Keating + + * config/rs6000/rs6000.c (num_insns_constant_wide): Correct + for type promotion. + (add_operand): Get test correct for 64-bit HOST_WIDE_INT. + (non_add_cint_operand): Likewise. + (logical_operand): Likewise. + (non_logical_cint_operand): Likewise. + (print_operand): Correct printf()s for 64-bit HOST_WIDE_INT. + (print_operand_address): Correct printf() for 64-bit HOST_WIDE_INT. + (rs6000_select_rtx_section): Suppress warning. + (small_data_operand): Suppress warning. + (rs6000_got_register): Suppress warning. + * config/rs6000/rs6000.md (andsi3): HOST_WIDE_INT is a signed + type, so `J' is generally the wrong constraint for a SImode value; + use `L' instead. + (andsi3_internal2): Likewise. + (andsi3_internal3): Likewise. + (iorsi3_internal1): Likewise. + (xorsi3_internal1): Likewise. + (movsi): Likewise. + (movsf_softfloat): Likewise. + various unnamed compare insns: Likewise. + (movsi+2): Preserve sign bits of SImode constant. + (floatsidf2_internal+1): Sign-extend SImode constant correctly. + (movdf+1): Preserve high bits of DFmode constant. + (movdi_32+1): Sign-extend properly. + various unnamed compare insns: Sign-extend properly. + + * unroll.c (loop_iterations): Convert HOST_WIDE_INT to unsigned + properly for mode. + * expmed.c (expand_mult_highpart): Convert HOST_WIDE_INT from unsigned + properly for mode. + (expand_divmod): Likewise. + * optabs.c (expand_fix): Keep HOST_WIDE_INT constants properly signed. + (expand_binop): Sometimes there is work to do when changing + the mode of a CONST_INT. + Sun Aug 1 12:55:31 1999 Bernd Schmidt * stmt.c (emit_filename, emit_lineno, expr_stmts_for_value, diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 6987b2b..4028bd4 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -666,16 +666,11 @@ num_insns_constant_wide (value) if (((unsigned HOST_WIDE_INT)value + 0x8000) < 0x10000) return 1; -#if HOST_BITS_PER_WIDE_INT == 32 - /* constant loadable with {cau|addis} */ - else if ((value & 0xffff) == 0) - return 1; - -#else /* constant loadable with {cau|addis} */ - else if ((value & 0xffff) == 0 && (value & ~0xffffffff) == 0) + else if (CONST_OK_FOR_LETTER_P (value, 'L')) return 1; +#if HOST_BITS_PER_WIDE_INT == 64 else if (TARGET_64BIT) { HOST_WIDE_INT low = value & 0xffffffff; @@ -880,7 +875,7 @@ mem_or_easy_const_operand (op, mode) } /* Return 1 if the operand is either a non-special register or an item - that can be used as the operand of an SI add insn. */ + that can be used as the operand of a `mode' add insn. */ int add_operand (op, mode) @@ -889,7 +884,7 @@ add_operand (op, mode) { return (reg_or_short_operand (op, mode) || (GET_CODE (op) == CONST_INT - && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff0000)) == 0)); + && CONST_OK_FOR_LETTER_P (INTVAL(op), 'L'))); } /* Return 1 if OP is a constant but not a valid add_operand. */ @@ -901,7 +896,7 @@ non_add_cint_operand (op, mode) { return (GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000 - && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff0000)) != 0); + && ! CONST_OK_FOR_LETTER_P (INTVAL(op), 'L')); } /* Return 1 if the operand is a non-special register or a constant that @@ -914,8 +909,10 @@ logical_operand (op, mode) { return (gpc_reg_operand (op, mode) || (GET_CODE (op) == CONST_INT - && ((INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff)) == 0 - || (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff0000)) == 0))); + && ((INTVAL (op) & GET_MODE_MASK (mode) + & (~ (HOST_WIDE_INT) 0xffff)) == 0 + || (INTVAL (op) & GET_MODE_MASK (mode) + & (~ (HOST_WIDE_INT) 0xffff0000)) == 0))); } /* Return 1 if C is a constant that is not a logical operand (as @@ -924,11 +921,13 @@ logical_operand (op, mode) int non_logical_cint_operand (op, mode) register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; + enum machine_mode mode; { return (GET_CODE (op) == CONST_INT - && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff)) != 0 - && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff0000)) != 0); + && (INTVAL (op) & GET_MODE_MASK (mode) & + (~ (HOST_WIDE_INT) 0xffff)) != 0 + && (INTVAL (op) & GET_MODE_MASK (mode) & + (~ (HOST_WIDE_INT) 0xffff0000)) != 0); } /* Return 1 if C is a constant that can be encoded in a 32-bit mask on the @@ -1198,7 +1197,7 @@ small_data_operand (op, mode) enum machine_mode mode ATTRIBUTE_UNUSED; { #if TARGET_ELF - rtx sym_ref, const_part; + rtx sym_ref; if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA) return 0; @@ -2474,7 +2473,7 @@ ccr_bit (op, scc_p) struct rtx_def * rs6000_got_register (value) - rtx value; + rtx value ATTRIBUTE_UNUSED; { /* The second flow pass currently (June 1999) can't update regs_ever_live without disturbing other parts of the compiler, so update it here to @@ -2627,7 +2626,7 @@ print_operand (file, x, code) if (! INT_P (x)) output_operand_lossage ("invalid %%b value"); - fprintf (file, "%d", INT_LOWPART (x) & 0xffff); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 0xffff); return; case 'B': @@ -2713,7 +2712,7 @@ print_operand (file, x, code) /* If constant, output low-order five bits. Otherwise, write normally. */ if (INT_P (x)) - fprintf (file, "%d", INT_LOWPART (x) & 31); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 31); else print_operand (file, x, 0); return; @@ -2722,7 +2721,7 @@ print_operand (file, x, code) /* If constant, output low-order six bits. Otherwise, write normally. */ if (INT_P (x)) - fprintf (file, "%d", INT_LOWPART (x) & 63); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 63); else print_operand (file, x, 0); return; @@ -2759,7 +2758,7 @@ print_operand (file, x, code) if (! INT_P (x)) output_operand_lossage ("invalid %%k value"); - fprintf (file, "%d", ~ INT_LOWPART (x)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INT_LOWPART (x)); return; case 'L': @@ -2903,7 +2902,7 @@ print_operand (file, x, code) if (! INT_P (x)) output_operand_lossage ("invalid %%s value"); - fprintf (file, "%d", (32 - INT_LOWPART (x)) & 31); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, (32 - INT_LOWPART (x)) & 31); return; case 'S': @@ -3006,7 +3005,8 @@ print_operand (file, x, code) if (! INT_P (x)) output_operand_lossage ("invalid %%u value"); - fprintf (file, "0x%x", (INT_LOWPART (x) >> 16) & 0xffff); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, + (INT_LOWPART (x) >> 16) & 0xffff); return; case 'v': @@ -3076,7 +3076,8 @@ print_operand (file, x, code) /* If constant, low-order 16 bits of constant, signed. Otherwise, write normally. */ if (INT_P (x)) - fprintf (file, "%d", ((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, + ((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000); else print_operand (file, x, 0); return; @@ -3085,7 +3086,7 @@ print_operand (file, x, code) /* If constant, low-order 16 bits of constant, unsigned. Otherwise, write normally. */ if (INT_P (x)) - fprintf (file, "%d", INT_LOWPART (x) & 0xffff); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 0xffff); else print_operand (file, x, 0); return; @@ -3221,7 +3222,10 @@ print_operand_address (file, x) reg_names[ REGNO (XEXP (x, 1)) ]); } else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) - fprintf (file, "%d(%s)", INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]); + { + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (XEXP (x, 1))); + fprintf (file, "(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); + } #if TARGET_ELF else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG && CONSTANT_P (XEXP (x, 1))) @@ -5649,7 +5653,7 @@ rs6000_longcall_ref (call_ref) void rs6000_select_rtx_section (mode, x) - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; rtx x; { if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x)) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index baf0243..62de865 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -1938,7 +1938,7 @@ (define_insn "andsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r") - (match_operand:SI 2 "and_operand" "?r,T,K,J"))) + (match_operand:SI 2 "and_operand" "?r,T,K,L"))) (clobber (match_scratch:CC 3 "=X,X,x,x"))] "" "@ @@ -1955,7 +1955,7 @@ (define_insn "*andsi3_internal2" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y") (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r") - (match_operand:SI 2 "and_operand" "r,K,J,T,r,K,J,T")) + (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T")) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r,r,r,r,r,r,r")) (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))] @@ -1992,7 +1992,7 @@ (define_insn "*andsi3_internal3" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y") (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r") - (match_operand:SI 2 "and_operand" "r,K,J,T,r,K,J,T")) + (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T")) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r") (and:SI (match_dup 1) @@ -2054,7 +2054,7 @@ (define_insn "*iorsi3_internal1" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r") (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r") - (match_operand:SI 2 "logical_operand" "r,K,J")))] + (match_operand:SI 2 "logical_operand" "r,K,L")))] "" "@ or %0,%1,%2 @@ -2161,7 +2161,7 @@ (define_insn "*xorsi3_internal1" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r") (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r") - (match_operand:SI 2 "logical_operand" "r,K,J")))] + (match_operand:SI 2 "logical_operand" "r,K,L")))] "" "@ xor %0,%1,%2 @@ -4226,7 +4226,7 @@ (match_dup 3)))] " { - operands[6] = GEN_INT (0x80000000); + operands[6] = GEN_INT (~ (HOST_WIDE_INT) 0x7fffffff); operands[7] = gen_rtx_REG (DFmode, FPMEM_REGNUM); }") @@ -6127,7 +6127,7 @@ (match_dup 3)))] " { - operands[2] = GEN_INT (INTVAL (operands[1]) & 0xffff0000); + operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff)); operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); }") @@ -6383,7 +6383,7 @@ int endian = (WORDS_BIG_ENDIAN == 0); operands[2] = operand_subword (operands[0], endian, 0, DFmode); operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode); - operands[4] = (INTVAL (operands[1]) & 0x80000000) ? constm1_rtx : const0_rtx; + operands[4] = GEN_INT(INTVAL (operands[1]) >> 31 >> 1); }") (define_split @@ -6740,13 +6740,14 @@ (set (match_dup 3) (match_dup 1))] " { + HOST_WIDE_INT value = INTVAL (operands[1]); operands[2] = gen_rtx_SUBREG (SImode, operands[0], WORDS_BIG_ENDIAN == 0); operands[3] = gen_rtx_SUBREG (SImode, operands[0], WORDS_BIG_ENDIAN != 0); #if HOST_BITS_PER_WIDE_INT == 32 - operands[4] = (INTVAL (operands[1]) & 0x80000000) ? constm1_rtx : const0_rtx; + operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx; #else - operands[4] = GEN_INT ((HOST_WIDE_INT) INTVAL (operands[1]) >> 32); - operands[1] = GEN_INT (INTVAL (operands[1]) & 0xffffffff); + operands[4] = GEN_INT (value >> 32); + operands[1] = GEN_INT ((value & 0x7fffffff) - (value & 0x80000000)); #endif }") @@ -8893,9 +8894,9 @@ sign-extended to 16 bits. Then see what constant could be XOR'ed with C to get the sign-extended value. */ - int c = INTVAL (operands[2]); - int sextc = (c << 16) >> 16; - int xorv = c ^ sextc; + HOST_WIDE_INT c = INTVAL (operands[2]); + HOST_WIDE_INT sextc = (c & 0x7fff) - (c & 0x8000); + HOST_WIDE_INT xorv = c ^ sextc; operands[4] = GEN_INT (xorv); operands[5] = GEN_INT (sextc); @@ -9128,7 +9129,7 @@ (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r") (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,J,I"))) + (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I"))) (clobber (match_scratch:SI 3 "=r,&r,r,r,r"))] "" "@ @@ -9157,7 +9158,7 @@ [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x") (compare:CC (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,J,I")) + (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I")) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r") (eq:SI (match_dup 1) (match_dup 2))) @@ -9209,7 +9210,7 @@ (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r") (plus:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,J,I")) + (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I")) (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r"))) (clobber (match_scratch:SI 4 "=&r,&r,&r,&r,&r"))] "" @@ -9226,7 +9227,7 @@ (compare:CC (plus:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,J,I")) + (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I")) (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r")) (const_int 0))) (clobber (match_scratch:SI 4 "=&r,&r,&r,&r,&r"))] @@ -9245,7 +9246,7 @@ (compare:CC (plus:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,J,I")) + (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I")) (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r")) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r") @@ -9264,7 +9265,7 @@ (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r") (neg:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,J,I"))))] + (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I"))))] "" "@ xor %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0 diff --git a/gcc/expmed.c b/gcc/expmed.c index ffe16fe..1af328e 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -2718,13 +2718,13 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost) int size = GET_MODE_BITSIZE (mode); rtx op1, wide_op1; - /* We can't support modes wider than HOST_BITS_PER_INT. */ + /* We can't support modes wider than HOST_BITS_PER_WIDE_INT. */ if (size > HOST_BITS_PER_WIDE_INT) abort (); - op1 = GEN_INT (cnst1); + op1 = GEN_INT (cnst1 | -(cnst1 & ((HOST_WIDE_INT) 1 << (size - 1)))); - if (GET_MODE_BITSIZE (wider_mode) <= HOST_BITS_PER_INT) + if (GET_MODE_BITSIZE (wider_mode) <= HOST_BITS_PER_WIDE_INT) wide_op1 = op1; else wide_op1 @@ -3726,6 +3726,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) post_shift = floor_log2 (d & -d); ml = invert_mod2n (d >> post_shift, size); + /* Sign-extend ml for compute_mode. */ + ml |= -(ml & (1 << (GET_MODE_BITSIZE (compute_mode)-1))); t1 = expand_mult (compute_mode, op0, GEN_INT (ml), NULL_RTX, unsignedp); quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1, diff --git a/gcc/md.texi b/gcc/md.texi index 11a4001..13dc442 100644 --- a/gcc/md.texi +++ b/gcc/md.texi @@ -1384,13 +1384,14 @@ Floating point register Signed 16 bit constant @item J -Constant whose low 16 bits are 0 +Unsigned 16 bit constant shifted left 16 bits (use @samp{L} instead for +@code{SImode} constants) @item K -Constant whose high 16 bits are 0 +Unsigned 16 bit constant @item L -Constant suitable as a mask operand +Signed 16 bit constant shifted left 16 bits @item M Constant larger than 31 @@ -1418,6 +1419,9 @@ AIX TOC entry @item S Constant suitable as a 64-bit mask operand +@item T +Constant suitable as a 32-bit mask operand + @item U System V Release 4 small data area reference @end table diff --git a/gcc/optabs.c b/gcc/optabs.c index 2b9091b..bad2776 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -857,12 +857,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) /* In case the insn wants input operands in modes different from the result, convert the operands. */ - if (GET_MODE (op0) != VOIDmode + if ((GET_MODE (op0) != VOIDmode || GET_CODE (op0) == CONST_INT) && GET_MODE (op0) != mode0 && mode0 != VOIDmode) xop0 = convert_to_mode (mode0, xop0, unsignedp); - if (GET_MODE (xop1) != VOIDmode + if ((GET_MODE (xop1) != VOIDmode || GET_CODE (xop1) == CONST_INT) && GET_MODE (xop1) != mode1 && mode1 != VOIDmode) xop1 = convert_to_mode (mode1, xop1, unsignedp); @@ -4231,7 +4231,7 @@ expand_fix (to, from, unsignedp) NULL_RTX, 0, OPTAB_LIB_WIDEN); expand_fix (to, target, 0); target = expand_binop (GET_MODE (to), xor_optab, to, - GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)), + GEN_INT ((HOST_WIDE_INT) -1 << (bitsize - 1)), to, 1, OPTAB_LIB_WIDEN); if (target != to) diff --git a/gcc/unroll.c b/gcc/unroll.c index d6dbcf0..7ce3a38 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -3588,6 +3588,7 @@ loop_iterations (loop_start, loop_end, loop_info) rtx comparison, comparison_value; rtx iteration_var, initial_value, increment, final_value; enum rtx_code comparison_code; + enum machine_mode comparison_mode; HOST_WIDE_INT abs_inc; unsigned HOST_WIDE_INT abs_diff; int off_by_one; @@ -3652,6 +3653,7 @@ loop_iterations (loop_start, loop_end, loop_info) invariant register when it canonicalizes the comparison. */ comparison_code = GET_CODE (comparison); + comparison_mode = GET_MODE (comparison); iteration_var = XEXP (comparison, 0); comparison_value = XEXP (comparison, 1); @@ -3991,6 +3993,10 @@ loop_iterations (loop_start, loop_end, loop_info) else abort (); + /* It may be that comparison_mode is smaller than a HOST_WIDE_INT, + for instance on a 64-bit host when comparison_mode is SImode. */ + abs_diff &= GET_MODE_MASK (comparison_mode); + /* For NE tests, make sure that the iteration variable won't miss the final value. If abs_diff mod abs_incr is not zero, then the iteration variable will overflow before the loop exits, and we -- cgit v1.1