This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[testcase] 3.{1,1.1,2} ICE on IA-32
- From: Jakub Jelinek <jakub at redhat dot com>
- To: rth at redhat dot com, m dot hayes at elec dot canterbury dot ac dot nz
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 29 Jul 2002 19:01:52 +0200
- Subject: [testcase] 3.{1,1.1,2} ICE on IA-32
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following testcase ICEs on IA-32. The reason is that precondition_loop_p
computes initial_value as
(ashift:SI (plus:SI (reg/v:SI 63) (const_int -1 [0xffffffff])) (const_int 12 [0xc]))
(this comes from fold_rtx_mult_add) and doloop.c (doloop_modify_runtime)
/* abs (final - initial) */
diff = expand_simple_binop (mode, MINUS,
copy_rtx (neg_inc ? initial_value : final_value),
copy_rtx (neg_inc ? final_value : initial_value),
NULL_RTX, unsigned_p, OPTAB_LIB_WIDEN);
passes these to expand_simple_binop.
This results in
(insn 169 162 171 (set (reg:SI 90)
(ashift:SI (plus:SI (reg/v:SI 63)
(const_int -1 [0xffffffff]))
(const_int 12 [0xc]))) -1 (insn_list 28 (nil))
(nil))
instruction which of course cannot be recognized.
force_reg wouldn't help here, it would result in the identical instruction.
Now, what's the right fix for this?
Disallowing this from being assigned into initial_value could kill
some optimization options (e.g. when it is possible to
simplify the difference between initial_value and final_value).
Should the fix be some force_reg like function for loop which would try to
recog the instruction and if it would not recognize it, would go
inside PLUS, MULT or ASHIFT, maybe others, and first do force_reg on the
argument, then on the whole pattern with the arguments replaced by the
registers (and should it add REG_EQUIV in that case or not)?
Or should doloop_modify_runtime try to recog all instructions it generated
in the sequence and if any of them fails to recognize, bail out?
2002-07-29 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20020729-1.c: New test.
--- gcc/testsuite/gcc.dg/20020729-1.c.jj 2002-07-23 20:50:16.000000000 +0200
+++ gcc/testsuite/gcc.dg/20020729-1.c 2002-07-29 15:03:23.000000000 +0200
@@ -0,0 +1,51 @@
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-options "-O2 -march=k6" } */
+
+static inline void *
+baz (void *s, unsigned long c, unsigned int count)
+{
+ int d0, d1;
+ __asm__ __volatile__ (""
+ : "=&c" (d0), "=&D" (d1)
+ :"a" (c), "q" (count), "0" (count / 4), "1" ((long) s)
+ :"memory");
+ return s;
+}
+
+struct A
+{
+ unsigned long *a;
+};
+
+inline static void *
+bar (struct A *x, int y)
+{
+ char *ptr;
+
+ ptr = (void *) x->a[y >> 12];
+ ptr += y % (1UL << 12);
+ return (void *) ptr;
+}
+
+int
+foo (struct A *x, unsigned int *y, int z, int u)
+{
+ int a, b, c, d, e;
+
+ z += *y;
+ c = z + u;
+ a = (z >> 12) + 1;
+ do
+ {
+ b = (a << 12);
+ d = b - z;
+ e = c - z;
+ if (e < d)
+ d = e;
+ baz (bar (x, z), 0, d);
+ z = b;
+ a++;
+ }
+ while (z < c);
+ return 0;
+}
Jakub