summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2020-01-09 10:23:34 +0000
committerFlorian Hahn <flo@fhahn.com>2020-01-09 10:52:52 +0000
commitccf24225e3f2356ebf0e73bb114a831bf1721222 (patch)
treea855236d435ba070d795fd1b3e81b3bb493c8aeb /llvm/lib/Transforms
parent287a874d1c460302677a1530a75d94bae4d4a348 (diff)
downloadbcm5719-llvm-ccf24225e3f2356ebf0e73bb114a831bf1721222.tar.gz
bcm5719-llvm-ccf24225e3f2356ebf0e73bb114a831bf1721222.zip
[Matrix] Update shape propagation to iterate until done.
This patch updates the shape propagation to iterate until no new shape information is discovered. As initial seed for the forward propagation, we use the matrix intrinsic instructions. Both propagateShapeForward and propagateShapeBackward return new work lists, with the instructions to be used for the next iteration. When propagating forward, we record all instructions we added new shape information for. When propagating backward, we record all users of instructions we added new shape information for. Reviewers: anemet, Gerolf, reames, hfinkel, andrew.w.kaylor Reviewed By: anemet Differential Revision: https://reviews.llvm.org/D70901
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp105
1 files changed, 62 insertions, 43 deletions
diff --git a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
index afe1b4e7cc7..0ff6ee8bcfc 100644
--- a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
+++ b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
@@ -10,9 +10,6 @@
//
// TODO:
// * Implement multiply & add fusion
-// * Implement shape propagation
-// * Implement optimizations to reduce or eliminateshufflevector uses by using
-// shape information.
// * Add remark, summarizing the available matrix optimization opportunities.
//
//===----------------------------------------------------------------------===//
@@ -321,32 +318,12 @@ public:
}
/// Propagate the shape information of instructions to their users.
- void propagateShapeForward() {
- // The work list contains instructions for which we can compute the shape,
- // either based on the information provided by matrix intrinsics or known
- // shapes of operands.
- SmallVector<Instruction *, 8> WorkList;
-
- // Initialize the work list with ops carrying shape information. Initially
- // only the shape of matrix intrinsics is known.
- for (BasicBlock &BB : Func)
- for (Instruction &Inst : BB) {
- IntrinsicInst *II = dyn_cast<IntrinsicInst>(&Inst);
- if (!II)
- continue;
-
- switch (II->getIntrinsicID()) {
- case Intrinsic::matrix_multiply:
- case Intrinsic::matrix_transpose:
- case Intrinsic::matrix_columnwise_load:
- case Intrinsic::matrix_columnwise_store:
- WorkList.push_back(&Inst);
- break;
- default:
- break;
- }
- }
-
+ /// The work list contains instructions for which we can compute the shape,
+ /// either based on the information provided by matrix intrinsics or known
+ /// shapes of operands.
+ SmallVector<Instruction *, 32>
+ propagateShapeForward(SmallVectorImpl<Instruction *> &WorkList) {
+ SmallVector<Instruction *, 32> NewWorkList;
// Pop an element for which we guaranteed to have at least one of the
// operand shapes. Add the shape for this and then add users to the work
// list.
@@ -395,20 +372,29 @@ public:
}
}
- if (Propagate)
+ if (Propagate) {
+ NewWorkList.push_back(Inst);
for (auto *User : Inst->users())
if (ShapeMap.count(User) == 0)
WorkList.push_back(cast<Instruction>(User));
+ }
}
+
+ return NewWorkList;
}
/// Propagate the shape to operands of instructions with shape information.
- void propagateShapeBackward() {
- SmallVector<Value *, 8> WorkList;
- // Worklist contains instruction for which we already know the shape.
- for (auto &V : ShapeMap)
- WorkList.push_back(V.first);
-
+ /// \p Worklist contains the instruction for which we already know the shape.
+ SmallVector<Instruction *, 32>
+ propagateShapeBackward(SmallVectorImpl<Instruction *> &WorkList) {
+ SmallVector<Instruction *, 32> NewWorkList;
+
+ auto pushInstruction = [](Value *V,
+ SmallVectorImpl<Instruction *> &WorkList) {
+ Instruction *I = dyn_cast<Instruction>(V);
+ if (I)
+ WorkList.push_back(I);
+ };
// Pop an element with known shape. Traverse the operands, if their shape
// derives from the result shape and is unknown, add it and add them to the
// worklist.
@@ -417,6 +403,7 @@ public:
Value *V = WorkList.back();
WorkList.pop_back();
+ size_t BeforeProcessingV = WorkList.size();
if (!isa<Instruction>(V))
continue;
@@ -429,21 +416,21 @@ public:
m_Value(MatrixA), m_Value(MatrixB), m_Value(M),
m_Value(N), m_Value(K)))) {
if (setShapeInfo(MatrixA, {M, N}))
- WorkList.push_back(MatrixA);
+ pushInstruction(MatrixA, WorkList);
if (setShapeInfo(MatrixB, {N, K}))
- WorkList.push_back(MatrixB);
+ pushInstruction(MatrixB, WorkList);
} else if (match(V, m_Intrinsic<Intrinsic::matrix_transpose>(
m_Value(MatrixA), m_Value(M), m_Value(N)))) {
// Flip dimensions.
if (setShapeInfo(MatrixA, {M, N}))
- WorkList.push_back(MatrixA);
+ pushInstruction(MatrixA, WorkList);
} else if (match(V, m_Intrinsic<Intrinsic::matrix_columnwise_store>(
m_Value(MatrixA), m_Value(), m_Value(),
m_Value(M), m_Value(N)))) {
if (setShapeInfo(MatrixA, {M, N})) {
- WorkList.push_back(MatrixA);
+ pushInstruction(MatrixA, WorkList);
}
} else if (isa<LoadInst>(V) ||
match(V, m_Intrinsic<Intrinsic::matrix_columnwise_load>())) {
@@ -456,16 +443,48 @@ public:
ShapeInfo Shape = ShapeMap[V];
for (Use &U : cast<Instruction>(V)->operands()) {
if (setShapeInfo(U.get(), Shape))
- WorkList.push_back(U.get());
+ pushInstruction(U.get(), WorkList);
}
}
+ // After we discovered new shape info for new instructions in the
+ // worklist, we use their users as seeds for the next round of forward
+ // propagation.
+ for (size_t I = BeforeProcessingV; I != WorkList.size(); I++)
+ for (User *U : WorkList[I]->users())
+ if (isa<Instruction>(U) && V != U)
+ NewWorkList.push_back(cast<Instruction>(U));
}
+ return NewWorkList;
}
bool Visit() {
if (EnableShapePropagation) {
- propagateShapeForward();
- propagateShapeBackward();
+ SmallVector<Instruction *, 32> WorkList;
+
+ // Initially only the shape of matrix intrinsics is known.
+ // Initialize the work list with ops carrying shape information.
+ for (BasicBlock &BB : Func)
+ for (Instruction &Inst : BB) {
+ IntrinsicInst *II = dyn_cast<IntrinsicInst>(&Inst);
+ if (!II)
+ continue;
+
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::matrix_multiply:
+ case Intrinsic::matrix_transpose:
+ case Intrinsic::matrix_columnwise_load:
+ case Intrinsic::matrix_columnwise_store:
+ WorkList.push_back(&Inst);
+ break;
+ default:
+ break;
+ }
+ }
+ // Propagate shapes until nothing changes any longer.
+ while (!WorkList.empty()) {
+ WorkList = propagateShapeForward(WorkList);
+ WorkList = propagateShapeBackward(WorkList);
+ }
}
ReversePostOrderTraversal<Function *> RPOT(&Func);
OpenPOWER on IntegriCloud