diff options
author | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-12-15 14:24:03 +0000 |
---|---|---|
committer | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-12-15 14:24:03 +0000 |
commit | 3b14a2e602092924efaf923d138577646e11ea40 (patch) | |
tree | 7e277a3c3fb3e1d051c6ab13c2d10111164e71c6 /gcc/config/s390 | |
parent | a55bafe44d7e4abc77979f6b5021c846f71204c5 (diff) | |
download | gcc-3b14a2e602092924efaf923d138577646e11ea40.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142762 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390')
-rw-r--r-- | gcc/config/s390/s390.c | 103 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 6 |
2 files changed, 109 insertions, 0 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index b6c2089f0ba..7ad230ea3a9 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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 (); } diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 1691fdba0f5..3df8755ba80 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -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). |