diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -1523,11 +1523,11 @@ Type *BTy = BPtr->getType()->getPointerElementType(); auto &DL = InnermostLoop->getHeader()->getModule()->getDataLayout(); uint64_t TypeByteSize = DL.getTypeAllocSize(ATy); + bool HasSameSize = TypeByteSize == DL.getTypeAllocSize(BTy); uint64_t Stride = std::abs(StrideAPtr); const SCEVConstant *C = dyn_cast(Dist); if (!C) { - if (!isa(Dist) && - TypeByteSize == DL.getTypeAllocSize(BTy) && + if (!isa(Dist) && HasSameSize && isSafeDependenceDistance(DL, *(PSE.getSE()), *(PSE.getBackedgeTakenCount()), *Dist, Stride, TypeByteSize)) @@ -1542,7 +1542,7 @@ int64_t Distance = Val.getSExtValue(); // Attempt to prove strided accesses independent. - if (std::abs(Distance) > 0 && Stride > 1 && ATy == BTy && + if (std::abs(Distance) > 0 && Stride > 1 && HasSameSize && areStridedAccessesIndependent(std::abs(Distance), Stride, TypeByteSize)) { LLVM_DEBUG(dbgs() << "LAA: Strided accesses are independent\n"); return Dependence::NoDep; @@ -1563,21 +1563,19 @@ } // Write to the same location with the same size. - // Could be improved to assert type sizes are the same (i32 == float, etc). if (Val == 0) { - if (ATy == BTy) + if (HasSameSize) return Dependence::Forward; LLVM_DEBUG( - dbgs() << "LAA: Zero dependence difference but different types\n"); + dbgs() << "LAA: Zero dependence difference but different type sizes\n"); return Dependence::Unknown; } assert(Val.isStrictlyPositive() && "Expect a positive value"); - if (ATy != BTy) { - LLVM_DEBUG( - dbgs() - << "LAA: ReadWrite-Write positive dependency with different types\n"); + if (!HasSameSize) { + LLVM_DEBUG(dbgs() << "LAA: ReadWrite-Write positive dependency with " + "different type sizes\n"); return Dependence::Unknown; } diff --git a/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll b/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll @@ -0,0 +1,68 @@ +; RUN: opt -S -tbaa -loop-accesses -analyze -enable-new-pm=0 < %s | FileCheck %s +; RUN: opt -S -disable-output -passes='require,require,require,loop(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. + +; CHECK-LABEL: function 'backdep_type_size_equivalence': +; CHECK: loop: +; CHECK: Memory dependences are safe with a maximum dependence distance of 800 bytes +; CHECK: Dependences: +; CHECK: Forward: +; CHECK: %2 = load float, float* %1, align 8 -> +; CHECK: store i32 %7, i32* %0, align 8 + +; CHECK: Forward: +; CHECK: %2 = load float, float* %1, align 8 -> +; CHECK: store float %3, float* %6, align 8 + +; CHECK: BackwardVectorizable: +; CHECK: store float %3, float* %6, align 8 -> +; CHECK: store i32 %7, i32* %0, align 8 + +%int_pair = type { i32, i32 } + +define void @backdep_type_size_equivalence(%int_pair* 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 + %0 = getelementptr inbounds %int_pair, %int_pair* %vec, i64 %indvars.iv, i32 0 + %1 = bitcast i32* %0 to float* + %2 = load float, float* %1, align 8 + %3 = fmul fast float %2, 5.0 + + ;; Store to vec[indvars.iv - 100].x as float + %4 = add nsw i64 %indvars.iv, -100 + %5 = getelementptr inbounds %int_pair, %int_pair* %vec, i64 %4, i32 0 + %6 = bitcast i32* %5 to float* + store float %3, float* %6, 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. + %7 = trunc i64 %indvars.iv to i32 + store i32 %7, i32* %0, 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. + %8 = getelementptr inbounds %int_pair, %int_pair* %vec, i64 %indvars.iv, i32 1 + store i32 %7, i32* %8, align 8 + + ;; Store to vec[indvars.iv + n].y as i32, to verify no dependence in the case + ;; of unknown dependence distance. + %9 = add nuw nsw i64 %indvars.iv, %n + %10 = getelementptr inbounds %int_pair, %int_pair* %vec, i64 %9, i32 1 + store i32 %7, i32* %10, 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 +}