Skip to content

Commit

Permalink
[SLP] Refactoring of EdgeInfo and UserTreeIdx in buildTree_rec().
Browse files Browse the repository at this point in the history
This is a follow-up refactoring patch after the introduction of usable TreeEntry pointers in D61706.
The EdgeInfo struct can now use a TreeEntry pointer instead of an index in VectorizableTree.

Committed on behalf of @vporpo (Vasileios Porpodas)

Differential Revision: https://reviews.llvm.org/D61795

llvm-svn: 361110
  • Loading branch information
dtemirbulatov authored and MrSidims committed May 24, 2019
1 parent 25c23c5 commit fa3c0c6
Showing 1 changed file with 48 additions and 58 deletions.
106 changes: 48 additions & 58 deletions llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
Expand Up @@ -485,6 +485,8 @@ namespace slpvectorizer {

/// Bottom Up SLP Vectorizer.
class BoUpSLP {
struct TreeEntry;

public:
using ValueList = SmallVector<Value *, 8>;
using InstrList = SmallVector<Instruction *, 16>;
Expand Down Expand Up @@ -620,8 +622,10 @@ class BoUpSLP {
/// (ii) the index of the edge.
struct EdgeInfo {
EdgeInfo() = default;
/// The index of the user TreeEntry in VectorizableTree.
int Idx = -1;
EdgeInfo(TreeEntry *UserTE, unsigned EdgeIdx)
: UserTE(UserTE), EdgeIdx(EdgeIdx) {}
/// The user TreeEntry.
TreeEntry *UserTE = nullptr;
/// The operand index of the use.
unsigned EdgeIdx = UINT_MAX;
#ifndef NDEBUG
Expand All @@ -632,7 +636,8 @@ class BoUpSLP {
}
/// Debug print.
void dump(raw_ostream &OS) const {
OS << "{User:" << Idx << " EdgeIdx:" << EdgeIdx << "}";
OS << "{User:" << (UserTE ? std::to_string(UserTE->Idx) : "null")
<< " EdgeIdx:" << EdgeIdx << "}";
}
LLVM_DUMP_METHOD void dump() const { dump(dbgs()); }
#endif
Expand Down Expand Up @@ -1083,16 +1088,15 @@ class BoUpSLP {
};

private:
struct TreeEntry;

/// Checks if all users of \p I are the part of the vectorization tree.
bool areAllUsersVectorized(Instruction *I) const;

/// \returns the cost of the vectorizable entry.
int getEntryCost(TreeEntry *E);

/// This is the recursive part of buildTree.
void buildTree_rec(ArrayRef<Value *> Roots, unsigned Depth, EdgeInfo EI);
void buildTree_rec(ArrayRef<Value *> Roots, unsigned Depth,
const EdgeInfo &EI);

/// \returns true if the ExtractElement/ExtractValue instructions in \p VL can
/// be vectorized to use the original vector (or aggregate "bitcast" to a
Expand Down Expand Up @@ -1177,6 +1181,9 @@ class BoUpSLP {
/// have multiple users so the data structure is not truly a tree.
SmallVector<EdgeInfo, 1> UserTreeIndices;

/// The index of this treeEntry in VectorizableTree.
int Idx = -1;

private:
/// The operands of each instruction in each lane Operands[op_index][lane].
/// Note: This helps avoid the replication of the code that performs the
Expand All @@ -1201,11 +1208,9 @@ class BoUpSLP {
void trySetUserTEOperand(const EdgeInfo &UserTreeIdx,
ArrayRef<Value *> OpVL,
ArrayRef<unsigned> ReuseShuffleIndices) {
if (UserTreeIdx.Idx >= 0) {
auto &VectorizableTree = Container;
VectorizableTree[UserTreeIdx.Idx]->setOperand(UserTreeIdx.EdgeIdx, OpVL,
ReuseShuffleIndices);
}
if (UserTreeIdx.UserTE)
UserTreeIdx.UserTE->setOperand(UserTreeIdx.EdgeIdx, OpVL,
ReuseShuffleIndices);
}

/// \returns the \p OpIdx operand of this TreeEntry.
Expand All @@ -1224,6 +1229,7 @@ class BoUpSLP {
#ifndef NDEBUG
/// Debug printer.
LLVM_DUMP_METHOD void dump() const {
dbgs() << Idx << ".\n";
for (unsigned OpI = 0, OpE = Operands.size(); OpI != OpE; ++OpI) {
dbgs() << "Operand " << OpI << ":\n";
for (const Value *V : Operands[OpI])
Expand Down Expand Up @@ -1260,12 +1266,12 @@ class BoUpSLP {

/// Create a new VectorizableTree entry.
TreeEntry *newTreeEntry(ArrayRef<Value *> VL, bool Vectorized,
EdgeInfo &UserTreeIdx,
const EdgeInfo &UserTreeIdx,
ArrayRef<unsigned> ReuseShuffleIndices = None,
ArrayRef<unsigned> ReorderIndices = None) {
VectorizableTree.push_back(llvm::make_unique<TreeEntry>(VectorizableTree));
TreeEntry *Last = VectorizableTree.back().get();
int idx = VectorizableTree.size() - 1;
Last->Idx = VectorizableTree.size() - 1;
Last->Scalars.insert(Last->Scalars.begin(), VL.begin(), VL.end());
Last->NeedToGather = !Vectorized;
Last->ReuseShuffleIndices.append(ReuseShuffleIndices.begin(),
Expand All @@ -1274,18 +1280,16 @@ class BoUpSLP {
if (Vectorized) {
for (int i = 0, e = VL.size(); i != e; ++i) {
assert(!getTreeEntry(VL[i]) && "Scalar already in tree!");
ScalarToTreeEntry[VL[i]] = idx;
ScalarToTreeEntry[VL[i]] = Last->Idx;
}
} else {
MustGather.insert(VL.begin(), VL.end());
}

if (UserTreeIdx.Idx >= 0)
if (UserTreeIdx.UserTE)
Last->UserTreeIndices.push_back(UserTreeIdx);

Last->trySetUserTEOperand(UserTreeIdx, VL, ReuseShuffleIndices);

UserTreeIdx.Idx = idx;
return Last;
}

Expand All @@ -1297,7 +1301,6 @@ class BoUpSLP {
/// Debug printer.
LLVM_DUMP_METHOD void dumpVectorizableTree() const {
for (unsigned Id = 0, IdE = VectorizableTree.size(); Id != IdE; ++Id) {
dbgs() << Id << ".\n";
VectorizableTree[Id]->dump();
dbgs() << "\n";
}
Expand Down Expand Up @@ -1837,7 +1840,7 @@ template <> struct GraphTraits<BoUpSLP *> {
ContainerTy &VT)
: ChildIteratorType::iterator_adaptor_base(W), VectorizableTree(VT) {}

NodeRef operator*() { return VectorizableTree[I->Idx].get(); }
NodeRef operator*() { return I->UserTE; }
};

static NodeRef getEntryNode(BoUpSLP &R) {
Expand Down Expand Up @@ -1987,7 +1990,7 @@ void BoUpSLP::buildTree(ArrayRef<Value *> Roots,
}

void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
EdgeInfo UserTreeIdx) {
const EdgeInfo &UserTreeIdx) {
assert((allConstant(VL) || allSameType(VL)) && "Invalid types!");

InstructionsState S = getSameOpcode(VL);
Expand Down Expand Up @@ -2144,7 +2147,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
}
}

newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a vector of PHINodes.\n");

for (unsigned i = 0, e = PH->getNumIncomingValues(); i < e; ++i) {
Expand All @@ -2154,8 +2157,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
Operands.push_back(cast<PHINode>(j)->getIncomingValueForBlock(
PH->getIncomingBlock(i)));

UserTreeIdx.EdgeIdx = i;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, i});
}
return;
}
Expand Down Expand Up @@ -2300,7 +2302,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
return;
}
}
newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n");

for (unsigned i = 0, e = VL0->getNumOperands(); i < e; ++i) {
Expand All @@ -2309,8 +2311,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
for (Value *j : VL)
Operands.push_back(cast<Instruction>(j)->getOperand(i));

UserTreeIdx.EdgeIdx = i;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, i});
}
return;
}
Expand All @@ -2332,7 +2333,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
}
}

newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a vector of compares.\n");

ValueList Left, Right;
Expand All @@ -2354,10 +2355,8 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
}
}

UserTreeIdx.EdgeIdx = 0;
buildTree_rec(Left, Depth + 1, UserTreeIdx);
UserTreeIdx.EdgeIdx = 1;
buildTree_rec(Right, Depth + 1, UserTreeIdx);
buildTree_rec(Left, Depth + 1, {TE, 0});
buildTree_rec(Right, Depth + 1, {TE, 1});
return;
}
case Instruction::Select:
Expand All @@ -2378,19 +2377,17 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
case Instruction::AShr:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
case Instruction::Xor: {
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a vector of bin op.\n");

// Sort operands of the instructions so that each side is more likely to
// have the same opcode.
if (isa<BinaryOperator>(VL0) && VL0->isCommutative()) {
ValueList Left, Right;
reorderInputsAccordingToOpcode(VL, Left, Right, *DL, *SE);
UserTreeIdx.EdgeIdx = 0;
buildTree_rec(Left, Depth + 1, UserTreeIdx);
UserTreeIdx.EdgeIdx = 1;
buildTree_rec(Right, Depth + 1, UserTreeIdx);
buildTree_rec(Left, Depth + 1, {TE, 0});
buildTree_rec(Right, Depth + 1, {TE, 1});
return;
}

Expand All @@ -2400,11 +2397,10 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
for (Value *j : VL)
Operands.push_back(cast<Instruction>(j)->getOperand(i));

UserTreeIdx.EdgeIdx = i;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, i});
}
return;

}
case Instruction::GetElementPtr: {
// We don't combine GEPs with complicated (nested) indexing.
for (unsigned j = 0; j < VL.size(); ++j) {
Expand Down Expand Up @@ -2442,16 +2438,15 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
}
}

newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a vector of GEPs.\n");
for (unsigned i = 0, e = 2; i < e; ++i) {
ValueList Operands;
// Prepare the operand vector.
for (Value *j : VL)
Operands.push_back(cast<Instruction>(j)->getOperand(i));

UserTreeIdx.EdgeIdx = i;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, i});
}
return;
}
Expand All @@ -2465,15 +2460,14 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
return;
}

newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a vector of stores.\n");

ValueList Operands;
for (Value *j : VL)
Operands.push_back(cast<Instruction>(j)->getOperand(0));

UserTreeIdx.EdgeIdx = 0;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, 0});
return;
}
case Instruction::Call: {
Expand Down Expand Up @@ -2533,20 +2527,19 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
}
}

newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
for (unsigned i = 0, e = CI->getNumArgOperands(); i != e; ++i) {
ValueList Operands;
// Prepare the operand vector.
for (Value *j : VL) {
CallInst *CI2 = dyn_cast<CallInst>(j);
Operands.push_back(CI2->getArgOperand(i));
}
UserTreeIdx.EdgeIdx = i;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, i});
}
return;
}
case Instruction::ShuffleVector:
case Instruction::ShuffleVector: {
// If this is not an alternate sequence of opcode like add-sub
// then do not vectorize this instruction.
if (!S.isAltShuffle()) {
Expand All @@ -2555,17 +2548,15 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
LLVM_DEBUG(dbgs() << "SLP: ShuffleVector are not vectorized.\n");
return;
}
newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
auto *TE = newTreeEntry(VL, true, UserTreeIdx, ReuseShuffleIndicies);
LLVM_DEBUG(dbgs() << "SLP: added a ShuffleVector op.\n");

// Reorder operands if reordering would enable vectorization.
if (isa<BinaryOperator>(VL0)) {
ValueList Left, Right;
reorderInputsAccordingToOpcode(VL, Left, Right, *DL, *SE);
UserTreeIdx.EdgeIdx = 0;
buildTree_rec(Left, Depth + 1, UserTreeIdx);
UserTreeIdx.EdgeIdx = 1;
buildTree_rec(Right, Depth + 1, UserTreeIdx);
buildTree_rec(Left, Depth + 1, {TE, 0});
buildTree_rec(Right, Depth + 1, {TE, 1});
return;
}

Expand All @@ -2575,11 +2566,10 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
for (Value *j : VL)
Operands.push_back(cast<Instruction>(j)->getOperand(i));

UserTreeIdx.EdgeIdx = i;
buildTree_rec(Operands, Depth + 1, UserTreeIdx);
buildTree_rec(Operands, Depth + 1, {TE, i});
}
return;

}
default:
BS.cancelScheduling(VL, VL0);
newTreeEntry(VL, false, UserTreeIdx, ReuseShuffleIndicies);
Expand Down

0 comments on commit fa3c0c6

Please sign in to comment.