public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [RFC][PATCH] Support multiple variants of memory addresses
@ 2002-08-14  3:15 Ulrich Weigand
  0 siblings, 0 replies; 3+ messages in thread
From: Ulrich Weigand @ 2002-08-14  3:15 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Hartmut Penner


Richard Henderson wrote:
>Looks ok to me.

Great!  I've now committed the patch, together with a s390 backend patch
that starts making use of the new features.  At this point, the use is
rather minimal; mostly the ugly (and strictly speaking, incorrect) 'Qo'
constraint combinations we had to use can now be replaced by just 'Q'.

Backend patches making more extensive use of EXTRA_MEMORY_CONSTRAINT
and EXTRA_ADDRESS_CONSTRAINT will follow.

For reference, I've appended the complete patch I've committed, including
the parts I had already posted.  With this patch applied, I've successfully
completed bootstrap and regression tests (and glibc build / test) on both
s390-ibm-linux and s390x-ibm-linux.


ChangeLog:

      * reload.c (find_reloads): Handle constraint letters marked by
      EXTRA_ADDRESS_CONSTRAINT and EXTRA_MEMORY_CONSTRAINT.
      (alternative_allows_memconst): Likewise.
      * reload1.c (maybe_fix_stack_asms): Likewise.
      * recog.c (asm_operand_ok, preprocess_constraints,
      constrain_operands): Likewise.
      * regclass.c (record_operand_costs, record_reg_classes): Likewise.
      * local-alloc.c (block_alloc, requires_inout): Likewise.
      * stmt.c (parse_output_constraint, parse_input_constraint): Likewise.

      * defaults.h (EXTRA_MEMORY_CONSTRAINT): Provide a default.
      (EXTRA_ADDRESS_CONSTRAINT): Likewise.
      * doc/tm.texi: Document these two new target macros.

      * config/s390/s390.c (s390_expand_plus_operand): Accept already
      valid operands.
      (q_constraint): New function.
      config/s390/s390-protos.h (q_constraint): Declare it.
      config/s390/s390.h (EXTRA_CONSTRAINT): Use it.
      (EXTRA_MEMORY_CONSTRAINT): New macro.

      * config/s390/s390.md: Throughout the machine description,
      replace all instances of the constraint combinations 'Qo'
      or 'oQ' with simply 'Q'.

Index: gcc/defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.87
diff -c -p -r1.87 defaults.h
*** gcc/defaults.h      31 Jul 2002 02:10:04 -0000    1.87
--- gcc/defaults.h      14 Aug 2002 09:46:02 -0000
*************** You Lose!  You must define PREFERRED_DEB
*** 590,593 ****
--- 590,605 ----
  #define DEFAULT_USE_CXA_ATEXIT 0
  #endif

+ /* Determine whether extra constraint letter should be handled
+    via address reload (like 'o').  */
+ #ifndef EXTRA_MEMORY_CONSTRAINT
+ #define EXTRA_MEMORY_CONSTRAINT(C) 0
+ #endif
+
+ /* Determine whether extra constraint letter should be handled
+    as an address (like 'p').  */
+ #ifndef EXTRA_ADDRESS_CONSTRAINT
+ #define EXTRA_ADDRESS_CONSTRAINT(C) 0
+ #endif
+
  #endif  /* ! GCC_DEFAULTS_H */
Index: gcc/local-alloc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/local-alloc.c,v
retrieving revision 1.109
diff -c -p -r1.109 local-alloc.c
*** gcc/local-alloc.c   30 May 2002 20:55:09 -0000    1.109
--- gcc/local-alloc.c   14 Aug 2002 09:46:04 -0000
*************** block_alloc (b)
*** 1342,1348 ****
              /* If the operand is an address, find a register in it.
                 There may be more than one register, but we only try one
                 of them.  */
!             if (recog_data.constraints[i][0] == 'p')
                while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
                  r1 = XEXP (r1, 0);

--- 1342,1349 ----
              /* If the operand is an address, find a register in it.
                 There may be more than one register, but we only try one
                 of them.  */
!             if (recog_data.constraints[i][0] == 'p'
!                 || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
                while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
                  r1 = XEXP (r1, 0);

*************** requires_inout (p)
*** 2472,2478 ****
      break;

        default:
!     if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
        break;
      /* FALLTHRU */
        case 'p':
--- 2473,2480 ----
      break;

        default:
!     if (REG_CLASS_FROM_LETTER (c) == NO_REGS
!         && !EXTRA_ADDRESS_CONSTRAINT (c))
        break;
      /* FALLTHRU */
        case 'p':
Index: gcc/recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.162
diff -c -p -r1.162 recog.c
*** gcc/recog.c   23 Jul 2002 20:50:59 -0000    1.162
--- gcc/recog.c   14 Aug 2002 09:46:06 -0000
*************** asm_operand_ok (op, constraint)
*** 1848,1853 ****
--- 1848,1865 ----
  #ifdef EXTRA_CONSTRAINT
        if (EXTRA_CONSTRAINT (op, c))
          return 1;
+       if (EXTRA_MEMORY_CONSTRAINT (c))
+         {
+           /* Every memory operand can be reloaded to fit.  */
+           if (memory_operand (op, VOIDmode))
+             return 1;
+         }
+       if (EXTRA_ADDRESS_CONSTRAINT (c))
+         {
+           /* Every address operand can be reloaded to fit.  */
+           if (address_operand (op, VOIDmode))
+             return 1;
+         }
  #endif
        break;
      }
*************** preprocess_constraints ()
*** 2287,2292 ****
--- 2299,2317 ----
              break;

            default:
+             if (EXTRA_MEMORY_CONSTRAINT (c))
+               {
+                 op_alt[j].memory_ok = 1;
+                 break;
+               }
+             if (EXTRA_ADDRESS_CONSTRAINT (c))
+               {
+                 op_alt[j].is_address = 1;
+                 op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
+                   [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                 break;
+               }
+
              op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
              break;
            }
*************** constrain_operands (strict)
*** 2600,2605 ****
--- 2625,2652 ----
  #ifdef EXTRA_CONSTRAINT
              else if (EXTRA_CONSTRAINT (op, c))
                win = 1;
+
+             if (EXTRA_MEMORY_CONSTRAINT (c))
+               {
+                 /* Every memory operand can be reloaded to fit,
+                  so copy the condition from the 'm' case.  */
+                 if (GET_CODE (op) == MEM
+                     /* Before reload, accept what reload can turn into mem.  */
+                     || (strict < 0 && CONSTANT_P (op))
+                     /* During reload, accept a pseudo  */
+                     || (reload_in_progress && GET_CODE (op) == REG
+                       && REGNO (op) >= FIRST_PSEUDO_REGISTER))
+                 win = 1;
+               }
+             if (EXTRA_ADDRESS_CONSTRAINT (c))
+               {
+                 /* Every address operand can be reloaded to fit,
+                  so copy the condition from the 'p' case.  */
+                 if (strict <= 0
+                     || (strict_memory_address_p (recog_data.operand_mode[opno],
+                                          op)))
+                   win = 1;
+               }
  #endif
              break;
            }
Index: gcc/regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.154
diff -c -p -r1.154 regclass.c
*** gcc/regclass.c      23 Jul 2002 20:50:59 -0000    1.154
--- gcc/regclass.c      14 Aug 2002 09:46:11 -0000
*************** record_operand_costs (insn, op_costs, re
*** 1007,1013 ****
        if (GET_CODE (recog_data.operand[i]) == MEM)
      record_address_regs (XEXP (recog_data.operand[i], 0),
                       MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
!       else if (constraints[i][0] == 'p')
      record_address_regs (recog_data.operand[i],
                       MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
      }
--- 1007,1014 ----
        if (GET_CODE (recog_data.operand[i]) == MEM)
      record_address_regs (XEXP (recog_data.operand[i], 0),
                       MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
!       else if (constraints[i][0] == 'p'
!            || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
      record_address_regs (recog_data.operand[i],
                       MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
      }
*************** record_reg_classes (n_alts, n_ops, ops,
*** 1709,1714 ****
--- 1710,1736 ----
  #ifdef EXTRA_CONSTRAINT
            else if (EXTRA_CONSTRAINT (op, c))
              win = 1;
+
+           if (EXTRA_MEMORY_CONSTRAINT (c))
+             {
+               /* Every MEM can be reloaded to fit.  */
+               allows_mem[i] = 1;
+               if (GET_CODE (op) == MEM)
+                 win = 1;
+             }
+           if (EXTRA_ADDRESS_CONSTRAINT (op))
+             {
+               /* Every address can be reloaded to fit.  */
+               allows_addr = 1;
+               if (address_operand (op, GET_MODE (op)))
+                 win = 1;
+               /* We know this operand is an address, so we want it to be
+                  allocated to a register that can be the base of an
+                  address, ie BASE_REG_CLASS.  */
+               classes[i]
+                 = reg_class_subunion[(int) classes[i]]
+                   [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+             }
  #endif
            break;
            }
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.187
diff -c -p -r1.187 reload.c
*** gcc/reload.c  23 Jul 2002 20:51:00 -0000    1.187
--- gcc/reload.c  14 Aug 2002 09:46:17 -0000
*************** find_reloads (insn, replace, ind_levels,
*** 2641,2647 ****
        if (*constraints[i] == 0)
      /* Ignore things like match_operator operands.  */
      ;
!       else if (constraints[i][0] == 'p')
      {
        find_reloads_address (VOIDmode, (rtx*) 0,
                        recog_data.operand[i],
--- 2641,2648 ----
        if (*constraints[i] == 0)
      /* Ignore things like match_operator operands.  */
      ;
!       else if (constraints[i][0] == 'p'
!            || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
      {
        find_reloads_address (VOIDmode, (rtx*) 0,
                        recog_data.operand[i],
*************** find_reloads (insn, replace, ind_levels,
*** 3222,3227 ****
--- 3223,3271 ----
            if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
              {
  #ifdef EXTRA_CONSTRAINT
+               if (EXTRA_MEMORY_CONSTRAINT (c))
+                 {
+                 if (force_reload)
+                   break;
+                   if (EXTRA_CONSTRAINT (operand, c))
+                     win = 1;
+                 /* If the address was already reloaded,
+                    we win as well.  */
+                 if (GET_CODE (operand) == MEM && address_reloaded[i])
+                   win = 1;
+                 /* Likewise if the address will be reloaded because
+                    reg_equiv_address is nonzero.  For reg_equiv_mem
+                    we have to check.  */
+                   if (GET_CODE (operand) == REG
+                     && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+                     && reg_renumber[REGNO (operand)] < 0
+                     && ((reg_equiv_mem[REGNO (operand)] != 0
+                          && EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
+                         || (reg_equiv_address[REGNO (operand)] != 0)))
+                   win = 1;
+
+                 /* If we didn't already win, we can reload
+                    constants via force_const_mem, and other
+                    MEMs by reloading the address like for 'o'.  */
+                 if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
+                     || GET_CODE (operand) == MEM)
+                   badop = 0;
+                 constmemok = 1;
+                 offmemok = 1;
+                 break;
+                 }
+               if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 {
+                   if (EXTRA_CONSTRAINT (operand, c))
+                     win = 1;
+
+                 /* If we didn't already win, we can reload
+                    the address into a base register.  */
+                 this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+                 badop = 0;
+                 break;
+                 }
+
                if (EXTRA_CONSTRAINT (operand, c))
                  win = 1;
  #endif
*************** alternative_allows_memconst (constraint,
*** 4291,4297 ****
    /* Scan the requested alternative for 'm' or 'o'.
       If one of them is present, this alternative accepts memory constants.  */
    while ((c = *constraint++) && c != ',' && c != '#')
!     if (c == 'm' || c == 'o')
        return 1;
    return 0;
  }
--- 4335,4341 ----
    /* Scan the requested alternative for 'm' or 'o'.
       If one of them is present, this alternative accepts memory constants.  */
    while ((c = *constraint++) && c != ',' && c != '#')
!     if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
        return 1;
    return 0;
  }
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.351
diff -c -p -r1.351 reload1.c
*** gcc/reload1.c 30 Jul 2002 16:42:05 -0000    1.351
--- gcc/reload1.c 14 Aug 2002 09:46:21 -0000
*************** maybe_fix_stack_asms ()
*** 1380,1387 ****
              break;

            default:
!             cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
!
            }
          }
      }
--- 1380,1391 ----
              break;

            default:
!             if (EXTRA_ADDRESS_CONSTRAINT (c))
!               cls = (int) reg_class_subunion[cls]
!                 [(int) MODE_BASE_REG_CLASS (VOIDmode)];
!             else
!               cls = (int) reg_class_subunion[cls]
!                 [(int) REG_CLASS_FROM_LETTER (c)];
            }
          }
      }
Index: gcc/stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.268
diff -c -p -r1.268 stmt.c
*** gcc/stmt.c    5 Aug 2002 18:46:33 -0000     1.268
--- gcc/stmt.c    14 Aug 2002 09:46:26 -0000
*************** parse_output_constraint (constraint_p, o
*** 1252,1257 ****
--- 1252,1261 ----
      if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
        *allows_reg = true;
  #ifdef EXTRA_CONSTRAINT
+     else if (EXTRA_ADDRESS_CONSTRAINT (*p))
+       *allows_reg = true;
+     else if (EXTRA_MEMORY_CONSTRAINT (*p))
+       *allows_mem = true;
      else
        {
          /* Otherwise we can't assume anything about the nature of
*************** parse_input_constraint (constraint_p, in
*** 1377,1382 ****
--- 1381,1390 ----
      if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
        *allows_reg = true;
  #ifdef EXTRA_CONSTRAINT
+     else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
+       *allows_reg = true;
+     else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
+       *allows_mem = true;
      else
        {
          /* Otherwise we can't assume anything about the nature of
Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.10
diff -c -p -r1.10 s390-protos.h
*** gcc/config/s390/s390-protos.h   13 Aug 2002 16:02:52 -0000    1.10
--- gcc/config/s390/s390-protos.h   14 Aug 2002 09:46:28 -0000
*************** extern void s390_emit_epilogue PARAMS ((
*** 31,36 ****
--- 31,37 ----
  extern void s390_function_profiler PARAMS ((FILE *, int));

  #ifdef RTX_CODE
+ extern int q_constraint PARAMS ((rtx));
  extern int const0_operand PARAMS ((rtx, enum machine_mode));
  extern int consttable_operand PARAMS ((rtx, enum machine_mode));
  extern int larl_operand PARAMS ((rtx, enum machine_mode));
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.45
diff -c -p -r1.45 s390.c
*** gcc/config/s390/s390.c    13 Aug 2002 16:02:52 -0000    1.45
--- gcc/config/s390/s390.c    14 Aug 2002 09:46:30 -0000
*************** s_imm_operand (op, mode)
*** 995,1000 ****
--- 995,1022 ----
    return general_s_operand (op, mode, 1);
  }

+ /* Return true if OP is a valid operand for a 'Q' constraint.
+    This differs from s_operand in that only memory operands
+    without index register are accepted, nothing else.  */
+
+ int
+ q_constraint (op)
+      register rtx op;
+ {
+   struct s390_address addr;
+
+   if (GET_CODE (op) != MEM)
+     return 0;
+
+   if (!s390_decompose_address (XEXP (op, 0), &addr, FALSE))
+     return 0;
+
+   if (addr.indx)
+     return 0;
+
+   return 1;
+ }
+
  /* Return true if OP is a valid operand for the BRAS instruction.
     OP is the current operation.
     MODE is the current operation mode.  */
*************** s390_expand_plus_operand (target, src, s
*** 1385,1390 ****
--- 1407,1421 ----
       float registers occur in an address.  */
    sum1 = find_replacement (&XEXP (src, 0));
    sum2 = find_replacement (&XEXP (src, 1));
+
+   /* Accept already valid addresses.  */
+   src = gen_rtx_PLUS (Pmode, sum1, sum2);
+   if (s390_decompose_address (src, NULL, 1))
+     {
+       src = legitimize_la_operand (src);
+       emit_insn (gen_rtx_SET (VOIDmode, target, src));
+       return;
+     }

    /* If one of the two operands is equal to the target,
       make it the first one.  If one is a constant, make
Index: gcc/config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.39
diff -c -p -r1.39 s390.h
*** gcc/config/s390/s390.h    16 Jul 2002 20:59:04 -0000    1.39
--- gcc/config/s390/s390.h    14 Aug 2002 09:46:31 -0000
*************** extern const enum reg_class regclass_map
*** 533,540 ****
  /* 'Q' means a memory-reference for a S-type operand.  */

  #define EXTRA_CONSTRAINT(OP, C)                                 \
!      ((C) == 'Q' ?  s_operand (OP, GET_MODE (OP)) :             \
        (C) == 'S' ?  larl_operand (OP, GET_MODE (OP)) : 0)

  /* Given an rtx X being reloaded into a reg required to be in class CLASS,
     return the class of reg to actually use.  In general this is just CLASS;
--- 533,542 ----
  /* 'Q' means a memory-reference for a S-type operand.  */

  #define EXTRA_CONSTRAINT(OP, C)                                 \
!      ((C) == 'Q' ?  q_constraint (OP) :                   \
        (C) == 'S' ?  larl_operand (OP, GET_MODE (OP)) : 0)
+
+ #define EXTRA_MEMORY_CONSTRAINT(C) ((C) == 'Q')

  /* Given an rtx X being reloaded into a reg required to be in class CLASS,
     return the class of reg to actually use.  In general this is just CLASS;
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.23
diff -c -p -r1.23 s390.md
*** gcc/config/s390/s390.md   13 Aug 2002 16:02:52 -0000    1.23
--- gcc/config/s390/s390.md   14 Aug 2002 09:46:36 -0000
***************
*** 278,284 ****

  (define_insn "*tmqi_ext"
    [(set (reg 33)
!         (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
                                (match_operand:SI 1 "const_int_operand" "n")
                                    (match_operand:SI 2 "const_int_operand" "n"))
                   (const_int 0)))]
--- 278,284 ----

  (define_insn "*tmqi_ext"
    [(set (reg 33)
!         (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Q")
                                (match_operand:SI 1 "const_int_operand" "n")
                                    (match_operand:SI 2 "const_int_operand" "n"))
                   (const_int 0)))]
***************
*** 345,351 ****

  (define_insn "*tmdi_mem"
    [(set (reg 33)
!         (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
                           (match_operand:DI 1 "immediate_operand" "n"))
                   (match_operand:DI 2 "immediate_operand" "n")))]
    "TARGET_64BIT
--- 345,351 ----

  (define_insn "*tmdi_mem"
    [(set (reg 33)
!         (compare (and:DI (match_operand:DI 0 "s_operand" "%Q")
                           (match_operand:DI 1 "immediate_operand" "n"))
                   (match_operand:DI 2 "immediate_operand" "n")))]
    "TARGET_64BIT
***************
*** 365,371 ****

  (define_insn "*tmsi_mem"
    [(set (reg 33)
!         (compare (and:SI (match_operand:SI 0 "s_operand" "%Qo")
                           (match_operand:SI 1 "immediate_operand" "n"))
                   (match_operand:SI 2 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
--- 365,371 ----

  (define_insn "*tmsi_mem"
    [(set (reg 33)
!         (compare (and:SI (match_operand:SI 0 "s_operand" "%Q")
                           (match_operand:SI 1 "immediate_operand" "n"))
                   (match_operand:SI 2 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
***************
*** 384,390 ****

  (define_insn "*tmhi_mem"
    [(set (reg 33)
!         (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
                           (match_operand:SI 1 "immediate_operand" "n"))
                   (match_operand:SI 2 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
--- 384,390 ----

  (define_insn "*tmhi_mem"
    [(set (reg 33)
!         (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Q") 0)
                           (match_operand:SI 1 "immediate_operand" "n"))
                   (match_operand:SI 2 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
***************
*** 403,409 ****

  (define_insn "*tmqi_mem"
    [(set (reg 33)
!         (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
                           (match_operand:SI 1 "immediate_operand" "n"))
                   (match_operand:SI 2 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
--- 403,409 ----

  (define_insn "*tmqi_mem"
    [(set (reg 33)
!         (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Q") 0)
                           (match_operand:SI 1 "immediate_operand" "n"))
                   (match_operand:SI 2 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
***************
*** 502,508 ****

  (define_insn "*tsthi"
    [(set (reg 33)
!         (compare (match_operand:HI 0 "s_operand" "Qo")
                   (match_operand:HI 1 "const0_operand" "")))
     (set (match_operand:HI 2 "register_operand" "=d")
          (match_dup 0))]
--- 502,508 ----

  (define_insn "*tsthi"
    [(set (reg 33)
!         (compare (match_operand:HI 0 "s_operand" "Q")
                   (match_operand:HI 1 "const0_operand" "")))
     (set (match_operand:HI 2 "register_operand" "=d")
          (match_dup 0))]
***************
*** 513,519 ****

  (define_insn "*tsthi_cconly"
    [(set (reg 33)
!         (compare (match_operand:HI 0 "s_operand" "Qo")
                   (match_operand:HI 1 "const0_operand" "")))
     (clobber (match_scratch:HI 2 "=d"))]
    "s390_match_ccmode(insn, CCSmode)"
--- 513,519 ----

  (define_insn "*tsthi_cconly"
    [(set (reg 33)
!         (compare (match_operand:HI 0 "s_operand" "Q")
                   (match_operand:HI 1 "const0_operand" "")))
     (clobber (match_scratch:HI 2 "=d"))]
    "s390_match_ccmode(insn, CCSmode)"
***************
*** 523,529 ****

  (define_insn "*tstqi"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Qo")
                   (match_operand:QI 1 "const0_operand" "")))
     (set (match_operand:QI 2 "register_operand" "=d")
          (match_dup 0))]
--- 523,529 ----

  (define_insn "*tstqi"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Q")
                   (match_operand:QI 1 "const0_operand" "")))
     (set (match_operand:QI 2 "register_operand" "=d")
          (match_dup 0))]
***************
*** 534,540 ****

  (define_insn "*tstqi_cconly"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Qo")
                   (match_operand:QI 1 "const0_operand" "")))
     (clobber (match_scratch:QI 2 "=d"))]
    "s390_match_ccmode(insn, CCSmode)"
--- 534,540 ----

  (define_insn "*tstqi_cconly"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Q")
                   (match_operand:QI 1 "const0_operand" "")))
     (clobber (match_scratch:QI 2 "=d"))]
    "s390_match_ccmode(insn, CCSmode)"
***************
*** 628,634 ****
  (define_insn "*cmphi_ccu"
    [(set (reg 33)
          (compare (match_operand:HI 0 "register_operand" "d")
!                  (match_operand:HI 1 "s_imm_operand" "Qo")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clm\\t%0,3,%1"
    [(set_attr "op_type" "RS")
--- 628,634 ----
  (define_insn "*cmphi_ccu"
    [(set (reg 33)
          (compare (match_operand:HI 0 "register_operand" "d")
!                  (match_operand:HI 1 "s_imm_operand" "Q")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clm\\t%0,3,%1"
    [(set_attr "op_type" "RS")
***************
*** 637,643 ****
  (define_insn "*cmpqi_ccu"
    [(set (reg 33)
          (compare (match_operand:QI 0 "register_operand" "d")
!                  (match_operand:QI 1 "s_imm_operand" "Qo")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clm\\t%0,1,%1"
    [(set_attr "op_type" "RS")
--- 637,643 ----
  (define_insn "*cmpqi_ccu"
    [(set (reg 33)
          (compare (match_operand:QI 0 "register_operand" "d")
!                  (match_operand:QI 1 "s_imm_operand" "Q")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clm\\t%0,1,%1"
    [(set_attr "op_type" "RS")
***************
*** 645,651 ****

  (define_insn "*cli"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Qo")
                   (match_operand:QI 1 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, CCUmode)"
    "cli\\t%0,%b1"
--- 645,651 ----

  (define_insn "*cli"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Q")
                   (match_operand:QI 1 "immediate_operand" "n")))]
    "s390_match_ccmode (insn, CCUmode)"
    "cli\\t%0,%b1"
***************
*** 654,661 ****

  (define_insn "*cmpdi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:DI 0 "s_operand" "oQ")
!                  (match_operand:DI 1 "s_imm_operand" "oQ")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(8,%R0),%1"
    [(set_attr "op_type" "SS")
--- 654,661 ----

  (define_insn "*cmpdi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:DI 0 "s_operand" "Q")
!                  (match_operand:DI 1 "s_imm_operand" "Q")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(8,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 663,670 ****

  (define_insn "*cmpsi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:SI 0 "s_operand" "oQ")
!                  (match_operand:SI 1 "s_imm_operand" "oQ")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(4,%R0),%1"
     [(set_attr "op_type" "SS")
--- 663,670 ----

  (define_insn "*cmpsi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:SI 0 "s_operand" "Q")
!                  (match_operand:SI 1 "s_imm_operand" "Q")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(4,%R0),%1"
     [(set_attr "op_type" "SS")
***************
*** 672,679 ****

  (define_insn "*cmphi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:HI 0 "s_operand" "oQ")
!                  (match_operand:HI 1 "s_imm_operand" "oQ")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(2,%R0),%1"
    [(set_attr "op_type" "SS")
--- 672,679 ----

  (define_insn "*cmphi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:HI 0 "s_operand" "Q")
!                  (match_operand:HI 1 "s_imm_operand" "Q")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(2,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 681,688 ****

  (define_insn "*cmpqi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "oQ")
!                  (match_operand:QI 1 "s_imm_operand" "oQ")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(1,%R0),%1"
    [(set_attr "op_type" "SS")
--- 681,688 ----

  (define_insn "*cmpqi_ccu_mem"
    [(set (reg 33)
!         (compare (match_operand:QI 0 "s_operand" "Q")
!                  (match_operand:QI 1 "s_imm_operand" "Q")))]
    "s390_match_ccmode(insn, CCUmode)"
    "clc\\t%O0(1,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 780,787 ****
  ;

  (define_insn "*movti_ss"
!   [(set (match_operand:TI 0 "s_operand" "=Qo")
!         (match_operand:TI 1 "s_imm_operand" "Qo"))]
    ""
    "mvc\\t%O0(16,%R0),%1"
    [(set_attr "op_type" "SS")
--- 780,787 ----
  ;

  (define_insn "*movti_ss"
!   [(set (match_operand:TI 0 "s_operand" "=Q")
!         (match_operand:TI 1 "s_imm_operand" "Q"))]
    ""
    "mvc\\t%O0(16,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 914,921 ****
      (set_attr "type"    "la")])

  (define_insn "*movdi_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
!         (match_operand:DI 1 "s_imm_operand" "Qo"))]
    ""
    "mvc\\t%O0(8,%R0),%1"
    [(set_attr "op_type" "SS")
--- 914,921 ----
      (set_attr "type"    "la")])

  (define_insn "*movdi_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
!         (match_operand:DI 1 "s_imm_operand" "Q"))]
    ""
    "mvc\\t%O0(8,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 1067,1074 ****
    [(set_attr "op_type" "RI")])

  (define_insn "*movsi_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
!         (match_operand:SI 1 "s_imm_operand" "Qo"))]
    ""
    "mvc\\t%O0(4,%R0),%1"
    [(set_attr "op_type" "SS")
--- 1067,1074 ----
    [(set_attr "op_type" "RI")])

  (define_insn "*movsi_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
!         (match_operand:SI 1 "s_imm_operand" "Q"))]
    ""
    "mvc\\t%O0(4,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 1156,1162 ****

  (define_insn "*movstricthi"
    [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
!                          (match_operand:HI 1 "s_imm_operand" "Qo"))
     (clobber (reg:CC 33))]
    ""
    "icm\\t%0,3,%1"
--- 1156,1162 ----

  (define_insn "*movstricthi"
    [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
!                          (match_operand:HI 1 "s_imm_operand" "Q"))
     (clobber (reg:CC 33))]
    ""
    "icm\\t%0,3,%1"
***************
*** 1197,1204 ****
  }")

  (define_insn "*movdf_ss"
!   [(set (match_operand:DF 0 "s_operand" "=Qo")
!         (match_operand:DF 1 "s_imm_operand" "Qo"))]
    ""
    "mvc\\t%O0(8,%R0),%1"
    [(set_attr "op_type" "SS")
--- 1197,1204 ----
  }")

  (define_insn "*movdf_ss"
!   [(set (match_operand:DF 0 "s_operand" "=Q")
!         (match_operand:DF 1 "s_imm_operand" "Q"))]
    ""
    "mvc\\t%O0(8,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 1300,1307 ****
  }")

  (define_insn "*movsf_ss"
!   [(set (match_operand:SF 0 "s_operand" "=Qo")
!         (match_operand:SF 1 "s_imm_operand" "Qo"))]
    ""
    "mvc\\t%O0(4,%R0),%1"
    [(set_attr "op_type" "SS")
--- 1300,1307 ----
  }")

  (define_insn "*movsf_ss"
!   [(set (match_operand:SF 0 "s_operand" "=Q")
!         (match_operand:SF 1 "s_imm_operand" "Q"))]
    ""
    "mvc\\t%O0(4,%R0),%1"
    [(set_attr "op_type" "SS")
***************
*** 1388,1394 ****
  (define_insn "*load_multiple_di"
    [(match_parallel 0 "load_multiple_operation"
               [(set (match_operand:DI 1 "register_operand" "=r")
!                  (match_operand:DI 2 "s_operand" "oQ"))])]
    ""
    "*
  {
--- 1388,1394 ----
  (define_insn "*load_multiple_di"
    [(match_parallel 0 "load_multiple_operation"
               [(set (match_operand:DI 1 "register_operand" "=r")
!                  (match_operand:DI 2 "s_operand" "Q"))])]
    ""
    "*
  {
***************
*** 1407,1413 ****
  (define_insn "*load_multiple_si"
    [(match_parallel 0 "load_multiple_operation"
               [(set (match_operand:SI 1 "register_operand" "=r")
!                  (match_operand:SI 2 "s_operand" "oQ"))])]
    ""
    "*
  {
--- 1407,1413 ----
  (define_insn "*load_multiple_si"
    [(match_parallel 0 "load_multiple_operation"
               [(set (match_operand:SI 1 "register_operand" "=r")
!                  (match_operand:SI 2 "s_operand" "Q"))])]
    ""
    "*
  {
***************
*** 1491,1497 ****

  (define_insn "*store_multiple_di"
    [(match_parallel 0 "store_multiple_operation"
!              [(set (match_operand:DI 1 "s_operand" "=oQ")
                   (match_operand:DI 2 "register_operand" "r"))])]
    ""
    "*
--- 1491,1497 ----

  (define_insn "*store_multiple_di"
    [(match_parallel 0 "store_multiple_operation"
!              [(set (match_operand:DI 1 "s_operand" "=Q")
                   (match_operand:DI 2 "register_operand" "r"))])]
    ""
    "*
***************
*** 1511,1517 ****

  (define_insn "*store_multiple_si"
    [(match_parallel 0 "store_multiple_operation"
!              [(set (match_operand:SI 1 "s_operand" "=oQ")
                   (match_operand:SI 2 "register_operand" "r"))])]
    ""
    "*
--- 1511,1517 ----

  (define_insn "*store_multiple_si"
    [(match_parallel 0 "store_multiple_operation"
!              [(set (match_operand:SI 1 "s_operand" "=Q")
                   (match_operand:SI 2 "register_operand" "r"))])]
    ""
    "*
***************
*** 1697,1704 ****
  ; The block length is taken as (operands[2] % 256) + 1.

  (define_insn "movstrdi_short"
!   [(set (match_operand:BLK 0 "s_operand" "=oQ,oQ")
!         (match_operand:BLK 1 "s_operand" "oQ,oQ"))
     (use (match_operand:DI 2 "nonmemory_operand" "n,a"))
     (clobber (match_scratch:DI 3 "=X,&a"))]
    "TARGET_64BIT"
--- 1697,1704 ----
  ; The block length is taken as (operands[2] % 256) + 1.

  (define_insn "movstrdi_short"
!   [(set (match_operand:BLK 0 "s_operand" "=Q,Q")
!         (match_operand:BLK 1 "s_operand" "Q,Q"))
     (use (match_operand:DI 2 "nonmemory_operand" "n,a"))
     (clobber (match_scratch:DI 3 "=X,&a"))]
    "TARGET_64BIT"
***************
*** 1723,1730 ****
     (set_attr "length"  "*,14")])

  (define_insn "movstrsi_short"
!   [(set (match_operand:BLK 0 "s_operand" "=oQ,oQ")
!         (match_operand:BLK 1 "s_operand" "oQ,oQ"))
     (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
     (clobber (match_scratch:SI 3 "=X,&a"))]
    "!TARGET_64BIT"
--- 1723,1730 ----
     (set_attr "length"  "*,14")])

  (define_insn "movstrsi_short"
!   [(set (match_operand:BLK 0 "s_operand" "=Q,Q")
!         (match_operand:BLK 1 "s_operand" "Q,Q"))
     (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
     (clobber (match_scratch:SI 3 "=X,&a"))]
    "!TARGET_64BIT"
***************
*** 1927,1933 ****
  ; Clear memory with length less than 256 bytes

  (define_insn "clrstrsico"
!   [(set (match_operand:BLK 0 "s_operand" "=Qo")
          (const_int 0))
     (use (match_operand 1 "immediate_operand" "I"))
     (clobber (reg:CC 33))]
--- 1927,1933 ----
  ; Clear memory with length less than 256 bytes

  (define_insn "clrstrsico"
!   [(set (match_operand:BLK 0 "s_operand" "=Q")
          (const_int 0))
     (use (match_operand 1 "immediate_operand" "I"))
     (clobber (reg:CC 33))]
***************
*** 2111,2118 ****

  (define_insn "cmpstr_const"
    [(set (reg:CCS 33)
!         (compare:CCS (match_operand:BLK 0 "s_operand" "oQ")
!                      (match_operand:BLK 1 "s_operand" "oQ")))
     (use (match_operand 2 "immediate_operand" "I"))]
    "(unsigned) INTVAL (operands[2]) < 256"
    "clc\\t%O0(%c2,%R0),%1"
--- 2111,2118 ----

  (define_insn "cmpstr_const"
    [(set (reg:CCS 33)
!         (compare:CCS (match_operand:BLK 0 "s_operand" "Q")
!                      (match_operand:BLK 1 "s_operand" "Q")))
     (use (match_operand 2 "immediate_operand" "I"))]
    "(unsigned) INTVAL (operands[2]) < 256"
    "clc\\t%O0(%c2,%R0),%1"
***************
*** 2193,2199 ****

  (define_insn "*sethighqisi"
    [(set (match_operand:SI 0 "register_operand" "=d")
!         (unspec:SI [(match_operand:QI 1 "s_operand" "Qo")] 10))
     (clobber (reg:CC 33))]
    ""
    "icm\\t%0,8,%1"
--- 2193,2199 ----

  (define_insn "*sethighqisi"
    [(set (match_operand:SI 0 "register_operand" "=d")
!         (unspec:SI [(match_operand:QI 1 "s_operand" "Q")] 10))
     (clobber (reg:CC 33))]
    ""
    "icm\\t%0,8,%1"
***************
*** 2202,2208 ****

  (define_insn "*sethighhisi"
    [(set (match_operand:SI 0 "register_operand" "=d")
!         (unspec:SI [(match_operand:HI 1 "s_operand" "Qo")] 10))
     (clobber (reg:CC 33))]
    ""
    "icm\\t%0,12,%1"
--- 2202,2208 ----

  (define_insn "*sethighhisi"
    [(set (match_operand:SI 0 "register_operand" "=d")
!         (unspec:SI [(match_operand:HI 1 "s_operand" "Q")] 10))
     (clobber (reg:CC 33))]
    ""
    "icm\\t%0,12,%1"
***************
*** 2211,2217 ****

  (define_insn "*sethighqidi_64"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
     (clobber (reg:CC 33))]
    "TARGET_64BIT"
    "icmh\\t%0,8,%1"
--- 2211,2217 ----

  (define_insn "*sethighqidi_64"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (unspec:DI [(match_operand:QI 1 "s_operand" "Q")] 10))
     (clobber (reg:CC 33))]
    "TARGET_64BIT"
    "icmh\\t%0,8,%1"
***************
*** 2220,2226 ****

  (define_insn "*sethighqidi_31"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
     (clobber (reg:CC 33))]
    "!TARGET_64BIT"
    "icm\\t%0,8,%1"
--- 2220,2226 ----

  (define_insn "*sethighqidi_31"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (unspec:DI [(match_operand:QI 1 "s_operand" "Q")] 10))
     (clobber (reg:CC 33))]
    "!TARGET_64BIT"
    "icm\\t%0,8,%1"
***************
*** 4486,4494 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*anddi3_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
          (and:DI (match_dup 0)
!                 (match_operand:DI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "nc\\t%O0(8,%R0),%1"
--- 4486,4494 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*anddi3_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
          (and:DI (match_dup 0)
!                 (match_operand:DI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "nc\\t%O0(8,%R0),%1"
***************
*** 4496,4503 ****
     (set_attr "atype"    "mem")])

  (define_insn "*anddi3_ss_inv"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
!         (and:DI (match_operand:DI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4496,4503 ----
     (set_attr "atype"    "mem")])

  (define_insn "*anddi3_ss_inv"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
!         (and:DI (match_operand:DI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4570,4578 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*andsi3_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
          (and:SI (match_dup 0)
!                 (match_operand:SI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "nc\\t%O0(4,%R0),%1"
--- 4570,4578 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*andsi3_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
          (and:SI (match_dup 0)
!                 (match_operand:SI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "nc\\t%O0(4,%R0),%1"
***************
*** 4580,4587 ****
     (set_attr "atype"    "mem")])

  (define_insn "*andsi3_ss_inv"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
!         (and:SI (match_operand:SI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4580,4587 ----
     (set_attr "atype"    "mem")])

  (define_insn "*andsi3_ss_inv"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
!         (and:SI (match_operand:SI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4616,4624 ****
     (set_attr "atype"    "reg")])

  (define_insn "*andhi3_ss"
!   [(set (match_operand:HI 0 "s_operand" "=Qo")
          (and:HI (match_dup 0)
!                 (match_operand:HI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "nc\\t%O0(2,%R0),%1"
--- 4616,4624 ----
     (set_attr "atype"    "reg")])

  (define_insn "*andhi3_ss"
!   [(set (match_operand:HI 0 "s_operand" "=Q")
          (and:HI (match_dup 0)
!                 (match_operand:HI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "nc\\t%O0(2,%R0),%1"
***************
*** 4626,4633 ****
     (set_attr "atype"    "mem")])

  (define_insn "*andhi3_ss_inv"
!   [(set (match_operand:HI 0 "s_operand" "=Qo")
!         (and:HI (match_operand:HI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4626,4633 ----
     (set_attr "atype"    "mem")])

  (define_insn "*andhi3_ss_inv"
!   [(set (match_operand:HI 0 "s_operand" "=Q")
!         (and:HI (match_operand:HI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4662,4670 ****
     (set_attr "atype"    "reg")])

  (define_insn "*andqi3_ss"
!   [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
          (and:QI (match_dup 0)
!                 (match_operand:QI 1 "s_imm_operand" "n,Qo")))
     (clobber (reg:CC 33))]
    ""
    "@
--- 4662,4670 ----
     (set_attr "atype"    "reg")])

  (define_insn "*andqi3_ss"
!   [(set (match_operand:QI 0 "s_operand" "=Q,Q")
          (and:QI (match_dup 0)
!                 (match_operand:QI 1 "s_imm_operand" "n,Q")))
     (clobber (reg:CC 33))]
    ""
    "@
***************
*** 4674,4681 ****
     (set_attr "atype"    "mem")])

  (define_insn "*andqi3_ss_inv"
!   [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
!         (and:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4674,4681 ----
     (set_attr "atype"    "mem")])

  (define_insn "*andqi3_ss_inv"
!   [(set (match_operand:QI 0 "s_operand" "=Q,Q")
!         (and:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4757,4765 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*iordi3_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
          (ior:DI (match_dup 0)
!                 (match_operand:DI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "oc\\t%O0(8,%R0),%1"
--- 4757,4765 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*iordi3_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
          (ior:DI (match_dup 0)
!                 (match_operand:DI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "oc\\t%O0(8,%R0),%1"
***************
*** 4767,4774 ****
     (set_attr "atype"    "mem")])

  (define_insn "*iordi3_ss_inv"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
!         (ior:DI (match_operand:DI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4767,4774 ----
     (set_attr "atype"    "mem")])

  (define_insn "*iordi3_ss_inv"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
!         (ior:DI (match_operand:DI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4841,4849 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*iorsi3_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
          (ior:SI (match_dup 0)
!                 (match_operand:SI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "oc\\t%O0(4,%R0),%1"
--- 4841,4849 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*iorsi3_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
          (ior:SI (match_dup 0)
!                 (match_operand:SI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "oc\\t%O0(4,%R0),%1"
***************
*** 4851,4858 ****
     (set_attr "atype"    "mem")])

  (define_insn "*iorsi3_ss_inv"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
!         (ior:SI (match_operand:SI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4851,4858 ----
     (set_attr "atype"    "mem")])

  (define_insn "*iorsi3_ss_inv"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
!         (ior:SI (match_operand:SI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4887,4895 ****
     (set_attr "atype"    "reg")])

  (define_insn "*iorhi3_ss"
!   [(set (match_operand:HI 0 "s_operand" "=Qo")
          (ior:HI (match_dup 0)
!                 (match_operand:HI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "oc\\t%O0(2,%R0),%1"
--- 4887,4895 ----
     (set_attr "atype"    "reg")])

  (define_insn "*iorhi3_ss"
!   [(set (match_operand:HI 0 "s_operand" "=Q")
          (ior:HI (match_dup 0)
!                 (match_operand:HI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "oc\\t%O0(2,%R0),%1"
***************
*** 4897,4904 ****
     (set_attr "atype"    "mem")])

  (define_insn "*iorhi3_ss_inv"
!   [(set (match_operand:HI 0 "s_operand" "=Qo")
!         (ior:HI (match_operand:HI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4897,4904 ----
     (set_attr "atype"    "mem")])

  (define_insn "*iorhi3_ss_inv"
!   [(set (match_operand:HI 0 "s_operand" "=Q")
!         (ior:HI (match_operand:HI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 4933,4941 ****
     (set_attr "atype"    "reg")])

  (define_insn "*iorqi3_ss"
!   [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
          (ior:QI (match_dup 0)
!                 (match_operand:QI 1 "s_imm_operand" "n,Qo")))
     (clobber (reg:CC 33))]
    ""
    "@
--- 4933,4941 ----
     (set_attr "atype"    "reg")])

  (define_insn "*iorqi3_ss"
!   [(set (match_operand:QI 0 "s_operand" "=Q,Q")
          (ior:QI (match_dup 0)
!                 (match_operand:QI 1 "s_imm_operand" "n,Q")))
     (clobber (reg:CC 33))]
    ""
    "@
***************
*** 4945,4952 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*iorqi3_ss_inv"
!   [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
!         (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 4945,4952 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*iorqi3_ss_inv"
!   [(set (match_operand:QI 0 "s_operand" "=Q,Q")
!         (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 5005,5013 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*xordi3_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
          (xor:DI (match_dup 0)
!                 (match_operand:DI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "xc\\t%O0(8,%R0),%1"
--- 5005,5013 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*xordi3_ss"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
          (xor:DI (match_dup 0)
!                 (match_operand:DI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "xc\\t%O0(8,%R0),%1"
***************
*** 5015,5022 ****
     (set_attr "atype"    "mem")])

  (define_insn "*xordi3_ss_inv"
!   [(set (match_operand:DI 0 "s_operand" "=Qo")
!         (xor:DI (match_operand:DI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 5015,5022 ----
     (set_attr "atype"    "mem")])

  (define_insn "*xordi3_ss_inv"
!   [(set (match_operand:DI 0 "s_operand" "=Q")
!         (xor:DI (match_operand:DI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 5068,5076 ****
     (set_attr "atype"    "reg,mem")])

  (define_insn "*xorsi3_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
          (xor:SI (match_dup 0)
!                 (match_operand:SI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "xc\\t%O0(4,%R0),%1"
--- 5068,5076 ----
     (set_attr "atype"    "reg,mem")])

  (define_insn "*xorsi3_ss"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
          (xor:SI (match_dup 0)
!                 (match_operand:SI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "xc\\t%O0(4,%R0),%1"
***************
*** 5078,5085 ****
     (set_attr "atype"    "mem")])

  (define_insn "*xorsi3_ss_inv"
!   [(set (match_operand:SI 0 "s_operand" "=Qo")
!         (xor:SI (match_operand:SI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 5078,5085 ----
     (set_attr "atype"    "mem")])

  (define_insn "*xorsi3_ss_inv"
!   [(set (match_operand:SI 0 "s_operand" "=Q")
!         (xor:SI (match_operand:SI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 5102,5110 ****
     (set_attr "atype"    "reg")])

  (define_insn "*xorhi3_ss"
!   [(set (match_operand:HI 0 "s_operand" "=Qo")
          (xor:HI (match_dup 0)
!                 (match_operand:HI 1 "s_imm_operand" "Qo")))
     (clobber (reg:CC 33))]
    ""
    "xc\\t%O0(2,%R0),%1"
--- 5102,5110 ----
     (set_attr "atype"    "reg")])

  (define_insn "*xorhi3_ss"
!   [(set (match_operand:HI 0 "s_operand" "=Q")
          (xor:HI (match_dup 0)
!                 (match_operand:HI 1 "s_imm_operand" "Q")))
     (clobber (reg:CC 33))]
    ""
    "xc\\t%O0(2,%R0),%1"
***************
*** 5112,5119 ****
     (set_attr "atype"    "mem")])

  (define_insn "*xorhi3_ss_inv"
!   [(set (match_operand:HI 0 "s_operand" "=Qo")
!         (xor:HI (match_operand:HI 1 "s_imm_operand" "Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 5112,5119 ----
     (set_attr "atype"    "mem")])

  (define_insn "*xorhi3_ss_inv"
!   [(set (match_operand:HI 0 "s_operand" "=Q")
!         (xor:HI (match_operand:HI 1 "s_imm_operand" "Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
***************
*** 5136,5144 ****
     (set_attr "atype"    "reg")])

  (define_insn "*xorqi3_ss"
!   [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
          (xor:QI (match_dup 0)
!                 (match_operand:QI 1 "s_imm_operand" "n,Qo")))
     (clobber (reg:CC 33))]
    ""
    "@
--- 5136,5144 ----
     (set_attr "atype"    "reg")])

  (define_insn "*xorqi3_ss"
!   [(set (match_operand:QI 0 "s_operand" "=Q,Q")
          (xor:QI (match_dup 0)
!                 (match_operand:QI 1 "s_imm_operand" "n,Q")))
     (clobber (reg:CC 33))]
    ""
    "@
***************
*** 5148,5155 ****
     (set_attr "atype"    "mem")])

  (define_insn "*xorqi3_ss_inv"
!   [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
!         (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
--- 5148,5155 ----
     (set_attr "atype"    "mem")])

  (define_insn "*xorqi3_ss_inv"
!   [(set (match_operand:QI 0 "s_operand" "=Q,Q")
!         (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
                  (match_dup 0)))
     (clobber (reg:CC 33))]
    ""
Index: gcc/doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.155
diff -c -p -r1.155 tm.texi
*** gcc/doc/tm.texi     7 Aug 2002 21:05:12 -0000     1.155
--- gcc/doc/tm.texi     14 Aug 2002 09:46:44 -0000
*************** letter @samp{Q} is defined as representi
*** 2614,2619 ****
--- 2614,2657 ----
  a @samp{Q} constraint on the input and @samp{r} on the output.  The next
  alternative specifies @samp{m} on the input and a register class that
  does not include r0 on the output.
+
+ @findex EXTRA_MEMORY_CONSTRAINT
+ @item EXTRA_MEMORY_CONSTRAINT (@var{c})
+ A C expression that defines the optional machine-dependent constraint
+ letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+ be treated like memory constraints by the reload pass.
+
+ It should return 1 if the operand type represented by the constraint
+ letter @var{c} comprises a subset of all memory references including
+ all those whose address is simply a base register.  This allows the reload
+ pass to reload an operand, if it does not directly correspond to the operand
+ type of @var{c}, by copying its address into a base register.
+
+ For example, on the S/390, some instructions do not accept arbitrary
+ memory references, but only those that do not make use of an index
+ register.  The constraint letter @samp{Q} is defined via
+ @code{EXTRA_CONSTRAINT} as representing a memory address of this type.
+ If the letter @samp{Q} is marked as @code{EXTRA_MEMORY_CONSTRAINT},
+ a @samp{Q} constraint can handle any memory operand, because the
+ reload pass knows it can be reloaded by copying the memory address
+ into a base register if required.  This is analogous to the way
+ a @samp{o} constraint can handle any memory operand.
+
+ @findex EXTRA_ADDRESS_CONSTRAINT
+ @item EXTRA_ADDRESS_CONSTRAINT (@var{c})
+ A C expression that defines the optional machine-dependent constraint
+ letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+ be treated like address constraints by the reload pass.
+
+ It should return 1 if the operand type represented by the constraint
+ letter @var{c} comprises a subset of all memory addresses including
+ all those that consist of just a base register.  This allows the reload
+ pass to reload an operand, if it does not directly correspond to the operand
+ type of @var{c}, by copying it into a base register.
+
+ Any constraint marked as @code{EXTRA_ADDRESS_CONSTRAINT} can only
+ be used with the @code{address_operand} predicate.  It is treated
+ analogously to the @samp{p} constraint.
  @end table

  @node Stack and Calling


Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC][PATCH] Support multiple variants of memory addresses
  2002-08-12 15:32 Ulrich Weigand
@ 2002-08-12 16:30 ` Richard Henderson
  0 siblings, 0 replies; 3+ messages in thread
From: Richard Henderson @ 2002-08-12 16:30 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc-patches, uweigand, hpenner

On Tue, Aug 13, 2002 at 12:32:17AM +0200, Ulrich Weigand wrote:
> Do you think this is an acceptable way to solve our problem?

Yes.

> 	* reload.c (find_reloads): Handle constraint letters marked by 
> 	EXTRA_ADDRESS_CONSTRAINT and EXTRA_MEMORY_CONSTRAINT.
> 	(alternative_allows_memconst): Likewise.
> 	* recog.c (asm_operand_ok, preprocess_constraints, 
> 	constrain_operands): Likewise.
> 	* regclass.c (record_operand_costs, record_reg_classes): Likewise.
> 	* local-alloc.c (block_alloc, requires_inout): Likewise.
> 	* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
> 
> 	* defaults.h (EXTRA_MEMORY_CONSTRAINT): Provide a default.
> 	(EXTRA_ADDRESS_CONSTRAINT): Likewise.
> 	* doc/tm.texi: Document these two new target macros.

Looks ok to me.


r~

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC][PATCH] Support multiple variants of memory addresses
@ 2002-08-12 15:32 Ulrich Weigand
  2002-08-12 16:30 ` Richard Henderson
  0 siblings, 1 reply; 3+ messages in thread
From: Ulrich Weigand @ 2002-08-12 15:32 UTC (permalink / raw)
  To: gcc-patches; +Cc: uweigand, hpenner

Hello,

this patch introduces a mechanism for the backend to handle
different variants of valid memory addresses.

On the S/390, most instructions accept memory addresses of the
type base + index + displacement, where base and index are two
registers (of class 'a') and displacement is a 12-bit unsigned
immediate value.

Some instructions, however, can only accept addresses of the
type base + displacement, i.e. an index register cannot be
used.

While we currently manage to represent this condition more or
less faithfully using special predicates and constraints, the
result is far from optimal.

To improve the situation, what we'd really like is to make reload
aware of the fact that we have multiple variants of memory
addresses.  Now, it is of course possible to define an 
EXTRA_CONSTRAINT letter that matches just the subset of memory
addresses that we are interested in.  However, if an operand
does not match that constraint, reload does not know how to
handle it.

The solution I'm suggesting is as follows:  we add a new target
macro EXTRA_MEMORY_CONSTRAINT that tells reload that particular 
constraint letters should be handled 'like memory constraints'.  
By returning 1 from this macro, the backend guarantees that 
its EXTRA_CONSTRAINT implementation handles these letters in the
following way: on the one hand, every operand accepted by such a 
constraint letter must be a memory operand, and on the other 
hand every 'trivial' memory operand must be accepted by the 
constraint (where a memory operand is trivial if its address is 
just a base register).

Given this knowledge, reload (and related passes like regclass)
know that they can treat this constraint like a memory constraint,
and accept any memory operand, because reload will be able to
handle any operand that isn't accepted by the constraint via
copying its address into a base register (this is completely
analogous to the way 'o' constraints are handled).

Likewise, we have a new target macro EXTRA_ADDRESS_CONSTRAINT
that allows to define a variant of the 'p' constraint that
accepts only a subset of all possible memory addresses (again,
this subset must include all 'trivial' addresses, i.e. all
base registers, so that other addresses can be reloaded).

Using this patch (plus a s390 backend patch to actually make
use of the new macros), I was able to bootstrap s390-ibm-linux
successfully.  (This patch does not affect in any way targets 
that do not define the new macros.)

Do you think this is an acceptable way to solve our problem?

(B.t.w. I haven't considered yet how this patch interacts
with the new register allocator.  Any changes to the new
allocator to fully support the new features should probably
be straightforward -- maybe one of the new-regalloc gurus
wants to comment?)

Bye,
Ulrich

ChangeLog:

	* reload.c (find_reloads): Handle constraint letters marked by 
	EXTRA_ADDRESS_CONSTRAINT and EXTRA_MEMORY_CONSTRAINT.
	(alternative_allows_memconst): Likewise.
	* recog.c (asm_operand_ok, preprocess_constraints, 
	constrain_operands): Likewise.
	* regclass.c (record_operand_costs, record_reg_classes): Likewise.
	* local-alloc.c (block_alloc, requires_inout): Likewise.
	* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.

	* defaults.h (EXTRA_MEMORY_CONSTRAINT): Provide a default.
	(EXTRA_ADDRESS_CONSTRAINT): Likewise.
	* doc/tm.texi: Document these two new target macros.


Index: gcc/defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.87
diff -c -p -r1.87 defaults.h
*** gcc/defaults.h	31 Jul 2002 02:10:04 -0000	1.87
--- gcc/defaults.h	12 Aug 2002 22:01:27 -0000
*************** You Lose!  You must define PREFERRED_DEB
*** 590,593 ****
--- 590,605 ----
  #define DEFAULT_USE_CXA_ATEXIT 0
  #endif
  
+ /* Determine whether extra constraint letter should be handled
+    via address reload (like 'o').  */
+ #ifndef EXTRA_MEMORY_CONSTRAINT
+ #define EXTRA_MEMORY_CONSTRAINT(C) 0
+ #endif
+ 
+ /* Determine whether extra constraint letter should be handled
+    as an address (like 'p').  */
+ #ifndef EXTRA_ADDRESS_CONSTRAINT
+ #define EXTRA_ADDRESS_CONSTRAINT(C) 0
+ #endif
+ 
  #endif  /* ! GCC_DEFAULTS_H */
Index: gcc/local-alloc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/local-alloc.c,v
retrieving revision 1.109
diff -c -p -r1.109 local-alloc.c
*** gcc/local-alloc.c	30 May 2002 20:55:09 -0000	1.109
--- gcc/local-alloc.c	12 Aug 2002 22:01:29 -0000
*************** block_alloc (b)
*** 1342,1348 ****
  		  /* If the operand is an address, find a register in it.
  		     There may be more than one register, but we only try one
  		     of them.  */
! 		  if (recog_data.constraints[i][0] == 'p')
  		    while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
  		      r1 = XEXP (r1, 0);
  
--- 1342,1349 ----
  		  /* If the operand is an address, find a register in it.
  		     There may be more than one register, but we only try one
  		     of them.  */
! 		  if (recog_data.constraints[i][0] == 'p'
! 		      || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
  		    while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
  		      r1 = XEXP (r1, 0);
  
*************** requires_inout (p)
*** 2472,2478 ****
  	break;
  
        default:
! 	if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
  	  break;
  	/* FALLTHRU */
        case 'p':
--- 2473,2480 ----
  	break;
  
        default:
! 	if (REG_CLASS_FROM_LETTER (c) == NO_REGS
! 	    && !EXTRA_ADDRESS_CONSTRAINT (c))
  	  break;
  	/* FALLTHRU */
        case 'p':
Index: gcc/recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.162
diff -c -p -r1.162 recog.c
*** gcc/recog.c	23 Jul 2002 20:50:59 -0000	1.162
--- gcc/recog.c	12 Aug 2002 22:01:32 -0000
*************** asm_operand_ok (op, constraint)
*** 1848,1853 ****
--- 1848,1865 ----
  #ifdef EXTRA_CONSTRAINT
  	  if (EXTRA_CONSTRAINT (op, c))
  	    return 1;
+ 	  if (EXTRA_MEMORY_CONSTRAINT (c))
+ 	    {
+ 	      /* Every memory operand can be reloaded to fit.  */
+ 	      if (memory_operand (op, VOIDmode))
+ 	        return 1;
+ 	    }
+ 	  if (EXTRA_ADDRESS_CONSTRAINT (c))
+ 	    {
+ 	      /* Every address operand can be reloaded to fit.  */
+ 	      if (address_operand (op, VOIDmode))
+ 	        return 1;
+ 	    }
  #endif
  	  break;
  	}
*************** preprocess_constraints ()
*** 2287,2292 ****
--- 2299,2317 ----
  		  break;
  
  		default:
+ 		  if (EXTRA_MEMORY_CONSTRAINT (c))
+ 		    {
+ 		      op_alt[j].memory_ok = 1;
+ 		      break;
+ 		    }
+ 		  if (EXTRA_ADDRESS_CONSTRAINT (c))
+ 		    {
+ 		      op_alt[j].is_address = 1;
+ 		      op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
+ 		        [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ 		      break;
+ 		    }
+ 
  		  op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
  		  break;
  		}
*************** constrain_operands (strict)
*** 2600,2605 ****
--- 2625,2652 ----
  #ifdef EXTRA_CONSTRAINT
  		  else if (EXTRA_CONSTRAINT (op, c))
  		    win = 1;
+ 
+ 		  if (EXTRA_MEMORY_CONSTRAINT (c))
+ 		    {
+ 		      /* Every memory operand can be reloaded to fit,
+ 			 so copy the condition from the 'm' case.  */
+ 		      if (GET_CODE (op) == MEM
+ 		          /* Before reload, accept what reload can turn into mem.  */
+ 		          || (strict < 0 && CONSTANT_P (op))
+ 		          /* During reload, accept a pseudo  */
+ 		          || (reload_in_progress && GET_CODE (op) == REG
+ 			      && REGNO (op) >= FIRST_PSEUDO_REGISTER))
+ 			win = 1;
+ 		    }
+ 		  if (EXTRA_ADDRESS_CONSTRAINT (c))
+ 		    {
+ 		      /* Every address operand can be reloaded to fit,
+ 			 so copy the condition from the 'p' case.  */
+ 		      if (strict <= 0
+ 		          || (strict_memory_address_p (recog_data.operand_mode[opno],
+ 						       op)))
+ 		        win = 1;
+ 		    }
  #endif
  		  break;
  		}
Index: gcc/regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.154
diff -c -p -r1.154 regclass.c
*** gcc/regclass.c	23 Jul 2002 20:50:59 -0000	1.154
--- gcc/regclass.c	12 Aug 2002 22:01:34 -0000
*************** record_operand_costs (insn, op_costs, re
*** 1007,1013 ****
        if (GET_CODE (recog_data.operand[i]) == MEM)
  	record_address_regs (XEXP (recog_data.operand[i], 0),
  			     MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
!       else if (constraints[i][0] == 'p')
  	record_address_regs (recog_data.operand[i],
  			     MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
      }
--- 1007,1014 ----
        if (GET_CODE (recog_data.operand[i]) == MEM)
  	record_address_regs (XEXP (recog_data.operand[i], 0),
  			     MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
!       else if (constraints[i][0] == 'p'
! 	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
  	record_address_regs (recog_data.operand[i],
  			     MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
      }
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1709,1714 ****
--- 1710,1736 ----
  #ifdef EXTRA_CONSTRAINT
  		else if (EXTRA_CONSTRAINT (op, c))
  		  win = 1;
+ 
+ 		if (EXTRA_MEMORY_CONSTRAINT (c))
+ 		  {
+ 		    /* Every MEM can be reloaded to fit.  */
+ 		    allows_mem[i] = 1;
+ 		    if (GET_CODE (op) == MEM)
+ 		      win = 1;
+ 		  }
+ 		if (EXTRA_ADDRESS_CONSTRAINT (op))
+ 		  {
+ 		    /* Every address can be reloaded to fit.  */
+ 		    allows_addr = 1;
+ 		    if (address_operand (op, GET_MODE (op)))
+ 		      win = 1;
+ 		    /* We know this operand is an address, so we want it to be
+ 		       allocated to a register that can be the base of an
+ 		       address, ie BASE_REG_CLASS.  */
+ 		    classes[i]
+ 		      = reg_class_subunion[(int) classes[i]]
+ 		        [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ 		  }
  #endif
  		break;
  	      }
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.187
diff -c -p -r1.187 reload.c
*** gcc/reload.c	23 Jul 2002 20:51:00 -0000	1.187
--- gcc/reload.c	12 Aug 2002 22:01:40 -0000
*************** find_reloads (insn, replace, ind_levels,
*** 2641,2647 ****
        if (*constraints[i] == 0)
  	/* Ignore things like match_operator operands.  */
  	;
!       else if (constraints[i][0] == 'p')
  	{
  	  find_reloads_address (VOIDmode, (rtx*) 0,
  				recog_data.operand[i],
--- 2641,2648 ----
        if (*constraints[i] == 0)
  	/* Ignore things like match_operator operands.  */
  	;
!       else if (constraints[i][0] == 'p'
! 	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
  	{
  	  find_reloads_address (VOIDmode, (rtx*) 0,
  				recog_data.operand[i],
*************** find_reloads (insn, replace, ind_levels,
*** 3222,3227 ****
--- 3223,3271 ----
  		if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
  		  {
  #ifdef EXTRA_CONSTRAINT
+ 		    if (EXTRA_MEMORY_CONSTRAINT (c))
+ 		      {
+ 			if (force_reload)
+ 			  break;
+ 		        if (EXTRA_CONSTRAINT (operand, c))
+ 		          win = 1;
+ 			/* If the address was already reloaded,
+ 			   we win as well.  */
+ 			if (GET_CODE (operand) == MEM && address_reloaded[i])
+ 			  win = 1;
+ 			/* Likewise if the address will be reloaded because
+ 			   reg_equiv_address is nonzero.  For reg_equiv_mem
+ 			   we have to check.  */
+ 		        if (GET_CODE (operand) == REG
+ 			    && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ 			    && reg_renumber[REGNO (operand)] < 0
+ 			    && ((reg_equiv_mem[REGNO (operand)] != 0
+ 			         && EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
+ 			        || (reg_equiv_address[REGNO (operand)] != 0)))
+ 			  win = 1;
+ 
+ 			/* If we didn't already win, we can reload
+ 			   constants via force_const_mem, and other
+ 			   MEMs by reloading the address like for 'o'.  */
+ 			if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
+ 			    || GET_CODE (operand) == MEM)
+ 			  badop = 0;
+ 			constmemok = 1;
+ 			offmemok = 1;
+ 			break;
+ 		      }
+ 		    if (EXTRA_ADDRESS_CONSTRAINT (c))
+ 		      {
+ 		        if (EXTRA_CONSTRAINT (operand, c))
+ 		          win = 1;
+ 
+ 			/* If we didn't already win, we can reload
+ 			   the address into a base register.  */
+ 			this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ 			badop = 0;
+ 			break;
+ 		      }
+ 
  		    if (EXTRA_CONSTRAINT (operand, c))
  		      win = 1;
  #endif
*************** alternative_allows_memconst (constraint,
*** 4291,4297 ****
    /* Scan the requested alternative for 'm' or 'o'.
       If one of them is present, this alternative accepts memory constants.  */
    while ((c = *constraint++) && c != ',' && c != '#')
!     if (c == 'm' || c == 'o')
        return 1;
    return 0;
  }
--- 4335,4341 ----
    /* Scan the requested alternative for 'm' or 'o'.
       If one of them is present, this alternative accepts memory constants.  */
    while ((c = *constraint++) && c != ',' && c != '#')
!     if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
        return 1;
    return 0;
  }
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.351
diff -c -p -r1.351 reload1.c
*** gcc/reload1.c	30 Jul 2002 16:42:05 -0000	1.351
--- gcc/reload1.c	12 Aug 2002 22:01:46 -0000
*************** maybe_fix_stack_asms ()
*** 1380,1387 ****
  		  break;
  
  		default:
! 		  cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
! 
  		}
  	    }
  	}
--- 1380,1391 ----
  		  break;
  
  		default:
! 		  if (EXTRA_ADDRESS_CONSTRAINT (c))
! 		    cls = (int) reg_class_subunion[cls]
! 		      [(int) MODE_BASE_REG_CLASS (VOIDmode)];
! 		  else
! 		    cls = (int) reg_class_subunion[cls]
! 		      [(int) REG_CLASS_FROM_LETTER (c)];
  		}
  	    }
  	}
Index: gcc/stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.268
diff -c -p -r1.268 stmt.c
*** gcc/stmt.c	5 Aug 2002 18:46:33 -0000	1.268
--- gcc/stmt.c	12 Aug 2002 22:01:51 -0000
*************** parse_output_constraint (constraint_p, o
*** 1252,1257 ****
--- 1252,1261 ----
  	if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
  	  *allows_reg = true;
  #ifdef EXTRA_CONSTRAINT
+ 	else if (EXTRA_ADDRESS_CONSTRAINT (*p))
+ 	  *allows_reg = true;
+ 	else if (EXTRA_MEMORY_CONSTRAINT (*p))
+ 	  *allows_mem = true;
  	else
  	  {
  	    /* Otherwise we can't assume anything about the nature of
*************** parse_input_constraint (constraint_p, in
*** 1377,1382 ****
--- 1381,1390 ----
  	if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
  	  *allows_reg = true;
  #ifdef EXTRA_CONSTRAINT
+ 	else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
+ 	  *allows_reg = true;
+ 	else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
+ 	  *allows_mem = true;
  	else
  	  {
  	    /* Otherwise we can't assume anything about the nature of

-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-08-14 10:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-14  3:15 [RFC][PATCH] Support multiple variants of memory addresses Ulrich Weigand
  -- strict thread matches above, loose matches on Subject: below --
2002-08-12 15:32 Ulrich Weigand
2002-08-12 16:30 ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).