Skip to content

[ASR/LLVM]: Implement Tuple/List Compare #1342

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

Merged
merged 15 commits into from
Dec 12, 2022

Conversation

Smit-create
Copy link
Collaborator

@Smit-create Smit-create commented Dec 2, 2022

@Smit-create Smit-create changed the title Implement Tuple Compare ASR: Implement Tuple Compare Dec 2, 2022
@Smit-create
Copy link
Collaborator Author

This PR adds to the ASR front end. We need to figure out how to handle it in the LLVM backend. C handles this recursively and I suppose that would work fine with the current C implementations.

@Smit-create Smit-create force-pushed the i-1245 branch 2 times, most recently from 9118f10 to 14c0c9d Compare December 2, 2022 08:59
@Smit-create Smit-create changed the title ASR: Implement Tuple Compare ASR: Implement Tuple/List Compare Dec 2, 2022
@Smit-create Smit-create marked this pull request as ready for review December 2, 2022 09:00
Copy link
Collaborator

@czgdp1807 czgdp1807 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please implement the support for both these nodes in LLVM. I will approve and merge then.

@Smit-create
Copy link
Collaborator Author

Yes, I'm planning to add a pass to handle the tuple/list comparison.

@Smit-create
Copy link
Collaborator Author

This PR needs #1349 to be merged


def f():
a11: tuple[i32, i32]
b11: tuple[i32, i32]
Copy link
Collaborator

@czgdp1807 czgdp1807 Dec 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test for nested tuples as well with mixed types like, tuple[i32, tuple[i64, f32], str].

Copy link
Collaborator

@czgdp1807 czgdp1807 Dec 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case (see #1342 (comment)) is not yet covered in the tests. Please test for this first.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case is not yet covered in the tests. Please test for this first.

I avoided using f32 because of precision issues in comparison. I added a test for the mixed types:

    a: tuple[tuple[i32, i32], str, bool]
    b: tuple[tuple[i32, i32], str, bool]
    a = (a11, 'ok', True)
    b = (b11, 'ok', True)
    assert a == b
    b = (b11, 'notok', True)
    assert a != b

@Smit-create Smit-create changed the title ASR: Implement Tuple/List Compare [ASR/LLVM][WIP]: Implement Tuple/List Compare Dec 5, 2022
using ASR::down_cast;

/*
* This ASR pass handles TupleCompare.
Copy link
Contributor

@certik certik Dec 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put an example here what is an example input and example output of this pass?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will document once I complete adding the ListCompare pass.

@certik
Copy link
Contributor

certik commented Dec 5, 2022

This adds a pass in the LLVM backend. What exactly does the pass do? Please document in the docstring, see my comment above.

Is this just an optional pass that we currently run to simplify the backend, but it is not needed to run in theory? Or is this pass required to always be run due to a deficiency in our ASR design? If the latter, then we need to improve ASR, so that one can generate code from it without requiring any passes.

@czgdp1807
Copy link
Collaborator

If the latter, then we need to improve ASR, so that one can generate code from it without requiring any passes.

IMHO, we don't need a pass here at all (at least for tuples). The backend should be able to do this. Comparing tuples is fairly simple in LLVM. Just generate code according to the type of the elements (they are fixed in number as tuples are fixed size types, we specify everything in the tuple type itself). Calling function for simple comparison of tuples is not worth it I think. Comparing lists though does require generating a loop but I think for generating low level code like LLVM, x86 the loop should be inlined. For C we can add function on our own. Pass might not be needed.

@Smit-create
Copy link
Collaborator Author

The reason for adding a pass to compare complex data types like lists, tuples is that it will make the LLVM backend less complex. The current approach recursively compares each element for a tuple, list, etc, and altogether is implemented under one class. The other benefit is that if we make this pass re-usable to any other backend will reduce the effort to write the same recursive algorithm in each backend.

IMHO, we don't need a pass here at all (at least for tuples)

We need TupleCompare and ListCompare at the same level (either both at ASR pass or both at the backend.) Otherwise, the nested datatypes won't work effectively. For example, if we implement ListCompare via a pass and TupleCompare in LLVM backend then, tuple[list[str], i32] won't work.

@czgdp1807
Copy link
Collaborator

The reason for adding a pass to compare complex data types like lists, tuples is that it will make the LLVM backend less complex

The problem is LLVM already has the infrastructure to generate code for Tuple comparisons. Extending it for List comparisons is easy. We need it to implement dict effectively. So having or not having this pass doesn't make much difference. You may use this pass for high level languages like C, C++, Julia, Fortran backends. But for low level backends like LLVM, x86 I would vouch for directly generating inlined code.

Let's do the following,

  1. For LLVM backend, open a separate PR and implement these comparisons directly there. Reason being simple, we already compare tuples in LLVM for implementing dict, so just re-using those APIs would be easy. See below,

llvm::Value* LLVMUtils::is_equal_by_value(llvm::Value* left, llvm::Value* right,
llvm::Module& module, ASR::ttype_t* asr_type) {

Extend it. Re-use it. Modify it. It will generate inlined code so no overhead of function calls.

  1. For C, C++ keep using this pass as it will require less effort there and generate readable code for high level languages backends.

@Smit-create
Copy link
Collaborator Author

Sure, that sounds like a good idea. I can add a pass for both the compares in this PR and open a new PR for the LLVM backend as a follow-up.

@Smit-create
Copy link
Collaborator Author

@certik @czgdp1807 I have added a pass for both list and tuple compare. We can merge this if this is okay and then as a follow-up, I'll try to remove this pass from the default list and then implement in the LLVM backend.

@Smit-create Smit-create added ready for review PRs that are ready for review asr ASR related changes asr_pass ASR pass related changes labels Dec 11, 2022
@czgdp1807
Copy link
Collaborator

I'll try to remove this pass from the default list and then implement in the LLVM backend.

I don't like the pass for LLVM backend but I will approve this PR. Please add it immediately after this PR is merged.


def f():
a11: tuple[i32, i32]
b11: tuple[i32, i32]
Copy link
Collaborator

@czgdp1807 czgdp1807 Dec 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case (see #1342 (comment)) is not yet covered in the tests. Please test for this first.

@Smit-create
Copy link
Collaborator Author

Ahh, this was working all good before rebasing but now fails with this:

this->visit_stmt(*x.m_body[i]);
  File "../libasr/asr.h", line 4217
  File "../libasr/asr.h", line 3983
  File "/Users/thebigbool/repos/lpython/src/libasr/codegen/asr_to_llvm.cpp", line 4007
    LFORTRAN_ASSERT(finder != nested_globals.end());
AssertFailed: finder != nested_globals.end()

@Smit-create Smit-create disabled auto-merge December 11, 2022 12:24
@Smit-create Smit-create changed the title [ASR/LLVM][WIP]: Implement Tuple/List Compare [ASR/LLVM]: Implement Tuple/List Compare Dec 12, 2022
@Smit-create Smit-create merged commit e6c2a3b into lcompilers:main Dec 12, 2022
@Smit-create Smit-create deleted the i-1245 branch December 12, 2022 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
asr_pass ASR pass related changes asr ASR related changes ready for review PRs that are ready for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants