re PR target/28623 (ICE in extract_insn, at recog.c:2077 (nrecognizable insn) [alpha])
authorRichard Henderson <rth@redhat.com>
Fri, 20 Apr 2007 19:35:55 +0000 (12:35 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 20 Apr 2007 19:35:55 +0000 (12:35 -0700)
        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
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.md

index d208773855d43b78e036614deb4d10e3e6a33f64..3b86e5ca5dc2d840097c14f3de2328305496c3af 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 9ce85c87008956f717f8a0b9bbb972f91ec833f1..2ba5dfb3a09b4e44b7f3f116d11a91e7b249f3e8 100644 (file)
@@ -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,
index 976111462c14a50b5152baad0c3df52d9c6dad53..be6067eb903a685f324f34d19cbefcf22af5db7f 100644 (file)
@@ -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]);
index 7f323af83ea3bb8598d608ff74d7c4dd8852e048..b86a4777621cccca370f449a580a41a0609d784f 100644 (file)
 
   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;
 
   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);
 ;; 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
 })
 
 (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"
   ""
 {
   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)
        (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"
       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]);
       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]);
     }
   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;
     }
   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;