forked from OSchip/llvm-project
[mlir] Simplify and better document std.view semantics
This [discussion](https://llvm.discourse.group/t/viewop-isnt-expressive-enough/991/2) raised some concerns with ViewOp. In particular, the handling of offsets is incorrect and does not match the op description. Note that with an elemental type change, offsets cannot be part of the type in general because sizeof(srcType) != sizeof(dstType). Howerver, offset is a poorly chosen term for this purpose and is renamed to byte_shift. Additionally, for all intended purposes, trying to support non-identity layouts for this op does not bring expressive power but rather increases code complexity. This revision simplifies the existing semantics and implementation. This simplification effort is voluntarily restrictive and acts as a stepping stone towards supporting richer semantics: treat the non-common cases as YAGNI for now and reevaluate based on concrete use cases once a round of simplification occurred. Differential revision: https://reviews.llvm.org/D79541
This commit is contained in:
parent
f056dacbd7
commit
6ed61a26c2
|
@ -2982,63 +2982,58 @@ def ViewOp : Std_Op<"view", [
|
|||
DeclareOpInterfaceMethods<ViewLikeOpInterface>, NoSideEffect]> {
|
||||
let summary = "memref view operation";
|
||||
let description = [{
|
||||
The "view" operation converts a 1-D memref with i8 element type,
|
||||
to an N-D memref with arbitrary element type. In addition, the ViewOp
|
||||
supports the following arguments:
|
||||
*) A single dynamic offset operand can be specified which represents a
|
||||
a dynamic offset within the base 1-D memref at which to create the
|
||||
resulting memref view.
|
||||
*) A dynamic size operand must be specified for each dynamic dimension
|
||||
The "view" operation extracts an N-D contiguous memref with empty layout map
|
||||
with arbitrary element type from a 1-D contiguous memref with empty layout
|
||||
map of i8 element type. The ViewOp supports the following arguments:
|
||||
*) A single dynamic byte-shift operand must be specified which represents a
|
||||
a shift of the base 1-D memref pointer from which to create the resulting
|
||||
contiguous memref view with identity layout.
|
||||
*) A dynamic size operand that must be specified for each dynamic dimension
|
||||
in the resulting view memref type.
|
||||
|
||||
The "view" operation gives a structured indexing form to a flat 1-D buffer.
|
||||
Unlike "subview" it can perform a type change. The type change behavior
|
||||
requires the op to have special semantics because, e.g. a byte shift of 3
|
||||
cannot be represented as an offset on f64.
|
||||
For now, a "view" op:
|
||||
1) Only takes a contiguous source memref with 0 offset and empty layout.
|
||||
2) Must specify a byte_shift operand (in the future, a special integer
|
||||
attribute may be added to support the folded case).
|
||||
3) Returns a contiguous memref with 0 offset and empty layout.
|
||||
|
||||
Example:
|
||||
|
||||
```mlir
|
||||
// Allocate a flat 1D/i8 memref.
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
|
||||
// ViewOp with static offset and sizes.
|
||||
%1 = view %0[][] : memref<2048xi8> to memref<64x4xf32>
|
||||
// ViewOp with dynamic offset and static sizes.
|
||||
%1 = view %0[%offset_1024][] : memref<2048xi8> to memref<64x4xf32>
|
||||
|
||||
// ViewOp with dynamic offset and one dynamic size.
|
||||
%2 = view %0[%offset_1024][%size0]
|
||||
: memref<2048xi8> to memref<?x4xf32, (d0, d1)[s0] -> (d0 * 4 + d1 + s0)>
|
||||
|
||||
// ViewOp creating 3D shape where two of the dim sizes are dynamic.
|
||||
// *) The dynamic offset specified in the ViewOp is applied to the
|
||||
// base 1-D memref, and is represented by the symbol 's0' in the
|
||||
// layout map of the ViewOp result memref type.
|
||||
// *) The dynamic size for the second dimension induces a dynamic
|
||||
// stride for the first dimension, which is represented by the
|
||||
// symbol 's1' in the layout map of the ViewOp result memref type.
|
||||
// Note that this dynamic stride will be computed from the view
|
||||
// shape and dynamic sizes.
|
||||
%3 = view %0[%offset_1024][%size0, %size1]
|
||||
: memref<2048xi8> to memref<?x?x4xf32,
|
||||
(d0, d1, d2)[s0, s1] -> (d0 * s1 + d1 * 4 + d2 + s0)>
|
||||
// ViewOp with dynamic offset and two dynamic size.
|
||||
%2 = view %0[%offset_1024][%size0, %size1] :
|
||||
memref<2048xi8> to memref<?x4x?xf32>
|
||||
```
|
||||
}];
|
||||
|
||||
let arguments = (ins MemRefRankOf<[I8], [1]>:$source,
|
||||
Variadic<Index>:$operands);
|
||||
Index:$byte_shift,
|
||||
Variadic<Index>:$sizes);
|
||||
let results = (outs AnyMemRef);
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
/// The result of a view is always a memref.
|
||||
MemRefType getType() { return getResult().getType().cast<MemRefType>(); }
|
||||
|
||||
/// Returns the dynamic offset for this view operation if specified.
|
||||
/// Returns nullptr if no dynamic offset was specified.
|
||||
Value getDynamicOffset();
|
||||
|
||||
/// Returns the starting operand list position of the dynamic size operands.
|
||||
unsigned getDynamicSizesOperandStart() {
|
||||
return getDynamicOffset() == nullptr ? 1 : 2;
|
||||
}
|
||||
|
||||
/// Returns the dynamic sizes for this view operation.
|
||||
/// Returns the dynamic sizes for this view operation. This is redundant
|
||||
/// with `sizes` but needed in template implementations. More specifically:
|
||||
/// ```
|
||||
/// template <typename AnyMemRefDefOp>
|
||||
/// bool isMemRefSizeValidSymbol(AnyMemRefDefOp memrefDefOp, unsigned index,
|
||||
/// Region *region)
|
||||
/// ```
|
||||
operand_range getDynamicSizes() {
|
||||
return {operand_begin() + getDynamicSizesOperandStart(), operand_end()};
|
||||
return {sizes().begin(), sizes().end()};
|
||||
}
|
||||
}];
|
||||
|
||||
|
|
|
@ -2676,35 +2676,31 @@ struct ViewOpLowering : public ConvertOpToLLVMPattern<ViewOp> {
|
|||
auto successStrides = getStridesAndOffset(viewMemRefType, strides, offset);
|
||||
if (failed(successStrides))
|
||||
return op->emitWarning("cannot cast to non-strided shape"), failure();
|
||||
assert(offset == 0 && "expected offset to be 0");
|
||||
|
||||
// Create the descriptor.
|
||||
MemRefDescriptor sourceMemRef(adaptor.source());
|
||||
auto targetMemRef = MemRefDescriptor::undef(rewriter, loc, targetDescTy);
|
||||
|
||||
// Field 1: Copy the allocated pointer, used for malloc/free.
|
||||
Value extracted = sourceMemRef.allocatedPtr(rewriter, loc);
|
||||
Value allocatedPtr = sourceMemRef.allocatedPtr(rewriter, loc);
|
||||
Value bitcastPtr = rewriter.create<LLVM::BitcastOp>(
|
||||
loc, targetElementTy.getPointerTo(), extracted);
|
||||
loc, targetElementTy.getPointerTo(), allocatedPtr);
|
||||
targetMemRef.setAllocatedPtr(rewriter, loc, bitcastPtr);
|
||||
|
||||
// Field 2: Copy the actual aligned pointer to payload.
|
||||
extracted = sourceMemRef.alignedPtr(rewriter, loc);
|
||||
Value alignedPtr = sourceMemRef.alignedPtr(rewriter, loc);
|
||||
alignedPtr = rewriter.create<LLVM::GEPOp>(loc, alignedPtr.getType(),
|
||||
alignedPtr, adaptor.byte_shift());
|
||||
bitcastPtr = rewriter.create<LLVM::BitcastOp>(
|
||||
loc, targetElementTy.getPointerTo(), extracted);
|
||||
loc, targetElementTy.getPointerTo(), alignedPtr);
|
||||
targetMemRef.setAlignedPtr(rewriter, loc, bitcastPtr);
|
||||
|
||||
// Field 3: Copy the offset in aligned pointer.
|
||||
unsigned numDynamicSizes = llvm::size(viewOp.getDynamicSizes());
|
||||
(void)numDynamicSizes;
|
||||
bool hasDynamicOffset = offset == MemRefType::getDynamicStrideOrOffset();
|
||||
auto sizeAndOffsetOperands = adaptor.operands();
|
||||
assert(llvm::size(sizeAndOffsetOperands) ==
|
||||
numDynamicSizes + (hasDynamicOffset ? 1 : 0));
|
||||
Value baseOffset = !hasDynamicOffset
|
||||
? createIndexConstant(rewriter, loc, offset)
|
||||
// TODO(ntv): better adaptor.
|
||||
: sizeAndOffsetOperands.front();
|
||||
targetMemRef.setOffset(rewriter, loc, baseOffset);
|
||||
// Field 3: The offset in the resulting type must be 0. This is because of
|
||||
// the type change: an offset on srcType* may not be expressible as an
|
||||
// offset on dstType*.
|
||||
targetMemRef.setOffset(rewriter, loc,
|
||||
createIndexConstant(rewriter, loc, offset));
|
||||
|
||||
// Early exit for 0-D corner case.
|
||||
if (viewMemRefType.getRank() == 0)
|
||||
|
@ -2714,14 +2710,10 @@ struct ViewOpLowering : public ConvertOpToLLVMPattern<ViewOp> {
|
|||
if (strides.back() != 1)
|
||||
return op->emitWarning("cannot cast to non-contiguous shape"), failure();
|
||||
Value stride = nullptr, nextSize = nullptr;
|
||||
// Drop the dynamic stride from the operand list, if present.
|
||||
ArrayRef<Value> sizeOperands(sizeAndOffsetOperands);
|
||||
if (hasDynamicOffset)
|
||||
sizeOperands = sizeOperands.drop_front();
|
||||
for (int i = viewMemRefType.getRank() - 1; i >= 0; --i) {
|
||||
// Update size.
|
||||
Value size =
|
||||
getSize(rewriter, loc, viewMemRefType.getShape(), sizeOperands, i);
|
||||
getSize(rewriter, loc, viewMemRefType.getShape(), adaptor.sizes(), i);
|
||||
targetMemRef.setSize(rewriter, loc, i, size);
|
||||
// Update stride.
|
||||
stride = getStride(rewriter, loc, strides, nextSize, stride, i);
|
||||
|
|
|
@ -169,7 +169,7 @@ static PromotionInfo promoteSubviewAsNewBuffer(OpBuilder &b, Location loc,
|
|||
dynamicBuffers, folder, alignment);
|
||||
auto fullLocalView = folded_std_view(
|
||||
folder, MemRefType::get(dynSizes, viewType.getElementType()), buffer,
|
||||
fullSizes);
|
||||
folded_std_constant_index(folder, 0), fullSizes);
|
||||
SmallVector<Value, 4> zeros(fullSizes.size(), zero);
|
||||
SmallVector<Value, 4> ones(fullSizes.size(), one);
|
||||
auto partialLocalView =
|
||||
|
|
|
@ -2759,8 +2759,8 @@ static ParseResult parseViewOp(OpAsmParser &parser, OperationState &result) {
|
|||
parser.parseOperandList(offsetInfo, OpAsmParser::Delimiter::Square))
|
||||
return failure();
|
||||
|
||||
if (offsetInfo.size() > 1)
|
||||
return parser.emitError(offsetLoc) << "expects 0 or 1 offset operand";
|
||||
if (offsetInfo.size() != 1)
|
||||
return parser.emitError(offsetLoc) << "expects 1 offset operand";
|
||||
|
||||
return failure(
|
||||
parser.parseOperandList(sizesInfo, OpAsmParser::Delimiter::Square) ||
|
||||
|
@ -2775,44 +2775,15 @@ static ParseResult parseViewOp(OpAsmParser &parser, OperationState &result) {
|
|||
|
||||
static void print(OpAsmPrinter &p, ViewOp op) {
|
||||
p << op.getOperationName() << ' ' << op.getOperand(0) << '[';
|
||||
auto dynamicOffset = op.getDynamicOffset();
|
||||
if (dynamicOffset != nullptr)
|
||||
p.printOperand(dynamicOffset);
|
||||
p << "][" << op.getDynamicSizes() << ']';
|
||||
p.printOperand(op.byte_shift());
|
||||
p << "][" << op.sizes() << ']';
|
||||
p.printOptionalAttrDict(op.getAttrs());
|
||||
p << " : " << op.getOperand(0).getType() << " to " << op.getType();
|
||||
}
|
||||
|
||||
Value ViewOp::getDynamicOffset() {
|
||||
int64_t offset;
|
||||
SmallVector<int64_t, 4> strides;
|
||||
auto result =
|
||||
succeeded(mlir::getStridesAndOffset(getType(), strides, offset));
|
||||
assert(result);
|
||||
if (result && offset == MemRefType::getDynamicStrideOrOffset())
|
||||
return getOperand(1);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LogicalResult verifyDynamicStrides(MemRefType memrefType,
|
||||
ArrayRef<int64_t> strides) {
|
||||
unsigned rank = memrefType.getRank();
|
||||
assert(rank == strides.size());
|
||||
bool dynamicStrides = false;
|
||||
for (int i = rank - 2; i >= 0; --i) {
|
||||
// If size at dim 'i + 1' is dynamic, set the 'dynamicStrides' flag.
|
||||
if (memrefType.isDynamicDim(i + 1))
|
||||
dynamicStrides = true;
|
||||
// If stride at dim 'i' is not dynamic, return error.
|
||||
if (dynamicStrides && strides[i] != MemRefType::getDynamicStrideOrOffset())
|
||||
return failure();
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
static LogicalResult verify(ViewOp op) {
|
||||
auto baseType = op.getOperand(0).getType().cast<MemRefType>();
|
||||
auto viewType = op.getResult().getType().cast<MemRefType>();
|
||||
auto viewType = op.getType();
|
||||
|
||||
// The base memref should have identity layout map (or none).
|
||||
if (baseType.getAffineMaps().size() > 1 ||
|
||||
|
@ -2820,32 +2791,24 @@ static LogicalResult verify(ViewOp op) {
|
|||
!baseType.getAffineMaps()[0].isIdentity()))
|
||||
return op.emitError("unsupported map for base memref type ") << baseType;
|
||||
|
||||
// The result memref should have identity layout map (or none).
|
||||
if (viewType.getAffineMaps().size() > 1 ||
|
||||
(viewType.getAffineMaps().size() == 1 &&
|
||||
!viewType.getAffineMaps()[0].isIdentity()))
|
||||
return op.emitError("unsupported map for result memref type ") << viewType;
|
||||
|
||||
// The base memref and the view memref should be in the same memory space.
|
||||
if (baseType.getMemorySpace() != viewType.getMemorySpace())
|
||||
return op.emitError("different memory spaces specified for base memref "
|
||||
"type ")
|
||||
<< baseType << " and view memref type " << viewType;
|
||||
|
||||
// Verify that the result memref type has a strided layout map.
|
||||
int64_t offset;
|
||||
SmallVector<int64_t, 4> strides;
|
||||
if (failed(getStridesAndOffset(viewType, strides, offset)))
|
||||
return op.emitError("result type ") << viewType << " is not strided";
|
||||
|
||||
// Verify that we have the correct number of operands for the result type.
|
||||
unsigned memrefOperandCount = 1;
|
||||
// Verify that we have the correct number of sizes for the result type.
|
||||
unsigned numDynamicDims = viewType.getNumDynamicDims();
|
||||
unsigned dynamicOffsetCount =
|
||||
offset == MemRefType::getDynamicStrideOrOffset() ? 1 : 0;
|
||||
if (op.getNumOperands() !=
|
||||
memrefOperandCount + numDynamicDims + dynamicOffsetCount)
|
||||
return op.emitError("incorrect number of operands for type ") << viewType;
|
||||
|
||||
// Verify dynamic strides symbols were added to correct dimensions based
|
||||
// on dynamic sizes.
|
||||
if (failed(verifyDynamicStrides(viewType, strides)))
|
||||
return op.emitError("incorrect dynamic strides in view memref type ")
|
||||
if (op.sizes().size() != numDynamicDims)
|
||||
return op.emitError("incorrect number of size operands for type ")
|
||||
<< viewType;
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
|
@ -2866,42 +2829,23 @@ struct ViewOpShapeFolder : public OpRewritePattern<ViewOp> {
|
|||
|
||||
// Get result memref type.
|
||||
auto memrefType = viewOp.getType();
|
||||
if (memrefType.getAffineMaps().size() > 1)
|
||||
return failure();
|
||||
auto map = memrefType.getAffineMaps().empty()
|
||||
? AffineMap::getMultiDimIdentityMap(memrefType.getRank(),
|
||||
rewriter.getContext())
|
||||
: memrefType.getAffineMaps()[0];
|
||||
|
||||
// Get offset from old memref view type 'memRefType'.
|
||||
int64_t oldOffset;
|
||||
SmallVector<int64_t, 4> oldStrides;
|
||||
if (failed(getStridesAndOffset(memrefType, oldStrides, oldOffset)))
|
||||
return failure();
|
||||
assert(oldOffset == 0 && "Expected 0 offset");
|
||||
|
||||
SmallVector<Value, 4> newOperands;
|
||||
|
||||
// Fold dynamic offset operand if it is produced by a constant.
|
||||
auto dynamicOffset = viewOp.getDynamicOffset();
|
||||
int64_t newOffset = oldOffset;
|
||||
unsigned dynamicOffsetOperandCount = 0;
|
||||
if (dynamicOffset != nullptr) {
|
||||
auto *defOp = dynamicOffset.getDefiningOp();
|
||||
if (auto constantIndexOp = dyn_cast_or_null<ConstantIndexOp>(defOp)) {
|
||||
// Dynamic offset will be folded into the map.
|
||||
newOffset = constantIndexOp.getValue();
|
||||
} else {
|
||||
// Unable to fold dynamic offset. Add it to 'newOperands' list.
|
||||
newOperands.push_back(dynamicOffset);
|
||||
dynamicOffsetOperandCount = 1;
|
||||
}
|
||||
}
|
||||
// Offset cannot be folded into result type.
|
||||
|
||||
// Fold any dynamic dim operands which are produced by a constant.
|
||||
SmallVector<int64_t, 4> newShapeConstants;
|
||||
newShapeConstants.reserve(memrefType.getRank());
|
||||
|
||||
unsigned dynamicDimPos = viewOp.getDynamicSizesOperandStart();
|
||||
unsigned dynamicDimPos = 0;
|
||||
unsigned rank = memrefType.getRank();
|
||||
for (unsigned dim = 0, e = rank; dim < e; ++dim) {
|
||||
int64_t dimSize = memrefType.getDimSize(dim);
|
||||
|
@ -2910,46 +2854,29 @@ struct ViewOpShapeFolder : public OpRewritePattern<ViewOp> {
|
|||
newShapeConstants.push_back(dimSize);
|
||||
continue;
|
||||
}
|
||||
auto *defOp = viewOp.getOperand(dynamicDimPos).getDefiningOp();
|
||||
auto *defOp = viewOp.sizes()[dynamicDimPos].getDefiningOp();
|
||||
if (auto constantIndexOp = dyn_cast_or_null<ConstantIndexOp>(defOp)) {
|
||||
// Dynamic shape dimension will be folded.
|
||||
newShapeConstants.push_back(constantIndexOp.getValue());
|
||||
} else {
|
||||
// Dynamic shape dimension not folded; copy operand from old memref.
|
||||
newShapeConstants.push_back(dimSize);
|
||||
newOperands.push_back(viewOp.getOperand(dynamicDimPos));
|
||||
newOperands.push_back(viewOp.sizes()[dynamicDimPos]);
|
||||
}
|
||||
dynamicDimPos++;
|
||||
}
|
||||
|
||||
// Compute new strides based on 'newShapeConstants'.
|
||||
SmallVector<int64_t, 4> newStrides(rank);
|
||||
newStrides[rank - 1] = 1;
|
||||
bool dynamicStrides = false;
|
||||
for (int i = rank - 2; i >= 0; --i) {
|
||||
if (ShapedType::isDynamic(newShapeConstants[i + 1]))
|
||||
dynamicStrides = true;
|
||||
if (dynamicStrides)
|
||||
newStrides[i] = MemRefType::getDynamicStrideOrOffset();
|
||||
else
|
||||
newStrides[i] = newShapeConstants[i + 1] * newStrides[i + 1];
|
||||
}
|
||||
|
||||
// Regenerate strided layout map with 'newStrides' and 'newOffset'.
|
||||
map = makeStridedLinearLayoutMap(newStrides, newOffset,
|
||||
rewriter.getContext());
|
||||
|
||||
// Create new memref type with constant folded dims and/or offset/strides.
|
||||
MemRefType newMemRefType = MemRefType::Builder(memrefType)
|
||||
.setShape(newShapeConstants)
|
||||
.setAffineMaps({map});
|
||||
(void)dynamicOffsetOperandCount; // unused in opt mode
|
||||
assert(static_cast<int64_t>(newOperands.size()) ==
|
||||
dynamicOffsetOperandCount + newMemRefType.getNumDynamicDims());
|
||||
// Create new memref type with constant folded dims.
|
||||
MemRefType newMemRefType =
|
||||
MemRefType::Builder(memrefType).setShape(newShapeConstants);
|
||||
// Nothing new, don't fold.
|
||||
if (newMemRefType == memrefType)
|
||||
return failure();
|
||||
|
||||
// Create new ViewOp.
|
||||
auto newViewOp = rewriter.create<ViewOp>(viewOp.getLoc(), newMemRefType,
|
||||
viewOp.getOperand(0), newOperands);
|
||||
viewOp.getOperand(0),
|
||||
viewOp.byte_shift(), newOperands);
|
||||
// Insert a cast so we have the same type as the old memref type.
|
||||
rewriter.replaceOpWithNewOp<MemRefCastOp>(viewOp, newViewOp,
|
||||
viewOp.getType());
|
||||
|
@ -2972,7 +2899,7 @@ struct ViewOpMemrefCastFolder : public OpRewritePattern<ViewOp> {
|
|||
if (!allocOp)
|
||||
return failure();
|
||||
rewriter.replaceOpWithNewOp<ViewOp>(viewOp, viewOp.getType(), allocOperand,
|
||||
viewOp.operands());
|
||||
viewOp.byte_shift(), viewOp.sizes());
|
||||
return success();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -773,43 +773,30 @@ func @view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
|||
// CHECK: llvm.mlir.undef : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
|
||||
// Test two dynamic sizes and dynamic offset.
|
||||
// Test two dynamic sizes.
|
||||
// CHECK: llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: llvm.bitcast %{{.*}} : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG2]], %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[BASE_PTR:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: %[[SHIFTED_BASE_PTR:.*]] = llvm.getelementptr %[[BASE_PTR]][%[[ARG2]]] : (!llvm<"i8*">, !llvm.i64) -> !llvm<"i8*">
|
||||
// CHECK: %[[CAST_SHIFTED_BASE_PTR:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR]] : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR]], %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %[[C0]], %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG1]], %{{.*}}[3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(1 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG0]], %{{.*}}[3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mul %{{.*}}, %[[ARG1]]
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
%1 = view %0[%arg2][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 + s1)>>
|
||||
%1 = view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref<?x?xf32>
|
||||
|
||||
// Test two dynamic sizes and static offset.
|
||||
// Test one dynamic size.
|
||||
// CHECK: llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: llvm.bitcast %{{.*}} : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(0 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(1 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %arg0, %{{.*}}[3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mul %{{.*}}, %[[ARG1]]
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
%2 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0 * s0 + d1)>>
|
||||
|
||||
// Test one dynamic size and dynamic offset.
|
||||
// CHECK: llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: llvm.bitcast %{{.*}} : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG2]], %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[BASE_PTR_2:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: %[[SHIFTED_BASE_PTR_2:.*]] = llvm.getelementptr %[[BASE_PTR_2]][%[[ARG2]]] : (!llvm<"i8*">, !llvm.i64) -> !llvm<"i8*">
|
||||
// CHECK: %[[CAST_SHIFTED_BASE_PTR_2:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR_2]] : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR_2]], %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[C0_2:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %[[C0_2]], %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG1]], %{{.*}}[3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(1 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
|
@ -817,33 +804,16 @@ func @view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
|||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mul %{{.*}}, %[[ARG1]]
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
%3 = view %0[%arg2][%arg1]
|
||||
: memref<2048xi8> to memref<4x?xf32, affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 + s1)>>
|
||||
%3 = view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32>
|
||||
|
||||
// Test one dynamic size and static offset.
|
||||
// Test static sizes.
|
||||
// CHECK: llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: llvm.bitcast %{{.*}} : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(0 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(16 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(1 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG0]], %{{.*}}[3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(4 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
%4 = view %0[][%arg0]
|
||||
: memref<2048xi8> to memref<?x16xf32, affine_map<(d0, d1) -> (d0 * 4 + d1)>>
|
||||
|
||||
// Test static sizes and static offset.
|
||||
// CHECK: llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: llvm.bitcast %{{.*}} : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(0 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[BASE_PTR_3:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: %[[SHIFTED_BASE_PTR_3:.*]] = llvm.getelementptr %[[BASE_PTR_3]][%[[ARG2]]] : (!llvm<"i8*">, !llvm.i64) -> !llvm<"i8*">
|
||||
// CHECK: %[[CAST_SHIFTED_BASE_PTR_3:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR_3]] : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR_3]], %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[C0_3:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %[[C0_3]], %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(4 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(1 : index) : !llvm.i64
|
||||
|
@ -852,23 +822,7 @@ func @view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
|||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mlir.constant(4 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
%5 = view %0[][]
|
||||
: memref<2048xi8> to memref<64x4xf32, affine_map<(d0, d1) -> (d0 * 4 + d1)>>
|
||||
|
||||
// Test dynamic everything.
|
||||
// CHECK: llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, i8*, i64, [1 x i64], [1 x i64] }">
|
||||
// CHECK: llvm.bitcast %{{.*}} : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG2]], %{{.*}}[2] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG1]], %{{.*}}[3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: %[[STRIDE_1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %[[STRIDE_1]], %{{.*}}[4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.insertvalue %[[ARG0]], %{{.*}}[3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
// CHECK: llvm.mul %[[STRIDE_1]], %[[ARG1]] : !llvm.i64
|
||||
// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
|
||||
%6 = view %0[%arg2][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 + s1)>>
|
||||
%5 = view %0[%arg2][] : memref<2048xi8> to memref<64x4xf32>
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// Test that we can lower all the way to LLVM without crashing, don't check results here.
|
||||
// RUN: mlir-opt %s -convert-linalg-to-affine-loops -convert-linalg-to-llvm -o=/dev/null 2>&1
|
||||
|
||||
// CHECK-DAG: #[[strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
|
||||
// CHECK-DAG: #[[strided3D:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2 + d2)>
|
||||
|
||||
// CHECK-DAG: #[[stride2Dilation1:.*]] = affine_map<(d0, d1) -> (d0 * 2 + d1)>
|
||||
|
@ -13,10 +12,10 @@
|
|||
func @matmul(%arg0: memref<?xi8>, %M: index, %N: index, %K: index) {
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%A = view %arg0[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%B = view %arg0[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%C = view %arg0[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
linalg.matmul(%A, %B, %C) : memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%A = view %arg0[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32>
|
||||
%B = view %arg0[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
%C = view %arg0[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
linalg.matmul(%A, %B, %C) : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -24,18 +23,18 @@ func @matmul(%arg0: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
// CHECK-SAME: [[M:arg[0-9]+]]: index
|
||||
// CHECK-SAME: [[N:arg[0-9]+]]: index
|
||||
// CHECK-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECK: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: affine.for %{{.*}} = 0 to %{{.*}} {
|
||||
// CHECK: affine.for %{{.*}} = 0 to %{{.*}} {
|
||||
// CHECK: affine.for %{{.*}} = 0 to %{{.*}} {
|
||||
// CHECK-DAG: %[[a:.*]] = affine.load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK-DAG: %[[b:.*]] = affine.load %[[B]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK-DAG: %[[a:.*]] = affine.load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECK-DAG: %[[b:.*]] = affine.load %[[B]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECK-DAG: %[[c:.*]] = affine.load %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK-DAG: %[[c:.*]] = affine.load %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
// CHECK: affine.store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: affine.store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
|
||||
func @conv_view3(%arg0: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, %arg1: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, %arg2: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
|
||||
linalg.conv(%arg0, %arg1, %arg2) {strides = [2]}: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>
|
||||
|
|
|
@ -7,7 +7,7 @@ func @memref_cast(%a: index, %b: index) -> memref<?x?xf32> {
|
|||
%c8 = constant 8 : index
|
||||
%c16 = constant 16 : index
|
||||
%1 = alloc (%b) : memref<?xi8>
|
||||
%2 = view %1[][] : memref<?xi8> to memref<16x16xf32>
|
||||
%2 = view %1[%c0][] : memref<?xi8> to memref<16x16xf32>
|
||||
%3 = memref_cast %2 : memref<16x16xf32> to memref<?x?xf32>
|
||||
%r0 = linalg.range %c0:%c8:%c1 : !linalg.range
|
||||
|
||||
|
|
|
@ -30,104 +30,104 @@
|
|||
func @matmul(%arg0: memref<?xi8>, %M: index, %N: index, %K: index) {
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%A = view %arg0[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%B = view %arg0[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%C = view %arg0[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
linalg.matmul(%A, %B, %C) : memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%A = view %arg0[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32>
|
||||
%B = view %arg0[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
%C = view %arg0[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
linalg.matmul(%A, %B, %C) : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
// CHECKLOOP-LABEL: func @matmul(%{{.*}}: memref<?xi8>,
|
||||
// CHECKLOOP-SAME: [[M:arg[0-9]+]]: index
|
||||
// CHECKLOOP-SAME: [[N:arg[0-9]+]]: index
|
||||
// CHECKLOOP-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECKLOOP: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKLOOP: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKLOOP: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKLOOP: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
|
||||
// CHECKLOOP: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
|
||||
// CHECKLOOP: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
|
||||
// CHECKLOOP-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP-DAG: %[[b:.*]] = load %[[B]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKLOOP-DAG: %[[b:.*]] = load %[[B]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKLOOP-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECKLOOP-DAG: %[[c:.*]] = load %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP-DAG: %[[c:.*]] = load %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKLOOP-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
// CHECKLOOP: store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP: store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
|
||||
// CHECKPARALLEL-LABEL: func @matmul(%{{.*}}: memref<?xi8>,
|
||||
// CHECKPARALLEL-SAME: [[M:arg[0-9]+]]: index
|
||||
// CHECKPARALLEL-SAME: [[N:arg[0-9]+]]: index
|
||||
// CHECKPARALLEL-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECKPARALLEL: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKPARALLEL: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKPARALLEL: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKPARALLEL: loop.parallel (%{{.*}}, %{{.*}}) = (%{{.*}}, %{{.*}}) to (%[[M]], %[[N]]) step (%{{.*}}, %{{.*}} {
|
||||
// CHECKPARALLEL: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
|
||||
// CHECKPARALLEL-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL-DAG: %[[b:.*]] = load %[[B]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[b:.*]] = load %[[B]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECKPARALLEL-DAG: %[[c:.*]] = load %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL-DAG: %[[c:.*]] = load %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
// CHECKPARALLEL: store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL: store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
|
||||
|
||||
|
||||
func @matvec(%arg0: memref<?xi8>, %M: index, %N: index) {
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%2 = view %arg0[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%3 = view %arg0[%c0][%M] : memref<?xi8> to memref<?xf32, offset: ?, strides: [1]>
|
||||
%4 = view %arg0[%c0][%N] : memref<?xi8> to memref<?xf32, offset: ?, strides: [1]>
|
||||
linalg.matvec(%2, %3, %4) : memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?xf32, offset: ?, strides: [1]>, memref<?xf32, offset: ?, strides: [1]>
|
||||
%2 = view %arg0[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
%3 = view %arg0[%c0][%M] : memref<?xi8> to memref<?xf32>
|
||||
%4 = view %arg0[%c0][%N] : memref<?xi8> to memref<?xf32>
|
||||
linalg.matvec(%2, %3, %4) : memref<?x?xf32>, memref<?xf32>, memref<?xf32>
|
||||
return
|
||||
}
|
||||
// CHECKLOOP-LABEL: func @matvec(%{{.*}}: memref<?xi8>,
|
||||
// CHECKLOOP-SAME: [[M:arg[0-9]+]]: index
|
||||
// CHECKLOOP-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECKLOOP: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKLOOP: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKLOOP: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKLOOP: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
|
||||
// CHECKLOOP: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
|
||||
// CHECKLOOP-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKLOOP-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKLOOP-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKLOOP-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECKLOOP-DAG: %[[c:.*]] = load %[[C]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP-DAG: %[[c:.*]] = load %[[C]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKLOOP-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
// CHECKLOOP: store %[[res]], %[[C]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP: store %[[res]], %[[C]][%{{.*}}] : memref<?xf32>
|
||||
|
||||
// CHECKPARALLEL-LABEL: func @matvec(%{{.*}}: memref<?xi8>,
|
||||
// CHECKPARALLEL-SAME: [[M:arg[0-9]+]]: index
|
||||
// CHECKPARALLEL-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECKPARALLEL: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL: %[[A:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECKPARALLEL: %[[B:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKPARALLEL: %[[C:.*]] = std.view %{{.*}}[{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKPARALLEL: loop.parallel (%{{.*}}) = (%{{.*}}) to (%[[M]]) step (%{{.*}}) {
|
||||
// CHECKPARALLEL: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
|
||||
// CHECKPARALLEL-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECKPARALLEL-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL-DAG: %[[a:.*]] = load %[[A]][%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECKPARALLEL-DAG: %[[c:.*]] = load %[[C]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL-DAG: %[[c:.*]] = load %[[C]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
// CHECKPARALLEL: store %[[res]], %[[C]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL: store %[[res]], %[[C]][%{{.*}}] : memref<?xf32>
|
||||
|
||||
|
||||
func @dot(%arg0: memref<?xi8>, %M: index) {
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%1 = view %arg0[%c0][%M] : memref<?xi8> to memref<?xf32, offset: ?, strides: [1]>
|
||||
%2 = view %arg0[%c0][%M] : memref<?xi8> to memref<?xf32, offset: ?, strides: [1]>
|
||||
%3 = view %arg0[][] : memref<?xi8> to memref<f32>
|
||||
linalg.dot(%1, %2, %3) : memref<?xf32, offset: ?, strides: [1]>, memref<?xf32, offset: ?, strides: [1]>, memref<f32>
|
||||
%1 = view %arg0[%c0][%M] : memref<?xi8> to memref<?xf32>
|
||||
%2 = view %arg0[%c0][%M] : memref<?xi8> to memref<?xf32>
|
||||
%3 = view %arg0[%c0][] : memref<?xi8> to memref<f32>
|
||||
linalg.dot(%1, %2, %3) : memref<?xf32>, memref<?xf32>, memref<f32>
|
||||
return
|
||||
}
|
||||
// CHECKLOOP-LABEL: func @dot(%{{.*}}: memref<?xi8>,
|
||||
// CHECKLOOP-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECKLOOP: %[[A:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP: %[[B:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP: %[[C:.*]] = std.view %{{.*}}[][] : memref<?xi8> to memref<f32>
|
||||
// CHECKLOOP: %[[A:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKLOOP: %[[B:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKLOOP: %[[C:.*]] = std.view %{{.*}}[{{.*}}][] : memref<?xi8> to memref<f32>
|
||||
// CHECKLOOP: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
|
||||
// CHECKLOOP-DAG: %[[a:.*]] = load %[[A]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKLOOP-DAG: %[[a:.*]] = load %[[A]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKLOOP-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKLOOP-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECKLOOP-DAG: %[[c:.*]] = load %[[C]][] : memref<f32>
|
||||
// CHECKLOOP-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
|
@ -135,12 +135,12 @@ func @dot(%arg0: memref<?xi8>, %M: index) {
|
|||
|
||||
// CHECKPARALLEL-LABEL: func @dot(%{{.*}}: memref<?xi8>,
|
||||
// CHECKPARALLEL-SAME: [[K:arg[0-9]+]]: index
|
||||
// CHECKPARALLEL: %[[A:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL: %[[B:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL: %[[C:.*]] = std.view %{{.*}}[][] : memref<?xi8> to memref<f32>
|
||||
// CHECKPARALLEL: %[[A:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKPARALLEL: %[[B:.*]] = std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?xf32>
|
||||
// CHECKPARALLEL: %[[C:.*]] = std.view %{{.*}}[{{.*}}][] : memref<?xi8> to memref<f32>
|
||||
// CHECKPARALLEL: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
|
||||
// CHECKPARALLEL-DAG: %[[a:.*]] = load %[[A]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32, #[[strided1D]]>
|
||||
// CHECKPARALLEL-DAG: %[[a:.*]] = load %[[A]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[b:.*]] = load %[[B]][%{{.*}}] : memref<?xf32>
|
||||
// CHECKPARALLEL-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
|
||||
// CHECKPARALLEL-DAG: %[[c:.*]] = load %[[C]][] : memref<f32>
|
||||
// CHECKPARALLEL-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// RUN: mlir-opt %s -linalg-promote-subviews | FileCheck %s
|
||||
// RUN: mlir-opt %s -linalg-promote-subviews="test-promote-dynamic" | FileCheck %s --check-prefix=DYNAMIC
|
||||
|
||||
#map0 = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
|
||||
#map1 = affine_map<(d0) -> (d0 + 2)>
|
||||
#map2 = affine_map<(d0) -> (d0 + 4)>
|
||||
#map3 = affine_map<(d0) -> (d0 + 3)>
|
||||
|
@ -15,19 +14,19 @@ func @matmul_f32(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
%c2 = constant 2 : index
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%3 = view %A[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32, #map0>
|
||||
%4 = view %A[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32, #map0>
|
||||
%5 = view %A[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32, #map0>
|
||||
%6 = dim %3, 0 : memref<?x?xf32, #map0>
|
||||
%7 = dim %3, 1 : memref<?x?xf32, #map0>
|
||||
%8 = dim %4, 1 : memref<?x?xf32, #map0>
|
||||
%3 = view %A[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32>
|
||||
%4 = view %A[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
%5 = view %A[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
%6 = dim %3, 0 : memref<?x?xf32>
|
||||
%7 = dim %3, 1 : memref<?x?xf32>
|
||||
%8 = dim %4, 1 : memref<?x?xf32>
|
||||
loop.for %arg4 = %c0 to %6 step %c2 {
|
||||
loop.for %arg5 = %c0 to %8 step %c3 {
|
||||
loop.for %arg6 = %c0 to %7 step %c4 {
|
||||
%11 = std.subview %3[%arg4, %arg6][%c2, %c4][%c1, %c1] : memref<?x?xf32, #map0> to memref<?x?xf32, offset: ?, strides: [?, ?]>
|
||||
%14 = std.subview %4[%arg6, %arg5][%c4, %c3][%c1, %c1] : memref<?x?xf32, #map0> to memref<?x?xf32, offset: ?, strides: [?, ?]>
|
||||
%17 = std.subview %5[%arg4, %arg5][%c2, %c3][%c1, %c1] : memref<?x?xf32, #map0> to memref<?x?xf32, offset: ?, strides: [?, ?]>
|
||||
linalg.matmul(%11, %14, %17) : memref<?x?xf32, offset: ?, strides: [?, ?]>, memref<?x?xf32, offset: ?, strides: [?, ?]>, memref<?x?xf32, offset: ?, strides: [?, ?]>
|
||||
%11 = std.subview %3[%arg4, %arg6][%c2, %c4][] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%14 = std.subview %4[%arg6, %arg5][%c4, %c3][] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%17 = std.subview %5[%arg4, %arg5][%c2, %c3][] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
linalg.matmul(%11, %14, %17) : memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,35 +37,35 @@ func @matmul_f32(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: %[[vA:.*]] = subview {{.*}} : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: %[[vB:.*]] = subview {{.*}} : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: %[[vC:.*]] = subview {{.*}} : memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK: %[[vA:.*]] = subview {{.*}} : memref<?x?xf32>
|
||||
// CHECK: %[[vB:.*]] = subview {{.*}} : memref<?x?xf32>
|
||||
// CHECK: %[[vC:.*]] = subview {{.*}} : memref<?x?xf32>
|
||||
///
|
||||
// CHECK: %[[tmpA:.*]] = alloc() : memref<32xi8>
|
||||
// CHECK: %[[fullA:.*]] = std.view %[[tmpA]][][{{.*}}] : memref<32xi8> to memref<?x?xf32>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[fullA:.*]] = std.view %[[tmpA]][{{.*}}][{{.*}}] : memref<32xi8> to memref<?x?xf32>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[partialA:.*]] = subview %[[fullA]]{{.*}} : memref<?x?xf32> to memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
///
|
||||
// CHECK: %[[tmpB:.*]] = alloc() : memref<48xi8>
|
||||
// CHECK: %[[fullB:.*]] = std.view %[[tmpB]][][{{.*}}] : memref<48xi8> to memref<?x?xf32>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[fullB:.*]] = std.view %[[tmpB]][{{.*}}][{{.*}}] : memref<48xi8> to memref<?x?xf32>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[partialB:.*]] = subview %[[fullB]]{{.*}} : memref<?x?xf32> to memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
///
|
||||
// CHECK: %[[tmpC:.*]] = alloc() : memref<24xi8>
|
||||
// CHECK: %[[fullC:.*]] = std.view %[[tmpC]][][{{.*}}] : memref<24xi8> to memref<?x?xf32>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[fullC:.*]] = std.view %[[tmpC]][{{.*}}][{{.*}}] : memref<24xi8> to memref<?x?xf32>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[partialC:.*]] = subview %[[fullC]]{{.*}} : memref<?x?xf32> to memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
|
||||
// CHECK: linalg.fill(%[[fullA]], {{.*}}) : memref<?x?xf32>, f32
|
||||
// CHECK: linalg.fill(%[[fullB]], {{.*}}) : memref<?x?xf32>, f32
|
||||
// CHECK: linalg.fill(%[[fullC]], {{.*}}) : memref<?x?xf32>, f32
|
||||
// CHECK: linalg.copy(%[[vA]], %[[partialA]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vB]], %[[partialB]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vC]], %[[partialC]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vA]], %[[partialA]]) : memref<?x?xf32, #[[strided2D]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vB]], %[[partialB]]) : memref<?x?xf32, #[[strided2D]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vC]], %[[partialC]]) : memref<?x?xf32, #[[strided2D]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
//
|
||||
// CHECK: linalg.matmul(%[[fullA]], %[[fullB]], %[[fullC]]) : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>
|
||||
//
|
||||
// CHECK: linalg.copy(%[[partialC]], %[[vC]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[partialC]], %[[vC]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D]]>
|
||||
//
|
||||
// CHECK: dealloc %[[tmpA]] : memref<32xi8>
|
||||
// CHECK: dealloc %[[tmpB]] : memref<48xi8>
|
||||
|
@ -80,19 +79,19 @@ func @matmul_f64(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
%c2 = constant 2 : index
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%3 = view %A[%c0][%M, %K] : memref<?xi8> to memref<?x?xf64, #map0>
|
||||
%4 = view %A[%c0][%K, %N] : memref<?xi8> to memref<?x?xf64, #map0>
|
||||
%5 = view %A[%c0][%M, %N] : memref<?xi8> to memref<?x?xf64, #map0>
|
||||
%6 = dim %3, 0 : memref<?x?xf64, #map0>
|
||||
%7 = dim %3, 1 : memref<?x?xf64, #map0>
|
||||
%8 = dim %4, 1 : memref<?x?xf64, #map0>
|
||||
%3 = view %A[%c0][%M, %K] : memref<?xi8> to memref<?x?xf64>
|
||||
%4 = view %A[%c0][%K, %N] : memref<?xi8> to memref<?x?xf64>
|
||||
%5 = view %A[%c0][%M, %N] : memref<?xi8> to memref<?x?xf64>
|
||||
%6 = dim %3, 0 : memref<?x?xf64>
|
||||
%7 = dim %3, 1 : memref<?x?xf64>
|
||||
%8 = dim %4, 1 : memref<?x?xf64>
|
||||
loop.for %arg4 = %c0 to %6 step %c2 {
|
||||
loop.for %arg5 = %c0 to %8 step %c3 {
|
||||
loop.for %arg6 = %c0 to %7 step %c4 {
|
||||
%11 = std.subview %3[%arg4, %arg6][%c2, %c4][%c1, %c1] : memref<?x?xf64, #map0> to memref<?x?xf64, offset: ?, strides: [?, ?]>
|
||||
%14 = std.subview %4[%arg6, %arg5][%c4, %c3][%c1, %c1] : memref<?x?xf64, #map0> to memref<?x?xf64, offset: ?, strides: [?, ?]>
|
||||
%17 = std.subview %5[%arg4, %arg5][%c2, %c3][%c1, %c1] : memref<?x?xf64, #map0> to memref<?x?xf64, offset: ?, strides: [?, ?]>
|
||||
linalg.matmul(%11, %14, %17) : memref<?x?xf64, offset: ?, strides: [?, ?]>, memref<?x?xf64, offset: ?, strides: [?, ?]>, memref<?x?xf64, offset: ?, strides: [?, ?]>
|
||||
%11 = std.subview %3[%arg4, %arg6][%c2, %c4][] : memref<?x?xf64> to memref<?x?xf64, offset: ?, strides: [?, 1]>
|
||||
%14 = std.subview %4[%arg6, %arg5][%c4, %c3][] : memref<?x?xf64> to memref<?x?xf64, offset: ?, strides: [?, 1]>
|
||||
%17 = std.subview %5[%arg4, %arg5][%c2, %c3][] : memref<?x?xf64> to memref<?x?xf64, offset: ?, strides: [?, 1]>
|
||||
linalg.matmul(%11, %14, %17) : memref<?x?xf64, offset: ?, strides: [?, 1]>, memref<?x?xf64, offset: ?, strides: [?, 1]>, memref<?x?xf64, offset: ?, strides: [?, 1]>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,35 +102,35 @@ func @matmul_f64(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: %[[vA_f64:.*]] = subview {{.*}} : memref<?x?xf64, #[[strided2D]]>
|
||||
// CHECK: %[[vB_f64:.*]] = subview {{.*}} : memref<?x?xf64, #[[strided2D]]>
|
||||
// CHECK: %[[vC_f64:.*]] = subview {{.*}} : memref<?x?xf64, #[[strided2D]]>
|
||||
// CHECK: %[[vA_f64:.*]] = subview {{.*}} : memref<?x?xf64>
|
||||
// CHECK: %[[vB_f64:.*]] = subview {{.*}} : memref<?x?xf64>
|
||||
// CHECK: %[[vC_f64:.*]] = subview {{.*}} : memref<?x?xf64>
|
||||
///
|
||||
// CHECK: %[[tmpA_f64:.*]] = alloc() : memref<64xi8>
|
||||
// CHECK: %[[fullA_f64:.*]] = std.view %[[tmpA_f64]][][{{.*}}] : memref<64xi8> to memref<?x?xf64>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xf64>
|
||||
// CHECK: %[[fullA_f64:.*]] = std.view %[[tmpA_f64]][{{.*}}][{{.*}}] : memref<64xi8> to memref<?x?xf64>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xf64>
|
||||
// CHECK: %[[partialA_f64:.*]] = subview %[[fullA_f64]][%{{.*}}, %{{.*}}] : memref<?x?xf64> to memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
///
|
||||
// CHECK: %[[tmpB_f64:.*]] = alloc() : memref<96xi8>
|
||||
// CHECK: %[[fullB_f64:.*]] = std.view %[[tmpB_f64]][][{{.*}}] : memref<96xi8> to memref<?x?xf64>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xf64>
|
||||
// CHECK: %[[fullB_f64:.*]] = std.view %[[tmpB_f64]][{{.*}}][{{.*}}] : memref<96xi8> to memref<?x?xf64>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xf64>
|
||||
// CHECK: %[[partialB_f64:.*]] = subview %[[fullB_f64]][%{{.*}}, %{{.*}}] : memref<?x?xf64> to memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
///
|
||||
// CHECK: %[[tmpC_f64:.*]] = alloc() : memref<48xi8>
|
||||
// CHECK: %[[fullC_f64:.*]] = std.view %[[tmpC_f64]][][{{.*}}] : memref<48xi8> to memref<?x?xf64>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xf64>
|
||||
// CHECK: %[[fullC_f64:.*]] = std.view %[[tmpC_f64]][{{.*}}][{{.*}}] : memref<48xi8> to memref<?x?xf64>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xf64>
|
||||
// CHECK: %[[partialC_f64:.*]] = subview %[[fullC_f64]][%{{.*}}, %{{.*}}] : memref<?x?xf64> to memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
|
||||
// CHECK: linalg.fill(%[[fullA_f64]], {{.*}}) : memref<?x?xf64>, f64
|
||||
// CHECK: linalg.fill(%[[fullB_f64]], {{.*}}) : memref<?x?xf64>, f64
|
||||
// CHECK: linalg.fill(%[[fullC_f64]], {{.*}}) : memref<?x?xf64>, f64
|
||||
// CHECK: linalg.copy(%[[vA_f64]], %[[partialA_f64]]) : memref<?x?xf64, #[[strided2D_dynamic]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vB_f64]], %[[partialB_f64]]) : memref<?x?xf64, #[[strided2D_dynamic]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vC_f64]], %[[partialC_f64]]) : memref<?x?xf64, #[[strided2D_dynamic]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vA_f64]], %[[partialA_f64]]) : memref<?x?xf64, #[[strided2D]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vB_f64]], %[[partialB_f64]]) : memref<?x?xf64, #[[strided2D]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vC_f64]], %[[partialC_f64]]) : memref<?x?xf64, #[[strided2D]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
//
|
||||
// CHECK: linalg.matmul(%[[fullA_f64]], %[[fullB_f64]], %[[fullC_f64]]) : memref<?x?xf64>, memref<?x?xf64>, memref<?x?xf64>
|
||||
//
|
||||
// CHECK: linalg.copy(%[[partialC_f64]], %[[vC_f64]]) : memref<?x?xf64, #[[strided2D_dynamic]]>, memref<?x?xf64, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[partialC_f64]], %[[vC_f64]]) : memref<?x?xf64, #[[strided2D_dynamic]]>, memref<?x?xf64, #[[strided2D]]>
|
||||
//
|
||||
// CHECK: dealloc %[[tmpA_f64]] : memref<64xi8>
|
||||
// CHECK: dealloc %[[tmpB_f64]] : memref<96xi8>
|
||||
|
@ -145,19 +144,19 @@ func @matmul_i32(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
%c2 = constant 2 : index
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
%3 = view %A[%c0][%M, %K] : memref<?xi8> to memref<?x?xi32, #map0>
|
||||
%4 = view %A[%c0][%K, %N] : memref<?xi8> to memref<?x?xi32, #map0>
|
||||
%5 = view %A[%c0][%M, %N] : memref<?xi8> to memref<?x?xi32, #map0>
|
||||
%6 = dim %3, 0 : memref<?x?xi32, #map0>
|
||||
%7 = dim %3, 1 : memref<?x?xi32, #map0>
|
||||
%8 = dim %4, 1 : memref<?x?xi32, #map0>
|
||||
%3 = view %A[%c0][%M, %K] : memref<?xi8> to memref<?x?xi32>
|
||||
%4 = view %A[%c0][%K, %N] : memref<?xi8> to memref<?x?xi32>
|
||||
%5 = view %A[%c0][%M, %N] : memref<?xi8> to memref<?x?xi32>
|
||||
%6 = dim %3, 0 : memref<?x?xi32>
|
||||
%7 = dim %3, 1 : memref<?x?xi32>
|
||||
%8 = dim %4, 1 : memref<?x?xi32>
|
||||
loop.for %arg4 = %c0 to %6 step %c2 {
|
||||
loop.for %arg5 = %c0 to %8 step %c3 {
|
||||
loop.for %arg6 = %c0 to %7 step %c4 {
|
||||
%11 = std.subview %3[%arg4, %arg6][%c2, %c4][%c1, %c1] : memref<?x?xi32, #map0> to memref<?x?xi32, offset: ?, strides: [?, ?]>
|
||||
%14 = std.subview %4[%arg6, %arg5][%c4, %c3][%c1, %c1] : memref<?x?xi32, #map0> to memref<?x?xi32, offset: ?, strides: [?, ?]>
|
||||
%17 = std.subview %5[%arg4, %arg5][%c2, %c3][%c1, %c1] : memref<?x?xi32, #map0> to memref<?x?xi32, offset: ?, strides: [?, ?]>
|
||||
linalg.matmul(%11, %14, %17) : memref<?x?xi32, offset: ?, strides: [?, ?]>, memref<?x?xi32, offset: ?, strides: [?, ?]>, memref<?x?xi32, offset: ?, strides: [?, ?]>
|
||||
%11 = std.subview %3[%arg4, %arg6][%c2, %c4][] : memref<?x?xi32> to memref<?x?xi32, offset: ?, strides: [?, 1]>
|
||||
%14 = std.subview %4[%arg6, %arg5][%c4, %c3][] : memref<?x?xi32> to memref<?x?xi32, offset: ?, strides: [?, 1]>
|
||||
%17 = std.subview %5[%arg4, %arg5][%c2, %c3][] : memref<?x?xi32> to memref<?x?xi32, offset: ?, strides: [?, 1]>
|
||||
linalg.matmul(%11, %14, %17) : memref<?x?xi32, offset: ?, strides: [?, 1]>, memref<?x?xi32, offset: ?, strides: [?, 1]>, memref<?x?xi32, offset: ?, strides: [?, 1]>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,35 +167,35 @@ func @matmul_i32(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
|
|||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
|
||||
// CHECK: %[[vA_i32:.*]] = subview {{.*}} : memref<?x?xi32, #[[strided2D]]>
|
||||
// CHECK: %[[vB_i32:.*]] = subview {{.*}} : memref<?x?xi32, #[[strided2D]]>
|
||||
// CHECK: %[[vC_i32:.*]] = subview {{.*}} : memref<?x?xi32, #[[strided2D]]>
|
||||
// CHECK: %[[vA_i32:.*]] = subview {{.*}} : memref<?x?xi32>
|
||||
// CHECK: %[[vB_i32:.*]] = subview {{.*}} : memref<?x?xi32>
|
||||
// CHECK: %[[vC_i32:.*]] = subview {{.*}} : memref<?x?xi32>
|
||||
///
|
||||
// CHECK: %[[tmpA_i32:.*]] = alloc() : memref<32xi8>
|
||||
// CHECK: %[[fullA_i32:.*]] = std.view %[[tmpA_i32]][][{{.*}}] : memref<32xi8> to memref<?x?xi32>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xi32>
|
||||
// CHECK: %[[fullA_i32:.*]] = std.view %[[tmpA_i32]][{{.*}}][{{.*}}] : memref<32xi8> to memref<?x?xi32>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xi32>
|
||||
// CHECK: %[[partialA_i32:.*]] = subview %[[fullA_i32]][%{{.*}}, %{{.*}}] : memref<?x?xi32> to memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
///
|
||||
// CHECK: %[[tmpB_i32:.*]] = alloc() : memref<48xi8>
|
||||
// CHECK: %[[fullB_i32:.*]] = std.view %[[tmpB_i32]][][{{.*}}] : memref<48xi8> to memref<?x?xi32>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xi32>
|
||||
// CHECK: %[[fullB_i32:.*]] = std.view %[[tmpB_i32]][{{.*}}][{{.*}}] : memref<48xi8> to memref<?x?xi32>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xi32>
|
||||
// CHECK: %[[partialB_i32:.*]] = subview %[[fullB_i32]][%{{.*}}, %{{.*}}] : memref<?x?xi32> to memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
///
|
||||
// CHECK: %[[tmpC_i32:.*]] = alloc() : memref<24xi8>
|
||||
// CHECK: %[[fullC_i32:.*]] = std.view %[[tmpC_i32]][][{{.*}}] : memref<24xi8> to memref<?x?xi32>
|
||||
// DYNAMIC: std.view %{{.*}}[][{{.*}}] : memref<?xi8> to memref<?x?xi32>
|
||||
// CHECK: %[[fullC_i32:.*]] = std.view %[[tmpC_i32]][{{.*}}][{{.*}}] : memref<24xi8> to memref<?x?xi32>
|
||||
// DYNAMIC: std.view %{{.*}}[{{.*}}][{{.*}}] : memref<?xi8> to memref<?x?xi32>
|
||||
// CHECK: %[[partialC_i32:.*]] = subview %[[fullC_i32]][%{{.*}}, %{{.*}}] : memref<?x?xi32> to memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
|
||||
// CHECK: linalg.fill(%[[fullA_i32]], {{.*}}) : memref<?x?xi32>, i32
|
||||
// CHECK: linalg.fill(%[[fullB_i32]], {{.*}}) : memref<?x?xi32>, i32
|
||||
// CHECK: linalg.fill(%[[fullC_i32]], {{.*}}) : memref<?x?xi32>, i32
|
||||
// CHECK: linalg.copy(%[[vA_i32]], %[[partialA_i32]]) : memref<?x?xi32, #[[strided2D_dynamic]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vB_i32]], %[[partialB_i32]]) : memref<?x?xi32, #[[strided2D_dynamic]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vC_i32]], %[[partialC_i32]]) : memref<?x?xi32, #[[strided2D_dynamic]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vA_i32]], %[[partialA_i32]]) : memref<?x?xi32, #[[strided2D]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vB_i32]], %[[partialB_i32]]) : memref<?x?xi32, #[[strided2D]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[vC_i32]], %[[partialC_i32]]) : memref<?x?xi32, #[[strided2D]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
//
|
||||
// CHECK: linalg.matmul(%[[fullA_i32]], %[[fullB_i32]], %[[fullC_i32]]) : memref<?x?xi32>, memref<?x?xi32>, memref<?x?xi32>
|
||||
//
|
||||
// CHECK: linalg.copy(%[[partialC_i32]], %[[vC_i32]]) : memref<?x?xi32, #[[strided2D_dynamic]]>, memref<?x?xi32, #[[strided2D_dynamic]]>
|
||||
// CHECK: linalg.copy(%[[partialC_i32]], %[[vC_i32]]) : memref<?x?xi32, #[[strided2D_dynamic]]>, memref<?x?xi32, #[[strided2D]]>
|
||||
//
|
||||
// CHECK: dealloc %[[tmpA_i32]] : memref<32xi8>
|
||||
// CHECK: dealloc %[[tmpB_i32]] : memref<48xi8>
|
||||
|
|
|
@ -16,34 +16,31 @@ func @range(%arg0: index, %arg1: index, %arg2: index) {
|
|||
// -----
|
||||
|
||||
// CHECK-DAG: #[[strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
|
||||
// CHECK-DAG: #[[strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
|
||||
|
||||
func @views(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) {
|
||||
%c0 = constant 0 : index
|
||||
%0 = muli %arg0, %arg0 : index
|
||||
%1 = alloc (%0) : memref<?xi8>
|
||||
%2 = linalg.range %arg0:%arg1:%arg2 : !linalg.range
|
||||
%3 = view %1[%c0][%arg0, %arg0] :
|
||||
memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%3 = view %1[%c0][%arg0, %arg0] : memref<?xi8> to memref<?x?xf32>
|
||||
%4 = linalg.slice %3[%2, %2] :
|
||||
memref<?x?xf32, offset: ?, strides: [?, 1]>,
|
||||
memref<?x?xf32>,
|
||||
!linalg.range,
|
||||
!linalg.range,
|
||||
memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%5 = linalg.slice %3[%2, %arg2] : memref<?x?xf32, offset: ?, strides: [?, 1]>,
|
||||
memref<?x?xf32>
|
||||
%5 = linalg.slice %3[%2, %arg2] : memref<?x?xf32>,
|
||||
!linalg.range,
|
||||
index,
|
||||
memref<?xf32, offset: ?, strides: [1]>
|
||||
%6 = linalg.slice %3[%arg2, %2] : memref<?x?xf32, offset: ?, strides: [?, 1]>,
|
||||
%6 = linalg.slice %3[%arg2, %2] : memref<?x?xf32>,
|
||||
index,
|
||||
!linalg.range,
|
||||
memref<?xf32, offset: ?, strides: [1]>
|
||||
%7 = linalg.slice %3[%arg2, %arg3] : memref<?x?xf32, offset: ?, strides: [?, 1]>,
|
||||
%7 = linalg.slice %3[%arg2, %arg3] : memref<?x?xf32>,
|
||||
index,
|
||||
index,
|
||||
memref<f32>
|
||||
%8 = view %1[%c0][%arg0, %arg0] :
|
||||
memref<?xi8> to memref<?x?xvector<4x4xf32>, offset: ?, strides: [?, 1]>
|
||||
%8 = view %1[%c0][%arg0, %arg0] : memref<?xi8> to memref<?x?xvector<4x4xf32>>
|
||||
dealloc %1 : memref<?xi8>
|
||||
return
|
||||
}
|
||||
|
@ -52,29 +49,29 @@ func @views(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index
|
|||
// CHECK-NEXT: alloc(%{{.*}}) : memref<?xi8>
|
||||
// CHECK-NEXT: range
|
||||
// CHECK-NEXT: std.view %{{.*}}[%{{.*}}][%{{.*}}] :
|
||||
// CHECK-SAME: memref<?xi8> to memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK-SAME: memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
|
||||
// CHECK-SAME: memref<?x?xf32, #[[strided2D]]>,
|
||||
// CHECK-SAME: memref<?x?xf32>,
|
||||
// CHECK-SAME: !linalg.range,
|
||||
// CHECK-SAME: !linalg.range,
|
||||
// CHECK-SAME: memref<?x?xf32, #[[strided2D]]>
|
||||
// CHECK-SAME: memref<?x?xf32>
|
||||
// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
|
||||
// CHECK-SAME: memref<?x?xf32, #[[strided2D]]>,
|
||||
// CHECK-SAME: memref<?x?xf32>,
|
||||
// CHECK-SAME: !linalg.range,
|
||||
// CHECK-SAME: index,
|
||||
// CHECK-SAME: memref<?xf32, #[[strided1D]]>
|
||||
// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
|
||||
// CHECK-SAME: memref<?x?xf32, #[[strided2D]]>,
|
||||
// CHECK-SAME: memref<?x?xf32>,
|
||||
// CHECK-SAME: index,
|
||||
// CHECK-SAME: !linalg.range,
|
||||
// CHECK-SAME: memref<?xf32, #[[strided1D]]>
|
||||
// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
|
||||
// CHECK-SAME: memref<?x?xf32, #[[strided2D]]>,
|
||||
// CHECK-SAME: memref<?x?xf32>,
|
||||
// CHECK-SAME: index,
|
||||
// CHECK-SAME: index,
|
||||
// CHECK-SAME: memref<f32>
|
||||
// CHECK-NEXT: view %{{.*}}[%{{.*}}][%{{.*}}] :
|
||||
// CHECK-SAME: memref<?xi8> to memref<?x?xvector<4x4xf32>, #[[strided2D]]>
|
||||
// CHECK-SAME: memref<?xi8> to memref<?x?xvector<4x4xf32>>
|
||||
// CHECK-NEXT: dealloc %{{.*}} : memref<?xi8>
|
||||
|
||||
// -----
|
||||
|
|
|
@ -280,13 +280,13 @@ func @promote_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
|
|||
// CHECK: %[[s1:.*]] = subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK: %[[s2:.*]] = subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK: %[[a0:.*]] = alloc({{%.*}}) : memref<?xi8>
|
||||
// CHECK: %[[v0:.*]] = std.view %[[a0]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[v0:.*]] = std.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[l0:.*]] = subview %[[v0]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK: %[[a1:.*]] = alloc({{%.*}}) : memref<?xi8>
|
||||
// CHECK: %[[v1:.*]] = std.view %[[a1]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[v1:.*]] = std.view %[[a1]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[l1:.*]] = subview %[[v1]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK: %[[a2:.*]] = alloc({{%.*}}) : memref<?xi8>
|
||||
// CHECK: %[[v2:.*]] = std.view %[[a2]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[v2:.*]] = std.view %[[a2]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[l2:.*]] = subview %[[v2]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK: linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK: linalg.copy(%[[s1]], %[[l1]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
|
||||
|
@ -330,13 +330,13 @@ func @promote_first_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?
|
|||
// CHECK: %[[s1:.*]] = subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK: %[[s2:.*]] = subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK: %[[a0:.*]] = alloc({{%.*}}) : memref<?xi8>
|
||||
// CHECK: %[[v0:.*]] = std.view %[[a0]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[v0:.*]] = std.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[l0:.*]] = subview %[[v0]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK-NOT: %[[a1:.*]] = alloc({{%.*}}) : memref<?xi8>
|
||||
// CHECK-NOT: %[[v1:.*]] = std.view %[[a1]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK-NOT: %[[v1:.*]] = std.view %[[a1]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK-NOT: %[[l0:.*]] = subview %[[v1]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK-NOT: %[[a2:.*]] = alloc({{%.*}}) : memref<?xi8>
|
||||
// CHECK-NOT: %[[v2:.*]] = std.view %[[a2]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK-NOT: %[[v2:.*]] = std.view %[[a2]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK-NOT: %[[l0:.*]] = subview %[[v2]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK: linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK-NOT: linalg.copy(%[[s1]], %[[l1]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
|
||||
|
@ -359,7 +359,7 @@ func @aligned_promote_fill(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
|
|||
// CHECK: %[[cf:.*]] = constant {{.*}} : f32
|
||||
// CHECK: %[[s0:.*]] = subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
|
||||
// CHECK: %[[a0:.*]] = alloc({{%.*}}) {alignment = 32 : i64} : memref<?xi8>
|
||||
// CHECK: %[[v0:.*]] = std.view %[[a0]][][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[v0:.*]] = std.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
|
||||
// CHECK: %[[l0:.*]] = subview %[[v0]][{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32> to memref<?x?xf32, #[[STRIDED_2D]]>
|
||||
// CHECK: linalg.fill(%[[v0]], {{%.*}}) : memref<?x?xf32>, f32
|
||||
// CHECK: linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
|
||||
// CHECK: #map1 = affine_map<()[s0] -> (s0 + 1)>
|
||||
|
||||
// CHECK-DAG: #[[VIEW_MAP1:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 4 + d1)>
|
||||
// CHECK-DAG: #[[VIEW_MAP2:map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + d1 + s0)>
|
||||
// CHECK-DAG: #[[VIEW_MAP3:map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0 * s0 + d1)>
|
||||
|
||||
// CHECK-DAG: #[[BASE_MAP0:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)>
|
||||
// CHECK-DAG: #[[BASE_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
|
||||
// CHECK-DAG: #[[SUBVIEW_MAP0:map[0-9]+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + d1 * s2 + d2 * s3 + s0)>
|
||||
|
@ -692,29 +688,17 @@ func @memref_cast(%arg0: memref<4xf32>, %arg1 : memref<?xf32>, %arg2 : memref<64
|
|||
func @memref_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// Test two dynamic sizes and dynamic offset.
|
||||
// CHECK: %{{.*}} = std.view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref<?x?xf32, #[[VIEW_MAP2]]>
|
||||
%1 = view %0[%arg2][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + d1 + s0)>>
|
||||
|
||||
// Test two dynamic sizes and static offset.
|
||||
// CHECK: %{{.*}} = std.view %0[][%arg0, %arg1] : memref<2048xi8> to memref<?x?xf32, #[[VIEW_MAP3]]>
|
||||
%2 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0 * s0 + d1)>>
|
||||
// CHECK: %{{.*}} = std.view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref<?x?xf32>
|
||||
%1 = view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref<?x?xf32>
|
||||
|
||||
// Test one dynamic size and dynamic offset.
|
||||
// CHECK: %{{.*}} = std.view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32, #[[VIEW_MAP2]]>
|
||||
%3 = view %0[%arg2][%arg1]
|
||||
: memref<2048xi8> to memref<4x?xf32, affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + d1 + s0)>>
|
||||
|
||||
// Test one dynamic size and static offset.
|
||||
// CHECK: %{{.*}} = std.view %0[][%arg0] : memref<2048xi8> to memref<?x4xf32, #[[VIEW_MAP1]]>
|
||||
%4 = view %0[][%arg0]
|
||||
: memref<2048xi8> to memref<?x4xf32, affine_map<(d0, d1) -> (d0 * 4 + d1)>>
|
||||
// CHECK: %{{.*}} = std.view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32>
|
||||
%3 = view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32>
|
||||
|
||||
// Test static sizes and static offset.
|
||||
// CHECK: %{{.*}} = std.view %0[][] : memref<2048xi8> to memref<64x4xf32, #[[VIEW_MAP1]]>
|
||||
%5 = view %0[][]
|
||||
: memref<2048xi8> to memref<64x4xf32, affine_map<(d0, d1) -> (d0 * 4 + d1)>>
|
||||
// CHECK: %{{.*}} = std.view %0[{{.*}}][] : memref<2048xi8> to memref<64x4xf32>
|
||||
%c0 = constant 0: index
|
||||
%5 = view %0[%c0][] : memref<2048xi8> to memref<64x4xf32>
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -927,29 +927,9 @@ func @invalid_splat(%v : f32) { // expected-note {{prior use here}}
|
|||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// expected-error@+1 {{incorrect number of operands for type}}
|
||||
// expected-error@+1 {{expects 1 offset operand}}
|
||||
%1 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0 * 4 + d1 + s0)>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// expected-error@+1 {{is not strided}}
|
||||
%1 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0, d1, s0)>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xf32>
|
||||
// expected-error@+1 {{must be 1D memref of 8-bit signless integer values}}
|
||||
%1 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xf32> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0 * 4 + d1 + s0)>>
|
||||
: memref<2048xi8> to memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -957,8 +937,8 @@ func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
|||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8, affine_map<(d0) -> (d0 floordiv 8, d0 mod 8)>>
|
||||
// expected-error@+1 {{unsupported map for base memref}}
|
||||
%1 = view %0[][%arg0, %arg1]
|
||||
// expected-error@+1 {{unsupported map for base memref type}}
|
||||
%1 = view %0[%arg2][%arg0, %arg1]
|
||||
: memref<2048xi8, affine_map<(d0) -> (d0 floordiv 8, d0 mod 8)>> to
|
||||
memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0 * 4 + d1 + s0)>>
|
||||
return
|
||||
|
@ -966,12 +946,20 @@ func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// expected-error@+1 {{unsupported map for result memref type}}
|
||||
%1 = view %0[%arg2][%arg0, %arg1]
|
||||
: memref<2048xi8> to memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0, d1, s0)>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8, 2>
|
||||
// expected-error@+1 {{different memory spaces}}
|
||||
%1 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xi8, 2> to
|
||||
memref<?x?xf32, affine_map<(d0, d1)[s0] -> (d0 * 4 + d1 + s0)>, 1>
|
||||
%1 = view %0[%arg2][%arg0, %arg1] : memref<2048xi8, 2> to memref<?x?xf32, 1>
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -979,32 +967,9 @@ func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
|||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// expected-error@+1 {{incorrect dynamic strides}}
|
||||
%1 = view %0[][%arg0, %arg1]
|
||||
: memref<2048xi8> to
|
||||
memref<?x?x4xf32, affine_map<(d0, d1, d2) -> (d0 * 777 + d1 * 4 + d2)>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// expected-error@+1 {{incorrect dynamic strides}}
|
||||
%1 = view %0[%arg0][]
|
||||
: memref<2048xi8> to
|
||||
memref<16x4x?xf32, affine_map<(d0, d1, d2) -> (d0 * 777 + d1 * 4 + d2)>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @multiple_offsets(%arg0: index) {
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
// expected-error@+1 {{expects 0 or 1 offset operand}}
|
||||
%1 = view %0[%arg0, %arg0][%arg0]
|
||||
: memref<2048xi8> to
|
||||
memref<?x?x4xf32, affine_map<(d0, d1, d2) -> (d0 * 777 + d1 * 4 + d2)>>
|
||||
// expected-error@+1 {{incorrect number of size operands for type}}
|
||||
%1 = view %0[%arg2][%arg0]
|
||||
: memref<2048xi8> to memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -445,9 +445,9 @@ func @dim_op_fold(%arg0: index, %arg1: index, %arg2: index, %BUF: memref<?xi8>,
|
|||
%ub = dim %3, 0 : memref<?xi8>
|
||||
affine.for %arg4 = 0 to %ub {
|
||||
%s = dim %0, 0 : memref<?x?xf32>
|
||||
%v = std.view %3[%c0][%arg4, %s] : memref<?xi8> to memref<?x?xf32, #map1>
|
||||
%v = std.view %3[%c0][%arg4, %s] : memref<?xi8> to memref<?x?xf32>
|
||||
%sv = subview %0[%c0, %c0][%s,%arg4][%c1,%c1] : memref<?x?xf32> to memref<?x?xf32, #map1>
|
||||
%l = dim %v, 1 : memref<?x?xf32, #map1>
|
||||
%l = dim %v, 1 : memref<?x?xf32>
|
||||
%u = dim %sv, 0 : memref<?x?xf32, #map1>
|
||||
affine.for %arg5 = %l to %u {
|
||||
"foo"() : () -> ()
|
||||
|
@ -462,13 +462,13 @@ func @dim_op_fold(%arg0: index, %arg1: index, %arg2: index, %BUF: memref<?xi8>,
|
|||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: }
|
||||
|
||||
%A = view %BUF[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%B = view %BUF[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%C = view %BUF[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%A = view %BUF[%c0][%M, %K] : memref<?xi8> to memref<?x?xf32>
|
||||
%B = view %BUF[%c0][%K, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
%C = view %BUF[%c0][%M, %N] : memref<?xi8> to memref<?x?xf32>
|
||||
|
||||
%M_ = dim %A, 0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%K_ = dim %A, 1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%N_ = dim %C, 1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
|
||||
%M_ = dim %A, 0 : memref<?x?xf32>
|
||||
%K_ = dim %A, 1 : memref<?x?xf32>
|
||||
%N_ = dim %C, 1 : memref<?x?xf32>
|
||||
loop.for %i = %c0 to %M_ step %c1 {
|
||||
loop.for %j = %c0 to %N_ step %c1 {
|
||||
loop.for %k = %c0 to %K_ step %c1 {
|
||||
|
@ -642,19 +642,9 @@ func @cast_values(%arg0: tensor<*xi32>, %arg1: memref<?xi32>) -> (tensor<2xi32>,
|
|||
|
||||
// -----
|
||||
|
||||
#TEST_VIEW_MAP0 = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + d1 + s0)>
|
||||
#TEST_VIEW_MAP1 = affine_map<(d0, d1, d2)[s0, s1] -> (d0 * s1 + d1 * s0 + d2)>
|
||||
#TEST_VIEW_MAP2 = affine_map<(d0, d1)[s0] -> (d0 * 4 + d1 + s0)>
|
||||
|
||||
// CHECK-DAG: #[[VIEW_MAP0:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 11 + d1 + 15)>
|
||||
// CHECK-DAG: #[[VIEW_MAP1:map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0 * 11 + s0 + d1)>
|
||||
// CHECK-DAG: #[[VIEW_MAP2:map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0 * s0 + d1 + 15)>
|
||||
// CHECK-DAG: #[[VIEW_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2)[s0] -> (d0 * s0 + d1 * 7 + d2)>
|
||||
// CHECK-DAG: #[[VIEW_MAP4:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 4 + d1 + 15)>
|
||||
// CHECK-DAG: #[[VIEW_MAP5:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 7 + d1)>
|
||||
|
||||
// CHECK-LABEL: func @view
|
||||
func @view(%arg0 : index) -> (f32, f32, f32, f32, f32, f32) {
|
||||
func @view(%arg0 : index) -> (f32, f32, f32, f32) {
|
||||
// CHECK: %[[C15:.*]] = constant 15 : index
|
||||
// CHECK: %[[ALLOC_MEM:.*]] = alloc() : memref<2048xi8>
|
||||
%0 = alloc() : memref<2048xi8>
|
||||
%c0 = constant 0 : index
|
||||
|
@ -662,45 +652,27 @@ func @view(%arg0 : index) -> (f32, f32, f32, f32, f32, f32) {
|
|||
%c11 = constant 11 : index
|
||||
%c15 = constant 15 : index
|
||||
|
||||
// Test: fold constant sizes and offset, update map with static stride/offset.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][][] : memref<2048xi8> to memref<7x11xf32, #[[VIEW_MAP0]]>
|
||||
%1 = view %0[%c15][%c7, %c11]
|
||||
: memref<2048xi8> to memref<?x?xf32, #TEST_VIEW_MAP0>
|
||||
%r0 = load %1[%c0, %c0] : memref<?x?xf32, #TEST_VIEW_MAP0>
|
||||
// Test: fold constant sizes.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][%[[C15]]][] : memref<2048xi8> to memref<7x11xf32>
|
||||
%1 = view %0[%c15][%c7, %c11] : memref<2048xi8> to memref<?x?xf32>
|
||||
%r0 = load %1[%c0, %c0] : memref<?x?xf32>
|
||||
|
||||
// Test: fold constant sizes but not offset, update map with static stride.
|
||||
// Test that we do not a fold dynamic dim which is not produced by a constant.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][%arg0][] : memref<2048xi8> to memref<7x11xf32, #[[VIEW_MAP1]]>
|
||||
%2 = view %0[%arg0][%c7, %c11]
|
||||
: memref<2048xi8> to memref<?x?xf32, #TEST_VIEW_MAP0>
|
||||
%r1 = load %2[%c0, %c0] : memref<?x?xf32, #TEST_VIEW_MAP0>
|
||||
// Test: fold one constant size.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][%[[C15]]][%arg0, %arg0] : memref<2048xi8> to memref<?x?x7xf32>
|
||||
%2 = view %0[%c15][%arg0, %arg0, %c7] : memref<2048xi8> to memref<?x?x?xf32>
|
||||
%r1 = load %2[%c0, %c0, %c0] : memref<?x?x?xf32>
|
||||
|
||||
// Test: fold constant offset but not sizes, update map with constant offset.
|
||||
// Test that we fold constant offset but not dynamic dims.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][][%arg0, %arg0] : memref<2048xi8> to memref<?x?xf32, #[[VIEW_MAP2]]>
|
||||
%3 = view %0[%c15][%arg0, %arg0]
|
||||
: memref<2048xi8> to memref<?x?xf32, #TEST_VIEW_MAP0>
|
||||
%r2 = load %3[%c0, %c0] : memref<?x?xf32, #TEST_VIEW_MAP0>
|
||||
|
||||
// Test: fold one constant dim, no offset, should update with constant
|
||||
// stride on dim 1, but leave dynamic stride on dim 0.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][][%arg0, %arg0] : memref<2048xi8> to memref<?x?x7xf32, #[[VIEW_MAP3]]>
|
||||
%4 = view %0[][%arg0, %arg0, %c7]
|
||||
: memref<2048xi8> to memref<?x?x?xf32, #TEST_VIEW_MAP1>
|
||||
%r3 = load %4[%c0, %c0, %c0] : memref<?x?x?xf32, #TEST_VIEW_MAP1>
|
||||
|
||||
// Test: preserve an existing static dim size while folding a dynamic
|
||||
// dimension and offset.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][][] : memref<2048xi8> to memref<7x4xf32, #[[VIEW_MAP4]]>
|
||||
%5 = view %0[%c15][%c7] : memref<2048xi8> to memref<?x4xf32, #TEST_VIEW_MAP2>
|
||||
%r4 = load %5[%c0, %c0] : memref<?x4xf32, #TEST_VIEW_MAP2>
|
||||
// Test: preserve an existing static size.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][%[[C15]]][] : memref<2048xi8> to memref<7x4xf32>
|
||||
%3 = view %0[%c15][%c7] : memref<2048xi8> to memref<?x4xf32>
|
||||
%r2 = load %3[%c0, %c0] : memref<?x4xf32>
|
||||
|
||||
// Test: folding static alloc and memref_cast into a view.
|
||||
// CHECK: std.view %[[ALLOC_MEM]][][] : memref<2048xi8> to memref<15x7xf32, #[[VIEW_MAP5]]>
|
||||
%6 = memref_cast %0 : memref<2048xi8> to memref<?xi8>
|
||||
%7 = view %6[%c15][%c7] : memref<?xi8> to memref<?x?xf32>
|
||||
%r5 = load %7[%c0, %c0] : memref<?x?xf32>
|
||||
return %r0, %r1, %r2, %r3, %r4, %r5 : f32, f32, f32, f32, f32, f32
|
||||
// CHECK: std.view %[[ALLOC_MEM]][%[[C15]]][] : memref<2048xi8> to memref<15x7xf32>
|
||||
%4 = memref_cast %0 : memref<2048xi8> to memref<?xi8>
|
||||
%5 = view %4[%c15][%c15, %c7] : memref<?xi8> to memref<?x?xf32>
|
||||
%r3 = load %5[%c0, %c0] : memref<?x?xf32>
|
||||
return %r0, %r1, %r2, %r3 : f32, f32, f32, f32
|
||||
}
|
||||
|
||||
// -----
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
// RUN: | mlir-cpu-runner -e matmul -entry-point-result=f32 -shared-libs=%linalg_test_lib_dir/libmlir_test_cblas%shlibext,%linalg_test_lib_dir/libmlir_test_cblas_interface%shlibext \
|
||||
// RUN: | FileCheck %s
|
||||
|
||||
#strided1D = affine_map<(d0) -> (d0)>
|
||||
#strided2D = affine_map<(d0, d1)[s0] -> (d0 * s0 + d1)>
|
||||
|
||||
// Creates and returns a 1-D buffer of size %s filled with the value %f
|
||||
func @alloc_filled_f32(%s : index, %f : f32) -> memref<?xi8> {
|
||||
%c0 = constant 0 : index
|
||||
|
@ -32,8 +29,8 @@ func @alloc_filled_f32(%s : index, %f : f32) -> memref<?xi8> {
|
|||
%c4 = constant 4 : index
|
||||
%s4 = muli %s, %c4: index
|
||||
%buf = alloc(%s4) {alignment = 256} : memref<?xi8>
|
||||
%V = view %buf[%s][] : memref<?xi8> to memref<?xf32, #strided1D>
|
||||
linalg.fill(%V, %f) : memref<?xf32, #strided1D>, f32
|
||||
%V = view %buf[%c0][%s] : memref<?xi8> to memref<?xf32>
|
||||
linalg.fill(%V, %f) : memref<?xf32>, f32
|
||||
return %buf : memref<?xi8>
|
||||
}
|
||||
|
||||
|
@ -50,11 +47,11 @@ func @dot() -> f32 {
|
|||
%bB = call @alloc_filled_f32(%c16, %f1) : (index, f32) -> (memref<?xi8>)
|
||||
%bC = call @alloc_filled_f32(%c1, %f10) : (index, f32) -> (memref<?xi8>)
|
||||
|
||||
%A = view %bA[%c16][] : memref<?xi8> to memref<?xf32, #strided1D>
|
||||
%B = view %bB[%c16][] : memref<?xi8> to memref<?xf32, #strided1D>
|
||||
%C = view %bC[][] : memref<?xi8> to memref<f32>
|
||||
%A = view %bA[%c0][%c16] : memref<?xi8> to memref<?xf32>
|
||||
%B = view %bB[%c0][%c16] : memref<?xi8> to memref<?xf32>
|
||||
%C = view %bC[%c0][] : memref<?xi8> to memref<f32>
|
||||
|
||||
linalg.dot(%A, %B, %C) : memref<?xf32, #strided1D>, memref<?xf32, #strided1D>, memref<f32>
|
||||
linalg.dot(%A, %B, %C) : memref<?xf32>, memref<?xf32>, memref<f32>
|
||||
%res = load %C[] : memref<f32>
|
||||
|
||||
dealloc %bC : memref<?xi8>
|
||||
|
@ -82,12 +79,12 @@ func @matmul() -> f32 {
|
|||
%bB = call @alloc_filled_f32(%c160, %f1) : (index, f32) -> (memref<?xi8>)
|
||||
%bC = call @alloc_filled_f32(%c100, %f10) : (index, f32) -> (memref<?xi8>)
|
||||
|
||||
%A = view %bA[][%c10, %c16] : memref<?xi8> to memref<?x?xf32, #strided2D>
|
||||
%B = view %bB[][%c16, %c10] : memref<?xi8> to memref<?x?xf32, #strided2D>
|
||||
%C = view %bC[][%c10, %c10] : memref<?xi8> to memref<?x?xf32, #strided2D>
|
||||
%A = view %bA[%c0][%c10, %c16] : memref<?xi8> to memref<?x?xf32>
|
||||
%B = view %bB[%c0][%c16, %c10] : memref<?xi8> to memref<?x?xf32>
|
||||
%C = view %bC[%c0][%c10, %c10] : memref<?xi8> to memref<?x?xf32>
|
||||
|
||||
linalg.matmul(%A, %B, %C) : memref<?x?xf32, #strided2D>, memref<?x?xf32, #strided2D>, memref<?x?xf32, #strided2D>
|
||||
%res = load %C[%c6, %c7] : memref<?x?xf32, #strided2D>
|
||||
linalg.matmul(%A, %B, %C) : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>
|
||||
%res = load %C[%c6, %c7] : memref<?x?xf32>
|
||||
|
||||
dealloc %bC : memref<?xi8>
|
||||
dealloc %bB : memref<?xi8>
|
||||
|
|
Loading…
Reference in New Issue