https://gcc.gnu.org/g:36b37616daeec9f84d6afa97a6e2d235bebe103d
commit 36b37616daeec9f84d6afa97a6e2d235bebe103d Author: Michael Meissner <meiss...@linux.ibm.com> Date: Tue Apr 9 00:27:11 2024 -0400 Add power10 wide immediate fusion 2024-04-09 Michael Meissner <meiss...@linux.ibm.com> gcc/ PR target/108018 * config/rs6000/rs6000.md (tocref<mode>_p10_fusion): New insn. (tocref<mode>): Don't allow tocrev<mode> if tocref<mode>_p10_fusion would be used. Diff: --- gcc/config/rs6000/rs6000.md | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index abc809448ad..1acd34ca0ee 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -11302,13 +11302,54 @@ "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL" "la %0,%2@l(%1)") +;; For power10 fusion, don't split the two pieces of the TOCREF, but keep them +;; together so the instructions will fuse in case the user is using power10 +;; fusion via -mtune=power10 but is not enabling the PC-relative support. If +;; we split the instructions up, the scheduler will likely split the ADDIS and +;; ADDI instruction. + +(define_insn "*tocref<mode>_p10_fusion" + [(set (match_operand:P 0 "gpc_reg_operand" "=b") + (match_operand:P 1 "small_toc_ref" "R"))] + "TARGET_TOC && TARGET_P10_FUSION && TARGET_CMODEL != CMODEL_SMALL + && (TARGET_ELF || TARGET_XCOFF) + && legitimate_constant_pool_address_p (operands[1], QImode, false)" +{ + rtx op = operands[1]; + machine_mode mode = <MODE>mode; + rtx offset = const0_rtx; + + if (GET_CODE (op) == PLUS && add_cint_operand (XEXP (op, 1), mode)) + { + offset = XEXP (op, 1); + op = XEXP (op, 0); + } + + gcc_assert (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL); + operands[2] = XVECEXP (op, 0, 0); /* symbol ref. */ + operands[3] = XVECEXP (op, 0, 1); /* register, usually r2. */ + operands[4] = offset; + + if (INTVAL (offset) == 0) + return (TARGET_ELF + ? "addis %0,%3,%2@toc@ha\;addi %0,%0,%2@toc@l" + : "addis %0,%2@u(%3)\;la %0,%2@l(%3)"); + else + return (TARGET_ELF + ? "addis %0,%3,%2+%4@toc@ha\;addi %0,%0,%2+%4@toc@l" + : "addis %0,%2+%4@u(%3)\;la %0,%2+%4@l(%3)"); +} + [(set_attr "type" "*") + (set_attr "length" "8")]) + (define_insn_and_split "*tocref<mode>" [(set (match_operand:P 0 "gpc_reg_operand" "=b") (match_operand:P 1 "small_toc_ref" "R"))] "TARGET_TOC + && !(TARGET_P10_FUSION && (TARGET_ELF || TARGET_XCOFF)) && legitimate_constant_pool_address_p (operands[1], QImode, false)" "la %0,%a1" - "&& TARGET_CMODEL != CMODEL_SMALL && reload_completed" + "&& TARGET_CMODEL != CMODEL_SMALL && !TARGET_P10_FUSION && reload_completed" [(set (match_dup 0) (high:P (match_dup 1))) (set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))])