This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: A patch for a bad combine bug
- To: hjl at lucon dot org (H.J. Lu)
- Subject: Re: A patch for a bad combine bug
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Fri, 03 Jul 1998 21:51:11 -0600
- cc: hymie at prolifics dot com, egcs-patches at cygnus dot com, kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner)
- Reply-To: law at cygnus dot com
In message <m0ykbCQ-00026AC@ocean.lucon.org>you write:
> The bug is introduced by
>
> Wed Mar 18 05:54:25 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
>
> * combine.c (simplify_comparison, case AND): Commute AND and
> SUBREG.
>
> I am not sure if my patch is correct. But Kenner's change is wrong.
Agreed. It isn't safe to commute AND into a paradoxical subreg if
WORD_REGISTER_OPERATIONS is not defined.
Consider
(and:SI (subreg:SI (reg:QI) 0) (const_int 127)
This states quite clearly that only the low 7 bits can possibly have nonzero
values after evaluation of this expression.
However, the current combiner can turn that into
(subreg:SI (and:QI (reg:QI 24) (const_int 127)) 0)
Which allows the upper 24 bits to have undetermined values after evaluation.
I'll check in this fix to egcs asap if nobody beat me to this bug over
the weekend:
* combine.c (simplify_comparison, case AND): Do not commute
AND into a paradoxical SUBREG if WORD_REGISTER_OPERATIONS is
not defined.
*** combine.c.ORIG Fri Jul 3 21:49:34 1998
--- combine.c Fri Jul 3 21:49:44 1998
*************** simplify_comparison (code, pop0, pop1)
*** 10154,10159 ****
--- 10154,10169 ----
|| subreg_lowpart_p (XEXP (op0, 0))
#endif
)
+ #ifndef WORD_REGISTER_OPERATIONS
+ /* It is unsafe to commute the AND into the SUBREG if the SUBREG
+ is paradoxical and WORD_REGISTER_OPERATIONS is not defined.
+ As originally written the upper bits have a defined value
+ due to the AND operation. However, if we commute the AND
+ inside the SUBREG then they no longer have defined values
+ and the meaning of the code has been changed. */
+ && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)))
+ <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))
+ #endif
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
jeff