Skip to content

Commit 8487e05

Browse files
committed
Revert "[mlir][SCF] ValueBoundsConstraintSet: Support scf.if (branches) (#85895)"
This reverts commit 6b30ffe. gcc7 bot is broken
1 parent e5e1bc0 commit 8487e05

File tree

5 files changed

+46
-334
lines changed

5 files changed

+46
-334
lines changed

mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -203,26 +203,6 @@ class ValueBoundsConstraintSet
203203
std::optional<int64_t> dim1 = std::nullopt,
204204
std::optional<int64_t> dim2 = std::nullopt);
205205

206-
/// Traverse the IR starting from the given value/dim and populate constraints
207-
/// as long as the stop condition holds. Also process all values/dims that are
208-
/// already on the worklist.
209-
void populateConstraints(Value value, std::optional<int64_t> dim);
210-
211-
/// Comparison operator for `ValueBoundsConstraintSet::compare`.
212-
enum ComparisonOperator { LT, LE, EQ, GT, GE };
213-
214-
/// Try to prove that, based on the current state of this constraint set
215-
/// (i.e., without analyzing additional IR or adding new constraints), the
216-
/// "lhs" value/dim is LE/LT/EQ/GT/GE than the "rhs" value/dim.
217-
///
218-
/// Return "true" if the specified relation between the two values/dims was
219-
/// proven to hold. Return "false" if the specified relation could not be
220-
/// proven. This could be because the specified relation does in fact not hold
221-
/// or because there is not enough information in the constraint set. In other
222-
/// words, if we do not know for sure, this function returns "false".
223-
bool compare(Value lhs, std::optional<int64_t> lhsDim, ComparisonOperator cmp,
224-
Value rhs, std::optional<int64_t> rhsDim);
225-
226206
/// Compute whether the given values/dimensions are equal. Return "failure" if
227207
/// equality could not be determined.
228208
///
@@ -294,13 +274,13 @@ class ValueBoundsConstraintSet
294274

295275
ValueBoundsConstraintSet(MLIRContext *ctx, StopConditionFn stopCondition);
296276

297-
/// Given an affine map with a single result (and map operands), add a new
298-
/// column to the constraint set that represents the result of the map.
299-
/// Traverse additional IR starting from the map operands as needed (as long
300-
/// as the stop condition is not satisfied). Also process all values/dims that
301-
/// are already on the worklist. Return the position of the newly added
302-
/// column.
303-
int64_t populateConstraints(AffineMap map, ValueDimList mapOperands);
277+
/// Populates the constraint set for a value/map without actually computing
278+
/// the bound. Returns the position for the value/map (via the return value
279+
/// and `posOut` output parameter).
280+
int64_t populateConstraintsSet(Value value,
281+
std::optional<int64_t> dim = std::nullopt);
282+
int64_t populateConstraintsSet(AffineMap map, ValueDimList mapOperands,
283+
int64_t *posOut = nullptr);
304284

305285
/// Iteratively process all elements on the worklist until an index-typed
306286
/// value or shaped value meets `stopCondition`. Such values are not processed
@@ -315,19 +295,14 @@ class ValueBoundsConstraintSet
315295
/// value/dimension exists in the constraint set.
316296
int64_t getPos(Value value, std::optional<int64_t> dim = std::nullopt) const;
317297

318-
/// Return an affine expression that represents column `pos` in the constraint
319-
/// set.
320-
AffineExpr getPosExpr(int64_t pos);
321-
322298
/// Insert a value/dimension into the constraint set. If `isSymbol` is set to
323299
/// "false", a dimension is added. The value/dimension is added to the
324-
/// worklist if `addToWorklist` is set.
300+
/// worklist.
325301
///
326302
/// Note: There are certain affine restrictions wrt. dimensions. E.g., they
327303
/// cannot be multiplied. Furthermore, bounds can only be queried for
328304
/// dimensions but not for symbols.
329-
int64_t insert(Value value, std::optional<int64_t> dim, bool isSymbol = true,
330-
bool addToWorklist = true);
305+
int64_t insert(Value value, std::optional<int64_t> dim, bool isSymbol = true);
331306

332307
/// Insert an anonymous column into the constraint set. The column is not
333308
/// bound to any value/dimension. If `isSymbol` is set to "false", a dimension

mlir/lib/Dialect/SCF/IR/ValueBoundsOpInterfaceImpl.cpp

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -111,66 +111,6 @@ struct ForOpInterface
111111
}
112112
};
113113

114-
struct IfOpInterface
115-
: public ValueBoundsOpInterface::ExternalModel<IfOpInterface, IfOp> {
116-
117-
static void populateBounds(scf::IfOp ifOp, Value value,
118-
std::optional<int64_t> dim,
119-
ValueBoundsConstraintSet &cstr) {
120-
unsigned int resultNum = cast<OpResult>(value).getResultNumber();
121-
Value thenValue = ifOp.thenYield().getResults()[resultNum];
122-
Value elseValue = ifOp.elseYield().getResults()[resultNum];
123-
124-
// Populate constraints for the yielded value (and all values on the
125-
// backward slice, as long as the current stop condition is not satisfied).
126-
cstr.populateConstraints(thenValue, dim);
127-
cstr.populateConstraints(elseValue, dim);
128-
auto boundsBuilder = cstr.bound(value);
129-
if (dim)
130-
boundsBuilder[*dim];
131-
132-
// Compare yielded values.
133-
// If thenValue <= elseValue:
134-
// * result <= elseValue
135-
// * result >= thenValue
136-
if (cstr.compare(thenValue, dim,
137-
ValueBoundsConstraintSet::ComparisonOperator::LE,
138-
elseValue, dim)) {
139-
if (dim) {
140-
cstr.bound(value)[*dim] >= cstr.getExpr(thenValue, dim);
141-
cstr.bound(value)[*dim] <= cstr.getExpr(elseValue, dim);
142-
} else {
143-
cstr.bound(value) >= thenValue;
144-
cstr.bound(value) <= elseValue;
145-
}
146-
}
147-
// If elseValue <= thenValue:
148-
// * result <= thenValue
149-
// * result >= elseValue
150-
if (cstr.compare(elseValue, dim,
151-
ValueBoundsConstraintSet::ComparisonOperator::LE,
152-
thenValue, dim)) {
153-
if (dim) {
154-
cstr.bound(value)[*dim] >= cstr.getExpr(elseValue, dim);
155-
cstr.bound(value)[*dim] <= cstr.getExpr(thenValue, dim);
156-
} else {
157-
cstr.bound(value) >= elseValue;
158-
cstr.bound(value) <= thenValue;
159-
}
160-
}
161-
}
162-
163-
void populateBoundsForIndexValue(Operation *op, Value value,
164-
ValueBoundsConstraintSet &cstr) const {
165-
populateBounds(cast<IfOp>(op), value, /*dim=*/std::nullopt, cstr);
166-
}
167-
168-
void populateBoundsForShapedValueDim(Operation *op, Value value, int64_t dim,
169-
ValueBoundsConstraintSet &cstr) const {
170-
populateBounds(cast<IfOp>(op), value, dim, cstr);
171-
}
172-
};
173-
174114
} // namespace
175115
} // namespace scf
176116
} // namespace mlir
@@ -179,6 +119,5 @@ void mlir::scf::registerValueBoundsOpInterfaceExternalModels(
179119
DialectRegistry &registry) {
180120
registry.addExtension(+[](MLIRContext *ctx, scf::SCFDialect *dialect) {
181121
scf::ForOp::attachInterface<scf::ForOpInterface>(*ctx);
182-
scf::IfOp::attachInterface<scf::IfOpInterface>(*ctx);
183122
});
184123
}

mlir/lib/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,20 @@ ScalableValueBoundsConstraintSet::computeScalableBound(
5959
ScalableValueBoundsConstraintSet scalableCstr(
6060
value.getContext(), stopCondition ? stopCondition : defaultStopCondition,
6161
vscaleMin, vscaleMax);
62-
int64_t pos = scalableCstr.insert(value, dim, /*isSymbol=*/false);
63-
scalableCstr.processWorklist();
62+
int64_t pos = scalableCstr.populateConstraintsSet(value, dim);
6463

65-
// Project out all columns apart from vscale and the starting point
66-
// (value/dim). This should result in constraints in terms of vscale only.
64+
// Project out all variables apart from vscale.
65+
// This should result in constraints in terms of vscale only.
6766
auto projectOutFn = [&](ValueDim p) {
68-
bool isStartingPoint =
69-
p.first == value &&
70-
p.second == dim.value_or(ValueBoundsConstraintSet::kIndexValue);
71-
return p.first != scalableCstr.getVscaleValue() && !isStartingPoint;
67+
return p.first != scalableCstr.getVscaleValue();
7268
};
7369
scalableCstr.projectOut(projectOutFn);
7470

7571
assert(scalableCstr.cstr.getNumDimAndSymbolVars() ==
7672
scalableCstr.positionToValueDim.size() &&
7773
"inconsistent mapping state");
7874

79-
// Check that the only columns left are vscale and the starting point.
75+
// Check that the only symbols left are vscale.
8076
for (int64_t i = 0; i < scalableCstr.cstr.getNumDimAndSymbolVars(); ++i) {
8177
if (i == pos)
8278
continue;

mlir/lib/Interfaces/ValueBoundsOpInterface.cpp

Lines changed: 30 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -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

156134
AffineExpr ValueBoundsConstraintSet::getExpr(OpFoldResult ofr) {
@@ -167,7 +145,7 @@ AffineExpr ValueBoundsConstraintSet::getExpr(int64_t constant) {
167145

168146
int64_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-
227193
static 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-
652569
FailureOr<bool>
653570
ValueBoundsConstraintSet::areEqual(Value value1, Value value2,
654571
std::optional<int64_t> dim1,

0 commit comments

Comments
 (0)