From 60e9352519ea5b351863a7b24dc19cafcff567ff Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 20 Apr 2007 12:35:55 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 16 +++++++ gcc/config/alpha/alpha-protos.h | 3 +- gcc/config/alpha/alpha.c | 24 ++++++++-- gcc/config/alpha/alpha.md | 83 +++++++++++++-------------------- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d208773855d..3b86e5ca5dc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2007-04-20 Richard Henderson + + 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 * config/alpha/alpha.h (CPP_SPEC, CPP_SUBTARGET_SPEC): Remove. diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 9ce85c87008..2ba5dfb3a09 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 976111462c1..be6067eb903 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 7f323af83ea..b86a4777621 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;