This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix PR rtl-optimization/46490
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Nov 2010 23:29:57 +0100
- Subject: Fix PR rtl-optimization/46490
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.
--
Eric Botcazou
Index: combine.c
===================================================================
--- combine.c (revision 166792)
+++ combine.c (working copy)
@@ -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));
-- { dg-do run }
-- { dg-options "-O2" }
with Opt12_Pkg; use Opt12_Pkg;
procedure Opt12 is
Static_Target : Static_Integer_Subtype;
begin
Static_Target := Static_Integer_Subtype(Fix_Half);
if not Equal(Static_Target, 1) then
raise Program_Error;
end if;
end Opt12;
package body Opt12_Pkg is
function Equal (L, R: Static_Integer_Subtype) return Boolean is
begin
return (L = R);
end;
end Opt12_Pkg;
package Opt12_Pkg is
type Static_Integer_Subtype is range -32_000 .. 32_000;
function Equal (L, R: Static_Integer_Subtype) return Boolean;
type My_Fixed is delta 0.1 range -5.0 .. 5.0;
Fix_Half : My_Fixed := 0.5;
end Opt12_Pkg;