119 lines · cpp
1//===- ConstantPropagationAnalysis.cpp - Constant propagation analysis ----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h"10#include "mlir/Analysis/DataFlow/SparseAnalysis.h"11#include "mlir/IR/BuiltinAttributes.h"12#include "mlir/IR/OpDefinition.h"13#include "mlir/IR/Operation.h"14#include "mlir/IR/Value.h"15#include "mlir/Support/LLVM.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/Support/Casting.h"18#include "llvm/Support/Debug.h"19#include "llvm/Support/DebugLog.h"20#include <cassert>21 22#define DEBUG_TYPE "constant-propagation"23 24using namespace mlir;25using namespace mlir::dataflow;26 27//===----------------------------------------------------------------------===//28// ConstantValue29//===----------------------------------------------------------------------===//30 31void ConstantValue::print(raw_ostream &os) const {32 if (isUninitialized()) {33 os << "<UNINITIALIZED>";34 return;35 }36 if (getConstantValue() == nullptr) {37 os << "<UNKNOWN>";38 return;39 }40 return getConstantValue().print(os);41}42 43//===----------------------------------------------------------------------===//44// SparseConstantPropagation45//===----------------------------------------------------------------------===//46 47LogicalResult SparseConstantPropagation::visitOperation(48 Operation *op, ArrayRef<const Lattice<ConstantValue> *> operands,49 ArrayRef<Lattice<ConstantValue> *> results) {50 LDBG() << "SCP: Visiting operation: " << *op;51 52 // Don't try to simulate the results of a region operation as we can't53 // guarantee that folding will be out-of-place. We don't allow in-place54 // folds as the desire here is for simulated execution, and not general55 // folding.56 if (op->getNumRegions()) {57 setAllToEntryStates(results);58 return success();59 }60 61 SmallVector<Attribute, 8> constantOperands;62 constantOperands.reserve(op->getNumOperands());63 for (auto *operandLattice : operands) {64 if (operandLattice->getValue().isUninitialized())65 return success();66 constantOperands.push_back(operandLattice->getValue().getConstantValue());67 }68 69 // Save the original operands and attributes just in case the operation70 // folds in-place. The constant passed in may not correspond to the real71 // runtime value, so in-place updates are not allowed.72 SmallVector<Value, 8> originalOperands(op->getOperands());73 DictionaryAttr originalAttrs = op->getAttrDictionary();74 75 // Simulate the result of folding this operation to a constant. If folding76 // fails or was an in-place fold, mark the results as overdefined.77 SmallVector<OpFoldResult, 8> foldResults;78 foldResults.reserve(op->getNumResults());79 if (failed(op->fold(constantOperands, foldResults))) {80 setAllToEntryStates(results);81 return success();82 }83 84 // If the folding was in-place, mark the results as overdefined and reset85 // the operation. We don't allow in-place folds as the desire here is for86 // simulated execution, and not general folding.87 if (foldResults.empty()) {88 op->setOperands(originalOperands);89 op->setAttrs(originalAttrs);90 setAllToEntryStates(results);91 return success();92 }93 94 // Merge the fold results into the lattice for this operation.95 assert(foldResults.size() == op->getNumResults() && "invalid result size");96 for (const auto it : llvm::zip(results, foldResults)) {97 Lattice<ConstantValue> *lattice = std::get<0>(it);98 99 // Merge in the result of the fold, either a constant or a value.100 OpFoldResult foldResult = std::get<1>(it);101 if (Attribute attr = llvm::dyn_cast_if_present<Attribute>(foldResult)) {102 LDBG() << "Folded to constant: " << attr;103 propagateIfChanged(lattice,104 lattice->join(ConstantValue(attr, op->getDialect())));105 } else {106 LDBG() << "Folded to value: " << cast<Value>(foldResult);107 AbstractSparseForwardDataFlowAnalysis::join(108 lattice, *getLatticeElement(cast<Value>(foldResult)));109 }110 }111 return success();112}113 114void SparseConstantPropagation::setToEntryState(115 Lattice<ConstantValue> *lattice) {116 propagateIfChanged(lattice,117 lattice->join(ConstantValue::getUnknownConstant()));118}119