#include "TestAliasAnalysis.h"
#include "mlir/Analysis/AliasAnalysis.h"
#include "mlir/Analysis/AliasAnalysis/LocalAliasAnalysis.h"
#include "mlir/Interfaces/FunctionInterfaces.h"
#include "mlir/Pass/Pass.h"
using namespace mlir;
static void printAliasOperand(Operation *op) {
llvm::errs() << op->getAttrOfType<StringAttr>("test.ptr").getValue();
}
static void printAliasOperand(Value value) {
if (BlockArgument arg = dyn_cast<BlockArgument>(value)) {
Region *region = arg.getParentRegion();
unsigned parentBlockNumber =
std::distance(region->begin(), arg.getOwner()->getIterator());
llvm::errs() << region->getParentOp()
->getAttrOfType<StringAttr>("test.ptr")
.getValue()
<< ".region" << region->getRegionNumber();
if (parentBlockNumber != 0)
llvm::errs() << ".block" << parentBlockNumber;
llvm::errs() << "#" << arg.getArgNumber();
return;
}
OpResult result = cast<OpResult>(value);
printAliasOperand(result.getOwner());
llvm::errs() << "#" << result.getResultNumber();
}
namespace mlir {
namespace test {
void printAliasResult(AliasResult result, Value lhs, Value rhs) {
printAliasOperand(lhs);
llvm::errs() << " <-> ";
printAliasOperand(rhs);
llvm::errs() << ": " << result << "\n";
}
void printModRefResult(ModRefResult result, Operation *op, Value location) {
printAliasOperand(op);
llvm::errs() << " -> ";
printAliasOperand(location);
llvm::errs() << ": " << result << "\n";
}
void TestAliasAnalysisBase::runAliasAnalysisOnOperation(
Operation *op, AliasAnalysis &aliasAnalysis) {
llvm::errs() << "Testing : " << *op->getInherentAttr("sym_name") << "\n";
SmallVector<Value, 32> valsToCheck;
op->walk([&](Operation *op) {
if (!op->getDiscardableAttr("test.ptr"))
return;
valsToCheck.append(op->result_begin(), op->result_end());
for (Region ®ion : op->getRegions())
for (Block &block : region)
valsToCheck.append(block.args_begin(), block.args_end());
});
for (auto it = valsToCheck.begin(), e = valsToCheck.end(); it != e; ++it)
for (auto *innerIt = valsToCheck.begin(); innerIt != it; ++innerIt)
printAliasResult(aliasAnalysis.alias(*innerIt, *it), *innerIt, *it);
}
void TestAliasAnalysisModRefBase::runAliasAnalysisOnOperation(
Operation *op, AliasAnalysis &aliasAnalysis) {
llvm::errs() << "Testing : " << *op->getInherentAttr("sym_name") << "\n";
SmallVector<Value, 32> valsToCheck;
op->walk([&](Operation *op) {
if (!op->getDiscardableAttr("test.ptr"))
return;
valsToCheck.append(op->result_begin(), op->result_end());
for (Region ®ion : op->getRegions())
for (Block &block : region)
valsToCheck.append(block.args_begin(), block.args_end());
});
for (auto &it : valsToCheck) {
op->walk([&](Operation *op) {
if (!op->getDiscardableAttr("test.ptr"))
return;
printModRefResult(aliasAnalysis.getModRef(op, it), op, it);
});
}
}
}
}
namespace {
struct TestAliasAnalysisPass
: public test::TestAliasAnalysisBase,
PassWrapper<TestAliasAnalysisPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisPass)
StringRef getArgument() const final { return "test-alias-analysis"; }
StringRef getDescription() const final {
return "Test alias analysis results.";
}
void runOnOperation() override {
AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
}
};
}
namespace {
struct TestAliasAnalysisModRefPass
: public test::TestAliasAnalysisModRefBase,
PassWrapper<TestAliasAnalysisModRefPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisModRefPass)
StringRef getArgument() const final { return "test-alias-analysis-modref"; }
StringRef getDescription() const final {
return "Test alias analysis ModRef results.";
}
void runOnOperation() override {
AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
}
};
}
static bool isFuncArg(Value val) {
auto blockArg = dyn_cast<BlockArgument>(val);
if (!blockArg)
return false;
return mlir::isa_and_nonnull<FunctionOpInterface>(
blockArg.getOwner()->getParentOp());
}
static bool isRestrict(Value val) {
auto blockArg = cast<BlockArgument>(val);
auto func =
mlir::cast<FunctionOpInterface>(blockArg.getOwner()->getParentOp());
return !!func.getArgAttr(blockArg.getArgNumber(),
"local_alias_analysis.restrict");
}
namespace {
class LocalAliasAnalysisRestrict : public LocalAliasAnalysis {
protected:
AliasResult aliasImpl(Value lhs, Value rhs) override {
if (lhs == rhs)
return AliasResult::MustAlias;
if (isFuncArg(lhs) && isFuncArg(rhs))
if (isRestrict(lhs) || isRestrict(rhs))
return AliasResult::NoAlias;
return LocalAliasAnalysis::aliasImpl(lhs, rhs);
}
};
struct TestAliasAnalysisExtendingPass
: public test::TestAliasAnalysisBase,
PassWrapper<TestAliasAnalysisExtendingPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisExtendingPass)
StringRef getArgument() const final {
return "test-alias-analysis-extending";
}
StringRef getDescription() const final {
return "Test alias analysis extending.";
}
void runOnOperation() override {
AliasAnalysis aliasAnalysis(getOperation());
aliasAnalysis.addAnalysisImplementation(LocalAliasAnalysisRestrict());
runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
}
};
}
namespace mlir {
namespace test {
void registerTestAliasAnalysisPass() {
PassRegistration<TestAliasAnalysisExtendingPass>();
PassRegistration<TestAliasAnalysisModRefPass>();
PassRegistration<TestAliasAnalysisPass>();
}
}
}