@@ -110,47 +110,25 @@ AffineExpr ValueBoundsConstraintSet::getExpr(Value value,
110110 assertValidValueDim (value, dim);
111111#endif // NDEBUG
112112
113- // Check if the value/dim is statically known. In that case, an affine
114- // constant expression should be returned. This allows us to support
115- // multiplications with constants. (Multiplications of two columns in the
116- // constraint set is not supported.)
117- std::optional<int64_t > constSize = std::nullopt ;
118113 auto shapedType = dyn_cast<ShapedType>(value.getType ());
119114 if (shapedType) {
115+ // Static dimension: return constant directly.
120116 if (shapedType.hasRank () && !shapedType.isDynamicDim (*dim))
121- constSize = shapedType.getDimSize (*dim);
122- } else if (auto constInt = ::getConstantIntValue (value)) {
123- constSize = *constInt;
117+ return builder.getAffineConstantExpr (shapedType.getDimSize (*dim));
118+ } else {
119+ // Constant index value: return directly.
120+ if (auto constInt = ::getConstantIntValue (value))
121+ return builder.getAffineConstantExpr (*constInt);
124122 }
125123
126- // If the value/dim is already mapped, return the corresponding expression
127- // directly.
124+ // Dynamic value: add to constraint set.
128125 ValueDim valueDim = std::make_pair (value, dim.value_or (kIndexValue ));
129- if (valueDimToPosition.contains (valueDim)) {
130- // If it is a constant, return an affine constant expression. Otherwise,
131- // return an affine expression that represents the respective column in the
132- // constraint set.
133- if (constSize)
134- return builder.getAffineConstantExpr (*constSize);
135- return getPosExpr (getPos (value, dim));
136- }
137-
138- if (constSize) {
139- // Constant index value/dim: add column to the constraint set, add EQ bound
140- // and return an affine constant expression without pushing the newly added
141- // column to the worklist.
142- (void )insert (value, dim, /* isSymbol=*/ true , /* addToWorklist=*/ false );
143- if (shapedType)
144- bound (value)[*dim] == *constSize;
145- else
146- bound (value) == *constSize;
147- return builder.getAffineConstantExpr (*constSize);
148- }
149-
150- // Dynamic value/dim: insert column to the constraint set and put it on the
151- // worklist. Return an affine expression that represents the newly inserted
152- // column in the constraint set.
153- return getPosExpr (insert (value, dim, /* isSymbol=*/ true ));
126+ if (!valueDimToPosition.contains (valueDim))
127+ (void )insert (value, dim);
128+ int64_t pos = getPos (value, dim);
129+ return pos < cstr.getNumDimVars ()
130+ ? builder.getAffineDimExpr (pos)
131+ : builder.getAffineSymbolExpr (pos - cstr.getNumDimVars ());
154132}
155133
156134AffineExpr ValueBoundsConstraintSet::getExpr (OpFoldResult ofr) {
@@ -167,7 +145,7 @@ AffineExpr ValueBoundsConstraintSet::getExpr(int64_t constant) {
167145
168146int64_t ValueBoundsConstraintSet::insert (Value value,
169147 std::optional<int64_t > dim,
170- bool isSymbol, bool addToWorklist ) {
148+ bool isSymbol) {
171149#ifndef NDEBUG
172150 assertValidValueDim (value, dim);
173151#endif // NDEBUG
@@ -182,12 +160,7 @@ int64_t ValueBoundsConstraintSet::insert(Value value,
182160 if (positionToValueDim[i].has_value ())
183161 valueDimToPosition[*positionToValueDim[i]] = i;
184162
185- if (addToWorklist) {
186- LLVM_DEBUG (llvm::dbgs () << " Push to worklist: " << value
187- << " (dim: " << dim.value_or (kIndexValue ) << " )\n " );
188- worklist.push (pos);
189- }
190-
163+ worklist.push (pos);
191164 return pos;
192165}
193166
@@ -217,13 +190,6 @@ int64_t ValueBoundsConstraintSet::getPos(Value value,
217190 return it->second ;
218191}
219192
220- AffineExpr ValueBoundsConstraintSet::getPosExpr (int64_t pos) {
221- assert (pos >= 0 && pos < cstr.getNumDimAndSymbolVars () && " invalid position" );
222- return pos < cstr.getNumDimVars ()
223- ? builder.getAffineDimExpr (pos)
224- : builder.getAffineSymbolExpr (pos - cstr.getNumDimVars ());
225- }
226-
227193static Operation *getOwnerOfValue (Value value) {
228194 if (auto bbArg = dyn_cast<BlockArgument>(value))
229195 return bbArg.getOwner ()->getParentOp ();
@@ -526,16 +492,15 @@ FailureOr<int64_t> ValueBoundsConstraintSet::computeConstantBound(
526492
527493 // Default stop condition if none was specified: Keep adding constraints until
528494 // a bound could be computed.
529- int64_t pos = 0 ;
495+ int64_t pos;
530496 auto defaultStopCondition = [&](Value v, std::optional<int64_t > dim,
531497 ValueBoundsConstraintSet &cstr) {
532498 return cstr.cstr .getConstantBound64 (type, pos).has_value ();
533499 };
534500
535501 ValueBoundsConstraintSet cstr (
536502 map.getContext (), stopCondition ? stopCondition : defaultStopCondition);
537- pos = cstr.populateConstraints (map, operands);
538- assert (pos == 0 && " expected `map` is the first column" );
503+ cstr.populateConstraintsSet (map, operands, &pos);
539504
540505 // Compute constant bound for `valueDim`.
541506 int64_t ubAdjustment = closedUB ? 0 : 1 ;
@@ -544,28 +509,29 @@ FailureOr<int64_t> ValueBoundsConstraintSet::computeConstantBound(
544509 return failure ();
545510}
546511
547- void ValueBoundsConstraintSet::populateConstraints (Value value,
548- std::optional<int64_t > dim) {
512+ int64_t
513+ ValueBoundsConstraintSet::populateConstraintsSet (Value value,
514+ std::optional<int64_t > dim) {
549515#ifndef NDEBUG
550516 assertValidValueDim (value, dim);
551517#endif // NDEBUG
552518
553- // `getExpr` pushes the value/dim onto the worklist (unless it was already
554- // analyzed).
555- (void )getExpr (value, dim);
556- // Process all values/dims on the worklist. This may traverse and analyze
557- // additional IR, depending the current stop function.
558- processWorklist ();
519+ AffineMap map =
520+ AffineMap::get (/* dimCount=*/ 1 , /* symbolCount=*/ 0 ,
521+ Builder (value.getContext ()).getAffineDimExpr (0 ));
522+ return populateConstraintsSet (map, {{value, dim}});
559523}
560524
561- int64_t ValueBoundsConstraintSet::populateConstraints (AffineMap map,
562- ValueDimList operands) {
525+ int64_t ValueBoundsConstraintSet::populateConstraintsSet (AffineMap map,
526+ ValueDimList operands,
527+ int64_t *posOut) {
563528 assert (map.getNumResults () == 1 && " expected affine map with one result" );
564529 int64_t pos = insert (/* isSymbol=*/ false );
530+ if (posOut)
531+ *posOut = pos;
565532
566533 // Add map and operands to the constraint set. Dimensions are converted to
567- // symbols. All operands are added to the worklist (unless they were already
568- // processed).
534+ // symbols. All operands are added to the worklist.
569535 auto mapper = [&](std::pair<Value, std::optional<int64_t >> v) {
570536 return getExpr (v.first , v.second );
571537 };
@@ -600,55 +566,6 @@ ValueBoundsConstraintSet::computeConstantDelta(Value value1, Value value2,
600566 {{value1, dim1}, {value2, dim2}});
601567}
602568
603- bool ValueBoundsConstraintSet::compare (Value lhs, std::optional<int64_t > lhsDim,
604- ComparisonOperator cmp, Value rhs,
605- std::optional<int64_t > rhsDim) {
606- // This function returns "true" if "lhs CMP rhs" is proven to hold.
607- //
608- // Example for ComparisonOperator::LE and index-typed values: We would like to
609- // prove that lhs <= rhs. Proof by contradiction: add the inverse
610- // relation (lhs > rhs) to the constraint set and check if the resulting
611- // constraint set is "empty" (i.e. has no solution). In that case,
612- // lhs > rhs must be incorrect and we can deduce that lhs <= rhs holds.
613-
614- // We cannot prove anything if the constraint set is already empty.
615- if (cstr.isEmpty ()) {
616- LLVM_DEBUG (
617- llvm::dbgs ()
618- << " cannot compare value/dims: constraint system is already empty" );
619- return false ;
620- }
621-
622- // EQ can be expressed as LE and GE.
623- if (cmp == EQ)
624- return compare (lhs, lhsDim, ComparisonOperator::LE, rhs, rhsDim) &&
625- compare (lhs, lhsDim, ComparisonOperator::GE, rhs, rhsDim);
626-
627- // Construct inequality. For the above example: lhs > rhs.
628- // `IntegerRelation` inequalities are expressed in the "flattened" form and
629- // with ">= 0". I.e., lhs - rhs - 1 >= 0.
630- SmallVector<int64_t > eq (cstr.getNumDimAndSymbolVars () + 1 , 0 );
631- if (cmp == LT || cmp == LE) {
632- ++eq[getPos (lhs, lhsDim)];
633- --eq[getPos (rhs, rhsDim)];
634- } else if (cmp == GT || cmp == GE) {
635- --eq[getPos (lhs, lhsDim)];
636- ++eq[getPos (rhs, rhsDim)];
637- } else {
638- llvm_unreachable (" unsupported comparison operator" );
639- }
640- if (cmp == LE || cmp == GE)
641- eq[cstr.getNumDimAndSymbolVars ()] -= 1 ;
642-
643- // Add inequality to the constraint set and check if it made the constraint
644- // set empty.
645- int64_t ineqPos = cstr.getNumInequalities ();
646- cstr.addInequality (eq);
647- bool isEmpty = cstr.isEmpty ();
648- cstr.removeInequality (ineqPos);
649- return isEmpty;
650- }
651-
652569FailureOr<bool >
653570ValueBoundsConstraintSet::areEqual (Value value1, Value value2,
654571 std::optional<int64_t > dim1,
0 commit comments