diff options
4 files changed, 120 insertions, 83 deletions
diff --git a/polly/include/polly/ScopBuilder.h b/polly/include/polly/ScopBuilder.h index c4e9686d969..e7a7cf7282e 100644 --- a/polly/include/polly/ScopBuilder.h +++ b/polly/include/polly/ScopBuilder.h @@ -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. diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp index bfb3af2844b..b7c9c6599ef 100644 --- a/polly/lib/Analysis/ScopBuilder.cpp +++ b/polly/lib/Analysis/ScopBuilder.cpp @@ -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::findFADGlobalNonAlloc(MemAccInst Inst) { 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(MemAccInst Inst) { 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); } diff --git a/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll b/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll index 59e6c7d25e2..b0c34f536f8 100644 --- a/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll +++ b/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored.ll @@ -52,6 +52,7 @@ entry.split: ; preds = %entry %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: ; preds = %return.loopexit, %e 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 diff --git a/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll b/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll new file mode 100644 index 00000000000..f291d1d2152 --- /dev/null +++ b/polly/test/ScopInfo/fortran_array_param_nonmalloc_nonvectored_read_and_write.ll @@ -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] } + +@0 = internal constant i32 10 +@.cst = private constant [12 x i8] c"program.f90\00", align 8 +@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] }; |