forked from OSchip/llvm-project
[InstCombine] Remove OverflowCheckFlavor; NFC
Instead pass binary op and signedness. The extra enum only makes things more complicated in this case. llvm-svn: 361720
This commit is contained in:
parent
0dbafe191e
commit
352f598795
|
@ -1749,15 +1749,12 @@ static Instruction *canonicalizeConstantArg0ToArg1(CallInst &Call) {
|
|||
}
|
||||
|
||||
Instruction *InstCombiner::foldIntrinsicWithOverflowCommon(IntrinsicInst *II) {
|
||||
OverflowCheckFlavor OCF =
|
||||
IntrinsicIDToOverflowCheckFlavor(II->getIntrinsicID());
|
||||
assert(OCF != OCF_INVALID && "unexpected!");
|
||||
|
||||
WithOverflowInst *WO = cast<WithOverflowInst>(II);
|
||||
Value *OperationResult = nullptr;
|
||||
Constant *OverflowResult = nullptr;
|
||||
if (OptimizeOverflowCheck(OCF, II->getArgOperand(0), II->getArgOperand(1),
|
||||
*II, OperationResult, OverflowResult))
|
||||
return CreateOverflowTuple(II, OperationResult, OverflowResult);
|
||||
if (OptimizeOverflowCheck(WO->getBinaryOp(), WO->isSigned(), WO->getLHS(),
|
||||
WO->getRHS(), *WO, OperationResult, OverflowResult))
|
||||
return CreateOverflowTuple(WO, OperationResult, OverflowResult);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -3936,9 +3936,9 @@ Instruction *InstCombiner::foldICmpWithCastAndCast(ICmpInst &ICmp) {
|
|||
return BinaryOperator::CreateNot(Result);
|
||||
}
|
||||
|
||||
bool InstCombiner::OptimizeOverflowCheck(OverflowCheckFlavor OCF, Value *LHS,
|
||||
Value *RHS, Instruction &OrigI,
|
||||
Value *&Result, Constant *&Overflow) {
|
||||
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);
|
||||
|
||||
|
@ -3956,18 +3956,17 @@ bool InstCombiner::OptimizeOverflowCheck(OverflowCheckFlavor OCF, Value *LHS,
|
|||
// compare.
|
||||
Builder.SetInsertPoint(&OrigI);
|
||||
|
||||
switch (OCF) {
|
||||
case OCF_INVALID:
|
||||
llvm_unreachable("bad overflow check kind!");
|
||||
switch (BinaryOp) {
|
||||
default:
|
||||
llvm_unreachable("unsupported binary op");
|
||||
|
||||
case OCF_UNSIGNED_ADD:
|
||||
case OCF_SIGNED_ADD: {
|
||||
case Instruction::Add: {
|
||||
// X + 0 -> {X, false}
|
||||
if (match(RHS, m_Zero()))
|
||||
return SetResult(LHS, Builder.getFalse(), false);
|
||||
|
||||
OverflowResult OR;
|
||||
if (OCF == OCF_UNSIGNED_ADD) {
|
||||
if (!IsSigned) {
|
||||
OR = computeOverflowForUnsignedAdd(LHS, RHS, &OrigI);
|
||||
if (OR == OverflowResult::NeverOverflows)
|
||||
return SetResult(Builder.CreateNUWAdd(LHS, RHS), Builder.getFalse(),
|
||||
|
@ -3984,14 +3983,13 @@ bool InstCombiner::OptimizeOverflowCheck(OverflowCheckFlavor OCF, Value *LHS,
|
|||
break;
|
||||
}
|
||||
|
||||
case OCF_UNSIGNED_SUB:
|
||||
case OCF_SIGNED_SUB: {
|
||||
case Instruction::Sub: {
|
||||
// X - 0 -> {X, false}
|
||||
if (match(RHS, m_Zero()))
|
||||
return SetResult(LHS, Builder.getFalse(), false);
|
||||
|
||||
OverflowResult OR;
|
||||
if (OCF == OCF_UNSIGNED_SUB) {
|
||||
if (!IsSigned) {
|
||||
OR = computeOverflowForUnsignedSub(LHS, RHS, &OrigI);
|
||||
if (OR == OverflowResult::NeverOverflows)
|
||||
return SetResult(Builder.CreateNUWSub(LHS, RHS), Builder.getFalse(),
|
||||
|
@ -4008,14 +4006,13 @@ bool InstCombiner::OptimizeOverflowCheck(OverflowCheckFlavor OCF, Value *LHS,
|
|||
break;
|
||||
}
|
||||
|
||||
case OCF_UNSIGNED_MUL:
|
||||
case OCF_SIGNED_MUL: {
|
||||
case Instruction::Mul: {
|
||||
// X * 1 -> {X, false}
|
||||
if (match(RHS, m_One()))
|
||||
return SetResult(LHS, Builder.getFalse(), false);
|
||||
|
||||
OverflowResult OR;
|
||||
if (OCF == OCF_UNSIGNED_MUL) {
|
||||
if (!IsSigned) {
|
||||
OR = computeOverflowForUnsignedMul(LHS, RHS, &OrigI);
|
||||
if (OR == OverflowResult::NeverOverflows)
|
||||
return SetResult(Builder.CreateNUWMul(LHS, RHS), Builder.getFalse(),
|
||||
|
@ -5053,8 +5050,8 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||
isa<IntegerType>(A->getType())) {
|
||||
Value *Result;
|
||||
Constant *Overflow;
|
||||
if (OptimizeOverflowCheck(OCF_UNSIGNED_ADD, A, B, *AddI, Result,
|
||||
Overflow)) {
|
||||
if (OptimizeOverflowCheck(Instruction::Add, /*Signed*/false, A, B,
|
||||
*AddI, Result, Overflow)) {
|
||||
replaceInstUsesWith(*AddI, Result);
|
||||
return replaceInstUsesWith(I, Overflow);
|
||||
}
|
||||
|
|
|
@ -185,40 +185,6 @@ static inline bool IsFreeToInvert(Value *V, bool WillInvertAllUses) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Specific patterns of overflow check idioms that we match.
|
||||
enum OverflowCheckFlavor {
|
||||
OCF_UNSIGNED_ADD,
|
||||
OCF_SIGNED_ADD,
|
||||
OCF_UNSIGNED_SUB,
|
||||
OCF_SIGNED_SUB,
|
||||
OCF_UNSIGNED_MUL,
|
||||
OCF_SIGNED_MUL,
|
||||
|
||||
OCF_INVALID
|
||||
};
|
||||
|
||||
/// Returns the OverflowCheckFlavor corresponding to a overflow_with_op
|
||||
/// intrinsic.
|
||||
static inline OverflowCheckFlavor
|
||||
IntrinsicIDToOverflowCheckFlavor(unsigned ID) {
|
||||
switch (ID) {
|
||||
default:
|
||||
return OCF_INVALID;
|
||||
case Intrinsic::uadd_with_overflow:
|
||||
return OCF_UNSIGNED_ADD;
|
||||
case Intrinsic::sadd_with_overflow:
|
||||
return OCF_SIGNED_ADD;
|
||||
case Intrinsic::usub_with_overflow:
|
||||
return OCF_UNSIGNED_SUB;
|
||||
case Intrinsic::ssub_with_overflow:
|
||||
return OCF_SIGNED_SUB;
|
||||
case Intrinsic::umul_with_overflow:
|
||||
return OCF_UNSIGNED_MUL;
|
||||
case Intrinsic::smul_with_overflow:
|
||||
return OCF_SIGNED_MUL;
|
||||
}
|
||||
}
|
||||
|
||||
/// Some binary operators require special handling to avoid poison and undefined
|
||||
/// behavior. If a constant vector has undef elements, replace those undefs with
|
||||
/// identity constants if possible because those are always safe to execute.
|
||||
|
@ -469,7 +435,8 @@ private:
|
|||
/// operation in OperationResult and result of the overflow check in
|
||||
/// OverflowResult, and return true. If no simplification is possible,
|
||||
/// returns false.
|
||||
bool OptimizeOverflowCheck(OverflowCheckFlavor OCF, Value *LHS, Value *RHS,
|
||||
bool OptimizeOverflowCheck(Instruction::BinaryOps BinaryOp, bool IsSigned,
|
||||
Value *LHS, Value *RHS,
|
||||
Instruction &CtxI, Value *&OperationResult,
|
||||
Constant *&OverflowResult);
|
||||
|
||||
|
|
Loading…
Reference in New Issue