diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 18266ba07898..899d7e0a11e6 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -273,7 +273,16 @@ class ConstraintInfo { public: ConstraintInfo(const DataLayout &DL, ArrayRef<Value *> FunctionArgs) - : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {} + : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) { + auto &Value2Index = getValue2Index(false); + // Add Arg > -1 constraints to unsigned system for all function arguments. + for (Value *Arg : FunctionArgs) { + ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0), + false, false, false); + VarPos.Coefficients[Value2Index[Arg]] = -1; + UnsignedCS.addVariableRow(VarPos.Coefficients); + } + } DenseMap<Value *, unsigned> &getValue2Index(bool Signed) { return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index(); @@ -1365,18 +1374,34 @@ removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info, ReproducerCondStack.pop_back(); } -/// Check if the first condition for an AND implies the second. -static bool checkAndSecondOpImpliedByFirst( +/// Check if either the first condition of an AND or OR is implied by the +/// (negated in case of OR) second condition or vice versa. +static bool checkOrAndOpImpliedByOther( FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl<ReproducerEntry> &ReproducerCondStack, SmallVectorImpl<StackEntry> &DFSInStack) { CmpInst::Predicate Pred; Value *A, *B; - Instruction *And = CB.getContextInst(); - if (!match(And->getOperand(0), m_ICmp(Pred, m_Value(A), m_Value(B)))) + Instruction *JoinOp = CB.getContextInst(); + CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify()); + unsigned OtherOpIdx = JoinOp->getOperand(0) == CmpToCheck ? 1 : 0; + + // Don't try to simplify the first condition of a select by the second, as + // this may make the select more poisonous than the original one. + // TODO: check if the first operand may be poison. + if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp)) return false; + if (!match(JoinOp->getOperand(OtherOpIdx), + m_ICmp(Pred, m_Value(A), m_Value(B)))) + return false; + + // For OR, check if the negated condition implies CmpToCheck. + bool IsOr = match(JoinOp, m_LogicalOr()); + if (IsOr) + Pred = CmpInst::getInversePredicate(Pred); + // Optimistically add fact from first condition. unsigned OldSize = DFSInStack.size(); Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack); @@ -1385,11 +1410,19 @@ static bool checkAndSecondOpImpliedByFirst( bool Changed = false; // Check if the second condition can be simplified now. - ICmpInst *Cmp = cast<ICmpInst>(And->getOperand(1)); - if (auto ImpliedCondition = checkCondition( - Cmp->getPredicate(), Cmp->getOperand(0), Cmp->getOperand(1), Cmp, - Info, CB.NumIn, CB.NumOut, CB.getContextInst())) { - And->setOperand(1, ConstantInt::getBool(And->getType(), *ImpliedCondition)); + if (auto ImpliedCondition = + checkCondition(CmpToCheck->getPredicate(), CmpToCheck->getOperand(0), + CmpToCheck->getOperand(1), CmpToCheck, Info, CB.NumIn, + CB.NumOut, CB.getContextInst())) { + if (IsOr && isa<SelectInst>(JoinOp)) { + JoinOp->setOperand( + OtherOpIdx == 0 ? 2 : 0, + ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition)); + } else + JoinOp->setOperand( + 1 - OtherOpIdx, + ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition)); + Changed = true; } @@ -1442,6 +1475,17 @@ void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B, DFSInStack.emplace_back(NumIn, NumOut, R.IsSigned, std::move(ValuesToRelease)); + if (!R.IsSigned) { + for (Value *V : NewVariables) { + ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0), + false, false, false); + VarPos.Coefficients[Value2Index[V]] = -1; + CSToUse.addVariableRow(VarPos.Coefficients); + DFSInStack.emplace_back(NumIn, NumOut, R.IsSigned, + SmallVector<Value *, 2>()); + } + } + if (R.isEq()) { // Also add the inverted constraint for equality constraints. for (auto &Coeff : R.Coefficients) @@ -1609,11 +1653,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, bool Simplified = checkAndReplaceCondition( Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(), ReproducerModule.get(), ReproducerCondStack, S.DT, ToRemove); - if (!Simplified && match(CB.getContextInst(), - m_LogicalAnd(m_Value(), m_Specific(Inst)))) { + if (!Simplified && + match(CB.getContextInst(), m_LogicalOp(m_Value(), m_Value()))) { Simplified = - checkAndSecondOpImpliedByFirst(CB, Info, ReproducerModule.get(), - ReproducerCondStack, DFSInStack); + checkOrAndOpImpliedByOther(CB, Info, ReproducerModule.get(), + ReproducerCondStack, DFSInStack); } Changed |= Simplified; } @@ -1687,7 +1731,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, #ifndef NDEBUG unsigned SignedEntries = count_if(DFSInStack, [](const StackEntry &E) { return E.IsSigned; }); - assert(Info.getCS(false).size() == DFSInStack.size() - SignedEntries && + assert(Info.getCS(false).size() - FunctionArgs.size() == + DFSInStack.size() - SignedEntries && "updates to CS and DFSInStack are out of sync"); assert(Info.getCS(true).size() == SignedEntries && "updates to CS and DFSInStack are out of sync"); |