Commit e3cba5e5 by Andreas Krebbel Committed by Andreas Krebbel

s390.c: (s390_swap_cmp): Look for conditional jumps if COND is NULL.

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.

From-SVN: r144466
parent c9e9e11f
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> 2009-02-26 Uros Bizjak <ubizjak@gmail.com>
* config/alpha/alpha.h (alpha_expand_mov): Return false if * config/alpha/alpha.h (alpha_expand_mov): Return false if
......
...@@ -9589,21 +9589,6 @@ s390_optimize_prologue (void) ...@@ -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 /* Returns 1 if INSN reads the value of REG for purposes not related
to addressing of memory, and 0 otherwise. */ to addressing of memory, and 0 otherwise. */
static int static int
...@@ -9613,6 +9598,71 @@ s390_non_addr_reg_read_p (rtx reg, rtx insn) ...@@ -9613,6 +9598,71 @@ s390_non_addr_reg_read_p (rtx reg, rtx insn)
&& !reg_used_in_mem_p (REGNO (reg), PATTERN (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 /* On z10, instructions of the compare-and-branch family have the
property to access the register occurring as second operand with property to access the register occurring as second operand with
...@@ -9622,7 +9672,7 @@ s390_non_addr_reg_read_p (rtx reg, rtx insn) ...@@ -9622,7 +9672,7 @@ s390_non_addr_reg_read_p (rtx reg, rtx insn)
pipeline recycles, thereby causing significant performance decline. pipeline recycles, thereby causing significant performance decline.
This function locates such situations and exchanges the two This function locates such situations and exchanges the two
operands of the compare. */ operands of the compare. */
static void static void
s390_z10_optimize_cmp (void) s390_z10_optimize_cmp (void)
{ {
rtx insn, prev_insn, next_insn; rtx insn, prev_insn, next_insn;
...@@ -9630,54 +9680,79 @@ s390_z10_optimize_cmp (void) ...@@ -9630,54 +9680,79 @@ s390_z10_optimize_cmp (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{ {
rtx cond, *op0, *op1;
if (!INSN_P (insn) || INSN_CODE (insn) <= 0) if (!INSN_P (insn) || INSN_CODE (insn) <= 0)
continue; 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. */ if (!pattern
pattern = single_set (insn); || SET_DEST (pattern) != pc_rtx
gcc_assert (GET_CODE (pattern) == SET); || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE)
jump_expr = XEXP (pattern, 1); continue;
gcc_assert (GET_CODE (jump_expr) == IF_THEN_ELSE);
cond = XEXP (jump_expr, 0);
op0 = XEXP (cond, 0);
op1 = XEXP (cond, 1);
/* Swap the COMPARE´s arguments and its mask if there is a cond = XEXP (SET_SRC (pattern), 0);
conflicting access in the previous insn. */ op0 = &XEXP (cond, 0);
prev_insn = PREV_INSN (insn); op1 = &XEXP (cond, 1);
if (prev_insn != NULL_RTX && INSN_P (prev_insn) }
&& reg_referenced_p (op1, PATTERN (prev_insn))) else if (GET_CODE (PATTERN (insn)) == SET)
{ {
s390_swap_cmp (cond); rtx src, dest;
op0 = XEXP (cond, 0);
op1 = XEXP (cond, 1);
}
/* Check if there is a conflict with the next insn. If there /* Handle normal compare instructions. */
was no conflict with the previous insn, then swap the src = SET_SRC (PATTERN (insn));
COMPARE´s arguments and its mask. If we already swapped dest = SET_DEST (PATTERN (insn));
the operands, or if swapping them would cause a conflict
with the previous insn, issue a NOP after the COMPARE in if (!REG_P (dest)
order to separate the two instuctions. */ || !CC_REGNO_P (REGNO (dest))
next_insn = NEXT_INSN (insn); || GET_CODE (src) != COMPARE)
if (next_insn != NULL_RTX && INSN_P (next_insn) continue;
&& s390_non_addr_reg_read_p (op1, next_insn))
{ /* s390_swap_cmp will try to find the conditional
if (s390_non_addr_reg_read_p (op0, prev_insn)) jump when passing NULL_RTX as condition. */
{ cond = NULL_RTX;
if (REGNO(op1) == 0) op0 = &XEXP (src, 0);
emit_insn_after (gen_nop1 (), insn); op1 = &XEXP (src, 1);
else }
emit_insn_after (gen_nop (), insn); else
added_NOPs = 1; 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 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) ...@@ -9799,7 +9874,7 @@ s390_reorg (void)
/* Eliminate z10-specific pipeline recycles related to some compare /* Eliminate z10-specific pipeline recycles related to some compare
instructions. */ instructions. */
if (TARGET_Z10) if (s390_tune == PROCESSOR_2097_Z10)
s390_z10_optimize_cmp (); s390_z10_optimize_cmp ();
} }
......
...@@ -235,7 +235,6 @@ ...@@ -235,7 +235,6 @@
;; can immediately read the new value. ;; can immediately read the new value.
;; z10_fr: union of Z10_fwd and z10_rec. ;; z10_fr: union of Z10_fwd and z10_rec.
;; z10_c: second operand of instruction is a register and read with complemented bits. ;; 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. ;; An additional suffix A1, A3, or E1 indicates the respective AGI bypass.
...@@ -245,7 +244,7 @@ ...@@ -245,7 +244,7 @@
z10_fwd, z10_fwd_A1, z10_fwd_A3, z10_fwd_E1, z10_fwd, z10_fwd_A1, z10_fwd_A3, z10_fwd_E1,
z10_rec, z10_rec,
z10_fr, z10_fr_A3, z10_fr_E1, z10_fr, z10_fr_A3, z10_fr_E1,
z10_c, z10_cobra" z10_c"
(const_string "none")) (const_string "none"))
...@@ -774,7 +773,7 @@ ...@@ -774,7 +773,7 @@
cy\t%0,%1 cy\t%0,%1
#" #"
[(set_attr "op_type" "RR,RI,RIL,RX,RXY,SS") [(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 ; Compare (signed) instructions
...@@ -1043,7 +1042,7 @@ ...@@ -1043,7 +1042,7 @@
} }
[(set_attr "op_type" "RIE") [(set_attr "op_type" "RIE")
(set_attr "type" "branch") (set_attr "type" "branch")
(set_attr "z10prop" "z10_cobra,z10_super") (set_attr "z10prop" "z10_super_c,z10_super")
(set (attr "length") (set (attr "length")
(if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000)) (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
(const_int 6) (const_int 12)))]) ; 8 byte for cr/jg (const_int 6) (const_int 12)))]) ; 8 byte for cr/jg
...@@ -1071,7 +1070,7 @@ ...@@ -1071,7 +1070,7 @@
} }
[(set_attr "op_type" "RIE") [(set_attr "op_type" "RIE")
(set_attr "type" "branch") (set_attr "type" "branch")
(set_attr "z10prop" "z10_cobra,z10_super") (set_attr "z10prop" "z10_super_c,z10_super")
(set (attr "length") (set (attr "length")
(if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000)) (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_int 6) (const_int 12)))]) ; 8 byte for clr/jg
...@@ -7679,7 +7678,7 @@ ...@@ -7679,7 +7678,7 @@
(const_string "RR") (const_string "RX"))) (const_string "RR") (const_string "RX")))
(set_attr "type" "branch") (set_attr "type" "branch")
(set_attr "atype" "agen") (set_attr "atype" "agen")
(set_attr "z10prop" "z10_cobra")]) (set_attr "z10prop" "z10_c")])
(define_insn_and_split "doloop_di" (define_insn_and_split "doloop_di"
[(set (pc) [(set (pc)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment