[llvm] c52f839 - Revert "[SCCP] Use ValueLatticeElement instead of LatticeVal (NFCI)"

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 12 11:49:31 PDT 2020


Author: Florian Hahn
Date: 2020-03-12T18:49:11Z
New Revision: c52f839e723ee288db2a3e21860b011f6a9d707e

URL: https://github.com/llvm/llvm-project/commit/c52f839e723ee288db2a3e21860b011f6a9d707e
DIFF: https://github.com/llvm/llvm-project/commit/c52f839e723ee288db2a3e21860b011f6a9d707e.diff

LOG: Revert "[SCCP] Use ValueLatticeElement instead of LatticeVal (NFCI)"

This commit is likely causing clang-with-lto-ubuntu to fail
http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/16052

Also causes PR45185.

This reverts commit f1ac5d2263f8419b865cc78ba1f5c8694970fb6b.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/SCCP.cpp
    llvm/test/Transforms/SCCP/ip-constant-ranges.ll
    llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp
index 6b130a41c4d6..2d83fa38b80f 100644
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp
@@ -74,26 +74,91 @@ STATISTIC(IPNumGlobalConst, "Number of globals found to be constant by IPSCCP");
 
 namespace {
 
-// Use ValueLatticeElement as LatticeVal.
-using LatticeVal = ValueLatticeElement;
-
-// Helper to check if \p LV is either a constant or a constant
-// range with a single element. This should cover exactly the same cases as the
-// old LatticeVal::isConstant() and is intended to be used in the transition
-// from LatticeVal to LatticeValueElement.
-bool isConstant(const LatticeVal &LV) {
-  return LV.isConstant() ||
-         (LV.isConstantRange() && LV.getConstantRange().isSingleElement());
-}
+/// LatticeVal class - This class represents the 
diff erent lattice values that
+/// an LLVM value may occupy.  It is a simple class with value semantics.
+///
+class LatticeVal {
+  enum LatticeValueTy {
+    /// unknown - This LLVM Value has no known value yet.
+    unknown,
 
-// Helper to check if \p LV is either overdefined or a constant range with more
-// than a single element. This should cover exactly the same cases as the old
-// LatticeVal::isOverdefined() and is intended to be used in the transition from
-// LatticeVal to LatticeValueElement.
-bool isOverdefined(const LatticeVal &LV) {
-  return LV.isOverdefined() ||
-         (LV.isConstantRange() && !LV.getConstantRange().isSingleElement());
-}
+    /// constant - This LLVM Value has a specific constant value.
+    constant,
+
+    /// overdefined - This instruction is not known to be constant, and we know
+    /// it has a value.
+    overdefined
+  };
+
+  /// Val: This stores the current lattice value along with the Constant* for
+  /// the constant if this is a 'constant' value.
+  PointerIntPair<Constant *, 2, LatticeValueTy> Val;
+
+  LatticeValueTy getLatticeValue() const {
+    return Val.getInt();
+  }
+
+public:
+  LatticeVal() : Val(nullptr, unknown) {}
+
+  bool isUnknown() const { return getLatticeValue() == unknown; }
+
+  bool isConstant() const { return getLatticeValue() == constant; }
+
+  bool isOverdefined() const { return getLatticeValue() == overdefined; }
+
+  Constant *getConstant() const {
+    assert(isConstant() && "Cannot get the constant of a non-constant!");
+    return Val.getPointer();
+  }
+
+  /// markOverdefined - Return true if this is a change in status.
+  bool markOverdefined() {
+    if (isOverdefined())
+      return false;
+
+    Val.setInt(overdefined);
+    return true;
+  }
+
+  /// markConstant - Return true if this is a change in status.
+  bool markConstant(Constant *V) {
+    if (getLatticeValue() == constant) { // Constant
+      assert(getConstant() == V && "Marking constant with 
diff erent value");
+      return false;
+    }
+
+    assert(isUnknown());
+    Val.setInt(constant);
+    assert(V && "Marking constant with NULL");
+    Val.setPointer(V);
+    return true;
+  }
+
+  /// getConstantInt - If this is a constant with a ConstantInt value, return it
+  /// otherwise return null.
+  ConstantInt *getConstantInt() const {
+    if (isConstant())
+      return dyn_cast<ConstantInt>(getConstant());
+    return nullptr;
+  }
+
+  /// getBlockAddress - If this is a constant with a BlockAddress value, return
+  /// it, otherwise return null.
+  BlockAddress *getBlockAddress() const {
+    if (isConstant())
+      return dyn_cast<BlockAddress>(getConstant());
+    return nullptr;
+  }
+
+  ValueLatticeElement toValueLattice() const {
+    if (isOverdefined())
+      return ValueLatticeElement::getOverdefined();
+    if (isConstant())
+      return ValueLatticeElement::get(getConstant());
+    return ValueLatticeElement();
+  }
+};
 
 //===----------------------------------------------------------------------===//
 //
@@ -105,6 +170,8 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
   std::function<const TargetLibraryInfo &(Function &)> GetTLI;
   SmallPtrSet<BasicBlock *, 8> BBExecutable; // The BBs that are executable.
   DenseMap<Value *, LatticeVal> ValueState;  // The state each value is in.
+  // The state each parameter is in.
+  DenseMap<Value *, ValueLatticeElement> ParamState;
 
   /// StructValueState - This maintains ValueState for values that have
   /// StructType, for example for formal arguments, calls, insertelement, etc.
@@ -159,8 +226,6 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
   DenseMap<Function *, AnalysisResultsForFn> AnalysisResults;
   DenseMap<Value *, SmallPtrSet<User *, 2>> AdditionalUsers;
 
-  LLVMContext &Ctx;
-
 public:
   void addAnalysis(Function &F, AnalysisResultsForFn A) {
     AnalysisResults.insert({&F, std::move(A)});
@@ -180,9 +245,8 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
   }
 
   SCCPSolver(const DataLayout &DL,
-             std::function<const TargetLibraryInfo &(Function &)> GetTLI,
-             LLVMContext &Ctx)
-      : DL(DL), GetTLI(std::move(GetTLI)), Ctx(Ctx) {}
+             std::function<const TargetLibraryInfo &(Function &)> GetTLI)
+      : DL(DL), GetTLI(std::move(GetTLI)) {}
 
   /// MarkBlockExecutable - This method can be used by clients to mark all of
   /// the blocks that are known to be intrinsically live in the processed unit.
@@ -318,50 +382,23 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
   }
 
   // isStructLatticeConstant - Return true if all the lattice values
-  // corresponding to elements of the structure are constants,
+  // corresponding to elements of the structure are not overdefined,
   // false otherwise.
   bool isStructLatticeConstant(Function *F, StructType *STy) {
     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
       const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i));
       assert(It != TrackedMultipleRetVals.end());
       LatticeVal LV = It->second;
-      if (!isConstant(LV))
+      if (LV.isOverdefined())
         return false;
     }
     return true;
   }
 
-  /// Helper to return a Constant if \p LV is either a constant or a constant
-  /// range with a single element.
-  Constant *getConstant(const LatticeVal &LV) const {
-    if (LV.isConstant())
-      return LV.getConstant();
-
-    if (LV.isConstantRange()) {
-      auto &CR = LV.getConstantRange();
-      if (CR.getSingleElement())
-        return ConstantInt::get(Ctx, *CR.getSingleElement());
-    }
-    return nullptr;
-  }
-
 private:
-  ConstantInt *getConstantInt(const LatticeVal &IV) const {
-    return dyn_cast_or_null<ConstantInt>(getConstant(IV));
-  }
-
   // pushToWorkList - Helper for markConstant/markOverdefined
   void pushToWorkList(LatticeVal &IV, Value *V) {
-    if (isOverdefined(IV))
-      return OverdefinedInstWorkList.push_back(V);
-    InstWorkList.push_back(V);
-  }
-
-  // Helper to push \p V to the worklist, after updating it to \p IV. Also
-  // prints a debug message with the updated value.
-  void pushToWorkListMsg(LatticeVal &IV, Value *V) {
-    LLVM_DEBUG(dbgs() << "updated " << IV << ": " << *V << '\n');
-    if (isOverdefined(IV))
+    if (IV.isOverdefined())
       return OverdefinedInstWorkList.push_back(V);
     InstWorkList.push_back(V);
   }
@@ -396,29 +433,22 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
     return true;
   }
 
-  bool mergeInValue(LatticeVal &IV, Value *V, LatticeVal MergeWithV,
-                    bool Widen = true) {
-    // Do a simple form of widening, to avoid extending a range repeatedly in a
-    // loop. If IV is a constant range, it means we already set it once. If
-    // MergeWithV would extend IV, mark V as overdefined.
-    if (Widen && IV.isConstantRange() && MergeWithV.isConstantRange() &&
-        !IV.getConstantRange().contains(MergeWithV.getConstantRange())) {
-      markOverdefined(IV, V);
-      return true;
-    }
-    if (IV.mergeIn(MergeWithV, DL)) {
-      pushToWorkList(IV, V);
-      LLVM_DEBUG(dbgs() << "Merged " << MergeWithV << " into " << *V << " : "
-                        << IV << "\n");
-      return true;
-    }
+  bool mergeInValue(LatticeVal &IV, Value *V, LatticeVal MergeWithV) {
+    if (IV.isOverdefined() || MergeWithV.isUnknown())
+      return false; // Noop.
+    if (MergeWithV.isOverdefined())
+      return markOverdefined(IV, V);
+    if (IV.isUnknown())
+      return markConstant(IV, V, MergeWithV.getConstant());
+    if (IV.getConstant() != MergeWithV.getConstant())
+      return markOverdefined(IV, V);
     return false;
   }
 
-  bool mergeInValue(Value *V, LatticeVal MergeWithV, bool Widen = true) {
+  bool mergeInValue(Value *V, LatticeVal MergeWithV) {
     assert(!V->getType()->isStructTy() &&
            "non-structs should use markConstant");
-    return mergeInValue(ValueState[V], V, MergeWithV, Widen);
+    return mergeInValue(ValueState[V], V, MergeWithV);
   }
 
   /// getValueState - Return the LatticeVal object that corresponds to the
@@ -462,6 +492,18 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
     return Res;
   }
 
+  ValueLatticeElement &getParamState(Value *V) {
+    assert(!V->getType()->isStructTy() && "Should use getStructValueState");
+
+    std::pair<DenseMap<Value*, ValueLatticeElement>::iterator, bool>
+        PI = ParamState.insert(std::make_pair(V, ValueLatticeElement()));
+    ValueLatticeElement &LV = PI.first->second;
+    if (PI.second)
+      LV = getValueState(V).toValueLattice();
+
+    return LV;
+  }
+
   /// getStructValueState - Return the LatticeVal object that corresponds to the
   /// value/field pair.  This function handles the case when the value hasn't
   /// been seen yet by properly seeding constants etc.
@@ -617,7 +659,7 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI,
     }
 
     LatticeVal BCValue = getValueState(BI->getCondition());
-    ConstantInt *CI = getConstantInt(BCValue);
+    ConstantInt *CI = BCValue.getConstantInt();
     if (!CI) {
       // Overdefined condition variables, and branches on unfoldable constant
       // conditions, mean the branch could go either way.
@@ -643,7 +685,7 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI,
       return;
     }
     LatticeVal SCValue = getValueState(SI->getCondition());
-    ConstantInt *CI = getConstantInt(SCValue);
+    ConstantInt *CI = SCValue.getConstantInt();
 
     if (!CI) {   // Overdefined or unknown condition?
       // All destinations are executable!
@@ -661,7 +703,7 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI,
   if (auto *IBR = dyn_cast<IndirectBrInst>(&TI)) {
     // Casts are folded by visitCastInst.
     LatticeVal IBRValue = getValueState(IBR->getAddress());
-    BlockAddress *Addr = dyn_cast_or_null<BlockAddress>(getConstant(IBRValue));
+    BlockAddress *Addr = IBRValue.getBlockAddress();
     if (!Addr) {   // Overdefined or unknown condition?
       // All destinations are executable!
       if (!IBRValue.isUnknown())
@@ -728,9 +770,8 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
   if (PN.getType()->isStructTy())
     return (void)markOverdefined(&PN);
 
-  if (isOverdefined(getValueState(&PN))) {
-    return (void)markOverdefined(&PN);
-  }
+  if (getValueState(&PN).isOverdefined())
+    return;  // Quick exit
 
   // Super-extra-high-degree PHI nodes are unlikely to ever be marked constant,
   // and slow us down a lot.  Just mark them overdefined.
@@ -750,11 +791,11 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
     if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent()))
       continue;
 
-    if (isOverdefined(IV)) // PHI node becomes overdefined!
+    if (IV.isOverdefined())    // PHI node becomes overdefined!
       return (void)markOverdefined(&PN);
 
     if (!OperandVal) {   // Grab the first value.
-      OperandVal = getConstant(IV);
+      OperandVal = IV.getConstant();
       continue;
     }
 
@@ -764,7 +805,7 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
 
     // Check to see if there are two 
diff erent constants merging, if so, the PHI
     // node is overdefined.
-    if (getConstant(IV) != OperandVal)
+    if (IV.getConstant() != OperandVal)
       return (void)markOverdefined(&PN);
   }
 
@@ -781,7 +822,7 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) {
 
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&I]))
+  if (ValueState[&I].isOverdefined())
     return;
 
   Function *F = I.getParent()->getParent();
@@ -822,25 +863,27 @@ void SCCPSolver::visitTerminator(Instruction &TI) {
 void SCCPSolver::visitCastInst(CastInst &I) {
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&I]))
+  if (ValueState[&I].isOverdefined())
     return;
 
   LatticeVal OpSt = getValueState(I.getOperand(0));
-  if (Constant *OpC = getConstant(OpSt)) {
+  if (OpSt.isOverdefined())          // Inherit overdefinedness of operand
+    markOverdefined(&I);
+  else if (OpSt.isConstant()) {
     // Fold the constant as we build.
-    Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL);
+    Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpSt.getConstant(),
+                                          I.getType(), DL);
     if (isa<UndefValue>(C))
       return;
     // Propagate constant value
     markConstant(&I, C);
-  } else if (!OpSt.isUnknown())
-    markOverdefined(&I);
+  }
 }
 
 void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) {
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&EVI]))
+  if (ValueState[&EVI].isOverdefined())
     return;
 
   // If this returns a struct, mark all elements over defined, we don't track
@@ -870,7 +913,7 @@ void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) {
 
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&IVI]))
+  if (ValueState[&IVI].isOverdefined())
     return;
 
   // If this has more than one index, we can't handle it, drive all results to
@@ -909,14 +952,14 @@ void SCCPSolver::visitSelectInst(SelectInst &I) {
 
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&I]))
+  if (ValueState[&I].isOverdefined())
     return;
 
   LatticeVal CondValue = getValueState(I.getCondition());
   if (CondValue.isUnknown())
     return;
 
-  if (ConstantInt *CondCB = getConstantInt(CondValue)) {
+  if (ConstantInt *CondCB = CondValue.getConstantInt()) {
     Value *OpVal = CondCB->isZero() ? I.getFalseValue() : I.getTrueValue();
     mergeInValue(&I, getValueState(OpVal));
     return;
@@ -929,9 +972,9 @@ void SCCPSolver::visitSelectInst(SelectInst &I) {
   LatticeVal FVal = getValueState(I.getFalseValue());
 
   // select ?, C, C -> C.
-  if (isConstant(TVal) && isConstant(FVal) &&
-      getConstant(TVal) == getConstant(FVal))
-    return (void)markConstant(&I, getConstant(FVal));
+  if (TVal.isConstant() && FVal.isConstant() &&
+      TVal.getConstant() == FVal.getConstant())
+    return (void)markConstant(&I, FVal.getConstant());
 
   if (TVal.isUnknown())   // select ?, undef, X -> X.
     return (void)mergeInValue(&I, FVal);
@@ -947,10 +990,10 @@ void SCCPSolver::visitUnaryOperator(Instruction &I) {
   LatticeVal &IV = ValueState[&I];
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(IV)) return;
+  if (IV.isOverdefined()) return;
 
-  if (isConstant(V0State)) {
-    Constant *C = ConstantExpr::get(I.getOpcode(), getConstant(V0State));
+  if (V0State.isConstant()) {
+    Constant *C = ConstantExpr::get(I.getOpcode(), V0State.getConstant());
 
     // op Y -> undef.
     if (isa<UndefValue>(C))
@@ -959,7 +1002,7 @@ void SCCPSolver::visitUnaryOperator(Instruction &I) {
   }
 
   // If something is undef, wait for it to resolve.
-  if (!isOverdefined(V0State))
+  if (!V0State.isOverdefined())
     return;
 
   markOverdefined(&I);
@@ -971,14 +1014,11 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
   LatticeVal V2State = getValueState(I.getOperand(1));
 
   LatticeVal &IV = ValueState[&I];
-  if (isOverdefined(IV)) {
-    markOverdefined(&I);
-    return;
-  }
+  if (IV.isOverdefined()) return;
 
-  if (isConstant(V1State) && isConstant(V2State)) {
-    Constant *C = ConstantExpr::get(I.getOpcode(), getConstant(V1State),
-                                    getConstant(V2State));
+  if (V1State.isConstant() && V2State.isConstant()) {
+    Constant *C = ConstantExpr::get(I.getOpcode(), V1State.getConstant(),
+                                    V2State.getConstant());
     // X op Y -> undef.
     if (isa<UndefValue>(C))
       return;
@@ -986,16 +1026,18 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
   }
 
   // If something is undef, wait for it to resolve.
-  if (V1State.isUnknown() || V2State.isUnknown())
+  if (!V1State.isOverdefined() && !V2State.isOverdefined()) {
+
     return;
+  }
 
   // Otherwise, one of our operands is overdefined.  Try to produce something
   // better than overdefined with some tricks.
   // If this is 0 / Y, it doesn't matter that the second operand is
   // overdefined, and we can replace it with zero.
   if (I.getOpcode() == Instruction::UDiv || I.getOpcode() == Instruction::SDiv)
-    if (isConstant(V1State) && getConstant(V1State)->isNullValue())
-      return (void)markConstant(IV, &I, getConstant(V1State));
+    if (V1State.isConstant() && V1State.getConstant()->isNullValue())
+      return (void)markConstant(IV, &I, V1State.getConstant());
 
   // If this is:
   // -> AND/MUL with 0
@@ -1004,10 +1046,9 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
   if (I.getOpcode() == Instruction::And || I.getOpcode() == Instruction::Mul ||
       I.getOpcode() == Instruction::Or) {
     LatticeVal *NonOverdefVal = nullptr;
-    if (!isOverdefined(V1State))
+    if (!V1State.isOverdefined())
       NonOverdefVal = &V1State;
-
-    else if (!isOverdefined(V2State))
+    else if (!V2State.isOverdefined())
       NonOverdefVal = &V2State;
     if (NonOverdefVal) {
       if (NonOverdefVal->isUnknown())
@@ -1017,13 +1058,13 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
           I.getOpcode() == Instruction::Mul) {
         // X and 0 = 0
         // X * 0 = 0
-        if (getConstant(*NonOverdefVal)->isNullValue())
-          return (void)markConstant(IV, &I, getConstant(*NonOverdefVal));
+        if (NonOverdefVal->getConstant()->isNullValue())
+          return (void)markConstant(IV, &I, NonOverdefVal->getConstant());
       } else {
         // X or -1 = -1
-        if (ConstantInt *CI = getConstantInt(*NonOverdefVal))
+        if (ConstantInt *CI = NonOverdefVal->getConstantInt())
           if (CI->isMinusOne())
-            return (void)markConstant(IV, &I, CI);
+            return (void)markConstant(IV, &I, NonOverdefVal->getConstant());
       }
     }
   }
@@ -1035,18 +1076,22 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
 void SCCPSolver::visitCmpInst(CmpInst &I) {
   // Do not cache this lookup, getValueState calls later in the function might
   // invalidate the reference.
-  if (isOverdefined(ValueState[&I])) {
-    markOverdefined(&I);
-    return;
-  }
+  if (ValueState[&I].isOverdefined()) return;
 
   Value *Op1 = I.getOperand(0);
   Value *Op2 = I.getOperand(1);
 
   // For parameters, use ParamState which includes constant range info if
   // available.
-  auto V1State = getValueState(Op1);
-  auto V2State = getValueState(Op2);
+  auto V1Param = ParamState.find(Op1);
+  ValueLatticeElement V1State = (V1Param != ParamState.end())
+                                    ? V1Param->second
+                                    : getValueState(Op1).toValueLattice();
+
+  auto V2Param = ParamState.find(Op2);
+  ValueLatticeElement V2State = V2Param != ParamState.end()
+                                    ? V2Param->second
+                                    : getValueState(Op2).toValueLattice();
 
   Constant *C = V1State.getCompare(I.getPredicate(), I.getType(), V2State);
   if (C) {
@@ -1059,8 +1104,8 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
   }
 
   // If operands are still unknown, wait for it to resolve.
-  if ((V1State.isUnknown() || V2State.isUnknown()) &&
-      !isConstant(ValueState[&I]))
+  if (!V1State.isOverdefined() && !V2State.isOverdefined() &&
+      !ValueState[&I].isConstant())
     return;
 
   markOverdefined(&I);
@@ -1069,7 +1114,7 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
 // Handle getelementptr instructions.  If all operands are constants then we
 // can turn this into a getelementptr ConstantExpr.
 void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
-  if (isOverdefined(ValueState[&I])) return;
+  if (ValueState[&I].isOverdefined()) return;
 
   SmallVector<Constant*, 8> Operands;
   Operands.reserve(I.getNumOperands());
@@ -1079,15 +1124,11 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
     if (State.isUnknown())
       return;  // Operands are not resolved yet.
 
-    if (isOverdefined(State))
+    if (State.isOverdefined())
       return (void)markOverdefined(&I);
 
-    if (Constant *C = getConstant(State)) {
-      Operands.push_back(C);
-      continue;
-    }
-
-    return (void)markOverdefined(&I);
+    assert(State.isConstant() && "Unknown state!");
+    Operands.push_back(State.getConstant());
   }
 
   Constant *Ptr = Operands[0];
@@ -1109,17 +1150,16 @@ void SCCPSolver::visitStoreInst(StoreInst &SI) {
 
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&SI]))
+  if (ValueState[&SI].isOverdefined())
     return;
 
   GlobalVariable *GV = cast<GlobalVariable>(SI.getOperand(1));
   DenseMap<GlobalVariable*, LatticeVal>::iterator I = TrackedGlobals.find(GV);
-  if (I == TrackedGlobals.end())
-    return;
+  if (I == TrackedGlobals.end() || I->second.isOverdefined()) return;
 
   // Get the value we are storing into the global, then merge it.
   mergeInValue(I->second, GV, getValueState(SI.getOperand(0)));
-  if (isOverdefined(I->second))
+  if (I->second.isOverdefined())
     TrackedGlobals.erase(I);      // No need to keep tracking this!
 }
 
@@ -1132,7 +1172,7 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
 
   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
   // discover a concrete value later.
-  if (isOverdefined(ValueState[&I]))
+  if (ValueState[&I].isOverdefined())
     return;
 
   LatticeVal PtrVal = getValueState(I.getOperand(0));
@@ -1140,10 +1180,10 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
 
   LatticeVal &IV = ValueState[&I];
 
-  if (!isConstant(PtrVal) || I.isVolatile())
+  if (!PtrVal.isConstant() || I.isVolatile())
     return (void)markOverdefined(IV, &I);
 
-  Constant *Ptr = getConstant(PtrVal);
+  Constant *Ptr = PtrVal.getConstant();
 
   // load null is undefined.
   if (isa<ConstantPointerNull>(Ptr)) {
@@ -1184,7 +1224,7 @@ void SCCPSolver::visitCallSite(CallSite CS) {
 
   if (auto *II = dyn_cast<IntrinsicInst>(I)) {
     if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
-      if (isOverdefined(ValueState[I]))
+      if (ValueState[I].isOverdefined())
         return;
 
       auto *PI = getPredicateInfoFor(I);
@@ -1222,7 +1262,7 @@ void SCCPSolver::visitCallSite(CallSite CS) {
       LatticeVal &IV = ValueState[I];
       if (PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_EQ) {
         addAdditionalUser(CmpOp1, I);
-        if (isConstant(OriginalVal))
+        if (OriginalVal.isConstant())
           mergeInValue(IV, I, OriginalVal);
         else
           mergeInValue(IV, I, EqVal);
@@ -1230,7 +1270,7 @@ void SCCPSolver::visitCallSite(CallSite CS) {
       }
       if (!PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_NE) {
         addAdditionalUser(CmpOp1, I);
-        if (isConstant(OriginalVal))
+        if (OriginalVal.isConstant())
           mergeInValue(IV, I, OriginalVal);
         else
           mergeInValue(IV, I, EqVal);
@@ -1262,13 +1302,13 @@ void SCCPSolver::visitCallSite(CallSite CS) {
 
         if (State.isUnknown())
           return;  // Operands are not resolved yet.
-        if (isOverdefined(State))
+        if (State.isOverdefined())
           return (void)markOverdefined(I);
-        assert(isConstant(State) && "Unknown state!");
-        Operands.push_back(getConstant(State));
+        assert(State.isConstant() && "Unknown state!");
+        Operands.push_back(State.getConstant());
       }
 
-      if (isOverdefined(getValueState(I)))
+      if (getValueState(I).isOverdefined())
         return;
 
       // If we can constant fold this, mark the result of the call as a
@@ -1306,10 +1346,24 @@ void SCCPSolver::visitCallSite(CallSite CS) {
       if (auto *STy = dyn_cast<StructType>(AI->getType())) {
         for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
           LatticeVal CallArg = getStructValueState(*CAI, i);
-          mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg, false);
+          mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg);
         }
-      } else
-        mergeInValue(&*AI, getValueState(*CAI), false);
+      } else {
+        // Most other parts of the Solver still only use the simpler value
+        // lattice, so we propagate changes for parameters to both lattices.
+        ValueLatticeElement ConcreteArgument =
+            isa<Argument>(*CAI) ? getParamState(*CAI)
+                                : getValueState(*CAI).toValueLattice();
+        bool ParamChanged = getParamState(&*AI).mergeIn(ConcreteArgument, DL);
+        bool ValueChanged =
+            mergeInValue(&*AI, toLatticeVal(ConcreteArgument, AI->getType()));
+        // Add argument to work list, if the state of a parameter changes but
+        // ValueState does not change (because it is already overdefined there),
+        // We have to take changes in ParamState into account, as it is used
+        // when evaluating Cmp instructions.
+        if (!ValueChanged && ParamChanged)
+          pushToWorkList(ValueState[&*AI], &*AI);
+      }
     }
   }
 
@@ -1367,7 +1421,7 @@ void SCCPSolver::Solve() {
       // since all of its users will have already been marked as overdefined.
       // Update all of the users of this instruction's value.
       //
-      if (I->getType()->isStructTy() || !isOverdefined(getValueState(I)))
+      if (I->getType()->isStructTy() || !getValueState(I).isOverdefined())
         markUsersAsChanged(I);
     }
 
@@ -1546,24 +1600,24 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
   Constant *Const = nullptr;
   if (V->getType()->isStructTy()) {
     std::vector<LatticeVal> IVs = Solver.getStructLatticeValueFor(V);
-    if (any_of(IVs, [](const LatticeVal &LV) { return isOverdefined(LV); }))
+    if (llvm::any_of(IVs,
+                     [](const LatticeVal &LV) { return LV.isOverdefined(); }))
       return false;
     std::vector<Constant *> ConstVals;
     auto *ST = cast<StructType>(V->getType());
     for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
       LatticeVal V = IVs[i];
-      ConstVals.push_back(isConstant(V)
-                              ? Solver.getConstant(V)
+      ConstVals.push_back(V.isConstant()
+                              ? V.getConstant()
                               : UndefValue::get(ST->getElementType(i)));
     }
     Const = ConstantStruct::get(ST, ConstVals);
   } else {
     const LatticeVal &IV = Solver.getLatticeValueFor(V);
-    if (isOverdefined(IV))
+    if (IV.isOverdefined())
       return false;
 
-    Const =
-        isConstant(IV) ? Solver.getConstant(IV) : UndefValue::get(V->getType());
+    Const = IV.isConstant() ? IV.getConstant() : UndefValue::get(V->getType());
   }
   assert(Const && "Constant is nullptr here!");
 
@@ -1596,8 +1650,7 @@ static bool runSCCP(Function &F, const DataLayout &DL,
                     const TargetLibraryInfo *TLI) {
   LLVM_DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
   SCCPSolver Solver(
-      DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; },
-      F.getContext());
+      DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; });
 
   // Mark the first block of the function as being executable.
   Solver.MarkBlockExecutable(&F.front());
@@ -1740,9 +1793,9 @@ static void findReturnsToZap(Function &F,
                if (U->getType()->isStructTy()) {
                  return all_of(
                      Solver.getStructLatticeValueFor(U),
-                     [](const LatticeVal &LV) { return !isOverdefined(LV); });
+                     [](const LatticeVal &LV) { return !LV.isOverdefined(); });
                }
-               return !isOverdefined(Solver.getLatticeValueFor(U));
+               return !Solver.getLatticeValueFor(U).isOverdefined();
              }) &&
       "We can only zap functions where all live users have a concrete value");
 
@@ -1799,7 +1852,7 @@ bool llvm::runIPSCCP(
     Module &M, const DataLayout &DL,
     std::function<const TargetLibraryInfo &(Function &)> GetTLI,
     function_ref<AnalysisResultsForFn(Function &)> getAnalysis) {
-  SCCPSolver Solver(DL, GetTLI, M.getContext());
+  SCCPSolver Solver(DL, GetTLI);
 
   // Loop over all functions, marking arguments to those with their addresses
   // taken or that are external as overdefined.
@@ -1985,7 +2038,7 @@ bool llvm::runIPSCCP(
   const MapVector<Function*, LatticeVal> &RV = Solver.getTrackedRetVals();
   for (const auto &I : RV) {
     Function *F = I.first;
-    if (isOverdefined(I.second) || F->getReturnType()->isVoidTy())
+    if (I.second.isOverdefined() || F->getReturnType()->isVoidTy())
       continue;
     findReturnsToZap(*F, ReturnsToZap, Solver);
   }
@@ -2010,8 +2063,8 @@ bool llvm::runIPSCCP(
   for (DenseMap<GlobalVariable*, LatticeVal>::const_iterator I = TG.begin(),
          E = TG.end(); I != E; ++I) {
     GlobalVariable *GV = I->first;
-    if (isOverdefined(I->second))
-      continue;
+    assert(!I->second.isOverdefined() &&
+           "Overdefined values should have been taken out of the map!");
     LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
                       << "' is constant!\n");
     while (!GV->use_empty()) {

diff  --git a/llvm/test/Transforms/SCCP/ip-constant-ranges.ll b/llvm/test/Transforms/SCCP/ip-constant-ranges.ll
index dbaedaa739bf..08de8dba4046 100644
--- a/llvm/test/Transforms/SCCP/ip-constant-ranges.ll
+++ b/llvm/test/Transforms/SCCP/ip-constant-ranges.ll
@@ -230,7 +230,7 @@ define i32 @caller6() {
 ; CHECK-NEXT:    %call.1 = call i32 @callee6.1(i32 30)
 ; CHECK-NEXT:    %call.2 = call i32 @callee6.1(i32 43)
 ; CHECK-NEXT:    ret i32 2
-;
+
   %call.1 = call i32 @callee6.1(i32 30)
   %call.2 = call i32 @callee6.1(i32 43)
   %res = add i32 %call.1, %call.2

diff  --git a/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll b/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll
index d56c91061cad..0fa465d09fd5 100644
--- a/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll
+++ b/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll
@@ -40,7 +40,9 @@ define internal i32 @test1_k(i8 %h, i32 %i) {
 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP0]] to i64
 ; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1*
 ; CHECK-NEXT:    [[CALL:%.*]] = call i1 @test1_g(%t1* [[TMP1]], i32 0)
-; CHECK-NEXT:    call void @use.1(i1 false)
+; CHECK-NEXT:    [[FROMBOOL_1:%.*]] = zext i1 false to i8
+; CHECK-NEXT:    [[TOBOOL_1:%.*]] = trunc i8 [[FROMBOOL_1]] to i1
+; CHECK-NEXT:    call void @use.1(i1 [[TOBOOL_1]])
 ; CHECK-NEXT:    ret i32 undef
 ;
 entry:
@@ -117,7 +119,9 @@ define internal i32 @test2_k(i8 %h, i32 %i) {
 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP0]] to i64
 ; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1*
 ; CHECK-NEXT:    [[CALL:%.*]] = call i1 @test3_g(%t1* [[TMP1]], i32 0)
-; CHECK-NEXT:    call void @use.1(i1 false)
+; CHECK-NEXT:    [[FROMBOOL:%.*]] = icmp slt i1 false, true
+; CHECK-NEXT:    [[ADD:%.*]] = add i1 [[FROMBOOL]], [[FROMBOOL]]
+; CHECK-NEXT:    call void @use.1(i1 [[FROMBOOL]])
 ; CHECK-NEXT:    ret i32 undef
 ;
 entry:
@@ -389,6 +393,7 @@ define void @test3() {
 ; CHECK-NEXT:    [[CMP25474:%.*]] = icmp sgt i32 [[TMP2]], 0
 ; CHECK-NEXT:    br i1 [[CMP25474]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
 ; CHECK:       for.body:
+; CHECK-NEXT:    [[DIV30:%.*]] = sdiv i32 0, [[SUB19]]
 ; CHECK-NEXT:    ret void
 ; CHECK:       for.end:
 ; CHECK-NEXT:    ret void


        


More information about the llvm-commits mailing list