diff options
-rw-r--r-- | lib/Transforms/Vectorize/LoopVectorize.cpp | 8 | ||||
-rw-r--r-- | test/Transforms/LoopVectorize/reduction.ll | 25 |
2 files changed, 31 insertions, 2 deletions
diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 0d910d1..4f6ab06 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -3818,9 +3818,13 @@ bool LoopVectorizationLegality::AddReductionVar(PHINode *Phi, // Check if we found the exit user. BasicBlock *Parent = Usr->getParent(); if (!TheLoop->contains(Parent)) { - // Exit if you find multiple outside users. - if (ExitInstruction != 0) + // Exit if you find multiple outside users or if the header phi node is + // being used. In this case the user uses the value of the previous + // iteration, in which case we would loose "VF-1" iterations of the + // reduction operation if we vectorize. + if (ExitInstruction != 0 || Cur == Phi) return false; + ExitInstruction = Cur; continue; } diff --git a/test/Transforms/LoopVectorize/reduction.ll b/test/Transforms/LoopVectorize/reduction.ll index 286b736..fbc5849 100644 --- a/test/Transforms/LoopVectorize/reduction.ll +++ b/test/Transforms/LoopVectorize/reduction.ll @@ -442,3 +442,28 @@ for.end: %add2 = fadd fast float %add.lcssa, %add1.lcssa ret float %add2 } + + +; When vectorizing a reduction whose loop header phi value is used outside the +; loop special care must be taken. Otherwise, the reduced value feeding into the +; outside user misses a few iterations (VF-1) of the loop. +; PR16522 + +; CHECK: @phivalueredux +; CHECK-NOT: x i32> + +define i32 @phivalueredux(i32 %p) { +entry: + br label %for.body + +for.body: + %t.03 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %p.addr.02 = phi i32 [ %p, %entry ], [ %xor, %for.body ] + %xor = xor i32 %p.addr.02, -1 + %inc = add nsw i32 %t.03, 1 + %exitcond = icmp eq i32 %inc, 16 + br i1 %exitcond, label %for.end, label %for.body + +for.end: + ret i32 %p.addr.02 +} |