This is an archive of the discontinued LLVM Phabricator instance.

[Polly] [Fortran Support] Change "global" pattern match to work for params
ClosedPublic

Authored by bollu on May 15 2017, 5:17 AM.

Details

Summary
  • Pattern match for parameters was incorrect: was matching on entire

array, not loads and stores into the array.

  • Realized when writing the pattern match that the GlobalNonAlloc

pattern will also match this case.

  • Changed code so that this is used. Also added a test case that checks for a match against both a load a store.

Diff Detail

Repository
rL LLVM

Event Timeline

bollu created this revision.May 15 2017, 5:17 AM
Meinersbur added inline comments.May 15 2017, 7:29 AM
include/polly/ScopBuilder.h
60–61 ↗(On Diff #98987)

I don't understand the concept of "visible/invisible" array descriptors. Why is an array whose' memory is loaded "invisible"?

bollu added a comment.May 15 2017, 8:02 AM

@Meinersbur: Perhaps Visible/Invisible is a poor choice of names. I would be glad if you could suggest something better.

Visible allocations:

If you consider this block of Fortran code:

code-with-allocate.f90
; MODULE src_soil
; USE data_parameters, ONLY :   &
;     wp,        & ! KIND-type parameter for real variables
;     iintegers    ! KIND-type parameter for standard integer variables
; IMPLICIT NONE
; REAL (KIND = wp),     ALLOCATABLE, PRIVATE  :: &
;   xdzs     (:)
; CONTAINS
; SUBROUTINE terra1(n)
;   INTEGER, intent(in) :: n
;   INTEGER (KIND=iintegers) ::  &
;     j
;   Allocate(xdzs(n));
;    DO j = 2, n
;         xdzs(j) = xdzs(j) * xdzs(j) + xdzs(j - 1)
;   END DO
; END SUBROUTINE terra1
; END MODULE src_soil

there's an Allocate call to the dynamically sized fortran array. So, when dragonegg generates code for this block of code, there's a corresponding call to malloc.

Invisible allocations:

Module scope arrays:
code-with-global.f90
; MODULE src_soil
; USE data_parameters, ONLY :   &
;     wp,        & ! KIND-type parameter for real variables
;     iintegers    ! KIND-type parameter for standard integer variables
; IMPLICIT NONE
; REAL (KIND = wp),     ALLOCATABLE, PRIVATE  :: &
;   xdzs     (:)
; CONTAINS
;
; SUBROUTINE terra1(n)
;   INTEGER, intent(in) :: n
;
;   INTEGER (KIND=iintegers) ::  &
;     j
;
;    DO j = 22, n
;         xdzs(j) = xdzs(j) * xdzs(j) + xdzs(j - 1)
;   END DO
; END SUBROUTINE terra1
; END MODULE src_soil

In this case, there's no Allocate to the module-scope xdzs variable, so the generated code has a LLVM global:

code-with-global.ll
@__src_soil_MOD_xdzs = unnamed_addr global %"struct.array1_real(kind=8)" zeroinitializer, align 32
...
"3.preheader":                                    ; preds = %entry.split
  %tmp2 = load i64, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 1), align 8, !tbaa !3
  %tmp3 = load double*, double** bitcast (%"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs to double**), align 32
  %tmp4 = add i32 %tmp, 1
Parameters to functions:
parameter.f90
;     SUBROUTINE func(xs, n)
;         IMPLICIT NONE
;         INTEGER, DIMENSION(:), INTENT(INOUT) :: xs
;         INTEGER, INTENT(IN) :: n
;         INTEGER :: i

;         DO i = 1, n
;             xs(i) = 1
;         END DO
;
;     END SUBROUTINE func

This generates the corresponding LLVM with no malloc, it simply assumes that the parameter is a fortran array descriptor:

parameter.ll
define internal void @testfunc(%"struct.array1_integer(kind=4)"* noalias %xs, i32* noalias %n) {
entry:
  br label %entry.split
...

@Meinersbur: I explained the Visible / Invisible thing, perhaps we could find better names for them? I'd like suggestions, because I think the current ones maybe too confusing.

Meinersbur edited edge metadata.May 17 2017, 4:57 AM

Why not using the Fortran notation? How does the DragonEgg code call these?

I don't know Fortran, but here is what I found after searching a bit on the Internet.
Fortran has "allocatable" and non-allocatable arrays. Allocatable arrays cane be allocated using the "ALLOCATE" statement (ok, that sounds a bit too obvious :-).

In your examples the difference seems to be that the "visible" variant has the "ALLOCATE" in the same function, which is therefore the source of the descripter pointer. In other cases, the descriptor pointer has been allocated somewhere else, it just has to load it from somewhere.

I'd not handle the two cases differently, i.e. in the same function. That the source of the pointer is sometimes a malloc, sometimes a load, is/might be a result of compiler optimizations such as SROA. Try to be more flexible and accept any pointer, whether it came in through a load, malloc, function argument or other sources. Use ScalarEvolution::getSCEV to avoid that sometimes there is a GetElementPtr or bitcast in-between. This might limit the recognizability of Fortran array to only recognize the descriptor type, but should be acceptable since we explicitly tell the compiler it's Fortran source using the command line switch.

Basically,

struct descriptor_dimension { int i,j,k; }
struct array1_integer { void *ptr; int x,y; descriptor_dimension dims[1];  }

struct array1_integer *Arr;
void *Ptr = Arr->ptr; 

access:
  Ptr[somewhere];

For each access, we are looking for Arr. From the access we only get Ptr. We can get to Arr by searching for a pointer variable of type struct.array1_integer*(that is, a type that matches the conditions) where Ptr is loaded from of stored to the first element. That is our Arr. Should be a much more stable detection algorithm which does not depend on certain optimizations to (not) occur.

Do you also plan to support non-allocatable arrays?

Meinersbur accepted this revision.May 17 2017, 6:54 AM

Accepting the change as useful compared to the previous state. If you want to follow my suggestion, you can update this review or create a new one after committing this.

include/polly/ScopBuilder.h
60–61 ↗(On Diff #98987)

Please explain here (as well) what "visible" means, or add an @see.

86 ↗(On Diff #98987)

Please explain here (as well) what "visible" means, or add a @see.

test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll
55 ↗(On Diff #98987)

Unrelated?

This revision is now accepted and ready to land.May 17 2017, 6:54 AM
bollu added inline comments.May 18 2017, 7:08 AM
test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll
55 ↗(On Diff #98987)

I wanted to explicitly state that this is the store we are interested in. It is perhaps redundant. Do you want me to remove it?

bollu added a comment.May 18 2017, 9:03 AM
This comment was removed by bollu.
This revision was automatically updated to reflect the committed changes.