Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/flydsl/Dialect/Fly/IR/FlyOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ def Fly_PtrStoreOp : Fly_Op<"ptr.store"> {
def Fly_RecastIterOp : Fly_Op<"recast_iter", [Pure]> {
let arguments = (ins Fly_Pointer:$src);
let results = (outs Fly_Pointer:$result);
let hasVerifier = 1;
}

def Fly_MemRefAllocaOp : Fly_Op<"memref.alloca", []> {
Expand Down
26 changes: 26 additions & 0 deletions lib/Dialect/Fly/IR/FlyOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1963,3 +1963,29 @@ FLY_INFER_RETURN_TYPES(MemRefLoadVecOp) {
}

#undef FLY_INFER_RETURN_TYPES

LogicalResult RecastIterOp::verify() {
auto srcTy = dyn_cast<PointerType>(getSrc().getType());
auto resultTy = dyn_cast<PointerType>(getResult().getType());
if (!srcTy || !resultTy)
return emitOpError("expected PointerType source and result");

if (srcTy.getAddressSpace() != resultTy.getAddressSpace())
return emitOpError("result pointer address space must match source");

// recast_iter only reinterprets the element type; it must not change the
// alignment guarantee in an unsound way. Narrowing the alignment is safe
// because a more strongly aligned pointer also satisfies any weaker alignment
// (for example, a 1024-byte-aligned pointer is necessarily 512-byte aligned),
// but claiming a stronger alignment than the source provides is not.
int32_t srcAlign = srcTy.getAlignment().getAlignment();
int32_t resultAlign = resultTy.getAlignment().getAlignment();
if (resultAlign <= 0 || srcAlign % resultAlign != 0)
return emitOpError("result pointer alignment must divide source alignment "
"(narrowing is allowed, widening is not)");

if (srcTy.getSwizzle() != resultTy.getSwizzle())
return emitOpError("result pointer swizzle must match source");

return success();
}
24 changes: 24 additions & 0 deletions tests/mlir/Conversion/recast_iter_invalid.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026 FlyDSL Project Contributors
// RUN: { not %fly-opt %s -split-input-file 2>&1; } | FileCheck %s

// CHECK: result pointer address space must match source
func.func @bad_recast_address_space(%ptr: !fly.ptr<f32, shared>) {
%bad = fly.recast_iter(%ptr) : (!fly.ptr<f32, shared>) -> !fly.ptr<f32, global>
return
}

// -----
// Widening the alignment guarantee is unsound and must be rejected.
// CHECK: result pointer alignment must divide source alignment
func.func @bad_recast_alignment(%ptr: !fly.ptr<f32, shared, align<512>>) {
%bad = fly.recast_iter(%ptr) : (!fly.ptr<f32, shared, align<512>>) -> !fly.ptr<f32, shared, align<1024>>
return
}

// -----
// CHECK: result pointer swizzle must match source
func.func @bad_recast_swizzle(%ptr: !fly.ptr<f32, shared, align<1024>, swz<3,3,3>>) {
%bad = fly.recast_iter(%ptr) : (!fly.ptr<f32, shared, align<1024>, swz<3,3,3>>) -> !fly.ptr<f32, shared, align<1024>>
return
}
Loading