Closed hecmay closed 1 year ago
Thanks for the PR! Can you also provide the generated MLIR code in the introduction? so that we can know better what kind of transformations you have done.
Right now, these ops do not transform the code; Specifically, when each .to()
is applied, the compiler only checks whether the .to()
is legal or not (based on the information from Polymer, which is saved as attr in the target loop).
My plan is to do the transformation lazily, because certain .to()
may violate the assumption, so it is better to let compiler do the transformation in the very end after each .to()
is verified. The compiler only performs the actual transformation (i.e., explicit PE instantiation, FIFO connection) after the legality if verified.
@chhzh123 I renamed the PR to "legality check using Polymer/PoCC" as the actual transformation part is not included. I will open another PR to add the actual transformation.
Got it. So what will .unfold
do in this case? I only see dep_distance = 0
in the attribute, which is supposed to be generated by .to()
? Then how is the information of unfold
preserved?
I just updated the test case. The unfold()
op will insert the desired factor into the target loop. And each.to()
op will check if the fine-grained data movement is legal or not based on the criteria mentioned in AutoSA paper.
Also, can you rebase the commits? We just upgraded the LLVM version. It seems this PR still uses the old version of LLVM for testing, so I'm not sure whether it will cause errors after merging. We have a prebuilt LLVM 18.x project under the /work/shared/users/common/llvm-project-18.x
folder, or you can use my docker image chhzh123/llvm-project
for testing.
@chhzh123 Sure. will do that. I have no other changes for this one.
It seems like that something in tblgen is not working as expected after rebasing. I am trying to debug
/scratch/users/sx233/hcl-dialect/lib/Transforms/LoopTransformations.cpp: In function ‘mlir::LogicalResult mlir::hcl::runIntraKernelOpCheck(mlir::func::FuncOp&, mlir::hcl::IntraKernelToOp&)’:
/scratch/users/sx233/hcl-dialect/lib/Transforms/LoopTransformations.cpp:455:44: error: ‘class mlir::hcl::IntraKernelToOp’ has no member named ‘pe_array’
455 | dyn_cast<CreateLoopHandleOp>(intraOp.pe_array().getDefiningOp());
| ^~~~~~~~
/scratch/users/sx233/hcl-dialect/lib/Transforms/LoopTransformations.cpp: In function ‘mlir::LogicalResult mlir::hcl::runUnfolding(mlir::func::FuncOp&, mlir::hcl::UnfoldOp&)’:
/scratch/users/sx233/hcl-dialect/lib/Transforms/LoopTransformations.cpp:502:35: error: ‘class mlir::hcl::UnfoldOp’ has no member named ‘factor’
502 | auto optional_factor = unfoldOp.factor();
@hecmay Yeah, the MLIR API changed. You need to use getPeArray
and getFactor
to retrieve the attributes
Summary
In this PR, I implemented the following features. NB: The names of these operators are subject to changes. We can choose better names later.
hcl.unfold()
. Unfolding loop into spatial PEs. . I chose this name in order to distinguish between thehcl.unroll()
op, which unrolls the loop by annotating with pragmas.hcl.to()
. Allow users to specify fine-grained data movement between PEs returned byhcl.unfold()
operator.Implementation details
These two ops will not mutate the AST immediately. Instead, they will annotate the target loop with necessary information. The compiler will pass the annotation to Polymer/PoCC for legality checking before mutating the IR.
Legality checking: all dependencies should be uniform the dependence distances on space loops should be no greater than one so that the data communication only happens between neighbor PEs.
Only when the legality checking passed, our compiler will apply the PE unfolding and inter-PE FIFO insertion.
Example
Here is a quick example to build a weight-stationary systolic array using
hcl.unfold()
andhcl.intra_kernel_to()
: