1; RUN: opt -loop-load-elim -S < %s | \ 2; RUN: FileCheck %s -check-prefix=ALL -check-prefix=ONE_STRIDE_SPEC \ 3; RUN: -check-prefix=TWO_STRIDE_SPEC 4 5; RUN: opt -loop-load-elim -S -enable-mem-access-versioning=0 < %s | \ 6; RUN: FileCheck %s -check-prefix=ALL -check-prefix=NO_ONE_STRIDE_SPEC \ 7; RUN: -check-prefix=NO_TWO_STRIDE_SPEC 8 9; RUN: opt -loop-load-elim -S -loop-load-elimination-scev-check-threshold=1 < %s | \ 10; RUN: FileCheck %s -check-prefix=ALL -check-prefix=ONE_STRIDE_SPEC \ 11; RUN: -check-prefix=NO_TWO_STRIDE_SPEC 12 13; Forwarding in the presence of symbolic strides: 14; 15; for (unsigned i = 0; i < 100; i++) 16; A[i + 1] = A[Stride * i] + B[i]; 17 18target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 19 20; ALL-LABEL: @f( 21define void @f(i32* noalias nocapture %A, i32* noalias nocapture readonly %B, i64 %N, 22 i64 %stride) { 23 24; ONE_STRIDE_SPEC: %ident.check = icmp ne i64 %stride, 1 25 26entry: 27; NO_ONE_STRIDE_SPEC-NOT: %load_initial = load i32, i32* %A 28; ONE_STRIDE_SPEC: %load_initial = load i32, i32* %A 29 br label %for.body 30 31for.body: ; preds = %for.body, %entry 32; NO_ONE_STRIDE_SPEC-NOT: %store_forwarded = phi i32 [ %load_initial, {{.*}} ], [ %add, %for.body ] 33; ONE_STRIDE_SPEC: %store_forwarded = phi i32 [ %load_initial, {{.*}} ], [ %add, %for.body ] 34 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 35 %mul = mul i64 %indvars.iv, %stride 36 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %mul 37 %load = load i32, i32* %arrayidx, align 4 38 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv 39 %load_1 = load i32, i32* %arrayidx2, align 4 40; NO_ONE_STRIDE_SPEC-NOT: %add = add i32 %load_1, %store_forwarded 41; ONE_STRIDE_SPEC: %add = add i32 %load_1, %store_forwarded 42 %add = add i32 %load_1, %load 43 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 44 %arrayidx_next = getelementptr inbounds i32, i32* %A, i64 %indvars.iv.next 45 store i32 %add, i32* %arrayidx_next, align 4 46 %exitcond = icmp eq i64 %indvars.iv.next, %N 47 br i1 %exitcond, label %for.end, label %for.body 48 49for.end: ; preds = %for.body 50 ret void 51} 52 53; With two symbolic strides: 54; 55; for (unsigned i = 0; i < 100; i++) 56; A[Stride2 * (i + 1)] = A[Stride1 * i] + B[i]; 57 58; ALL-LABEL: @two_strides( 59define void @two_strides(i32* noalias nocapture %A, i32* noalias nocapture readonly %B, i64 %N, 60 i64 %stride.1, i64 %stride.2) { 61 62; TWO_STRIDE_SPEC: %ident.check = icmp ne i64 %stride.2, 1 63; TWO_STRIDE_SPEC: %ident.check1 = icmp ne i64 %stride.1, 1 64; NO_TWO_STRIDE_SPEC-NOT: %ident.check{{.*}} = icmp ne i64 %stride{{.*}}, 1 65 66entry: 67; NO_TWO_STRIDE_SPEC-NOT: %load_initial = load i32, i32* %A 68; TWO_STRIDE_SPEC: %load_initial = load i32, i32* %A 69 br label %for.body 70 71for.body: ; preds = %for.body, %entry 72; NO_TWO_STRIDE_SPEC-NOT: %store_forwarded = phi i32 [ %load_initial, {{.*}} ], [ %add, %for.body ] 73; TWO_STRIDE_SPEC: %store_forwarded = phi i32 [ %load_initial, {{.*}} ], [ %add, %for.body ] 74 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 75 %mul = mul i64 %indvars.iv, %stride.1 76 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %mul 77 %load = load i32, i32* %arrayidx, align 4 78 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv 79 %load_1 = load i32, i32* %arrayidx2, align 4 80; NO_TWO_STRIDE_SPEC-NOT: %add = add i32 %load_1, %store_forwarded 81; TWO_STRIDE_SPEC: %add = add i32 %load_1, %store_forwarded 82 %add = add i32 %load_1, %load 83 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 84 %mul.2 = mul i64 %indvars.iv.next, %stride.2 85 %arrayidx_next = getelementptr inbounds i32, i32* %A, i64 %mul.2 86 store i32 %add, i32* %arrayidx_next, align 4 87 %exitcond = icmp eq i64 %indvars.iv.next, %N 88 br i1 %exitcond, label %for.end, label %for.body 89 90for.end: ; preds = %for.body 91 ret void 92} 93