[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