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.cpp28
1 files changed, 28 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 3e09fba..86f2829 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -2111,6 +2111,31 @@ bool CodeGenPrepare::optimizeURem(Instruction *Rem) {
return false;
}
+/// Some targets have better codegen for `ctpop(X) u< 2` than `ctpop(X) == 1`.
+/// This function converts `ctpop(X) ==/!= 1` into `ctpop(X) u</u> 2/1` if the
+/// result cannot be zero.
+static bool adjustIsPower2Test(CmpInst *Cmp, const TargetLowering &TLI,
+ const TargetTransformInfo &TTI,
+ const DataLayout &DL) {
+ ICmpInst::Predicate Pred;
+ if (!match(Cmp, m_ICmp(Pred, m_Intrinsic<Intrinsic::ctpop>(), m_One())))
+ return false;
+ if (!ICmpInst::isEquality(Pred))
+ return false;
+ auto *II = cast<IntrinsicInst>(Cmp->getOperand(0));
+
+ if (isKnownNonZero(II, DL)) {
+ if (Pred == ICmpInst::ICMP_EQ) {
+ Cmp->setOperand(1, ConstantInt::get(II->getType(), 2));
+ Cmp->setPredicate(ICmpInst::ICMP_ULT);
+ } else {
+ Cmp->setPredicate(ICmpInst::ICMP_UGT);
+ }
+ return true;
+ }
+ return false;
+}
+
bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) {
if (sinkCmpExpression(Cmp, *TLI))
return true;
@@ -2130,6 +2155,9 @@ bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) {
if (foldFCmpToFPClassTest(Cmp, *TLI, *DL))
return true;
+ if (adjustIsPower2Test(Cmp, *TLI, *TTI, *DL))
+ return true;
+
return false;
}