-
Notifications
You must be signed in to change notification settings - Fork 318
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FIRRTL] Simple points-to like analysis (#4637)
This analysis maps values back to their definitions (operations which produce a new value) and provides an indexing path in the original definition to produce the current value. Subaccesses produce a -1 (wildcard) in the path. The analysis provides the user with a stable summary node for each value which is suitable to use in other data-structures. wire a : firrtl.vector<bundle<f1: uint, f2: uint>, 4> => definition, is a root (empty path) v = subindex(a, 2) => derived from a with path {2} w = subfield(v, f2) => derived from a with path {2, 1}
- Loading branch information
Showing
7 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
//===- FIRRTLFieldSource.h - Field Source (points-to) -----------*- 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 file defines the FIRRTL Field Source Analysis, which is a points-to | ||
// analysis which identifies the source field and storage of any value derived | ||
// from a storage location. Values derived from reads of storage locations do | ||
// not appear in this analysis. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_DIALECT_FIRRTL_FIRRTLFIELDSOURCE_H | ||
#define CIRCT_DIALECT_FIRRTL_FIRRTLFIELDSOURCE_H | ||
|
||
#include "circt/Dialect/FIRRTL/FIRRTLOps.h" | ||
#include "circt/Support/LLVM.h" | ||
|
||
namespace circt { | ||
namespace firrtl { | ||
|
||
/// To use this class, retrieve a cached copy from the analysis manager: | ||
/// auto &fieldsource = getAnalysis<FieldSource>(getOperation()); | ||
class FieldSource { | ||
|
||
public: | ||
explicit FieldSource(Operation *operation); | ||
|
||
struct PathNode { | ||
PathNode(Value src, ArrayRef<int64_t> ar) : src(src), path(ar) {} | ||
Value src; | ||
SmallVector<int64_t, 4> path; | ||
|
||
bool isRoot() const { return path.empty(); } | ||
}; | ||
|
||
const PathNode *nodeForValue(Value v) const; | ||
|
||
private: | ||
void visitOp(Operation *op); | ||
void visitSubfield(SubfieldOp sf); | ||
void visitSubindex(SubindexOp si); | ||
void visitSubaccess(SubaccessOp sa); | ||
void visitMem(MemOp mem); | ||
void visitInst(InstanceOp inst); | ||
|
||
void makeNodeForValue(Value dst, Value src, ArrayRef<int64_t> path); | ||
|
||
DenseMap<Value, PathNode> paths; | ||
}; | ||
|
||
} // namespace firrtl | ||
} // namespace circt | ||
|
||
#endif // CIRCT_DIALECT_FIRRTL_FIRRTLFIELDSOURCE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
//===- FIRRTLFieldSource.cpp - Field Source Analysis ------------*- 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 file defines a basic points-to like analysis. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "circt/Dialect/FIRRTL/FIRRTLFieldSource.h" | ||
|
||
using namespace circt; | ||
using namespace firrtl; | ||
|
||
FieldSource::FieldSource(Operation *operation) { | ||
FModuleOp mod = cast<FModuleOp>(operation); | ||
for (auto port : mod.getBodyBlock()->getArguments()) | ||
if (auto ft = dyn_cast<FIRRTLBaseType>(port.getType())) | ||
if (!ft.isGround()) | ||
makeNodeForValue(port, port, {}); | ||
for (auto &op : *mod.getBodyBlock()) | ||
visitOp(&op); | ||
} | ||
|
||
void FieldSource::visitOp(Operation *op) { | ||
if (auto sf = dyn_cast<SubfieldOp>(op)) | ||
return visitSubfield(sf); | ||
if (auto si = dyn_cast<SubindexOp>(op)) | ||
return visitSubindex(si); | ||
if (auto sa = dyn_cast<SubaccessOp>(op)) | ||
return visitSubaccess(sa); | ||
if (isa<WireOp, NodeOp, RegOp, RegResetOp, BitCastOp>(op)) | ||
return makeNodeForValue(op->getResult(0), op->getResult(0), {}); | ||
if (auto mem = dyn_cast<MemOp>(op)) | ||
return visitMem(mem); | ||
if (auto inst = dyn_cast<InstanceOp>(op)) | ||
return visitInst(inst); | ||
// recurse in to regions | ||
for (auto &r : op->getRegions()) | ||
for (auto &b : r.getBlocks()) | ||
for (auto &op : b) | ||
visitOp(&op); | ||
} | ||
|
||
void FieldSource::visitSubfield(SubfieldOp sf) { | ||
auto value = sf.getInput(); | ||
const auto *node = nodeForValue(value); | ||
assert(node && "node should be in the map"); | ||
auto sv = node->path; | ||
sv.push_back(sf.getFieldIndex()); | ||
makeNodeForValue(sf.getResult(), node->src, sv); | ||
} | ||
|
||
void FieldSource::visitSubindex(SubindexOp si) { | ||
auto value = si.getInput(); | ||
const auto *node = nodeForValue(value); | ||
assert(node && "node should be in the map"); | ||
auto sv = node->path; | ||
sv.push_back(si.getIndex()); | ||
makeNodeForValue(si.getResult(), node->src, sv); | ||
} | ||
|
||
void FieldSource::visitSubaccess(SubaccessOp sa) { | ||
auto value = sa.getInput(); | ||
const auto *node = nodeForValue(value); | ||
assert(node && "node should be in the map"); | ||
auto sv = node->path; | ||
sv.push_back(-1); | ||
makeNodeForValue(sa.getResult(), node->src, sv); | ||
} | ||
|
||
void FieldSource::visitMem(MemOp mem) { | ||
for (auto r : mem.getResults()) | ||
makeNodeForValue(r, r, {}); | ||
} | ||
|
||
void FieldSource::visitInst(InstanceOp inst) { | ||
for (auto r : inst.getResults()) | ||
makeNodeForValue(r, r, {}); | ||
} | ||
|
||
const FieldSource::PathNode *FieldSource::nodeForValue(Value v) const { | ||
auto ii = paths.find(v); | ||
if (ii == paths.end()) | ||
return nullptr; | ||
return &ii->second; | ||
} | ||
|
||
void FieldSource::makeNodeForValue(Value dst, Value src, | ||
ArrayRef<int64_t> path) { | ||
auto ii = paths.try_emplace(dst, src, path); | ||
assert(ii.second && "Double insert into the map"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
//===- PrintFIRRTLFieldSource.cpp - Print the Field Source ------*- 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 | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Print the FieldSource analysis. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "PassDetails.h" | ||
#include "circt/Dialect/FIRRTL/FIRRTLFieldSource.h" | ||
#include "circt/Dialect/FIRRTL/Passes.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
using namespace circt; | ||
using namespace firrtl; | ||
|
||
namespace { | ||
struct PrintFIRRTLFieldSourcePass | ||
: public PrintFIRRTLFieldSourcePassBase<PrintFIRRTLFieldSourcePass> { | ||
PrintFIRRTLFieldSourcePass(raw_ostream &os) : os(os) {} | ||
|
||
void visitValue(const FieldSource &fieldRefs, Value v) { | ||
auto *p = fieldRefs.nodeForValue(v); | ||
if (p) { | ||
if (p->isRoot()) | ||
os << "ROOT: "; | ||
else | ||
os << "SUB: " << v; | ||
os << " : " << p->src << " : {"; | ||
llvm::interleaveComma(p->path, os); | ||
os << "}\n"; | ||
} | ||
} | ||
|
||
void visitOp(const FieldSource &fieldRefs, Operation *op) { | ||
for (auto r : op->getResults()) | ||
visitValue(fieldRefs, r); | ||
// recurse in to regions | ||
for (auto &r : op->getRegions()) | ||
for (auto &b : r.getBlocks()) | ||
for (auto &op : b) | ||
visitOp(fieldRefs, &op); | ||
} | ||
|
||
void runOnOperation() override { | ||
auto modOp = getOperation(); | ||
os << "** " << modOp.getName() << "\n"; | ||
auto &fieldRefs = getAnalysis<FieldSource>(); | ||
for (auto port : modOp.getBodyBlock()->getArguments()) | ||
visitValue(fieldRefs, port); | ||
for (auto &op : *modOp.getBodyBlock()) | ||
visitOp(fieldRefs, &op); | ||
|
||
markAllAnalysesPreserved(); | ||
} | ||
raw_ostream &os; | ||
}; | ||
} // end anonymous namespace | ||
|
||
std::unique_ptr<mlir::Pass> circt::firrtl::createFIRRTLFieldSourcePass() { | ||
return std::make_unique<PrintFIRRTLFieldSourcePass>(llvm::errs()); | ||
} |