2009-02-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Feb 2009 14:56:19 +0000 (14:56 +0000)
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Feb 2009 14:56:19 +0000 (14:56 +0000)
* gcc/config/s390/s390.c: (s390_swap_cmp): Look for conditional
jumps if COND is NULL.
(find_cond_jump): New function.
(s390_z10_optimize_cmp): Handling for reg-reg compares added.
* gcc/config/s390/s390.md: Remove z10_cobra attribute value.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@144466 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 9aef9cb..27ccf26 100644 (file)
@@ -1,3 +1,11 @@
+2009-02-27  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+       * gcc/config/s390/s390.c: (s390_swap_cmp): Look for conditional
+       jumps if COND is NULL.
+       (find_cond_jump): New function.
+       (s390_z10_optimize_cmp): Handling for reg-reg compares added.
+       * gcc/config/s390/s390.md: Remove z10_cobra attribute value.
+
 2009-02-26  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/alpha/alpha.h (alpha_expand_mov): Return false if
index 7ad230e..eb08828 100644 (file)
@@ -9589,21 +9589,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
@@ -9613,6 +9598,71 @@ s390_non_addr_reg_read_p (rtx reg, rtx insn)
     && !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
@@ -9622,7 +9672,7 @@ s390_non_addr_reg_read_p (rtx reg, rtx insn)
    pipeline recycles, thereby causing significant performance decline.
    This function locates such situations and exchanges the two
    operands of the compare.  */
-static void 
+static void
 s390_z10_optimize_cmp (void)
 {
   rtx insn, prev_insn, next_insn;
@@ -9630,54 +9680,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);
 
-         /* Extract the comparison´s 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);
+         if (!pattern
+             || SET_DEST (pattern) != pc_rtx
+             || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE)
+           continue;
 
-         /* Swap the COMPARE´s 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);
        }
     }
 
@@ -9799,7 +9874,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 3d628d8..7ecc3cc 100644 (file)
 ;;   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.
 
                         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"))
 
 
    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
 
 }
   [(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
 }
   [(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
                       (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)