This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] m68k.h: Fix PR target/20583.
- From: Kazu Hirata <kazu at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: law at redhat dot com, schwab at suse dot de
- Date: Sun, 6 Nov 2005 17:58:10 -0800
- Subject: [patch] m68k.h: Fix PR target/20583.
Hi,
Attached is a patch to fix PR target/20583.
Consider the testcase below. Tree optimizers fail to optimize away
the switch statement even though **q is known to be 3. CSE catches
this opportunity and tries to fold the switch statement and generate
(set (reg:HI ...)
(const:HI (truncate:HI (minus:HI (label_ref ...)
(label_ref ...)))))
Assembly output functions do not know how to handle this piece of rtx.
Specifically, output_addr_const does not know how to output
(truncate:HI ...) and triggers an ICE.
The patch simply teaches LEGITIMATE_CONSTANT_P to reject
(const:xx (truncate:xx ...)).
Tested on m68k-elf (modulo execution tests). OK to apply?
Kazu Hirata
2005-11-07 Kazu Hirata <kazu@codesourcery.com>
PR target/20583
* m68k.h (LEGITIMATE_CONSTANT_P): Reject CONST wrapping
TRUNCATE.
2005-11-07 Kazu Hirata <kazu@codesourcery.com>
PR target/20583
* gcc.c-torture/compile/pr20583.c: New.
Index: m68k.h
===================================================================
--- m68k.h (revision 106554)
+++ m68k.h (working copy)
@@ -639,7 +639,9 @@ __transfer_from_trampoline () \
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-#define LEGITIMATE_CONSTANT_P(X) (GET_MODE (X) != XFmode)
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_MODE (X) != XFmode \
+ && !(GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == TRUNCATE))
#ifndef REG_OK_STRICT
#define PCREL_GENERAL_OPERAND_OK 0
--- /dev/null 2005-09-01 09:08:28.063949816 -0700
+++ pr20583.c 2005-11-06 17:56:13.987167405 -0800
@@ -0,0 +1,30 @@
+/* PR target/20583
+ On m68k-none-elf, CSE used to generate
+
+ (set (reg:HI ...)
+ (const:HI (truncate:HI (minus:HI (label_ref ...)
+ (label_ref ...)))))
+
+ which output functions do not know how to handle. Make sure that
+ such a constant will be rejected. */
+
+void bar (unsigned int);
+
+void
+foo (void)
+{
+ char buf[1] = { 3 };
+ const char *p = buf;
+ const char **q = &p;
+ unsigned int ch;
+ switch (**q)
+ {
+ case 1: ch = 5; break;
+ case 2: ch = 4; break;
+ case 3: ch = 3; break;
+ case 4: ch = 2; break;
+ case 5: ch = 1; break;
+ default: ch = 0; break;
+ }
+ bar (ch);
+}