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
3 changed files with 117 additions and 0 deletions
|
@ -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>
|
2008-12-12 Rainer Emrich <r.emrich@de.tecosim.com>
|
||||||
|
|
||||||
PR bootstrap/38383
|
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. */
|
/* Perform machine-dependent processing. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -9698,6 +9796,11 @@ s390_reorg (void)
|
||||||
|
|
||||||
/* Try to optimize prologue and epilogue further. */
|
/* Try to optimize prologue and epilogue further. */
|
||||||
s390_optimize_prologue ();
|
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"
|
"lr\t0,0"
|
||||||
[(set_attr "op_type" "RR")])
|
[(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).
|
; Special literal pool access instruction pattern(s).
|
||||||
|
|
Loading…
Add table
Reference in a new issue