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 SizesAreSame = 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) && SizesAreSame && 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 && SizesAreSame && 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 (SizesAreSame) 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 (!SizesAreSame) { + 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,54 @@ +; 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 double types and some +; are done as i64 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 double, double* %1, align 8 -> +; CHECK: store i64 %indvars.iv, i64* %0, align 8 + +; CHECK: Forward: +; CHECK: %2 = load double, double* %1, align 8 -> +; CHECK: store double %3, double* %6, align 8 + +; CHECK: BackwardVectorizable: +; CHECK: store double %3, double* %6, align 8 -> +; CHECK: store i64 %indvars.iv, i64* %0, align 8 + +define void @backdep_type_size_equivalence(i64* 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 + %0 = getelementptr i64, i64* %vec, i64 %indvars.iv + %1 = bitcast i64* %0 to double* + %2 = load double, double* %1, align 8 + %3 = fmul fast double %2, 5.0 + + ;; Store to vec[indvars.iv - 100] as double + %4 = add nsw i64 %indvars.iv, -100 + %5 = getelementptr i64, i64* %vec, i64 %4 + %6 = bitcast i64* %5 to double* + store double %3, double* %6, align 8 + + ;; Store to vec[indvars.iv] as i64, creating a backwards dependency between + ;; the two stores with different element types but the same element size. + store i64 %indvars.iv, i64* %0, 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 +}