[polly] r303356 - [Fortran Support] Change "global" pattern match to work for params

Siddharth Bhat via llvm-commits llvm-commits at lists.llvm.org
Thu May 18 09:47:13 PDT 2017


Author: bollu
Date: Thu May 18 11:47:13 2017
New Revision: 303356

URL: http://llvm.org/viewvc/llvm-project?rev=303356&view=rev
Log:
[Fortran Support] Change "global" pattern match to work for params

Summary:
- Rename global / local naming convention that did not make much sense
to Visible / Invisible, where the visible refers to whether the ALLOCATE
call to the Fortran array is present in the current module or not.

- This match now works on both cross fortran module globals and on
parameters to functions since neither of them are necessarily allocated
at the point of their usage.

- Add testcase that matches against both a load and a store against
function parameters.

Differential Revision: https://reviews.llvm.org/D33190

Added:
    polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll
Modified:
    polly/trunk/include/polly/ScopBuilder.h
    polly/trunk/lib/Analysis/ScopBuilder.cpp
    polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll

Modified: polly/trunk/include/polly/ScopBuilder.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopBuilder.h?rev=303356&r1=303355&r2=303356&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopBuilder.h (original)
+++ polly/trunk/include/polly/ScopBuilder.h Thu May 18 11:47:13 2017
@@ -57,21 +57,24 @@ class ScopBuilder {
   // Methods for pattern matching against Fortran code generated by dragonegg.
   // @{
 
-  /// Try to match for the descriptor of a Fortran Array that has been declared
-  /// global, and is allocated in this module.
+  /// Try to match for the descriptor of a Fortran array whose allocation
+  /// is not visible. That is, we can see the load/store into the memory, but
+  /// we don't actually know where the memory is allocated. If ALLOCATE had been
+  /// called on the Fortran array, then we will see the lowered malloc() call.
+  /// If not, this is dubbed as an "invisible allocation".
   ///
-  /// "@globaldescriptor" is the descriptor of the Fortran Array.
+  /// "<descriptor>" is the descriptor of the Fortran array.
   ///
-  /// Pattern match for "@globaldescriptor":
+  /// Pattern match for "@descriptor":
   ///  1. %mem = load double*, double** bitcast (%"struct.array1_real(kind=8)"*
-  ///    @globaldescriptor to double**), align 32
+  ///    <descriptor> to double**), align 32
   ///
   ///  2. [%slot = getelementptr inbounds i8, i8* %mem, i64 <index>]
   ///  2 is optional because if you are writing to the 0th index, you don't
   ///     need a GEP.
   ///
-  ///  3.1 store/load <memtype> <val>, <memtype>* %slot, align 8
-  ///  3.2 store/load <memtype> <val>, <memtype>* %mem, align 8
+  ///  3.1 store/load <memtype> <val>, <memtype>* %slot
+  ///  3.2 store/load <memtype> <val>, <memtype>* %mem
   ///
   /// @see polly::MemoryAccess, polly::ScopArrayInfo
   ///
@@ -79,19 +82,20 @@ class ScopBuilder {
   ///
   /// @param Inst The LoadInst/StoreInst that accesses the memory.
   ///
-  /// @returns Reference to @globaldescriptor on success, nullptr on failure.
-  Value *findFADGlobalAlloc(MemAccInst Inst);
+  /// @returns Reference to <descriptor> on success, nullptr on failure.
+  Value *findFADAllocationInvisible(MemAccInst Inst);
 
-  /// Try to match for the descriptor of a Fortran Array that has been declared
-  /// global, has not been allocated, and is being allocated here.
+  /// Try to match for the descriptor of a Fortran array whose allocation
+  /// call is visible. When we have a Fortran array, we try to look for a
+  /// Fortran array where we can see the lowered ALLOCATE call. ALLOCATE
+  /// is materialized as a malloc(...) which we pattern match for.
   ///
-  /// Pattern match for "@globaldescriptor":
+  /// Pattern match for "%untypedmem":
   ///  1. %untypedmem = i8* @malloc(...)
   ///
-  ///  2. %typedmem = bitcast i8* %untypedmem to <memtype>*
+  ///  2. %typedmem = bitcast i8* %untypedmem to <memtype>
   ///
-  ///  3. [%slot = getelementptr inbounds
-  ///                  <memtype>, <memtype>* %typedmem, i64 <index>]
+  ///  3. [%slot = getelementptr inbounds i8, i8* %typedmem, i64 <index>]
   ///  3 is optional because if you are writing to the 0th index, you don't
   ///     need a GEP.
   ///
@@ -104,30 +108,9 @@ class ScopBuilder {
   ///
   /// @param Inst The LoadInst/StoreInst that accesses the memory.
   ///
-  /// @returns Reference to @globaldescriptor on success, nullptr on failure.
-  Value *findFADGlobalNonAlloc(MemAccInst Inst);
+  /// @returns Reference to %untypedmem on success, nullptr on failure.
+  Value *findFADAllocationVisible(MemAccInst Inst);
 
-  /// Try to match for the descriptor of a Fortran array that is a parameter
-  /// to a function, and has not been allocated.
-  ///
-  /// Pattern match for "%param":
-  ///  1. %mem =  bitcast %"struct.array1_integer(kind=4)"* %param to i32**
-  ///
-  ///  2. [%slot = getelementptr inbounds i8, i8* %mem, i64 <index>]
-  ///  2 is optional because if you are writing to the 0th index, you don't
-  ///     need a GEP.
-  ///
-  ///  3.1 store/load <memtype> <val>, <memtype>* %slot, align 8
-  ///  3.2 store/load <memtype> <val>, <memtype>* %mem, align 8
-  ///
-  /// @see polly::MemoryAccess, polly::ScopArrayInfo
-  ///
-  /// @note assumes -polly-canonicalize has been run.
-  ///
-  /// @param Inst The LoadInst/StoreInst that accesses the memory.
-  ///
-  /// @returns Reference to "%param" on success, nullptr on failure.
-  Value *findFADLocalNonAlloc(MemAccInst Inst);
   // @}
 
   // Build the SCoP for Region @p R.

Modified: polly/trunk/lib/Analysis/ScopBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopBuilder.cpp?rev=303356&r1=303355&r2=303356&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopBuilder.cpp (original)
+++ polly/trunk/lib/Analysis/ScopBuilder.cpp Thu May 18 11:47:13 2017
@@ -201,7 +201,7 @@ bool isFortranArrayDescriptor(Value *V)
   return true;
 }
 
-Value *ScopBuilder::findFADGlobalNonAlloc(MemAccInst Inst) {
+Value *ScopBuilder::findFADAllocationVisible(MemAccInst Inst) {
   // match: 4.1 & 4.2 store/load
   if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst))
     return nullptr;
@@ -272,15 +272,11 @@ Value *ScopBuilder::findFADGlobalNonAllo
   return nullptr;
 }
 
-Value *ScopBuilder::findFADGlobalAlloc(MemAccInst Inst) {
+Value *ScopBuilder::findFADAllocationInvisible(MemAccInst Inst) {
   // match: 3
   if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst))
     return nullptr;
 
-  // match: 3
-  if (Inst.getAlignment() != 8)
-    return nullptr;
-
   Value *Slot = Inst.getPointerOperand();
 
   LoadInst *MemLoad = nullptr;
@@ -311,40 +307,6 @@ Value *ScopBuilder::findFADGlobalAlloc(M
   return Descriptor;
 }
 
-Value *ScopBuilder::findFADLocalNonAlloc(MemAccInst Inst) {
-  // match: 3
-  if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst))
-    return nullptr;
-
-  // match: 3
-  if (Inst.getAlignment() != 8)
-    return nullptr;
-
-  Value *Slot = Inst.getPointerOperand();
-
-  BitCastOperator *MemBitcast = nullptr;
-  // [match: 2]
-  if (auto *SlotGEP = dyn_cast<GetElementPtrInst>(Slot)) {
-    // match: 1
-    MemBitcast = dyn_cast<BitCastOperator>(SlotGEP->getPointerOperand());
-  } else {
-    // match: 1
-    MemBitcast = dyn_cast<BitCastOperator>(Slot);
-  }
-
-  if (!MemBitcast)
-    return nullptr;
-
-  Value *Descriptor = dyn_cast<Value>(MemBitcast->getOperand(0));
-  if (!Descriptor)
-    return nullptr;
-
-  if (!isFortranArrayDescriptor(Descriptor))
-    return nullptr;
-
-  return Descriptor;
-}
-
 bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) {
   Value *Val = Inst.getValueOperand();
   Type *ElementType = Val->getType();
@@ -771,11 +733,9 @@ void ScopBuilder::addArrayAccess(
   if (!DetectFortranArrays)
     return;
 
-  if (Value *FAD = findFADGlobalNonAlloc(MemAccInst))
-    MemAccess->setFortranArrayDescriptor(FAD);
-  else if (Value *FAD = findFADGlobalAlloc(MemAccInst))
+  if (Value *FAD = findFADAllocationInvisible(MemAccInst))
     MemAccess->setFortranArrayDescriptor(FAD);
-  else if (Value *FAD = findFADLocalNonAlloc(MemAccInst))
+  else if (Value *FAD = findFADAllocationVisible(MemAccInst))
     MemAccess->setFortranArrayDescriptor(FAD);
 }
 

Modified: polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll?rev=303356&r1=303355&r2=303356&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll (original)
+++ polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll Thu May 18 11:47:13 2017
@@ -52,6 +52,7 @@ entry.split:
   %tmp10 = mul i64 %tmp3, %tmp9
   %tmp11 = sub i64 %tmp10, %tmp3
   %tmp12 = getelementptr i32, i32* %tmp5, i64 %tmp11
+  ; store
   store i32 1, i32* %tmp12, align 4
   %tmp13 = icmp eq i32 %tmp8, %tmp6
   %tmp14 = add i32 %tmp8, 1
@@ -64,4 +65,4 @@ return:
   ret void
 }
 
-; CHECK: ReadAccess :=  [Reduction Type: NONE] [Fortran array descriptor: xs] [Scalar: 0]
+; CHECK: MayWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: xs] [Scalar: 0]
\ No newline at end of file

Added: polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll?rev=303356&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll (added)
+++ polly/trunk/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll Thu May 18 11:47:13 2017
@@ -0,0 +1,93 @@
+; RUN: opt %loadPolly -analyze -polly-detect-fortran-arrays \
+; RUN: -polly-scops -polly-allow-nonaffine -polly-ignore-aliasing < %s | FileCheck %s
+
+; PROGRAM main
+; ...
+; CONTAINS
+;     SUBROUTINE copy(xs, ys, n)
+;         IMPLICIT NONE
+;         INTEGER, DIMENSION(:), INTENT(INOUT) :: xs, ys
+;         INTEGER, INTENT(IN) :: n
+;         INTEGER :: i
+; 
+;         DO i = 1, n
+;             ys(i * i) = xs(i * i)
+;         END DO
+; 
+;     END SUBROUTINE copy
+; END PROGRAM
+
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
+
+%"struct.array1_integer(kind=4)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
+%struct.descriptor_dimension = type { i64, i64, i64 }
+%"struct.array1_integer(kind=4).0" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
+%"struct.array1_integer(kind=4).1" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
+%"struct.array1_integer(kind=4).2" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
+%struct.__st_parameter_dt = type { %struct.__st_parameter_common, i64, i64*, i64*, i8*, i8*, i32, i32, i8*, i8*, i32, i32, i8*, [256 x i8], i32*, i64, i8*, i32, i32, i8*, i8*, i32, i32, i8*, i8*, i32, i32, i8*, i8*, i32, [4 x i8] }
+%struct.__st_parameter_common = type { i32, i32, i8*, i32, i32, i8*, i32* }
+%"struct.array1_integer(kind=4).3" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
+
+ at 0 = internal constant i32 10
+ at .cst = private constant [12 x i8] c"program.f90\00", align 8
+ at options.12.1603 = internal constant [8 x i32] [i32 68, i32 511, i32 0, i32 0, i32 0, i32 1, i32 0, i32 1], align 32
+
+; Function Attrs: nounwind uwtable
+define internal void @copy.1550(%"struct.array1_integer(kind=4)"* noalias %xs, %"struct.array1_integer(kind=4).0"* noalias %ys, i32* noalias %n) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  %0 = getelementptr inbounds %"struct.array1_integer(kind=4).0", %"struct.array1_integer(kind=4).0"* %ys, i64 0, i32 3, i64 0, i32 0
+  %1 = load i64, i64* %0, align 8
+  %2 = icmp eq i64 %1, 0
+  %3 = select i1 %2, i64 1, i64 %1
+  %4 = bitcast %"struct.array1_integer(kind=4).0"* %ys to i32**
+  %5 = load i32*, i32** %4, align 8
+  %6 = getelementptr inbounds %"struct.array1_integer(kind=4)", %"struct.array1_integer(kind=4)"* %xs, i64 0, i32 3, i64 0, i32 0
+  %7 = load i64, i64* %6, align 8
+  %8 = icmp eq i64 %7, 0
+  %. = select i1 %8, i64 1, i64 %7
+  %9 = bitcast %"struct.array1_integer(kind=4)"* %xs to i32**
+  %10 = load i32*, i32** %9, align 8
+  %11 = load i32, i32* %n, align 4
+  %12 = icmp sgt i32 %11, 0
+  br i1 %12, label %"9.preheader", label %return
+
+"9.preheader":                                    ; preds = %entry.split
+  br label %"9"
+
+"9":                                              ; preds = %"9.preheader", %"9"
+  %13 = phi i32 [ %26, %"9" ], [ 1, %"9.preheader" ]
+  %14 = mul i32 %13, %13
+  %15 = sext i32 %14 to i64
+  %16 = mul i64 %3, %15
+  %17 = sub i64 %16, %3
+  %18 = mul i32 %13, %13
+  %19 = sext i32 %18 to i64
+  %20 = mul i64 %., %19
+  %21 = sub i64 %20, %.
+  %22 = getelementptr i32, i32* %10, i64 %21
+  ; load
+  %23 = load i32, i32* %22, align 4
+  %24 = getelementptr i32, i32* %5, i64 %17
+  ; write
+  store i32 %23, i32* %24, align 4
+  %25 = icmp eq i32 %13, %11
+  %26 = add i32 %13, 1
+  br i1 %25, label %return.loopexit, label %"9"
+
+return.loopexit:                                  ; preds = %"9"
+  br label %return
+
+return:                                           ; preds = %return.loopexit, %entry.split
+  ret void
+}
+
+; CHECK:      ReadAccess :=	[Reduction Type: NONE] [Fortran array descriptor: xs] [Scalar: 0]
+; CHECK-NEXT:     [p_0_loaded_from_n] -> { Stmt_9[i0] -> MemRef0[o0] };
+; CHECK-NEXT: MayWriteAccess :=	[Reduction Type: NONE] [Fortran array descriptor: ys] [Scalar: 0]
+; CHECK-NEXT:     [p_0_loaded_from_n] -> { Stmt_9[i0] -> MemRef1[o0] };




More information about the llvm-commits mailing list