/// This is the recursive part of buildTree.
void buildTree_rec(ArrayRef<Value *> Roots, unsigned Depth);
- /// Vectorizer a single entry in the tree.
+ /// Vectorize a single entry in the tree.
Value *vectorizeTree(TreeEntry *E);
- /// Vectorizer a single entry in the tree, starting in \p VL.
+ /// Vectorize a single entry in the tree, starting in \p VL.
Value *vectorizeTree(ArrayRef<Value *> VL);
+ /// \returns the pointer to the vectorized value if \p VL is already
+ /// vectorized, or NULL. They may happen in cycles.
+ Value *alreadyVectorized(ArrayRef<Value *> VL);
+
/// \brief Take the pointer operand from the Load/Store instruction.
/// \returns NULL if this is not a valid Load/Store instruction.
static Value *getPointerOperand(Value *I);
/// \returns the Instrucion in the bundle \p VL.
Instruction *getLastInstruction(ArrayRef<Value *> VL);
- /// \returns the Instruction at index \p Index which is in Block \p BB.
- Instruction *getInstructionForIndex(unsigned Index, BasicBlock *BB);
-
- /// \returns the index of the first User of \p VL.
- int getFirstUserIndex(ArrayRef<Value *> VL);
-
/// \returns a vector from a collection of scalars in \p VL.
Value *Gather(ArrayRef<Value *> VL, VectorType *Ty);
DEBUG(dbgs() << "SLP: Calculating cost for tree of size " <<
VectorizableTree.size() << ".\n");
- if (!VectorizableTree.size()) {
- assert(!ExternalUses.size() && "We should not have any external users");
+ // Don't vectorize tiny trees. Small load/store chains or consecutive stores
+ // of constants will be vectoried in SelectionDAG in MergeConsecutiveStores.
+ // The SelectionDAG vectorizer can only handle pairs (trees of height = 2).
+ if (VectorizableTree.size() < 3) {
+ if (!VectorizableTree.size()) {
+ assert(!ExternalUses.size() && "We should not have any external users");
+ }
return 0;
}
return I;
}
-Instruction *BoUpSLP::getInstructionForIndex(unsigned Index, BasicBlock *BB) {
- BlockNumbering &BN = BlocksNumbers[BB];
- return BN.getInstruction(Index);
-}
-
-int BoUpSLP::getFirstUserIndex(ArrayRef<Value *> VL) {
- BasicBlock *BB = getSameBlock(VL);
- assert(BB && "All instructions must come from the same block");
- BlockNumbering &BN = BlocksNumbers[BB];
-
- // Find the first user of the values.
- int FirstUser = BN.getIndex(BB->getTerminator());
- for (unsigned i = 0, e = VL.size(); i < e; ++i) {
- for (Value::use_iterator U = VL[i]->use_begin(), UE = VL[i]->use_end();
- U != UE; ++U) {
- Instruction *Instr = dyn_cast<Instruction>(*U);
-
- if (!Instr || Instr->getParent() != BB)
- continue;
-
- FirstUser = std::min(FirstUser, BN.getIndex(Instr));
- }
- }
- return FirstUser;
-}
-
Value *BoUpSLP::Gather(ArrayRef<Value *> VL, VectorType *Ty) {
Value *Vec = UndefValue::get(Ty);
// Generate the 'InsertElement' instruction.
return Vec;
}
+Value *BoUpSLP::alreadyVectorized(ArrayRef<Value *> VL) {
+ if (ScalarToTreeEntry.count(VL[0])) {
+ int Idx = ScalarToTreeEntry[VL[0]];
+ TreeEntry *En = &VectorizableTree[Idx];
+ if (En->isSame(VL) && En->VectorizedValue)
+ return En->VectorizedValue;
+ }
+ return 0;
+}
+
Value *BoUpSLP::vectorizeTree(ArrayRef<Value *> VL) {
if (ScalarToTreeEntry.count(VL[0])) {
int Idx = ScalarToTreeEntry[VL[0]];
Builder.SetInsertPoint(getLastInstruction(E->Scalars));
Value *InVec = vectorizeTree(INVL);
+
+ if (Value *V = alreadyVectorized(E->Scalars))
+ return V;
+
CastInst *CI = dyn_cast<CastInst>(VL0);
Value *V = Builder.CreateCast(CI->getOpcode(), InVec, VecTy);
E->VectorizedValue = V;
Builder.SetInsertPoint(getLastInstruction(E->Scalars));
Value *L = vectorizeTree(LHSV);
Value *R = vectorizeTree(RHSV);
- Value *V;
+
+ if (Value *V = alreadyVectorized(E->Scalars))
+ return V;
CmpInst::Predicate P0 = dyn_cast<CmpInst>(VL0)->getPredicate();
+ Value *V;
if (Opcode == Instruction::FCmp)
V = Builder.CreateFCmp(P0, L, R);
else
Value *Cond = vectorizeTree(CondVec);
Value *True = vectorizeTree(TrueVec);
Value *False = vectorizeTree(FalseVec);
+
+ if (Value *V = alreadyVectorized(E->Scalars))
+ return V;
+
Value *V = Builder.CreateSelect(Cond, True, False);
E->VectorizedValue = V;
return V;
assert((VL0->getOperand(0) == VL0->getOperand(1)) && "Invalid order");
}
+ if (Value *V = alreadyVectorized(E->Scalars))
+ return V;
+
BinaryOperator *BinOp = cast<BinaryOperator>(VL0);
Value *V = Builder.CreateBinOp(BinOp->getOpcode(), LHS, RHS);
E->VectorizedValue = V;
if (!DL)
return false;
+ // Don't vectorize when the attribute NoImplicitFloat is used.
+ if (F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::NoImplicitFloat))
+ return false;
+
DEBUG(dbgs() << "SLP: Analyzing blocks in " << F.getName() << ".\n");
// Use the bollom up slp vectorizer to construct chains that start with
}
}
- if (Changed || ChainLen > VF)
return Changed;
-
- // Handle short chains. This helps us catch types such as <3 x float> that
- // are smaller than vector size.
- R.buildTree(Chain);
-
- int Cost = R.getTreeCost();
-
- if (Cost < CostThreshold) {
- DEBUG(dbgs() << "SLP: Found store chain cost = " << Cost
- << " for size = " << ChainLen << "\n");
- R.vectorizeTree();
- return true;
- }
-
- return false;
}
bool SLPVectorizer::vectorizeStores(ArrayRef<StoreInst *> Stores,