Comments
Patch
===================================================================
@@ -6761,11 +6761,11 @@ expand_compound_operation (rtx x)
count. This can happen in a case like (x >> 31) & 255 on machines
that can't shift by a constant. On those machines, we would first
combine the shift with the AND to produce a variable-position
- extraction. Then the constant of 31 would be substituted in to produce
- a such a position. */
+ extraction. Then the constant of 31 would be substituted in
+ to produce such a position. */
modewidth = GET_MODE_BITSIZE (GET_MODE (x));
- if (modewidth + len >= pos)
+ if (modewidth >= pos + len)
{
enum machine_mode mode = GET_MODE (x);
tem = gen_lowpart (mode, XEXP (x, 0));
This is a regression with -O2 -mtune=i386 present on the mainline. The combiner turns: (insn 9 8 10 2 (set (reg:QI 68) (sign_extract:QI (reg:HI 70) (const_int 8 [0x8]) (const_int 8 [0x8]))) p.adb:9 64 {*movqi_extv_1} (expr_list:REG_EQUAL (mod:QI (reg:QI 66 [ q__fix_half ]) (const_int 16 [0x10])) (nil))) (insn 11 10 12 2 (set (reg:QI 72) (reg:QI 68)) p.adb:9 52 {*movqi_internal} (expr_list:REG_DEAD (reg:QI 68) (nil))) into: (insn 11 10 12 2 (parallel [ (set (reg:QI 72) (ashift:QI (subreg:QI (reg:HI 70) 0) (const_int -8 [0xfffffff8]))) (clobber (reg:CC 17 flags)) ]) p.adb:9 391 {*ashlqi3_1_lea} (expr_list:REG_UNUSED (reg:CC 17 flags) (expr_list:REG_DEAD (reg:HI 70) (nil)))) Note the bogus (const_int -8). Yet the combiner specifically checks for that: /* If we reach here, we want to return a pair of shifts. The inner shift is a left shift of BITSIZE - POS - LEN bits. The outer shift is a right shift of BITSIZE - LEN bits. It is arithmetic or logical depending on the value of UNSIGNEDP. If this was a ZERO_EXTEND or ZERO_EXTRACT, this pair of shifts will be converted into an AND of a shift. We must check for the case where the left shift would have a negative count. This can happen in a case like (x >> 31) & 255 on machines that can't shift by a constant. On those machines, we would first combine the shift with the AND to produce a variable-position extraction. Then the constant of 31 would be substituted in to produce a such a position. */ but there has been a thinko in the check since the first revision (r357). This had apparently stayed latent until after H.J. added the 8-bit divmov support to the x86 port in June, with the unusual sign_extract pattern. Tested on i586-suse-linux, applied on the mainline 2010-11-16 Eric Botcazou <ebotcazou@adacore.com> PR rtl-optimization/46490 * combine.c (expand_compound_operation): Fix thinko. 2010-11-16 Eric Botcazou <ebotcazou@adacore.com> * gnat.dg/opt12.adb: New test. * gnat.dg/opt12_pkg.ad[sb]: New helper.