31 std::default_initializable<Val> &&
requires(Val lhs, Val rhs, mlir::raw_ostream &os) {
33 { os << lhs } -> std::same_as<mlir::raw_ostream &>;
35 { lhs == rhs } -> std::same_as<bool>;
37 { lhs.join(rhs) } -> std::same_as<Val &>;
40template <
typename Derived, ScalarLatticeValue ScalarTy>
class AbstractLatticeValue {
50 using ArrayTy = std::vector<std::unique_ptr<Derived>>;
54 static ArrayTy constructArrayTy(
const mlir::ArrayRef<int64_t> &shape) {
56 for (
auto dim : shape) {
57 ensure(!mlir::ShapedType::isDynamic(dim),
"Cannot pre-allocate dynamically-sized array");
60 ArrayTy arr(totalElem);
61 for (
auto it = arr.begin(); it != arr.end(); it++) {
62 *it = std::make_unique<Derived>();
67 static inline bool isDynamicArray(
const mlir::ArrayRef<int64_t> &shape) {
68 return mlir::ShapedType::isDynamicShape(shape);
71 explicit AbstractLatticeValue(ScalarTy s)
72 : value(s), arrayShape(std::nullopt), isDynamic(
false) {}
73 AbstractLatticeValue() : AbstractLatticeValue(ScalarTy()) {}
74 explicit AbstractLatticeValue(
const mlir::ArrayRef<int64_t> shape)
79 value = constructArrayTy(shape);
83 AbstractLatticeValue(
const AbstractLatticeValue &rhs) { *
this = rhs; }
84 AbstractLatticeValue(AbstractLatticeValue &&rhs) =
default;
87 AbstractLatticeValue &operator=(
const AbstractLatticeValue &rhs) {
89 if (rhs.
isScalar() || rhs.isDynamicArray()) {
96 for (
unsigned i = 0; i < lhsArr.size(); i++) {
98 *lhsArr[i] = *rhsArr[i];
103 AbstractLatticeValue &operator=(AbstractLatticeValue &&rhs) =
default;
106 bool isScalar()
const {
return std::holds_alternative<ScalarTy>(value); }
108 bool isArray()
const {
return std::holds_alternative<ArrayTy>(value); }
113 return std::get<ScalarTy>(value);
118 return std::get<ScalarTy>(value);
123 return std::get<ArrayTy>(value);
128 return std::get<ArrayTy>(value);
135 ensure(i < arr.size(),
"index out of range");
142 ensure(i < arr.size(),
"index out of range");
150 void print(mlir::raw_ostream &os)
const {
156 for (
auto it = arr.begin(); it != arr.end();) {
159 if (it != arr.end()) {
186 mlir::ChangeResult
setValue(
const AbstractLatticeValue &rhs) {
188 return mlir::ChangeResult::NoChange;
191 return mlir::ChangeResult::Change;
195 mlir::ChangeResult
update(
const Derived &rhs) {
220 std::variant<ScalarTy, ArrayTy> &
getValue() {
return value; }
223 ensure(arrayShape != std::nullopt,
"not an array value");
224 return arrayShape.value();
229 ensure(i < arrShape.size(),
"dimension index out of bounds");
230 return arrShape.at(i);
234 arrayShape = rhs.arrayShape;
235 isDynamic = rhs.isDynamic;
243 return mlir::ChangeResult::NoChange;
246 return mlir::ChangeResult::Change;
251 mlir::ChangeResult res = mlir::ChangeResult::NoChange;
254 res |= lhs[i]->update(*rhs.at(i));
263 auto rhsScalar = rhs.foldToScalar();
264 folded.join(rhsScalar);
266 return mlir::ChangeResult::NoChange;
269 return mlir::ChangeResult::Change;
273 std::variant<ScalarTy, ArrayTy> value;
274 std::optional<std::vector<int64_t>> arrayShape;