This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]