aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2007-04-20 12:35:55 -0700
committerRichard Henderson <rth@gcc.gnu.org>2007-04-20 12:35:55 -0700
commit60e9352519ea5b351863a7b24dc19cafcff567ff (patch)
treea99c28e30a1ffc590503139ffa75a83bdb771164
parentf326fd7a0323d1a17756dc64af3e7d91ef366928 (diff)
downloadgcc-60e9352519ea5b351863a7b24dc19cafcff567ff.zip
gcc-60e9352519ea5b351863a7b24dc19cafcff567ff.tar.gz
gcc-60e9352519ea5b351863a7b24dc19cafcff567ff.tar.bz2
re PR target/28623 (ICE in extract_insn, at recog.c:2077 (nrecognizable insn) [alpha])
PR target/28623 * config/alpha/alpha.c (get_unaligned_address): Remove extra_offset argument; update all callers. (get_unaligned_offset): New. * config/alpha/alpha.md (extendqidi2, extendhidi2): Don't use get_unaligned_address, just pass on the address directly. (unaligned_extendqidi): Use gen_lowpart instead of open-coding the subreg in the helper patterns. (unaligned_extendqidi_le): Use get_unaligned_offset. (unaligned_extendqidi_be, unaligned_extendhidi_le): Likewise. (unaligned_extendhidi_be): Likewise. (unaligned_extendhidi): Tidy. * config/alpha/alpha-protos.h: Update. From-SVN: r124002
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/alpha/alpha-protos.h3
-rw-r--r--gcc/config/alpha/alpha.c24
-rw-r--r--gcc/config/alpha/alpha.md83
4 files changed, 70 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d208773..3b86e5c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,21 @@
2007-04-20 Richard Henderson <rth@redhat.com>
+ PR target/28623
+ * config/alpha/alpha.c (get_unaligned_address): Remove extra_offset
+ argument; update all callers.
+ (get_unaligned_offset): New.
+ * config/alpha/alpha.md (extendqidi2, extendhidi2): Don't use
+ get_unaligned_address, just pass on the address directly.
+ (unaligned_extendqidi): Use gen_lowpart instead of open-coding
+ the subreg in the helper patterns.
+ (unaligned_extendqidi_le): Use get_unaligned_offset.
+ (unaligned_extendqidi_be, unaligned_extendhidi_le): Likewise.
+ (unaligned_extendhidi_be): Likewise.
+ (unaligned_extendhidi): Tidy.
+ * config/alpha/alpha-protos.h: Update.
+
+2007-04-20 Richard Henderson <rth@redhat.com>
+
* config/alpha/alpha.h (CPP_SPEC, CPP_SUBTARGET_SPEC): Remove.
(EXTRA_SPECS, SUBTARGET_EXTRA_SPECS): Remove.
* config/alpha/linux.h (CPP_SPEC): Undef before redefine.
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 9ce85c8..2ba5dfb 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -47,7 +47,8 @@ extern rtx alpha_legitimize_reload_address (rtx, enum machine_mode,
extern rtx split_small_symbolic_operand (rtx);
extern void get_aligned_mem (rtx, rtx *, rtx *);
-extern rtx get_unaligned_address (rtx, int);
+extern rtx get_unaligned_address (rtx);
+extern rtx get_unaligned_offset (rtx, HOST_WIDE_INT);
extern enum reg_class alpha_preferred_reload_class (rtx, enum reg_class);
extern enum reg_class alpha_secondary_reload_class (enum reg_class,
enum machine_mode, rtx,
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 9761114..be6067e 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1461,7 +1461,7 @@ get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
Add EXTRA_OFFSET to the address we return. */
rtx
-get_unaligned_address (rtx ref, int extra_offset)
+get_unaligned_address (rtx ref)
{
rtx base;
HOST_WIDE_INT offset = 0;
@@ -1481,7 +1481,23 @@ get_unaligned_address (rtx ref, int extra_offset)
if (GET_CODE (base) == PLUS)
offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
- return plus_constant (base, offset + extra_offset);
+ return plus_constant (base, offset);
+}
+
+/* Compute a value X, such that X & 7 == (ADDR + OFS) & 7.
+ X is always returned in a register. */
+
+rtx
+get_unaligned_offset (rtx addr, HOST_WIDE_INT ofs)
+{
+ if (GET_CODE (addr) == PLUS)
+ {
+ ofs += INTVAL (XEXP (addr, 1));
+ addr = XEXP (addr, 0);
+ }
+
+ return expand_simple_binop (Pmode, PLUS, addr, GEN_INT (ofs & 7),
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
}
/* On the Alpha, all (non-symbolic) constants except zero go into
@@ -2230,7 +2246,7 @@ alpha_expand_mov_nobwx (enum machine_mode mode, rtx *operands)
seq = ((mode == QImode
? gen_unaligned_loadqi
: gen_unaligned_loadhi)
- (subtarget, get_unaligned_address (operands[1], 0),
+ (subtarget, get_unaligned_address (operands[1]),
temp1, temp2));
alpha_set_memflags (seq, operands[1]);
emit_insn (seq);
@@ -2269,7 +2285,7 @@ alpha_expand_mov_nobwx (enum machine_mode mode, rtx *operands)
rtx seq = ((mode == QImode
? gen_unaligned_storeqi
: gen_unaligned_storehi)
- (get_unaligned_address (operands[0], 0),
+ (get_unaligned_address (operands[0]),
operands[1], temp1, temp2, temp3));
alpha_set_memflags (seq, operands[0]);
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 7f323af..b86a477 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -1664,10 +1664,7 @@
if (unaligned_memory_operand (operands[1], QImode))
{
- rtx seq
- = gen_unaligned_extendqidi (operands[0],
- get_unaligned_address (operands[1], 1));
-
+ rtx seq = gen_unaligned_extendqidi (operands[0], XEXP (operands[1], 0));
alpha_set_memflags (seq, operands[1]);
emit_insn (seq);
DONE;
@@ -1727,9 +1724,7 @@
if (unaligned_memory_operand (operands[1], HImode))
{
- rtx seq
- = gen_unaligned_extendhidi (operands[0],
- get_unaligned_address (operands[1], 2));
+ rtx seq = gen_unaligned_extendhidi (operands[0], XEXP (operands[1], 0));
alpha_set_memflags (seq, operands[1]);
emit_insn (seq);
@@ -1744,12 +1739,13 @@
;; as a pattern saves one instruction. The code is similar to that for
;; the unaligned loads (see below).
;;
-;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result.
+;; Operand 1 is the address, operand 0 is the result.
(define_expand "unaligned_extendqidi"
[(use (match_operand:QI 0 "register_operand" ""))
(use (match_operand:DI 1 "address_operand" ""))]
""
{
+ operands[0] = gen_lowpart (DImode, operands[0]);
if (WORDS_BIG_ENDIAN)
emit_insn (gen_unaligned_extendqidi_be (operands[0], operands[1]));
else
@@ -1758,48 +1754,40 @@
})
(define_expand "unaligned_extendqidi_le"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3)
- (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1))
- (const_int -8))))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
(ashift:DI (match_dup 3)
(minus:DI (const_int 64)
(ashift:DI
(and:DI (match_dup 2) (const_int 7))
(const_int 3)))))
- (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+ (set (match_operand:DI 0 "register_operand" "")
(ashiftrt:DI (match_dup 4) (const_int 56)))]
"! WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], 1);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendqidi_be"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3) (plus:DI (match_dup 2) (const_int -1)))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
- (mem:DI (and:DI (match_dup 3)
- (const_int -8))))
- (set (match_dup 5) (plus:DI (match_dup 2) (const_int -2)))
- (set (match_dup 6)
- (ashift:DI (match_dup 4)
+ (ashift:DI (match_dup 3)
(ashift:DI
(and:DI
- (plus:DI (match_dup 5) (const_int 1))
+ (plus:DI (match_dup 2) (const_int 1))
(const_int 7))
(const_int 3))))
- (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
- (ashiftrt:DI (match_dup 6) (const_int 56)))]
+ (set (match_operand:DI 0 "register_operand" "")
+ (ashiftrt:DI (match_dup 4) (const_int 56)))]
"WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], -1);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
- operands[6] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendhidi"
@@ -1808,17 +1796,16 @@
""
{
operands[0] = gen_lowpart (DImode, operands[0]);
- emit_insn ((WORDS_BIG_ENDIAN
- ? gen_unaligned_extendhidi_be
- : gen_unaligned_extendhidi_le) (operands[0], operands[1]));
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_extendhidi_be (operands[0], operands[1]));
+ else
+ emit_insn (gen_unaligned_extendhidi_le (operands[0], operands[1]));
DONE;
})
(define_expand "unaligned_extendhidi_le"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3)
- (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2))
- (const_int -8))))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
(ashift:DI (match_dup 3)
(minus:DI (const_int 64)
@@ -1829,34 +1816,28 @@
(ashiftrt:DI (match_dup 4) (const_int 48)))]
"! WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], 2);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendhidi_be"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3) (plus:DI (match_dup 2) (const_int -2)))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
- (mem:DI (and:DI (match_dup 3)
- (const_int -8))))
- (set (match_dup 5) (plus:DI (match_dup 2) (const_int -3)))
- (set (match_dup 6)
- (ashift:DI (match_dup 4)
+ (ashift:DI (match_dup 3)
(ashift:DI
(and:DI
- (plus:DI (match_dup 5) (const_int 1))
+ (plus:DI (match_dup 2) (const_int 1))
(const_int 7))
(const_int 3))))
(set (match_operand:DI 0 "register_operand" "")
- (ashiftrt:DI (match_dup 6) (const_int 48)))]
+ (ashiftrt:DI (match_dup 4) (const_int 48)))]
"WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], -1);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
- operands[6] = gen_reg_rtx (DImode);
})
(define_insn "*extxl_const"
@@ -6133,7 +6114,7 @@
else
scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- addr = get_unaligned_address (operands[1], 0);
+ addr = get_unaligned_address (operands[1]);
operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
seq = gen_unaligned_loadqi (operands[0], addr, scratch, operands[0]);
alpha_set_memflags (seq, operands[1]);
@@ -6167,7 +6148,7 @@
else
scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- addr = get_unaligned_address (operands[1], 0);
+ addr = get_unaligned_address (operands[1]);
operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
seq = gen_unaligned_loadhi (operands[0], addr, scratch, operands[0]);
alpha_set_memflags (seq, operands[1]);
@@ -6191,7 +6172,7 @@
}
else
{
- rtx addr = get_unaligned_address (operands[0], 0);
+ rtx addr = get_unaligned_address (operands[0]);
rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2]));
rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
rtx scratch3 = scratch1;
@@ -6223,7 +6204,7 @@
}
else
{
- rtx addr = get_unaligned_address (operands[0], 0);
+ rtx addr = get_unaligned_address (operands[0]);
rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2]));
rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
rtx scratch3 = scratch1;