Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
mlir/lib/Transforms/Utils/DialectConversion.cpp
Show First 20 Lines • Show All 845 Lines • ▼ Show 20 Lines | |||||||||||||||||||||||
} | } | ||||||||||||||||||||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||||||||||||||||||
// ConversionPatternRewriterImpl | // ConversionPatternRewriterImpl | ||||||||||||||||||||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||||||||||||||||||
namespace mlir { | namespace mlir { | ||||||||||||||||||||||
namespace detail { | namespace detail { | ||||||||||||||||||||||
struct ConversionPatternRewriterImpl { | struct ConversionPatternRewriterImpl { | ||||||||||||||||||||||
ConversionPatternRewriterImpl(PatternRewriter &rewriter) | explicit ConversionPatternRewriterImpl(PatternRewriter &rewriter) | ||||||||||||||||||||||
: argConverter(rewriter, unresolvedMaterializations) {} | : argConverter(rewriter, unresolvedMaterializations), | ||||||||||||||||||||||
notifyCallback(nullptr) {} | |||||||||||||||||||||||
/// Cleanup and destroy any generated rewrite operations. This method is | /// Cleanup and destroy any generated rewrite operations. This method is | ||||||||||||||||||||||
/// invoked when the conversion process fails. | /// invoked when the conversion process fails. | ||||||||||||||||||||||
void discardRewrites(); | void discardRewrites(); | ||||||||||||||||||||||
/// Apply all requested operation rewrites. This method is invoked when the | /// Apply all requested operation rewrites. This method is invoked when the | ||||||||||||||||||||||
/// conversion process succeeds. | /// conversion process succeeds. | ||||||||||||||||||||||
void applyRewrites(); | void applyRewrites(); | ||||||||||||||||||||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | struct ConversionPatternRewriterImpl { | ||||||||||||||||||||||
/// with values with different result types than the original operation, e.g. | /// with values with different result types than the original operation, e.g. | ||||||||||||||||||||||
/// 1->N conversion of some kind. | /// 1->N conversion of some kind. | ||||||||||||||||||||||
SmallVector<unsigned, 4> operationsWithChangedResults; | SmallVector<unsigned, 4> operationsWithChangedResults; | ||||||||||||||||||||||
/// The current type converter, or nullptr if no type converter is currently | /// The current type converter, or nullptr if no type converter is currently | ||||||||||||||||||||||
/// active. | /// active. | ||||||||||||||||||||||
TypeConverter *currentTypeConverter = nullptr; | TypeConverter *currentTypeConverter = nullptr; | ||||||||||||||||||||||
/// This allows the user to collect the match failure message. | |||||||||||||||||||||||
function_ref<void(Diagnostic &)> notifyCallback; | |||||||||||||||||||||||
#ifndef NDEBUG | #ifndef NDEBUG | ||||||||||||||||||||||
/// A set of operations that have pending updates. This tracking isn't | /// A set of operations that have pending updates. This tracking isn't | ||||||||||||||||||||||
/// strictly necessary, and is thus only active during debug builds for extra | /// strictly necessary, and is thus only active during debug builds for extra | ||||||||||||||||||||||
/// verification. | /// verification. | ||||||||||||||||||||||
SmallPtrSet<Operation *, 1> pendingRootUpdates; | SmallPtrSet<Operation *, 1> pendingRootUpdates; | ||||||||||||||||||||||
/// A logger used to emit diagnostics during the conversion process. | /// A logger used to emit diagnostics during the conversion process. | ||||||||||||||||||||||
llvm::ScopedPrinter logger{llvm::dbgs()}; | llvm::ScopedPrinter logger{llvm::dbgs()}; | ||||||||||||||||||||||
▲ Show 20 Lines • Show All 451 Lines • ▼ Show 20 Lines | void ConversionPatternRewriterImpl::notifyRegionWasClonedBefore( | ||||||||||||||||||||||
// This original region has already had its conversion set computed, so there | // This original region has already had its conversion set computed, so there | ||||||||||||||||||||||
// shouldn't be any new failures. | // shouldn't be any new failures. | ||||||||||||||||||||||
(void)result; | (void)result; | ||||||||||||||||||||||
assert(succeeded(result) && "expected region to have no unreachable blocks"); | assert(succeeded(result) && "expected region to have no unreachable blocks"); | ||||||||||||||||||||||
} | } | ||||||||||||||||||||||
LogicalResult ConversionPatternRewriterImpl::notifyMatchFailure( | LogicalResult ConversionPatternRewriterImpl::notifyMatchFailure( | ||||||||||||||||||||||
Location loc, function_ref<void(Diagnostic &)> reasonCallback) { | Location loc, function_ref<void(Diagnostic &)> reasonCallback) { | ||||||||||||||||||||||
LLVM_DEBUG({ | LLVM_DEBUG({ | ||||||||||||||||||||||
rriddle: This isn't the same as LLVM_DEBUG. LLVM_DEBUG also handles checking if the current debug mode… | |||||||||||||||||||||||
Reverted back to use LLVM_DEBUG I think that's enough for the initial support Chia-hungDuan: Reverted back to use LLVM_DEBUG I think that's enough for the initial support | |||||||||||||||||||||||
Diagnostic diag(loc, DiagnosticSeverity::Remark); | Diagnostic diag(loc, DiagnosticSeverity::Remark); | ||||||||||||||||||||||
reasonCallback(diag); | reasonCallback(diag); | ||||||||||||||||||||||
logger.startLine() << "** Failure : " << diag.str() << "\n"; | logger.startLine() << "** Failure : " << diag.str() << "\n"; | ||||||||||||||||||||||
if (notifyCallback) | |||||||||||||||||||||||
notifyCallback(diag); | |||||||||||||||||||||||
}); | }); | ||||||||||||||||||||||
return failure(); | return failure(); | ||||||||||||||||||||||
} | } | ||||||||||||||||||||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||||||||||||||||||
// ConversionPatternRewriter | // ConversionPatternRewriter | ||||||||||||||||||||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||||||||||||||||||
ConversionPatternRewriter::ConversionPatternRewriter(MLIRContext *ctx) | ConversionPatternRewriter::ConversionPatternRewriter(MLIRContext *ctx) | ||||||||||||||||||||||
: PatternRewriter(ctx), | : PatternRewriter(ctx), | ||||||||||||||||||||||
impl(new detail::ConversionPatternRewriterImpl(*this)) {} | impl(new detail::ConversionPatternRewriterImpl(*this)) {} | ||||||||||||||||||||||
ConversionPatternRewriter::~ConversionPatternRewriter() {} | ConversionPatternRewriter::~ConversionPatternRewriter() {} | ||||||||||||||||||||||
void ConversionPatternRewriter::replaceOpWithIf( | void ConversionPatternRewriter::replaceOpWithIf( | ||||||||||||||||||||||
Operation *op, ValueRange newValues, bool *allUsesReplaced, | Operation *op, ValueRange newValues, bool *allUsesReplaced, | ||||||||||||||||||||||
llvm::unique_function<bool(OpOperand &) const> functor) { | llvm::unique_function<bool(OpOperand &) const> functor) { | ||||||||||||||||||||||
Not Done ReplyInline Actions
nit: I would just inline all of these into the class. rriddle: nit: I would just inline all of these into the class. | |||||||||||||||||||||||
// TODO: To support this we will need to rework a bit of how replacements are | // TODO: To support this we will need to rework a bit of how replacements are | ||||||||||||||||||||||
// tracked, given that this isn't guranteed to replace all of the uses of an | // tracked, given that this isn't guranteed to replace all of the uses of an | ||||||||||||||||||||||
// operation. The main change is that now an operation can be replaced | // operation. The main change is that now an operation can be replaced | ||||||||||||||||||||||
// multiple times, in parts. The current "set" based tracking is mainly useful | // multiple times, in parts. The current "set" based tracking is mainly useful | ||||||||||||||||||||||
// for tracking if a replaced operation should be ignored, i.e. if all of the | // for tracking if a replaced operation should be ignored, i.e. if all of the | ||||||||||||||||||||||
// uses will be replaced. | // uses will be replaced. | ||||||||||||||||||||||
llvm_unreachable( | llvm_unreachable( | ||||||||||||||||||||||
"replaceOpWithIf is currently not supported by DialectConversion"); | "replaceOpWithIf is currently not supported by DialectConversion"); | ||||||||||||||||||||||
▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | OperationLegalizer::legalizeWithPattern(Operation *op, | ||||||||||||||||||||||
// Functor that returns if the given pattern may be applied. | // Functor that returns if the given pattern may be applied. | ||||||||||||||||||||||
auto canApply = [&](const Pattern &pattern) { | auto canApply = [&](const Pattern &pattern) { | ||||||||||||||||||||||
return canApplyPattern(op, pattern, rewriter); | return canApplyPattern(op, pattern, rewriter); | ||||||||||||||||||||||
}; | }; | ||||||||||||||||||||||
// Functor that cleans up the rewriter state after a pattern failed to match. | // Functor that cleans up the rewriter state after a pattern failed to match. | ||||||||||||||||||||||
RewriterState curState = rewriterImpl.getCurrentState(); | RewriterState curState = rewriterImpl.getCurrentState(); | ||||||||||||||||||||||
auto onFailure = [&](const Pattern &pattern) { | auto onFailure = [&](const Pattern &pattern) { | ||||||||||||||||||||||
LLVM_DEBUG(logFailure(rewriterImpl.logger, "pattern failed to match")); | LLVM_DEBUG({ | ||||||||||||||||||||||
logFailure(rewriterImpl.logger, "pattern failed to match"); | |||||||||||||||||||||||
if (rewriterImpl.notifyCallback) { | |||||||||||||||||||||||
Diagnostic diag(op->getLoc(), DiagnosticSeverity::Remark); | |||||||||||||||||||||||
diag << "Failed to apply pattern \"" << pattern.getDebugName() | |||||||||||||||||||||||
<< "\" on op:\n" | |||||||||||||||||||||||
<< *op; | |||||||||||||||||||||||
rewriterImpl.notifyCallback(diag); | |||||||||||||||||||||||
Not Done ReplyInline ActionsWhat does the pattern debug log output look like with this? rriddle: What does the pattern debug log output look like with this? | |||||||||||||||||||||||
As you mentioned, the curly brackets may have little problem. Added a new line for output. Now it looks like Failed to apply pattern "(anonymous namespace)::TestRegionRewriteBlockMovement" on op: "test.region"() ( { ^bb0(%arg0: i64): // no predecessors br ^bb1(%arg0 : i64) ^bb1(%0: i64): // pred: ^bb0 "test.invalid"(%0) : (i64) -> () }) {legalizer.erase_old_blocks, legalizer.should_clone} : () -> () Chia-hungDuan: As you mentioned, the curly brackets may have little problem. Added a new line for output. Now… | |||||||||||||||||||||||
} | |||||||||||||||||||||||
}); | |||||||||||||||||||||||
rewriterImpl.resetState(curState); | rewriterImpl.resetState(curState); | ||||||||||||||||||||||
appliedPatterns.erase(&pattern); | appliedPatterns.erase(&pattern); | ||||||||||||||||||||||
}; | }; | ||||||||||||||||||||||
// Functor that performs additional legalization when a pattern is | // Functor that performs additional legalization when a pattern is | ||||||||||||||||||||||
// successfully applied. | // successfully applied. | ||||||||||||||||||||||
auto onSuccess = [&](const Pattern &pattern) { | auto onSuccess = [&](const Pattern &pattern) { | ||||||||||||||||||||||
auto result = legalizePatternResult(op, pattern, rewriter, curState); | auto result = legalizePatternResult(op, pattern, rewriter, curState); | ||||||||||||||||||||||
▲ Show 20 Lines • Show All 367 Lines • ▼ Show 20 Lines | |||||||||||||||||||||||
struct OperationConverter { | struct OperationConverter { | ||||||||||||||||||||||
explicit OperationConverter(ConversionTarget &target, | explicit OperationConverter(ConversionTarget &target, | ||||||||||||||||||||||
const FrozenRewritePatternSet &patterns, | const FrozenRewritePatternSet &patterns, | ||||||||||||||||||||||
OpConversionMode mode, | OpConversionMode mode, | ||||||||||||||||||||||
DenseSet<Operation *> *trackedOps = nullptr) | DenseSet<Operation *> *trackedOps = nullptr) | ||||||||||||||||||||||
: opLegalizer(target, patterns), mode(mode), trackedOps(trackedOps) {} | : opLegalizer(target, patterns), mode(mode), trackedOps(trackedOps) {} | ||||||||||||||||||||||
/// Converts the given operations to the conversion target. | /// Converts the given operations to the conversion target. | ||||||||||||||||||||||
LogicalResult convertOperations(ArrayRef<Operation *> ops); | LogicalResult | ||||||||||||||||||||||
convertOperations(ArrayRef<Operation *> ops, | |||||||||||||||||||||||
function_ref<void(Diagnostic &)> notifyCallback = nullptr); | |||||||||||||||||||||||
private: | private: | ||||||||||||||||||||||
/// Converts an operation with the given rewriter. | /// Converts an operation with the given rewriter. | ||||||||||||||||||||||
LogicalResult convert(ConversionPatternRewriter &rewriter, Operation *op); | LogicalResult convert(ConversionPatternRewriter &rewriter, Operation *op); | ||||||||||||||||||||||
/// This method is called after the conversion process to legalize any | /// This method is called after the conversion process to legalize any | ||||||||||||||||||||||
/// remaining artifacts and complete the conversion. | /// remaining artifacts and complete the conversion. | ||||||||||||||||||||||
LogicalResult finalize(ConversionPatternRewriter &rewriter); | LogicalResult finalize(ConversionPatternRewriter &rewriter); | ||||||||||||||||||||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | if (failed(opLegalizer.legalize(op, rewriter))) { | ||||||||||||||||||||||
// Analysis conversions don't fail if any operations fail to legalize, | // Analysis conversions don't fail if any operations fail to legalize, | ||||||||||||||||||||||
// they are only interested in the operations that were successfully | // they are only interested in the operations that were successfully | ||||||||||||||||||||||
// legalized. | // legalized. | ||||||||||||||||||||||
trackedOps->insert(op); | trackedOps->insert(op); | ||||||||||||||||||||||
} | } | ||||||||||||||||||||||
return success(); | return success(); | ||||||||||||||||||||||
} | } | ||||||||||||||||||||||
LogicalResult OperationConverter::convertOperations(ArrayRef<Operation *> ops) { | LogicalResult OperationConverter::convertOperations( | ||||||||||||||||||||||
ArrayRef<Operation *> ops, | |||||||||||||||||||||||
function_ref<void(Diagnostic &)> notifyCallback) { | |||||||||||||||||||||||
if (ops.empty()) | if (ops.empty()) | ||||||||||||||||||||||
return success(); | return success(); | ||||||||||||||||||||||
ConversionTarget &target = opLegalizer.getTarget(); | ConversionTarget &target = opLegalizer.getTarget(); | ||||||||||||||||||||||
// Compute the set of operations and blocks to convert. | // Compute the set of operations and blocks to convert. | ||||||||||||||||||||||
SmallVector<Operation *> toConvert; | SmallVector<Operation *> toConvert; | ||||||||||||||||||||||
for (auto *op : ops) { | for (auto *op : ops) { | ||||||||||||||||||||||
toConvert.emplace_back(op); | toConvert.emplace_back(op); | ||||||||||||||||||||||
for (auto ®ion : op->getRegions()) | for (auto ®ion : op->getRegions()) | ||||||||||||||||||||||
if (failed(computeConversionSet(region.getBlocks(), region.getLoc(), | if (failed(computeConversionSet(region.getBlocks(), region.getLoc(), | ||||||||||||||||||||||
toConvert, &target))) | toConvert, &target))) | ||||||||||||||||||||||
return failure(); | return failure(); | ||||||||||||||||||||||
} | } | ||||||||||||||||||||||
// Convert each operation and discard rewrites on failure. | // Convert each operation and discard rewrites on failure. | ||||||||||||||||||||||
ConversionPatternRewriter rewriter(ops.front()->getContext()); | ConversionPatternRewriter rewriter(ops.front()->getContext()); | ||||||||||||||||||||||
ConversionPatternRewriterImpl &rewriterImpl = rewriter.getImpl(); | ConversionPatternRewriterImpl &rewriterImpl = rewriter.getImpl(); | ||||||||||||||||||||||
rewriterImpl.notifyCallback = notifyCallback; | |||||||||||||||||||||||
for (auto *op : toConvert) | for (auto *op : toConvert) | ||||||||||||||||||||||
if (failed(convert(rewriter, op))) | if (failed(convert(rewriter, op))) | ||||||||||||||||||||||
return rewriterImpl.discardRewrites(), failure(); | return rewriterImpl.discardRewrites(), failure(); | ||||||||||||||||||||||
// Now that all of the operations have been converted, finalize the conversion | // Now that all of the operations have been converted, finalize the conversion | ||||||||||||||||||||||
// process to ensure any lingering conversion artifacts are cleaned up and | // process to ensure any lingering conversion artifacts are cleaned up and | ||||||||||||||||||||||
// legalized. | // legalized. | ||||||||||||||||||||||
if (failed(finalize(rewriter))) | if (failed(finalize(rewriter))) | ||||||||||||||||||||||
▲ Show 20 Lines • Show All 831 Lines • ▼ Show 20 Lines | |||||||||||||||||||||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||||||||||||||||||
// Analysis Conversion | // Analysis Conversion | ||||||||||||||||||||||
LogicalResult | LogicalResult | ||||||||||||||||||||||
mlir::applyAnalysisConversion(ArrayRef<Operation *> ops, | mlir::applyAnalysisConversion(ArrayRef<Operation *> ops, | ||||||||||||||||||||||
ConversionTarget &target, | ConversionTarget &target, | ||||||||||||||||||||||
const FrozenRewritePatternSet &patterns, | const FrozenRewritePatternSet &patterns, | ||||||||||||||||||||||
DenseSet<Operation *> &convertedOps) { | DenseSet<Operation *> &convertedOps, | ||||||||||||||||||||||
function_ref<void(Diagnostic &)> notifyCallback) { | |||||||||||||||||||||||
OperationConverter opConverter(target, patterns, OpConversionMode::Analysis, | OperationConverter opConverter(target, patterns, OpConversionMode::Analysis, | ||||||||||||||||||||||
&convertedOps); | &convertedOps); | ||||||||||||||||||||||
return opConverter.convertOperations(ops); | return opConverter.convertOperations(ops, notifyCallback); | ||||||||||||||||||||||
} | } | ||||||||||||||||||||||
LogicalResult | LogicalResult | ||||||||||||||||||||||
mlir::applyAnalysisConversion(Operation *op, ConversionTarget &target, | mlir::applyAnalysisConversion(Operation *op, ConversionTarget &target, | ||||||||||||||||||||||
const FrozenRewritePatternSet &patterns, | const FrozenRewritePatternSet &patterns, | ||||||||||||||||||||||
DenseSet<Operation *> &convertedOps) { | DenseSet<Operation *> &convertedOps, | ||||||||||||||||||||||
function_ref<void(Diagnostic &)> notifyCallback) { | |||||||||||||||||||||||
return applyAnalysisConversion(llvm::makeArrayRef(op), target, patterns, | return applyAnalysisConversion(llvm::makeArrayRef(op), target, patterns, | ||||||||||||||||||||||
convertedOps); | convertedOps, notifyCallback); | ||||||||||||||||||||||
} | } |
This isn't the same as LLVM_DEBUG. LLVM_DEBUG also handles checking if the current debug mode enabled is dialect conversion. Can we just have a bool that is defaulted to true/false depending on notifyCallback, that gets explicitly set to true inside of an LLVM_DEBUG code block?