mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
At some point, pass definitions were heavily macro-ized. Pass descriptive names were added in two places. This is not only redundant but a source of confusion. You could waste a lot of time grepping for the wrong string. I removed all the getName() overrides which, at around 90 passes, was a fairly significant amount of code bloat. Any pass that we want to be able to invoke by name from a tool (sil-opt) or pipeline plan *should* have unique type name, enum value, commend-line string, and name string. I removed a comment about the various inliner passes that contradicted that. Side note: We should be consistent with the policy that a pass is identified by its type. We have a couple passes, LICM and CSE, which currently violate that convention.
263 lines
8.5 KiB
C++
263 lines
8.5 KiB
C++
//===--- LSLocationPrinter.cpp - Dump all memory locations in program -----===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://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/SIL/Projection.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "swift/SIL/SILValue.h"
|
|
#include "swift/SILOptimizer/Analysis/Analysis.h"
|
|
#include "swift/SILOptimizer/PassManager/Passes.h"
|
|
#include "swift/SILOptimizer/PassManager/Transforms.h"
|
|
#include "swift/SILOptimizer/Utils/LoadStoreOptUtils.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")));
|
|
|
|
static llvm::cl::opt<bool> UseProjection("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) {
|
|
T.getValue().print(llvm::outs(), *M);
|
|
}
|
|
PPList.clear();
|
|
}
|
|
}
|
|
llvm::outs() << "\n";
|
|
}
|
|
|
|
void printTypeExpansionWithProjection(SILFunction &Fn) {
|
|
SILModule *M = &Fn.getModule();
|
|
llvm::SmallVector<Optional<ProjectionPath>, 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();
|
|
ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList);
|
|
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
|
|
V = SI->getDest();
|
|
// This is an address type, take it object type.
|
|
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) {
|
|
T.getValue().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)) {
|
|
SILValue Mem = LI->getOperand();
|
|
SILValue UO = getUnderlyingObject(Mem);
|
|
L.init(UO, ProjectionPath::getProjectionPath(UO, Mem));
|
|
if (!L.isValid())
|
|
continue;
|
|
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
|
|
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
|
|
SILValue Mem = SI->getDest();
|
|
SILValue UO = getUnderlyingObject(Mem);
|
|
L.init(UO, ProjectionPath::getProjectionPath(UO, Mem));
|
|
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(llvm::outs(), &Fn.getModule());
|
|
}
|
|
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)) {
|
|
SILValue Mem = LI->getOperand();
|
|
SILValue UO = getUnderlyingObject(Mem);
|
|
L.init(UO, ProjectionPath::getProjectionPath(UO, Mem));
|
|
if (!L.isValid())
|
|
continue;
|
|
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
|
|
} else if (auto *SI = dyn_cast<StoreInst>(&II)) {
|
|
SILValue Mem = SI->getDest();
|
|
SILValue UO = getUnderlyingObject(Mem);
|
|
L.init(UO, ProjectionPath::getProjectionPath(UO, Mem));
|
|
if (!L.isValid())
|
|
continue;
|
|
LSLocation::expand(L, &Fn.getModule(), Locs, TE);
|
|
} else {
|
|
// Not interested in these instructions yet.
|
|
continue;
|
|
}
|
|
|
|
// Try to reduce it.
|
|
//
|
|
// Reduction should not care about the order of the memory locations in
|
|
// the set.
|
|
for (auto I = Locs.begin(); I != Locs.end(); ++I) {
|
|
SLocs.insert(*I);
|
|
}
|
|
|
|
// This should get the original (unexpanded) location back.
|
|
LSLocation::reduce(L, &Fn.getModule(), SLocs);
|
|
llvm::outs() << "#" << Counter++ << II;
|
|
for (auto &Loc : SLocs) {
|
|
Loc.print(llvm::outs(), &Fn.getModule());
|
|
}
|
|
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:
|
|
printTypeExpansionWithProjection(Fn);
|
|
break;
|
|
case MLKind::OnlyExpansion:
|
|
printMemExpansion(Fn);
|
|
break;
|
|
case MLKind::OnlyReduction:
|
|
printMemReduction(Fn);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
SILTransform *swift::createLSLocationPrinter() {
|
|
return new LSLocationPrinter();
|
|
}
|