public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] More thorough checking in reg_fits_class_p
@ 2012-04-26 13:21 Jim MacArthur
  2012-04-30 13:45 ` Richard Earnshaw
  0 siblings, 1 reply; 18+ messages in thread
From: Jim MacArthur @ 2012-04-26 13:21 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 899 bytes --]

The current code in reg_fits_class_p appears to be incorrect; since 
offset may be negative, it's necessary to check both ends of the range 
otherwise an array overrun or underrun may occur when calling 
in_hard_reg_set_p. in_hard_reg_set_p should also be checked for each 
register in the range of regno .. regno+offset.

A negative offset can occur on a big-endian target. For example, on 
AArch64, subreg_regno_offset (0, DImode, 0, TImode) returns -1.

We discovered this problem while developing unrelated code for 
big-endian support in the AArch64 back end.

I've tested this with an x86 bootstrap which shows no errors, and with 
our own AArch64 back end.

Ok for trunk?

gcc/Changelog entry:

2012-04-26 Jim MacArthur<jim.macarthur@arm.com>
      * recog.c (reg_fits_class_p): Check every register between regno and
        regno+offset is in the hard register set.


[-- Attachment #2: reg-fits-class-9 --]
[-- Type: text/plain, Size: 1128 bytes --]

diff --git a/gcc/recog.c b/gcc/recog.c
index 8fb96a0..825bfb1 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2759,14 +2759,28 @@ bool
 reg_fits_class_p (const_rtx operand, reg_class_t cl, int offset,
 		  enum machine_mode mode)
 {
-  int regno = REGNO (operand);
+  unsigned int regno = REGNO (operand);
 
   if (cl == NO_REGS)
     return false;
 
-  return (HARD_REGISTER_NUM_P (regno)
-	  && in_hard_reg_set_p (reg_class_contents[(int) cl],
-				mode, regno + offset));
+  /* We should not assume all registers in the range regno to regno + offset are
+     valid just because each end of the range is.  */
+  if (HARD_REGISTER_NUM_P (regno) && HARD_REGISTER_NUM_P (regno + offset))
+    {
+      unsigned int i;
+
+      unsigned int start = MIN (regno, regno + offset);
+      unsigned int end = MAX (regno, regno + offset);
+      for (i = start; i <= end; i++)
+	{
+	  if (!in_hard_reg_set_p (reg_class_contents[(int) cl],
+				  mode, i))
+	    return false;
+	}
+      return true;
+    }
+  return false;
 }
 \f
 /* Split single instruction.  Helper function for split_all_insns and

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2012-05-24 11:35 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-26 13:21 [patch] More thorough checking in reg_fits_class_p Jim MacArthur
2012-04-30 13:45 ` Richard Earnshaw
2012-04-30 14:08   ` Richard Sandiford
2012-04-30 14:13     ` Richard Earnshaw
2012-04-30 14:39       ` Richard Sandiford
2012-04-30 14:57         ` Richard Earnshaw
2012-04-30 15:19           ` Richard Sandiford
2012-05-02 12:04             ` Jim MacArthur
2012-05-02 13:00               ` Richard Sandiford
2012-05-02 13:52                 ` Richard Earnshaw
2012-05-02 13:56                   ` Richard Sandiford
2012-05-17 13:24                     ` Jim MacArthur
2012-05-18  9:11                       ` Richard Sandiford
2012-05-21 14:48                       ` Richard Earnshaw
2012-05-24 11:35                         ` Marcus Shawcroft
2012-04-30 14:32     ` Richard Earnshaw
2012-04-30 15:37       ` Georg-Johann Lay
2012-04-30 15:45         ` Richard Earnshaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).