; RUN: opt -S -disable-output --opaque-pointers -passes='print-access-info' < %s 2>&1 | FileCheck %s ; In the function below some of the accesses are done as float types and some ; are done as i32 types. When doing dependence analysis the type should not ; matter if it can be determined that they are the same size. %int_pair = type { i32, i32 } ; CHECK-LABEL: function 'backdep_type_size_equivalence': ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe with a maximum dependence distance of 800 bytes ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %ld.f32 = load float, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store i32 %indvars.iv.i32, ptr %gep.iv, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Forward: ; CHECK-NEXT: %ld.f32 = load float, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store float %val, ptr %gep.iv.min.100, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: BackwardVectorizable: ; CHECK-NEXT: store float %val, ptr %gep.iv.min.100, align 8 -> ; CHECK-NEXT: store i32 %indvars.iv.i32, ptr %gep.iv, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: define void @backdep_type_size_equivalence(ptr nocapture %vec, i64 %n) { entry: br label %loop loop: %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] ;; Load from vec[indvars.iv].x as float %gep.iv = getelementptr inbounds %int_pair, ptr %vec, i64 %indvars.iv, i32 0 %ld.f32 = load float, ptr %gep.iv, align 8 %val = fmul fast float %ld.f32, 5.0 ;; Store to vec[indvars.iv - 100].x as float %indvars.iv.min.100 = add nsw i64 %indvars.iv, -100 %gep.iv.min.100 = getelementptr inbounds %int_pair, ptr %vec, i64 %indvars.iv.min.100, i32 0 store float %val, ptr %gep.iv.min.100, align 8 ;; Store to vec[indvars.iv].x as i32, creating a backward dependency between ;; the two stores with different element types but the same element size. %indvars.iv.i32 = trunc i64 %indvars.iv to i32 store i32 %indvars.iv.i32, ptr %gep.iv, align 8 ;; Store to vec[indvars.iv].y as i32, strided accesses should be independent ;; between the two stores with different element types but the same element size. %gep.iv.1 = getelementptr inbounds %int_pair, ptr %vec, i64 %indvars.iv, i32 1 store i32 %indvars.iv.i32, ptr %gep.iv.1, align 8 ;; Store to vec[indvars.iv + n].y as i32, to verify no dependence in the case ;; of unknown dependence distance. %indvars.iv.n = add nuw nsw i64 %indvars.iv, %n %gep.iv.n = getelementptr inbounds %int_pair, ptr %vec, i64 %indvars.iv.n, i32 1 store i32 %indvars.iv.i32, ptr %gep.iv.n, align 8 ;; Loop condition. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 %cond = icmp eq i64 %indvars.iv.next, %n br i1 %cond, label %exit, label %loop exit: ret void } ; In the function below one of the accesses is done as i19 type, which has a ; different store size than the i32 type, even though their alloc sizes are ; equivalent. This is a negative test to ensure that they are not analyzed as ; in the tests above. ; ; CHECK-LABEL: function 'backdep_type_store_size_equivalence': ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. ; CHECK-NEXT: Unknown data dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Unknown: ; CHECK-NEXT: %ld.f32 = load float, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store i19 %indvars.iv.i19, ptr %gep.iv, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: define void @backdep_type_store_size_equivalence(ptr nocapture %vec, i64 %n) { entry: br label %loop loop: %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] ;; Load from vec[indvars.iv].x as float %gep.iv = getelementptr inbounds %int_pair, ptr %vec, i64 %indvars.iv, i32 0 %ld.f32 = load float, ptr %gep.iv, align 8 %val = fmul fast float %ld.f32, 5.0 ;; Store to vec[indvars.iv].x as i19. %indvars.iv.i19 = trunc i64 %indvars.iv to i19 store i19 %indvars.iv.i19, ptr %gep.iv, align 8 ;; Loop condition. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 %cond = icmp eq i64 %indvars.iv.next, %n br i1 %cond, label %exit, label %loop exit: ret void } ; In the function below some of the accesses are done as double types and some ; are done as i64 and i32 types. This is a negative test to ensure that they ; are not analyzed as in the tests above. ; CHECK-LABEL: function 'neg_dist_dep_type_size_equivalence': ; CHECK-NEXT: loop: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. ; CHECK-NEXT: Unknown data dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Unknown: ; CHECK-NEXT: %ld.f64 = load double, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store i32 %ld.i64.i32, ptr %gep.iv.n, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Unknown: ; CHECK-NEXT: %ld.i64 = load i64, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store i32 %ld.i64.i32, ptr %gep.iv.n, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: BackwardVectorizableButPreventsForwarding: ; CHECK-NEXT: %ld.f64 = load double, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store double %val, ptr %gep.iv.101, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: ForwardButPreventsForwarding: ; CHECK-NEXT: store double %val, ptr %gep.iv.101, align 8 -> ; CHECK-NEXT: %ld.i64 = load i64, ptr %gep.iv, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Unknown: ; CHECK-NEXT: store double %val, ptr %gep.iv.101, align 8 -> ; CHECK-NEXT: store i32 %ld.i64.i32, ptr %gep.iv.n, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: define void @neg_dist_dep_type_size_equivalence(ptr nocapture %vec, i64 %n) { entry: br label %loop loop: %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] ;; Load from vec[indvars.iv] as double %gep.iv = getelementptr i64, ptr %vec, i64 %indvars.iv %ld.f64 = load double, ptr %gep.iv, align 8 %val = fmul fast double %ld.f64, 5.0 ;; Store to vec[indvars.iv + 101] as double %indvars.iv.101 = add nsw i64 %indvars.iv, 101 %gep.iv.101 = getelementptr i64, ptr %vec, i64 %indvars.iv.101 store double %val, ptr %gep.iv.101, align 8 ;; Read from vec[indvars.iv] as i64 creating ;; a forward but prevents forwarding dependence ;; with different types but same sizes. %ld.i64 = load i64, ptr %gep.iv, align 8 ;; Different sizes %indvars.iv.n = add nuw nsw i64 %indvars.iv, %n %gep.iv.n = getelementptr inbounds i64, ptr %vec, i64 %indvars.iv.n %ld.i64.i32 = trunc i64 %ld.i64 to i32 store i32 %ld.i64.i32, ptr %gep.iv.n, align 8 ;; Loop condition. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 %cond = icmp eq i64 %indvars.iv.next, %n br i1 %cond, label %exit, label %loop exit: ret void }