diff options
author | Craig Topper <craig.topper@intel.com> | 2017-06-21 16:07:13 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2017-06-21 16:07:13 +0000 |
commit | ae86cc725dfd33a534efec9eab249609ddd1980d (patch) | |
tree | 5a7543b0ece5fbf5fcb9e326f4046a47cc8ce780 /llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
parent | cbac691c4bbf6c98c35441fff0460de4235c483d (diff) | |
download | bcm5719-llvm-ae86cc725dfd33a534efec9eab249609ddd1980d.tar.gz bcm5719-llvm-ae86cc725dfd33a534efec9eab249609ddd1980d.zip |
[InstCombine] Don't let folding (select (icmp eq (and X, C1), 0), Y, (or Y, C2)) create more instructions than it removes
Summary:
Previously this folding had no checks to see if it was going to result in less instructions. This was pointed out during the review of D34184
This patch adds code to count how many instructions its going to create vs how many its going to remove so we can make a proper decision.
Reviewers: spatel, majnemer
Reviewed By: spatel
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D34437
llvm-svn: 305926
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index b9674d85634..993c095dc6f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -303,7 +303,7 @@ Instruction *InstCombiner::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, /// We want to turn: /// (select (icmp eq (and X, C1), 0), Y, (or Y, C2)) /// into: -/// (or (shl (and X, C1), C3), y) +/// (or (shl (and X, C1), C3), Y) /// iff: /// C1 and C2 are both powers of 2 /// where: @@ -345,6 +345,20 @@ static Value *foldSelectICmpAndOr(const SelectInst &SI, Value *TrueVal, unsigned C1Log = C1->logBase2(); unsigned C2Log = C2->logBase2(); + + ICmpInst::Predicate Pred = IC->getPredicate(); + bool NeedXor = (Pred == ICmpInst::ICMP_NE && OrOnFalseVal) || + (Pred == ICmpInst::ICMP_EQ && OrOnTrueVal); + bool NeedShift = C1Log != C2Log; + bool NeedZExtTrunc = Y->getType()->getIntegerBitWidth() != + V->getType()->getIntegerBitWidth(); + + // Make sure we don't create more instructions than we save. + Value *Or = OrOnFalseVal ? FalseVal : TrueVal; + if ((NeedShift + NeedXor + NeedZExtTrunc) > + (IC->hasOneUse() + Or->hasOneUse())) + return nullptr; + if (C2Log > C1Log) { V = Builder->CreateZExtOrTrunc(V, Y->getType()); V = Builder->CreateShl(V, C2Log - C1Log); @@ -354,9 +368,7 @@ static Value *foldSelectICmpAndOr(const SelectInst &SI, Value *TrueVal, } else V = Builder->CreateZExtOrTrunc(V, Y->getType()); - ICmpInst::Predicate Pred = IC->getPredicate(); - if ((Pred == ICmpInst::ICMP_NE && OrOnFalseVal) || - (Pred == ICmpInst::ICMP_EQ && OrOnTrueVal)) + if (NeedXor) V = Builder->CreateXor(V, *C2); return Builder->CreateOr(V, Y); |