This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] combine.c: Fix execute/0021120-2.c and execute/941101-1.c.
- From: Kazu Hirata <kazu at cs dot umass dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Cc: echristo at redhat dot com
- Date: Mon, 02 Jun 2003 19:28:44 -0400 (EDT)
- Subject: [patch] combine.c: Fix execute/0021120-2.c and execute/941101-1.c.
- References: <20030601.185539.21936407.kazu@cs.umass.edu>
Hi,
The attached is a patch to fix regressions caused by
http://gcc.gnu.org/ml/gcc-patches/2003-03/msg02597.html
Specifically, on H8, the patch causes execute/20021120-2.c and
execute/941101-1.c to fail at compile time.
Consider the following, derived from 941101-1.c.
/* h8300-hms-gcc -mh -O2 */
int
foo ()
{
int var = 7;
return var / 7;
}
After the life analysis, we have:
(set (reg:SI 22)
(const_int 7))
(set (reg:HI 23)
(subreg:HI (reg:SI 22) 2))
(parallel
[(set (reg:HI 20)
(truncate:HI (div:SI (reg:SI 22)
(sign_extend:SI (reg:HI 23)))))
(set (reg:HI 21)
(truncate:HI (mod:SI (reg:SI 22)
(sign_extend:SI (reg:HI 23)))))])
(set (reg/i:HI 0) <- this (reg 0) is the return value register
(reg:HI 20))
With the patch, the combiner outputs
(set (subreg:SI (reg:HI 21) 0) <- This code is redundant.
(const_int 0)) The result of mod:SI is not used.
(set (subreg:SI (reg:HI 20) 0)
(const_int 1))
(set (reg/i:HI 0 r0)
(reg:HI 20))
and I see
941101-1.c: In function `foo':
941101-1.c:6: internal compiler error: in find_free_reg, at local-alloc.c:2185
local-alloc does not seem to like
(set (subreg:SI (...) 0) (const_int))
which I don't think is valid on a machine without
WORD_REGISTER_OPERATIONS because of
http://gcc.gnu.org/ml/gcc/2003-06/msg00111.html
http://gcc.gnu.org/ml/gcc/2003-06/msg00115.html
The patch avoids creating a paradoxical subreg as a SET_DEST. With
the patch, the combiner outputs
(set (reg:HI 20)
(const_int 1))
(set (reg/i:HI 0)
(reg:HI 20))
Tested on h8300 port. OK to apply?
Kazu Hirata
2003-06-02 Kazu Hirata <kazu@cs.umass.edu>
* combine.c (simplify_set): Don't move a subreg in SET_SRC to
SET_DEST if WORD_REGISTER_OPERATIONS is not defined.
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.358
diff -u -9 -r1.358 combine.c
--- combine.c 16 May 2003 02:05:29 -0000 1.358
+++ combine.c 2 Jun 2003 14:17:45 -0000
@@ -5232,57 +5232,55 @@
}
else
{
/* Get SET_SRC in a form where we have placed back any
compound expressions. Then do the checks below. */
src = make_compound_operation (src, SET);
SUBST (SET_SRC (x), src);
}
+#ifdef WORD_REGISTER_OPERATIONS
/* If we have (set x (subreg:m1 (op:m2 ...) 0)) with OP being some operation,
and X being a REG or (subreg (reg)), we may be able to convert this to
(set (subreg:m2 x) (op)).
We can always do this if M1 is narrower than M2 because that means that
we only care about the low bits of the result.
However, on machines without WORD_REGISTER_OPERATIONS defined, we cannot
perform a narrower operation than requested since the high-order bits will
be undefined. On machine where it is defined, this transformation is safe
as long as M1 and M2 have the same number of words. */
if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
&& GET_RTX_CLASS (GET_CODE (SUBREG_REG (src))) != 'o'
&& (((GET_MODE_SIZE (GET_MODE (src)) + (UNITS_PER_WORD - 1))
/ UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))
-#ifndef WORD_REGISTER_OPERATIONS
- && (GET_MODE_SIZE (GET_MODE (src))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
-#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
GET_MODE (SUBREG_REG (src)),
GET_MODE (src)))
#endif
&& (GET_CODE (dest) == REG
|| (GET_CODE (dest) == SUBREG
&& GET_CODE (SUBREG_REG (dest)) == REG)))
{
SUBST (SET_DEST (x),
gen_lowpart_for_combine (GET_MODE (SUBREG_REG (src)),
dest));
SUBST (SET_SRC (x), SUBREG_REG (src));
src = SET_SRC (x), dest = SET_DEST (x);
}
+#endif
#ifdef HAVE_cc0
/* If we have (set (cc0) (subreg ...)), we try to remove the subreg
in SRC. */
if (dest == cc0_rtx
&& GET_CODE (src) == SUBREG
&& subreg_lowpart_p (src)
&& (GET_MODE_BITSIZE (GET_MODE (src))
< GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (src)))))