summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorEvandro Menezes <e.menezes@samsung.com>2018-02-23 19:27:43 +0000
committerEvandro Menezes <e.menezes@samsung.com>2018-02-23 19:27:43 +0000
commit1afffac05b37af21c6df63ef5e662e2e1b81c2f8 (patch)
treed645b7355b9adb592ec738225da898622cbc74fa /llvm/lib
parentd6ba3dbbbd9c327f853907ad2eb603899ceacf3a (diff)
downloadbcm5719-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.td5
-rw-r--r--llvm/lib/Target/AArch64/AArch64MacroFusion.cpp86
-rw-r--r--llvm/lib/Target/AArch64/AArch64Subtarget.h4
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; }
OpenPOWER on IntegriCloud