diff options
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 36 |
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; } |