This is the mail archive of the
mailing list for the GCC project.
[PATCH] Fix reload ICE with swapped operands
- From: Ulrich Weigand <uweigand at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 14 Feb 2005 15:20:52 +0100 (CET)
- Subject: [PATCH] Fix reload ICE with swapped operands
Andreas' new regression tester has revealed a latent bug in
find_reloads, which causes test case failures on s390-ibm-linux
when building the compiler with --enable-checking=release.
The problem shows up with my *cmpsi_cct pattern, which reads
[(set (reg 33)
(compare (match_operand:SI 0 "nonimmediate_operand" "%d,d,d,d,Q")
(match_operand:SI 1 "general_operand" "d,K,R,T,BQ")))]
Note that Q is an EXTRA_MEMORY_CONSTRAINT, while BQ is a two-letter
EXTRA_CONSTRAINT. Both accept memory operands without an index register;
BQ in addition rejects constant pool references.
Now assume we get here in find_reloads with the first operand a MEM
with invalid address, and the second operand a MEM with valid address
but with index register. Before considering alternatives, find_reload
will notice that the first operand requires an address reload. It will
push the corresponding reloads, and set address_reloaded to true.
Since address_reloaded is true, operand 0 will fulfil the 'Q'
constraint. But as operand 1 has an index register, it won't
fultil 'BQ', and since BQ is not an EXTRA_MEMORY_CONSTRAINT,
find_reload gives up on this alternative.
So it will find no alternative that wins without reload. However,
as the insn has a '%' marker, it will now try again with operands
0 and 1 swapped. The way this works is by swapping in-place the
find_reloads data structures corresponding to the two operands.
Unfortunately, the address_reloads array is *not* swapped here.
Thus in the next pass through the alternatives list, the (now)
operand 0 of the form 'mem (base + index)' will get accepted,
because address_reloaded is still true, even though the new
operand 0 did *not* have its address reloaded ...
The patch below fixes the problem by swapping address_reloaded
at the same place preferred_class and pref_or_nothing are already
swapped. (It looks like none of the other per-operand arrays in
find_reloads need to be swapped; but the whole things appears
somewhat fragile to me ...)
Bootstrapped/regtested on s390-ibm-linux, s390x-ibm-linux, and
i386-pc-linux. OK for mainline?
* reload.c (find_reloads): Swap address_reloaded flags when
swapping commutative operands.
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.265
diff -c -p -r1.265 reload.c
*** gcc/reload.c 15 Jan 2005 16:06:15 -0000 1.265
--- gcc/reload.c 22 Jan 2005 19:47:09 -0000
*************** find_reloads (rtx insn, int replace, int
*** 3668,3673 ****
--- 3668,3677 ----
pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
pref_or_nothing[commutative + 1] = t;
+ t = address_reloaded[commutative];
+ address_reloaded[commutative] = address_reloaded[commutative + 1];
+ address_reloaded[commutative + 1] = t;
memcpy (constraints, recog_data.constraints,
noperands * sizeof (char *));
Dr. Ulrich Weigand
Linux on zSeries Development