Skip to content
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

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

assem2002
Copy link
Contributor

@assem2002 assem2002 commented Oct 13, 2024

Fixes #4860
Fixes #4798
Fixes #4719
Fixes #4523
Fixes ##5739 (The issue now complains about wrong printing with provided formmating)
towards ##5672

@assem2002 assem2002 marked this pull request as ready for review October 13, 2024 20:57
@certik
Copy link
Contributor

certik commented Oct 14, 2024

The CI currently fails.

@certik
Copy link
Contributor

certik commented Nov 26, 2024

@assem2002 let's finish this?

@assem2002
Copy link
Contributor Author

I'll put it as next to work on. It's tricky, but It will be good to have this issue resolved.

@assem2002
Copy link
Contributor Author

assem2002 commented Nov 27, 2024

The major issue is with the various backends we support. This PR removes the implementation in print_arr.cpp pass that iterates on the array and print it element by element in the ASR, instead the llvm backend can handle such a thing and that how things go with write it uses the backend printing not the ASR.
The major CI fails happen because we don't support array printing in the backend with c++ and WASM. Can we make the pass use the removed implementation with all other backends but LLVM? atleast for now

@certik
Copy link
Contributor

certik commented Nov 28, 2024

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.

@assem2002 assem2002 force-pushed the Remove-arr-printing branch 2 times, most recently from e833905 to 698dcea Compare December 9, 2024 01:26
@assem2002
Copy link
Contributor Author

assem2002 commented Dec 10, 2024

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 NOFAST label should be good for now, I believe we can later get that fixed by fixing a similar issue like that one #5062 -- I believe it has the same issue somehow.

@assem2002 assem2002 marked this pull request as ready for review December 10, 2024 08:24
@assem2002
Copy link
Contributor Author

I test all the issues linked to this PR and they work as intended.

Copy link
Contributor

@certik certik left a 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;
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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 ) {
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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.

Copy link
Contributor Author

@assem2002 assem2002 Dec 11, 2024

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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).

Copy link
Contributor Author

@assem2002 assem2002 Dec 12, 2024

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;
Copy link
Contributor

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
};
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@certik certik marked this pull request as draft December 10, 2024 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants