mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-16 06:29:41 +08:00
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:
parent
d7fda78bf4
commit
d277db6b0f
@ -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
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user