[llvm] r324195 - [LV] Use Demanded Bits and ValueTracking for reduction type-shrinking

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 19 07:26:48 PST 2018


Merged to 6.0 in r325508.

On Sun, Feb 4, 2018 at 4:42 PM, Chad Rosier via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: mcrosier
> Date: Sun Feb  4 07:42:24 2018
> New Revision: 324195
>
> URL: http://llvm.org/viewvc/llvm-project?rev=324195&view=rev
> Log:
> [LV] Use Demanded Bits and ValueTracking for reduction type-shrinking
>
> The type-shrinking logic in reduction detection, although narrow in scope, is
> also rather ad-hoc, which has led to bugs (e.g., PR35734). This patch modifies
> the approach to rely on the demanded bits and value tracking analyses, if
> available. We currently perform type-shrinking separately for reductions and
> other instructions in the loop. Long-term, we should probably think about
> computing minimal bit widths in a more complete way for the loops we want to
> vectorize.
>
> PR35734
> Differential Revision: https://reviews.llvm.org/D42309
>
> Modified:
>     llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
>     llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
>     llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>     llvm/trunk/test/Transforms/LoopVectorize/reduction-small-size.ll
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h?rev=324195&r1=324194&r2=324195&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h Sun Feb  4 07:42:24 2018
> @@ -21,6 +21,7 @@
>  #include "llvm/ADT/SmallVector.h"
>  #include "llvm/ADT/StringRef.h"
>  #include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/DemandedBits.h"
>  #include "llvm/Analysis/EHPersonalities.h"
>  #include "llvm/Analysis/TargetTransformInfo.h"
>  #include "llvm/IR/Dominators.h"
> @@ -172,15 +173,25 @@ public:
>                                 Value *Left, Value *Right);
>
>    /// Returns true if Phi is a reduction of type Kind and adds it to the
> -  /// RecurrenceDescriptor.
> +  /// RecurrenceDescriptor. If either \p DB is non-null or \p AC and \p DT are
> +  /// non-null, the minimal bit width needed to compute the reduction will be
> +  /// computed.
>    static bool AddReductionVar(PHINode *Phi, RecurrenceKind Kind, Loop *TheLoop,
>                                bool HasFunNoNaNAttr,
> -                              RecurrenceDescriptor &RedDes);
> -
> -  /// Returns true if Phi is a reduction in TheLoop. The RecurrenceDescriptor is
> -  /// returned in RedDes.
> +                              RecurrenceDescriptor &RedDes,
> +                              DemandedBits *DB = nullptr,
> +                              AssumptionCache *AC = nullptr,
> +                              DominatorTree *DT = nullptr);
> +
> +  /// Returns true if Phi is a reduction in TheLoop. The RecurrenceDescriptor
> +  /// is returned in RedDes. If either \p DB is non-null or \p AC and \p DT are
> +  /// non-null, the minimal bit width needed to compute the reduction will be
> +  /// computed.
>    static bool isReductionPHI(PHINode *Phi, Loop *TheLoop,
> -                             RecurrenceDescriptor &RedDes);
> +                             RecurrenceDescriptor &RedDes,
> +                             DemandedBits *DB = nullptr,
> +                             AssumptionCache *AC = nullptr,
> +                             DominatorTree *DT = nullptr);
>
>    /// Returns true if Phi is a first-order recurrence. A first-order recurrence
>    /// is a non-reduction recurrence relation in which the value of the
> @@ -218,24 +229,6 @@ public:
>    /// Returns true if the recurrence kind is an arithmetic kind.
>    static bool isArithmeticRecurrenceKind(RecurrenceKind Kind);
>
> -  /// Determines if Phi may have been type-promoted. If Phi has a single user
> -  /// that ANDs the Phi with a type mask, return the user. RT is updated to
> -  /// account for the narrower bit width represented by the mask, and the AND
> -  /// instruction is added to CI.
> -  static Instruction *lookThroughAnd(PHINode *Phi, Type *&RT,
> -                                     SmallPtrSetImpl<Instruction *> &Visited,
> -                                     SmallPtrSetImpl<Instruction *> &CI);
> -
> -  /// Returns true if all the source operands of a recurrence are either
> -  /// SExtInsts or ZExtInsts. This function is intended to be used with
> -  /// lookThroughAnd to determine if the recurrence has been type-promoted. The
> -  /// source operands are added to CI, and IsSigned is updated to indicate if
> -  /// all source operands are SExtInsts.
> -  static bool getSourceExtensionKind(Instruction *Start, Instruction *Exit,
> -                                     Type *RT, bool &IsSigned,
> -                                     SmallPtrSetImpl<Instruction *> &Visited,
> -                                     SmallPtrSetImpl<Instruction *> &CI);
> -
>    /// Returns the type of the recurrence. This type can be narrower than the
>    /// actual type of the Phi if the recurrence has been type-promoted.
>    Type *getRecurrenceType() { return RecurrenceType; }
>
> Modified: llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp?rev=324195&r1=324194&r2=324195&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp Sun Feb  4 07:42:24 2018
> @@ -23,6 +23,7 @@
>  #include "llvm/Analysis/ScalarEvolutionExpander.h"
>  #include "llvm/Analysis/ScalarEvolutionExpressions.h"
>  #include "llvm/Analysis/TargetTransformInfo.h"
> +#include "llvm/Analysis/ValueTracking.h"
>  #include "llvm/IR/Dominators.h"
>  #include "llvm/IR/Instructions.h"
>  #include "llvm/IR/Module.h"
> @@ -30,6 +31,7 @@
>  #include "llvm/IR/ValueHandle.h"
>  #include "llvm/Pass.h"
>  #include "llvm/Support/Debug.h"
> +#include "llvm/Support/KnownBits.h"
>  #include "llvm/Transforms/Utils/BasicBlockUtils.h"
>
>  using namespace llvm;
> @@ -77,10 +79,13 @@ bool RecurrenceDescriptor::isArithmeticR
>    return false;
>  }
>
> -Instruction *
> -RecurrenceDescriptor::lookThroughAnd(PHINode *Phi, Type *&RT,
> -                                     SmallPtrSetImpl<Instruction *> &Visited,
> -                                     SmallPtrSetImpl<Instruction *> &CI) {
> +/// Determines if Phi may have been type-promoted. If Phi has a single user
> +/// that ANDs the Phi with a type mask, return the user. RT is updated to
> +/// account for the narrower bit width represented by the mask, and the AND
> +/// instruction is added to CI.
> +static Instruction *lookThroughAnd(PHINode *Phi, Type *&RT,
> +                                   SmallPtrSetImpl<Instruction *> &Visited,
> +                                   SmallPtrSetImpl<Instruction *> &CI) {
>    if (!Phi->hasOneUse())
>      return Phi;
>
> @@ -101,70 +106,92 @@ RecurrenceDescriptor::lookThroughAnd(PHI
>    return Phi;
>  }
>
> -bool RecurrenceDescriptor::getSourceExtensionKind(
> -    Instruction *Start, Instruction *Exit, Type *RT, bool &IsSigned,
> -    SmallPtrSetImpl<Instruction *> &Visited,
> -    SmallPtrSetImpl<Instruction *> &CI) {
> +/// Compute the minimal bit width needed to represent a reduction whose exit
> +/// instruction is given by Exit.
> +static std::pair<Type *, bool> computeRecurrenceType(Instruction *Exit,
> +                                                     DemandedBits *DB,
> +                                                     AssumptionCache *AC,
> +                                                     DominatorTree *DT) {
> +  bool IsSigned = false;
> +  const DataLayout &DL = Exit->getModule()->getDataLayout();
> +  uint64_t MaxBitWidth = DL.getTypeSizeInBits(Exit->getType());
> +
> +  if (DB) {
> +    // Use the demanded bits analysis to determine the bits that are live out
> +    // of the exit instruction, rounding up to the nearest power of two. If the
> +    // use of demanded bits results in a smaller bit width, we know the value
> +    // must be positive (i.e., IsSigned = false), because if this were not the
> +    // case, the sign bit would have been demanded.
> +    auto Mask = DB->getDemandedBits(Exit);
> +    MaxBitWidth = Mask.getBitWidth() - Mask.countLeadingZeros();
> +  }
> +
> +  if (MaxBitWidth == DL.getTypeSizeInBits(Exit->getType()) && AC && DT) {
> +    // If demanded bits wasn't able to limit the bit width, we can try to use
> +    // value tracking instead. This can be the case, for example, if the value
> +    // may be negative.
> +    auto NumSignBits = ComputeNumSignBits(Exit, DL, 0, AC, nullptr, DT);
> +    auto NumTypeBits = DL.getTypeSizeInBits(Exit->getType());
> +    MaxBitWidth = NumTypeBits - NumSignBits;
> +    KnownBits Bits = computeKnownBits(Exit, DL);
> +    if (!Bits.isNonNegative()) {
> +      // If the value is not known to be non-negative, we set IsSigned to true,
> +      // meaning that we will use sext instructions instead of zext
> +      // instructions to restore the original type.
> +      IsSigned = true;
> +      if (!Bits.isNegative())
> +        // If the value is not known to be negative, we don't known what the
> +        // upper bit is, and therefore, we don't know what kind of extend we
> +        // will need. In this case, just increase the bit width by one bit and
> +        // use sext.
> +        ++MaxBitWidth;
> +    }
> +  }
> +  if (!isPowerOf2_64(MaxBitWidth))
> +    MaxBitWidth = NextPowerOf2(MaxBitWidth);
> +
> +  return std::make_pair(Type::getIntNTy(Exit->getContext(), MaxBitWidth),
> +                        IsSigned);
> +}
> +
> +/// Collect cast instructions that can be ignored in the vectorizer's cost
> +/// model, given a reduction exit value and the minimal type in which the
> +/// reduction can be represented.
> +static void collectCastsToIgnore(Loop *TheLoop, Instruction *Exit,
> +                                 Type *RecurrenceType,
> +                                 SmallPtrSetImpl<Instruction *> &Casts) {
>
>    SmallVector<Instruction *, 8> Worklist;
> -  bool FoundOneOperand = false;
> -  unsigned DstSize = RT->getPrimitiveSizeInBits();
> +  SmallPtrSet<Instruction *, 8> Visited;
>    Worklist.push_back(Exit);
>
> -  // Traverse the instructions in the reduction expression, beginning with the
> -  // exit value.
>    while (!Worklist.empty()) {
> -    Instruction *I = Worklist.pop_back_val();
> -    for (Use &U : I->operands()) {
> -
> -      // Terminate the traversal if the operand is not an instruction, or we
> -      // reach the starting value.
> -      Instruction *J = dyn_cast<Instruction>(U.get());
> -      if (!J || J == Start)
> -        continue;
> -
> -      // Otherwise, investigate the operation if it is also in the expression.
> -      if (Visited.count(J)) {
> -        Worklist.push_back(J);
> +    Instruction *Val = Worklist.pop_back_val();
> +    Visited.insert(Val);
> +    if (auto *Cast = dyn_cast<CastInst>(Val))
> +      if (Cast->getSrcTy() == RecurrenceType) {
> +        // If the source type of a cast instruction is equal to the recurrence
> +        // type, it will be eliminated, and should be ignored in the vectorizer
> +        // cost model.
> +        Casts.insert(Cast);
>          continue;
>        }
>
> -      // If the operand is not in Visited, it is not a reduction operation, but
> -      // it does feed into one. Make sure it is either a single-use sign- or
> -      // zero-extend instruction.
> -      CastInst *Cast = dyn_cast<CastInst>(J);
> -      bool IsSExtInst = isa<SExtInst>(J);
> -      if (!Cast || !Cast->hasOneUse() || !(isa<ZExtInst>(J) || IsSExtInst))
> -        return false;
> -
> -      // Ensure the source type of the extend is no larger than the reduction
> -      // type. It is not necessary for the types to be identical.
> -      unsigned SrcSize = Cast->getSrcTy()->getPrimitiveSizeInBits();
> -      if (SrcSize > DstSize)
> -        return false;
> -
> -      // Furthermore, ensure that all such extends are of the same kind.
> -      if (FoundOneOperand) {
> -        if (IsSigned != IsSExtInst)
> -          return false;
> -      } else {
> -        FoundOneOperand = true;
> -        IsSigned = IsSExtInst;
> -      }
> -
> -      // Lastly, if the source type of the extend matches the reduction type,
> -      // add the extend to CI so that we can avoid accounting for it in the
> -      // cost model.
> -      if (SrcSize == DstSize)
> -        CI.insert(Cast);
> -    }
> +    // Add all operands to the work list if they are loop-varying values that
> +    // we haven't yet visited.
> +    for (Value *O : cast<User>(Val)->operands())
> +      if (auto *I = dyn_cast<Instruction>(O))
> +        if (TheLoop->contains(I) && !Visited.count(I))
> +          Worklist.push_back(I);
>    }
> -  return true;
>  }
>
>  bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurrenceKind Kind,
>                                             Loop *TheLoop, bool HasFunNoNaNAttr,
> -                                           RecurrenceDescriptor &RedDes) {
> +                                           RecurrenceDescriptor &RedDes,
> +                                           DemandedBits *DB,
> +                                           AssumptionCache *AC,
> +                                           DominatorTree *DT) {
>    if (Phi->getNumIncomingValues() != 2)
>      return false;
>
> @@ -353,14 +380,49 @@ bool RecurrenceDescriptor::AddReductionV
>    if (!FoundStartPHI || !FoundReduxOp || !ExitInstruction)
>      return false;
>
> -  // If we think Phi may have been type-promoted, we also need to ensure that
> -  // all source operands of the reduction are either SExtInsts or ZEstInsts. If
> -  // so, we will be able to evaluate the reduction in the narrower bit width.
> -  if (Start != Phi)
> -    if (!getSourceExtensionKind(Start, ExitInstruction, RecurrenceType,
> -                                IsSigned, VisitedInsts, CastInsts))
> +  if (Start != Phi) {
> +    // If the starting value is not the same as the phi node, we speculatively
> +    // looked through an 'and' instruction when evaluating a potential
> +    // arithmetic reduction to determine if it may have been type-promoted.
> +    //
> +    // We now compute the minimal bit width that is required to represent the
> +    // reduction. If this is the same width that was indicated by the 'and', we
> +    // can represent the reduction in the smaller type. The 'and' instruction
> +    // will be eliminated since it will essentially be a cast instruction that
> +    // can be ignore in the cost model. If we compute a different type than we
> +    // did when evaluating the 'and', the 'and' will not be eliminated, and we
> +    // will end up with different kinds of operations in the recurrence
> +    // expression (e.g., RK_IntegerAND, RK_IntegerADD). We give up if this is
> +    // the case.
> +    //
> +    // The vectorizer relies on InstCombine to perform the actual
> +    // type-shrinking. It does this by inserting instructions to truncate the
> +    // exit value of the reduction to the width indicated by RecurrenceType and
> +    // then extend this value back to the original width. If IsSigned is false,
> +    // a 'zext' instruction will be generated; otherwise, a 'sext' will be
> +    // used.
> +    //
> +    // TODO: We should not rely on InstCombine to rewrite the reduction in the
> +    //       smaller type. We should just generate a correctly typed expression
> +    //       to begin with.
> +    Type *ComputedType;
> +    std::tie(ComputedType, IsSigned) =
> +        computeRecurrenceType(ExitInstruction, DB, AC, DT);
> +    if (ComputedType != RecurrenceType)
>        return false;
>
> +    // The recurrence expression will be represented in a narrower type. If
> +    // there are any cast instructions that will be unnecessary, collect them
> +    // in CastInsts. Note that the 'and' instruction was already included in
> +    // this list.
> +    //
> +    // TODO: A better way to represent this may be to tag in some way all the
> +    //       instructions that are a part of the reduction. The vectorizer cost
> +    //       model could then apply the recurrence type to these instructions,
> +    //       without needing a white list of instructions to ignore.
> +    collectCastsToIgnore(TheLoop, ExitInstruction, RecurrenceType, CastInsts);
> +  }
> +
>    // We found a reduction var if we have reached the original phi node and we
>    // only have a single instruction with out-of-loop users.
>
> @@ -480,47 +542,57 @@ bool RecurrenceDescriptor::hasMultipleUs
>    return false;
>  }
>  bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
> -                                          RecurrenceDescriptor &RedDes) {
> +                                          RecurrenceDescriptor &RedDes,
> +                                          DemandedBits *DB, AssumptionCache *AC,
> +                                          DominatorTree *DT) {
>
>    BasicBlock *Header = TheLoop->getHeader();
>    Function &F = *Header->getParent();
>    bool HasFunNoNaNAttr =
>        F.getFnAttribute("no-nans-fp-math").getValueAsString() == "true";
>
> -  if (AddReductionVar(Phi, RK_IntegerAdd, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_IntegerAdd, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found an ADD reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_IntegerMult, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_IntegerMult, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found a MUL reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_IntegerOr, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_IntegerOr, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found an OR reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_IntegerAnd, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_IntegerAnd, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found an AND reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_IntegerXor, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_IntegerXor, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found a XOR reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_IntegerMinMax, TheLoop, HasFunNoNaNAttr,
> -                      RedDes)) {
> +  if (AddReductionVar(Phi, RK_IntegerMinMax, TheLoop, HasFunNoNaNAttr, RedDes,
> +                      DB, AC, DT)) {
>      DEBUG(dbgs() << "Found a MINMAX reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_FloatMult, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_FloatMult, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found an FMult reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_FloatAdd, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_FloatAdd, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found an FAdd reduction PHI." << *Phi << "\n");
>      return true;
>    }
> -  if (AddReductionVar(Phi, RK_FloatMinMax, TheLoop, HasFunNoNaNAttr, RedDes)) {
> +  if (AddReductionVar(Phi, RK_FloatMinMax, TheLoop, HasFunNoNaNAttr, RedDes, DB,
> +                      AC, DT)) {
>      DEBUG(dbgs() << "Found an float MINMAX reduction PHI." << *Phi << "\n");
>      return true;
>    }
>
> Modified: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp?rev=324195&r1=324194&r2=324195&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp (original)
> +++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp Sun Feb  4 07:42:24 2018
> @@ -1539,9 +1539,10 @@ public:
>        const TargetTransformInfo *TTI,
>        std::function<const LoopAccessInfo &(Loop &)> *GetLAA, LoopInfo *LI,
>        OptimizationRemarkEmitter *ORE, LoopVectorizationRequirements *R,
> -      LoopVectorizeHints *H)
> +      LoopVectorizeHints *H, DemandedBits *DB, AssumptionCache *AC)
>        : TheLoop(L), PSE(PSE), TLI(TLI), TTI(TTI), DT(DT), GetLAA(GetLAA),
> -        ORE(ORE), InterleaveInfo(PSE, L, DT, LI), Requirements(R), Hints(H) {}
> +        ORE(ORE), InterleaveInfo(PSE, L, DT, LI), Requirements(R), Hints(H),
> +        DB(DB), AC(AC) {}
>
>    /// ReductionList contains the reduction descriptors for all
>    /// of the reductions that were found in the loop.
> @@ -1830,6 +1831,14 @@ private:
>    /// Used to emit an analysis of any legality issues.
>    LoopVectorizeHints *Hints;
>
> +  /// The demanded bits analsyis is used to compute the minimum type size in
> +  /// which a reduction can be computed.
> +  DemandedBits *DB;
> +
> +  /// The assumption cache analysis is used to compute the minimum type size in
> +  /// which a reduction can be computed.
> +  AssumptionCache *AC;
> +
>    /// While vectorizing these instructions we have to generate a
>    /// call to the appropriate masked intrinsic
>    SmallPtrSet<const Instruction *, 8> MaskedOp;
> @@ -5105,7 +5114,8 @@ bool LoopVectorizationLegality::canVecto
>          }
>
>          RecurrenceDescriptor RedDes;
> -        if (RecurrenceDescriptor::isReductionPHI(Phi, TheLoop, RedDes)) {
> +        if (RecurrenceDescriptor::isReductionPHI(Phi, TheLoop, RedDes, DB, AC,
> +                                                 DT)) {
>            if (RedDes.hasUnsafeAlgebra())
>              Requirements->addUnsafeAlgebraInst(RedDes.getUnsafeAlgebraInst());
>            AllowedExit.insert(RedDes.getLoopExitInstr());
> @@ -8323,7 +8333,7 @@ bool LoopVectorizePass::processLoop(Loop
>    // Check if it is legal to vectorize the loop.
>    LoopVectorizationRequirements Requirements(*ORE);
>    LoopVectorizationLegality LVL(L, PSE, DT, TLI, AA, F, TTI, GetLAA, LI, ORE,
> -                                &Requirements, &Hints);
> +                                &Requirements, &Hints, DB, AC);
>    if (!LVL.canVectorize()) {
>      DEBUG(dbgs() << "LV: Not vectorizing: Cannot prove legality.\n");
>      emitMissedWarning(F, L, Hints, ORE);
>
> Modified: llvm/trunk/test/Transforms/LoopVectorize/reduction-small-size.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/reduction-small-size.ll?rev=324195&r1=324194&r2=324195&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/LoopVectorize/reduction-small-size.ll (original)
> +++ llvm/trunk/test/Transforms/LoopVectorize/reduction-small-size.ll Sun Feb  4 07:42:24 2018
> @@ -14,7 +14,7 @@ target datalayout = "e-m:e-i64:64-f80:12
>  ; CHECK-NEXT:    [[TMP17]] = zext <4 x i8> [[TMP16]] to <4 x i32>
>  ; CHECK-NEXT:    br i1 {{.*}}, label %middle.block, label %vector.body
>  ;
> -define void @PR34687(i1 %c, i32 %x, i32 %n) {
> +define i8 @PR34687(i1 %c, i32 %x, i32 %n) {
>  entry:
>    br label %for.body
>
> @@ -36,5 +36,38 @@ if.end:
>
>  for.end:
>    %tmp2 = phi i32 [ %r.next, %if.end ]
> -  ret void
> +  %tmp3 = trunc i32 %tmp2 to i8
> +  ret i8 %tmp3
> +}
> +
> +; CHECK-LABEL: @PR35734(
> +; CHECK:       vector.ph:
> +; CHECK:         [[TMP3:%.*]] = insertelement <4 x i32> zeroinitializer, i32 %y, i32 0
> +; CHECK-NEXT:    br label %vector.body
> +; CHECK:       vector.body:
> +; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
> +; CHECK-NEXT:    [[VEC_PHI:%.*]] = phi <4 x i32> [ [[TMP3]], %vector.ph ], [ [[TMP9:%.*]], %vector.body ]
> +; CHECK:         [[TMP5:%.*]] = and <4 x i32> [[VEC_PHI]], <i32 1, i32 1, i32 1, i32 1>
> +; CHECK-NEXT:    [[TMP6:%.*]] = add <4 x i32> [[TMP5]], <i32 -1, i32 -1, i32 -1, i32 -1>
> +; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 4
> +; CHECK:         [[TMP8:%.*]] = trunc <4 x i32> [[TMP6]] to <4 x i1>
> +; CHECK-NEXT:    [[TMP9]] = sext <4 x i1> [[TMP8]] to <4 x i32>
> +; CHECK-NEXT:    br i1 {{.*}}, label %middle.block, label %vector.body
> +;
> +define i32 @PR35734(i32 %x, i32 %y) {
> +entry:
> +  br label %for.body
> +
> +for.body:
> +  %i = phi i32 [ %x, %entry ], [ %i.next, %for.body ]
> +  %r = phi i32 [ %y, %entry ], [ %r.next, %for.body ]
> +  %tmp0 = and i32 %r, 1
> +  %r.next = add i32 %tmp0, -1
> +  %i.next = add nsw i32 %i, 1
> +  %cond = icmp sgt i32 %i, 77
> +  br i1 %cond, label %for.end, label %for.body
> +
> +for.end:
> +  %tmp1 = phi i32 [ %r.next, %for.body ]
> +  ret i32 %tmp1
>  }
>
>
> _______________________________________________
> 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