summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/combine.c8
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c17
4 files changed, 27 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8acb3b68335..2691d51d26d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2009-08-11 Adam Nemet <anemet@caviumnetworks.com>
+
+ * combine.c (try_widen_shift_mode): Factor out code to check if an
+ integer constant is a low-order bitmask from here ...
+ * rtlanal.c (low_bitmask_len): ... to here.
+ * rtl.h (low_bitmask_len): Declare.
+
2009-08-11 Uros Bizjak <ubizjak@gmail.com>
PR target/8603
diff --git a/gcc/combine.c b/gcc/combine.c
index 3a2c41205e5..faa7e0dc038 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -9027,13 +9027,9 @@ try_widen_shift_mode (enum rtx_code code, rtx op, int count,
/* We can also widen if the bits brought in will be masked off. This
operation is performed in ORIG_MODE. */
- if (outer_code == AND
- && GET_MODE_BITSIZE (orig_mode) <= HOST_BITS_PER_WIDE_INT)
+ if (outer_code == AND)
{
- int care_bits;
-
- outer_const &= GET_MODE_MASK (orig_mode);
- care_bits = exact_log2 (outer_const + 1);
+ int care_bits = low_bitmask_len (orig_mode, outer_const);
if (care_bits >= 0
&& GET_MODE_BITSIZE (orig_mode) - care_bits >= count)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index d5ae561d3af..cf07348a3cb 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1095,6 +1095,7 @@ extern unsigned HOST_WIDE_INT nonzero_bits (const_rtx, enum machine_mode);
extern unsigned int num_sign_bit_copies (const_rtx, enum machine_mode);
extern bool constant_pool_constant_p (rtx);
extern bool truncated_to_mode (enum machine_mode, const_rtx);
+extern int low_bitmask_len (enum machine_mode, unsigned HOST_WIDE_INT);
/* 1 if RTX is a subreg containing a reg that is already known to be
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 49289b65c37..aebcfa66904 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5032,3 +5032,20 @@ constant_pool_constant_p (rtx x)
x = avoid_constant_pool_reference (x);
return GET_CODE (x) == CONST_DOUBLE;
}
+
+/* If M is a bitmask that selects a field of low-order bits within an item but
+ not the entire word, return the length of the field. Return -1 otherwise.
+ M is used in machine mode MODE. */
+
+int
+low_bitmask_len (enum machine_mode mode, unsigned HOST_WIDE_INT m)
+{
+ if (mode != VOIDmode)
+ {
+ if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
+ return -1;
+ m &= GET_MODE_MASK (mode);
+ }
+
+ return exact_log2 (m + 1);
+}