From c6e4aa9ba79e8043d5f8d0bd90da297849bebe2f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 26 Sep 2018 21:18:42 -0700 Subject: [PATCH] Fix b/116749799, an issue where the ZeroResult trait's verifier hook left in an old form. Upgrade it, and move all the trait verifier implementations consistently out of line to reduce template bloat. PiperOrigin-RevId: 214718242 --- mlir/include/mlir/IR/OpDefinition.h | 62 +++++++++++++---------------- mlir/lib/IR/Operation.cpp | 52 ++++++++++++++++++++++++ mlir/test/IR/invalid-ops.mlir | 7 ++++ 3 files changed, 86 insertions(+), 35 deletions(-) diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h index 6a08bc7e3f9d..8f0c42d607a0 100644 --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -214,6 +214,23 @@ public: namespace OpTrait { +// These functions are out-of-line implementations of the methods in the +// corresponding trait classes. This avoids them being template +// instantiated/duplicated. +namespace impl { +bool verifyZeroOperands(const Operation *op); +bool verifyOneOperand(const Operation *op); +bool verifyNOperands(const Operation *op, unsigned numOperands); +bool verifyAtLeastNOperands(const Operation *op, unsigned numOperands); +bool verifyZeroResult(const Operation *op); +bool verifyOneResult(const Operation *op); +bool verifyNResults(const Operation *op, unsigned numOperands); +bool verifyAtLeastNResults(const Operation *op, unsigned numOperands); +bool verifySameOperandsAndResult(const Operation *op); +bool verifyResultsAreFloatLike(const Operation *op); +bool verifyResultsAreIntegerLike(const Operation *op); +} // namespace impl + /// Helper class for implementing traits. Clients are not expected to interact /// with this directly, so its members are all protected. template class TraitType> @@ -245,9 +262,7 @@ template class ZeroOperands : public TraitBase { public: static bool verifyTrait(const Operation *op) { - if (op->getNumOperands() != 0) - return op->emitOpError("requires zero operands"); - return false; + return impl::verifyZeroOperands(op); } private: @@ -272,9 +287,7 @@ public: } static bool verifyTrait(const Operation *op) { - if (op->getNumOperands() != 1) - return op->emitOpError("requires a single operand"); - return false; + return impl::verifyOneOperand(op); } }; @@ -301,9 +314,7 @@ public: } static bool verifyTrait(const Operation *op) { - if (op->getNumOperands() != N) - return op->emitOpError("expected " + Twine(N) + " operands"); - return false; + return impl::verifyNOperands(op, N); } }; }; @@ -358,9 +369,7 @@ public: } static bool verifyTrait(const Operation *op) { - if (op->getNumOperands() < N) - return op->emitOpError("expected " + Twine(N) + " or more operands"); - return false; + return impl::verifyAtLeastNOperands(op, N); } }; }; @@ -414,10 +423,8 @@ public: template class ZeroResult : public TraitBase { public: - static const char *verifyTrait(const Operation *op) { - if (op->getNumResults() != 0) - return "requires zero results."; - return nullptr; + static bool verifyTrait(const Operation *op) { + return impl::verifyZeroResult(op); } }; @@ -433,10 +440,8 @@ public: Type *getType() const { return getResult()->getType(); } - static const char *verifyTrait(const Operation *op) { - if (op->getNumResults() != 1) - return "requires one result"; - return nullptr; + static bool verifyTrait(const Operation *op) { + return impl::verifyOneResult(op); } /// This hook implements a constant folder for this operation. If the @@ -469,9 +474,7 @@ public: Type *getType(unsigned i) const { return getResult(i)->getType(); } static bool verifyTrait(const Operation *op) { - if (op->getNumResults() != N) - return op->emitOpError("expected " + Twine(N) + " results"); - return false; + return impl::verifyNResults(op, N); } }; }; @@ -497,9 +500,7 @@ public: Type *getType(unsigned i) const { return getResult(i)->getType(); } static bool verifyTrait(const Operation *op) { - if (op->getNumResults() < N) - return op->emitOpError("expected " + Twine(N) + " or more results"); - return false; + return impl::verifyAtLeastNResults(op, N); } }; }; @@ -524,15 +525,6 @@ public: } }; -// These functions are out-of-line implementations of the methods in the -// corresponding trait classes. This avoids them being template -// instantiated/duplicated. -namespace impl { -bool verifySameOperandsAndResult(const Operation *op); -bool verifyResultsAreFloatLike(const Operation *op); -bool verifyResultsAreIntegerLike(const Operation *op); -} // namespace impl - /// This class provides verification for ops that are known to have the same /// operand and result type. template diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp index d1f92b5b1785..81a6f3f6d34e 100644 --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -226,6 +226,58 @@ void OpState::emitNote(const Twine &message) const { // Op Trait implementations //===----------------------------------------------------------------------===// +bool OpTrait::impl::verifyZeroOperands(const Operation *op) { + if (op->getNumOperands() != 0) + return op->emitOpError("requires zero operands"); + return false; +} + +bool OpTrait::impl::verifyOneOperand(const Operation *op) { + if (op->getNumOperands() != 1) + return op->emitOpError("requires a single operand"); + return false; +} + +bool OpTrait::impl::verifyNOperands(const Operation *op, unsigned numOperands) { + if (op->getNumOperands() != numOperands) + return op->emitOpError("expected " + Twine(numOperands) + " operands"); + return false; +} + +bool OpTrait::impl::verifyAtLeastNOperands(const Operation *op, + unsigned numOperands) { + if (op->getNumOperands() < numOperands) + return op->emitOpError("expected " + Twine(numOperands) + + " or more operands"); + return false; +} + +bool OpTrait::impl::verifyZeroResult(const Operation *op) { + if (op->getNumResults() != 0) + return op->emitOpError("requires zero results"); + return false; +} + +bool OpTrait::impl::verifyOneResult(const Operation *op) { + if (op->getNumResults() != 1) + return op->emitOpError("requires one result"); + return false; +} + +bool OpTrait::impl::verifyNResults(const Operation *op, unsigned numOperands) { + if (op->getNumResults() != numOperands) + return op->emitOpError("expected " + Twine(numOperands) + " results"); + return false; +} + +bool OpTrait::impl::verifyAtLeastNResults(const Operation *op, + unsigned numOperands) { + if (op->getNumResults() < numOperands) + return op->emitOpError("expected " + Twine(numOperands) + + " or more results"); + return false; +} + bool OpTrait::impl::verifySameOperandsAndResult(const Operation *op) { auto *type = op->getResult(0)->getType(); for (unsigned i = 1, e = op->getNumResults(); i < e; ++i) { diff --git a/mlir/test/IR/invalid-ops.mlir b/mlir/test/IR/invalid-ops.mlir index 94e0ba69511a..cb5ca5cbe424 100644 --- a/mlir/test/IR/invalid-ops.mlir +++ b/mlir/test/IR/invalid-ops.mlir @@ -101,6 +101,13 @@ bb0: // ----- +mlfunc @test_store_zero_results2(%x: i32, %p: memref) { + "store"(%x,%p) : (i32, memref) -> i32 // expected-error {{'store' op requires zero results}} + return +} + +// ----- + cfgfunc @test_alloc_memref_map_rank_mismatch() { bb0: %0 = alloc() : memref<1024x64xf32, (d0) -> (d0), 1> // expected-error {{affine map dimension count must equal memref rank}}