summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-09 21:55:08 +0000
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-09 21:55:08 +0000
commitb616908520cb4834992d8d375de58c6ad32d21ba (patch)
tree7297e5bc9c199d8424196e39c140d44184b116ee
parent5381eb98a264ed2e15673ceba37806390ce85a8f (diff)
downloadgcc-b616908520cb4834992d8d375de58c6ad32d21ba.tar.gz
* arm.c (arm_gen_constant): Add new heuristic for generating
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/arm/arm.c31
2 files changed, 24 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ae7d68e4672..e6fd1afebdc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1743980b1cf..aaa9daaeaec 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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;
}