Hi, It's the sixth patch of a series of patches optimizing CC modes on rs6000.
This patch splits setcc to two separate insns after reload so that other insns can be inserted between them. It should increase the parallelism. The rotate_cr pattern still needs the info of the number of cr fields as the pass pro_and_epilogue might change the cr register. Bootstrapped and tested on powerpc64-linux BE and LE with no regressions. Is it OK for the trunk? Thanks Gui Haochen ChangeLog rs6000: Split setcc to two insns after reload This patch splits setcc to two separate insns after reload so that other insns can be inserted between them. gcc/ * config/rs6000/rs6000.md (c_enum unpsec): Add UNSPEC_MFCR and UNSPEC_ROTATE_CR. (*move_from_cr): New. (insn set<mode>_cc): Remove. (*rotate_cr): New. (insn_and_split set<mode>_cc): New. patch.diff diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index ccf392b6409..0ad08e3111e 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -159,6 +159,8 @@ (define_c_enum "unspec" UNSPEC_XXSPLTIW_CONST UNSPEC_FMAX UNSPEC_FMIN + UNSPEC_MFCR + UNSPEC_ROTATE_CR ]) ;; @@ -12744,26 +12746,51 @@ (define_insn_and_split "*cmp<IBM128:mode>_internal2" } }) -;; Now we have the scc insns. We can do some combinations because of the -;; way the machine works. -;; -;; Note that this is probably faster if we can put an insn between the -;; mfcr and rlinm, but this is tricky. Let's leave it for now. In most -;; cases the insns below which don't use an intermediate CR field will -;; be used instead. -(define_insn "set<mode>_cc" + +(define_insn "*move_from_cr" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") - (match_operator:GPR 1 "scc_comparison_operator" - [(match_operand 2 "cc_reg_operand" "y") - (const_int 0)]))] + (unspec:GPR [(match_operand 1 "cc_reg_operand" "y")] + UNSPEC_MFCR))] "" - "mfcr %0%Q2\;rlwinm %0,%0,%J1,1" + "mfcr %0%Q1" [(set (attr "type") (cond [(match_test "TARGET_MFCRF") (const_string "mfcrf") ] - (const_string "mfcr"))) - (set_attr "length" "8")]) + (const_string "mfcr")))]) + +;; Split the insn after reload so that other insns can be inserted +;; between mfcr and rlinm. +(define_insn_and_split "set<mode>_cc" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (match_operator:GPR 1 "scc_comparison_operator" + [(match_operand 2 "cc_reg_operand" "y") + (const_int 0)]))] + "!TARGET_POWER10 + || (GET_MODE (operands[2]) != CCmode + && GET_MODE (operands[2]) != CCUNSmode)" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:GPR [(match_dup 2)] + UNSPEC_MFCR)) + (set (match_dup 0) + (unspec:GPR [(match_dup 0) + (match_dup 1)] + UNSPEC_ROTATE_CR))] + "" + [(set_attr "length" "8")]) + +(define_insn "*rotate_cr" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (unspec:GPR [(match_operand:GPR 3 "gpc_reg_operand" "r") + (match_operator:GPR 1 "scc_comparison_operator" + [(match_operand 2 "cc_reg_operand" "y") + (const_int 0)])] + UNSPEC_ROTATE_CR))] + "" + "rlwinm %0,%3,%J1,1" +) (define_insn_and_split "*set<GPR:mode><CCANY:mode>_rev" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")