[InstCombine] Refactor OptimizeOverflowCheck; NFCI
authorNikita Popov <nikita.ppv@gmail.com>
Sun, 26 May 2019 11:43:37 +0000 (11:43 +0000)
committerNikita Popov <nikita.ppv@gmail.com>
Sun, 26 May 2019 11:43:37 +0000 (11:43 +0000)
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

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/lib/Transforms/InstCombine/InstCombineInternal.h

index d848aef..ab2da17 100644 (file)
@@ -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
index 123025b..434b0d5 100644 (file)
@@ -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;