Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c.orig	2009-11-20 13:52:33.000000000 +0100
+++ gcc/config/s390/s390.c	2009-11-20 13:52:34.000000000 +0100
@@ -9594,21 +9594,6 @@ s390_optimize_prologue (void)
     }
 }
 
-
-/* Exchange the two operands of COND, and swap its mask so that the
-   semantics does not change.  */
-static void
-s390_swap_cmp (rtx cond)
-{
-  enum rtx_code code = swap_condition (GET_CODE (cond));
-  rtx tmp = XEXP (cond, 0);
-
-  XEXP (cond, 0) = XEXP (cond, 1);
-  XEXP (cond, 1) = tmp;
-  PUT_CODE (cond, code);
-}
-
-
 /* Returns 1 if INSN reads the value of REG for purposes not related
    to addressing of memory, and 0 otherwise.  */
 static int
@@ -9618,6 +9603,71 @@ s390_non_addr_reg_read_p (rtx reg, rtx i
     && !reg_used_in_mem_p (REGNO (reg), PATTERN (insn));
 }
 
+/* Starting from INSN find_cond_jump looks downwards in the insn
+   stream for a single jump insn which is the last user of the
+   condition code set in INSN.  */
+static rtx
+find_cond_jump (rtx insn)
+{
+  for (; insn; insn = NEXT_INSN (insn))
+    {
+      rtx ite, cc;
+
+      if (LABEL_P (insn))
+	break;
+
+      if (!JUMP_P (insn))
+	{
+	  if (reg_mentioned_p (gen_rtx_REG (CCmode, CC_REGNUM), insn))
+	    break;
+	  continue;
+	}
+
+      /* This will be triggered by a return.  */
+      if (GET_CODE (PATTERN (insn)) != SET)
+	break;
+
+      gcc_assert (SET_DEST (PATTERN (insn)) == pc_rtx);
+      ite = SET_SRC (PATTERN (insn));
+
+      if (GET_CODE (ite) != IF_THEN_ELSE)
+	break;
+
+      cc = XEXP (XEXP (ite, 0), 0);
+      if (!REG_P (cc) || !CC_REGNO_P (REGNO (cc)))
+	break;
+
+      if (find_reg_note (insn, REG_DEAD, cc))
+	return insn;
+      break;
+    }
+
+  return NULL_RTX;
+}
+
+/* Swap the condition in COND and the operands in OP0 and OP1 so that
+   the semantics does not change.  If NULL_RTX is passed as COND the
+   function tries to find the conditional jump starting with INSN.  */
+static void
+s390_swap_cmp (rtx cond, rtx *op0, rtx *op1, rtx insn)
+{
+  rtx tmp = *op0;
+
+  if (cond == NULL_RTX)
+    {
+      rtx jump = find_cond_jump (NEXT_INSN (insn));
+      jump = jump ? single_set (jump) : NULL_RTX;
+
+      if (jump == NULL_RTX)
+	return;
+
+      cond = XEXP (XEXP (jump, 1), 0);
+    }
+
+  *op0 = *op1;
+  *op1 = tmp;
+  PUT_CODE (cond, swap_condition (GET_CODE (cond)));
+}
 
 /* On z10, instructions of the compare-and-branch family have the
    property to access the register occurring as second operand with
@@ -9635,54 +9685,79 @@ s390_z10_optimize_cmp (void)
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
+      rtx cond, *op0, *op1;
+
       if (!INSN_P (insn) || INSN_CODE (insn) <= 0)
 	continue;
 
-      if (get_attr_z10prop (insn) == Z10PROP_Z10_COBRA)
+      if (GET_CODE (PATTERN (insn)) == PARALLEL)
 	{
-	  rtx op0, op1, pattern, jump_expr, cond;
+	  /* Handle compare and branch and branch on count
+	     instructions.  */
+	  rtx pattern = single_set (insn);
+
+	  if (!pattern
+	      || SET_DEST (pattern) != pc_rtx
+	      || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE)
+	    continue;
 
-	  /* Extract the comparisons condition and its operands.  */
-	  pattern = single_set (insn);
-	  gcc_assert (GET_CODE (pattern) == SET);
-	  jump_expr = XEXP (pattern, 1);
-	  gcc_assert (GET_CODE (jump_expr) == IF_THEN_ELSE);
-	  cond = XEXP (jump_expr, 0);
-	  op0 = XEXP (cond, 0);
-	  op1 = XEXP (cond, 1);
-
-	  /* Swap the COMPAREs arguments and its mask if there is a
-	     conflicting access in the previous insn.  */
-	  prev_insn = PREV_INSN (insn);
-          if (prev_insn != NULL_RTX && INSN_P (prev_insn)
-              && reg_referenced_p (op1, PATTERN (prev_insn)))
-	    {
-	      s390_swap_cmp (cond);
-   	      op0 = XEXP (cond, 0);
-	      op1 = XEXP (cond, 1);
-	    }
+	  cond = XEXP (SET_SRC (pattern), 0);
+	  op0 = &XEXP (cond, 0);
+	  op1 = &XEXP (cond, 1);
+	}
+      else if (GET_CODE (PATTERN (insn)) == SET)
+	{
+	  rtx src, dest;
 
-	  /* Check if there is a conflict with the next insn. If there
-	     was no conflict with the previous insn, then swap the
-	     COMPARE´s arguments and its mask.  If we already swapped
-	     the operands, or if swapping them would cause a conflict
-	     with the previous insn, issue a NOP after the COMPARE in
-	     order to separate the two instuctions.  */
-	  next_insn = NEXT_INSN (insn);
-          if (next_insn != NULL_RTX && INSN_P (next_insn)
-              && s390_non_addr_reg_read_p (op1, next_insn))
-            {
-	      if (s390_non_addr_reg_read_p (op0, prev_insn))
-		{
-                  if (REGNO(op1) == 0)
-		    emit_insn_after (gen_nop1 (), insn);
-                  else
-		    emit_insn_after (gen_nop (), insn);
-                  added_NOPs = 1;
-                }
+	  /* Handle normal compare instructions.  */
+	  src = SET_SRC (PATTERN (insn));
+	  dest = SET_DEST (PATTERN (insn));
+
+	  if (!REG_P (dest)
+	      || !CC_REGNO_P (REGNO (dest))
+	      || GET_CODE (src) != COMPARE)
+	    continue;
+
+	  /* s390_swap_cmp will try to find the conditional
+	     jump when passing NULL_RTX as condition.  */
+	  cond = NULL_RTX;
+	  op0 = &XEXP (src, 0);
+	  op1 = &XEXP (src, 1);
+	}
+      else
+	continue;
+
+      if (!REG_P (*op0) || !REG_P (*op1))
+	continue;
+
+      /* Swap the COMPARE arguments and its mask if there is a
+	 conflicting access in the previous insn.  */
+      prev_insn = PREV_INSN (insn);
+      if (prev_insn != NULL_RTX && INSN_P (prev_insn)
+	  && reg_referenced_p (*op1, PATTERN (prev_insn)))
+	s390_swap_cmp (cond, op0, op1, insn);
+
+      /* Check if there is a conflict with the next insn. If there
+	 was no conflict with the previous insn, then swap the
+	 COMPARE arguments and its mask.  If we already swapped
+	 the operands, or if swapping them would cause a conflict
+	 with the previous insn, issue a NOP after the COMPARE in
+	 order to separate the two instuctions.  */
+      next_insn = NEXT_INSN (insn);
+      if (next_insn != NULL_RTX && INSN_P (next_insn)
+	  && s390_non_addr_reg_read_p (*op1, next_insn))
+	{
+	  if (prev_insn != NULL_RTX && INSN_P (prev_insn)
+	      && s390_non_addr_reg_read_p (*op0, prev_insn))
+	    {
+	      if (REGNO (*op1) == 0)
+		emit_insn_after (gen_nop1 (), insn);
 	      else
- 	        s390_swap_cmp (cond);
+		emit_insn_after (gen_nop (), insn);
+	      added_NOPs = 1;
 	    }
+	  else
+	    s390_swap_cmp (cond, op0, op1, insn);
 	}
     }
 
@@ -9807,7 +9882,7 @@ s390_reorg (void)
 
   /* Eliminate z10-specific pipeline recycles related to some compare
      instructions.  */
-  if (TARGET_Z10)
+  if (s390_tune == PROCESSOR_2097_Z10)
     s390_z10_optimize_cmp ();
 }
 
Index: gcc/config/s390/s390.md
===================================================================
--- gcc/config/s390/s390.md.orig	2009-11-20 13:52:33.000000000 +0100
+++ gcc/config/s390/s390.md	2009-11-20 13:52:34.000000000 +0100
@@ -232,7 +232,6 @@
 ;;   can immediately read the new value.
 ;; z10_fr: union of Z10_fwd and z10_rec.
 ;; z10_c: second operand of instruction is a register and read with complemented bits.
-;; z10_cobra: its a compare and branch instruction
 ;;
 ;; An additional suffix A1, A3, or E1 indicates the respective AGI bypass.
 
@@ -242,7 +241,7 @@
                         z10_fwd, z10_fwd_A1, z10_fwd_A3, z10_fwd_E1,
                         z10_rec,
                         z10_fr, z10_fr_A3, z10_fr_E1,
-                        z10_c, z10_cobra"
+                        z10_c"
              (const_string "none"))
 
 
@@ -771,7 +770,7 @@
    cy\t%0,%1
    #"
   [(set_attr "op_type" "RR,RI,RIL,RX,RXY,SS")
-   (set_attr "z10prop" "z10_super,z10_super,z10_super,z10_super,z10_super,*")])
+   (set_attr "z10prop" "z10_super_c,z10_super,z10_super,z10_super,z10_super,*")])
 
 ; Compare (signed) instructions
 
@@ -1040,7 +1039,7 @@
 }
   [(set_attr "op_type" "RIE")
    (set_attr "type"    "branch")
-   (set_attr "z10prop" "z10_cobra,z10_super")
+   (set_attr "z10prop" "z10_super_c,z10_super")
    (set (attr "length")
         (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
                       (const_int 6) (const_int 12)))]) ; 8 byte for cr/jg
@@ -1068,7 +1067,7 @@
 }
   [(set_attr "op_type" "RIE")
    (set_attr "type"    "branch")
-   (set_attr "z10prop" "z10_cobra,z10_super")
+   (set_attr "z10prop" "z10_super_c,z10_super")
    (set (attr "length")
         (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
                       (const_int 6) (const_int 12)))]) ; 8 byte for clr/jg
@@ -7676,7 +7675,7 @@
                       (const_string "RR") (const_string "RX")))
    (set_attr "type"  "branch")
    (set_attr "atype" "agen")
-   (set_attr "z10prop"  "z10_cobra")])
+   (set_attr "z10prop"  "z10_c")])
 
 (define_insn_and_split "doloop_di"
   [(set (pc)
