Index: lib/Analysis/DependenceAnalysis.cpp =================================================================== --- lib/Analysis/DependenceAnalysis.cpp +++ lib/Analysis/DependenceAnalysis.cpp @@ -3241,6 +3241,28 @@ llvm_unreachable("constraint has unexpected kind"); } +/// Ensure all recurrences in an expression are affine. +static bool allAddRecsAffine(const SCEVAddRecExpr *S) { + + // Local struct for the SCEVTraversal. Traverse the expression until a + // SCEVAddRecExpr is found that is not affine. + struct AllAddRecsAffine { + bool IsAffine; + AllAddRecsAffine() : IsAffine(true) {} + bool follow(const SCEV *S) { + if (auto *AddRec = dyn_cast(S)) + IsAffine = AddRec->isAffine(); + return true; + } + bool isDone() { return !IsAffine; } + }; + + AllAddRecsAffine Check; + SCEVTraversal ST(Check); + ST.visitAll(S); + return Check.IsAffine; +} + /// Check if we can delinearize the subscripts. If the SCEVs representing the /// source and destination array references are recurrences on a nested loop, /// this function flattens the nested recurrences into separate recurrences @@ -3262,7 +3284,7 @@ const SCEVAddRecExpr *SrcAR = dyn_cast(SrcSCEV); const SCEVAddRecExpr *DstAR = dyn_cast(DstSCEV); - if (!SrcAR || !DstAR || !SrcAR->isAffine() || !DstAR->isAffine()) + if (!SrcAR || !DstAR || !allAddRecsAffine(SrcAR) || !allAddRecsAffine(DstAR)) return false; // First step: collect parametric terms in both array references. Index: test/Analysis/DependenceAnalysis/AffineSCEVAddRecExpr.ll =================================================================== --- /dev/null +++ test/Analysis/DependenceAnalysis/AffineSCEVAddRecExpr.ll @@ -0,0 +1,45 @@ +; REQUIRES: asserts +; RUN: opt -analyze -basicaa -da-delinearize -da %s + +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" +target triple = "thumbv7--linux-gnueabi" + +define void @f() align 2 { +entry: + %sub.ptr.div.i = ashr exact i32 undef, 3 + br i1 undef, label %for.cond6.preheader.lr.ph, label %for.end56 + +for.cond6.preheader.lr.ph: + br i1 undef, label %for.cond16.preheader, label %for.inc54 + +for.cond16.preheader: + br i1 undef, label %for.inc48, label %for.cond19.preheader + +for.cond19.preheader: + %k.197 = phi i32 [ %2, %for.inc45 ], [ 0, %for.cond16.preheader ] + %indvars.iv8095 = phi i32 [ %indvars.iv.next81, %for.inc45 ], [ %sub.ptr.div.i, %for.cond16.preheader ] + br i1 undef, label %for.inc45, label %for.body23 + +for.body23: + %k.292 = phi i32 [ %inc, %for.body23 ], [ %k.197, %for.cond19.preheader ] + %inc = add i32 %k.292, 1 + %0 = load i32*, i32** undef, align 4 + %add.ptr.i75 = getelementptr inbounds i32, i32* %0, i32 %k.292 + %1 = load i32, i32* %add.ptr.i75, align 4 + br i1 false, label %for.inc45, label %for.body23 + +for.inc45: + %indvars.iv8096 = phi i32 [ %indvars.iv8095, %for.cond19.preheader ], [ %indvars.iv8095, %for.body23 ] + %2 = add i32 %k.197, %indvars.iv8096 + %indvars.iv.next81 = add i32 %indvars.iv8095, -1 + br i1 undef, label %for.inc48, label %for.cond19.preheader + +for.inc48: + unreachable + +for.inc54: + unreachable + +for.end56: + ret void +}