[PATCH] D142445: [mlir][tensor|memref] Harden the checks on dim op
Mehdi AMINI via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 26 15:57:20 PST 2023
mehdi_amini added a comment.
In D142445#4081964 <https://reviews.llvm.org/D142445#4081964>, @qcolombet wrote:
> Hi @mehdi_amini,
>
> After talking with @aartbik and sleeping on it, I think making 0-ranked dim op invalid makes sense. I don't believe we can produce them with optimizations.
Seems reasonable for now: producing this would involve a type change, which isn't a "normal" safe thing to do (which is why I wasn't sure about this).
The part that is a bit speculative that worried me a bit is how it creates an "edge case" make it not uniform to handle. For example take some pseudo-IR like this:
// return the first dimension or 0 if rank == 0.
func @unranked(%arg0 : memref<*xf32>) : index {
%rank = memref.rank %arg0 : memref<*xf32>
%zero = arith.constant 0 : index
%rank_not_zero = arith.icmpi ne, %rank, %zero : (index, index) -> i1
%res = scf.if (%rank) {
%dim = memref.dim %arg0[0] : memref<*xf32>
scf.yield %dim
} else {
scf.yield %zero
}
return %res
}
This is fairly useless code, but just to illustrate my point: assume this is a generic / reusable routine part of a library.
Now when we integrate this in a larger program we could try to do some inlining and/or function specialization, to turn the unranked into ranked. So if you have a call-site with a rank-1 memref you would specialize as such:
func @unranked1(%arg0 : memref<?xf32>) : index {
%rank = memref.rank %arg0 : memref<?xf32>
%zero = arith.constant 0 : index
%rank_not_zero = arith.icmpi ne, %rank, %zero : (index, index) -> i1
%res = scf.if (%rank) {
%dim = memref.dim %arg0[0] : memref<?xf32>
scf.yield %dim
} else {
scf.yield %zero
}
return %res
}
which then can fold (`memref.rank` folds to 1):
func @unranked1(%arg0 : memref<?xf32>) : index {
%dim = memref.dim %arg0[0] : memref<?xf32>
return %res
}
But the same logic trying to specialize for rank 0 is impossible:
func @unranked0(%arg0 : memref<f32>) : index {
%rank = memref.rank %arg0 : memref<f32>
%zero = arith.constant 0 : index
%rank_not_zero = arith.icmpi ne, %rank, %zero : (index, index) -> i1
%res = scf.if (%rank) {
%dim = memref.dim %arg0[0] : memref<f32> // <= verifier error
scf.yield %dim
} else {
scf.yield %zero
}
return %res
}
Even though the folding would yield:
func @unranked0(%arg0 : memref<f32>) : index {
%zero = arith.constant 0 : index
return %zero
}
> Regarding the out-of-bound accesses for the non-0-ranked shapes, I will do a separate patch to remove the verifier checks and do something sensible (unreachable, ..., anything but crash).
Thanks!
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D142445/new/
https://reviews.llvm.org/D142445
More information about the llvm-commits
mailing list