1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
; Analyze this loop:
; for (i = 0; i < n; i++)
; A[i + 1] = A[i] * B[i] * C[i];
; In this case, runtime checks are needed, and there is a convergent operation.
define void @rtchecks_needed(ptr %a, ptr %b, ptr %c) {
; CHECK-LABEL: 'rtchecks_needed'
; CHECK-NEXT: for.body:
; CHECK-NEXT: Has convergent operation in loop
; CHECK-NEXT: Report: cannot add control dependency to convergent operation
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadA = load i16, ptr %arrayidxA, align 2 ->
; CHECK-NEXT: store i16 %mul1, ptr %arrayidxA_plus_2, align 2
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
; CHECK-NEXT: Against group GRP1:
; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, ptr %b, i64 %storemerge3
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %storemerge3
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: %a High: (42 + %a))
; CHECK-NEXT: Member: {%a,+,2}<nuw><%for.body>
; CHECK-NEXT: Member: {(2 + %a),+,2}<nw><%for.body>
; CHECK-NEXT: Group GRP1:
; CHECK-NEXT: (Low: %b High: (40 + %b))
; CHECK-NEXT: Member: {%b,+,2}<nuw><%for.body>
; CHECK-NEXT: Group GRP2:
; CHECK-NEXT: (Low: %c High: (40 + %c))
; CHECK-NEXT: Member: {%c,+,2}<nuw><%for.body>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %for.body
for.body: ; preds = %for.body, %entry
%storemerge3 = phi i64 [ 0, %entry ], [ %add, %for.body ]
%arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
%loadA = load i16, ptr %arrayidxA, align 2
%arrayidxB = getelementptr inbounds i16, ptr %b, i64 %storemerge3
%loadB = load i16, ptr %arrayidxB, align 2
%arrayidxC = getelementptr inbounds i16, ptr %c, i64 %storemerge3
%loadC = load i16, ptr %arrayidxC, align 2
call i16 @llvm.convergent(i16 %loadC)
%mul = mul i16 %loadB, %loadA
%mul1 = mul i16 %mul, %loadC
%add = add nuw nsw i64 %storemerge3, 1
%arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
store i16 %mul1, ptr %arrayidxA_plus_2, align 2
%exitcond = icmp eq i64 %add, 20
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
ret void
}
; In this case, no runtime checks are needed, and there is a convergent operation.
define void @no_rtchecks(ptr noalias %a, ptr noalias %b, ptr noalias %c, ptr noalias %d, ptr noalias %e) {
; CHECK-LABEL: 'no_rtchecks'
; CHECK-NEXT: for.body:
; CHECK-NEXT: Has convergent operation in loop
; CHECK-NEXT: Report: cannot add control dependency to convergent operation
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadA = load i16, ptr %arrayidxA, align 4 ->
; CHECK-NEXT: store i16 %mulA, ptr %arrayidxA_plus_4, align 4
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Grouped accesses:
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %for.body
for.body: ; preds = %for.body, %entry
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
%arrayidxA = getelementptr inbounds i16, ptr %a, i64 %ind
%loadA = load i16, ptr %arrayidxA, align 4
%arrayidxB = getelementptr inbounds i16, ptr %b, i64 %ind
%loadB = load i16, ptr %arrayidxB, align 4
%mulA = mul i16 %loadB, %loadA
%add = add nuw nsw i64 %ind, 1
%arrayidxA_plus_4 = getelementptr inbounds i16, ptr %a, i64 %add
store i16 %mulA, ptr %arrayidxA_plus_4, align 4
%arrayidxD = getelementptr inbounds i16, ptr %d, i64 %ind
%loadD = load i16, ptr %arrayidxD, align 4
%arrayidxE = getelementptr inbounds i16, ptr %e, i64 %ind
%loadE = load i16, ptr %arrayidxE, align 4
%convergentD = call i16 @llvm.convergent(i16 %loadD)
%mulC = mul i16 %convergentD, %loadE
%arrayidxC = getelementptr inbounds i16, ptr %c, i64 %ind
store i16 %mulC, ptr %arrayidxC, align 4
%exitcond = icmp eq i64 %add, 20
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
ret void
}
declare i16 @llvm.convergent(i16) #0
attributes #0 = { nounwind readnone convergent }
|