; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes='print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:o-i64:64-p1:128:128-f80:128-n8:16:32:64-S128" ; for (i = 0; i < 1024; i++) ; A[i % 16] = A[i % 16] + 1; define void @load_store_same_clamped_i32(ptr %a) { ; CHECK-LABEL: 'load_store_same_clamped_i32' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep, 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-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep = getelementptr inbounds i32, ptr %a, i64 %idx: ; CHECK-NEXT: ((4 * (zext i4 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 16 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %lv = load i32, ptr %gep, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 8] = B[i]; define void @store_clamped_load_linear(ptr %a, ptr %b) { ; CHECK-LABEL: 'store_clamped_load_linear' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe with run-time checks ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Check 0: ; CHECK-NEXT: Comparing group GRP0: ; CHECK-NEXT: %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv ; CHECK-NEXT: Against group GRP1: ; CHECK-NEXT: %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx.mod ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %b High: (4096 + %b)) ; CHECK-NEXT: Member: {%b,+,4}<%loop> ; CHECK-NEXT: Group GRP1: ; CHECK-NEXT: (Low: %a High: (4096 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx.mod: ; CHECK-NEXT: ((4 * (zext i3 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx.mod = urem i64 %iv, 8 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv %lv = load i32, ptr %gep.b, align 4 %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx.mod store i32 %lv, ptr %gep.a, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 4] = i; define void @only_store_clamped(ptr %a) { ; CHECK-LABEL: 'only_store_clamped' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 4 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %val = trunc i64 %iv to i32 store i32 %val, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 8] = A[i % 8] + 1; define void @clamped_power_of_2(ptr %a) { ; CHECK-LABEL: 'clamped_power_of_2' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep, 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-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep = getelementptr inbounds i32, ptr %a, i64 %idx: ; CHECK-NEXT: ((4 * (zext i3 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 8 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %lv = load i32, ptr %gep, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 7] = A[i % 7] + 1; define void @clamped_non_power_of_2(ptr %a) { ; CHECK-LABEL: 'clamped_non_power_of_2' ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: IndirectUnsafe: ; CHECK-NEXT: %lv = load i32, ptr %gep, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep, 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 7 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %lv = load i32, ptr %gep, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) { ; A[i % 8] = x; ; A[i % 8] = y; ; } define void @two_stores_same_clamped(ptr %a, i32 %x, i32 %y) { ; CHECK-LABEL: 'two_stores_same_clamped' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 8 %gep = getelementptr inbounds i32, ptr %a, i64 %idx store i32 %x, ptr %gep, align 4 store i32 %y, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 8] = A[(i + 1) % 8]; define void @clamped_offset_load(ptr %a) { ; CHECK-LABEL: 'clamped_offset_load' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep.load, align 4 -> ; CHECK-NEXT: store i32 %lv, ptr %gep.store, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4100 + %a)) ; CHECK-NEXT: Member: {(4 + %a),+,4}<%loop> ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {1,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.load = getelementptr inbounds i32, ptr %a, i64 %idx.load: ; CHECK-NEXT: ((4 * (zext i3 {1,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {(4 + %a),+,4}<%loop> ; CHECK-NEXT: [PSE] %gep.store = getelementptr inbounds i32, ptr %a, i64 %idx.store: ; CHECK-NEXT: ((4 * (zext i3 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %iv.plus1 = add nuw nsw i64 %iv, 1 %idx.store = urem i64 %iv, 8 %idx.load = urem i64 %iv.plus1, 8 %gep.load = getelementptr inbounds i32, ptr %a, i64 %idx.load %lv = load i32, ptr %gep.load, align 4 %gep.store = getelementptr inbounds i32, ptr %a, i64 %idx.store store i32 %lv, ptr %gep.store, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 2] += 1; define void @clamped_small_bound(ptr %a) { ; CHECK-LABEL: 'clamped_small_bound' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep, 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-NEXT: {false,+,true}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep = getelementptr inbounds i32, ptr %a, i64 %idx: ; CHECK-NEXT: ((4 * (zext i1 {false,+,true}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,-4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 2 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %lv = load i32, ptr %gep, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; sum += A[i % 8]; define i32 @clamped_read_only(ptr noalias %a) { ; CHECK-LABEL: 'clamped_read_only' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop ] %idx = urem i64 %iv, 8 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %lv = load i32, ptr %gep, align 4 %sum.next = add i32 %sum, %lv %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret i32 %sum.next } ; for (i = 0; i < 1024; i++) ; A[i % 8] = A[i] + 1; define void @clamped_and_linear_same_array(ptr %a) { ; CHECK-LABEL: 'clamped_and_linear_same_array' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep.load, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep.store, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4096 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.store = getelementptr inbounds i32, ptr %a, i64 %idx.mod: ; CHECK-NEXT: ((4 * (zext i3 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx.mod = urem i64 %iv, 8 %gep.load = getelementptr inbounds i32, ptr %a, i64 %iv %lv = load i32, ptr %gep.load, align 4 %add = add i32 %lv, 1 %gep.store = getelementptr inbounds i32, ptr %a, i64 %idx.mod store i32 %add, ptr %gep.store, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 1] = i; define void @clamped_one(ptr %a) { ; CHECK-LABEL: 'clamped_one' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 1 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %val = trunc i64 %iv to i32 store i32 %val, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 4] = A[i % 8] + 1; define void @different_clamped_bounds_same_array(ptr %a) { ; CHECK-LABEL: 'different_clamped_bounds_same_array' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep.load, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep.store, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4096 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.load = getelementptr inbounds i32, ptr %a, i64 %idx.load: ; CHECK-NEXT: ((4 * (zext i3 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; CHECK-NEXT: [PSE] %gep.store = getelementptr inbounds i32, ptr %a, i64 %idx.store: ; CHECK-NEXT: ((4 * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx.load = urem i64 %iv, 8 %idx.store = urem i64 %iv, 4 %gep.load = getelementptr inbounds i32, ptr %a, i64 %idx.load %lv = load i32, ptr %gep.load, align 4 %add = add i32 %lv, 1 %gep.store = getelementptr inbounds i32, ptr %a, i64 %idx.store store i32 %add, ptr %gep.store, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[(2*i) % 8] = i; define void @clamped_non_unit_step(ptr %a) { ; CHECK-LABEL: 'clamped_non_unit_step' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %iv2 = shl i64 %iv, 1 %idx = urem i64 %iv2, 8 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %val = trunc i64 %iv to i32 store i32 %val, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 8] = i; // i8 type (1 byte) define void @clamped_i8_type(ptr %a) { ; CHECK-LABEL: 'clamped_i8_type' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 8 %gep = getelementptr inbounds i8, ptr %a, i64 %idx %val = trunc i64 %iv to i8 store i8 %val, ptr %gep, align 1 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 4] += 1; // i64 type (8 bytes) define void @clamped_i64_type(ptr %a) { ; CHECK-LABEL: 'clamped_i64_type' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i64, ptr %gep, align 8 -> ; CHECK-NEXT: store i64 %add, ptr %gep, align 8 ; 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-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep = getelementptr inbounds i64, ptr %a, i64 %idx: ; CHECK-NEXT: ((8 * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,8}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 4 %gep = getelementptr inbounds i64, ptr %a, i64 %idx %lv = load i64, ptr %gep, align 8 %add = add i64 %lv, 1 store i64 %add, ptr %gep, align 8 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < N; i++) ; A[i % C] = B[i]; define void @clamped_non_constant(ptr %a, ptr %b, i64 %c) { ; CHECK-LABEL: 'clamped_non_constant' ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: cannot identify array bounds ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, %c %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv %lv = load i32, ptr %gep.b, align 4 %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx store i32 %lv, ptr %gep.a, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; for (i = 0; i < 1024; i++) ; A[i % 16] = B[i % 16] + 1; define void @clamped_different_arrays_same_bound(ptr %a, ptr %b) { ; CHECK-LABEL: 'clamped_different_arrays_same_bound' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe with run-time checks ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Check 0: ; CHECK-NEXT: Comparing group GRP0: ; CHECK-NEXT: %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx ; CHECK-NEXT: Against group GRP1: ; CHECK-NEXT: %gep.b = getelementptr inbounds i32, ptr %b, i64 %idx ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4096 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Group GRP1: ; CHECK-NEXT: (Low: %b High: (4096 + %b)) ; CHECK-NEXT: Member: {%b,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.b = getelementptr inbounds i32, ptr %b, i64 %idx: ; CHECK-NEXT: ((4 * (zext i4 {0,+,1}<%loop> to i64)) + %b) ; CHECK-NEXT: --> {%b,+,4}<%loop> ; CHECK-NEXT: [PSE] %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx: ; CHECK-NEXT: ((4 * (zext i4 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 16 %gep.b = getelementptr inbounds i32, ptr %b, i64 %idx %lv = load i32, ptr %gep.b, align 4 %add = add i32 %lv, 1 %gep.a = getelementptr inbounds i32, ptr %a, i64 %idx store i32 %add, ptr %gep.a, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } ; Two stores with different modulo bounds to same array. ; for (i = 0; i < 1024; i++) { ; A[i % 4] = x; ; A[i % 8] = y; ; } define void @two_stores_different_clamped(ptr %a, i32 %x, i32 %y) { ; CHECK-LABEL: 'two_stores_different_clamped' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: store i32 %x, ptr %gep4, align 4 -> ; CHECK-NEXT: store i32 %y, ptr %gep8, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4096 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep4 = getelementptr inbounds i32, ptr %a, i64 %idx4: ; CHECK-NEXT: ((4 * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; CHECK-NEXT: [PSE] %gep8 = getelementptr inbounds i32, ptr %a, i64 %idx8: ; CHECK-NEXT: ((4 * (zext i3 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx4 = urem i64 %iv, 4 %idx8 = urem i64 %iv, 8 %gep4 = getelementptr inbounds i32, ptr %a, i64 %idx4 store i32 %x, ptr %gep4, align 4 %gep8 = getelementptr inbounds i32, ptr %a, i64 %idx8 store i32 %y, ptr %gep8, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @srem_not_matched_as_clamped(ptr %a) { ; CHECK-LABEL: 'srem_not_matched_as_clamped' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = srem i64 %iv, 8 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %val = trunc i64 %iv to i32 store i32 %val, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_multi_index_gep(ptr %a) { ; CHECK-LABEL: 'clamped_multi_index_gep' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; 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 %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 7 %gep = getelementptr inbounds [16 x i32], ptr %a, i64 0, i64 %idx %val = trunc i64 %iv to i32 store i32 %val, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_mod_256_narrow_cutoff(ptr %a) { ; CHECK-LABEL: 'clamped_mod_256_narrow_cutoff' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep, 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-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep = getelementptr inbounds i32, ptr %a, i64 %idx: ; CHECK-NEXT: ((4 * (zext i8 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 256 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %lv = load i32, ptr %gep, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_with_const_offset(ptr %a) { ; CHECK-LABEL: 'clamped_with_const_offset' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i32, ptr %gep.off, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep.off, 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-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.off = getelementptr inbounds i8, ptr %gep, i64 16: ; CHECK-NEXT: (16 + (4 * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {(16 + %a),+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 4 %gep = getelementptr inbounds i32, ptr %a, i64 %idx %gep.off = getelementptr inbounds i8, ptr %gep, i64 16 %lv = load i32, ptr %gep.off, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep.off, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_load_clamped_store_same(ptr %a) { ; CHECK-LABEL: 'clamped_load_clamped_store_same' ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Backward loop carried data dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: %lv = load i32, ptr %gep.l, align 4 -> ; CHECK-NEXT: store i32 %add, ptr %gep.s, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4100 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Member: {(4 + %a),+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {1,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.l = getelementptr inbounds i32, ptr %a, i64 %idx.l: ; CHECK-NEXT: ((4 * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; CHECK-NEXT: [PSE] %gep.s = getelementptr inbounds i32, ptr %a, i64 %idx.s: ; CHECK-NEXT: ((4 * (zext i2 {1,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {(4 + %a),+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx.l = urem i64 %iv, 4 %iv.p1 = add i64 %iv, 1 %idx.s = urem i64 %iv.p1, 4 %gep.l = getelementptr inbounds i32, ptr %a, i64 %idx.l %gep.s = getelementptr inbounds i32, ptr %a, i64 %idx.s %lv = load i32, ptr %gep.l, align 4 %add = add i32 %lv, 1 store i32 %add, ptr %gep.s, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_i24_store_size(ptr %a, ptr %b) { ; CHECK-LABEL: 'clamped_i24_store_size' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe with run-time checks ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %lv = load i24, ptr %gep.a, align 4 -> ; CHECK-NEXT: store i24 %add, ptr %gep.a, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Check 0: ; CHECK-NEXT: Comparing group GRP0: ; CHECK-NEXT: %gep.b = getelementptr inbounds i24, ptr %b, i64 %iv ; CHECK-NEXT: Against group GRP1: ; CHECK-NEXT: %gep.a = getelementptr inbounds i24, ptr %a, i64 %idx ; CHECK-NEXT: %gep.a = getelementptr inbounds i24, ptr %a, i64 %idx ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %b High: (4095 + %b)) ; CHECK-NEXT: Member: {%b,+,4}<%loop> ; CHECK-NEXT: Group GRP1: ; CHECK-NEXT: (Low: %a High: (4095 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.a = getelementptr inbounds i24, ptr %a, i64 %idx: ; CHECK-NEXT: ((4 * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,4}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 4 %gep.a = getelementptr inbounds i24, ptr %a, i64 %idx %lv = load i24, ptr %gep.a, align 4 %add = add i24 %lv, 1 store i24 %add, ptr %gep.a, align 4 %gep.b = getelementptr inbounds i24, ptr %b, i64 %iv store i24 %add, ptr %gep.b, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_scalable_with_dep(ptr %a, ptr %b) { ; CHECK-LABEL: 'clamped_scalable_with_dep' ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: IndirectUnsafe: ; CHECK-NEXT: store zeroinitializer, ptr %gep.a, align 16 -> ; CHECK-NEXT: store i32 %lv, ptr %gep.b2, align 4 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Check 0: ; CHECK-NEXT: Comparing group GRP0: ; CHECK-NEXT: %gep.b2 = getelementptr inbounds i32, ptr %a, i64 %iv ; CHECK-NEXT: Against group GRP2: ; CHECK-NEXT: %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv ; CHECK-NEXT: Check 1: ; CHECK-NEXT: Comparing group GRP1: ; CHECK-NEXT: %gep.a = getelementptr inbounds , ptr %a, i64 %idx ; CHECK-NEXT: Against group GRP2: ; CHECK-NEXT: %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group GRP0: ; CHECK-NEXT: (Low: %a High: (4096 + %a)) ; CHECK-NEXT: Member: {%a,+,4}<%loop> ; CHECK-NEXT: Group GRP1: ; CHECK-NEXT: (Low: (((16368 * vscale) + %a) umin %a) High: ((16 * vscale) + (((16368 * vscale) + %a) umax %a))) ; CHECK-NEXT: Member: {%a,+,(16 * vscale)}<%loop> ; CHECK-NEXT: Group GRP2: ; CHECK-NEXT: (Low: %b High: (4096 + %b)) ; CHECK-NEXT: Member: {%b,+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: ; CHECK-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep.a = getelementptr inbounds , ptr %a, i64 %idx: ; CHECK-NEXT: ((16 * vscale * (zext i2 {0,+,1}<%loop> to i64)) + %a) ; CHECK-NEXT: --> {%a,+,(16 * vscale)}<%loop> ; entry: br label %loop loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i64 %iv, 4 %gep.a = getelementptr inbounds , ptr %a, i64 %idx store zeroinitializer, ptr %gep.a, align 16 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv %lv = load i32, ptr %gep.b, align 4 %gep.b2 = getelementptr inbounds i32, ptr %a, i64 %iv store i32 %lv, ptr %gep.b2, align 4 %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void } define void @clamped_mul_huge_scale_as1(ptr addrspace(1) %a) { ; CHECK-LABEL: 'clamped_mul_huge_scale_as1' ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: IndirectUnsafe: ; CHECK-NEXT: %ld = load i64, ptr addrspace(1) %gep, align 8 -> ; CHECK-NEXT: store i64 %add, ptr addrspace(1) %gep, align 8 ; 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-NEXT: {0,+,1}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; CHECK-NEXT: [PSE] %gep = getelementptr inbounds i8, ptr addrspace(1) %a, i128 %off: ; CHECK-NEXT: ((36893488147419103232 * (zext i2 {0,+,1}<%loop> to i128)) + %a) ; CHECK-NEXT: --> {%a,+,36893488147419103232}<%loop> ; entry: br label %loop loop: %iv = phi i128 [ 0, %entry ], [ %iv.next, %loop ] %idx = urem i128 %iv, 4 %off = mul i128 %idx, 36893488147419103232 %gep = getelementptr inbounds i8, ptr addrspace(1) %a, i128 %off %ld = load i64, ptr addrspace(1) %gep, align 8 %add = add i64 %ld, 1 store i64 %add, ptr addrspace(1) %gep, align 8 %iv.next = add nuw nsw i128 %iv, 1 %ec = icmp eq i128 %iv.next, 1024 br i1 %ec, label %exit, label %loop exit: ret void }