diff options
| author | Nadav Rotem <nrotem@apple.com> | 2013-05-03 17:42:55 +0000 | 
|---|---|---|
| committer | Nadav Rotem <nrotem@apple.com> | 2013-05-03 17:42:55 +0000 | 
| commit | 4ce060b3da6b64c44e4d22b4a1a2111276ada553 (patch) | |
| tree | 00e502355a53007e8ea498207b9c6d1f25100627 /llvm/lib | |
| parent | 4489b85f2b2487f25778053d4dcbc05bbf83fbb5 (diff) | |
| download | bcm5719-llvm-4ce060b3da6b64c44e4d22b4a1a2111276ada553.tar.gz bcm5719-llvm-4ce060b3da6b64c44e4d22b4a1a2111276ada553.zip | |
LoopVectorizer: Add support for if-conversion of PHINodes with 3+ incoming values.
By supporting the vectorization of PHINodes with more than two incoming values we can increase the complexity of nested if statements.
We can now vectorize this loop:
int foo(int *A, int *B, int n) {
  for (int i=0; i < n; i++) {
    int x = 9;
    if (A[i] > B[i]) {
      if (A[i] > 19) {
        x = 3;
      } else if (B[i] < 4 ) {
        x = 4;
      } else {
        x = 5;
      }
    }
    A[i] = x;
  }
}
llvm-svn: 181037
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 49 | 
1 files changed, 29 insertions, 20 deletions
| diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 9a832f7a120..b00b50e7613 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1982,18 +1982,33 @@ InnerLoopVectorizer::vectorizeBlockInLoop(LoopVectorizationLegality *Legal,          // We know that all PHIs in non header blocks are converted into          // selects, so we don't have to worry about the insertion order and we          // can just use the builder. -          // At this point we generate the predication tree. There may be          // duplications since this is a simple recursive scan, but future          // optimizations will clean it up. -        VectorParts Cond = createEdgeMask(P->getIncomingBlock(0), -                                               P->getParent()); -        for (unsigned part = 0; part < UF; ++part) { -        VectorParts &In0 = getVectorValue(P->getIncomingValue(0)); -        VectorParts &In1 = getVectorValue(P->getIncomingValue(1)); -          Entry[part] = Builder.CreateSelect(Cond[part], In0[part], In1[part], -                                             "predphi"); +        unsigned NumIncoming = P->getNumIncomingValues(); +        assert(NumIncoming > 1 && "Invalid PHI"); + +        // Generate a sequence of selects of the form: +        // SELECT(Mask3, In3, +        //      SELECT(Mask2, In2, +        //                   ( ...))) +        for (unsigned In = 0; In < NumIncoming; In++) { +          VectorParts Cond = createEdgeMask(P->getIncomingBlock(In), +                                            P->getParent()); +          VectorParts &In0 = getVectorValue(P->getIncomingValue(In)); + +          for (unsigned part = 0; part < UF; ++part) { +            // We don't need to 'select' the first PHI operand because it is +            // the default value if all of the other masks don't match. +            if (In == 0) +              Entry[part] = In0[part]; +            else +              // Select between the current value and the previous incoming edge +              // based on the incoming mask. +              Entry[part] = Builder.CreateSelect(Cond[part], In0[part], +                                                 Entry[part], "predphi"); +          }          }          continue;        } @@ -2273,12 +2288,6 @@ bool LoopVectorizationLegality::canVectorizeWithIfConvert() {      if (!isa<BranchInst>(BB->getTerminator()))        return false; -    // We must have at most two predecessors because we need to convert -    // all PHIs to selects. -    unsigned Preds = std::distance(pred_begin(BB), pred_end(BB)); -    if (Preds > 2) -      return false; -      // We must be able to predicate all blocks that need to be predicated.      if (blockNeedsPredication(BB) && !blockCanBePredicated(BB))        return false; @@ -2376,12 +2385,6 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {           ++it) {        if (PHINode *Phi = dyn_cast<PHINode>(it)) { -        // This should not happen because the loop should be normalized. -        if (Phi->getNumIncomingValues() != 2) { -          DEBUG(dbgs() << "LV: Found an invalid PHI.\n"); -          return false; -        } -          // Check that this PHI type is allowed.          if (!Phi->getType()->isIntegerTy() &&              !Phi->getType()->isFloatingPointTy() && @@ -2396,6 +2399,12 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {          if (*bb != Header)            continue; +        // We only allow if-converted PHIs with more than two incoming values. +        if (Phi->getNumIncomingValues() != 2) { +          DEBUG(dbgs() << "LV: Found an invalid PHI.\n"); +          return false; +        } +          // This is the value coming from the preheader.          Value *StartValue = Phi->getIncomingValueForBlock(PreHeader);          // Check if this is an induction variable. | 

