MLIR: lib/Dialect/Affine/IR/ValueBoundsOpInterfaceImpl.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

10

13

14 using namespace mlir;

16

17 namespace mlir {

18 namespace {

19

20 struct AffineApplyOpInterface

21 : public ValueBoundsOpInterface::ExternalModel<AffineApplyOpInterface,

22 AffineApplyOp> {

23 void populateBoundsForIndexValue(Operation *op, Value value,

25 auto applyOp = cast(op);

26 assert(value == applyOp.getResult() && "invalid value");

27 assert(applyOp.getAffineMap().getNumResults() == 1 &&

28 "expected single result");

29

30

31

32

33 AffineMap map = applyOp.getAffineMap();

36

37

40 for (int64_t i = 0, e = map.getNumDims(); i < e; ++i)

41 dimReplacements.push_back(cstr.getExpr(operands[i]));

44 i < e; ++i)

45 symReplacements.push_back(cstr.getExpr(operands[i]));

48 cstr.bound(value) == bound;

49 }

50 };

51

52 struct AffineMinOpInterface

53 : public ValueBoundsOpInterface::ExternalModel<AffineMinOpInterface,

54 AffineMinOp> {

55 void populateBoundsForIndexValue(Operation *op, Value value,

57 auto minOp = cast(op);

58 assert(value == minOp.getResult() && "invalid value");

59

60

61 for (AffineExpr expr : minOp.getAffineMap().getResults()) {

63 minOp.getDimOperands(), [&](Value v) { return cstr.getExpr(v); }));

65 minOp.getSymbolOperands(), [&](Value v) { return cstr.getExpr(v); }));

68 cstr.bound(value) <= bound;

69 }

70 };

71 };

72

73 struct AffineMaxOpInterface

74 : public ValueBoundsOpInterface::ExternalModel<AffineMaxOpInterface,

75 AffineMaxOp> {

76 void populateBoundsForIndexValue(Operation *op, Value value,

78 auto maxOp = cast(op);

79 assert(value == maxOp.getResult() && "invalid value");

80

81

82 for (AffineExpr expr : maxOp.getAffineMap().getResults()) {

84 maxOp.getDimOperands(), [&](Value v) { return cstr.getExpr(v); }));

86 maxOp.getSymbolOperands(), [&](Value v) { return cstr.getExpr(v); }));

89 cstr.bound(value) >= bound;

90 }

91 };

92 };

93

94 struct AffineDelinearizeIndexOpInterface

95 : public ValueBoundsOpInterface::ExternalModel<

96 AffineDelinearizeIndexOpInterface, AffineDelinearizeIndexOp> {

97 void populateBoundsForIndexValue(Operation *rawOp, Value value,

99 auto op = cast(rawOp);

100 auto result = cast(value);

101 assert(result.getOwner() == rawOp &&

102 "bounded value isn't a result of this delinearize_index");

103 unsigned resIdx = result.getResultNumber();

104

106

109 for (OpFoldResult basisElem : llvm::drop_begin(basis, resIdx + 1))

110 divisor = divisor * cstr.getExpr(basisElem);

111

112 if (resIdx == 0) {

113 cstr.bound(value) == linearIdx.floorDiv(divisor);

114 if (!basis.front().isNull())

115 cstr.bound(value) < cstr.getExpr(basis.front());

116 return;

117 }

119 cstr.bound(value) == (linearIdx % (thisBasis * divisor)).floorDiv(divisor);

120 }

121 };

122

123 struct AffineLinearizeIndexOpInterface

124 : public ValueBoundsOpInterface::ExternalModel<

125 AffineLinearizeIndexOpInterface, AffineLinearizeIndexOp> {

126 void populateBoundsForIndexValue(Operation *rawOp, Value value,

128 auto op = cast(rawOp);

129 assert(value == op.getResult() &&

130 "value isn't the result of this linearize");

131

135 OperandRange multiIndex = op.getMultiIndex();

136 unsigned numArgs = multiIndex.size();

137 for (auto [revArgNum, length] : llvm::enumerate(llvm::reverse(basis))) {

138 unsigned argNum = numArgs - (revArgNum + 1);

139 if (argNum == 0)

140 break;

142 bound = bound + cstr.getExpr(indexAsFoldRes) * stride;

143 stride = stride * cstr.getExpr(length);

144 }

145 bound = bound + cstr.getExpr(op.getMultiIndex().front()) * stride;

146 cstr.bound(value) == bound;

147 if (op.getDisjoint() && !basis.front().isNull()) {

148 cstr.bound(value) < stride *cstr.getExpr(basis.front());

149 }

150 }

151 };

152 }

153 }

154

158 AffineApplyOp::attachInterface(*ctx);

159 AffineMaxOp::attachInterface(*ctx);

160 AffineMinOp::attachInterface(*ctx);

161 AffineDelinearizeIndexOp::attachInterface<

162 AffineDelinearizeIndexOpInterface>(*ctx);

163 AffineLinearizeIndexOp::attachInterface(

164 *ctx);

165 });

166 }

167

168 FailureOr<int64_t>

170 assert(value1.getType().isIndex() && "expected index type");

171 assert(value2.getType().isIndex() && "expected index type");

172

173

174

178

179

180

182 mapOperands.push_back(value1);

183 mapOperands.push_back(value2);

188 }

Base type for affine expression.

AffineExpr replaceDimsAndSymbols(ArrayRef< AffineExpr > dimReplacements, ArrayRef< AffineExpr > symReplacements) const

This method substitutes any uses of dimensions and symbols (e.g.

AffineExpr floorDiv(uint64_t v) const

A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.

static AffineMap get(MLIRContext *context)

Returns a zero result affine map with no dimensions or symbols: () -> ().

unsigned getNumSymbols() const

unsigned getNumDims() const

AffineExpr getResult(unsigned idx) const

This class is a general helper class for creating context-global objects like types,...

AffineExpr getAffineDimExpr(unsigned position)

The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.

bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)

Add the given extension to the registry.

MLIRContext is the top-level object for a collection of MLIR operations.

This class represents a single result from folding an operation.

This class implements the operand iterators for the Operation class.

Operation is the basic unit of execution within MLIR.

OpResult getResult(unsigned idx)

Get the 'idx'th result of this operation.

A variable that can be added to the constraint set as a "column".

A helper class to be used with ValueBoundsOpInterface.

AffineExpr getExpr(Value value, std::optional< int64_t > dim=std::nullopt)

Return an expression that represents the given index-typed value or shaped value dimension.

BoundBuilder bound(Value value)

Add a bound for the given index-typed value or shaped value.

static FailureOr< int64_t > computeConstantBound(presburger::BoundType type, const Variable &var, StopConditionFn stopCondition=nullptr, bool closedUB=false)

Compute a constant bound for the given variable.

This class represents an instance of an SSA value in the MLIR system, representing a computable value...

MLIRContext * getContext() const

Utility to get the associated MLIRContext that this value is defined in.

Type getType() const

Return the type of this value.

void fullyComposeAffineMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)

Given an affine map map and its input operands, this method composes into map, maps of AffineApplyOps...

void registerValueBoundsOpInterfaceExternalModels(DialectRegistry &registry)

FailureOr< int64_t > fullyComposeAndComputeConstantDelta(Value value1, Value value2)

Compute a constant delta of the given two values.

constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)

Include the generated interface declarations.

OpFoldResult getAsOpFoldResult(Value val)

Given a value, try to extract a constant Attribute.