* arm.c (arm_gen_constant): Add new heuristic for generating
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 May 2005 21:55:08 +0000 (21:55 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 May 2005 21:55:08 +0000 (21:55 +0000)
constant integers that can be expressed as the difference of two
valid immediates.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99472 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm.c

index ae7d68e..e6fd1af 100644 (file)
@@ -1,3 +1,9 @@
+2005-05-09  Richard Earnshaw  <richard.earnshaw@arm.com>
+
+       * arm.c (arm_gen_constant): Add new heuristic for generating
+       constant integers that can be expressed as the difference of two
+       valid immediates.
+
 2005-05-09  Roger Sayle  <roger@eyesopen.com>
 
        * c-tree.h (parser_build_unary_op): New prototype.
index 1743980..aaa9daa 100644 (file)
@@ -1531,8 +1531,8 @@ use_return_insn (int iscond, rtx sibling)
 int
 const_ok_for_arm (HOST_WIDE_INT i)
 {
-  unsigned HOST_WIDE_INT mask = ~(unsigned HOST_WIDE_INT)0xFF;
-
+  int lowbit;
+  
   /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
      be all zero, or all one.  */
   if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
@@ -1541,19 +1541,24 @@ const_ok_for_arm (HOST_WIDE_INT i)
              & ~(unsigned HOST_WIDE_INT) 0xffffffff)))
     return FALSE;
 
-  /* Fast return for 0 and powers of 2 */
-  if ((i & (i - 1)) == 0)
+  i &= (unsigned HOST_WIDE_INT) 0xffffffff;
+  
+  /* Fast return for 0 and small values.  We must do this for zero, since
+     the code below can't handle that one case.  */
+  if ((i & ~(unsigned HOST_WIDE_INT) 0xff) == 0)
     return TRUE;
 
-  do
-    {
-      if ((i & mask & (unsigned HOST_WIDE_INT) 0xffffffff) == 0)
-        return TRUE;
-      mask =
-         (mask << 2) | ((mask & (unsigned HOST_WIDE_INT) 0xffffffff)
-                         >> (32 - 2)) | ~(unsigned HOST_WIDE_INT) 0xffffffff;
-    }
-  while (mask != ~(unsigned HOST_WIDE_INT) 0xFF);
+  /* Get the number of trailing zeros, rounded down to the nearest even
+     number.  */
+  lowbit = (ffs ((int) i) - 1) & ~1;
+
+  if ((i & ~(((unsigned HOST_WIDE_INT) 0xff) << lowbit)) == 0)
+    return TRUE;
+  else if (lowbit <= 4
+          && ((i & ~0xc000003f) == 0
+              || (i & ~0xf000000f) == 0
+              || (i & ~0xfc000003) == 0))
+    return TRUE;
 
   return FALSE;
 }