OpPointer: replace conversion operator to Operation* to OpType*.

The implementation of OpPointer<OpType> provides an implicit conversion to
Operation *, but not to the underlying OpType *.  This has led to
awkward-looking code when an OpPointer needs to be passed to a function
accepting an OpType *.  For example,

    if (auto someOp = genericOp.dyn_cast<OpType>())
      someFunction(&*someOp);

where "&*" makes it harder to read.  Arguably, one does not want to spell out
OpPointer<OpType> in the line with dyn_cast.  More generally, OpPointer is now
being used as an owning pointer to OpType rather than to operation.

Replace the implicit conversion to Operation* with the conversion to OpType*
taking into account const-ness of the type.  An Operation* can be obtained from
an OpType with a simple call.  Since an instance of OpPointer owns the OpType
value, the pointer to it is never null.  However, the OpType value may not be
associated with any Operation*.  In this case, return nullptr when conversion
is attempted to maintain consistency with the existing null checks.

PiperOrigin-RevId: 224368103
This commit is contained in:
Alex Zinenko
2018-12-06 10:56:21 -08:00
committed by jpienaar
parent 73fc0223e4
commit 513d6d896c
3 changed files with 18 additions and 9 deletions

View File

@@ -70,9 +70,12 @@ public:
operator bool() const { return value.getOperation(); }
/// OpPointer can always be implicitly converted to Operation*.
operator Operation *() const {
return const_cast<Operation *>(value.getOperation());
/// OpPointer can be implicitly converted to OpType*.
/// Return `nullptr` if there is no associated Operation*.
operator OpType *() {
if (!value.getOperation())
return nullptr;
return &value;
}
/// If the OpType operation includes the OneResult trait, then OpPointer can
@@ -103,8 +106,13 @@ public:
/// Return true if non-null.
operator bool() const { return value.getOperation(); }
/// ConstOpPointer can always be implicitly converted to const Operation*.
operator const Operation *() const { return value.getOperation(); }
/// ConstOpPointer can always be implicitly converted to const OpType*.
/// Return `nullptr` if there is no associated Operation*.
operator const OpType *() const {
if (!value.getOperation())
return nullptr;
return &value;
}
/// If the OpType operation includes the OneResult trait, then OpPointer can
/// be implicitly converted to an const SSAValue*. This yields the value of

View File

@@ -230,7 +230,7 @@ public:
template <typename OpTy, typename... Args>
void replaceOpWithNewOp(Operation *op, Args... args) {
auto newOp = create<OpTy>(op->getLoc(), args...);
replaceOpWithResultsOfAnotherOp(op, newOp, {});
replaceOpWithResultsOfAnotherOp(op, newOp->getOperation(), {});
}
/// Replaces the result op with a new op that is created without verification.
@@ -241,7 +241,8 @@ public:
ArrayRef<SSAValue *> valuesToRemoveIfDead,
Args... args) {
auto newOp = create<OpTy>(op->getLoc(), args...);
replaceOpWithResultsOfAnotherOp(op, newOp, valuesToRemoveIfDead);
replaceOpWithResultsOfAnotherOp(op, newOp->getOperation(),
valuesToRemoveIfDead);
}
/// This method is used as the final notification hook for patterns that end

View File

@@ -414,11 +414,11 @@ static bool instantiateMaterialization(Statement *stmt,
MLFuncBuilder b(stmt);
auto *opStmt = cast<OperationStmt>(stmt);
if (auto write = opStmt->dyn_cast<VectorTransferWriteOp>()) {
instantiate(&b, &*write, state->hwVectorType, state->hwVectorInstance,
instantiate(&b, write, state->hwVectorType, state->hwVectorInstance,
state->substitutionsMap);
return false;
} else if (auto read = opStmt->dyn_cast<VectorTransferReadOp>()) {
auto *clone = instantiate(&b, &*read, state->hwVectorType,
auto *clone = instantiate(&b, read, state->hwVectorType,
state->hwVectorInstance, state->substitutionsMap);
state->substitutionsMap->insert(std::make_pair(
cast<MLValue>(read->getResult()), cast<MLValue>(clone->getResult(0))));