diff options
| author | Evandro Menezes <e.menezes@samsung.com> | 2019-01-14 23:54:36 +0000 |
|---|---|---|
| committer | Evandro Menezes <e.menezes@samsung.com> | 2019-01-14 23:54:36 +0000 |
| commit | bf59cb02c3db77ac1fa0b931bda32dfa44b3ab58 (patch) | |
| tree | dd7ba75ad12bd66fec4246964018ec49a9e4e89f /llvm/lib | |
| parent | ed2df18a48d55325b5758c850fd321a99fd69ae7 (diff) | |
| download | bcm5719-llvm-bf59cb02c3db77ac1fa0b931bda32dfa44b3ab58.tar.gz bcm5719-llvm-bf59cb02c3db77ac1fa0b931bda32dfa44b3ab58.zip | |
[AArch64] Add new target feature to fuse arithmetic and logic operations
This feature enables the fusion of some arithmetic and logic instructions
together.
Differential revision: https://reviews.llvm.org/D56572
llvm-svn: 351139
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64.td | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64MacroFusion.cpp | 104 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64Subtarget.h | 9 |
3 files changed, 116 insertions, 7 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index e102987e2f3..c895d4f0482 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -188,14 +188,18 @@ def FeatureFuseAES : SubtargetFeature< "fuse-aes", "HasFuseAES", "true", "CPU fuses AES crypto operations">; -def FeatureFuseCryptoEOR : SubtargetFeature< - "fuse-crypto-eor", "HasFuseCryptoEOR", "true", - "CPU fuses AES/PMULL and EOR operations">; +def FeatureFuseArithmeticLogic : SubtargetFeature< + "fuse-arith-logic", "HasFuseArithmeticLogic", "true", + "CPU fuses arithmetic and logic operations">; def FeatureFuseCCSelect : SubtargetFeature< "fuse-csel", "HasFuseCCSelect", "true", "CPU fuses conditional select operations">; +def FeatureFuseCryptoEOR : SubtargetFeature< + "fuse-crypto-eor", "HasFuseCryptoEOR", "true", + "CPU fuses AES/PMULL and EOR operations">; + def FeatureFuseLiterals : SubtargetFeature< "fuse-literals", "HasFuseLiterals", "true", "CPU fuses literal generation operations">; diff --git a/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp b/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp index fb8a339dc4d..bc596dd38b6 100644 --- a/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp +++ b/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp @@ -270,7 +270,107 @@ static bool isCCSelectPair(const MachineInstr *FirstMI, return false; } -/// Check if the instr pair, FirstMI and SecondMI, should be fused +// Arithmetic and logic. +static bool isArithmeticLogicPair(const MachineInstr *FirstMI, + const MachineInstr &SecondMI) { + if (AArch64InstrInfo::hasShiftedReg(SecondMI)) + return false; + + switch (SecondMI.getOpcode()) { + // Arithmetic + case AArch64::ADDWrr: + case AArch64::ADDXrr: + case AArch64::SUBWrr: + case AArch64::SUBXrr: + case AArch64::ADDWrs: + case AArch64::ADDXrs: + case AArch64::SUBWrs: + case AArch64::SUBXrs: + // Logic + case AArch64::ANDWrr: + case AArch64::ANDXrr: + case AArch64::BICWrr: + case AArch64::BICXrr: + case AArch64::EONWrr: + case AArch64::EONXrr: + case AArch64::EORWrr: + case AArch64::EORXrr: + case AArch64::ORNWrr: + case AArch64::ORNXrr: + case AArch64::ORRWrr: + case AArch64::ORRXrr: + case AArch64::ANDWrs: + case AArch64::ANDXrs: + case AArch64::BICWrs: + case AArch64::BICXrs: + case AArch64::EONWrs: + case AArch64::EONXrs: + case AArch64::EORWrs: + case AArch64::EORXrs: + case AArch64::ORNWrs: + case AArch64::ORNXrs: + case AArch64::ORRWrs: + case AArch64::ORRXrs: + // Assume the 1st instr to be a wildcard if it is unspecified. + if (FirstMI == nullptr) + return true; + + // Arithmetic + switch (FirstMI->getOpcode()) { + case AArch64::ADDWrr: + case AArch64::ADDXrr: + case AArch64::ADDSWrr: + case AArch64::ADDSXrr: + case AArch64::SUBWrr: + case AArch64::SUBXrr: + case AArch64::SUBSWrr: + case AArch64::SUBSXrr: + return true; + case AArch64::ADDWrs: + case AArch64::ADDXrs: + case AArch64::ADDSWrs: + case AArch64::ADDSXrs: + case AArch64::SUBWrs: + case AArch64::SUBXrs: + case AArch64::SUBSWrs: + case AArch64::SUBSXrs: + return !AArch64InstrInfo::hasShiftedReg(*FirstMI); + } + break; + + // Arithmetic, setting flags. + case AArch64::ADDSWrr: + case AArch64::ADDSXrr: + case AArch64::SUBSWrr: + case AArch64::SUBSXrr: + case AArch64::ADDSWrs: + case AArch64::ADDSXrs: + case AArch64::SUBSWrs: + case AArch64::SUBSXrs: + // Assume the 1st instr to be a wildcard if it is unspecified. + if (FirstMI == nullptr) + return true; + + // Arithmetic, not setting flags. + switch (FirstMI->getOpcode()) { + case AArch64::ADDWrr: + case AArch64::ADDXrr: + case AArch64::SUBWrr: + case AArch64::SUBXrr: + return true; + case AArch64::ADDWrs: + case AArch64::ADDXrs: + case AArch64::SUBWrs: + case AArch64::SUBXrs: + return !AArch64InstrInfo::hasShiftedReg(*FirstMI); + } + break; + } + + 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. static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, @@ -295,6 +395,8 @@ static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, return true; if (ST.hasFuseCCSelect() && isCCSelectPair(FirstMI, SecondMI)) return true; + if (ST.hasFuseArithmeticLogic() && isArithmeticLogicPair(FirstMI, SecondMI)) + return true; return false; } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index f2ad4b504ac..82f7bb75595 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -166,8 +166,9 @@ protected: bool HasArithmeticCbzFusion = false; bool HasFuseAddress = false; bool HasFuseAES = false; - bool HasFuseCryptoEOR = false; + bool HasFuseArithmeticLogic = false; bool HasFuseCCSelect = false; + bool HasFuseCryptoEOR = false; bool HasFuseLiterals = false; bool DisableLatencySchedHeuristic = false; bool UseRSqrt = false; @@ -311,14 +312,16 @@ public: bool hasArithmeticCbzFusion() const { return HasArithmeticCbzFusion; } bool hasFuseAddress() const { return HasFuseAddress; } bool hasFuseAES() const { return HasFuseAES; } - bool hasFuseCryptoEOR() const { return HasFuseCryptoEOR; } + bool hasFuseArithmeticLogic() const { return HasFuseArithmeticLogic; } bool hasFuseCCSelect() const { return HasFuseCCSelect; } + bool hasFuseCryptoEOR() const { return HasFuseCryptoEOR; } bool hasFuseLiterals() const { return HasFuseLiterals; } /// Return true if the CPU supports any kind of instruction fusion. bool hasFusion() const { return hasArithmeticBccFusion() || hasArithmeticCbzFusion() || - hasFuseAES() || hasFuseCCSelect() || hasFuseLiterals(); + hasFuseAES() || hasFuseArithmeticLogic() || + hasFuseCCSelect() || hasFuseLiterals(); } bool useRSqrt() const { return UseRSqrt; } |

