aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/InstructionSimplify.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-11-27 06:32:46 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-11-27 06:32:46 +0000
commitc6a5e1dd4f595b2ff437ee47345b9c27864ad232 (patch)
tree47ed58586fe32b5e92445a363a94bcca4f8e98ab /llvm/lib/Analysis/InstructionSimplify.cpp
parenta5cd950c731c803e1a65159e53bbdad0ca255bef (diff)
downloadllvm-c6a5e1dd4f595b2ff437ee47345b9c27864ad232.zip
llvm-c6a5e1dd4f595b2ff437ee47345b9c27864ad232.tar.gz
llvm-c6a5e1dd4f595b2ff437ee47345b9c27864ad232.tar.bz2
InstSimplify: Restore optimizations lost in r210006
This restores our ability to optimize: (X & C) ? X & ~C : X into X & ~C (X & C) ? X : X & ~C into X (X & C) ? X | C : X into X (X & C) ? X : X | C into X | C llvm-svn: 222868
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 014bc0f..3c61cd1 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3055,6 +3055,40 @@ static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal,
if (isa<UndefValue>(FalseVal)) // select C, X, undef -> X
return TrueVal;
+ if (const auto *ICI = dyn_cast<ICmpInst>(CondVal)) {
+ Value *X;
+ const APInt *Y;
+ if (ICI->isEquality() &&
+ match(ICI->getOperand(0), m_And(m_Value(X), m_APInt(Y))) &&
+ match(ICI->getOperand(1), m_Zero())) {
+ ICmpInst::Predicate Pred = ICI->getPredicate();
+ const APInt *C;
+ // (X & Y) == 0 ? X & ~Y : X --> X
+ // (X & Y) != 0 ? X & ~Y : X --> X & ~Y
+ if (FalseVal == X && match(TrueVal, m_And(m_Specific(X), m_APInt(C))) &&
+ *Y == ~*C)
+ return Pred == ICmpInst::ICMP_EQ ? FalseVal : TrueVal;
+ // (X & Y) == 0 ? X : X & ~Y --> X & ~Y
+ // (X & Y) != 0 ? X : X & ~Y --> X
+ if (TrueVal == X && match(FalseVal, m_And(m_Specific(X), m_APInt(C))) &&
+ *Y == ~*C)
+ return Pred == ICmpInst::ICMP_EQ ? FalseVal : TrueVal;
+
+ if (Y->isPowerOf2()) {
+ // (X & Y) == 0 ? X | Y : X --> X | Y
+ // (X & Y) != 0 ? X | Y : X --> X
+ if (FalseVal == X && match(TrueVal, m_Or(m_Specific(X), m_APInt(C))) &&
+ *Y == *C)
+ return Pred == ICmpInst::ICMP_EQ ? TrueVal : FalseVal;
+ // (X & Y) == 0 ? X : X | Y --> X
+ // (X & Y) != 0 ? X : X | Y --> X | Y
+ if (TrueVal == X && match(FalseVal, m_Or(m_Specific(X), m_APInt(C))) &&
+ *Y == *C)
+ return Pred == ICmpInst::ICMP_EQ ? TrueVal : FalseVal;
+ }
+ }
+ }
+
return nullptr;
}