diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-06-23 02:49:24 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-06-23 02:49:24 +0000 |
commit | 726901b638a4f791b565bae9f1cdc396e17736ca (patch) | |
tree | 2337787b05175a16f83350d8ea1719c4dbe35962 /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | |
parent | aeef0618b97e6a8331dffabe9166b412889dfe1c (diff) | |
download | llvm-726901b638a4f791b565bae9f1cdc396e17736ca.zip llvm-726901b638a4f791b565bae9f1cdc396e17736ca.tar.gz llvm-726901b638a4f791b565bae9f1cdc396e17736ca.tar.bz2 |
[InstCombine] Optimize subtract of selects into a select of a sub
This came up when examining some code generated by clang's IRGen for
certain member pointers.
llvm-svn: 240369
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 29ecc1d..0301543 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1611,6 +1611,32 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return BinaryOperator::CreateAnd(A, B); } + // (sub (select (a, c, b)), (select (a, d, b))) -> (select (a, (sub c, d), 0)) + // (sub (select (a, b, c)), (select (a, b, d))) -> (select (a, 0, (sub c, d))) + if (auto *SI0 = dyn_cast<SelectInst>(Op0)) { + if (auto *SI1 = dyn_cast<SelectInst>(Op1)) { + if (SI0->getCondition() == SI1->getCondition()) { + if (Value *V = SimplifySubInst( + SI0->getFalseValue(), SI1->getFalseValue(), I.hasNoSignedWrap(), + I.hasNoUnsignedWrap(), DL, TLI, DT, AC)) + return SelectInst::Create( + SI0->getCondition(), + Builder->CreateSub(SI0->getTrueValue(), SI1->getTrueValue(), "", + /*HasNUW=*/I.hasNoUnsignedWrap(), + /*HasNSW=*/I.hasNoSignedWrap()), + V); + if (Value *V = SimplifySubInst(SI0->getTrueValue(), SI1->getTrueValue(), + I.hasNoSignedWrap(), + I.hasNoUnsignedWrap(), DL, TLI, DT, AC)) + return SelectInst::Create( + SI0->getCondition(), V, + Builder->CreateSub(SI0->getFalseValue(), SI1->getFalseValue(), "", + /*HasNUW=*/I.hasNoUnsignedWrap(), + /*HasNSW=*/I.hasNoSignedWrap())); + } + } + } + if (Op0->hasOneUse()) { Value *Y = nullptr; // ((X | Y) - X) --> (~X & Y) |