blob: fef3e77b2b1e19e2f9a02cd46d32be6b0daa476d [file] [log] [blame]
///===--- LSLocationPrinter.cpp - Dump all memory locations in program ---===//
///
/// This source file is part of the Swift.org open source project
///
/// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
/// Licensed under Apache License v2.0 with Runtime Library Exception
///
/// See http://swift.org/LICENSE.txt for license information
/// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
///
///===---------------------------------------------------------------------===//
///
/// This pass tests type expansion, memlocation expansion and memlocation
/// reduction.
///
///===---------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-memlocation-dumper"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILValue.h"
#include "swift/SIL/SILValueProjection.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
using namespace swift;
//===----------------------------------------------------------------------===//
// Top Level Driver
//===----------------------------------------------------------------------===//
namespace {
enum class MLKind : unsigned {
OnlyExpansion = 0,
OnlyReduction = 1,
OnlyTypeExpansion = 2,
All = 3,
};
} // end anonymous namespace
static llvm::cl::opt<MLKind> LSLocationKinds(
"ml", llvm::cl::desc("LSLocation Kinds:"), llvm::cl::init(MLKind::All),
llvm::cl::values(
clEnumValN(MLKind::OnlyExpansion, "only-expansion", "only-expansion"),
clEnumValN(MLKind::OnlyReduction, "only-reduction", "only-reduction"),
clEnumValN(MLKind::OnlyTypeExpansion, "only-type-expansion",
"only-type-expansion"),
clEnumValN(MLKind::All, "all", "all"), clEnumValEnd));
static llvm::cl::opt<bool> UseNewProjection("lslocation-dump-use-new-projection",
llvm::cl::init(false));
namespace {
class LSLocationPrinter : public SILModuleTransform {
/// Type expansion analysis.
TypeExpansionAnalysis *TE;
public:
/// Dumps the expansions of SILType accessed in the function.
/// This tests the expandTypeIntoLeafProjectionPaths function, which is
/// a function used extensively in expand and reduce functions.
///
/// We test it to catch any suspicious things in the earliest point.
///
void printTypeExpansion(SILFunction &Fn) {
SILModule *M = &Fn.getModule();
ProjectionPathList PPList;
unsigned Counter = 0;
for (auto &BB : Fn) {
for (auto &II : BB) {
if (auto *LI = dyn_cast<LoadInst>(&II)) {
SILValue V = LI->getOperand();
// This is an address type, take it object type.
SILType Ty = V.getType().getObjectType();
ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList);
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
SILValue V = SI->getDest();
// This is an address type, take it object type.
SILType Ty = V.getType().getObjectType();
ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList);
} else {
// Not interested in these instructions yet.
continue;
}
llvm::outs() << "#" << Counter++ << II;
for (auto &T : PPList) {
llvm::outs() << T.getValue();
}
PPList.clear();
}
}
llvm::outs() << "\n";
}
void printTypeExpansionWithNewProjection(SILFunction &Fn) {
SILModule *M = &Fn.getModule();
llvm::SmallVector<NewProjectionPath, 8> PPList;
unsigned Counter = 0;
for (auto &BB : Fn) {
for (auto &II : BB) {
SILValue V;
SILType Ty;
if (auto *LI = dyn_cast<LoadInst>(&II)) {
V = LI->getOperand();
// This is an address type, take it object type.
Ty = V.getType().getObjectType();
NewProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList,
true);
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
V = SI->getDest();
// This is an address type, take it object type.
Ty = V.getType().getObjectType();
NewProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList,
true);
} else {
// Not interested in these instructions yet.
continue;
}
llvm::outs() << "#" << Counter++ << II;
for (auto &T : PPList) {
T.print(llvm::outs(), *M);
}
PPList.clear();
}
}
llvm::outs() << "\n";
}
/// Dumps the expansions of memory locations accessed in the function.
/// This tests the expand function in LSLocation class.
///
/// We test it to catch any suspicious things when memory location is
/// expanded, i.e. base is traced back and aggregate is expanded
/// properly.
void printMemExpansion(SILFunction &Fn) {
LSLocation L;
LSLocationList Locs;
unsigned Counter = 0;
for (auto &BB : Fn) {
for (auto &II : BB) {
if (auto *LI = dyn_cast<LoadInst>(&II)) {
L.initialize(LI->getOperand());
if (!L.isValid())
continue;
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
L.initialize(SI->getDest());
if (!L.isValid())
continue;
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
} else {
// Not interested in these instructions yet.
continue;
}
llvm::outs() << "#" << Counter++ << II;
for (auto &Loc : Locs) {
Loc.print();
}
L.reset();
Locs.clear();
}
}
llvm::outs() << "\n";
}
/// Dumps the reductions of set of memory locations.
///
/// This function first calls expand on a memory location. It then calls
/// reduce, in hope to get the original memory location back.
///
void printMemReduction(SILFunction &Fn) {
LSLocation L;
LSLocationList Locs;
llvm::DenseSet<LSLocation> SLocs;
unsigned Counter = 0;
for (auto &BB : Fn) {
for (auto &II : BB) {
// Expand it first.
//
if (auto *LI = dyn_cast<LoadInst>(&II)) {
L.initialize(LI->getOperand());
if (!L.isValid())
continue;
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
L.initialize(SI->getDest());
if (!L.isValid())
continue;
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
} else {
// Not interested in these instructions yet.
continue;
}
// Try to reduce it.
//
// Add into the set in reverse order, Reduction should not care
// about the order of the memory locations in the set.
for (auto I = Locs.rbegin(); I != Locs.rend(); ++I) {
SLocs.insert(*I);
}
// This should get the original (unexpanded) location back.
LSLocation::reduce(L, &Fn.getModule(), SLocs, TE);
llvm::outs() << "#" << Counter++ << II;
for (auto &Loc : SLocs) {
Loc.print();
}
L.reset();
Locs.clear();
SLocs.clear();
}
}
llvm::outs() << "\n";
}
void run() override {
for (auto &Fn : *getModule()) {
if (Fn.isExternalDeclaration()) continue;
// Initialize the type expansion analysis.
TE = PM->getAnalysis<TypeExpansionAnalysis>();
llvm::outs() << "@" << Fn.getName() << "\n";
switch (LSLocationKinds) {
case MLKind::OnlyTypeExpansion:
if (UseNewProjection) {
printTypeExpansionWithNewProjection(Fn);
} else {
printTypeExpansion(Fn);
}
break;
case MLKind::OnlyExpansion:
printMemExpansion(Fn);
break;
case MLKind::OnlyReduction:
printMemReduction(Fn);
break;
default:
break;
}
}
}
StringRef getName() override { return "Mem Location Dumper"; }
};
} // end anonymous namespace
SILTransform *swift::createLSLocationPrinter() {
return new LSLocationPrinter();
}