//===- Utils.h - Utils for Presburger Tests ---------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines helper functions for Presburger unittests. // //===----------------------------------------------------------------------===// #ifndef MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H #define MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H #include "../../Dialect/Affine/Analysis/AffineStructuresParser.h" #include "mlir/Analysis/Presburger/IntegerRelation.h" #include "mlir/Analysis/Presburger/PWMAFunction.h" #include "mlir/Analysis/Presburger/PresburgerRelation.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Support/LLVM.h" #include namespace mlir { namespace presburger { /// Parses a IntegerPolyhedron from a StringRef. It is expected that the /// string represents a valid IntegerSet, otherwise it will violate a gtest /// assertion. inline IntegerPolyhedron parsePoly(StringRef str) { MLIRContext context(MLIRContext::Threading::DISABLED); FailureOr poly = parseIntegerSetToFAC(str, &context); EXPECT_TRUE(succeeded(poly)); return *poly; } /// Parse a list of StringRefs to IntegerRelation and combine them into a /// PresburgerSet be using the union operation. It is expected that the strings /// are all valid IntegerSet representation and that all of them have the same /// number of dimensions as is specified by the numDims argument. inline PresburgerSet parsePresburgerSetFromPolyStrings(unsigned numDims, ArrayRef strs) { PresburgerSet set = PresburgerSet::getEmpty(PresburgerSpace::getSetSpace(numDims)); for (StringRef str : strs) set.unionInPlace(parsePoly(str)); return set; } inline Matrix makeMatrix(unsigned numRow, unsigned numColumns, ArrayRef> matrix) { Matrix results(numRow, numColumns); assert(matrix.size() == numRow); for (unsigned i = 0; i < numRow; ++i) { assert(matrix[i].size() == numColumns && "Output expression has incorrect dimensionality!"); for (unsigned j = 0; j < numColumns; ++j) results(i, j) = matrix[i][j]; } return results; } /// Construct a PWMAFunction given the dimensionalities and an array describing /// the list of pieces. Each piece is given by a string describing the domain /// and a 2D array that represents the output. inline PWMAFunction parsePWMAF( unsigned numInputs, unsigned numOutputs, ArrayRef, 8>>> data, unsigned numSymbols = 0) { static MLIRContext context; PWMAFunction result( PresburgerSpace::getSetSpace(numInputs - numSymbols, numSymbols), numOutputs); for (const auto &pair : data) { IntegerPolyhedron domain = parsePoly(pair.first); result.addPiece( domain, makeMatrix(numOutputs, domain.getNumVars() + 1, pair.second)); } return result; } /// lhs and rhs represent non-negative integers or positive infinity. The /// infinity case corresponds to when the Optional is empty. inline bool infinityOrUInt64LE(Optional lhs, Optional rhs) { // No constraint. if (!rhs) return true; // Finite rhs provided so lhs has to be finite too. if (!lhs) return false; return *lhs <= *rhs; } /// Expect that the computed volume is a valid overapproximation of /// the true volume `trueVolume`, while also being at least as good an /// approximation as `resultBound`. inline void expectComputedVolumeIsValidOverapprox(Optional computedVolume, Optional trueVolume, Optional resultBound) { assert(infinityOrUInt64LE(trueVolume, resultBound) && "can't expect result to be less than the true volume"); EXPECT_TRUE(infinityOrUInt64LE(trueVolume, computedVolume)); EXPECT_TRUE(infinityOrUInt64LE(computedVolume, resultBound)); } } // namespace presburger } // namespace mlir #endif // MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H