diff options
| author | Evandro Menezes <e.menezes@samsung.com> | 2018-02-23 19:27:43 +0000 |
|---|---|---|
| committer | Evandro Menezes <e.menezes@samsung.com> | 2018-02-23 19:27:43 +0000 |
| commit | 1afffac05b37af21c6df63ef5e662e2e1b81c2f8 (patch) | |
| tree | d645b7355b9adb592ec738225da898622cbc74fa /llvm/lib | |
| parent | d6ba3dbbbd9c327f853907ad2eb603899ceacf3a (diff) | |
| download | bcm5719-llvm-1afffac05b37af21c6df63ef5e662e2e1b81c2f8.tar.gz bcm5719-llvm-1afffac05b37af21c6df63ef5e662e2e1b81c2f8.zip | |
[PATCH] [AArch64] Add new target feature to fuse conditional select
This feature enables the fusion of the comparison and the conditional select
instructions together.
Differential revision: https://reviews.llvm.org/D42392
llvm-svn: 325939
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64.td | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64MacroFusion.cpp | 86 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64Subtarget.h | 4 |
3 files changed, 73 insertions, 22 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index e99842bd2e0..db84666a434 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -128,6 +128,10 @@ def FeatureFuseAES : SubtargetFeature< "fuse-aes", "HasFuseAES", "true", "CPU fuses AES crypto operations">; +def FeatureFuseCCSelect : SubtargetFeature< + "fuse-csel", "HasFuseCCSelect", "true", + "CPU fuses conditional select operations">; + def FeatureFuseLiterals : SubtargetFeature< "fuse-literals", "HasFuseLiterals", "true", "CPU fuses literal generation operations">; @@ -352,6 +356,7 @@ def ProcExynosM3 : SubtargetFeature<"exynosm3", "ARMProcFamily", "ExynosM3", FeatureFPARMv8, FeatureFuseAddress, FeatureFuseAES, + FeatureFuseCCSelect, FeatureFuseLiterals, FeatureLSLFast, FeatureNEON, diff --git a/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp b/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp index 7f3989f62fc..b46509d1d65 100644 --- a/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp +++ b/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp @@ -53,8 +53,7 @@ static bool isArithmeticBccPair(const MachineInstr *FirstMI, case AArch64::BICSWrs: case AArch64::BICSXrs: // Shift value can be 0 making these behave like the "rr" variant... - if (!AArch64InstrInfo::hasShiftedReg(*FirstMI)) - return true; + return (!AArch64InstrInfo::hasShiftedReg(*FirstMI)); } } return false; @@ -102,8 +101,7 @@ static bool isArithmeticCbzPair(const MachineInstr *FirstMI, case AArch64::BICWrs: case AArch64::BICXrs: // Shift value can be 0 making these behave like the "rr" variant... - if (!AArch64InstrInfo::hasShiftedReg(*FirstMI)) - return true; + return (!AArch64InstrInfo::hasShiftedReg(*FirstMI)); } } return false; @@ -125,10 +123,10 @@ static bool isAESPair(const MachineInstr *FirstMI, SecondOpcode == AArch64::AESMCrrTied)) return true; // AES decode. - if ((FirstOpcode == AArch64::INSTRUCTION_LIST_END || - FirstOpcode == AArch64::AESDrr) && - (SecondOpcode == AArch64::AESIMCrr || - SecondOpcode == AArch64::AESIMCrrTied)) + else if ((FirstOpcode == AArch64::INSTRUCTION_LIST_END || + FirstOpcode == AArch64::AESDrr) && + (SecondOpcode == AArch64::AESIMCrr || + SecondOpcode == AArch64::AESIMCrrTied)) return true; return false; @@ -149,20 +147,23 @@ static bool isLiteralsPair(const MachineInstr *FirstMI, SecondOpcode == AArch64::ADDXri) return true; // 32 bit immediate. - if ((FirstOpcode == AArch64::INSTRUCTION_LIST_END || - FirstOpcode == AArch64::MOVZWi) && - SecondOpcode == AArch64::MOVKWi && SecondMI.getOperand(3).getImm() == 16) + else if ((FirstOpcode == AArch64::INSTRUCTION_LIST_END || + FirstOpcode == AArch64::MOVZWi) && + (SecondOpcode == AArch64::MOVKWi && + SecondMI.getOperand(3).getImm() == 16)) return true; // Lower half of 64 bit immediate. - if((FirstOpcode == AArch64::INSTRUCTION_LIST_END || - FirstOpcode == AArch64::MOVZXi) && - SecondOpcode == AArch64::MOVKXi && SecondMI.getOperand(3).getImm() == 16) + else if((FirstOpcode == AArch64::INSTRUCTION_LIST_END || + FirstOpcode == AArch64::MOVZXi) && + (SecondOpcode == AArch64::MOVKXi && + SecondMI.getOperand(3).getImm() == 16)) return true; // Upper half of 64 bit immediate. - if ((FirstOpcode == AArch64::INSTRUCTION_LIST_END || - (FirstOpcode == AArch64::MOVKXi && - FirstMI->getOperand(3).getImm() == 32)) && - SecondOpcode == AArch64::MOVKXi && SecondMI.getOperand(3).getImm() == 48) + else if ((FirstOpcode == AArch64::INSTRUCTION_LIST_END || + (FirstOpcode == AArch64::MOVKXi && + FirstMI->getOperand(3).getImm() == 32)) && + (SecondOpcode == AArch64::MOVKXi && + SecondMI.getOperand(3).getImm() == 48)) return true; return false; @@ -203,9 +204,7 @@ static bool isAddressLdStPair(const MachineInstr *FirstMI, switch (FirstMI->getOpcode()) { case AArch64::ADR: - if (SecondMI.getOperand(2).getImm() == 0) - return true; - return false; + return (SecondMI.getOperand(2).getImm() == 0); case AArch64::ADRP: return true; } @@ -213,6 +212,49 @@ static bool isAddressLdStPair(const MachineInstr *FirstMI, return false; } +// Fuse compare and conditional select. +static bool isCCSelectPair(const MachineInstr *FirstMI, + const MachineInstr &SecondMI) { + unsigned SecondOpcode = SecondMI.getOpcode(); + + // 32 bits + if (SecondOpcode == AArch64::CSELWr) { + // Assume the 1st instr to be a wildcard if it is unspecified. + if (!FirstMI) + return true; + + if (FirstMI->definesRegister(AArch64::WZR)) + switch (FirstMI->getOpcode()) { + case AArch64::SUBSWrs: + return (!AArch64InstrInfo::hasShiftedReg(*FirstMI)); + case AArch64::SUBSWrx: + return (!AArch64InstrInfo::hasExtendedReg(*FirstMI)); + case AArch64::SUBSWrr: + case AArch64::SUBSWri: + return true; + } + } + // 64 bits + else if (SecondOpcode == AArch64::CSELXr) { + // Assume the 1st instr to be a wildcard if it is unspecified. + if (!FirstMI) + return true; + + if (FirstMI->definesRegister(AArch64::XZR)) + switch (FirstMI->getOpcode()) { + case AArch64::SUBSXrs: + return (!AArch64InstrInfo::hasShiftedReg(*FirstMI)); + case AArch64::SUBSXrx: + case AArch64::SUBSXrx64: + return (!AArch64InstrInfo::hasExtendedReg(*FirstMI)); + case AArch64::SUBSXrr: + case AArch64::SUBSXri: + return true; + } + } + return false; +} + /// \brief Check if the instr pair, FirstMI and SecondMI, should be fused /// together. Given SecondMI, when FirstMI is unspecified, then check if /// SecondMI may be part of a fused pair at all. @@ -232,6 +274,8 @@ static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, return true; if (ST.hasFuseAddress() && isAddressLdStPair(FirstMI, SecondMI)) return true; + if (ST.hasFuseCCSelect() && isCCSelectPair(FirstMI, SecondMI)) + return true; return false; } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index d06f8a1ae57..d58f50dd8d7 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -113,6 +113,7 @@ protected: bool HasArithmeticCbzFusion = false; bool HasFuseAddress = false; bool HasFuseAES = false; + bool HasFuseCCSelect = false; bool HasFuseLiterals = false; bool DisableLatencySchedHeuristic = false; bool UseRSqrt = false; @@ -239,12 +240,13 @@ public: bool hasArithmeticCbzFusion() const { return HasArithmeticCbzFusion; } bool hasFuseAddress() const { return HasFuseAddress; } bool hasFuseAES() const { return HasFuseAES; } + bool hasFuseCCSelect() const { return HasFuseCCSelect; } bool hasFuseLiterals() const { return HasFuseLiterals; } /// \brief Return true if the CPU supports any kind of instruction fusion. bool hasFusion() const { return hasArithmeticBccFusion() || hasArithmeticCbzFusion() || - hasFuseAES() || hasFuseLiterals(); + hasFuseAES() || hasFuseCCSelect() || hasFuseLiterals(); } bool useRSqrt() const { return UseRSqrt; } |

