1; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s 3 4target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 5 6declare void @llvm.assume(i1) 7 8declare void @use(ptr noundef) 9 10; %offset is known positive via assume, so we should be able to detect the 11; forward dependence. 12define void @offset_i8_known_positive_via_assume_forward_dep_1(ptr %A, i64 %offset, i64 %N) { 13; CHECK-LABEL: 'offset_i8_known_positive_via_assume_forward_dep_1' 14; CHECK-NEXT: loop: 15; CHECK-NEXT: Memory dependences are safe 16; CHECK-NEXT: Dependences: 17; CHECK-NEXT: Forward: 18; CHECK-NEXT: %l = load i8, ptr %gep.off, align 4 -> 19; CHECK-NEXT: store i8 %add, ptr %gep, align 4 20; CHECK-EMPTY: 21; CHECK-NEXT: Run-time memory checks: 22; CHECK-NEXT: Grouped accesses: 23; CHECK-EMPTY: 24; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 25; CHECK-NEXT: SCEV assumptions: 26; CHECK-EMPTY: 27; CHECK-NEXT: Expressions re-written: 28; 29entry: 30 %c = icmp sgt i64 %offset, 0 31 call void @llvm.assume(i1 %c) 32 %off = getelementptr inbounds i8, ptr %A, i64 %offset 33 call void @use(ptr noundef %off) 34 br label %loop 35 36loop: 37 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 38 %gep.off = getelementptr inbounds i8, ptr %off, i64 %iv 39 %l = load i8 , ptr %gep.off, align 4 40 %add = add nsw i8 %l, 5 41 %gep = getelementptr inbounds i8, ptr %A, i64 %iv 42 store i8 %add, ptr %gep, align 4 43 %iv.next = add nuw nsw i64 %iv, 1 44 %exitcond.not = icmp eq i64 %iv.next, %N 45 br i1 %exitcond.not, label %exit, label %loop 46 47exit: 48 ret void 49} 50 51define void @offset_i32_known_positive_via_assume_forward_dep_1(ptr %A, i64 %offset, i64 %N) { 52; CHECK-LABEL: 'offset_i32_known_positive_via_assume_forward_dep_1' 53; CHECK-NEXT: loop: 54; CHECK-NEXT: Memory dependences are safe with run-time checks 55; CHECK-NEXT: Dependences: 56; CHECK-NEXT: Run-time memory checks: 57; CHECK-NEXT: Check 0: 58; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]): 59; CHECK-NEXT: %gep = getelementptr inbounds i32, ptr %A, i64 %iv 60; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]): 61; CHECK-NEXT: %gep.off = getelementptr inbounds i32, ptr %off, i64 %iv 62; CHECK-NEXT: Grouped accesses: 63; CHECK-NEXT: Group [[GRP1]]: 64; CHECK-NEXT: (Low: %A High: (-3 + (4 * %N) + %A)) 65; CHECK-NEXT: Member: {%A,+,4}<nuw><%loop> 66; CHECK-NEXT: Group [[GRP2]]: 67; CHECK-NEXT: (Low: ((4 * %offset)<nsw> + %A) High: (-3 + (4 * %offset)<nsw> + (4 * %N) + %A)) 68; CHECK-NEXT: Member: {((4 * %offset)<nsw> + %A),+,4}<nw><%loop> 69; CHECK-EMPTY: 70; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 71; CHECK-NEXT: SCEV assumptions: 72; CHECK-EMPTY: 73; CHECK-NEXT: Expressions re-written: 74; 75entry: 76 %c = icmp sgt i64 %offset, 0 77 call void @llvm.assume(i1 %c) 78 %off = getelementptr inbounds i32, ptr %A, i64 %offset 79 call void @use(ptr noundef %off) 80 81 br label %loop 82 83loop: 84 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 85 %gep.off = getelementptr inbounds i32, ptr %off, i64 %iv 86 %l = load i8 , ptr %gep.off, align 4 87 %add = add nsw i8 %l, 5 88 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 89 store i8 %add, ptr %gep, align 4 90 %iv.next = add nuw nsw i64 %iv, 1 91 %exitcond.not = icmp eq i64 %iv.next, %N 92 br i1 %exitcond.not, label %exit, label %loop 93 94exit: 95 ret void 96} 97 98; %offset is known positive via assume, so we should be able to detect the 99; forward dependence. 100define void @offset_known_positive_via_assume_forward_dep_2(ptr %A, i64 %offset, i64 %N) { 101; CHECK-LABEL: 'offset_known_positive_via_assume_forward_dep_2' 102; CHECK-NEXT: loop: 103; CHECK-NEXT: Memory dependences are safe 104; CHECK-NEXT: Dependences: 105; CHECK-NEXT: Forward: 106; CHECK-NEXT: %l = load i32, ptr %gep.off, align 4 -> 107; CHECK-NEXT: store i32 %add, ptr %gep, align 4 108; CHECK-EMPTY: 109; CHECK-NEXT: Run-time memory checks: 110; CHECK-NEXT: Grouped accesses: 111; CHECK-EMPTY: 112; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 113; CHECK-NEXT: SCEV assumptions: 114; CHECK-EMPTY: 115; CHECK-NEXT: Expressions re-written: 116; 117entry: 118 %c = icmp sgt i64 %offset, 0 119 call void @llvm.assume(i1 %c) 120 %c.2 = icmp slt i64 %offset, 20 121 call void @llvm.assume(i1 %c.2) 122 %off = getelementptr inbounds i32, ptr %A, i64 %offset 123 br label %loop 124 125loop: 126 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 127 %gep.off = getelementptr inbounds i32, ptr %off, i64 %iv 128 %l = load i32, ptr %gep.off, align 4 129 %add = add nsw i32 %l, 5 130 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 131 store i32 %add, ptr %gep, align 4 132 %iv.next = add nuw nsw i64 %iv, 1 133 %exitcond.not = icmp eq i64 %iv.next, %N 134 br i1 %exitcond.not, label %exit, label %loop 135 136exit: 137 ret void 138} 139 140; The range of %offset is known via assumes, but it may be positive or negative. 141define void @offset_may_be_negative_via_assume_unknown_dep(ptr %A, i64 %offset, i64 %N) { 142; CHECK-LABEL: 'offset_may_be_negative_via_assume_unknown_dep' 143; CHECK-NEXT: loop: 144; CHECK-NEXT: Memory dependences are safe with run-time checks 145; CHECK-NEXT: Dependences: 146; CHECK-NEXT: Run-time memory checks: 147; CHECK-NEXT: Check 0: 148; CHECK-NEXT: Comparing group ([[GRP3:0x[0-9a-f]+]]): 149; CHECK-NEXT: %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv 150; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]): 151; CHECK-NEXT: %gep = getelementptr inbounds i32, ptr %off, i64 %iv 152; CHECK-NEXT: Grouped accesses: 153; CHECK-NEXT: Group [[GRP3]]: 154; CHECK-NEXT: (Low: %A High: ((4 * %N) + %A)) 155; CHECK-NEXT: Member: {%A,+,4}<nuw><%loop> 156; CHECK-NEXT: Group [[GRP4]]: 157; CHECK-NEXT: (Low: ((4 * %offset)<nsw> + %A) High: ((4 * %offset)<nsw> + (4 * %N) + %A)) 158; CHECK-NEXT: Member: {((4 * %offset)<nsw> + %A),+,4}<nw><%loop> 159; CHECK-EMPTY: 160; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 161; CHECK-NEXT: SCEV assumptions: 162; CHECK-EMPTY: 163; CHECK-NEXT: Expressions re-written: 164; 165entry: 166 %c = icmp sgt i64 %offset, -4 167 call void @llvm.assume(i1 %c) 168 %c.2 = icmp slt i64 %offset, 20 169 call void @llvm.assume(i1 %c.2) 170 %off = getelementptr inbounds i32, ptr %A, i64 %offset 171 br label %loop 172 173loop: 174 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 175 %gep = getelementptr inbounds i32, ptr %off, i64 %iv 176 %l = load i32, ptr %gep, align 4 177 %add = add nsw i32 %l, 5 178 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv 179 store i32 %add, ptr %gep.mul.2, align 4 180 %iv.next = add nuw nsw i64 %iv, 1 181 %exitcond.not = icmp eq i64 %iv.next, %N 182 br i1 %exitcond.not, label %exit, label %loop 183 184exit: 185 ret void 186} 187 188define void @offset_no_assumes(ptr %A, i64 %offset, i64 %N) { 189; CHECK-LABEL: 'offset_no_assumes' 190; CHECK-NEXT: loop: 191; CHECK-NEXT: Memory dependences are safe with run-time checks 192; CHECK-NEXT: Dependences: 193; CHECK-NEXT: Run-time memory checks: 194; CHECK-NEXT: Check 0: 195; CHECK-NEXT: Comparing group ([[GRP5:0x[0-9a-f]+]]): 196; CHECK-NEXT: %gep = getelementptr inbounds i32, ptr %A, i64 %iv 197; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]): 198; CHECK-NEXT: %gep.off = getelementptr inbounds i32, ptr %off, i64 %iv 199; CHECK-NEXT: Grouped accesses: 200; CHECK-NEXT: Group [[GRP5]]: 201; CHECK-NEXT: (Low: %A High: ((4 * %N) + %A)) 202; CHECK-NEXT: Member: {%A,+,4}<nuw><%loop> 203; CHECK-NEXT: Group [[GRP6]]: 204; CHECK-NEXT: (Low: ((4 * %offset)<nsw> + %A) High: ((4 * %offset)<nsw> + (4 * %N) + %A)) 205; CHECK-NEXT: Member: {((4 * %offset)<nsw> + %A),+,4}<nw><%loop> 206; CHECK-EMPTY: 207; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 208; CHECK-NEXT: SCEV assumptions: 209; CHECK-EMPTY: 210; CHECK-NEXT: Expressions re-written: 211; 212entry: 213 %off = getelementptr inbounds i32, ptr %A, i64 %offset 214 br label %loop 215 216loop: 217 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 218 %gep.off = getelementptr inbounds i32, ptr %off, i64 %iv 219 %l = load i32, ptr %gep.off, align 4 220 %add = add nsw i32 %l, 5 221 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 222 store i32 %add, ptr %gep, align 4 223 %iv.next = add nuw nsw i64 %iv, 1 224 %exitcond.not = icmp eq i64 %iv.next, %N 225 br i1 %exitcond.not, label %exit, label %loop 226 227exit: 228 ret void 229} 230