165 lines
8.3 KiB
C++
165 lines
8.3 KiB
C++
//===- CFGToSCF.h - Control Flow Graph to Structured Control Flow *- C++ -*===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This header file defines a generic `transformCFGToSCF` function that can be
|
|
// used to lift any dialect operations implementing control flow graph
|
|
// operations to any dialect implementing structured control flow operations.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_TRANSFORMS_CFGTOSCF_H
|
|
#define MLIR_TRANSFORMS_CFGTOSCF_H
|
|
|
|
#include "mlir/IR/Builders.h"
|
|
#include "mlir/IR/Dominance.h"
|
|
#include "mlir/IR/Operation.h"
|
|
|
|
namespace mlir {
|
|
|
|
/// Interface that should be implemented by any caller of `transformCFGToSCF`.
|
|
/// The transformation requires the caller to 1) create switch-like control
|
|
/// flow operations for intermediate transformations and 2) to create
|
|
/// the desired structured control flow ops.
|
|
class CFGToSCFInterface {
|
|
public:
|
|
virtual ~CFGToSCFInterface() = default;
|
|
|
|
/// Creates a structured control flow operation branching to one of `regions`.
|
|
/// It replaces `controlFlowCondOp` and must have `resultTypes` as results.
|
|
/// `regions` contains the list of branch regions corresponding to each
|
|
/// successor of `controlFlowCondOp`. Their bodies must simply be taken and
|
|
/// left as is.
|
|
/// Returns failure if incapable of converting the control flow graph
|
|
/// operation.
|
|
virtual FailureOr<Operation *> createStructuredBranchRegionOp(
|
|
OpBuilder &builder, Operation *controlFlowCondOp, TypeRange resultTypes,
|
|
MutableArrayRef<Region> regions) = 0;
|
|
|
|
/// Creates a return-like terminator for a branch region of the op returned
|
|
/// by `createStructuredBranchRegionOp`. `branchRegionOp` is the operation
|
|
/// returned by `createStructuredBranchRegionOp`.
|
|
/// `replacedControlFlowOp` is the control flow op being replaced by the
|
|
/// terminator or nullptr if the terminator is not replacing any existing
|
|
/// control flow op. `results` are the values that should be returned by the
|
|
/// branch region.
|
|
virtual LogicalResult createStructuredBranchRegionTerminatorOp(
|
|
Location loc, OpBuilder &builder, Operation *branchRegionOp,
|
|
Operation *replacedControlFlowOp, ValueRange results) = 0;
|
|
|
|
/// Creates a structured control flow operation representing a do-while loop.
|
|
/// The do-while loop is expected to have the exact same result types as the
|
|
/// types of the iteration values.
|
|
/// `loopBody` is the body of the loop. The implementation of this
|
|
/// function must create a suitable terminator op at the end of the last block
|
|
/// in `loopBody` which continues the loop if `condition` is 1 and exits the
|
|
/// loop if 0. `loopValuesNextIter` are the values that have to be passed as
|
|
/// the iteration values for the next iteration if continuing, or the result
|
|
/// of the loop if exiting.
|
|
/// `condition` is guaranteed to be of the same type as values returned by
|
|
/// `getCFGSwitchValue` with either 0 or 1 as value.
|
|
///
|
|
/// `loopValuesInit` are the values used to initialize the iteration
|
|
/// values of the loop.
|
|
/// Returns failure if incapable of creating a loop op.
|
|
virtual FailureOr<Operation *> createStructuredDoWhileLoopOp(
|
|
OpBuilder &builder, Operation *replacedOp, ValueRange loopValuesInit,
|
|
Value condition, ValueRange loopValuesNextIter, Region &&loopBody) = 0;
|
|
|
|
/// Creates a constant operation with a result representing `value` that is
|
|
/// suitable as flag for `createCFGSwitchOp`.
|
|
virtual Value getCFGSwitchValue(Location loc, OpBuilder &builder,
|
|
unsigned value) = 0;
|
|
|
|
/// Creates a switch CFG branch operation branching to one of
|
|
/// `caseDestinations` or `defaultDest`. This is used by the transformation
|
|
/// for intermediate transformations before lifting to structured control
|
|
/// flow. The switch op branches based on `flag` which is guaranteed to be of
|
|
/// the same type as values returned by `getCFGSwitchValue`. The insertion
|
|
/// block of the builder is guaranteed to have its predecessors already set
|
|
/// to create an equivalent CFG after this operation.
|
|
/// Note: `caseValues` and other related ranges may be empty to represent an
|
|
/// unconditional branch.
|
|
virtual void createCFGSwitchOp(Location loc, OpBuilder &builder, Value flag,
|
|
ArrayRef<unsigned> caseValues,
|
|
BlockRange caseDestinations,
|
|
ArrayRef<ValueRange> caseArguments,
|
|
Block *defaultDest,
|
|
ValueRange defaultArgs) = 0;
|
|
|
|
/// Creates a constant operation returning an undefined instance of `type`.
|
|
/// This is required by the transformation as the lifting process might create
|
|
/// control-flow paths where an SSA-value is undefined.
|
|
virtual Value getUndefValue(Location loc, OpBuilder &builder, Type type) = 0;
|
|
|
|
/// Returns true if this operation (which has >1 successors) can be
|
|
/// converted to structured control flow by `createStructuredBranchRegionOp`.
|
|
/// Called during precondition checking, before any IR modifications.
|
|
/// Default implementation accepts all ops.
|
|
virtual bool canConvertMultiSuccessorBranchOp(Operation *op) { return true; }
|
|
|
|
/// Creates a return-like terminator indicating unreachable.
|
|
/// This is required when the transformation encounters a statically known
|
|
/// infinite loop. Since structured control flow ops are not terminators,
|
|
/// after lifting an infinite loop, a terminator has to be placed after to
|
|
/// possibly satisfy the terminator requirement of the region originally
|
|
/// passed to `transformCFGToSCF`.
|
|
///
|
|
/// `region` is guaranteed to be the region originally passed to
|
|
/// `transformCFGToSCF` and the op is guaranteed to always be an op in a block
|
|
/// directly nested under `region` after the transformation.
|
|
///
|
|
/// Returns failure if incapable of creating an unreachable terminator.
|
|
virtual FailureOr<Operation *>
|
|
createUnreachableTerminator(Location loc, OpBuilder &builder,
|
|
Region ®ion) = 0;
|
|
|
|
/// Helper function to create an unconditional branch using
|
|
/// `createCFGSwitchOp`.
|
|
void createSingleDestinationBranch(Location loc, OpBuilder &builder,
|
|
Value dummyFlag, Block *destination,
|
|
ValueRange arguments) {
|
|
createCFGSwitchOp(loc, builder, dummyFlag, {}, {}, {}, destination,
|
|
arguments);
|
|
}
|
|
|
|
/// Helper function to create a conditional branch using
|
|
/// `createCFGSwitchOp`.
|
|
void createConditionalBranch(Location loc, OpBuilder &builder,
|
|
Value condition, Block *trueDest,
|
|
ValueRange trueArgs, Block *falseDest,
|
|
ValueRange falseArgs) {
|
|
createCFGSwitchOp(loc, builder, condition, {0}, {falseDest}, {falseArgs},
|
|
trueDest, trueArgs);
|
|
}
|
|
};
|
|
|
|
/// Transformation lifting any dialect implementing control flow graph
|
|
/// operations to a dialect implementing structured control flow operations.
|
|
/// `region` is the region that should be transformed.
|
|
/// The implementation of `interface` is responsible for the conversion of the
|
|
/// control flow operations to the structured control flow operations.
|
|
///
|
|
/// If the region contains only a single kind of return-like operation, all
|
|
/// control flow graph operations will be converted successfully.
|
|
/// Otherwise a single control flow graph operation branching to one block
|
|
/// per return-like operation kind remains.
|
|
///
|
|
/// The transformation currently requires that all control flow graph operations
|
|
/// have no side effects, implement the BranchOpInterface and does not have any
|
|
/// operation produced successor operands.
|
|
/// Returns failure if any of the preconditions are violated or if any of the
|
|
/// methods of `interface` failed. The IR is left in an unspecified state.
|
|
///
|
|
/// Otherwise, returns true or false if any changes to the IR have been made.
|
|
FailureOr<bool> transformCFGToSCF(Region ®ion, CFGToSCFInterface &interface,
|
|
DominanceInfo &dominanceInfo);
|
|
|
|
} // namespace mlir
|
|
|
|
#endif // MLIR_TRANSFORMS_CFGTOSCF_H
|