aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/CodeGenPrepare.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index bece70a..921a5b7 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1943,6 +1943,39 @@ static bool swapICmpOperandsToExposeCSEOpportunities(CmpInst *Cmp) {
return false;
}
+static bool foldFCmpToFPClassTest(CmpInst *Cmp, const TargetLowering &TLI,
+ const DataLayout &DL) {
+ FCmpInst *FCmp = dyn_cast<FCmpInst>(Cmp);
+ if (!FCmp)
+ return false;
+
+ // Don't fold if the target offers free fabs and the predicate is legal.
+ EVT VT = TLI.getValueType(DL, Cmp->getOperand(0)->getType());
+ if (TLI.isFAbsFree(VT) &&
+ TLI.isCondCodeLegal(getFCmpCondCode(FCmp->getPredicate()),
+ VT.getSimpleVT()))
+ return false;
+
+ // Reverse the canonicalization if it is a FP class test
+ auto ShouldReverseTransform = [](FPClassTest ClassTest) {
+ return ClassTest == fcInf || ClassTest == (fcInf | fcNan);
+ };
+ auto [ClassVal, ClassTest] =
+ fcmpToClassTest(FCmp->getPredicate(), *FCmp->getParent()->getParent(),
+ FCmp->getOperand(0), FCmp->getOperand(1));
+ if (!ClassVal)
+ return false;
+
+ if (!ShouldReverseTransform(ClassTest) && !ShouldReverseTransform(~ClassTest))
+ return false;
+
+ IRBuilder<> Builder(Cmp);
+ Value *IsFPClass = Builder.createIsFPClass(ClassVal, ClassTest);
+ Cmp->replaceAllUsesWith(IsFPClass);
+ RecursivelyDeleteTriviallyDeadInstructions(Cmp);
+ return true;
+}
+
bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) {
if (sinkCmpExpression(Cmp, *TLI))
return true;
@@ -1959,6 +1992,9 @@ bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) {
if (swapICmpOperandsToExposeCSEOpportunities(Cmp))
return true;
+ if (foldFCmpToFPClassTest(Cmp, *TLI, *DL))
+ return true;
+
return false;
}