summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRiver Riddle <riverriddle@google.com>2019-03-06 17:37:14 -0800
committerjpienaar <jpienaar@google.com>2019-03-29 17:04:19 -0700
commitba6fdc8b01403d0c83454019c81a38b84966fe9a (patch)
treee1d055a55d368e4647bb9850c8801dae2544a644
parent157e3cdb1946121210d1b9f52d9739a918a92e6d (diff)
downloadbcm5719-llvm-ba6fdc8b01403d0c83454019c81a38b84966fe9a.tar.gz
bcm5719-llvm-ba6fdc8b01403d0c83454019c81a38b84966fe9a.zip
Move UtilResult into the Support directory and rename it to Status. Status provides an unambiguous way to specify success/failure results. These can be generated by 'Status::success()' and Status::failure()'. Status provides no implicit conversion to bool and should be consumed by one of the following utility functions:
* bool succeeded(Status) - Return if the status corresponds to a success value. * bool failed(Status) - Return if the status corresponds to a failure value. PiperOrigin-RevId: 237153884
-rw-r--r--mlir/include/mlir/Support/Status.h48
-rw-r--r--mlir/include/mlir/Transforms/LoopUtils.h47
-rw-r--r--mlir/lib/Transforms/LoopTiling.cpp10
-rw-r--r--mlir/lib/Transforms/LoopUnroll.cpp8
-rw-r--r--mlir/lib/Transforms/LoopUnrollAndJam.cpp27
-rw-r--r--mlir/lib/Transforms/PipelineDataTransfer.cpp2
-rw-r--r--mlir/lib/Transforms/Utils/LoopUtils.cpp51
7 files changed, 117 insertions, 76 deletions
diff --git a/mlir/include/mlir/Support/Status.h b/mlir/include/mlir/Support/Status.h
new file mode 100644
index 00000000000..365842a26db
--- /dev/null
+++ b/mlir/include/mlir/Support/Status.h
@@ -0,0 +1,48 @@
+//===- Status.h - Utilities for handling success/failure --------*- C++ -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+
+#ifndef MLIR_SUPPORT_STATUS_H
+#define MLIR_SUPPORT_STATUS_H
+
+#include "mlir/Support/LLVM.h"
+
+namespace mlir {
+
+// Values that can be used to signal success/failure. This should be used in
+// conjunction with the 'succeeded' and 'failed' functions below.
+struct Status {
+ enum ResultEnum { Success, Failure } value;
+ Status(ResultEnum v) : value(v) {}
+
+ /// Utility method to generate a success result.
+ static Status success() { return Success; }
+
+ /// Utility method to generate a failure result.
+ static Status failure() { return Failure; }
+};
+
+/// Utility function that returns true if the provided Status corresponds
+/// to a success value.
+inline bool succeeded(Status result) { return result.value == Status::Success; }
+
+/// Utility function that returns true if the provided Status corresponds
+/// to a failure value.
+inline bool failed(Status result) { return result.value == Status::Failure; }
+
+} // namespace mlir
+
+#endif // MLIR_SUPPORT_STATUS_H
diff --git a/mlir/include/mlir/Transforms/LoopUtils.h b/mlir/include/mlir/Transforms/LoopUtils.h
index 2bcf9779597..62c0b1e0f63 100644
--- a/mlir/include/mlir/Transforms/LoopUtils.h
+++ b/mlir/include/mlir/Transforms/LoopUtils.h
@@ -25,6 +25,7 @@
#define MLIR_TRANSFORMS_LOOP_UTILS_H
#include "mlir/Support/LLVM.h"
+#include "mlir/Support/Status.h"
namespace mlir {
class AffineMap;
@@ -34,39 +35,31 @@ class Function;
class FuncBuilder;
template <typename T> class OpPointer;
-// Values that can be used to signal success/failure. This can be implicitly
-// converted to/from boolean values, with false representing success and true
-// failure.
-struct LLVM_NODISCARD UtilResult {
- enum ResultEnum { Success, Failure } value;
- UtilResult(ResultEnum v) : value(v) {}
- operator bool() const { return value == Failure; }
-};
-
/// Unrolls this for instruction completely if the trip count is known to be
-/// constant. Returns false otherwise.
-bool loopUnrollFull(OpPointer<AffineForOp> forOp);
-/// Unrolls this for instruction by the specified unroll factor. Returns false
+/// constant.
+Status loopUnrollFull(OpPointer<AffineForOp> forOp);
+/// Unrolls this for instruction by the specified unroll factor. Returns failure
/// if the loop cannot be unrolled either due to restrictions or due to invalid
/// unroll factors.
-bool loopUnrollByFactor(OpPointer<AffineForOp> forOp, uint64_t unrollFactor);
+Status loopUnrollByFactor(OpPointer<AffineForOp> forOp, uint64_t unrollFactor);
/// Unrolls this loop by the specified unroll factor or its trip count,
/// whichever is lower.
-bool loopUnrollUpToFactor(OpPointer<AffineForOp> forOp, uint64_t unrollFactor);
+Status loopUnrollUpToFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollFactor);
-/// Unrolls and jams this loop by the specified factor. Returns true if the loop
-/// is successfully unroll-jammed.
-bool loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
- uint64_t unrollJamFactor);
+/// Unrolls and jams this loop by the specified factor. Returns success if the
+/// loop is successfully unroll-jammed.
+Status loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollJamFactor);
/// Unrolls and jams this loop by the specified factor or by the trip count (if
/// constant), whichever is lower.
-bool loopUnrollJamUpToFactor(OpPointer<AffineForOp> forOp,
- uint64_t unrollJamFactor);
+Status loopUnrollJamUpToFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollJamFactor);
/// Promotes the loop body of a AffineForOp to its containing block if the
-/// AffineForOp was known to have a single iteration. Returns false otherwise.
-bool promoteIfSingleIteration(OpPointer<AffineForOp> forOp);
+/// AffineForOp was known to have a single iteration.
+Status promoteIfSingleIteration(OpPointer<AffineForOp> forOp);
/// Promotes all single iteration AffineForOp's in the Function, i.e., moves
/// their body into the containing Block.
@@ -86,13 +79,15 @@ AffineMap getUnrolledLoopUpperBound(ConstOpPointer<AffineForOp> forOp,
/// Skew the instructions in the body of a 'for' instruction with the specified
/// instruction-wise shifts. The shifts are with respect to the original
/// execution order, and are multiplied by the loop 'step' before being applied.
-UtilResult instBodySkew(OpPointer<AffineForOp> forOp, ArrayRef<uint64_t> shifts,
- bool unrollPrologueEpilogue = false);
+LLVM_NODISCARD
+Status instBodySkew(OpPointer<AffineForOp> forOp, ArrayRef<uint64_t> shifts,
+ bool unrollPrologueEpilogue = false);
/// Tiles the specified band of perfectly nested loops creating tile-space loops
/// and intra-tile loops. A band is a contiguous set of loops.
-UtilResult tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
- ArrayRef<unsigned> tileSizes);
+LLVM_NODISCARD
+Status tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
+ ArrayRef<unsigned> tileSizes);
/// Performs loop interchange on 'forOpA' and 'forOpB'. Requires that 'forOpA'
/// and 'forOpB' are part of a perfectly nested sequence of loops.
diff --git a/mlir/lib/Transforms/LoopTiling.cpp b/mlir/lib/Transforms/LoopTiling.cpp
index e58de3bc136..7e345bf15fe 100644
--- a/mlir/lib/Transforms/LoopTiling.cpp
+++ b/mlir/lib/Transforms/LoopTiling.cpp
@@ -151,8 +151,8 @@ static void constructTiledIndexSetHyperRect(
/// Tiles the specified band of perfectly nested loops creating tile-space loops
/// and intra-tile loops. A band is a contiguous set of loops.
// TODO(bondhugula): handle non hyper-rectangular spaces.
-UtilResult mlir::tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
- ArrayRef<unsigned> tileSizes) {
+Status mlir::tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
+ ArrayRef<unsigned> tileSizes) {
assert(!band.empty());
assert(band.size() == tileSizes.size() && "Incorrect number of tile sizes");
@@ -215,7 +215,7 @@ UtilResult mlir::tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
if (!cst.isHyperRectangular(0, width)) {
rootAffineForOp->emitError("tiled code generation unimplemented for the"
"non-hyperrectangular case");
- return UtilResult::Failure;
+ return Status::failure();
}
constructTiledIndexSetHyperRect(origLoops, newLoops, tileSizes);
@@ -227,7 +227,7 @@ UtilResult mlir::tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
// Erase the old loop nest.
rootAffineForOp->erase();
- return UtilResult::Success;
+ return Status::success();
}
// Identify valid and profitable bands of loops to tile. This is currently just
@@ -265,7 +265,7 @@ void LoopTiling::runOnFunction() {
clTileSizes.begin() + std::min(clTileSizes.size(), band.size()),
tileSizes.begin());
- if (tileCodeGen(band, tileSizes))
+ if (failed(tileCodeGen(band, tileSizes)))
return signalPassFailure();
}
}
diff --git a/mlir/lib/Transforms/LoopUnroll.cpp b/mlir/lib/Transforms/LoopUnroll.cpp
index 40da2f63f62..5a20f99173e 100644
--- a/mlir/lib/Transforms/LoopUnroll.cpp
+++ b/mlir/lib/Transforms/LoopUnroll.cpp
@@ -80,8 +80,8 @@ struct LoopUnroll : public FunctionPass<LoopUnroll> {
void runOnFunction() override;
- /// Unroll this for inst. Returns false if nothing was done.
- bool runOnAffineForOp(OpPointer<AffineForOp> forOp);
+ /// Unroll this for inst. Returns failure if nothing was done.
+ Status runOnAffineForOp(OpPointer<AffineForOp> forOp);
static const unsigned kDefaultUnrollFactor = 4;
};
@@ -154,7 +154,7 @@ void LoopUnroll::runOnFunction() {
break;
bool unrolled = false;
for (auto forOp : loops)
- unrolled |= runOnAffineForOp(forOp);
+ unrolled |= succeeded(runOnAffineForOp(forOp));
if (!unrolled)
// Break out if nothing was unrolled.
break;
@@ -163,7 +163,7 @@ void LoopUnroll::runOnFunction() {
/// Unrolls a 'for' inst. Returns true if the loop was unrolled, false
/// otherwise. The default unroll factor is 4.
-bool LoopUnroll::runOnAffineForOp(OpPointer<AffineForOp> forOp) {
+Status LoopUnroll::runOnAffineForOp(OpPointer<AffineForOp> forOp) {
// Use the function callback if one was provided.
if (getUnrollFactor) {
return loopUnrollByFactor(forOp, getUnrollFactor(forOp));
diff --git a/mlir/lib/Transforms/LoopUnrollAndJam.cpp b/mlir/lib/Transforms/LoopUnrollAndJam.cpp
index 63fc451287b..8bc3a6f1e0c 100644
--- a/mlir/lib/Transforms/LoopUnrollAndJam.cpp
+++ b/mlir/lib/Transforms/LoopUnrollAndJam.cpp
@@ -78,7 +78,7 @@ struct LoopUnrollAndJam : public FunctionPass<LoopUnrollAndJam> {
: unrollJamFactor(unrollJamFactor) {}
void runOnFunction() override;
- bool runOnAffineForOp(OpPointer<AffineForOp> forOp);
+ Status runOnAffineForOp(OpPointer<AffineForOp> forOp);
};
} // end anonymous namespace
@@ -97,8 +97,8 @@ void LoopUnrollAndJam::runOnFunction() {
}
/// Unroll and jam a 'for' inst. Default unroll jam factor is
-/// kDefaultUnrollJamFactor. Return false if nothing was done.
-bool LoopUnrollAndJam::runOnAffineForOp(OpPointer<AffineForOp> forOp) {
+/// kDefaultUnrollJamFactor. Return failure if nothing was done.
+Status LoopUnrollAndJam::runOnAffineForOp(OpPointer<AffineForOp> forOp) {
// Unroll and jam by the factor that was passed if any.
if (unrollJamFactor.hasValue())
return loopUnrollJamByFactor(forOp, unrollJamFactor.getValue());
@@ -110,8 +110,8 @@ bool LoopUnrollAndJam::runOnAffineForOp(OpPointer<AffineForOp> forOp) {
return loopUnrollJamByFactor(forOp, kDefaultUnrollJamFactor);
}
-bool mlir::loopUnrollJamUpToFactor(OpPointer<AffineForOp> forOp,
- uint64_t unrollJamFactor) {
+Status mlir::loopUnrollJamUpToFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollJamFactor) {
Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
if (mayBeConstantTripCount.hasValue() &&
@@ -121,8 +121,8 @@ bool mlir::loopUnrollJamUpToFactor(OpPointer<AffineForOp> forOp,
}
/// Unrolls and jams this loop by the specified factor.
-bool mlir::loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
- uint64_t unrollJamFactor) {
+Status mlir::loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollJamFactor) {
// Gathers all maximal sub-blocks of instructions that do not themselves
// include a for inst (a instruction could have a descendant for inst though
// in its tree).
@@ -153,13 +153,13 @@ bool mlir::loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
assert(unrollJamFactor >= 1 && "unroll jam factor should be >= 1");
if (unrollJamFactor == 1 || forOp->getBody()->empty())
- return false;
+ return Status::failure();
Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
if (!mayBeConstantTripCount.hasValue() &&
getLargestDivisorOfTripCount(forOp) % unrollJamFactor != 0)
- return false;
+ return Status::failure();
auto lbMap = forOp->getLowerBoundMap();
auto ubMap = forOp->getUpperBoundMap();
@@ -169,18 +169,18 @@ bool mlir::loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
// do such unrolling for a Function would be to specialize the loop for the
// 'hotspot' case and unroll that hotspot.
if (lbMap.getNumResults() != 1 || ubMap.getNumResults() != 1)
- return false;
+ return Status::failure();
// Same operand list for lower and upper bound for now.
// TODO(bondhugula): handle bounds with different sets of operands.
if (!forOp->matchingBoundOperandList())
- return false;
+ return Status::failure();
// If the trip count is lower than the unroll jam factor, no unroll jam.
// TODO(bondhugula): option to specify cleanup loop unrolling.
if (mayBeConstantTripCount.hasValue() &&
mayBeConstantTripCount.getValue() < unrollJamFactor)
- return false;
+ return Status::failure();
auto *forInst = forOp->getInstruction();
@@ -241,8 +241,7 @@ bool mlir::loopUnrollJamByFactor(OpPointer<AffineForOp> forOp,
// Promote the loop body up if this has turned into a single iteration loop.
promoteIfSingleIteration(forOp);
-
- return true;
+ return Status::success();
}
static PassRegistration<LoopUnrollAndJam> pass("loop-unroll-jam",
diff --git a/mlir/lib/Transforms/PipelineDataTransfer.cpp b/mlir/lib/Transforms/PipelineDataTransfer.cpp
index 08115eddbe7..fa9c4dc0035 100644
--- a/mlir/lib/Transforms/PipelineDataTransfer.cpp
+++ b/mlir/lib/Transforms/PipelineDataTransfer.cpp
@@ -375,7 +375,7 @@ void PipelineDataTransfer::runOnAffineForOp(OpPointer<AffineForOp> forOp) {
return;
}
- if (instBodySkew(forOp, shifts)) {
+ if (failed(instBodySkew(forOp, shifts))) {
LLVM_DEBUG(llvm::dbgs() << "inst body skewing failed - unexpected\n";);
return;
}
diff --git a/mlir/lib/Transforms/Utils/LoopUtils.cpp b/mlir/lib/Transforms/Utils/LoopUtils.cpp
index da5169342ca..412b468b60d 100644
--- a/mlir/lib/Transforms/Utils/LoopUtils.cpp
+++ b/mlir/lib/Transforms/Utils/LoopUtils.cpp
@@ -89,16 +89,16 @@ AffineMap mlir::getCleanupLoopLowerBound(ConstOpPointer<AffineForOp> forOp,
}
/// Promotes the loop body of a forOp to its containing block if the forOp
-/// was known to have a single iteration. Returns false otherwise.
+/// was known to have a single iteration.
// TODO(bondhugula): extend this for arbitrary affine bounds.
-bool mlir::promoteIfSingleIteration(OpPointer<AffineForOp> forOp) {
+Status mlir::promoteIfSingleIteration(OpPointer<AffineForOp> forOp) {
Optional<uint64_t> tripCount = getConstantTripCount(forOp);
if (!tripCount.hasValue() || tripCount.getValue() != 1)
- return false;
+ return Status::failure();
// TODO(mlir-team): there is no builder for a max.
if (forOp->getLowerBoundMap().getNumResults() != 1)
- return false;
+ return Status::failure();
// Replaces all IV uses to its single iteration value.
auto *iv = forOp->getInductionVar();
@@ -129,7 +129,7 @@ bool mlir::promoteIfSingleIteration(OpPointer<AffineForOp> forOp) {
block->getInstructions().splice(Block::iterator(forInst),
forOp->getBody()->getInstructions());
forOp->erase();
- return true;
+ return Status::success();
}
/// Promotes all single iteration for inst's in the Function, i.e., moves
@@ -191,7 +191,7 @@ generateLoop(AffineMap lbMap, AffineMap ubMap,
loopChunk->getBody()->push_back(inst->clone(operandMap, b->getContext()));
}
}
- if (promoteIfSingleIteration(loopChunk))
+ if (succeeded(promoteIfSingleIteration(loopChunk)))
return OpPointer<AffineForOp>();
return loopChunk;
}
@@ -211,11 +211,11 @@ generateLoop(AffineMap lbMap, AffineMap ubMap,
// asserts preservation of SSA dominance. A check for that as well as that for
// memory-based depedence preservation check rests with the users of this
// method.
-UtilResult mlir::instBodySkew(OpPointer<AffineForOp> forOp,
- ArrayRef<uint64_t> shifts,
- bool unrollPrologueEpilogue) {
+Status mlir::instBodySkew(OpPointer<AffineForOp> forOp,
+ ArrayRef<uint64_t> shifts,
+ bool unrollPrologueEpilogue) {
if (forOp->getBody()->empty())
- return UtilResult::Success;
+ return Status::success();
// If the trip counts aren't constant, we would need versioning and
// conditional guards (or context information to prevent such versioning). The
@@ -224,7 +224,7 @@ UtilResult mlir::instBodySkew(OpPointer<AffineForOp> forOp,
auto mayBeConstTripCount = getConstantTripCount(forOp);
if (!mayBeConstTripCount.hasValue()) {
LLVM_DEBUG(forOp->emitNote("non-constant trip count loop not handled"));
- return UtilResult::Success;
+ return Status::success();
}
uint64_t tripCount = mayBeConstTripCount.getValue();
@@ -243,7 +243,7 @@ UtilResult mlir::instBodySkew(OpPointer<AffineForOp> forOp,
// Such large shifts are not the typical use case.
if (maxShift >= numChildInsts) {
forOp->emitWarning("not shifting because shifts are unrealistically large");
- return UtilResult::Success;
+ return Status::success();
}
// An array of instruction groups sorted by shift amount; each group has all
@@ -329,11 +329,11 @@ UtilResult mlir::instBodySkew(OpPointer<AffineForOp> forOp,
epilogue->getInstruction() != prologue->getInstruction())
loopUnrollFull(epilogue);
- return UtilResult::Success;
+ return Status::success();
}
/// Unrolls this loop completely.
-bool mlir::loopUnrollFull(OpPointer<AffineForOp> forOp) {
+Status mlir::loopUnrollFull(OpPointer<AffineForOp> forOp) {
Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
if (mayBeConstantTripCount.hasValue()) {
uint64_t tripCount = mayBeConstantTripCount.getValue();
@@ -342,13 +342,13 @@ bool mlir::loopUnrollFull(OpPointer<AffineForOp> forOp) {
}
return loopUnrollByFactor(forOp, tripCount);
}
- return false;
+ return Status::failure();
}
/// Unrolls and jams this loop by the specified factor or by the trip count (if
/// constant) whichever is lower.
-bool mlir::loopUnrollUpToFactor(OpPointer<AffineForOp> forOp,
- uint64_t unrollFactor) {
+Status mlir::loopUnrollUpToFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollFactor) {
Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
if (mayBeConstantTripCount.hasValue() &&
@@ -357,17 +357,17 @@ bool mlir::loopUnrollUpToFactor(OpPointer<AffineForOp> forOp,
return loopUnrollByFactor(forOp, unrollFactor);
}
-/// Unrolls this loop by the specified factor. Returns true if the loop
+/// Unrolls this loop by the specified factor. Returns success if the loop
/// is successfully unrolled.
-bool mlir::loopUnrollByFactor(OpPointer<AffineForOp> forOp,
- uint64_t unrollFactor) {
+Status mlir::loopUnrollByFactor(OpPointer<AffineForOp> forOp,
+ uint64_t unrollFactor) {
assert(unrollFactor >= 1 && "unroll factor should be >= 1");
if (unrollFactor == 1)
return promoteIfSingleIteration(forOp);
if (forOp->getBody()->empty())
- return false;
+ return Status::failure();
auto lbMap = forOp->getLowerBoundMap();
auto ubMap = forOp->getUpperBoundMap();
@@ -377,12 +377,12 @@ bool mlir::loopUnrollByFactor(OpPointer<AffineForOp> forOp,
// do such unrolling for a Function would be to specialize the loop for the
// 'hotspot' case and unroll that hotspot.
if (lbMap.getNumResults() != 1 || ubMap.getNumResults() != 1)
- return false;
+ return Status::failure();
// Same operand list for lower and upper bound for now.
// TODO(bondhugula): handle bounds with different operand lists.
if (!forOp->matchingBoundOperandList())
- return false;
+ return Status::failure();
Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
@@ -390,7 +390,7 @@ bool mlir::loopUnrollByFactor(OpPointer<AffineForOp> forOp,
// TODO(bondhugula): option to specify cleanup loop unrolling.
if (mayBeConstantTripCount.hasValue() &&
mayBeConstantTripCount.getValue() < unrollFactor)
- return false;
+ return Status::failure();
// Generate the cleanup loop if trip count isn't a multiple of unrollFactor.
Instruction *forInst = forOp->getInstruction();
@@ -451,8 +451,7 @@ bool mlir::loopUnrollByFactor(OpPointer<AffineForOp> forOp,
// Promote the loop body up if this has turned into a single iteration loop.
promoteIfSingleIteration(forOp);
-
- return true;
+ return Status::success();
}
/// Performs loop interchange on 'forOpA' and 'forOpB', where 'forOpB' is
OpenPOWER on IntegriCloud