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>
* config/alpha/alpha.h (alpha_expand_mov): Return false if
......
......@@ -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 ();
}
......
......@@ -235,7 +235,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.
......@@ -245,7 +244,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"))
......@@ -774,7 +773,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
......@@ -1043,7 +1042,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
......@@ -1071,7 +1070,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
......@@ -7679,7 +7678,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)
......
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