From b15ef5d3f8a611af67254cdfaf126412872ca95c Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Tue, 7 Nov 2017 20:33:57 +0100 Subject: [PATCH] rs6000: Use isel for the cstore patterns We currently generate (sometimes pretty long) sequences of integer insns to implement the various cstore patterns. If the CPU has a fast isel, we can use that at the same latency as of just two integer insns (you also get a load immediate of 1, and sometimes one of 0 as well, but those are not in the critical path: they don't depend on any other instruction). There are a few patterns that already are implemented with just two instructions; so don't use isel in that case (I still need to check all lt/gt/ltu/gtu/le/leu/ge/geu patterns with all SI/DI combinations, one or two might be better without isel). This introduces a new GPR2 mode iterator, for those patterns that use two independent integer modes. * config/rs6000/rs6000.md (GPR2): New mode_iterator. ("cstore4"): Don't always expand with rs6000_emit_int_cmove for eq and ne if TARGET_ISEL. (cmp): New code_iterator. (UNS, UNSU_, UNSIK): New code_attrs. (2_isel): New define_insn_and_split. ("eq3"): New define_expand, rename the define_insn_and_split to... ("eq3"): ... this. ("ne3"): New define_expand, rename the define_insn_and_split to... ("ne3"): ... this. From-SVN: r254508 --- gcc/ChangeLog | 15 ++++ gcc/config/rs6000/rs6000.md | 133 ++++++++++++++++++++++++++++++++---- 2 files changed, 134 insertions(+), 14 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 29c3349caec..9c9f0ef8bb9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2017-11-07 Segher Boessenkool + + * config/rs6000/rs6000.md (GPR2): New mode_iterator. + ("cstore4"): Don't always expand with rs6000_emit_int_cmove for + eq and ne if TARGET_ISEL. + (cmp): New code_iterator. + (UNS, UNSU_, UNSIK): New code_attrs. + (2_isel): New define_insn_and_split. + ("eq3"): New define_expand, rename the define_insn_and_split + to... + ("eq3"): ... this. + ("ne3"): New define_expand, rename the define_insn_and_split + to... + ("ne3"): ... this. + 2017-11-07 Julia Koval PR target/82812 diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index ed5ff397e07..b800276692d 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -323,6 +323,9 @@ ; of whole values in GPRs. (define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")]) +; And again, for patterns that need two (potentially) different integer modes. +(define_mode_iterator GPR2 [SI (DI "TARGET_POWERPC64")]) + ; Any supported integer mode. (define_mode_iterator INT [QI HI SI DI TI PTI]) @@ -11780,13 +11783,9 @@ (clobber (match_operand:GPR 0 "gpc_reg_operand"))] "" { - /* Use ISEL if the user asked for it. */ - if (TARGET_ISEL) - rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx); - /* Expanding EQ and NE directly to some machine instructions does not help but does hurt combine. So don't. */ - else if (GET_CODE (operands[1]) == EQ) + if (GET_CODE (operands[1]) == EQ) emit_insn (gen_eq3 (operands[0], operands[2], operands[3])); else if (mode == Pmode && GET_CODE (operands[1]) == NE) @@ -11798,7 +11797,11 @@ emit_insn (gen_xor3 (operands[0], tmp, const1_rtx)); } - /* Expanding the unsigned comparisons however helps a lot: all the neg_ltu + /* If ISEL is fast, expand to it. */ + else if (TARGET_ISEL) + rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx); + + /* Expanding the unsigned comparisons helps a lot: all the neg_ltu etc. combinations magically work out just right. */ else if (mode == Pmode && unsigned_comparison_operator (operands[1], VOIDmode)) @@ -12280,18 +12283,102 @@ "") +(define_code_iterator cmp [eq ne lt ltu gt gtu le leu ge geu]) +(define_code_attr UNS [(eq "CC") + (ne "CC") + (lt "CC") (ltu "CCUNS") + (gt "CC") (gtu "CCUNS") + (le "CC") (leu "CCUNS") + (ge "CC") (geu "CCUNS")]) +(define_code_attr UNSu_ [(eq "") + (ne "") + (lt "") (ltu "u_") + (gt "") (gtu "u_") + (le "") (leu "u_") + (ge "") (geu "u_")]) +(define_code_attr UNSIK [(eq "I") + (ne "I") + (lt "I") (ltu "K") + (gt "I") (gtu "K") + (le "I") (leu "K") + (ge "I") (geu "K")]) + +(define_insn_and_split "2_isel" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (cmp:GPR (match_operand:GPR2 1 "gpc_reg_operand" "r") + (match_operand:GPR2 2 "reg_or_short_operand" "r"))) + (clobber (match_scratch:GPR 3 "=r")) + (clobber (match_scratch:GPR 4 "=r")) + (clobber (match_scratch: 5 "=y"))] + "TARGET_ISEL + && !( == EQ && operands[2] == const0_rtx) + && !( == NE && operands[2] == const0_rtx + && mode == Pmode && mode == Pmode)" + "#" + "&& 1" + [(pc)] +{ + if ( == NE || == LE || == GE + || == LEU || == GEU) + operands[3] = const0_rtx; + else + { + if (GET_CODE (operands[3]) == SCRATCH) + operands[3] = gen_reg_rtx (mode); + emit_move_insn (operands[3], const0_rtx); + } + + if (GET_CODE (operands[4]) == SCRATCH) + operands[4] = gen_reg_rtx (mode); + emit_move_insn (operands[4], const1_rtx); + + if (GET_CODE (operands[5]) == SCRATCH) + operands[5] = gen_reg_rtx (mode); + + rtx c1 = gen_rtx_COMPARE (mode, operands[1], operands[2]); + emit_insn (gen_rtx_SET (operands[5], c1)); + + rtx c2 = gen_rtx_fmt_ee (, mode, operands[5], const0_rtx); + rtx x = gen_rtx_IF_THEN_ELSE (mode, c2, operands[4], operands[3]); + emit_move_insn (operands[0], x); + + DONE; +} + [(set (attr "cost") + (if_then_else (match_test " == NE || == LE || == GE + || == LEU || == GEU") + (const_string "9") + (const_string "10")))]) + (define_mode_attr scc_eq_op2 [(SI "rKLI") (DI "rKJI")]) -(define_insn_and_split "eq3" +(define_expand "eq3" + [(parallel [ + (set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "scc_eq_operand" ""))) + (clobber (match_scratch:GPR 3 "=r")) + (clobber (match_scratch:GPR 4 "=r"))])] + "" +{ + if (TARGET_ISEL && operands[2] != const0_rtx) + { + emit_insn (gen_eq2_isel (operands[0], operands[1], + operands[2])); + DONE; + } +}) + +(define_insn_and_split "*eq3" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") (match_operand:GPR 2 "scc_eq_operand" ""))) (clobber (match_scratch:GPR 3 "=r")) (clobber (match_scratch:GPR 4 "=r"))] - "" + "!(TARGET_ISEL && operands[2] != const0_rtx)" "#" - "" + "&& 1" [(set (match_dup 4) (clz:GPR (match_dup 3))) (set (match_dup 0) @@ -12311,16 +12398,34 @@ (const_string "8") (const_string "12")))]) -(define_insn_and_split "ne3" +(define_expand "ne3" + [(parallel [ + (set (match_operand:P 0 "gpc_reg_operand" "=r") + (ne:P (match_operand:P 1 "gpc_reg_operand" "r") + (match_operand:P 2 "scc_eq_operand" ""))) + (clobber (match_scratch:P 3 "=r")) + (clobber (match_scratch:P 4 "=r")) + (clobber (reg:P CA_REGNO))])] + "" +{ + if (TARGET_ISEL && operands[2] != const0_rtx) + { + emit_insn (gen_ne2_isel (operands[0], operands[1], + operands[2])); + DONE; + } +}) + +(define_insn_and_split "*ne3" [(set (match_operand:P 0 "gpc_reg_operand" "=r") (ne:P (match_operand:P 1 "gpc_reg_operand" "r") (match_operand:P 2 "scc_eq_operand" ""))) (clobber (match_scratch:P 3 "=r")) (clobber (match_scratch:P 4 "=r")) (clobber (reg:P CA_REGNO))] - "!TARGET_ISEL" + "!(TARGET_ISEL && operands[2] != const0_rtx)" "#" - "" + "&& 1" [(parallel [(set (match_dup 4) (plus:P (match_dup 3) (const_int -1))) @@ -12573,9 +12678,9 @@ (clobber (match_scratch:SI 3 "=r")) (clobber (match_scratch:SI 4 "=r")) (clobber (match_scratch:EXTSI 5 "=r"))] - "" + "!TARGET_ISEL" "#" - "" + "&& 1" [(set (match_dup 4) (clz:SI (match_dup 3))) (set (match_dup 5) -- 2.30.2