summaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2008-12-15 14:24:03 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2008-12-15 14:24:03 +0000
commit3b14a2e602092924efaf923d138577646e11ea40 (patch)
tree7e277a3c3fb3e1d051c6ab13c2d10111164e71c6 /gcc/config/s390
parenta55bafe44d7e4abc77979f6b5021c846f71204c5 (diff)
downloadgcc-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.c103
-rw-r--r--gcc/config/s390/s390.md6
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).