diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1994-06-16 06:47:10 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1994-06-16 06:47:10 -0400 |
commit | c85663b1a886532c02cabf33da28ca867c177cc0 (patch) | |
tree | ba0d2c4d5235a8231510f2d07dc1561915708caf /gcc/cse.c | |
parent | 88d0b2b86554cd8a5ae64ec08cf62d8dcd95f855 (diff) | |
download | gcc-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.c | 64 |
1 files changed, 51 insertions, 13 deletions
@@ -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; |