s390.c (s390_swap_cmp): New function.

2008-12-15  Wolfgang Gellerich  <gellerich@de.ibm.com>

	* config/s390/s390.c (s390_swap_cmp): New function.
	(s390_non_addr_reg_read_p): New function.
	(s390_z10_optimize_cmp): New function.
	(s390_reorg): Added call to s390_optimize_cmp.
	* config/s390/s390.md (nop1): New insn.

From-SVN: r142762
This commit is contained in:
Wolfgang Gellerich 2008-12-15 14:24:03 +00:00 committed by Andreas Krebbel
parent d7fda78bf4
commit d277db6b0f
3 changed files with 117 additions and 0 deletions

View File

@ -1,3 +1,11 @@
2008-12-15 Wolfgang Gellerich <gellerich@de.ibm.com>
* config/s390/s390.c (s390_swap_cmp): New function.
(s390_non_addr_reg_read_p): New function.
(s390_z10_optimize_cmp): New function.
(s390_reorg): Added call to s390_optimize_cmp.
* config/s390/s390.md (nop1): New insn.
2008-12-12 Rainer Emrich <r.emrich@de.tecosim.com>
PR bootstrap/38383

View File

@ -9589,6 +9589,104 @@ 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
s390_non_addr_reg_read_p (rtx reg, rtx insn)
{
return reg_referenced_p (reg, PATTERN (insn))
&& !reg_used_in_mem_p (REGNO (reg), PATTERN (insn));
}
/* On z10, instructions of the compare-and-branch family have the
property to access the register occurring as second operand with
its bits complemented. If such a compare is grouped with a second
instruction that accesses the same register non-complemented, and
if that register's value is delivered via a bypass, then the
pipeline recycles, thereby causing significant performance decline.
This function locates such situations and exchanges the two
operands of the compare. */
static void
s390_z10_optimize_cmp (void)
{
rtx insn, prev_insn, next_insn;
int added_NOPs = 0;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (!INSN_P (insn) || INSN_CODE (insn) <= 0)
continue;
if (get_attr_z10prop (insn) == Z10PROP_Z10_COBRA)
{
rtx op0, op1, pattern, jump_expr, cond;
/* 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);
/* 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);
}
/* 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;
}
else
s390_swap_cmp (cond);
}
}
}
/* Adjust branches if we added new instructions. */
if (added_NOPs)
shorten_branches (get_insns ());
}
/* Perform machine-dependent processing. */
static void
@ -9698,6 +9796,11 @@ s390_reorg (void)
/* Try to optimize prologue and epilogue further. */
s390_optimize_prologue ();
/* Eliminate z10-specific pipeline recycles related to some compare
instructions. */
if (TARGET_Z10)
s390_z10_optimize_cmp ();
}

View File

@ -8467,6 +8467,12 @@
"lr\t0,0"
[(set_attr "op_type" "RR")])
(define_insn "nop1"
[(const_int 1)]
""
"lr\t1,1"
[(set_attr "op_type" "RR")])
;
; Special literal pool access instruction pattern(s).