[llvm] r274627 - [LV] Don't widen trivial induction variables

Matthew Simpson via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 11 07:01:22 PDT 2016


Sorry about that. Yes, I will take a look.

-- Matt

-----Original Message-----
From: anemet at apple.com [mailto:anemet at apple.com] 
Sent: Friday, July 08, 2016 6:52 PM
To: Matthew Simpson <mssimpso at codeaurora.org>; Chris Matthews <chris.matthews at apple.com>
Cc: llvm-commits <llvm-commits at lists.llvm.org>
Subject: Re: [llvm] r274627 - [LV] Don't widen trivial induction variables


> On Jul 8, 2016, at 3:49 PM, Adam Nemet <anemet at apple.com> wrote:
> 
> Hi Matt,
> 
> We’re seeing some compile-time regressions after this change.  There are a number of them in the LLVM testsuite.  One example is:
> 
> 1.024 to 1.1012 on GlobalDataFlow-flt from the LLVM test-suite compiling for AArch64 with -O3 and -flto.

One more thing, this was measured with a Release build.

> 
> Can  you please take a look?  Let me know if you are unable to reproduce.
> 
> Thanks,
> Adam
> 
>> On Jul 6, 2016, at 7:27 AM, Matthew Simpson via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>> 
>> Author: mssimpso
>> Date: Wed Jul  6 09:26:59 2016
>> New Revision: 274627
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=274627&view=rev
>> Log:
>> [LV] Don't widen trivial induction variables
>> 
>> We currently always vectorize induction variables. However, if an 
>> induction variable is only used for counting loop iterations or 
>> computing addresses with getelementptr instructions, we don't need to 
>> do this. Vectorizing these trivial induction variables can create 
>> vector code that is difficult to simplify later on. This is 
>> especially true when the unroll factor is greater than one, and we 
>> create vector arithmetic when computing step vectors. With this 
>> patch, we check if an induction variable is only used for counting 
>> iterations or computing addresses, and if so, scalarize the arithmetic when computing step vectors instead. This allows for greater simplification.
>> 
>> This patch addresses the suboptimal pointer arithmetic sequence seen 
>> in PR27881.
>> 
>> Reference: https://llvm.org/bugs/show_bug.cgi?id=27881
>> Differential Revision: http://reviews.llvm.org/D21620
>> 
>> Modified:
>>   llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>>   llvm/trunk/test/Transforms/LoopVectorize/gep_with_bitcast.ll
>>   llvm/trunk/test/Transforms/LoopVectorize/induction.ll
>>   llvm/trunk/test/Transforms/LoopVectorize/iv_outside_user.ll
>>   llvm/trunk/test/Transforms/LoopVectorize/reverse_induction.ll
>> 
>> Modified: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectori
>> ze/LoopVectorize.cpp?rev=274627&r1=274626&r2=274627&view=diff
>> =====================================================================
>> =========
>> --- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp (original)
>> +++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp Wed Jul  6 
>> +++ 09:26:59 2016
>> @@ -308,10 +308,14 @@ public:
>>  // Perform the actual loop widening (vectorization).
>>  // MinimumBitWidths maps scalar integer values to the smallest 
>> bitwidth they  // can be validly truncated to. The cost model has 
>> assumed this truncation
>> -  // will happen when vectorizing.
>> +  // will happen when vectorizing. VecValuesToIgnore contains scalar 
>> + values  // that the cost model has chosen to ignore because they 
>> + will not be  // vectorized.
>>  void vectorize(LoopVectorizationLegality *L,
>> -                 const MapVector<Instruction *, uint64_t> &MinimumBitWidths) {
>> +                 const MapVector<Instruction *, uint64_t> &MinimumBitWidths,
>> +                 SmallPtrSetImpl<const Value *> &VecValuesToIgnore) 
>> + {
>>    MinBWs = &MinimumBitWidths;
>> +    ValuesNotWidened = &VecValuesToIgnore;
>>    Legal = L;
>>    // Create a new empty loop. Unlink the old loop and connect the new one.
>>    createEmptyLoop();
>> @@ -407,6 +411,13 @@ protected:
>>  /// to each vector element of Val. The sequence starts at StartIndex.
>>  virtual Value *getStepVector(Value *Val, int StartIdx, Value *Step);
>> 
>> +  /// Compute a step vector like the above function, but scalarize 
>> + the  /// arithmetic instead. The results of the computation are 
>> + inserted into a  /// new vector with VF elements. \p Val is the 
>> + initial value, \p Step is the  /// size of the step, and \p 
>> + StartIdx indicates the index of the increment  /// from which to start computing the steps.
>> +  Value *getScalarizedStepVector(Value *Val, int StartIdx, Value 
>> + *Step);
>> +
>>  /// Create a vector induction phi node based on an existing scalar 
>> one. This  /// currently only works for integer induction variables 
>> with a constant  /// step. If \p TruncType is non-null, instead of 
>> widening the original IV, @@ -582,6 +593,11 @@ protected:
>>  /// represented as. The vector equivalents of these values should be 
>> truncated  /// to this type.
>>  const MapVector<Instruction *, uint64_t> *MinBWs;
>> +
>> +  /// A set of values that should not be widened. This is taken from  
>> + /// VecValuesToIgnore in the cost model.
>> +  SmallPtrSetImpl<const Value *> *ValuesNotWidened;
>> +
>>  LoopVectorizationLegality *Legal;
>> 
>>  // Record whether runtime checks are added.
>> @@ -2073,7 +2089,7 @@ struct LoopVectorize : public FunctionPa
>>      // If we decided that it is not legal to vectorize the loop, then
>>      // interleave it.
>>      InnerLoopUnroller Unroller(L, PSE, LI, DT, TLI, TTI, AC, IC);
>> -      Unroller.vectorize(&LVL, CM.MinBWs);
>> +      Unroller.vectorize(&LVL, CM.MinBWs, CM.VecValuesToIgnore);
>> 
>>      emitOptimizationRemark(F->getContext(), LV_NAME, *F, L->getStartLoc(),
>>                             Twine("interleaved loop (interleaved 
>> count: ") + @@ -2081,7 +2097,7 @@ struct LoopVectorize : public FunctionPa
>>    } else {
>>      // If we decided that it is *legal* to vectorize the loop, then do it.
>>      InnerLoopVectorizer LB(L, PSE, LI, DT, TLI, TTI, AC, VF.Width, IC);
>> -      LB.vectorize(&LVL, CM.MinBWs);
>> +      LB.vectorize(&LVL, CM.MinBWs, CM.VecValuesToIgnore);
>>      ++LoopsVectorized;
>> 
>>      // Add metadata to disable runtime unrolling a scalar loop when 
>> there are @@ -2201,7 +2217,8 @@ void 
>> InnerLoopVectorizer::widenIntInduct
>>  // Try to create a new independent vector induction variable. If we 
>> can't  // create the phi node, we will splat the scalar induction 
>> variable in each  // loop iteration.
>> -  if (VF > 1 && IV->getType() == Induction->getType() && Step)
>> +  if (VF > 1 && IV->getType() == Induction->getType() && Step &&
>> +      !ValuesNotWidened->count(IV))
>>    return createVectorIntInductionPHI(ID, Entry, TruncType);
>> 
>>  // The scalar value to broadcast. This will be derived from the 
>> canonical @@ -2231,6 +2248,15 @@ void InnerLoopVectorizer::widenIntInduct
>>    }
>>  }
>> 
>> +  // If an induction variable is only used for counting loop 
>> + iterations or  // calculating addresses, it shouldn't be widened. 
>> + Scalarize the step vector  // to give InstCombine a better chance of simplifying it.
>> +  if (VF > 1 && ValuesNotWidened->count(IV)) {
>> +    for (unsigned Part = 0; Part < UF; ++Part)
>> +      Entry[Part] = getScalarizedStepVector(ScalarIV, VF * Part, Step);
>> +    return;
>> +  }
>> +
>>  // Finally, splat the scalar induction variable, and build the 
>> necessary step  // vectors.
>>  Value *Broadcasted = getBroadcastInstrs(ScalarIV); @@ -2266,6 
>> +2292,29 @@ Value *InnerLoopVectorizer::getStepVecto
>>  return Builder.CreateAdd(Val, Step, "induction"); }
>> 
>> +Value *InnerLoopVectorizer::getScalarizedStepVector(Value *Val, int StartIdx,
>> +                                                    Value *Step) {
>> +
>> +  // We can't create a vector with less than two elements.
>> +  assert(VF > 1 && "VF should be greater than one");
>> +
>> +  // Get the value type and ensure it and the step have the same integer type.
>> +  Type *ValTy = Val->getType()->getScalarType();
>> +  assert(ValTy->isIntegerTy() && ValTy == Step->getType() &&
>> +         "Val and Step should have the same integer type");
>> +
>> +  // Compute the scalarized step vector. We perform scalar 
>> + arithmetic and then  // insert the results into the step vector.
>> +  Value *StepVector = UndefValue::get(ToVectorTy(ValTy, VF));  for 
>> + (unsigned I = 0; I < VF; ++I) {
>> +    auto *Mul = Builder.CreateMul(ConstantInt::get(ValTy, StartIdx + I), Step);
>> +    auto *Add = Builder.CreateAdd(Val, Mul);
>> +    StepVector = Builder.CreateInsertElement(StepVector, Add, I);  }
>> +
>> +  return StepVector;
>> +}
>> +
>> int LoopVectorizationLegality::isConsecutivePtr(Value *Ptr) {
>>  assert(Ptr->getType()->isPointerTy() && "Unexpected non-ptr");  auto 
>> *SE = PSE.getSE(); @@ -6445,8 +6494,8 @@ void 
>> LoopVectorizationCostModel::collect
>>    auto *UpdateV = 
>> PN->getIncomingValueForBlock(TheLoop->getLoopLatch());
>> 
>>    // Check that the PHI is only used by the induction increment (UpdateV) or
>> -    // by GEPs. Then check that UpdateV is only used by a compare instruction or
>> -    // the loop header PHI.
>> +    // by GEPs. Then check that UpdateV is only used by a compare instruction,
>> +    // the loop header PHI, or by GEPs.
>>    // FIXME: Need precise def-use analysis to determine if this instruction
>>    // variable will be vectorized.
>>    if (std::all_of(PN->user_begin(), PN->user_end(), @@ -6455,7 
>> +6504,8 @@ void LoopVectorizationCostModel::collect
>>                    }) &&
>>        std::all_of(UpdateV->user_begin(), UpdateV->user_end(),
>>                    [&](const User *U) -> bool {
>> -                      return U == PN || isa<ICmpInst>(U);
>> +                      return U == PN || isa<ICmpInst>(U) ||
>> +                             isa<GetElementPtrInst>(U);
>>                    })) {
>>      VecValuesToIgnore.insert(PN);
>>      VecValuesToIgnore.insert(UpdateV);
>> 
>> Modified: 
>> llvm/trunk/test/Transforms/LoopVectorize/gep_with_bitcast.ll
>> URL: 
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVe
>> ctorize/gep_with_bitcast.ll?rev=274627&r1=274626&r2=274627&view=diff
>> =====================================================================
>> =========
>> --- llvm/trunk/test/Transforms/LoopVectorize/gep_with_bitcast.ll 
>> (original)
>> +++ llvm/trunk/test/Transforms/LoopVectorize/gep_with_bitcast.ll Wed 
>> +++ Jul  6 09:26:59 2016
>> @@ -12,11 +12,11 @@ target datalayout = "e-m:e-i64:64-i128:1
>> 
>> ; CHECK-LABEL: @foo
>> ; CHECK: vector.body
>> -; CHECK:  %0 = phi
>> -; CHECK:  %2 = getelementptr inbounds double*, double** %in, i64 %0 
>> -; CHECK:  %3 = bitcast double** %2 to <4 x i64>* -; CHECK:  
>> %wide.load = load <4 x i64>, <4 x i64>* %3, align 8 -; CHECK:  %4 = 
>> icmp eq <4 x i64> %wide.load, zeroinitializer
>> +; CHECK:  %[[IV:.+]] = phi i64 [ 0, %vector.ph ], [ %index.next, 
>> +%vector.body ] ; CHECK:  %[[v0:.+]] = getelementptr inbounds 
>> +double*, double** %in, i64 %[[IV]] ; CHECK:  %[[v1:.+]] = bitcast 
>> +double** %[[v0]] to <4 x i64>* ; CHECK:  %wide.load = load <4 x 
>> +i64>, <4 x i64>* %[[v1]], align 8 ; CHECK:  icmp eq <4 x i64> 
>> +%wide.load, zeroinitializer
>> ; CHECK:  br i1
>> 
>> define void @foo(double** noalias nocapture readonly %in, double** 
>> noalias nocapture readnone %out, i8* noalias nocapture %res) #0 {
>> 
>> Modified: llvm/trunk/test/Transforms/LoopVectorize/induction.ll
>> URL: 
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVe
>> ctorize/induction.ll?rev=274627&r1=274626&r2=274627&view=diff
>> =====================================================================
>> =========
>> --- llvm/trunk/test/Transforms/LoopVectorize/induction.ll (original)
>> +++ llvm/trunk/test/Transforms/LoopVectorize/induction.ll Wed Jul  6 
>> +++ 09:26:59 2016
>> @@ -1,6 +1,7 @@
>> ; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 
>> -force-vector-width=2 -S | FileCheck %s ; RUN: opt < %s 
>> -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 
>> -instcombine -S | FileCheck %s --check-prefix=IND ; RUN: opt < %s 
>> -loop-vectorize -force-vector-interleave=2 -force-vector-width=2 
>> -instcombine -S | FileCheck %s --check-prefix=UNROLL
>> +; RUN: opt < %s -loop-vectorize -force-vector-interleave=2 
>> +-force-vector-width=4 -enable-interleaved-mem-accesses -instcombine 
>> +-S | FileCheck %s --check-prefix=INTERLEAVE
>> 
>> 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"
>> 
>> @@ -66,6 +67,137 @@ loopexit:
>>  ret void
>> }
>> 
>> +; Make sure we don't create a vector induction phi node that is unused.
>> +; Scalarize the step vectors instead.
>> +;
>> +; for (int i = 0; i < n; ++i)
>> +;   sum += a[i];
>> +;
>> +; IND-LABEL: @scalarize_induction_variable_01(
>> +; IND:     vector.body:
>> +; IND:       %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
>> +; IND-NOT:   add i64 {{.*}}, 2
>> +; IND:       getelementptr inbounds i64, i64* %a, i64 %index
>> +;
>> +; UNROLL-LABEL: @scalarize_induction_variable_01(
>> +; UNROLL:     vector.body:
>> +; UNROLL:       %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
>> +; UNROLL-NOT:   add i64 {{.*}}, 4
>> +; UNROLL:       %[[g1:.+]] = getelementptr inbounds i64, i64* %a, i64 %index
>> +; UNROLL:       getelementptr i64, i64* %[[g1]], i64 2
>> +
>> +define i64 @scalarize_induction_variable_01(i64 *%a, i64 %n) {
>> +entry:
>> +  br label %for.body
>> +
>> +for.body:
>> +  %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
>> +  %sum = phi i64 [ %2, %for.body ], [ 0, %entry ]
>> +  %0 = getelementptr inbounds i64, i64* %a, i64 %i
>> +  %1 = load i64, i64* %0, align 8
>> +  %2 = add i64 %1, %sum
>> +  %i.next = add nuw nsw i64 %i, 1
>> +  %cond = icmp slt i64 %i.next, %n
>> +  br i1 %cond, label %for.body, label %for.end
>> +
>> +for.end:
>> +  %3  = phi i64 [ %2, %for.body ]
>> +  ret i64 %3
>> +}
>> +
>> +; Make sure we scalarize the step vectors used for the pointer 
>> +arithmetic. We ; can't easily simplify vectorized step vectors.
>> +;
>> +; float s = 0;
>> +; for (int i ; 0; i < n; i += 8)
>> +;   s += (a[i] + b[i] + 1.0f);
>> +;
>> +; IND-LABEL: @scalarize_induction_variable_02( ; IND: vector.body:
>> +; IND:   %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
>> +; IND:   %[[i0:.+]] = shl i64 %index, 3
>> +; IND:   %[[i1:.+]] = or i64 %[[i0]], 8
>> +; IND:   getelementptr inbounds float, float* %a, i64 %[[i0]]
>> +; IND:   getelementptr inbounds float, float* %a, i64 %[[i1]]
>> +;
>> +; UNROLL-LABEL: @scalarize_induction_variable_02( ; UNROLL: 
>> +vector.body:
>> +; UNROLL:   %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
>> +; UNROLL:   %[[i0:.+]] = shl i64 %index, 3
>> +; UNROLL:   %[[i1:.+]] = or i64 %[[i0]], 8
>> +; UNROLL:   %[[i2:.+]] = or i64 %[[i0]], 16
>> +; UNROLL:   %[[i3:.+]] = or i64 %[[i0]], 24
>> +; UNROLL:   getelementptr inbounds float, float* %a, i64 %[[i0]]
>> +; UNROLL:   getelementptr inbounds float, float* %a, i64 %[[i1]]
>> +; UNROLL:   getelementptr inbounds float, float* %a, i64 %[[i2]]
>> +; UNROLL:   getelementptr inbounds float, float* %a, i64 %[[i3]]
>> +
>> +define float @scalarize_induction_variable_02(float* %a, float* %b, 
>> +i64 %n) {
>> +entry:
>> +  br label %for.body
>> +
>> +for.body:
>> +  %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ]
>> +  %s = phi float [ 0.0, %entry ], [ %6, %for.body ]
>> +  %0 = getelementptr inbounds float, float* %a, i64 %i
>> +  %1 = load float, float* %0, align 4
>> +  %2 = getelementptr inbounds float, float* %b, i64 %i
>> +  %3 = load float, float* %2, align 4
>> +  %4 = fadd fast float %s, 1.0
>> +  %5 = fadd fast float %4, %1
>> +  %6 = fadd fast float %5, %3
>> +  %i.next = add nuw nsw i64 %i, 8
>> +  %cond = icmp slt i64 %i.next, %n
>> +  br i1 %cond, label %for.body, label %for.end
>> +
>> +for.end:
>> +  %s.lcssa = phi float [ %6, %for.body ]
>> +  ret float %s.lcssa
>> +}
>> +
>> +; Make sure we scalarize the step vectors used for the pointer 
>> +arithmetic. We ; can't easily simplify vectorized step vectors. 
>> +(Interleaved accesses.) ; ; for (int i = 0; i < n; ++i)
>> +;   a[i].f ^= y;
>> +;
>> +; INTERLEAVE-LABEL: @scalarize_induction_variable_03( ; INTERLEAVE: 
>> +vector.body:
>> +; INTERLEAVE:   %[[i0:.+]] = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
>> +; INTERLEAVE:   %[[i1:.+]] = or i64 %[[i0]], 1
>> +; INTERLEAVE:   %[[i2:.+]] = or i64 %[[i0]], 2
>> +; INTERLEAVE:   %[[i3:.+]] = or i64 %[[i0]], 3
>> +; INTERLEAVE:   %[[i4:.+]] = or i64 %[[i0]], 4
>> +; INTERLEAVE:   %[[i5:.+]] = or i64 %[[i0]], 5
>> +; INTERLEAVE:   %[[i6:.+]] = or i64 %[[i0]], 6
>> +; INTERLEAVE:   %[[i7:.+]] = or i64 %[[i0]], 7
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i0]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i1]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i2]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i3]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i4]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i5]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i6]], i32 1
>> +; INTERLEAVE:   getelementptr inbounds %pair, %pair* %p, i64 %[[i7]], i32 1
>> +
>> +%pair = type { i32, i32 }
>> +define void @scalarize_induction_variable_03(%pair *%p, i32 %y, i64 
>> +%n) {
>> +entry:
>> +  br label %for.body
>> +
>> +for.body:
>> +  %i  = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
>> +  %f = getelementptr inbounds %pair, %pair* %p, i64 %i, i32 1
>> +  %0 = load i32, i32* %f, align 8
>> +  %1 = xor i32 %0, %y
>> +  store i32 %1, i32* %f, align 8
>> +  %i.next = add nuw nsw i64 %i, 1
>> +  %cond = icmp slt i64 %i.next, %n
>> +  br i1 %cond, label %for.body, label %for.end
>> +
>> +for.end:
>> +  ret void
>> +}
>> 
>> ; Make sure that the loop exit count computation does not overflow 
>> for i8 and ; i16. The exit count of these loops is i8/i16 max + 1. If 
>> we don't cast the @@ -114,9 +246,11 @@ define i32 @i16_loop() 
>> nounwind readnone ; CHECK-LABEL: max_i32_backedgetaken ; CHECK:  br 
>> i1 true, label %scalar.ph, label %min.iters.checked
>> 
>> +; CHECK: middle.block:
>> +; CHECK:  %[[v9:.+]] = extractelement <2 x i32> %bin.rdx, i32 0
>> ; CHECK: scalar.ph:
>> -; CHECK:  %bc.resume.val = phi i32 [ 0, %middle.block ], [ 0, %0 ] 
>> -; CHECK:  %bc.merge.rdx = phi i32 [ 1, %0 ], [ 1, %min.iters.checked 
>> ], [ %5, %middle.block ]
>> +; CHECK:  %bc.resume.val = phi i32 [ 0, %middle.block ], [ 0, 
>> +%[[v0:.+]] ] ; CHECK:  %bc.merge.rdx = phi i32 [ 1, %[[v0:.+]] ], [ 
>> +1, %min.iters.checked ], [ %[[v9]], %middle.block ]
>> 
>> define i32 @max_i32_backedgetaken() nounwind readnone ssp uwtable {
>> 
>> 
>> Modified: llvm/trunk/test/Transforms/LoopVectorize/iv_outside_user.ll
>> URL: 
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVe
>> ctorize/iv_outside_user.ll?rev=274627&r1=274626&r2=274627&view=diff
>> =====================================================================
>> =========
>> --- llvm/trunk/test/Transforms/LoopVectorize/iv_outside_user.ll 
>> (original)
>> +++ llvm/trunk/test/Transforms/LoopVectorize/iv_outside_user.ll Wed 
>> +++ Jul  6 09:26:59 2016
>> @@ -22,8 +22,8 @@ for.end:
>> 
>> ; CHECK-LABEL: @preinc
>> ; CHECK-LABEL: middle.block:
>> -; CHECK: %3 = sub i32 %n.vec, 1
>> -; CHECK: %ind.escape = add i32 0, %3
>> +; CHECK: %[[v3:.+]] = sub i32 %n.vec, 1 ; CHECK: %ind.escape = add 
>> +i32 0, %[[v3]]
>> ; CHECK-LABEL: scalar.ph:
>> ; CHECK: %bc.resume.val = phi i32 [ %n.vec, %middle.block ], [ 0, 
>> %entry ] ; CHECK-LABEL: for.end:
>> 
>> Modified: 
>> llvm/trunk/test/Transforms/LoopVectorize/reverse_induction.ll
>> URL: 
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVe
>> ctorize/reverse_induction.ll?rev=274627&r1=274626&r2=274627&view=diff
>> =====================================================================
>> =========
>> --- llvm/trunk/test/Transforms/LoopVectorize/reverse_induction.ll 
>> (original)
>> +++ llvm/trunk/test/Transforms/LoopVectorize/reverse_induction.ll Wed 
>> +++ Jul  6 09:26:59 2016
>> @@ -5,9 +5,24 @@ target datalayout = "e-p:64:64:64-i1:8:8 ; Make sure 
>> consecutive vector generates correct negative indices.
>> ; PR15882
>> 
>> -; CHECK-LABEL: @reverse_induction_i64( -; CHECK: %step.add = add <4 
>> x i64> %vec.ind, <i64 -4, i64 -4, i64 -4, i64 -4> -; CHECK: 
>> %step.add2 = add <4 x i64> %step.add, <i64 -4, i64 -4, i64 -4, i64 
>> -4>
>> +; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, 
>> +%vector.body ] ; CHECK: %offset.idx = sub i64 %startval, %index ; 
>> +CHECK: %[[a0:.+]] = add i64 %offset.idx, 0 ; CHECK: %[[v0:.+]] = 
>> +insertelement <4 x i64> undef, i64 %[[a0]], i64 0 ; CHECK: 
>> +%[[a1:.+]] = add i64 %offset.idx, -1 ; CHECK: %[[v1:.+]] = 
>> +insertelement <4 x i64> %[[v0]], i64 %[[a1]], i64 1 ; CHECK: 
>> +%[[a2:.+]] = add i64 %offset.idx, -2 ; CHECK: %[[v2:.+]] = 
>> +insertelement <4 x i64> %[[v1]], i64 %[[a2]], i64 2 ; CHECK: 
>> +%[[a3:.+]] = add i64 %offset.idx, -3 ; CHECK: %[[v3:.+]] = 
>> +insertelement <4 x i64> %[[v2]], i64 %[[a3]], i64 3 ; CHECK: 
>> +%[[a4:.+]] = add i64 %offset.idx, -4 ; CHECK: %[[v4:.+]] = 
>> +insertelement <4 x i64> undef, i64 %[[a4]], i64 0 ; CHECK: 
>> +%[[a5:.+]] = add i64 %offset.idx, -5 ; CHECK: %[[v5:.+]] = 
>> +insertelement <4 x i64> %[[v4]], i64 %[[a5]], i64 1 ; CHECK: 
>> +%[[a6:.+]] = add i64 %offset.idx, -6 ; CHECK: %[[v6:.+]] = 
>> +insertelement <4 x i64> %[[v5]], i64 %[[a6]], i64 2 ; CHECK: 
>> +%[[a7:.+]] = add i64 %offset.idx, -7 ; CHECK: %[[v7:.+]] = 
>> +insertelement <4 x i64> %[[v6]], i64 %[[a7]], i64 3
>> 
>> define i32 @reverse_induction_i64(i64 %startval, i32 * %ptr) {
>> entry:
>> @@ -30,8 +45,25 @@ loopend:
>> }
>> 
>> ; CHECK-LABEL: @reverse_induction_i128( -; CHECK: %step.add = add <4 
>> x i128> %vec.ind, <i128 -4, i128 -4, i128 -4, i128 -4> -; CHECK: 
>> %step.add2 = add <4 x i128> %step.add, <i128 -4, i128 -4, i128 -4, 
>> i128 -4>
>> +; CHECK: %index = phi i128 [ 0, %vector.ph ], [ %index.next, 
>> +%vector.body ] ; CHECK: %offset.idx = sub i128 %startval, %index ; 
>> +CHECK: %[[a0:.+]] = add i128 %offset.idx, 0 ; CHECK: %[[v0:.+]] = 
>> +insertelement <4 x i128> undef, i128 %[[a0]], i64 0 ; CHECK: 
>> +%[[a1:.+]] = add i128 %offset.idx, -1 ; CHECK: %[[v1:.+]] = 
>> +insertelement <4 x i128> %[[v0]], i128 %[[a1]], i64 1 ; CHECK: 
>> +%[[a2:.+]] = add i128 %offset.idx, -2 ; CHECK: %[[v2:.+]] = 
>> +insertelement <4 x i128> %[[v1]], i128 %[[a2]], i64 2 ; CHECK: 
>> +%[[a3:.+]] = add i128 %offset.idx, -3 ; CHECK: %[[v3:.+]] = 
>> +insertelement <4 x i128> %[[v2]], i128 %[[a3]], i64 3 ; CHECK: 
>> +%[[a4:.+]] = add i128 %offset.idx, -4 ; CHECK: %[[v4:.+]] = 
>> +insertelement <4 x i128> undef, i128 %[[a4]], i64 0 ; CHECK: 
>> +%[[a5:.+]] = add i128 %offset.idx, -5 ; CHECK: %[[v5:.+]] = 
>> +insertelement <4 x i128> %[[v4]], i128 %[[a5]], i64 1 ; CHECK: 
>> +%[[a6:.+]] = add i128 %offset.idx, -6 ; CHECK: %[[v6:.+]] = 
>> +insertelement <4 x i128> %[[v5]], i128 %[[a6]], i64 2 ; CHECK: 
>> +%[[a7:.+]] = add i128 %offset.idx, -7 ; CHECK: %[[v7:.+]] = 
>> +insertelement <4 x i128> %[[v6]], i128 %[[a7]], i64 3
>> +
>> define i32 @reverse_induction_i128(i128 %startval, i32 * %ptr) {
>> entry:
>>  br label %for.body
>> @@ -53,8 +85,24 @@ loopend:
>> }
>> 
>> ; CHECK-LABEL: @reverse_induction_i16( -; CHECK: add <4 x i16> 
>> %[[SPLAT:.*]], <i16 0, i16 -1, i16 -2, i16 -3> -; CHECK: add <4 x 
>> i16> %[[SPLAT]], <i16 -4, i16 -5, i16 -6, i16 -7>
>> +; CHECK: %index = phi i32 [ 0, %vector.ph ], [ %index.next, 
>> +%vector.body ] ; CHECK: %offset.idx = sub i16 %startval, {{.*}} ; 
>> +CHECK: %[[a0:.+]] = add i16 %offset.idx, 0 ; CHECK: %[[v0:.+]] = 
>> +insertelement <4 x i16> undef, i16 %[[a0]], i64 0 ; CHECK: 
>> +%[[a1:.+]] = add i16 %offset.idx, -1 ; CHECK: %[[v1:.+]] = 
>> +insertelement <4 x i16> %[[v0]], i16 %[[a1]], i64 1 ; CHECK: 
>> +%[[a2:.+]] = add i16 %offset.idx, -2 ; CHECK: %[[v2:.+]] = 
>> +insertelement <4 x i16> %[[v1]], i16 %[[a2]], i64 2 ; CHECK: 
>> +%[[a3:.+]] = add i16 %offset.idx, -3 ; CHECK: %[[v3:.+]] = 
>> +insertelement <4 x i16> %[[v2]], i16 %[[a3]], i64 3 ; CHECK: 
>> +%[[a4:.+]] = add i16 %offset.idx, -4 ; CHECK: %[[v4:.+]] = 
>> +insertelement <4 x i16> undef, i16 %[[a4]], i64 0 ; CHECK: 
>> +%[[a5:.+]] = add i16 %offset.idx, -5 ; CHECK: %[[v5:.+]] = 
>> +insertelement <4 x i16> %[[v4]], i16 %[[a5]], i64 1 ; CHECK: 
>> +%[[a6:.+]] = add i16 %offset.idx, -6 ; CHECK: %[[v6:.+]] = 
>> +insertelement <4 x i16> %[[v5]], i16 %[[a6]], i64 2 ; CHECK: 
>> +%[[a7:.+]] = add i16 %offset.idx, -7 ; CHECK: %[[v7:.+]] = 
>> +insertelement <4 x i16> %[[v6]], i16 %[[a7]], i64 3
>> 
>> define i32 @reverse_induction_i16(i16 %startval, i32 * %ptr) {
>> entry:
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> 




More information about the llvm-commits mailing list