-
-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove arr printing in pass print_arr
#5039
base: main
Are you sure you want to change the base?
Conversation
The CI currently fails. |
@assem2002 let's finish this? |
I'll put it as next to work on. It's tricky, but It will be good to have this issue resolved. |
The major issue is with the various backends we support. This PR removes the implementation in |
You can keep the old pass and run it for other backends, but add a new pass or whatever new way just for the LLVM backend. That way things wouldn't change for the other backends and we can merge it. |
e833905
to
698dcea
Compare
…onflicts now with array_size of kind(8)
…(A workaround - The codebase doesn't handle array size of integer kind 8)
… It has some weird bug with dead code llvm optimization
698dcea
to
89cbab5
Compare
The failing test (https://github.com/lfortran/lfortran/actions/runs/12251263956/job/34176739756) works for me locally. It's usually related to the optimization done by llvm, It considers some of the ASR is dead code and removes it and sometimes segfaults. I think |
I test all the issues linked to this PR and they work as intended. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fixes! I think there are some design choices that I think we should do differently, I left comments. Let me know what you think.
Let's also add tests that previously segfaulted but now work.
Why does it fail with FAST?
@@ -783,7 +783,7 @@ char** parse_fortran_format(char* format, int64_t *count, int64_t *item_start) { | |||
|
|||
struct array_iteration_state{ | |||
//Preserve array size and current element index | |||
int64_t array_size; | |||
int32_t array_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did we move from 64bit to 32bit?
32bit is faster, and it's ok to use by default, but if we only support 1 integer size, I think we should support 64bit, otherwise we can't index larger arrays than 2GB, so it is going to bite us later.
I think we either support just one int, in that case it must be 64 bit. Or we support both, then the default can be 32 bit for speed, as long as users can select 64 bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think it kinda of important thing to handle. We have issue with handling size node with return type of kind 8 . I'll invoke the error and let you know and maybe create and MRE and report the issue. I would like also to mention that allocatable arrays don't handle size of i64
the array_descriptor just have i32
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I addressed the issue here #5647. I'm working on it.
ASR::is_a<ASR::StructType_t>(* | ||
ASRUtils::type_get_past_array_pointer_allocatable( | ||
ASRUtils::expr_type(format->m_args[i]))); | ||
if (PassUtils::is_array(format->m_args[i]) && print_not_handled_by_backend ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is problematic. I think we should not be hardwiring backend information into ASR passes. I think ASR passes should not care what current and future backends you use them with.
Rather, we want to pass in the option to either transform the array or not, as a regular option into the pass constructor. Then at the upper level you decide what passes and what options to call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great thing to know about. So you suggest passing a flag to the pass saying (okay we support printing array in the backend we're targeting), rather than making the passes themselves try to make decisions based on the passed backend?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. You tell the ASR pass exactly what you want to get done. If we are not transforming the printing, is the print_arr
pass even doing anything? If so, just pass in a flag to customize what it is doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just want to make sure we're on the same page. I'll just create a bool backend_supports_array_printing=false
as member of the PassOptions
struct and the print_arr
acts upon that flag. Is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call the flag differently. I don't quite understand what print_arr
is doing if not changing the array printing. Why not just skip the pass itself altogether? If you can explain to me what else the pass is doing, I can provide a better direction.
If we need the pass, then the option should be call "skip_array_printing". The pass does not care about any backend, nor what it supports.
Regarding the PassOptions, you can probably put it there for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for now we support printing arrays in LLVM for fortran primitive types (character, integer, real, complex, ...) but not for arrays of type struct (Fortran type
). for any other backend we don't yet support printing arrays in the backend.
So, We need to always use the pass with all the backends; but with LLVM we have to use the pass for only the case of array of type struct (Fortran type).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual motive behind printing arrays in the backend instead of using the ASR was returning correct output when using fmt
as it could be runtime value so we had to print the array at the runtime instead of replacing the print node for the whole array with arrayitems, so we gave everything to the backend (the fmt
and all the arguments) to handle the formatting at runtime.
now I'm questioning the road we went through! Direct array printing statement seems to be a thing to be handled by the frontend of the compiler as we could be using low-level backend like LLVM or C or C++ that doesn't know how to print an array. but we still face the issue of the runtime formatting on the args, The ASR can't spread the array into separate printable elements for the string_format function to recognize -- print_arr pass loops on the array based on the runtime size of the array.
We need to find a way that makes the runtime-formatting function match against the actual element (runtime element) but also to not make the backend really concerned about proper looping and knowing the type of the thing it's trying to print ( EX : An array of struct A
( struct A
has struct B
as member), this would be a messy message to pass and it could get so long and very nested)
@@ -61,6 +65,7 @@ struct PassOptions { | |||
bool openmp = false; | |||
bool experimental_simplifier = false; | |||
bool enable_gpu_offloading = false; | |||
Backend backend = Backend::llvm; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is problematic. I think we don't care in the compiler options which backends we use. For example, users can write their own backends, and they want to call certain passes. We should not hardwire backends like this, nor make any decisions based on what backends are run.
Rather, the compilation is composed of various passes with options, and users assemble their compilation pipeline as they see fit.
|
||
enum Backend { | ||
llvm, c, cpp, x86, wasm, fortran, mlir | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should stay here. It's the highest-level driver that should decide what pipelines and backends will get run. The internals of the compiler should not care.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that is #5039 (comment) what we should do, so this change won't be needed.
Fixes #4860
Fixes #4798
Fixes #4719
Fixes #4523
Fixes ##5739 (The issue now complains about wrong printing with provided formmating)
towards ##5672