diff options
author | James Greenhalgh <james.greenhalgh@arm.com> | 2015-10-01 09:33:40 +0000 |
---|---|---|
committer | James Greenhalgh <jgreenhalgh@gcc.gnu.org> | 2015-10-01 09:33:40 +0000 |
commit | cdc1afa3c04e6ddf2d2119a4144754cabcfe419a (patch) | |
tree | a761d52740934b009615ba7ff8c4bc9430922f59 /gcc/config/arm/aarch-common.c | |
parent | 34050b6bee181a12099a9bc31a4d25469573bc6d (diff) | |
download | gcc-cdc1afa3c04e6ddf2d2119a4144754cabcfe419a.tar.gz |
[Patch 2/2 ARM/AArch64] Add a new Cortex-A53 scheduling model
* config/arm/aarch-common-protos.h
(aarch_accumulator_forwarding): New.
(aarch_forward_to_shift_is_not_shifted_reg): Likewise.
* config/arm/aarch-common.c (aarch_accumulator_forwarding): New.
(aarch_forward_to_shift_is_not_shifted_reg): Liekwise.
* config/arm/cortex-a53.md: Rewrite.
From-SVN: r228324
Diffstat (limited to 'gcc/config/arm/aarch-common.c')
-rw-r--r-- | gcc/config/arm/aarch-common.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c index 5dd8222539e..43579d8be70 100644 --- a/gcc/config/arm/aarch-common.c +++ b/gcc/config/arm/aarch-common.c @@ -394,6 +394,112 @@ arm_mac_accumulator_is_result (rtx producer, rtx consumer) && !reg_overlap_mentioned_p (result, op1)); } +/* Return non-zero if the destination of PRODUCER feeds the accumulator + operand of an MLA-like operation. */ + +int +aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer) +{ + rtx producer_set = single_set (producer); + rtx consumer_set = single_set (consumer); + + /* We are looking for a SET feeding a SET. */ + if (!producer_set || !consumer_set) + return 0; + + rtx dest = SET_DEST (producer_set); + rtx mla = SET_SRC (consumer_set); + + /* We're looking for a register SET. */ + if (!REG_P (dest)) + return 0; + + rtx accumulator; + + /* Strip a zero_extend. */ + if (GET_CODE (mla) == ZERO_EXTEND) + mla = XEXP (mla, 0); + + switch (GET_CODE (mla)) + { + case PLUS: + /* Possibly an MADD. */ + if (GET_CODE (XEXP (mla, 0)) == MULT) + accumulator = XEXP (mla, 1); + else + return 0; + break; + case MINUS: + /* Possibly an MSUB. */ + if (GET_CODE (XEXP (mla, 1)) == MULT) + accumulator = XEXP (mla, 0); + else + return 0; + break; + case FMA: + { + /* Possibly an FMADD/FMSUB/FNMADD/FNMSUB. */ + if (REG_P (XEXP (mla, 1)) + && REG_P (XEXP (mla, 2)) + && (REG_P (XEXP (mla, 0)) + || GET_CODE (XEXP (mla, 0)) == NEG)) + + { + /* FMADD/FMSUB. */ + accumulator = XEXP (mla, 2); + } + else if (REG_P (XEXP (mla, 1)) + && GET_CODE (XEXP (mla, 2)) == NEG + && (REG_P (XEXP (mla, 0)) + || GET_CODE (XEXP (mla, 0)) == NEG)) + { + /* FNMADD/FNMSUB. */ + accumulator = XEXP (XEXP (mla, 2), 0); + } + else + return 0; + break; + } + default: + /* Not an MLA-like operation. */ + return 0; + } + + return (REGNO (dest) == REGNO (accumulator)); +} + +/* Return nonzero if the CONSUMER instruction is some sort of + arithmetic or logic + shift operation, and the register we are + writing in PRODUCER is not used in a register shift by register + operation. */ + +int +aarch_forward_to_shift_is_not_shifted_reg (rtx_insn *producer, + rtx_insn *consumer) +{ + rtx value, op; + rtx early_op; + + if (!arm_get_set_operands (producer, consumer, &value, &op)) + return 0; + + if ((early_op = arm_find_shift_sub_rtx (op))) + { + if (REG_P (early_op)) + early_op = op; + + /* Any other canonicalisation of a shift is a shift-by-constant + so we don't care. */ + if (GET_CODE (early_op) == ASHIFT) + return (!REG_P (XEXP (early_op, 0)) + || !REG_P (XEXP (early_op, 1))); + else + return 1; + } + + return 0; +} + /* Return non-zero if the consumer (a multiply-accumulate instruction) has an accumulator dependency on the result of the producer (a multiplication instruction) and no other dependency on that result. */ |