lfortran icon indicating copy to clipboard operation
lfortran copied to clipboard

feat: add support for array type indices in array sections

Open kmr-srbh opened this issue 1 year ago • 5 comments

resolves #4405

We convert

array_1(:, array_2)

to

DO i = lbound(array_1, 1), ubound(array_1, 1)
  DO j = lbound(array_1, 2), ubound(array_1, 2)
    array_1(i, j) = a(i, array_2(j))
  END DO
END DO

kmr-srbh avatar Jul 03 '24 16:07 kmr-srbh

Excellent! Thanks for working on this.

certik avatar Jul 03 '24 16:07 certik

I have a few questions which I need help with.

  1. For the provided MRE,
program main
   implicit none
   real :: A(2, 2), B(2, 2)
   integer :: P(2)

   ! Initialize the matrices and arrays
   A = reshape([1.0, 2.0, 3.0, 4.0], shape(A))
   P = [2, 1]

   ! Slicing
   B = A(:, P)
   print*, rank(A), rank(B)

end program main

the transformed code after the array_op pass is:

! Fortran code after applying the pass: array_op
program main
implicit none
integer(4) :: __1_k
integer(4) :: __1_t
integer(4) :: __1_v
integer(4) :: __2_t
integer(4) :: __2_v
integer(4), dimension(2) :: __libasr__created__var__0__array_constant_
real(4), dimension(:), pointer :: __libasr__created__var__0__array_section_pointer_
real(4), dimension(2, 2) :: a
real(4), dimension(2, 2) :: b
integer(4), dimension(2) :: p
a = reshape([1.00000000e+00, 2.00000000e+00, 3.00000000e+00, 4.00000000e+00], Shape(a))
__1_k = lbound(__libasr__created__var__0__array_constant_, 1)
__libasr__created__var__0__array_constant_(__1_k) = 2
__1_k = __1_k + 1
__libasr__created__var__0__array_constant_(__1_k) = 1
__1_k = __1_k + 1
__1_v = lbound(__libasr__created__var__0__array_constant_, 1)
do __1_t = lbound(p, 1), ubound(p, 1)
    p(__1_t) = __libasr__created__var__0__array_constant_(__1_v)
    __1_v = __1_v + 1
end do
__1_v = lbound(p, 1)
do __1_t = lbound(b, 1), ubound(b, 1)
    __2_v = lbound(p, 1)
    do __2_t = lbound(b, 2), ubound(b, 2)
        b(__1_t, __2_t) = a(ubound(a, 1), p(__2_t))
        __2_v = __2_v + 1
    end do
    __1_v = __1_v + 1
end do
__libasr__created__var__0__array_section_pointer_ => b
print *, Rank(a), Rank(b)
end program main

I see that the current transformation has the assignment value as a(ubound(a, 1), p(__2_t)). We need this to be a(__1_t, p(__2_t)) to get the desired output as GFortran. How do we get access to the outer loop variable?

  1. For every array section, we create an array section pointer which is later utilized for all purposes like printing. I think the above case is special as we cannot have a definitive array section for it due to an array being the index. I tried handling it using a flag variable and not creating in this case, but then the generated output is 0 0 0 0. How do we handle the array section pointer for this?
  2. Minor: I notice an unused variable being created here - __2_v. Why is it created? How do we remove it?

kmr-srbh avatar Jul 03 '24 17:07 kmr-srbh

This implementation currently does not handle the case of the left index being an array. I will handle it along with the proposed methods for handling the queries stated above.

kmr-srbh avatar Jul 03 '24 17:07 kmr-srbh

Regarding the first question, you need to keep track of the loops in the visitor I think.

Regarding the second question, can you give an example code and ASR for that? It might not be possible to use pointers, let's see.

certik avatar Jul 03 '24 17:07 certik

can you give an example code and ASR for that?

MRE

program main
   implicit none
   real :: A(2, 2), B(2, 2)
   integer :: P(2)

   A = reshape([1.0, 2.0, 3.0, 4.0], shape(A))
   P = [2, 1]

   B = A(:, P)
   print *, B

end program main

ASR after array_op pass

;; ASR after applying the pass: array_op
(TranslationUnit
    (SymbolTable
        1
        {
            main:
                (Program
                    (SymbolTable
                        2
                        {
                            __1_k:
                                (Variable
                                    2
                                    __1_k
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Integer 4)
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            __1_t:
                                (Variable
                                    2
                                    __1_t
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Integer 4)
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            __1_v:
                                (Variable
                                    2
                                    __1_v
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Integer 4)
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            __2_t:
                                (Variable
                                    2
                                    __2_t
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Integer 4)
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            __2_v:
                                (Variable
                                    2
                                    __2_v
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Integer 4)
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            __libasr__created__var__0__array_constant_:
                                (Variable
                                    2
                                    __libasr__created__var__0__array_constant_
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Array
                                        (Integer 4)
                                        [((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))]
                                        FixedSizeArray
                                    )
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            __libasr__created__var__0__array_section_pointer_:
                                (Variable
                                    2
                                    __libasr__created__var__0__array_section_pointer_
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Pointer
                                        (Array
                                            (Real 4)
                                            [(()
                                            ())]
                                            DescriptorArray
                                        )
                                    )
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            a:
                                (Variable
                                    2
                                    a
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Array
                                        (Real 4)
                                        [((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))
                                        ((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))]
                                        FixedSizeArray
                                    )
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            b:
                                (Variable
                                    2
                                    b
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Array
                                        (Real 4)
                                        [((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))
                                        ((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))]
                                        FixedSizeArray
                                    )
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                ),
                            p:
                                (Variable
                                    2
                                    p
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (Array
                                        (Integer 4)
                                        [((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))]
                                        FixedSizeArray
                                    )
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                )
                        })
                    main
                    []
                    [(Assignment
                        (Var 2 a)
                        (ArrayReshape
                            (ArrayConstant
                                16
                                [1.00000000e+00, 2.00000000e+00, 3.00000000e+00, 4.00000000e+00]
                                (Array
                                    (Real 4)
                                    [((IntegerConstant 1 (Integer 4))
                                    (IntegerConstant 4 (Integer 4)))]
                                    FixedSizeArray
                                )
                                ColMajor
                            )
                            (ArrayPhysicalCast
                                (IntrinsicArrayFunction
                                    Shape
                                    [(ArrayPhysicalCast
                                        (Var 2 a)
                                        FixedSizeArray
                                        DescriptorArray
                                        (Array
                                            (Real 4)
                                            [((IntegerConstant 1 (Integer 4))
                                            (IntegerConstant 2 (Integer 4)))
                                            ((IntegerConstant 1 (Integer 4))
                                            (IntegerConstant 2 (Integer 4)))]
                                            DescriptorArray
                                        )
                                        ()
                                    )]
                                    0
                                    (Array
                                        (Integer 4)
                                        [((IntegerConstant 1 (Integer 4))
                                        (IntegerConstant 2 (Integer 4)))]
                                        FixedSizeArray
                                    )
                                    (ArrayConstant
                                        8
                                        [2, 2]
                                        (Array
                                            (Integer 4)
                                            [((IntegerConstant 1 (Integer 4))
                                            (IntegerConstant 2 (Integer 4)))]
                                            FixedSizeArray
                                        )
                                        ColMajor
                                    )
                                )
                                FixedSizeArray
                                DescriptorArray
                                (Array
                                    (Integer 4)
                                    [((IntegerConstant 1 (Integer 4))
                                    (IntegerConstant 2 (Integer 4)))]
                                    DescriptorArray
                                )
                                ()
                            )
                            (Array
                                (Real 4)
                                [(()
                                ())]
                                FixedSizeArray
                            )
                            ()
                        )
                        ()
                    )
                    (Assignment
                        (Var 2 __1_k)
                        (ArrayBound
                            (Var 2 __libasr__created__var__0__array_constant_)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            LBound
                            ()
                        )
                        ()
                    )
                    (Assignment
                        (ArrayItem
                            (Var 2 __libasr__created__var__0__array_constant_)
                            [(()
                            (Var 2 __1_k)
                            ())]
                            (Integer 4)
                            RowMajor
                            ()
                        )
                        (IntegerConstant 2 (Integer 4))
                        ()
                    )
                    (Assignment
                        (Var 2 __1_k)
                        (IntegerBinOp
                            (Var 2 __1_k)
                            Add
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            ()
                        )
                        ()
                    )
                    (Assignment
                        (ArrayItem
                            (Var 2 __libasr__created__var__0__array_constant_)
                            [(()
                            (Var 2 __1_k)
                            ())]
                            (Integer 4)
                            RowMajor
                            ()
                        )
                        (IntegerConstant 1 (Integer 4))
                        ()
                    )
                    (Assignment
                        (Var 2 __1_k)
                        (IntegerBinOp
                            (Var 2 __1_k)
                            Add
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            ()
                        )
                        ()
                    )
                    (Assignment
                        (Var 2 __1_v)
                        (ArrayBound
                            (Var 2 __libasr__created__var__0__array_constant_)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            LBound
                            ()
                        )
                        ()
                    )
                    (DoLoop
                        ()
                        ((Var 2 __1_t)
                        (ArrayBound
                            (Var 2 p)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            LBound
                            ()
                        )
                        (ArrayBound
                            (Var 2 p)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            UBound
                            ()
                        )
                        ())
                        [(Assignment
                            (ArrayItem
                                (Var 2 p)
                                [(()
                                (Var 2 __1_t)
                                ())]
                                (Integer 4)
                                RowMajor
                                ()
                            )
                            (ArrayItem
                                (Var 2 __libasr__created__var__0__array_constant_)
                                [(()
                                (Var 2 __1_v)
                                ())]
                                (Integer 4)
                                RowMajor
                                ()
                            )
                            ()
                        )
                        (Assignment
                            (Var 2 __1_v)
                            (IntegerBinOp
                                (Var 2 __1_v)
                                Add
                                (IntegerConstant 1 (Integer 4))
                                (Integer 4)
                                ()
                            )
                            ()
                        )]
                        []
                    )
                    (Assignment
                        (Var 2 __1_v)
                        (ArrayBound
                            (Var 2 p)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            LBound
                            ()
                        )
                        ()
                    )
                    (DoLoop
                        ()
                        ((Var 2 __1_t)
                        (ArrayBound
                            (Var 2 b)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            LBound
                            ()
                        )
                        (ArrayBound
                            (Var 2 b)
                            (IntegerConstant 1 (Integer 4))
                            (Integer 4)
                            UBound
                            ()
                        )
                        ())
                        [(Assignment
                            (Var 2 __2_v)
                            (ArrayBound
                                (Var 2 p)
                                (IntegerConstant 1 (Integer 4))
                                (Integer 4)
                                LBound
                                ()
                            )
                            ()
                        )
                        (DoLoop
                            ()
                            ((Var 2 __2_t)
                            (ArrayBound
                                (Var 2 b)
                                (IntegerConstant 2 (Integer 4))
                                (Integer 4)
                                LBound
                                ()
                            )
                            (ArrayBound
                                (Var 2 b)
                                (IntegerConstant 2 (Integer 4))
                                (Integer 4)
                                UBound
                                ()
                            )
                            ())
                            [(Assignment
                                (ArrayItem
                                    (Var 2 b)
                                    [(()
                                    (Var 2 __1_t)
                                    ())
                                    (()
                                    (Var 2 __2_t)
                                    ())]
                                    (Real 4)
                                    RowMajor
                                    ()
                                )
                                (ArrayItem
                                    (Var 2 a)
                                    [((ArrayBound
                                        (Var 2 a)
                                        (IntegerConstant 1 (Integer 4))
                                        (Integer 4)
                                        LBound
                                        (IntegerConstant 1 (Integer 4))
                                    )
                                    (ArrayBound
                                        (Var 2 a)
                                        (IntegerConstant 1 (Integer 4))
                                        (Integer 4)
                                        UBound
                                        (IntegerConstant 2 (Integer 4))
                                    )
                                    (IntegerConstant 1 (Integer 4)))
                                    (()
                                    (ArrayItem
                                        (Var 2 p)
                                        [(()
                                        (Var 2 __2_t)
                                        ())]
                                        (Real 4)
                                        ColMajor
                                        ()
                                    )
                                    ())]
                                    (Real 4)
                                    ColMajor
                                    ()
                                )
                                ()
                            )
                            (Assignment
                                (Var 2 __2_v)
                                (IntegerBinOp
                                    (Var 2 __2_v)
                                    Add
                                    (IntegerConstant 1 (Integer 4))
                                    (Integer 4)
                                    ()
                                )
                                ()
                            )]
                            []
                        )
                        (Assignment
                            (Var 2 __1_v)
                            (IntegerBinOp
                                (Var 2 __1_v)
                                Add
                                (IntegerConstant 1 (Integer 4))
                                (Integer 4)
                                ()
                            )
                            ()
                        )]
                        []
                    )
                    (Associate
                        (Var 2 __libasr__created__var__0__array_section_pointer_)
                        (ArrayPhysicalCast
                            (Var 2 b)
                            FixedSizeArray
                            DescriptorArray
                            (Array
                                (Real 4)
                                [((IntegerConstant 1 (Integer 4))
                                (IntegerConstant 2 (Integer 4)))
                                ((IntegerConstant 1 (Integer 4))
                                (IntegerConstant 2 (Integer 4)))]
                                DescriptorArray
                            )
                            ()
                        )
                    )
                    (Print
                        [(Var 2 b)]
                        ()
                        ()
                    )]
                )
        })
    []
)

kmr-srbh avatar Jul 03 '24 17:07 kmr-srbh

Since this feature is used quite some times in PRIMA, I am just quickly updating this PR. I will update it finally with a test tomorrow morning (IST).

kmr-srbh avatar Oct 23 '24 20:10 kmr-srbh

Done! Adding tests now.

program main
    implicit none
    real :: A(2, 2, 2), B(2, 2, 2)
    integer :: P(2)

    ! Initialize the matrices and arrays
    A = reshape([1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 5.0], shape(A))
    P = [2, 1]

    ! Slicing
    B = A(:, :, P)
    print*, rank(A), rank(B)

end program main
(lf) saurabh-kumar@Awadh:~/Projects/System/lfortran$ gfortran ./examples/example.f90 && ./a.out
           3           3
(lf) saurabh-kumar@Awadh:~/Projects/System/lfortran$ lfortran ./examples/example.f90
3    3

kmr-srbh avatar Oct 24 '24 04:10 kmr-srbh

Ready.

kmr-srbh avatar Oct 24 '24 04:10 kmr-srbh

This looks good, great job!

Can you send this against the simplifier also? We need to ensure it doesn't break things there.

certik avatar Oct 24 '24 05:10 certik

The CI failed due to issue related to ArrayReshape when using --experimental-simplifier. Skipping testing with it for now.

kmr-srbh avatar Oct 24 '24 06:10 kmr-srbh

The failure in #5139 is a missing implementation detail. Marking this as draft for now.

kmr-srbh avatar Oct 24 '24 12:10 kmr-srbh

This doesn't work in #5139 since there is no result_var there. We need to create a temporary result to fix that. I tried making a temporary but it is being created as an allocatable, and I don't think that is required. @kmr-srbh could you take a look?

advikkabra avatar Oct 25 '24 03:10 advikkabra

@advikkabra right, that's exactly the cause of the failure. As for the creation of the temporary as an allocatable, I am guessing the ttype passed to get_result_type() might be that of ArraySection (x->m_type). We handle array sections as DescriptorArray. Could you please push a commit to this PR? Let's iterate on this further.

kmr-srbh avatar Oct 25 '24 03:10 kmr-srbh

I rebased everything to get the latest CI tests.

certik avatar Nov 24 '24 15:11 certik

@kmr-srbh if this is ready to be merged, then go ahead and merge it.

certik avatar Nov 24 '24 15:11 certik

There is some formatting issue (braces required), I am resolving it and merging this.

kmr-srbh avatar Nov 24 '24 16:11 kmr-srbh