* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
@ 2004-10-31 12:53 ` ralf_corsepius at rtems dot org
2004-10-31 12:54 ` ralf_corsepius at rtems dot org
` (26 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: ralf_corsepius at rtems dot org @ 2004-10-31 12:53 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From ralf_corsepius at rtems dot org 2004-10-31 12:53 -------
Created an attachment (id=7441)
--> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=7441&action=view)
example code to reproduce the breakdown.
The example code is a stripped down version of a much larger real world piece
of code triggering this breakdown
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
2004-10-31 12:53 ` [Bug target/18251] " ralf_corsepius at rtems dot org
@ 2004-10-31 12:54 ` ralf_corsepius at rtems dot org
2004-10-31 14:47 ` pinskia at gcc dot gnu dot org
` (25 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: ralf_corsepius at rtems dot org @ 2004-10-31 12:54 UTC (permalink / raw)
To: gcc-bugs
--
What |Removed |Added
----------------------------------------------------------------------------
CC| |joel at oarcorp dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
2004-10-31 12:53 ` [Bug target/18251] " ralf_corsepius at rtems dot org
2004-10-31 12:54 ` ralf_corsepius at rtems dot org
@ 2004-10-31 14:47 ` pinskia at gcc dot gnu dot org
2005-02-08 19:17 ` pinskia at gcc dot gnu dot org
` (24 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-10-31 14:47 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-31 14:47 -------
Confirmed on the mainline.
--
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Ever Confirmed| |1
Keywords| |ice-on-valid-code
Known to fail| |4.0.0
Last reconfirmed|0000-00-00 00:00:00 |2004-10-31 14:47:03
date| |
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (2 preceding siblings ...)
2004-10-31 14:47 ` pinskia at gcc dot gnu dot org
@ 2005-02-08 19:17 ` pinskia at gcc dot gnu dot org
2005-02-10 0:35 ` bjoern dot m dot haase at web dot de
` (23 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2005-02-08 19:17 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From pinskia at gcc dot gnu dot org 2005-02-08 13:55 -------
*** Bug 19822 has been marked as a duplicate of this bug. ***
--
What |Removed |Added
----------------------------------------------------------------------------
CC| |dieterbmeier at yahoo dot
| |com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (3 preceding siblings ...)
2005-02-08 19:17 ` pinskia at gcc dot gnu dot org
@ 2005-02-10 0:35 ` bjoern dot m dot haase at web dot de
2005-02-10 1:16 ` bjoern dot m dot haase at web dot de
` (22 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: bjoern dot m dot haase at web dot de @ 2005-02-10 0:35 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From bjoern dot m dot haase at web dot de 2005-02-09 20:27 -------
The bug seems still to be present in head 4.0.0.
The failing example could be stripped down a little bit further:
// Begin of sample code
unsigned long semaphore_create (unsigned long name,
unsigned long count,
unsigned long attribute_set,
unsigned long *id
);
struct termios
{
unsigned int c_iflag;
unsigned int c_oflag;
unsigned int c_cflag;
unsigned int c_lflag;
unsigned char c_cc[19];
};
typedef struct termios_callbacks
{
int (*firstOpen) (int major, int minor, void *arg);
int (*lastClose) (int major, int minor, void *arg);
int (*pollRead) (int minor);
} termios_callbacks;
void *calloc (unsigned int __nmemb, unsigned int __size);
struct termios_rawbuf
{
char *theBuf;
int Head;
int Tail;
int Size;
int Semaphore;
};
struct termios_tty
{
struct termios_tty *forw;
struct termios_tty *back;
unsigned long major;
unsigned long minor;
unsigned long isem;
unsigned long osem;
char *cbuf;
int ccount;
int cindex;
int column;
int read_start_column;
struct termios termios;
struct termios_rawbuf rawInBuf;
struct termios_rawbuf rawOutBuf;
termios_callbacks device;
unsigned int flow_ctrl;
unsigned int lowwater, highwater;
unsigned int rxTaskId;
unsigned int txTaskId;
int tty_rcvwakeup;
};
unsigned long
termios_open (unsigned long major,
unsigned long minor,
struct termios_tty *tty,
const termios_callbacks * callbacks)
{
unsigned long sc;
{
tty = calloc (1,0);
if (tty == ((void *) 0))
return 0;
tty->rawInBuf.Size = 128;
tty->minor = minor;
tty->major = major;
sc = semaphore_create (0, 1, 0, 0 );
tty->device = *callbacks;
tty->lowwater = tty->rawInBuf.Size * 1 / 2;
}
}
// End of sample code
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (4 preceding siblings ...)
2005-02-10 0:35 ` bjoern dot m dot haase at web dot de
@ 2005-02-10 1:16 ` bjoern dot m dot haase at web dot de
2005-02-12 16:56 ` andrewhutchinson at cox dot net
` (21 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: bjoern dot m dot haase at web dot de @ 2005-02-10 1:16 UTC (permalink / raw)
To: gcc-bugs
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 467 bytes --]
------- Additional Comments From bjoern dot m dot haase at web dot de 2005-02-09 23:14 -------
Maybe this will help to localize the origin of the bug a bit better:
I have made the observation that the presence of the bug strongly depends on
the size of the memory footprint of the structs. Maybe there is a problem when
the stack frame starts to grow beyond the 128 Byte boundary.
Yours,
Björn
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (5 preceding siblings ...)
2005-02-10 1:16 ` bjoern dot m dot haase at web dot de
@ 2005-02-12 16:56 ` andrewhutchinson at cox dot net
2005-02-14 0:04 ` giovannibajo at libero dot it
` (20 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: andrewhutchinson at cox dot net @ 2005-02-12 16:56 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From andrewhutchinson at cox dot net 2005-02-12 13:50 -------
A sub-optimal fix is to disable movmemhi expansion. Either delete it or the less
draconian:
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:HI 2 "const_int_operand" ""))
(use (match_operand:HI 3 "const_int_operand" ""))
(clobber (match_scratch:HI 4 ""))
(clobber (match_scratch:HI 5 ""))
(clobber (match_dup 6))])]
"(0)"
etc
A better solution is currently being tested.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (6 preceding siblings ...)
2005-02-12 16:56 ` andrewhutchinson at cox dot net
@ 2005-02-14 0:04 ` giovannibajo at libero dot it
2005-02-22 16:04 ` dieterbmeier at yahoo dot com
` (19 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: giovannibajo at libero dot it @ 2005-02-14 0:04 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From giovannibajo at libero dot it 2005-02-13 17:25 -------
Andy, the patch needs a ChangeLog and needs to be posted to gcc-patches. I
suggest you to explicitly CC the AVR maintainers when you post the patch.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (7 preceding siblings ...)
2005-02-14 0:04 ` giovannibajo at libero dot it
@ 2005-02-22 16:04 ` dieterbmeier at yahoo dot com
2005-02-22 17:13 ` andrewhutchinson at cox dot net
` (18 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: dieterbmeier at yahoo dot com @ 2005-02-22 16:04 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From dieterbmeier at yahoo dot com 2005-02-22 10:32 -------
Andy's patch works great for HEAD, but I get
patching file avr.md
Hunk #1 FAILED at 344.
1 out of 1 hunk FAILED -- saving rejects to file avr.md.rej
when patching 3_4 branch.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (8 preceding siblings ...)
2005-02-22 16:04 ` dieterbmeier at yahoo dot com
@ 2005-02-22 17:13 ` andrewhutchinson at cox dot net
2005-02-22 17:25 ` ericw at evcohs dot com
` (17 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: andrewhutchinson at cox dot net @ 2005-02-22 17:13 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From andrewhutchinson at cox dot net 2005-02-22 12:31 -------
Subject: Re: unable to find a register to spill in class
`POINTER_REGS'
if you can wait 12hrs I'll create 3.4 version.
Alternatively cut n paste from a 4.0 avr.md
the change is local to one area.
dieterbmeier at yahoo dot com wrote:
>------- Additional Comments From dieterbmeier at yahoo dot com 2005-02-22 10:32 -------
>Andy's patch works great for HEAD, but I get
>
>patching file avr.md
>Hunk #1 FAILED at 344.
>1 out of 1 hunk FAILED -- saving rejects to file avr.md.rej
>
>when patching 3_4 branch.
>
>
>
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (9 preceding siblings ...)
2005-02-22 17:13 ` andrewhutchinson at cox dot net
@ 2005-02-22 17:25 ` ericw at evcohs dot com
2005-03-05 9:33 ` dieterbmeier at yahoo dot com
` (16 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: ericw at evcohs dot com @ 2005-02-22 17:25 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From ericw at evcohs dot com 2005-02-22 13:19 -------
Subject: Re: unable to find a register to spill in class
`POINTER_REGS'
dieterbmeier at yahoo dot com wrote:
>------- Additional Comments From dieterbmeier at yahoo dot com 2005-02-22 10:32 -------
>Andy's patch works great for HEAD, but I get
>
>patching file avr.md
>Hunk #1 FAILED at 344.
>1 out of 1 hunk FAILED -- saving rejects to file avr.md.rej
>
>when patching 3_4 branch.
>
>
>
That's usually expected: a patch for HEAD does not guarantee that the
patch will work for an earlier branch (3.4.x). Remember, this patch
fixes a bug found on HEAD.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (10 preceding siblings ...)
2005-02-22 17:25 ` ericw at evcohs dot com
@ 2005-03-05 9:33 ` dieterbmeier at yahoo dot com
2005-03-10 20:50 ` joel at gcc dot gnu dot org
` (15 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: dieterbmeier at yahoo dot com @ 2005-03-05 9:33 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From dieterbmeier at yahoo dot com 2005-03-05 09:33 -------
18251gcc34.patch.bz2 makes termios.c and arpcache.i to compile again on
3_4-20050305.
Thank you!
Can we have this patch in 3.4.4?
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (11 preceding siblings ...)
2005-03-05 9:33 ` dieterbmeier at yahoo dot com
@ 2005-03-10 20:50 ` joel at gcc dot gnu dot org
2005-03-10 21:30 ` ericw at evcohs dot com
` (14 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: joel at gcc dot gnu dot org @ 2005-03-10 20:50 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From joel at gcc dot gnu dot org 2005-03-10 20:50 -------
Any chance of this getting committed to the 3.4, 4.0 and 4.1 branches so it
can be closed?
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (12 preceding siblings ...)
2005-03-10 20:50 ` joel at gcc dot gnu dot org
@ 2005-03-10 21:30 ` ericw at evcohs dot com
2005-03-12 20:39 ` marekm at amelek dot gda dot pl
` (13 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: ericw at evcohs dot com @ 2005-03-10 21:30 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From ericw at evcohs dot com 2005-03-10 21:30 -------
Marek, can you review this bug, the attached patches, and possibly approve
committing the fix?
Thanks
Eric
--
What |Removed |Added
----------------------------------------------------------------------------
CC| |marekm at amelek dot gda dot
| |pl
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (13 preceding siblings ...)
2005-03-10 21:30 ` ericw at evcohs dot com
@ 2005-03-12 20:39 ` marekm at amelek dot gda dot pl
2005-03-12 21:20 ` andrewhutchinson at cox dot net
` (12 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: marekm at amelek dot gda dot pl @ 2005-03-12 20:39 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From marekm at amelek dot gda dot pl 2005-03-12 20:39 -------
(In reply to comment #17)
> Marek, can you review this bug, the attached patches, and possibly approve
> committing the fix?
I'm looking into it right now. I'm not sure about one thing: should "movmemhi"
handle only constant block sizes, or variable block sizes too? If variable -
is it safe to assume nonzero? (now 0 means 65536)
Operand 2 (block size) has the "const_int_operand" predicate - doesn't this
mean that (GET_CODE(operands[2]) == CONST_INT) is always true?
Thanks,
Marek
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (14 preceding siblings ...)
2005-03-12 20:39 ` marekm at amelek dot gda dot pl
@ 2005-03-12 21:20 ` andrewhutchinson at cox dot net
2005-03-13 0:31 ` marekm at amelek dot gda dot pl
` (11 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: andrewhutchinson at cox dot net @ 2005-03-12 21:20 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From andrewhutchinson at cox dot net 2005-03-12 21:20 -------
(In reply to comment #18)
> (In reply to comment #17)
I think it is always true but the original used the same predicate and test (so
I played safe).
The pattern only helps if it is a constant. I also thought it should handle
variable block size. However, I found gcc already produces optimal code for
that case without any help.
> > Marek, can you review this bug, the attached patches, and possibly approve
> > committing the fix?
>
> I'm looking into it right now. I'm not sure about one thing: should "movmemhi"
> handle only constant block sizes, or variable block sizes too? If variable -
> is it safe to assume nonzero? (now 0 means 65536)
>
> Operand 2 (block size) has the "const_int_operand" predicate - doesn't this
> mean that (GET_CODE(operands[2]) == CONST_INT) is always true?
>
> Thanks,
> Marek
>
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (15 preceding siblings ...)
2005-03-12 21:20 ` andrewhutchinson at cox dot net
@ 2005-03-13 0:31 ` marekm at amelek dot gda dot pl
2005-03-13 1:20 ` andrewhutchinson at cox dot net
` (10 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: marekm at amelek dot gda dot pl @ 2005-03-13 0:31 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From marekm at amelek dot gda dot pl 2005-03-13 00:30 -------
Subject: Re: unable to find a register to spill in class `POINTER_REGS'
On Sat, Mar 12, 2005 at 09:20:18PM -0000, andrewhutchinson at cox dot net wrote:
> The pattern only helps if it is a constant. I also thought it should handle
> variable block size. However, I found gcc already produces optimal code for
> that case without any help.
See below for revised patch (currently for mainline):
- FAIL if count is not a CONST_INT
- handle count == 0 (nothing to do)
- handle count > 32767 (negative in RTL, mask with 0xffff)
- minor formatting fixes
But, I'm still concerned a little about the variable block size:
- __tmp_reg__ will not be used (some other register will)
- more importantly, can the problem from this PR (unable to find a register
to spill in class POINTER_REGS) still occur in the variable size case?
(only with a different, not yet known test case - this means we are
perhaps trying to hide the real bug instead of fixing it...)
If we have to handle the variable count case too, one more insn will
be needed (initially jump to decrementing the counter; test for carry
instead of zero). Some other targets handle this by calling a subroutine
in libgcc.S - smaller (but slower) than generating the loop inline.
Marek
2005-03-12 Andy Hutchinson <HutchinsonAndy@netscape.net>
PR target/18251
* config/avr/avr.md (movmemhi): Rewrite as RTL loop.
(*movmemqi_insn): Delete.
(*movmemhi): Delete.
Index: avr.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.md,v
retrieving revision 1.50
diff -c -3 -p -r1.50 avr.md
*** avr.md 6 Mar 2005 21:50:36 -0000 1.50
--- avr.md 12 Mar 2005 23:51:57 -0000
***************
*** 346,421 ****
;;=========================================================================
;; move string (like memcpy)
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
! (match_operand:BLK 1 "memory_operand" ""))
! (use (match_operand:HI 2 "const_int_operand" ""))
! (use (match_operand:HI 3 "const_int_operand" ""))
! (clobber (match_scratch:HI 4 ""))
! (clobber (match_scratch:HI 5 ""))
! (clobber (match_dup 6))])]
""
"{
! rtx addr0, addr1;
! int cnt8;
enum machine_mode mode;
if (GET_CODE (operands[2]) != CONST_INT)
FAIL;
- cnt8 = byte_immediate_operand (operands[2], GET_MODE (operands[2]));
- mode = cnt8 ? QImode : HImode;
- operands[6] = gen_rtx_SCRATCH (mode);
- operands[2] = copy_to_mode_reg (mode,
- gen_int_mode (INTVAL (operands[2]), mode));
- addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
! operands[0] = gen_rtx_MEM (BLKmode, addr0);
! operands[1] = gen_rtx_MEM (BLKmode, addr1);
}")
- (define_insn "*movmemqi_insn"
- [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
- (mem:BLK (match_operand:HI 1 "register_operand" "e")))
- (use (match_operand:QI 2 "register_operand" "r"))
- (use (match_operand:QI 3 "const_int_operand" "i"))
- (clobber (match_scratch:HI 4 "=0"))
- (clobber (match_scratch:HI 5 "=1"))
- (clobber (match_scratch:QI 6 "=2"))]
- ""
- "ld __tmp_reg__,%a1+
- st %a0+,__tmp_reg__
- dec %2
- brne .-8"
- [(set_attr "length" "4")
- (set_attr "cc" "clobber")])
-
- (define_insn "*movmemhi"
- [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
- (mem:BLK (match_operand:HI 1 "register_operand" "e,e")))
- (use (match_operand:HI 2 "register_operand" "!w,d"))
- (use (match_operand:HI 3 "const_int_operand" ""))
- (clobber (match_scratch:HI 4 "=0,0"))
- (clobber (match_scratch:HI 5 "=1,1"))
- (clobber (match_scratch:HI 6 "=2,2"))]
- ""
- "*{
- if (which_alternative==0)
- return (AS2 (ld,__tmp_reg__,%a1+) CR_TAB
- AS2 (st,%a0+,__tmp_reg__) CR_TAB
- AS2 (sbiw,%A2,1) CR_TAB
- AS1 (brne,.-8));
- else
- return (AS2 (ld,__tmp_reg__,%a1+) CR_TAB
- AS2 (st,%a0+,__tmp_reg__) CR_TAB
- AS2 (subi,%A2,1) CR_TAB
- AS2 (sbci,%B2,0) CR_TAB
- AS1 (brne,.-10));
- }"
- [(set_attr "length" "4,5")
- (set_attr "cc" "clobber,clobber")])
-
;; =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0
;; memset (%0, 0, %1)
--- 346,414 ----
;;=========================================================================
;; move string (like memcpy)
+ ;; implement as RTL loop
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
! (match_operand:BLK 1 "memory_operand" ""))
! (use (match_operand:HI 2 "const_int_operand" ""))
! (use (match_operand:HI 3 "const_int_operand" ""))])]
""
"{
! int prob, count;
enum machine_mode mode;
+ rtx label = gen_label_rtx ();
+ rtx loop_reg;
+ rtx jump;
+
+ /* Copy pointers into new psuedos - they will be changed. */
+ rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+ rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+
+ /* Create rtx for tmp register - we use this as scratch. */
+ rtx tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
if (GET_CODE (operands[2]) != CONST_INT)
FAIL;
! count = INTVAL (operands[2]) & 0xffff;
! if (count == 0)
! DONE;
!
! /* Work out branch probability for latter use. */
! prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;
!
! /* See if constant fit 8 bits. */
! mode = (count < 0x100) ? QImode : HImode;
! /* Create loop counter register. */
! loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));
!
! /* Now create RTL code for move loop. */
! /* Label at top of loop. */
! emit_label (label);
!
! /* Move one byte into scratch and inc pointer. */
! emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
! emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
!
! /* Move to mem and inc pointer. */
! emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
! emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
!
! /* Decrement count. */
! emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
!
! /* Compare with zero and jump if not equal. */
! emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
! label);
! /* Set jump probability based on loop count. */
! jump = get_last_insn ();
! REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
! GEN_INT (prob),
! REG_NOTES (jump));
! DONE;
}")
;; =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0
;; memset (%0, 0, %1)
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (16 preceding siblings ...)
2005-03-13 0:31 ` marekm at amelek dot gda dot pl
@ 2005-03-13 1:20 ` andrewhutchinson at cox dot net
2005-03-13 2:07 ` schlie at comcast dot net
` (9 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: andrewhutchinson at cox dot net @ 2005-03-13 1:20 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From andrewhutchinson at cox dot net 2005-03-13 01:19 -------
Subject: Re: unable to find a register to spill in class
`POINTER_REGS'
The concerns have merit but can be discounted:.
The reload problem occurs because the original pattern demands two
pointers in "parrallel" existence.(Actually two pointers and a
counter!) The current register allocation is imperfect and with this
constraint (and only 3 pointers incl frame) fails to find a solution.
The new RTL expansion does not demand both pointer registers at the same
time - indeed they could be the same register in extreme circumstances.
Breaking up the RTL reveals this to GCC and allows the register
allocator to find a solution. So that is why it works.
The SAME result can also be realised by deleting the offending pattern -
in this situation GCC generates it's own solution which happens to be
identical RTL to the proposed solution (with a 16 bit counter). And
indeed there is no reload failure.
Since the proposed pattern "FAILS", the variable case, we will still end
up with GCC's solution and we can conclude there will be no hidden
reload issue. (It should also be noted that a variable count is also
less retrictive on hard register use than a constant).
Now here is the neat bit!. Since GCC middle end generates the detailed
RTL loop, for a variable count, we can and should rely on it to
consider any restriction on the variable (ie variable count=0). If not,
its very very broken.
I was very tempted to submit a patch that just deletes the pattern,
however, that would produce worse code for the very common case where
"fixed" count<255.
I hope this clarifies things.
marekm at amelek dot gda dot pl wrote:
>------- Additional Comments From marekm at amelek dot gda dot pl 2005-03-13 00:30 -------
>Subject: Re: unable to find a register to spill in class `POINTER_REGS'
>
>On Sat, Mar 12, 2005 at 09:20:18PM -0000, andrewhutchinson at cox dot net wrote:
>
>
>
>>The pattern only helps if it is a constant. I also thought it should handle
>>variable block size. However, I found gcc already produces optimal code for
>>that case without any help.
>>
>>
>
>See below for revised patch (currently for mainline):
> - FAIL if count is not a CONST_INT
> - handle count == 0 (nothing to do)
> - handle count > 32767 (negative in RTL, mask with 0xffff)
> - minor formatting fixes
>
>But, I'm still concerned a little about the variable block size:
> - __tmp_reg__ will not be used (some other register will)
> - more importantly, can the problem from this PR (unable to find a register
> to spill in class POINTER_REGS) still occur in the variable size case?
> (only with a different, not yet known test case - this means we are
> perhaps trying to hide the real bug instead of fixing it...)
>
>If we have to handle the variable count case too, one more insn will
>be needed (initially jump to decrementing the counter; test for carry
>instead of zero). Some other targets handle this by calling a subroutine
>in libgcc.S - smaller (but slower) than generating the loop inline.
>
>Marek
>
>
>2005-03-12 Andy Hutchinson <HutchinsonAndy@netscape.net>
>
> PR target/18251
> * config/avr/avr.md (movmemhi): Rewrite as RTL loop.
> (*movmemqi_insn): Delete.
> (*movmemhi): Delete.
>
>Index: avr.md
>===================================================================
>RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.md,v
>retrieving revision 1.50
>diff -c -3 -p -r1.50 avr.md
>*** avr.md 6 Mar 2005 21:50:36 -0000 1.50
>--- avr.md 12 Mar 2005 23:51:57 -0000
>***************
>*** 346,421 ****
>
> ;;=========================================================================
> ;; move string (like memcpy)
>
> (define_expand "movmemhi"
> [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
>! (match_operand:BLK 1 "memory_operand" ""))
>! (use (match_operand:HI 2 "const_int_operand" ""))
>! (use (match_operand:HI 3 "const_int_operand" ""))
>! (clobber (match_scratch:HI 4 ""))
>! (clobber (match_scratch:HI 5 ""))
>! (clobber (match_dup 6))])]
> ""
> "{
>! rtx addr0, addr1;
>! int cnt8;
> enum machine_mode mode;
>
> if (GET_CODE (operands[2]) != CONST_INT)
> FAIL;
>- cnt8 = byte_immediate_operand (operands[2], GET_MODE (operands[2]));
>- mode = cnt8 ? QImode : HImode;
>- operands[6] = gen_rtx_SCRATCH (mode);
>- operands[2] = copy_to_mode_reg (mode,
>- gen_int_mode (INTVAL (operands[2]), mode));
>- addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
>- addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
>
>! operands[0] = gen_rtx_MEM (BLKmode, addr0);
>! operands[1] = gen_rtx_MEM (BLKmode, addr1);
> }")
>
>- (define_insn "*movmemqi_insn"
>- [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
>- (mem:BLK (match_operand:HI 1 "register_operand" "e")))
>- (use (match_operand:QI 2 "register_operand" "r"))
>- (use (match_operand:QI 3 "const_int_operand" "i"))
>- (clobber (match_scratch:HI 4 "=0"))
>- (clobber (match_scratch:HI 5 "=1"))
>- (clobber (match_scratch:QI 6 "=2"))]
>- ""
>- "ld __tmp_reg__,%a1+
>- st %a0+,__tmp_reg__
>- dec %2
>- brne .-8"
>- [(set_attr "length" "4")
>- (set_attr "cc" "clobber")])
>-
>- (define_insn "*movmemhi"
>- [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
>- (mem:BLK (match_operand:HI 1 "register_operand" "e,e")))
>- (use (match_operand:HI 2 "register_operand" "!w,d"))
>- (use (match_operand:HI 3 "const_int_operand" ""))
>- (clobber (match_scratch:HI 4 "=0,0"))
>- (clobber (match_scratch:HI 5 "=1,1"))
>- (clobber (match_scratch:HI 6 "=2,2"))]
>- ""
>- "*{
>- if (which_alternative==0)
>- return (AS2 (ld,__tmp_reg__,%a1+) CR_TAB
>- AS2 (st,%a0+,__tmp_reg__) CR_TAB
>- AS2 (sbiw,%A2,1) CR_TAB
>- AS1 (brne,.-8));
>- else
>- return (AS2 (ld,__tmp_reg__,%a1+) CR_TAB
>- AS2 (st,%a0+,__tmp_reg__) CR_TAB
>- AS2 (subi,%A2,1) CR_TAB
>- AS2 (sbci,%B2,0) CR_TAB
>- AS1 (brne,.-10));
>- }"
>- [(set_attr "length" "4,5")
>- (set_attr "cc" "clobber,clobber")])
>-
> ;; =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0
> ;; memset (%0, 0, %1)
>
>--- 346,414 ----
>
> ;;=========================================================================
> ;; move string (like memcpy)
>+ ;; implement as RTL loop
>
> (define_expand "movmemhi"
> [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
>! (match_operand:BLK 1 "memory_operand" ""))
>! (use (match_operand:HI 2 "const_int_operand" ""))
>! (use (match_operand:HI 3 "const_int_operand" ""))])]
> ""
> "{
>! int prob, count;
> enum machine_mode mode;
>+ rtx label = gen_label_rtx ();
>+ rtx loop_reg;
>+ rtx jump;
>+
>+ /* Copy pointers into new psuedos - they will be changed. */
>+ rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
>+ rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
>+
>+ /* Create rtx for tmp register - we use this as scratch. */
>+ rtx tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
>
> if (GET_CODE (operands[2]) != CONST_INT)
> FAIL;
>
>! count = INTVAL (operands[2]) & 0xffff;
>! if (count == 0)
>! DONE;
>!
>! /* Work out branch probability for latter use. */
>! prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;
>!
>! /* See if constant fit 8 bits. */
>! mode = (count < 0x100) ? QImode : HImode;
>! /* Create loop counter register. */
>! loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));
>!
>! /* Now create RTL code for move loop. */
>! /* Label at top of loop. */
>! emit_label (label);
>!
>! /* Move one byte into scratch and inc pointer. */
>! emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
>! emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
>!
>! /* Move to mem and inc pointer. */
>! emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
>! emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
>!
>! /* Decrement count. */
>! emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
>!
>! /* Compare with zero and jump if not equal. */
>! emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
>! label);
>! /* Set jump probability based on loop count. */
>! jump = get_last_insn ();
>! REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
>! GEN_INT (prob),
>! REG_NOTES (jump));
>! DONE;
> }")
>
> ;; =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0
> ;; memset (%0, 0, %1)
>
>
>
>
>
>
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (17 preceding siblings ...)
2005-03-13 1:20 ` andrewhutchinson at cox dot net
@ 2005-03-13 2:07 ` schlie at comcast dot net
2005-03-13 2:44 ` andrewhutchinson at cox dot net
` (8 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: schlie at comcast dot net @ 2005-03-13 2:07 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From schlie at comcast dot net 2005-03-13 02:06 -------
(In reply to comment #20)
with reference to the most recent patch:
- anding with 0xFFFF may turn negatives positive so it seems wrong.
- there's no need limit byte counts to below 0x100 for bytes, as 0xFF is a
count as long is it was originally verifed that the integer value is positive.
And just as a heads up, from when I was fooling a differnt varant, discovered
that (use (match_operand:HI 2 "const_int_operand" "")) apparently
also matches variable operands when compiling avrlibc:
Apparently failing as no code is generated:
../../../../libc/stdlib/realloc.c:154: error: unrecognizable insn:
(insn 235 232 236 31 ../../../../libc/stdlib/realloc.c:151 (parallel [
(set (mem:BLK (reg/v/f:HI 49 [ memp ]) [0 A8])
(mem:BLK (reg/v/f:HI 60 [ ptr ]) [0 A8]))
(use (reg:HI 81 [ <variable>.sz ]))
(use (const_int 1 [0x1]))
]) -1 (insn_list:REG_DEP_TRUE 232 (nil))
(expr_list:REG_DEAD (reg:HI 81 [ <variable>.sz ])
(expr_list:REG_DEAD (reg/v/f:HI 49 [ memp ])
(nil))))
>From the following yet another version of Andy's patch:
(and for the hell of it, enclosed at the end, a version which
attempts to handle variable counts, but couldn't figure out
how to get the conditional insertion of a forward branch
label generated correctly:)
- won't emit code unless (count > 0).
- removes code for non-constant count moves; as it would have
generated incorrect code for move count <= 0.
- allocates a temporary, rather than presuming r0 is safe to use.
(and seems to generate just as good code, as a step to freeing r0)
-- def --
;; move string (like memcpy)
;; implement as RTL loop
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:HI 2 "const_int_operand" ""))
(use (match_operand:HI 3 "const_int_operand" ""))] )]
""
"{
int cnt8, prob;
enum machine_mode mode;
rtx loop_reg;
rtx label = gen_label_rtx ();
/* Copy pointers into new psuedos - they will be changed. */
rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
/* If loop count is constant, try to use QImode counter. */
if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) > 0))
{
/* See if constant fit 8 bits. */
cnt8 = byte_immediate_operand (operands[2], GET_MODE (operands[2]));
mode = cnt8 ? QImode : HImode;
/* Create loop counter register. */
loop_reg = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]),
mode));
/* Create RTL code for move loop, with label at top of loop. */
emit_label (label);
/* Move one byte into scratch and inc pointer. */
rtx tmp_reg = copy_to_mode_reg (QImode, gen_rtx_MEM (QImode, addr1));
emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
/* Move scratch into mem, and inc other pointer. */
emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg);
emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
/* Decrement count. */
emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
/* Compare with zero and jump if not equal. */
emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
label);
/* Set jump probability based on loop count. */
rtx jump = get_last_insn ();
prob = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / INTVAL (operands[2]));
REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
REG_NOTES (jump));
DONE;
}}")
This time attempting to handle variable counts:
;; move string (like memcpy)
;; implement as RTL loop
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:HI 2 "const_int_operand" ""))
(use (match_operand:HI 3 "const_int_operand" ""))] )]
""
"{
enum machine_mode mode = HImode;
int prob = (REG_BR_PROB_BASE * 95) / 100;
rtx test_label = 0; /* Initial no-test value. */
/* Specify default variable loop count initial value. */
rtx loop_cnt = copy_to_mode_reg (mode, operands[2]);
/* Only generate code for variable, or constant counts != 0. */
if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
goto done;
if (GET_CODE (operands[2]) == CONST_INT) /* A constant count. */
{
/* Adjust loop count mode size as a function of const size. */
if (byte_immediate_operand (operands[2], GET_MODE (operands[2])))
{
mode = QImode;
}
/* Adjust jump probability based on known loop count. */
prob = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / INTVAL (operands[2]));
/* Update intermediate loop_cnt value based on its mode size. */
loop_cnt = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]),
mode));
}
else /* A variable count. */
{
#if 0 /* FIXME, should jump to test_label if loop_cnt is a variable. */
/* Specify first jump to test_label to verify loop_cnt != 0. */
test_label = gen_label_rtx ();
emit_jump_insn (test_label);
#endif
}
/* Specify memory operand pointer registers. */
rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
/* Specify RLT loop, beginning with loop_label. */
rtx loop_label = gen_label_rtx ();
emit_label (loop_label);
/* Specify move one byte into scratch and inc pointer. */
rtx tmp_reg = copy_to_mode_reg (QImode, gen_rtx_MEM (QImode, addr1));
emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
/* Specify move scratch into mem, and inc other pointer. */
emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg);
emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
/* Decrement count. */
emit_move_insn (loop_cnt, gen_rtx_PLUS (mode, loop_cnt, constm1_rtx));
#if 0 /* FIXME, should specify initial variable loop_cnt test_label. */
/* Specify test label, conditionally defined if loop_cnt = variable. */
if (test_label) emit_label (test_label); should work as test_label.
#endif
/* Compare with zero and loop if not-equal. */
emit_cmp_and_jump_insns (loop_cnt, const0_rtx, NE, NULL_RTX, mode, 1,
loop_label);
/* Set jump probability based on loop count. */
rtx jump = get_last_insn ();
REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
REG_NOTES (jump));
DONE;
done:
}")
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (18 preceding siblings ...)
2005-03-13 2:07 ` schlie at comcast dot net
@ 2005-03-13 2:44 ` andrewhutchinson at cox dot net
2005-03-13 3:39 ` schlie at comcast dot net
` (7 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: andrewhutchinson at cox dot net @ 2005-03-13 2:44 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From andrewhutchinson at cox dot net 2005-03-13 02:44 -------
Subject: Re: unable to find a register to spill in class
`POINTER_REGS'
This is a define EXPAND. predicates (such as const_int_operand) and
pattern have no effect at all on generated code or matching. This
pattern always emits DONE or FAIL.
That is why you need to test operand in body.
And with oxffff is wrong. As is trying to handle the variable count
case. That is fixing something that is not broke.
So looks like my patch is ok?
schlie at comcast dot net wrote:
>------- Additional Comments From schlie at comcast dot net 2005-03-13 02:06 -------
>(In reply to comment #20)
>
>with reference to the most recent patch:
>- anding with 0xFFFF may turn negatives positive so it seems wrong.
>- there's no need limit byte counts to below 0x100 for bytes, as 0xFF is a
> count as long is it was originally verifed that the integer value is positive.
>
>And just as a heads up, from when I was fooling a differnt varant, discovered
>that (use (match_operand:HI 2 "const_int_operand" "")) apparently
>also matches variable operands when compiling avrlibc:
>
>Apparently failing as no code is generated:
>
>../../../../libc/stdlib/realloc.c:154: error: unrecognizable insn:
>(insn 235 232 236 31 ../../../../libc/stdlib/realloc.c:151 (parallel [
> (set (mem:BLK (reg/v/f:HI 49 [ memp ]) [0 A8])
> (mem:BLK (reg/v/f:HI 60 [ ptr ]) [0 A8]))
> (use (reg:HI 81 [ <variable>.sz ]))
> (use (const_int 1 [0x1]))
> ]) -1 (insn_list:REG_DEP_TRUE 232 (nil))
> (expr_list:REG_DEAD (reg:HI 81 [ <variable>.sz ])
> (expr_list:REG_DEAD (reg/v/f:HI 49 [ memp ])
> (nil))))
>
>>From the following yet another version of Andy's patch:
>
>(and for the hell of it, enclosed at the end, a version which
> attempts to handle variable counts, but couldn't figure out
> how to get the conditional insertion of a forward branch
> label generated correctly:)
>
>- won't emit code unless (count > 0).
>
>- removes code for non-constant count moves; as it would have
> generated incorrect code for move count <= 0.
>
>- allocates a temporary, rather than presuming r0 is safe to use.
> (and seems to generate just as good code, as a step to freeing r0)
>
>-- def --
>
>;; move string (like memcpy)
>;; implement as RTL loop
>
>(define_expand "movmemhi"
> [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
> (match_operand:BLK 1 "memory_operand" ""))
> (use (match_operand:HI 2 "const_int_operand" ""))
> (use (match_operand:HI 3 "const_int_operand" ""))] )]
> ""
> "{
> int cnt8, prob;
> enum machine_mode mode;
>
> rtx loop_reg;
> rtx label = gen_label_rtx ();
>
> /* Copy pointers into new psuedos - they will be changed. */
> rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
> rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
>
> /* If loop count is constant, try to use QImode counter. */
> if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) > 0))
> {
> /* See if constant fit 8 bits. */
> cnt8 = byte_immediate_operand (operands[2], GET_MODE (operands[2]));
> mode = cnt8 ? QImode : HImode;
>
> /* Create loop counter register. */
> loop_reg = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]),
> mode));
>
> /* Create RTL code for move loop, with label at top of loop. */
> emit_label (label);
>
> /* Move one byte into scratch and inc pointer. */
> rtx tmp_reg = copy_to_mode_reg (QImode, gen_rtx_MEM (QImode, addr1));
> emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
>
> /* Move scratch into mem, and inc other pointer. */
> emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg);
> emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
>
> /* Decrement count. */
> emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
>
> /* Compare with zero and jump if not equal. */
> emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
> label);
>
> /* Set jump probability based on loop count. */
> rtx jump = get_last_insn ();
> prob = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / INTVAL (operands[2]));
> REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
> REG_NOTES (jump));
> DONE;
> }}")
>
>This time attempting to handle variable counts:
>
>;; move string (like memcpy)
>;; implement as RTL loop
>
>(define_expand "movmemhi"
> [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
> (match_operand:BLK 1 "memory_operand" ""))
> (use (match_operand:HI 2 "const_int_operand" ""))
> (use (match_operand:HI 3 "const_int_operand" ""))] )]
> ""
> "{
> enum machine_mode mode = HImode;
> int prob = (REG_BR_PROB_BASE * 95) / 100;
> rtx test_label = 0; /* Initial no-test value. */
>
> /* Specify default variable loop count initial value. */
> rtx loop_cnt = copy_to_mode_reg (mode, operands[2]);
>
> /* Only generate code for variable, or constant counts != 0. */
> if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
> goto done;
>
> if (GET_CODE (operands[2]) == CONST_INT) /* A constant count. */
> {
> /* Adjust loop count mode size as a function of const size. */
> if (byte_immediate_operand (operands[2], GET_MODE (operands[2])))
> {
> mode = QImode;
> }
> /* Adjust jump probability based on known loop count. */
> prob = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / INTVAL (operands[2]));
> /* Update intermediate loop_cnt value based on its mode size. */
> loop_cnt = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]),
> mode));
> }
> else /* A variable count. */
> {
>#if 0 /* FIXME, should jump to test_label if loop_cnt is a variable. */
> /* Specify first jump to test_label to verify loop_cnt != 0. */
> test_label = gen_label_rtx ();
> emit_jump_insn (test_label);
>#endif
> }
>
> /* Specify memory operand pointer registers. */
> rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
> rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
>
> /* Specify RLT loop, beginning with loop_label. */
> rtx loop_label = gen_label_rtx ();
> emit_label (loop_label);
>
> /* Specify move one byte into scratch and inc pointer. */
> rtx tmp_reg = copy_to_mode_reg (QImode, gen_rtx_MEM (QImode, addr1));
> emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
>
> /* Specify move scratch into mem, and inc other pointer. */
> emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg);
> emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
>
> /* Decrement count. */
> emit_move_insn (loop_cnt, gen_rtx_PLUS (mode, loop_cnt, constm1_rtx));
>
>#if 0 /* FIXME, should specify initial variable loop_cnt test_label. */
> /* Specify test label, conditionally defined if loop_cnt = variable. */
> if (test_label) emit_label (test_label); should work as test_label.
>#endif
>
> /* Compare with zero and loop if not-equal. */
> emit_cmp_and_jump_insns (loop_cnt, const0_rtx, NE, NULL_RTX, mode, 1,
> loop_label);
>
> /* Set jump probability based on loop count. */
> rtx jump = get_last_insn ();
> REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
> REG_NOTES (jump));
>
> DONE;
> done:
> }")
>
>
>
>
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (19 preceding siblings ...)
2005-03-13 2:44 ` andrewhutchinson at cox dot net
@ 2005-03-13 3:39 ` schlie at comcast dot net
2005-03-13 4:05 ` andrewhutchinson at cox dot net
` (6 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: schlie at comcast dot net @ 2005-03-13 3:39 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From schlie at comcast dot net 2005-03-13 03:39 -------
(In reply to comment #23)
> This is a define EXPAND. predicates (such as const_int_operand) and
> pattern have no effect at all on generated code or matching. This
> pattern always emits DONE or FAIL.
>
> That is why you need to test operand in body.
- thanks, understood.
> And with oxffff is wrong. As is trying to handle the variable count
> case. That is fixing something that is not broke.
>
> So looks like my patch is ok?
- how about in the case of a variable count = 0 ?
(or since only constants are handled, it falls back to letting gcc figure it out?)
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (20 preceding siblings ...)
2005-03-13 3:39 ` schlie at comcast dot net
@ 2005-03-13 4:05 ` andrewhutchinson at cox dot net
2005-03-13 4:18 ` schlie at comcast dot net
` (5 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: andrewhutchinson at cox dot net @ 2005-03-13 4:05 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From andrewhutchinson at cox dot net 2005-03-13 04:05 -------
Subject: Re: unable to find a register to spill in class
`POINTER_REGS'
You answered your own question. GCC handles variable moves just like
anything else. Dealing with range of possible values and size etc and
construct appropriate RTL.
GCC does not need this backend define or expand. It is quite happy
working out moves by itself.
The pattern is *only* defined when the target can do a better job -
i.e. when we have a constant byte count - but not otherwise. I have
found it's a really bad idea to second guess compiler optimisations.
>- how about in the case of a variable count = 0 ?
> (or since only constants are handled, it falls back to letting gcc figure it out?)
>
>
>
>
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (21 preceding siblings ...)
2005-03-13 4:05 ` andrewhutchinson at cox dot net
@ 2005-03-13 4:18 ` schlie at comcast dot net
2005-03-13 10:10 ` cvs-commit at gcc dot gnu dot org
` (4 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: schlie at comcast dot net @ 2005-03-13 4:18 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From schlie at comcast dot net 2005-03-13 04:17 -------
(In reply to comment #25)
> Subject: Re: unable to find a register to spill in class
> `POINTER_REGS'
> ...
> GCC does not need this backend define or expand. It is quite happy
> working out moves by itself.
- thanks again, sound's good.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (22 preceding siblings ...)
2005-03-13 4:18 ` schlie at comcast dot net
@ 2005-03-13 10:10 ` cvs-commit at gcc dot gnu dot org
2005-03-13 10:11 ` marekm at amelek dot gda dot pl
` (3 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: cvs-commit at gcc dot gnu dot org @ 2005-03-13 10:10 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From cvs-commit at gcc dot gnu dot org 2005-03-13 10:10 -------
Subject: Bug 18251
CVSROOT: /cvs/gcc
Module name: gcc
Changes by: marekm@gcc.gnu.org 2005-03-13 10:09:56
Modified files:
gcc : ChangeLog
gcc/config/avr : avr.md
Log message:
PR target/18251
* config/avr/avr.md (movmemhi): Rewrite as RTL loop.
(*movmemqi_insn): Delete.
(*movmemhi): Delete.
Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7811&r2=2.7812
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/avr/avr.md.diff?cvsroot=gcc&r1=1.50&r2=1.51
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (23 preceding siblings ...)
2005-03-13 10:10 ` cvs-commit at gcc dot gnu dot org
@ 2005-03-13 10:11 ` marekm at amelek dot gda dot pl
2005-03-19 15:45 ` cvs-commit at gcc dot gnu dot org
` (2 subsequent siblings)
27 siblings, 0 replies; 39+ messages in thread
From: marekm at amelek dot gda dot pl @ 2005-03-13 10:11 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From marekm at amelek dot gda dot pl 2005-03-13 10:10 -------
Subject: Re: unable to find a register to spill in class `POINTER_REGS'
On Sun, Mar 13, 2005 at 02:44:51AM -0000, andrewhutchinson at cox dot net wrote:
> And with oxffff is wrong. As is trying to handle the variable count
> case. That is fixing something that is not broke.
Does this look OK? Now "movmemhi" will only handle positive constant
counts, and FAIL for the other cases (zero, negative or variable) to
let GCC handle them by itself.
Hopefully this is the final version, committed to mainline - 4.0 and
3.4 will follow soon if there are no problems, please test.
Thanks,
Marek
;; move string (like memcpy)
;; implement as RTL loop
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:HI 2 "const_int_operand" ""))
(use (match_operand:HI 3 "const_int_operand" ""))])]
""
"{
int prob;
HOST_WIDE_INT count;
enum machine_mode mode;
rtx label = gen_label_rtx ();
rtx loop_reg;
rtx jump;
/* Copy pointers into new psuedos - they will be changed. */
rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
/* Create rtx for tmp register - we use this as scratch. */
rtx tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
if (GET_CODE (operands[2]) != CONST_INT)
FAIL;
count = INTVAL (operands[2]);
if (count <= 0)
FAIL;
/* Work out branch probability for latter use. */
prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;
/* See if constant fit 8 bits. */
mode = (count < 0x100) ? QImode : HImode;
/* Create loop counter register. */
loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));
/* Now create RTL code for move loop. */
/* Label at top of loop. */
emit_label (label);
/* Move one byte into scratch and inc pointer. */
emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
/* Move to mem and inc pointer. */
emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
/* Decrement count. */
emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
/* Compare with zero and jump if not equal. */
emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
label);
/* Set jump probability based on loop count. */
jump = get_last_insn ();
REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
GEN_INT (prob),
REG_NOTES (jump));
DONE;
}")
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (24 preceding siblings ...)
2005-03-13 10:11 ` marekm at amelek dot gda dot pl
@ 2005-03-19 15:45 ` cvs-commit at gcc dot gnu dot org
2005-03-19 15:46 ` cvs-commit at gcc dot gnu dot org
2005-04-22 16:10 ` eisvogel at seitics dot de
27 siblings, 0 replies; 39+ messages in thread
From: cvs-commit at gcc dot gnu dot org @ 2005-03-19 15:45 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From cvs-commit at gcc dot gnu dot org 2005-03-19 15:44 -------
Subject: Bug 18251
CVSROOT: /cvs/gcc
Module name: gcc
Branch: gcc-4_0-branch
Changes by: marekm@gcc.gnu.org 2005-03-19 15:44:26
Modified files:
gcc : ChangeLog
gcc/config/avr : avr.md
Log message:
PR target/18251
* config/avr/avr.md (movmemhi): Rewrite as RTL loop.
(*movmemqi_insn): Delete.
(*movmemhi): Delete.
Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=2.7592.2.62&r2=2.7592.2.63
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/avr/avr.md.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.49.8.1&r2=1.49.8.2
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (25 preceding siblings ...)
2005-03-19 15:45 ` cvs-commit at gcc dot gnu dot org
@ 2005-03-19 15:46 ` cvs-commit at gcc dot gnu dot org
2005-04-22 16:10 ` eisvogel at seitics dot de
27 siblings, 0 replies; 39+ messages in thread
From: cvs-commit at gcc dot gnu dot org @ 2005-03-19 15:46 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From cvs-commit at gcc dot gnu dot org 2005-03-19 15:45 -------
Subject: Bug 18251
CVSROOT: /cvs/gcc
Module name: gcc
Branch: gcc-3_4-branch
Changes by: marekm@gcc.gnu.org 2005-03-19 15:45:41
Modified files:
gcc : ChangeLog
gcc/config/avr : avr.md
Log message:
PR target/18251
* config/avr/avr.md (movstrhi): Rewrite as RTL loop.
(*movstrqi_insn): Delete.
(*movstrhi): Delete.
Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.821&r2=2.2326.2.822
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/avr/avr.md.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.42.4.3&r2=1.42.4.4
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Bug target/18251] unable to find a register to spill in class `POINTER_REGS'
2004-10-31 12:51 [Bug target/18251] New: " ralf_corsepius at rtems dot org
` (26 preceding siblings ...)
2005-03-19 15:46 ` cvs-commit at gcc dot gnu dot org
@ 2005-04-22 16:10 ` eisvogel at seitics dot de
27 siblings, 0 replies; 39+ messages in thread
From: eisvogel at seitics dot de @ 2005-04-22 16:10 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From eisvogel at seitics dot de 2005-04-22 16:10 -------
This bug is AFAICT not fully resolved in 4.0 HEAD as of today. The test case
compiles under 3.4.3, though. The code snippet used to be part of an MD5
transform function but I have stripped it down to the point where it is still
valid C code but does not do anything useful any more. In this state removing
any of the remaining lines usually prevents the ICE from occurring, most notably
the LPM macro (taken from avr-libc HEAD).
$ avr-gcc -Os -mmcu=atmega162 -c test.c
test.c: In function 'test':
test.c:46: error: unable to find a register to spill in class 'POINTER_REGS'
test.c:46: error: this is the insn:
(insn 18 115 20 0 (set (reg/v:SI 56 [ a ])
(mem:SI (post_inc:HI (reg/f:HI 22 r22 [orig:59 D.1226 ] [59])) [2 S4
A8])) 14 {*movsi} (insn_list:REG_DEP_TRUE 115 (nil))
(expr_list:REG_INC (reg/f:HI 22 r22 [orig:59 D.1226 ] [59])
(nil)))
test.c:46: internal compiler error: in spill_failure, at reload1.c:1897
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
Compiler version:
$ avr-gcc -v
Using built-in specs.
Target: avr
Configured with: ../configure --target=avr --prefix=/home/eisvogel/avr
--enable-languages=c,c++ --disable-nls
Thread model: single
gcc version 4.1.0 20050422 (experimental)
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251
^ permalink raw reply [flat|nested] 39+ messages in thread