forked from OSchip/llvm-project
103 lines
5.0 KiB
LLVM
103 lines
5.0 KiB
LLVM
; RUN: opt %loadPolly -analyze -polly-scops \
|
|
; RUN: -polly-detect-fortran-arrays \
|
|
; RUN: -polly-invariant-load-hoisting \
|
|
; RUN: -polly-use-llvm-names \
|
|
; RUN: < %s | FileCheck %s --check-prefix=SCOP
|
|
|
|
; RUN: opt %loadPolly -S \
|
|
; RUN: -polly-detect-fortran-arrays \
|
|
; RUN: -polly-codegen-ppcg \
|
|
; RUN: -polly-invariant-load-hoisting \
|
|
; RUN: -polly-use-llvm-names \
|
|
; RUN: -polly-acc-fail-on-verify-module-failure \
|
|
; RUN: < %s | FileCheck %s --check-prefix=HOST-IR
|
|
|
|
; REQUIRES: pollyacc
|
|
|
|
; In Polly, we specifically add a parameter to represent the outermost dimension
|
|
; size of fortran arrays. We do this because this information is statically
|
|
; available from the fortran metadata generated by dragonegg.
|
|
; However, we were only materializing these parameters (meaning, creating an
|
|
; llvm::Value to back the isl_id) from *memory accesses*. This is wrong,
|
|
; we should materialize parameters from *scop array info*.
|
|
|
|
; It is wrong because if there is a case where we detect 2 fortran arrays,
|
|
; but only one of them is accessed, we may not materialize the other array's
|
|
; dimensions at all.
|
|
|
|
; This test case checks that we do not fail if there is an array that does
|
|
; not have an access (In this case, `memory`), we still generate the
|
|
; parameter.
|
|
|
|
; Check that we detect the function as a Scop.
|
|
; SCOP: Function: f
|
|
; SCOP-NEXT: Region: %loop.prepare---%for.exit
|
|
; SCOP-NEXT: Max Loop Depth: 1
|
|
|
|
; Check that we detect fortran arrays.
|
|
; SCOP: Arrays (Bounds as pw_affs) {
|
|
; SCOP: double* MemRef_global_arr[*]; // Element size 8
|
|
; SCOP-NEXT: double MemRef_memory[ [MemRef_memory_fortranarr_size] -> { [] -> [(MemRef_memory_fortranarr_size)] } ]; [BasePtrOrigin: MemRef_global_arr] // Element size 8
|
|
; SCOP-NEXT: double MemRef_memory2[ [MemRef_memory2_fortranarr_size] -> { [] -> [(MemRef_memory2_fortranarr_size)] } ]; [BasePtrOrigin: MemRef_global_arr] // Element size 8
|
|
; SCOP-NEXT: }
|
|
|
|
; Check that we have writes *only* into memory2, not into memory.
|
|
; SCOP: Statements {
|
|
; SCOP: Stmt_for_body
|
|
; SCOP: MustWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: global_arr] [Scalar: 0]
|
|
; SCOP-NEXT: [start_val, end_val, offset, MemRef_memory_fortranarr_size, MemRef_memory2_fortranarr_size] -> { Stmt_for_body[i0] -> MemRef_memory2[start_val + offset + i0] };
|
|
; SCOP-NEXT: ReadAccess := [Reduction Type: NONE] [Fortran array descriptor: global_arr] [Scalar: 0]
|
|
; SCOP-NEXT: [start_val, end_val, offset, MemRef_memory_fortranarr_size, MemRef_memory2_fortranarr_size] -> { Stmt_for_body[i0] -> MemRef_memory2[start_val + offset + i0] };
|
|
; SCOP-NEXT: }
|
|
|
|
; Check that we materialize the sizes and send it across to the kernel.
|
|
; HOST-IR: store i64 %MemRef_memory_size, i64* %polly_launch_0_param_4
|
|
; HOST-IR: store i64 %MemRef_memory2_size, i64* %polly_launch_0_param_5
|
|
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_real(kind=8)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
|
|
%struct.descriptor_dimension = type { i64, i64, i64 }
|
|
|
|
@global_arr = external unnamed_addr global %"struct.array1_real(kind=8)", align 32
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
define void @f(i32* noalias %ipstart, i32* noalias %ipend) unnamed_addr #0 {
|
|
entry:
|
|
br label %loop.prepare
|
|
|
|
|
|
loop.prepare: ; preds = %"6", %"3.preheader"
|
|
%start.val = load i32, i32* %ipstart, align 4
|
|
%end.val = load i32, i32* %ipend, align 4
|
|
%should.loop = icmp sgt i32 %start.val, %end.val
|
|
br i1 %should.loop, label %for.exit, label %for.body
|
|
|
|
|
|
for.body: ; preds = %for.body, %"4.preheader"
|
|
%i = phi i32 [ %i.next, %for.body ], [ %start.val, %loop.prepare ]
|
|
%i.sext = sext i32 %i to i64
|
|
%memory = load double*, double** bitcast (%"struct.array1_real(kind=8)"* @global_arr to double**), align 32
|
|
%offset = load i64, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @global_arr, i64 0, i32 1), align 8
|
|
%idx = add i64 %offset, %i.sext
|
|
%slot = getelementptr double, double* %memory, i64 %idx
|
|
store double 1.0, double* %slot, align 8
|
|
|
|
%memory2 = load double*, double** bitcast (%"struct.array1_real(kind=8)"* @global_arr to double**), align 32
|
|
%offset2 = load i64, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @global_arr, i64 0, i32 1), align 8
|
|
%idx2 = add i64 %offset2, %i.sext
|
|
%slot2 = getelementptr double, double* %memory2, i64 %idx2
|
|
%val = load double, double* %slot2, align 8
|
|
|
|
%should.loopexit = icmp eq i32 %i, %end.val
|
|
%i.next = add i32 %i, 1
|
|
br i1 %should.loopexit, label %for.exit, label %for.body
|
|
|
|
for.exit: ; preds = %for.body
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { nounwind uwtable }
|