diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1995-11-26 12:08:18 -0500 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1995-11-26 12:08:18 -0500 |
commit | 57cfde96bb13ce457494b8649dea2d44bbaa7f63 (patch) | |
tree | bd8b0ac31514a9dad67d415967bc108b11fc70e2 | |
parent | 63a014a0832cc9c7b630ad105a2bad5ea2c4d660 (diff) | |
download | gcc-57cfde96bb13ce457494b8649dea2d44bbaa7f63.zip gcc-57cfde96bb13ce457494b8649dea2d44bbaa7f63.tar.gz gcc-57cfde96bb13ce457494b8649dea2d44bbaa7f63.tar.bz2 |
(alpha_emit_set_const): Don't output SImode sequences that rely on invisible overflow.
(alpha_emit_set_const): Don't output SImode sequences that rely on
invisible overflow. Sign extend new when SImode. Don't recur if new
== c. Don't allow shift outside mode. Make logical right shift be
unsigned.
From-SVN: r10589
-rw-r--r-- | gcc/config/alpha/alpha.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 12ffc08..d460e8b 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -713,7 +713,12 @@ alpha_emit_set_const (target, mode, c, n) if (c == low || (low == 0 && extra == 0)) return copy_to_suggested_reg (GEN_INT (c), target, mode); - else if (n >= 2 + (extra != 0)) + else if (n >= 2 + (extra != 0) + /* We can't do this when SImode if HIGH required adjustment. + This is because the code relies on an implicit overflow + which is invisible to the RTL. We can thus get incorrect + code if the two ldah instructions are combined. */ + && ! (mode == SImode && extra != 0)) { temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode); @@ -744,7 +749,14 @@ alpha_emit_set_const (target, mode, c, n) if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0) new |= (HOST_WIDE_INT) 0xff << i; - if ((temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0) + /* We are only called for SImode and DImode. If this is SImode, ensure that + we are sign extended to a full word. */ + + if (mode == SImode) + new = (new & 0xffffffff) - 2 * (new & 0x80000000); + + if (new != c + && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0) return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new), target, 0, OPTAB_WIDEN); #endif @@ -781,9 +793,11 @@ alpha_emit_set_const (target, mode, c, n) target, 0, OPTAB_WIDEN); /* Now try high-order zero bits. Here we try the shifted-in bits as - all zero and all ones. */ + all zero and all ones. Be careful to avoid shifting outside the + mode and to avoid shifting outside the host wide int size. */ - if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (c) - 1) > 0) + if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) + - floor_log2 (c) - 1)) > 0) for (; bits > 0; bits--) if ((temp = alpha_emit_set_const (subtarget, mode, c << bits, i)) != 0 @@ -793,12 +807,14 @@ alpha_emit_set_const (target, mode, c, n) i))) != 0)) return expand_binop (mode, lshr_optab, temp, GEN_INT (bits), - target, 0, OPTAB_WIDEN); + target, 1, OPTAB_WIDEN); /* Now try high-order 1 bits. We get that with a sign-extension. - But one bit isn't enough here. */ + But one bit isn't enough here. Be careful to avoid shifting outside + the mode and to avoid shifting outside the host wide int size. */ - if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (~ c) - 2) > 0) + if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) + - floor_log2 (~ c) - 2)) > 0) for (; bits > 0; bits--) if ((temp = alpha_emit_set_const (subtarget, mode, c << bits, i)) != 0 |