From 0862d589ee51941f2c84fb110e6b42458767aea7 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 27 Jun 2013 15:11:55 +0000 Subject: [PATCH] LoopVectorize: Use vectorized loop invariant gep index anchored in loop Use vectorized instruction instead of original instruction anchored in the original loop. Fixes PR16452 and t2075.c of PR16455. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185081 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Vectorize/LoopVectorize.cpp | 28 ++++++++++----- .../LoopVectorize/undef-inst-bug.ll | 36 +++++++++++++++++++ 2 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 test/Transforms/LoopVectorize/undef-inst-bug.ll diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 3784b95a76b..57a44d895a5 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1205,16 +1205,28 @@ void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr, // The last index does not have to be the induction. It can be // consecutive and be a function of the index. For example A[I+1]; unsigned NumOperands = Gep->getNumOperands(); - - Value *LastGepOperand = Gep->getOperand(NumOperands - 1); - VectorParts &GEPParts = getVectorValue(LastGepOperand); - Value *LastIndex = GEPParts[0]; - LastIndex = Builder.CreateExtractElement(LastIndex, Zero); - + unsigned LastOperand = NumOperands - 1; // Create the new GEP with the new induction variable. GetElementPtrInst *Gep2 = cast(Gep->clone()); - Gep2->setOperand(NumOperands - 1, LastIndex); - Gep2->setName("gep.indvar.idx"); + + for (unsigned i = 0; i < NumOperands; ++i) { + Value *GepOperand = Gep->getOperand(i); + Instruction *GepOperandInst = dyn_cast(GepOperand); + + // Update last index or loop invariant instruction anchored in loop. + if (i == LastOperand || + (GepOperandInst && OrigLoop->contains(GepOperandInst))) { + assert((i == LastOperand || + SE->isLoopInvariant(SE->getSCEV(GepOperandInst), OrigLoop)) && + "Must be last index or loop invariant"); + + VectorParts &GEPParts = getVectorValue(GepOperand); + Value *Index = GEPParts[0]; + Index = Builder.CreateExtractElement(Index, Zero); + Gep2->setOperand(i, Index); + Gep2->setName("gep.indvar.idx"); + } + } Ptr = Builder.Insert(Gep2); } else { // Use the induction element ptr. diff --git a/test/Transforms/LoopVectorize/undef-inst-bug.ll b/test/Transforms/LoopVectorize/undef-inst-bug.ll new file mode 100644 index 00000000000..f6b17ba713c --- /dev/null +++ b/test/Transforms/LoopVectorize/undef-inst-bug.ll @@ -0,0 +1,36 @@ +; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +; We use to fail on this loop because we did not properly handle the loop +; invariant instruction anchored in the loop when used as a getelementptr index. +; We would use the index from the original loop resulting in a use not dominated +; by the definition. + +; PR16452 + +; Verify that we don't miscompile this loop. + +; CHECK: @t +; CHECK: <4 x i32> + +define void @t() { +entry: + br label %for.body + +for.body: + %indvars.iv17 = phi i64 [ %indvars.next, %for.body ], [ 128, %entry ] + + ; Loop invariant anchored in loop. + %idxprom21 = zext i32 undef to i64 + + %arrayidx23 = getelementptr inbounds [100 x [100 x i32]]* undef, i64 0, i64 %idxprom21, i64 %indvars.iv17 + store i32 undef, i32* %arrayidx23, align 4 + %indvars.next= add i64 %indvars.iv17, -1 + %0 = trunc i64 %indvars.next to i32 + %cmp15 = icmp ugt i32 %0, undef + br i1 %cmp15, label %for.body, label %loopexit + +loopexit: + ret void +} -- 2.34.1