summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorJuergen Ributzka <juergen@apple.com>2014-11-13 00:36:43 +0000
committerJuergen Ributzka <juergen@apple.com>2014-11-13 00:36:43 +0000
commit424c5fd12f9e3c5ec7de218f97b410e774d63969 (patch)
tree7744c0e1a6948a18f2012fec3160e440817838ba /llvm/lib/Target
parentd1a042abd088894ae307b5d8321e0c062040b147 (diff)
downloadbcm5719-llvm-424c5fd12f9e3c5ec7de218f97b410e774d63969.tar.gz
bcm5719-llvm-424c5fd12f9e3c5ec7de218f97b410e774d63969.zip
[FastISel][AArch64] Fold the cmp into the select when possible.
This folds the compare emission into the select emission when possible, so we can directly use the flags and don't have to emit a separate compare. Related to rdar://problem/18960150. llvm-svn: 221847
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/AArch64/AArch64FastISel.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
index 82080c7e4b1..28e4b0a4599 100644
--- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
@@ -2531,6 +2531,7 @@ bool AArch64FastISel::selectSelect(const Instruction *I) {
const SelectInst *SI = cast<SelectInst>(I);
const Value *Cond = SI->getCondition();
AArch64CC::CondCode CC = AArch64CC::NE;
+ AArch64CC::CondCode ExtraCC = AArch64CC::AL;
// Try to pickup the flags, so we don't have to emit another compare.
if (foldXALUIntrinsic(CC, I, Cond)) {
@@ -2538,6 +2539,54 @@ bool AArch64FastISel::selectSelect(const Instruction *I) {
unsigned CondReg = getRegForValue(Cond);
if (!CondReg)
return false;
+ } else if (isa<CmpInst>(Cond) && cast<CmpInst>(Cond)->hasOneUse() &&
+ isValueAvailable(Cond)) {
+ const auto *Cmp = cast<CmpInst>(Cond);
+ // Try to optimize or fold the cmp.
+ CmpInst::Predicate Predicate = optimizeCmpPredicate(Cmp);
+ const Value *FoldSelect = nullptr;
+ switch (Predicate) {
+ default:
+ break;
+ case CmpInst::FCMP_FALSE:
+ FoldSelect = SI->getFalseValue();
+ break;
+ case CmpInst::FCMP_TRUE:
+ FoldSelect = SI->getTrueValue();
+ break;
+ }
+
+ if (FoldSelect) {
+ unsigned SrcReg = getRegForValue(FoldSelect);
+ if (!SrcReg)
+ return false;
+ unsigned UseReg = lookUpRegForValue(SI);
+ if (UseReg)
+ MRI.clearKillFlags(UseReg);
+
+ updateValueMap(I, SrcReg);
+ return true;
+ }
+
+ // Emit the cmp.
+ if (!emitCmp(Cmp->getOperand(0), Cmp->getOperand(1), Cmp->isUnsigned()))
+ return false;
+
+ // FCMP_UEQ and FCMP_ONE cannot be checked with a single select instruction.
+ CC = getCompareCC(Predicate);
+ switch (Predicate) {
+ default:
+ break;
+ case CmpInst::FCMP_UEQ:
+ ExtraCC = AArch64CC::EQ;
+ CC = AArch64CC::VS;
+ break;
+ case CmpInst::FCMP_ONE:
+ ExtraCC = AArch64CC::MI;
+ CC = AArch64CC::GT;
+ break;
+ }
+ assert((CC != AArch64CC::AL) && "Unexpected condition code.");
} else {
unsigned CondReg = getRegForValue(Cond);
if (!CondReg)
@@ -2560,6 +2609,11 @@ bool AArch64FastISel::selectSelect(const Instruction *I) {
if (!Src1Reg || !Src2Reg)
return false;
+ if (ExtraCC != AArch64CC::AL) {
+ Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
+ Src2IsKill, ExtraCC);
+ Src2IsKill = true;
+ }
unsigned ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
Src2IsKill, CC);
updateValueMap(I, ResultReg);
OpenPOWER on IntegriCloud