aboutsummaryrefslogtreecommitdiff
path: root/gcc/cse.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-06-16 06:47:10 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1994-06-16 06:47:10 -0400
commitc85663b1a886532c02cabf33da28ca867c177cc0 (patch)
treeba0d2c4d5235a8231510f2d07dc1561915708caf /gcc/cse.c
parent88d0b2b86554cd8a5ae64ec08cf62d8dcd95f855 (diff)
downloadgcc-c85663b1a886532c02cabf33da28ca867c177cc0.zip
gcc-c85663b1a886532c02cabf33da28ca867c177cc0.tar.gz
gcc-c85663b1a886532c02cabf33da28ca867c177cc0.tar.bz2
(set_nonvarying_address_components): Rework and also handle an AND
used for non-aligned accesses. From-SVN: r7503
Diffstat (limited to 'gcc/cse.c')
-rw-r--r--gcc/cse.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/gcc/cse.c b/gcc/cse.c
index c33cbd0..a9dfa4d 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2240,7 +2240,7 @@ set_nonvarying_address_components (addr, size, pbase, pstart, pend)
HOST_WIDE_INT *pstart, *pend;
{
rtx base;
- int start, end;
+ HOST_WIDE_INT start, end;
base = addr;
start = 0;
@@ -2267,20 +2267,58 @@ set_nonvarying_address_components (addr, size, pbase, pstart, pend)
base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
}
- /* By definition, operand1 of a LO_SUM is the associated constant
- address. Use the associated constant address as the base instead. */
- if (GET_CODE (base) == LO_SUM)
- base = XEXP (base, 1);
-
- /* Strip off CONST. */
- if (GET_CODE (base) == CONST)
- base = XEXP (base, 0);
+ /* Handle everything that we can find inside an address that has been
+ viewed as constant. */
- if (GET_CODE (base) == PLUS
- && GET_CODE (XEXP (base, 1)) == CONST_INT)
+ while (1)
{
- start += INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
+ /* If no part of this switch does a "continue", the code outside
+ will exit this loop. */
+
+ switch (GET_CODE (base))
+ {
+ case LO_SUM:
+ /* By definition, operand1 of a LO_SUM is the associated constant
+ address. Use the associated constant address as the base
+ instead. */
+ base = XEXP (base, 1);
+ continue;
+
+ case CONST:
+ /* Strip off CONST. */
+ base = XEXP (base, 0);
+ continue;
+
+ case PLUS:
+ if (GET_CODE (XEXP (base, 1)) == CONST_INT)
+ {
+ start += INTVAL (XEXP (base, 1));
+ base = XEXP (base, 0);
+ continue;
+ }
+ break;
+
+ case AND:
+ /* Handle the case of an AND which is the negative of a power of
+ two. This is used to represent unaligned memory operations. */
+ if (GET_CODE (XEXP (base, 1)) == CONST_INT
+ && exact_log2 (- INTVAL (XEXP (base, 1))) > 0)
+ {
+ set_nonvarying_address_components (XEXP (base, 0), size,
+ pbase, pstart, pend);
+
+ /* Assume the worst misalignment. START is affected, but not
+ END, so compensate but adjusting SIZE. Don't lose any
+ constant we already had. */
+
+ size = *pend - *pstart - INTVAL (XEXP (base, 1)) - 1;
+ start += *pstart - INTVAL (XEXP (base, 1)) - 1;
+ base = *pbase;
+ }
+ break;
+ }
+
+ break;
}
end = start + size;