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
......@@ -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
cond = XEXP (SET_SRC (pattern), 0);
op0 = &XEXP (cond, 0);
op1 = &XEXP (cond, 1);
}
else if (GET_CODE (PATTERN (insn)) == SET)
{
rtx src, dest;
/* 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 = XEXP (cond, 0);
op1 = XEXP (cond, 1);
}
&& 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´s arguments and its mask. If we already swapped
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))
&& s390_non_addr_reg_read_p (*op1, next_insn))
{
if (s390_non_addr_reg_read_p (op0, prev_insn))
if (prev_insn != NULL_RTX && INSN_P (prev_insn)
&& s390_non_addr_reg_read_p (*op0, prev_insn))
{
if (REGNO(op1) == 0)
if (REGNO (*op1) == 0)
emit_insn_after (gen_nop1 (), insn);
else
emit_insn_after (gen_nop (), insn);
added_NOPs = 1;
}
else
s390_swap_cmp (cond);
}
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