This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR middle-end/19378: Fix AVR build failures / possibly less restrictive alternative.
- From: Björn Haase <bjoern dot m dot haase at web dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: roger at eyesopen dot com,Paul Schlie <schlie at comcast dot net>
- Date: Wed, 19 Jan 2005 00:03:45 +0100
- Subject: [PATCH] PR middle-end/19378: Fix AVR build failures / possibly less restrictive alternative.
The bug that this patch is addressing is discussed more in detail in
?http://gcc.gnu.org/ml/gcc-patches/2005-01/msg00834.html
and the thread
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18887
.
Brief summary:
Current Head 4.0.0 cannot be built for the avr-target: It breaks due to some
problem with reloading DI expressions. Problem appears to be a problem in the
back-end code that has become evident only recently due to a change in
reload.c .
Roger Sayle has suggested a very similar patch disallowing to span Reg28:29
completely:
>The following patch resolves PR middle-end/19378 which is an ICE
>compiling libgcc for AVR, due to an abort in reload.c's find_valid_class.
>It turns out that the undelying problem is in avr.c's definition of
>avr_hard_regno_mode_ok. This function currently allows a DImode psuedo
>to be allocated in the 8 QImode registers starting at r24. Unfortunately,
>this same function doesn't allow the 6th register of that same DImode
>value to be accessed, as avr_hard_regno_mode_ok returns false for r29
>in QImode!
>
>The solution I've taken below is to completely rewrite this function
>such that the pair of registers r28 and r29 are effectively always
>reserved for holding Pmode values (i.e. the frame pointer). We then
>reject any other regno/mode combination that overlaps with this pair.
>It may be possible to improve upon this logic allowing r28 and r29
>as general registers when the frame pointer is not required, but I
>didn't fancy risking this without more active avr maintainers.
Since in many occasions, especially for the more common case that the embedded
application does not use any long longs, the frame pointer can be avoided
completely. I would prefer a solution, that only affects the use of long
longs since this way, the Y register possibly could be used also for
containing SI or HI values.
The following alternative patch removes the problem for the current head
revision by restricting the DI values to be allowed to be placed in all
registers except for the pointer registers.
Yours,
Björn
Index: avr.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/avr/avr.c,v
retrieving revision 1.125
diff -U17 -r1.125 avr.c
--- avr.c 25 Dec 2004 22:20:04 -0000 1.125
+++ avr.c 18 Jan 2005 22:34:16 -0000
@@ -5120,34 +5120,45 @@
int
avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
{
/* Bug workaround: recog.c (peep2_find_free_register) and probably
a few other places assume that the frame pointer is a single hard
register, so r29 may be allocated and overwrite the high byte of
the frame pointer. Do not allow any value to start in r29. */
if (regno == REG_Y + 1)
return 0;
/* Reload can use r28:r29 for reload register and for frame pointer
in one insn. It's wrong. We must disable it. */
if (mode != Pmode && reload_in_progress && frame_pointer_required_p ()
&& regno <= REG_Y && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
return 0;
+ /* Reload has problems when trying to place DI in registers since */
+ /* acessing r29 with mode QI is explicitly forbidden. */
+ /* When allowing DI to start only below reg:20, we prevent also that */
+ /* the precious pointer registers are wasted for DI objects. */
+ if (mode == DImode)
+ { if ((regno < 20) && (!(regno & 1)))
+ return 1;
+ else
+ return 0;
+ }
+
if (mode == QImode)
return 1;
/* if (regno < 24 && !AVR_ENHANCED)
return 1;*/
return !(regno & 1);
}
/* Returns 1 if X is a valid address for an I/O register of size SIZE
(1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
int
avr_io_address_p (rtx x, int size)
{
return (optimize > 0 && GET_CODE (x) == CONST_INT
&& INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
}