1//===- Utils.h - Utils for Presburger Tests ---------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines helper functions for Presburger unittests.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H
14#define MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H
15
16#include "mlir/Analysis/Presburger/GeneratingFunction.h"
17#include "mlir/Analysis/Presburger/IntegerRelation.h"
18#include "mlir/Analysis/Presburger/Matrix.h"
19#include "mlir/Analysis/Presburger/PWMAFunction.h"
20#include "mlir/Analysis/Presburger/PresburgerRelation.h"
21#include "mlir/Analysis/Presburger/QuasiPolynomial.h"
22#include "mlir/Analysis/Presburger/Simplex.h"
23#include "mlir/IR/MLIRContext.h"
24#include "mlir/Support/LLVM.h"
25
26#include <gtest/gtest.h>
27#include <optional>
28
29namespace mlir {
30namespace presburger {
31
32inline IntMatrix makeIntMatrix(unsigned numRow, unsigned numColumns,
33 ArrayRef<SmallVector<int, 8>> matrix) {
34 IntMatrix results(numRow, numColumns);
35 assert(matrix.size() == numRow);
36 for (unsigned i = 0; i < numRow; ++i) {
37 assert(matrix[i].size() == numColumns &&
38 "Output expression has incorrect dimensionality!");
39 for (unsigned j = 0; j < numColumns; ++j)
40 results(i, j) = MPInt(matrix[i][j]);
41 }
42 return results;
43}
44
45inline FracMatrix makeFracMatrix(unsigned numRow, unsigned numColumns,
46 ArrayRef<SmallVector<Fraction, 8>> matrix) {
47 FracMatrix results(numRow, numColumns);
48 assert(matrix.size() == numRow);
49 for (unsigned i = 0; i < numRow; ++i) {
50 assert(matrix[i].size() == numColumns &&
51 "Output expression has incorrect dimensionality!");
52 for (unsigned j = 0; j < numColumns; ++j)
53 results(i, j) = matrix[i][j];
54 }
55 return results;
56}
57
58inline void EXPECT_EQ_INT_MATRIX(IntMatrix a, IntMatrix b) {
59 EXPECT_EQ(a.getNumRows(), b.getNumRows());
60 EXPECT_EQ(a.getNumColumns(), b.getNumColumns());
61
62 for (unsigned row = 0; row < a.getNumRows(); row++)
63 for (unsigned col = 0; col < a.getNumColumns(); col++)
64 EXPECT_EQ(a(row, col), b(row, col));
65}
66
67inline void EXPECT_EQ_FRAC_MATRIX(FracMatrix a, FracMatrix b) {
68 EXPECT_EQ(a.getNumRows(), b.getNumRows());
69 EXPECT_EQ(a.getNumColumns(), b.getNumColumns());
70
71 for (unsigned row = 0; row < a.getNumRows(); row++)
72 for (unsigned col = 0; col < a.getNumColumns(); col++)
73 EXPECT_EQ(a(row, col), b(row, col));
74}
75
76// Check the coefficients (in order) of two generating functions.
77// Note that this is not a true equality check.
78inline void EXPECT_EQ_REPR_GENERATINGFUNCTION(detail::GeneratingFunction a,
79 detail::GeneratingFunction b) {
80 EXPECT_EQ(a.getNumParams(), b.getNumParams());
81
82 SmallVector<int> aSigns = a.getSigns();
83 SmallVector<int> bSigns = b.getSigns();
84 EXPECT_EQ(aSigns.size(), bSigns.size());
85 for (unsigned i = 0, e = aSigns.size(); i < e; i++)
86 EXPECT_EQ(aSigns[i], bSigns[i]);
87
88 std::vector<detail::ParamPoint> aNums = a.getNumerators();
89 std::vector<detail::ParamPoint> bNums = b.getNumerators();
90 EXPECT_EQ(aNums.size(), bNums.size());
91 for (unsigned i = 0, e = aNums.size(); i < e; i++)
92 EXPECT_EQ_FRAC_MATRIX(a: aNums[i], b: bNums[i]);
93
94 std::vector<std::vector<detail::Point>> aDens = a.getDenominators();
95 std::vector<std::vector<detail::Point>> bDens = b.getDenominators();
96 EXPECT_EQ(aDens.size(), bDens.size());
97 for (unsigned i = 0, e = aDens.size(); i < e; i++) {
98 EXPECT_EQ(aDens[i].size(), bDens[i].size());
99 for (unsigned j = 0, f = aDens[i].size(); j < f; j++) {
100 EXPECT_EQ(aDens[i][j].size(), bDens[i][j].size());
101 for (unsigned k = 0, g = aDens[i][j].size(); k < g; k++) {
102 EXPECT_EQ(aDens[i][j][k], bDens[i][j][k]);
103 }
104 }
105 }
106}
107
108// Check the coefficients (in order) of two quasipolynomials.
109// Note that this is not a true equality check.
110inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a,
111 QuasiPolynomial b) {
112 EXPECT_EQ(a.getNumInputs(), b.getNumInputs());
113
114 SmallVector<Fraction> aCoeffs = a.getCoefficients(),
115 bCoeffs = b.getCoefficients();
116 EXPECT_EQ(aCoeffs.size(), bCoeffs.size());
117 for (unsigned i = 0, e = aCoeffs.size(); i < e; i++)
118 EXPECT_EQ(aCoeffs[i], bCoeffs[i]);
119
120 std::vector<std::vector<SmallVector<Fraction>>> aAff = a.getAffine(),
121 bAff = b.getAffine();
122 EXPECT_EQ(aAff.size(), bAff.size());
123 for (unsigned i = 0, e = aAff.size(); i < e; i++) {
124 EXPECT_EQ(aAff[i].size(), bAff[i].size());
125 for (unsigned j = 0, f = aAff[i].size(); j < f; j++)
126 for (unsigned k = 0, g = a.getNumInputs(); k <= g; k++)
127 EXPECT_EQ(aAff[i][j][k], bAff[i][j][k]);
128 }
129}
130
131/// lhs and rhs represent non-negative integers or positive infinity. The
132/// infinity case corresponds to when the Optional is empty.
133inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,
134 std::optional<MPInt> rhs) {
135 // No constraint.
136 if (!rhs)
137 return true;
138 // Finite rhs provided so lhs has to be finite too.
139 if (!lhs)
140 return false;
141 return *lhs <= *rhs;
142}
143
144/// Expect that the computed volume is a valid overapproximation of
145/// the true volume `trueVolume`, while also being at least as good an
146/// approximation as `resultBound`.
147inline void expectComputedVolumeIsValidOverapprox(
148 const std::optional<MPInt> &computedVolume,
149 const std::optional<MPInt> &trueVolume,
150 const std::optional<MPInt> &resultBound) {
151 assert(infinityOrUInt64LE(trueVolume, resultBound) &&
152 "can't expect result to be less than the true volume");
153 EXPECT_TRUE(infinityOrUInt64LE(trueVolume, computedVolume));
154 EXPECT_TRUE(infinityOrUInt64LE(computedVolume, resultBound));
155}
156
157inline void expectComputedVolumeIsValidOverapprox(
158 const std::optional<MPInt> &computedVolume,
159 std::optional<int64_t> trueVolume, std::optional<int64_t> resultBound) {
160 expectComputedVolumeIsValidOverapprox(
161 computedVolume, trueVolume: llvm::transformOptional(O: trueVolume, F&: mpintFromInt64),
162 resultBound: llvm::transformOptional(O: resultBound, F&: mpintFromInt64));
163}
164
165} // namespace presburger
166} // namespace mlir
167
168#endif // MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H
169

source code of mlir/unittests/Analysis/Presburger/Utils.h