mn10300.c: Include tm-constrs.h.
authorNick Clifton <nickc@redhat.com>
Tue, 15 Feb 2011 17:09:39 +0000 (17:09 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Tue, 15 Feb 2011 17:09:39 +0000 (17:09 +0000)
* config/mn10300/mn10300.c: Include tm-constrs.h.
(struct liw_data): New data structure describing an LIW candidate
instruction.
(extract_bundle): Use struct liw_data.  Allow small integer
operands for some instructions.
(check_liw_constraints): Use struct liw_data.  Remove swapped
parameter.  Add comments describing the checks.  Fix bug when
assigning the source of liw1 to the source of liw2.
(liw_candidate): Delete.  Code moved into extract_bundle.
(mn10300_bundle_liw): Use struct liw_data.  Check constraints
before swapping.
* config/mn10300/predicates.md (liw_operand): New predicate.
Allows registers and small integer constants.
* config/mn10300/constraints.md (O): New constraint.  Accetps
integers in the range -8 to +7 inclusive.
* config/mn10300/mn10300.md (movesi_internal): Add an alternative
for moving a small integer into a register.  Give this alternative
LIW attributes.
(addsi3, subsi3, cmpsi, lshrsi3, ashrsi3): Likewise.
(ashlsi3): Likewise, plus give LIW attributes to the alternatives
using the J,K,L and M constraints,
(liw): Remove SI mode on second operands to allow for HI and QI
mode values.
(cmp_liw, liw_cmp): Likewise.  Plus fix order of operands in the
instruction.

From-SVN: r170182

gcc/ChangeLog
gcc/config/mn10300/constraints.md
gcc/config/mn10300/mn10300.c
gcc/config/mn10300/mn10300.md
gcc/config/mn10300/predicates.md

index 8f4f569d02463528ecf76026b1c98b0d544b7466..a6d81d03550c18ec22bd7c6d7ee7273f4dd1bdb9 100644 (file)
@@ -1,3 +1,31 @@
+2011-02-15  Nick Clifton  <nickc@redhat.com>
+
+       * config/mn10300/mn10300.c: Include tm-constrs.h.
+       (struct liw_data): New data structure describing an LIW candidate
+       instruction.
+       (extract_bundle): Use struct liw_data.  Allow small integer
+       operands for some instructions.
+       (check_liw_constraints): Use struct liw_data.  Remove swapped
+       parameter.  Add comments describing the checks.  Fix bug when
+       assigning the source of liw1 to the source of liw2.
+       (liw_candidate): Delete.  Code moved into extract_bundle.
+       (mn10300_bundle_liw): Use struct liw_data.  Check constraints
+       before swapping.
+       * config/mn10300/predicates.md (liw_operand): New predicate.
+       Allows registers and small integer constants.
+       * config/mn10300/constraints.md (O): New constraint.  Accetps
+       integers in the range -8 to +7 inclusive.
+       * config/mn10300/mn10300.md (movesi_internal): Add an alternative
+       for moving a small integer into a register.  Give this alternative
+       LIW attributes.
+       (addsi3, subsi3, cmpsi, lshrsi3, ashrsi3): Likewise.
+       (ashlsi3): Likewise, plus give LIW attributes to the alternatives
+       using the J,K,L and M constraints,
+       (liw): Remove SI mode on second operands to allow for HI and QI
+       mode values.
+       (cmp_liw, liw_cmp): Likewise.  Plus fix order of operands in the
+       instruction.
+
 2011-02-15  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR middle-end/47725
index a4816c1e20cb926681dffbdbcc11f2c5e1d54912..c8ee2d4e2d960e871edba3539ce60e3ea481c0d9 100644 (file)
        (ior (match_test "ival == 255")
            (match_test "ival == 65535"))))
 
+(define_constraint "O"
+  "An integer between -8 and +7 inclusive."
+  (and (match_code "const_int")
+       (and (match_test "ival >= -8")
+           (match_test "ival <=  7"))))
+
 ;; Floating-point constraints
 (define_constraint "G"
   "Floating-point zero."
index 5ff8852c5f7314fdd002823855802fddf0394b75..0b68f2d3e858a4560cbb0af51cec4acf8a3ed06b 100644 (file)
@@ -40,6 +40,7 @@
 #include "obstack.h"
 #include "diagnostic-core.h"
 #include "tm_p.h"
+#include "tm-constrs.h"
 #include "target.h"
 #include "target-def.h"
 #include "df.h"
@@ -2945,91 +2946,143 @@ mn10300_split_and_operand_count (rtx op)
     }
 }
 \f
-/* Extract operands and (if requested) the LIW op type from the insn.
-   Returns false if the insn can't be bundled.  */
+struct liw_data
+{
+  enum attr_liw slot;
+  enum attr_liw_op op;
+  rtx dest;
+  rtx src;
+};
+
+/* Decide if the given insn is a candidate for LIW bundling.  If it is then
+   extract the operands and LIW attributes from the insn and use them to fill
+   in the liw_data structure.  Return true upon success or false if the insn
+   cannot be bundled.  */
 
 static bool
-extract_bundle (rtx insn, rtx * ops, enum attr_liw_op * plop)
+extract_bundle (rtx insn, struct liw_data * pdata)
 {
-  enum attr_liw_op lop;
-  rtx p, s;
+  bool allow_consts = true;
+  rtx p,s;
 
+  gcc_assert (pdata != NULL);
+
+  if (insn == NULL_RTX)
+    return false;
+  /* Make sure that we are dealing with a simple SET insn.  */
   p = single_set (insn);
+  if (p == NULL_RTX)
+    return false;
+
+  /* Make sure that it could go into one of the LIW pipelines.  */
+  pdata->slot = get_attr_liw (insn);
+  if (pdata->slot == LIW_BOTH)
+    return false;
+
+  pdata->op = get_attr_liw_op (insn);
+
   s = SET_SRC (p);
-  lop = get_attr_liw_op (insn);
-  if (plop != NULL)
-    * plop = lop;
 
-  switch (lop)
+  switch (pdata->op)
     {
     case LIW_OP_MOV:
-      ops[0] = SET_DEST (p);
-      ops[1] = SET_SRC (p);
+      pdata->dest = SET_DEST (p);
+      pdata->src = SET_SRC (p);
       break;
     case LIW_OP_CMP:
-      ops[0] = XEXP (SET_SRC (p), 0);
-      ops[1] = XEXP (SET_SRC (p), 1);
+      pdata->dest = XEXP (SET_SRC (p), 0);
+      pdata->src = XEXP (SET_SRC (p), 1);
       break;
     case LIW_OP_NONE:
       return false;
+    case LIW_OP_AND:
+    case LIW_OP_OR:
+    case LIW_OP_XOR:
+      /* The AND, OR and XOR long instruction words only accept register arguments.  */
+      allow_consts = false;
+      /* Fall through.  */
     default:
-      ops[0] = SET_DEST (p);
-      ops[1] = XEXP (SET_SRC (p), 1);
+      pdata->dest = SET_DEST (p);
+      pdata->src = XEXP (SET_SRC (p), 1);
       break;
     }
 
-  return REG_P (ops[0]) && REG_P (ops[1]);
+  if (! REG_P (pdata->dest))
+    return false;
+
+  if (REG_P (pdata->src))
+    return true;
+
+  return allow_consts && satisfies_constraint_O (pdata->src);
 }
 
-/* Look for conflicts in the operands used in
-   the potential bundling of the two insns.  */
+/* Make sure that it is OK to execute LIW1 and LIW2 in parallel.  GCC generated
+   the instructions with the assumption that LIW1 would be executed before LIW2
+   so we must check for overlaps between their sources and destinations.  */
 
 static bool
-check_liw_constraints (rtx ops[4],
-                      enum attr_liw_op op1,
-                      enum attr_liw_op op2,
-                      bool swapped)
-{
-  /* Look for the two destination registers being the same.  This is OK if
-     the first op is a comparison op, since it will compare the value prior
-     to the completion of the second op.  */
-  if (REGNO (ops[0]) == REGNO (ops[2])
-      && ( (! swapped && op1 != LIW_OP_CMP)
-         || (swapped && op2 != LIW_OP_CMP)))
+check_liw_constraints (struct liw_data * pliw1, struct liw_data * pliw2)
+{
+  /* Check for slot conflicts.  */
+  if (pliw2->slot == pliw1->slot && pliw1->slot != LIW_EITHER)
     return false;
 
-  /* Look for the source of the second op being the destination of the first op.
-     Nomrally this will prevent the bundling since GCC has generated sequential
-     operations and the LIW opcodes are executed in parallel.  But if the first
-     opcode is a MOV, we can copy its source to the second ops source.  */
-  if (swapped)
-    return REGNO (ops[1]) != REGNO (ops[2]);
+  /* If either operation is a compare, then "dest" is really an input; the real
+     destination is CC_REG.  So these instructions need different checks.  */
+
+  /* Changing "CMP ; OP" into "CMP | OP" is OK because the comparison will
+     check its values prior to any changes made by OP.  */
+  if (pliw1->op == LIW_OP_CMP)
+    {
+      /* Two sequential comparisons means dead code, which ought to 
+         have been eliminated given that bundling only happens with
+         optimization.  We cannot bundle them in any case.  */
+      gcc_assert (pliw1->op != pliw2->op);
+      return true;
+    }
 
-  if (REGNO (ops[3]) == REGNO (ops[0]))
+  /* Changing "OP ; CMP" into "OP | CMP" does not work if the value being compared
+     is the destination of OP, as the CMP will look at the old value, not the new
+     one.  */
+  if (pliw2->op == LIW_OP_CMP)
     {
-      if (op1 == LIW_OP_MOV)
+      if (REGNO (pliw2->dest) == REGNO (pliw1->dest))
+       return false;
+
+      if (REG_P (pliw2->src))
+       return REGNO (pliw2->src) != REGNO (pliw1->dest);
+
+      return true;
+    }
+
+  /* Changing "OP1 ; OP2" into "OP1 | OP2" does not work if they both write to the
+     same destination register.  */
+  if (REGNO (pliw2->dest) == REGNO (pliw1->dest))
+    return false;
+
+  /* Changing "OP1 ; OP2" into "OP1 | OP2" generally does not work if the destination
+     of OP1 is the source of OP2.  The exception is when OP1 is a MOVE instruction when
+     we can replace the source in OP2 with the source of OP1.  */
+  if (REG_P (pliw2->src) && REGNO (pliw2->src) == REGNO (pliw1->dest))
+    {
+      if (pliw1->op == LIW_OP_MOV && REG_P (pliw1->src))
        {
-         ops[3] = ops[1];
+         if (! REG_P (pliw1->src)
+             && (pliw2->op == LIW_OP_AND
+                 || pliw2->op == LIW_OP_OR
+                 || pliw2->op == LIW_OP_XOR))
+           return false;
+                 
+         pliw2->src = pliw1->src;
          return true;
        }
       return false;
     }
 
+  /* Everything else is OK.  */
   return true;
 }
 
-/* Decide if the given insn is a candidate for LIW bundling.  For now we just
-   check that the insn has an LIW attribute.  Later on we check operand
-   constraints and such.  */
-
-static bool
-liw_candidate (rtx insn)
-{
-  return insn != NULL_RTX
-    && single_set (insn) != NULL_RTX
-    && get_attr_liw (insn) != LIW_BOTH;
-}
-
 /* Combine pairs of insns into LIW bundles.  */
 
 static void
@@ -3039,61 +3092,41 @@ mn10300_bundle_liw (void)
 
   for (r = get_insns (); r != NULL_RTX; r = next_nonnote_nondebug_insn (r))
     {
-      rtx insn1, insn2, ops[4];
-      enum attr_liw liw1, liw2;
-      enum attr_liw_op op1, op2;
-      bool swapped = false;
+      rtx insn1, insn2;
+      struct liw_data liw1, liw2;
 
       insn1 = r;
-      if (! liw_candidate (insn1))
+      if (! extract_bundle (insn1, & liw1))
        continue;
 
       insn2 = next_nonnote_nondebug_insn (insn1);
-      if (! liw_candidate (insn2))
+      if (! extract_bundle (insn2, & liw2))
        continue;
 
-      liw1 = get_attr_liw (insn1);
-      if (liw1 == LIW_BOTH)
-       continue;
-      liw2 = get_attr_liw (insn2);
-      if (liw2 == LIW_BOTH)
-       continue;
-      if (liw2 == liw1 && liw1 != LIW_EITHER)
+      /* Check for source/destination overlap.  */
+      if (! check_liw_constraints (& liw1, & liw2))
        continue;
 
-      /* The scheduler always groups the insns correctly, but not
-        always in sequence.  So, we can do a naive check and expect
-        it to work.  */
-      if (liw1 == LIW_OP2 || liw2 == LIW_OP1)
+      if (liw1.slot == LIW_OP2 || liw2.slot == LIW_OP1)
        {
-         rtx r;
-         enum attr_liw lt;
-
-         r = insn1;
-         insn1 = insn2;
-         insn2 = r;
-         lt = liw1;
+         struct liw_data temp;
+         
+         temp = liw1;
          liw1 = liw2;
-         liw2 = lt;
-         swapped = true;
+         liw2 = temp;
        }
 
-      if (! extract_bundle (insn1, ops, & op1))
-       continue;
-      if (! extract_bundle (insn2, ops + 2, & op2))
-       continue;
-      if (! check_liw_constraints (ops, op1, op2, swapped))
-       continue;
-
       delete_insn (insn2);
 
-      if (op1 == LIW_OP_CMP)
-       insn2 = gen_cmp_liw (ops[2], ops[3], ops[0], ops[1], GEN_INT (op2));
-      else if (op2 == LIW_OP_CMP)
-       insn2 = gen_liw_cmp (ops[0], ops[1], ops[2], ops[3], GEN_INT (op1));
+      if (liw1.op == LIW_OP_CMP)
+       insn2 = gen_cmp_liw (liw2.dest, liw2.src, liw1.dest, liw1.src,
+                            GEN_INT (liw2.op));
+      else if (liw2.op == LIW_OP_CMP)
+       insn2 = gen_liw_cmp (liw1.dest, liw1.src, liw2.dest, liw2.src,
+                            GEN_INT (liw1.op));
       else
-       insn2 = gen_liw (ops[0], ops[2], ops[1], ops[3],
-                        GEN_INT (op1), GEN_INT (op2));
+       insn2 = gen_liw (liw1.dest, liw2.dest, liw1.src, liw2.src,
+                        GEN_INT (liw1.op), GEN_INT (liw2.op));
 
       insn2 = emit_insn_after (insn2, insn1);
       delete_insn (insn1);
index e8d2ae1194dc829821558e53e436f3b14074536d..3d8e914705250514b23179c7d08f33200cc23e1e 100644 (file)
 
 (define_insn "*movsi_internal"
   [(set (match_operand:SI 0 "nonimmediate_operand"
-                         "=r,r,r,m,r, A,*y,*y,*z,*d")
+                         "=r,r,r,r,m,r, A,*y,*y,*z,*d")
        (match_operand:SI 1 "general_operand"
-                         " 0,i,r,r,m,*y, A, i,*d,*z"))]
+                         " 0,O,i,r,r,m,*y, A, i,*d,*z"))]
   "register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode)"
 {
     {
     case 0:
       return "";
-    case 1: /* imm-reg*/
+    case 1: /* imm-reg.  */
+    case 2: 
       /* See movhi for a discussion of sizes for 8-bit movu.  Note that the
         24-bit movu is 6 bytes, which is the same size as the full 32-bit
         mov form for An and Dn.  So again movu is only a win for Rn.  */
            return "movu %1,%0";
        }
       /* FALLTHRU */
-    case 2:  /* reg-reg */
-    case 3:  /* reg-mem */
-    case 4:  /* mem-reg */
-    case 5:  /* sp-reg */
-    case 6:  /* reg-sp */
-    case 7:  /* imm-sp */
-    case 8:  /* reg-mdr */
-    case 9:  /* mdr-reg */
+    case 3:  /* reg-reg */
+    case 4:  /* reg-mem */
+    case 5:  /* mem-reg */
+    case 6:  /* sp-reg */
+    case 7:  /* reg-sp */
+    case 8:  /* imm-sp */
+    case 9:  /* reg-mdr */
+    case 10:  /* mdr-reg */
       return "mov %1,%0";
     default:
       gcc_unreachable ();
     }
 }
-  [(set_attr "isa" "*,*,*,*,*,*,*,am33,*,*")
-   (set_attr "liw" "*,*,either,*,*,*,*,*,*,*")
+  [(set_attr "isa" "*,*,*,*,*,*,*,*,am33,*,*")
+   (set_attr "liw" "*,either,*,either,*,*,*,*,*,*,*")
    (set_attr "liw_op" "mov")
    (set_attr_alternative "timings"
         [(const_int 11)
+         (const_int 22)
          (const_int 22)
          (const_int 11)
          (if_then_else (eq_attr "cpu" "am34")
 ;; ----------------------------------------------------------------------
 
 (define_insn "addsi3"
-  [(set (match_operand:SI          0 "register_operand"  "=r,r,!*y,!r")
-       (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,  0, r")
-                (match_operand:SI 2 "nonmemory_operand"  "r,i,  i, r")))
+  [(set (match_operand:SI          0 "register_operand"  "=r,r,r,!*y,!r")
+       (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,  0, r")
+                (match_operand:SI 2 "nonmemory_operand"  "r,O,i,  i, r")))
    (clobber (reg:CC CC_REG))]
   ""
   { return mn10300_output_add (operands, false); }
-  [(set_attr "timings" "11,11,11,22")
-   (set_attr "liw" "either,*,*,*")
+  [(set_attr "timings" "11,11,11,11,22")
+   (set_attr "liw" "either,either,*,*,*")
    (set_attr "liw_op" "add")]
 )
 
 ;; ----------------------------------------------------------------------
 
 (define_insn "subsi3"
-  [(set (match_operand:SI           0 "register_operand"  "=r,r,r")
-       (minus:SI (match_operand:SI 1 "register_operand"   "0,0,r")
-                 (match_operand:SI 2 "nonmemory_operand"  "r,i,r")))
+  [(set (match_operand:SI           0 "register_operand"  "=r,r,r,r")
+       (minus:SI (match_operand:SI 1 "register_operand"   "0,0,0,r")
+                 (match_operand:SI 2 "nonmemory_operand"  "r,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
+   sub %2,%0
    sub %2,%0
    sub %2,%0
    sub %2,%1,%0"
-  [(set_attr "isa" "*,*,am33")
-   (set_attr "liw" "either,*,*")
+  [(set_attr "isa" "*,*,*,am33")
+   (set_attr "liw" "either,either,*,*")
    (set_attr "liw_op" "sub")
-   (set_attr "timings" "11,11,22")]
+   (set_attr "timings" "11,11,11,22")]
 )
 
 (define_insn "*subsi3_flags"
 
 (define_insn "*cmpsi"
   [(set (reg CC_REG)
-       (compare (match_operand:SI 0 "register_operand"  "r,r")
-                (match_operand:SI 1 "nonmemory_operand" "r,i")))]
+       (compare (match_operand:SI 0 "register_operand"  "r,r,r")
+                (match_operand:SI 1 "nonmemory_operand" "r,O,i")))]
   "reload_completed"
 {
   /* The operands of CMP must be distinct registers.  In the case where
 }
   [(set_attr_alternative "timings"
      [(if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))
+      (if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))
       (if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))])
-   (set_attr "liw" "either,*")
+   (set_attr "liw" "either,either,*")
    (set_attr "liw_op" "cmp")]
 )
 
 ;; ----------------------------------------------------------------------
 
 (define_insn "ashlsi3"
-  [(set (match_operand:SI  0 "register_operand"   "=r,D,d,d,D,D,r")
+  [(set (match_operand:SI  0 "register_operand"   "=r,D,d,d,D,D,D,r")
        (ashift:SI
-         (match_operand:SI 1 "register_operand"  " 0,0,0,0,0,0,r")
-         (match_operand:QI 2 "nonmemory_operand" " J,K,M,L,D,i,r")))
+         (match_operand:SI 1 "register_operand"  " 0,0,0,0,0,0,0,r")
+         (match_operand:QI 2 "nonmemory_operand" " J,K,M,L,D,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
    asl2 %0\;asl2 %0
    asl %S2,%0
    asl %S2,%0
+   asl %S2,%0
    asl %2,%1,%0"
-  [(set_attr "isa" "*,*,*,*,*,*,am33")
-   (set_attr "liw" "*,*,*,*,op2,*,*")
+  [(set_attr "isa" "*,*,*,*,*,*,*,am33")
+   (set_attr "liw" "op2,op2,op2,op2,op2,op2,*,*")
    (set_attr "liw_op" "asl")
-   (set_attr "timings" "11,11,22,22,11,11,11")]
+   (set_attr "timings" "11,11,22,22,11,11,11,11")]
 )
 
 (define_insn "lshrsi3"
-  [(set (match_operand:SI  0 "register_operand"  "=D,D,r")
+  [(set (match_operand:SI  0 "register_operand"  "=D,D,D,r")
        (lshiftrt:SI
-         (match_operand:SI 1 "register_operand"  "0,0,r")
-         (match_operand:QI 2 "nonmemory_operand" "D,i,r")))
+         (match_operand:SI 1 "register_operand"  "0,0,0,r")
+         (match_operand:QI 2 "nonmemory_operand" "D,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
+   lsr %S2,%0
    lsr %S2,%0
    lsr %S2,%0
    lsr %2,%1,%0"
-  [(set_attr "isa" "*,*,am33")
-   (set_attr "liw" "op2,*,*")
+  [(set_attr "isa" "*,*,*,am33")
+   (set_attr "liw" "op2,op2,*,*")
    (set_attr "liw_op" "lsr")]
 )
 
 (define_insn "ashrsi3"
-  [(set (match_operand:SI  0 "register_operand"  "=D,D,r")
+  [(set (match_operand:SI  0 "register_operand"  "=D,D,D,r")
        (ashiftrt:SI
-         (match_operand:SI 1 "register_operand"  "0,0,r")
-         (match_operand:QI 2 "nonmemory_operand" "D,i,r")))
+         (match_operand:SI 1 "register_operand"  "0,0,0,r")
+         (match_operand:QI 2 "nonmemory_operand" "D,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
+   asr %S2,%0
    asr %S2,%0
    asr %S2,%0
    asr %2,%1,%0"
-  [(set_attr "isa" "*,*,am33")
-   (set_attr "liw" "op2,*,*")
+  [(set_attr "isa" "*,*,*,am33")
+   (set_attr "liw" "op2,op2,*,*")
    (set_attr "liw_op" "asr")]
 )
 
 (define_insn "liw"
   [(set (match_operand:SI             0 "register_operand" "=r")
        (unspec:SI [(match_dup 0)
-                    (match_operand:SI 2 "register_operand" "r")
+                    (match_operand    2 "liw_operand"       "rO")
                     (match_operand:SI 4 "const_int_operand" "")]
                    UNSPEC_LIW))
    (set (match_operand:SI             1 "register_operand" "=r")
         (unspec:SI [(match_dup 1)
-                    (match_operand    3 "register_operand" "r")
+                    (match_operand    3 "liw_operand"       "rO")
                     (match_operand:SI 5 "const_int_operand" "")]
                    UNSPEC_LIW))]
   "TARGET_ALLOW_LIW"
 (define_insn "cmp_liw"
   [(set (reg:CC CC_REG)
        (compare:CC (match_operand:SI 2 "register_operand" "r")
-                   (match_operand:SI 3 "register_operand" "r")))
+                   (match_operand    3 "liw_operand"      "rO")))
    (set (match_operand:SI             0 "register_operand" "=r")
         (unspec:SI [(match_dup 0)
-                    (match_operand    1 "register_operand" "r")
+                    (match_operand    1 "liw_operand"       "rO")
                     (match_operand:SI 4 "const_int_operand" "")]
                    UNSPEC_LIW))]
   "TARGET_ALLOW_LIW"
-  "cmp_%W4 %2, %3, %0, %1"
+  "cmp_%W4 %3, %2, %1, %0"
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 13) (const_int 12)))]
 )
 (define_insn "liw_cmp"
   [(set (match_operand:SI             0 "register_operand" "=r")
         (unspec:SI [(match_dup 0)
-                    (match_operand:SI 1 "register_operand" "r")
+                    (match_operand    1 "liw_operand"      "rO")
                     (match_operand:SI 4 "const_int_operand" "")]
                    UNSPEC_LIW))
    (set (reg:CC CC_REG)
        (compare:CC (match_operand:SI 2 "register_operand" "r")
-                   (match_operand:SI 3 "register_operand" "r")))]
+                   (match_operand    3 "liw_operand"      "rO")))]
   "TARGET_ALLOW_LIW"
-  "%W4_cmp %0, %1, %2, %3"
+  "%W4_cmp %1, %0, %3, %2"
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 13) (const_int 12)))]
 )
index 83169901648179ebc430bd521d91cdca025ad5e0..4c78c51e4634daa4edda2fbcf3e30030e96b306d 100644 (file)
@@ -63,3 +63,7 @@
 
 (define_predicate "CCZN_comparison_operator"
   (match_code "eq,ne,lt,ge"))
+
+(define_predicate "liw_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_test "satisfies_constraint_O (op)")))