diff options
| author | River Riddle <riverriddle@google.com> | 2019-03-06 17:37:14 -0800 |
|---|---|---|
| committer | jpienaar <jpienaar@google.com> | 2019-03-29 17:04:19 -0700 |
| commit | ba6fdc8b01403d0c83454019c81a38b84966fe9a (patch) | |
| tree | e1d055a55d368e4647bb9850c8801dae2544a644 | |
| parent | 157e3cdb1946121210d1b9f52d9739a918a92e6d (diff) | |
| download | bcm5719-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.h | 48 | ||||
| -rw-r--r-- | mlir/include/mlir/Transforms/LoopUtils.h | 47 | ||||
| -rw-r--r-- | mlir/lib/Transforms/LoopTiling.cpp | 10 | ||||
| -rw-r--r-- | mlir/lib/Transforms/LoopUnroll.cpp | 8 | ||||
| -rw-r--r-- | mlir/lib/Transforms/LoopUnrollAndJam.cpp | 27 | ||||
| -rw-r--r-- | mlir/lib/Transforms/PipelineDataTransfer.cpp | 2 | ||||
| -rw-r--r-- | mlir/lib/Transforms/Utils/LoopUtils.cpp | 51 |
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 |

