AffineMap(const AffineMap &other) : map(other.map) {}
AffineMap &operator=(const AffineMap &other) = default;
+ /// Returns a zero result affine map with no dimensions or symbols: () -> ().
+ static AffineMap get(MLIRContext *context);
+
static AffineMap get(unsigned dimCount, unsigned symbolCount,
ArrayRef<AffineExpr> results);
private:
ImplType *map;
+
+ static AffineMap getImpl(unsigned dimCount, unsigned symbolCount,
+ ArrayRef<AffineExpr> results, MLIRContext *context);
};
// Make AffineExpr hashable.
ArrayRef<AffineExpr> results);
// Special cases of affine maps and integer sets
+ /// Returns a zero result affine map with no dimensions or symbols: () -> ().
+ AffineMap getEmptyAffineMap();
/// Returns a single constant result affine map with 0 dimensions and 0
/// symbols. One constant result: () -> (val).
AffineMap getConstantAffineMap(int64_t val);
result->addOperands(memref);
result->addOperands(indices);
auto memrefType = memref->getType().cast<MemRefType>();
- auto map = builder->getMultiDimIdentityMap(memrefType.getRank());
+ auto rank = memrefType.getRank();
+ // Create identity map for memrefs with at least one dimension or () -> ()
+ // for zero-dimensional memrefs.
+ auto map = rank ? builder->getMultiDimIdentityMap(rank)
+ : builder->getEmptyAffineMap();
result->addAttribute(getMapAttrName(), builder->getAffineMapAttr(map));
result->types.push_back(memrefType.getElementType());
}
return IntegerSet::get(dimCount, symbolCount, constraints, isEq);
}
+AffineMap Builder::getEmptyAffineMap() { return AffineMap::get(context); }
+
AffineMap Builder::getConstantAffineMap(int64_t val) {
return AffineMap::get(/*dimCount=*/0, /*symbolCount=*/0,
{getAffineConstantExpr(val)});
return getImpl().affineUniquer;
}
-AffineMap AffineMap::get(unsigned dimCount, unsigned symbolCount,
- ArrayRef<AffineExpr> results) {
- // The number of results can't be zero.
- assert(!results.empty());
-
- auto &impl = results[0].getContext()->getImpl();
+AffineMap AffineMap::getImpl(unsigned dimCount, unsigned symbolCount,
+ ArrayRef<AffineExpr> results,
+ MLIRContext *context) {
+ auto &impl = context->getImpl();
auto key = std::make_tuple(dimCount, symbolCount, results);
// Safely get or create an AffineMap instance.
});
}
+AffineMap AffineMap::get(MLIRContext *context) {
+ return getImpl(/*dimCount=*/0, /*symbolCount=*/0, /*results=*/{}, context);
+}
+
+AffineMap AffineMap::get(unsigned dimCount, unsigned symbolCount,
+ ArrayRef<AffineExpr> results) {
+ // The number of results can't be zero.
+ assert(!results.empty());
+ return getImpl(dimCount, symbolCount, results, results[0].getContext());
+}
+
//===----------------------------------------------------------------------===//
// Integer Sets: these are allocated into the bump pointer, and are immutable.
// Unlike AffineMap's, these are uniqued only if they are small.
// CHECK: affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>
}
return
-}
\ No newline at end of file
+}
+
+// -----
+
+// Test with zero-dimensional operands.
+func @zero_dim(%arg0 : memref<i32>, %arg1 : memref<i32>) {
+ %0 = affine.load %arg0[] : memref<i32>
+ affine.store %0, %arg1[] : memref<i32>
+ // CHECK: affine.load %{{.*}}[] : memref<i32>
+ // CHECK: affine.store %{{.*}}, %{{.*}}[] : memref<i32>
+ return
+}
return
}
+// Test with zero-dimensional operands using no index in load/store.
+// CHECK-LABEL: func @zero_dim_no_idx
+func @zero_dim_no_idx(%arg0 : memref<i32>, %arg1 : memref<i32>, %arg2 : memref<i32>) {
+ %0 = std.load %arg0[] : memref<i32>
+ std.store %0, %arg1[] : memref<i32>
+ return
+ // CHECK: %0 = load %{{.*}}[] : memref<i32>
+ // CHECK: store %{{.*}}, %{{.*}}[] : memref<i32>
+}
+
// CHECK-LABEL: func @return_op(%arg0: i32) -> i32 {
func @return_op(%a : i32) -> i32 {
// CHECK: return %arg0 : i32
func @bool_literal_in_non_bool_tensor() {
// expected-error @+1 {{expected i1 type for 'true' or 'false' values}}
"foo"() {bar = dense<true> : tensor<2xi16>} : () -> ()
-}
\ No newline at end of file
+}