diff options
| author | Nikita Popov <nikita.ppv@gmail.com> | 2019-05-26 11:43:37 +0000 |
|---|---|---|
| committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-05-26 11:43:37 +0000 |
| commit | 39f2bebf415d2e8c8cc439aeb40fff5c23e9c8c1 (patch) | |
| tree | ecedb67b42786e2c7debe8e53aec9e641423f3ce /llvm/lib | |
| parent | 352f59879522c059f98c853e04f50fd7e46acee5 (diff) | |
| download | bcm5719-llvm-39f2bebf415d2e8c8cc439aeb40fff5c23e9c8c1.tar.gz bcm5719-llvm-39f2bebf415d2e8c8cc439aeb40fff5c23e9c8c1.zip | |
[InstCombine] Refactor OptimizeOverflowCheck; NFCI
Extract method to compute overflow based on binop and signedness,
and then make the result handling code generic. This extends the
always-overflow handling to signed muls, but has currently no effect,
as we don't compute always overflow for them (thus NFC).
llvm-svn: 361721
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 138 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineInternal.h | 6 |
2 files changed, 65 insertions, 79 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d848aef2552..ab2da177d7b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3936,100 +3936,82 @@ Instruction *InstCombiner::foldICmpWithCastAndCast(ICmpInst &ICmp) { return BinaryOperator::CreateNot(Result); } +static bool isNeutralValue(Instruction::BinaryOps BinaryOp, Value *RHS) { + switch (BinaryOp) { + default: + llvm_unreachable("Unsupported binary op"); + case Instruction::Add: + case Instruction::Sub: + return match(RHS, m_Zero()); + case Instruction::Mul: + return match(RHS, m_One()); + } +} + +OverflowResult InstCombiner::computeOverflow( + Instruction::BinaryOps BinaryOp, bool IsSigned, + Value *LHS, Value *RHS, Instruction *CxtI) const { + switch (BinaryOp) { + default: + llvm_unreachable("Unsupported binary op"); + case Instruction::Add: + if (IsSigned) + return computeOverflowForSignedAdd(LHS, RHS, CxtI); + else + return computeOverflowForUnsignedAdd(LHS, RHS, CxtI); + case Instruction::Sub: + if (IsSigned) + return computeOverflowForSignedSub(LHS, RHS, CxtI); + else + return computeOverflowForUnsignedSub(LHS, RHS, CxtI); + case Instruction::Mul: + if (IsSigned) + return computeOverflowForSignedMul(LHS, RHS, CxtI); + else + return computeOverflowForUnsignedMul(LHS, RHS, CxtI); + } +} + bool InstCombiner::OptimizeOverflowCheck( Instruction::BinaryOps BinaryOp, bool IsSigned, Value *LHS, Value *RHS, Instruction &OrigI, Value *&Result, Constant *&Overflow) { if (OrigI.isCommutative() && isa<Constant>(LHS) && !isa<Constant>(RHS)) std::swap(LHS, RHS); - auto SetResult = [&](Value *OpResult, Constant *OverflowVal, bool ReuseName) { - Result = OpResult; - Overflow = OverflowVal; - if (ReuseName) - Result->takeName(&OrigI); - return true; - }; - // If the overflow check was an add followed by a compare, the insertion point // may be pointing to the compare. We want to insert the new instructions // before the add in case there are uses of the add between the add and the // compare. Builder.SetInsertPoint(&OrigI); - switch (BinaryOp) { - default: - llvm_unreachable("unsupported binary op"); - - case Instruction::Add: { - // X + 0 -> {X, false} - if (match(RHS, m_Zero())) - return SetResult(LHS, Builder.getFalse(), false); - - OverflowResult OR; - if (!IsSigned) { - OR = computeOverflowForUnsignedAdd(LHS, RHS, &OrigI); - if (OR == OverflowResult::NeverOverflows) - return SetResult(Builder.CreateNUWAdd(LHS, RHS), Builder.getFalse(), - true); - } else { - OR = computeOverflowForSignedAdd(LHS, RHS, &OrigI); - if (OR == OverflowResult::NeverOverflows) - return SetResult(Builder.CreateNSWAdd(LHS, RHS), Builder.getFalse(), - true); - } - - if (OR == OverflowResult::AlwaysOverflows) - return SetResult(Builder.CreateAdd(LHS, RHS), Builder.getTrue(), true); - break; - } - - case Instruction::Sub: { - // X - 0 -> {X, false} - if (match(RHS, m_Zero())) - return SetResult(LHS, Builder.getFalse(), false); - - OverflowResult OR; - if (!IsSigned) { - OR = computeOverflowForUnsignedSub(LHS, RHS, &OrigI); - if (OR == OverflowResult::NeverOverflows) - return SetResult(Builder.CreateNUWSub(LHS, RHS), Builder.getFalse(), - true); - } else { - OR = computeOverflowForSignedSub(LHS, RHS, &OrigI); - if (OR == OverflowResult::NeverOverflows) - return SetResult(Builder.CreateNSWSub(LHS, RHS), Builder.getFalse(), - true); - } - - if (OR == OverflowResult::AlwaysOverflows) - return SetResult(Builder.CreateSub(LHS, RHS), Builder.getTrue(), true); - break; + if (isNeutralValue(BinaryOp, RHS)) { + Result = LHS; + Overflow = Builder.getFalse(); + return true; } - case Instruction::Mul: { - // X * 1 -> {X, false} - if (match(RHS, m_One())) - return SetResult(LHS, Builder.getFalse(), false); - - OverflowResult OR; - if (!IsSigned) { - OR = computeOverflowForUnsignedMul(LHS, RHS, &OrigI); - if (OR == OverflowResult::NeverOverflows) - return SetResult(Builder.CreateNUWMul(LHS, RHS), Builder.getFalse(), - true); - if (OR == OverflowResult::AlwaysOverflows) - return SetResult(Builder.CreateMul(LHS, RHS), Builder.getTrue(), true); - } else { - OR = computeOverflowForSignedMul(LHS, RHS, &OrigI); - if (OR == OverflowResult::NeverOverflows) - return SetResult(Builder.CreateNSWMul(LHS, RHS), Builder.getFalse(), - true); - } - break; - } + switch (computeOverflow(BinaryOp, IsSigned, LHS, RHS, &OrigI)) { + case OverflowResult::MayOverflow: + return false; + case OverflowResult::AlwaysOverflows: + Result = Builder.CreateBinOp(BinaryOp, LHS, RHS); + Result->takeName(&OrigI); + Overflow = Builder.getTrue(); + return true; + case OverflowResult::NeverOverflows: + Result = Builder.CreateBinOp(BinaryOp, LHS, RHS); + Result->takeName(&OrigI); + Overflow = Builder.getFalse(); + if (auto *Inst = dyn_cast<Instruction>(Result)) { + if (IsSigned) + Inst->setHasNoSignedWrap(); + else + Inst->setHasNoUnsignedWrap(); + } + return true; } - return false; + llvm_unreachable("Unexpected overflow result"); } /// Recognize and process idiom involving test for multiplication diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index 123025bbccf..434b0d59121 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -692,7 +692,7 @@ public: } OverflowResult computeOverflowForSignedMul(const Value *LHS, - const Value *RHS, + const Value *RHS, const Instruction *CxtI) const { return llvm::computeOverflowForSignedMul(LHS, RHS, DL, &AC, CxtI, &DT); } @@ -720,6 +720,10 @@ public: return llvm::computeOverflowForSignedSub(LHS, RHS, DL, &AC, CxtI, &DT); } + OverflowResult computeOverflow( + Instruction::BinaryOps BinaryOp, bool IsSigned, + Value *LHS, Value *RHS, Instruction *CxtI) const; + /// Maximum size of array considered when transforming. uint64_t MaxArraySizeForCombine; |

