clangir
clangir copied to clipboard
Through MLIR lowering (not LLVM): Missing CIR operations
There are two lowering paths from CIR:
- CIR to LLVM IR dialect
- CIR to MLIR in-tree dialects
Most effort has been into (1), which the list below doesn't really apply. Here's a the list of missing features in (2):
-
cir.alloc_exception
-
cir.await
-
cir.base_class_addr
-
cir.break
-
cir.asm
-
cir.catch
-
cir.catch_param
-
cir.ceil
-
cir.condition
-
cir.continue
-
cir.cos
-
cir.do
-
cir.exp2
-
cir.exp
-
cir.fabs
-
cir.floor
-
cir.for
-
cir.get_bitfield
-
cir.get_global
-
cir.get_member
-
cir.global
-
cir.if
-
cir.iterator_begin
-
cir.iterator_end
-
cir.log10
-
cir.libc.memchr
-
cir.libc.memcpy
-
cir.nearbyint
-
cir.objsize
-
cir.ptr_diff
-
cir.ptr_stride
-
cir.resume
-
cir.rint
-
cir.round
-
cir.set_bitfield
-
cir.shift
-
cir.sin
-
cir.sqrt
-
cir.stack_restore
-
cir.stack_save
-
cir.std.find
-
cir.throw
-
cir.trunc
-
cir.try_call
-
cir.try
-
cir.va.arg
-
cir.va.copy
-
cir.va.end
-
cir.vtable.address_point
-
cir.vec.cmp
-
cir.vec.create
-
cir.vec.extract
-
cir.vec.insert
-
cir.while
-
cir.llvmir.zeroinit
Btw, thanks for trying to categorize, this is going to be very useful for distributing work into multiple issues.
Hello, in the clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp
:
void populateCIRToMLIRConversionPatterns(mlir::RewritePatternSet &patterns,
mlir::TypeConverter &converter) {
patterns.add<CIRReturnLowering, CIRBrOpLowering>(patterns.getContext());
patterns.add<CIRCmpOpLowering, CIRCallOpLowering, CIRUnaryOpLowering,
CIRBinOpLowering, CIRLoadOpLowering, CIRConstantOpLowering,
CIRStoreOpLowering, CIRAllocaOpLowering, CIRFuncOpLowering,
CIRScopeOpLowering, CIRBrCondOpLowering, CIRTernaryOpLowering,
CIRYieldOpLowering>(converter, patterns.getContext());
}
I find these operations can be lowered to MLIR, cir.if
and cir.global
donot have releating passes, which can lower cir.if
, cir.global
to MLIR, why not lower cir.if
to scf.if
? .But clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
, these passes can lower cir operations to llvm ir.
Oh, my apologies, this is talking about "Through MLIR" path, not our direct lowering, let me re-open! Sorry for the confusion
I just updated the issue description! Thanks for pushing this
@bcardosolopes Currently the lowering prepare pass runs only on the LLVMIR lowering path. Should we introduce a similar pass for the MLIR lowering path? Some of the operations listed here can be transformed or canonicalized before lowering.
Operation | Category | Difficulty | Progress |
---|---|---|---|
cir.cos | Math | Easy | Done |
cir.ceil | Math | Easy | Done |
cir.exp2 | Math | Easy | Done |
cir.exp | Math | Easy | Done |
cir.fabs | Math | Easy | Done |
cir.floor | Math | Easy | Done |
cir.log10 | Math | Easy | Done |
cir.rint | Math | Easy | |
cir.round | Math | Easy | Done |
cir.sin | Math | Easy | Done |
cir.sqrt | Math | Easy | Done |
cir.shift | Math | Easy | Done |
cir.libc.memchr | lib call | Easy | |
cir.libc.memcpy | lib call | Easy | |
cir.nearbyint | Lib Call | Easy | |
cir.get_bitfield | Address | Easy | |
cir.get_global | Address | Easy | Done |
cir.global | Address | Easy | Done |
cir.set_bitfield | Address | Easy | |
cir.std.find | Lib Call | Easy | |
cir.break | Control Flow | Mid | |
cir.asm | Control Flow | Mid | |
cir.condition | Control Flow | Mid | Done |
cir.continue | Control Flow | Mid | |
cir.for | Control Flow | Mid | Done |
cir.do | Control Flow | Mid | |
cir.if | Control Flow | Mid | Done |
cir.while | Control Flow | Mid | Done |
cir.llvmir.zeroinit | LLVM | Mid | |
cir.alloc_exception | Exception | Hard | |
cir.catch | Exception | Hard | |
cir.catch_param | Exception | Hard | |
cir.throw | Exception | Hard | |
cir.trunc | Exception | Hard | |
cir.try_call | Exception | Hard | |
cir.resume | Exception | Hard | |
cir.try | Exception | Hard | |
cir.va.arg | Paramenter List | Hard | |
cir.va.copy | Paramenter List | Hard | |
cir.va.end | Paramenter List | Hard | |
cir.vec.cmp | SIMD vector | Hard | |
cir.vec.create | SIMD vector | Hard | |
cir.vec.extract | SIMD vector | Hard | |
cir.vec.insert | SIMD vector | Hard | |
cir.iterator_begin | Iterator | Hard | |
cir.iterator_end | Iterator | Hard | |
cir.ptr_diff | Pointer | Hard | |
cir.ptr_stride | Pointer | Hard | Done |
cir.stack_restore | Stack Operation | Hard | |
cir.stack_save | Stack Operation | Hard | |
cir.base_class_addr | Class | Hard | |
cir.objsize | Normal | Hard | |
cir.get_member | Class | Hard | |
cir.vtable.address_point | Vtable | Hard | |
cir.await | Asynchronous programming | Hard |
Hello, I have conducted research on these operations, classified them, and made a simple assessment of the difficulty of implementing these operations. I want to solve this issue. The current idea is to solve it one by one from easy to difficult, starting with math-related operations.
Sounds good
@bcardosolopes Currently the lowering prepare pass runs only on the LLVMIR lowering path. Should we introduce a similar pass for the MLIR lowering path? Some of the operations listed here can be transformed or canonicalized before lowering.
Sure, we should just add LoweringPrepare for that pipeline. There shouldn't be anything LLVM specific there, though somethings naturally go that direction (e.g. lowering globals). If we find that we need to different decisions, we can think about how to refactor that once we get into those.
@orbiri this table could be interesting for you too!
Sure, we should just add LoweringPrepare for that pipeline. There shouldn't be anything LLVM specific there, though somethings naturally go that direction (e.g. lowering globals). If we find that we need to different decisions, we can think about how to refactor that once we get into those.
I checked this again. The current LoweringPrepare pass is included in the C++-to-MLIR pipeline (i.e. the pipeline built by clang frontend). But it is not included in the pipelines built by cir-opt
or cir-translate
. Is it intentional? Should we add the pass in those pipelines?
But it is not included in the pipelines built by cir-opt or cir-translate. Is it intentional?
LoweringPrepare needs the AST, and we don't have that (yet) by standalone invocations of cir-opt
or cir-translate
on top of CIR files. :(
Should we add the pass in those pipelines?
We should probably add it to clang driven "through MLIR" codegen, yes.
Hello , I find that some libc functions lowering to mlir can use func.call
methods, however, I think it is not necessary to do this. And like some vtable
operations, it is difficult to lowering them to mlir. @bcardosolopes
Hello , I find that some libc functions lowering to mlir can use
func.call
methods, however, I think it is not necessary to do this. And like somevtable
operations, it is difficult to lowering them to mlir.
Sorry, I'm not sure I understand the concern, can you elaborate?
What I mean is how to translate libc function calls into MLIR , and whether operations related to some vtable can be translated into MLIR? @bcardosolopes
I understand your question, but I don't understand the specifics:
I find that some libc functions lowering to mlir can use func.call methods, however, I think it is not necessary to do this
If you don't want to use func.call
methods, what do you want to use instead?
some vtable operations, it is difficult to lowering them to mlir
Why? What did you tried that didn't work?
Also, on a tangent, what is it your goal on working on MLIR support? Are you just trying to cover all CIR lowering possible for MLIR?
We are currently attempting to lower C code to CIR and then further to MLIR for performance analysis. However, for library function calls like libc, we haven't found a good solution to lower them to MLIR yet, and MLIR currently does not support C struct type. @bcardosolopes
for library function calls like libc, we haven't found a good solution to lower them to MLIR yet
Can you elaborate on why func.call isn't good enough? Are you looking into more higher level representations for libc functions in MLIR? I'm not aware of any, indeed. Btw, I'm asking more questions case I'm curious to understand :)
We started mapping some libc functions in CIR, see memchr for instance, but approaches like that would only be useful if you were doing your perf analysis on top of CIR, not MLIR dialects.