1; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-flatten-schedule -polly-delicm -analyze < %s | FileCheck %s 2; 3; Use %phi instead of the normal %add; that is, the last last iteration will 4; be ignored such the %phi cannot be written to A[3] in %body. 5; 6; void func(double *A) { 7; for (int j = 0; j < 2; j += 1) { /* outer */ 8; double phi; 9; double incoming = A[j]; 10; for (int i = 0; i < 4; i += 1) { /* reduction */ 11; phi = incoming; 12; add = phi + 4.2; 13; incoming = add; 14; } 15; A[j] = phi; 16; } 17; } 18; 19define void @func(double* noalias nonnull %A) { 20entry: 21 br label %outer.preheader 22 23outer.preheader: 24 br label %outer.for 25 26outer.for: 27 %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] 28 %j.cmp = icmp slt i32 %j, 2 29 br i1 %j.cmp, label %reduction.preheader, label %outer.exit 30 31 32 reduction.preheader: 33 %A_idx = getelementptr inbounds double, double* %A, i32 %j 34 %init = load double, double* %A_idx 35 br label %reduction.for 36 37 reduction.for: 38 %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] 39 %phi = phi double [%init, %reduction.preheader], [%add, %reduction.inc] 40 br label %body 41 42 43 44 body: 45 %add = fadd double %phi, 4.2 46 br label %reduction.inc 47 48 49 50 reduction.inc: 51 %i.inc = add nuw nsw i32 %i, 1 52 %i.cmp = icmp slt i32 %i.inc, 4 53 br i1 %i.cmp, label %reduction.for, label %reduction.exit 54 55 reduction.exit: 56 store double %phi, double* %A_idx 57 br label %outer.inc 58 59 60 61outer.inc: 62 %j.inc = add nuw nsw i32 %j, 1 63 br label %outer.for 64 65outer.exit: 66 br label %return 67 68return: 69 ret void 70} 71 72 73; CHECK: Statistics { 74; CHECK: Compatible overwrites: 1 75; CHECK: Overwrites mapped to: 1 76; CHECK: Value scalars mapped: 1 77; CHECK: PHI scalars mapped: 1 78; CHECK: } 79 80; CHECK: After accesses { 81; CHECK-NEXT: Stmt_reduction_preheader 82; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] 83; CHECK-NEXT: { Stmt_reduction_preheader[i0] -> MemRef_A[i0] }; 84; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] 85; CHECK-NEXT: { Stmt_reduction_preheader[i0] -> MemRef_phi__phi[] }; 86; CHECK-NEXT: new: { Stmt_reduction_preheader[i0] -> MemRef_A[i0] }; 87; CHECK-NEXT: Stmt_reduction_for 88; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] 89; CHECK-NEXT: { Stmt_reduction_for[i0, i1] -> MemRef_phi__phi[] }; 90; CHECK-NEXT: new: { Stmt_reduction_for[i0, i1] -> MemRef_A[i0] }; 91; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] 92; CHECK-NEXT: { Stmt_reduction_for[i0, i1] -> MemRef_phi[] }; 93; CHECK-NEXT: new: { Stmt_reduction_for[i0, i1] -> MemRef_A[i0] }; 94; CHECK-NEXT: Stmt_body 95; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] 96; CHECK-NEXT: { Stmt_body[i0, i1] -> MemRef_add[] }; 97; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] 98; CHECK-NEXT: { Stmt_body[i0, i1] -> MemRef_phi[] }; 99; CHECK-NEXT: new: { Stmt_body[i0, i1] -> MemRef_A[i0] : 3i1 <= 22 - 14i0; Stmt_body[1, 3] -> MemRef_A[1] }; 100; CHECK-NEXT: Stmt_reduction_inc 101; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] 102; CHECK-NEXT: { Stmt_reduction_inc[i0, i1] -> MemRef_add[] }; 103; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] 104; CHECK-NEXT: { Stmt_reduction_inc[i0, i1] -> MemRef_phi__phi[] }; 105; CHECK-NEXT: new: { Stmt_reduction_inc[i0, i1] -> MemRef_A[i0] : i1 <= 2 }; 106; CHECK-NEXT: Stmt_reduction_exit 107; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] 108; CHECK-NEXT: { Stmt_reduction_exit[i0] -> MemRef_A[i0] }; 109; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] 110; CHECK-NEXT: { Stmt_reduction_exit[i0] -> MemRef_phi[] }; 111; CHECK-NEXT: new: { Stmt_reduction_exit[i0] -> MemRef_A[i0] }; 112; CHECK-NEXT: } 113