Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[GlobalISel] Add a GISelValueTracker printing pass #139687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions 8 llvm/docs/GlobalISel/KnownBits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,18 @@ dependency with ``INITIALIZE_PASS_DEPENDENCY``.
...

INITIALIZE_PASS_BEGIN(...)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_END(...)

and require the pass in ``getAnalysisUsage``.

.. code-block:: c++

void MyPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
// Optional: If your pass preserves known bits analysis (many do) then
// indicate that it's preserved for re-use by another pass here.
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
}

Then it's just a matter of fetching the analysis and using it:
Expand All @@ -86,7 +86,7 @@ Then it's just a matter of fetching the analysis and using it:

bool MyPass::runOnMachineFunction(MachineFunction &MF) {
...
GISelValueTracking &VT = getAnalysis<GISelValueTrackingAnalysis>().get(MF);
GISelValueTracking &VT = getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
...
MachineInstr *MI = ...;
KnownBits Known = VT->getKnownBits(MI->getOperand(0).getReg());
Expand Down
30 changes: 27 additions & 3 deletions 30 llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/IR/PassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/KnownBits.h"

Expand Down Expand Up @@ -104,19 +105,42 @@ class GISelValueTracking : public GISelChangeObserver {
/// Eventually add other features such as caching/ser/deserializing
/// to MIR etc. Those implementations can derive from GISelValueTracking
/// and override computeKnownBitsImpl.
class GISelValueTrackingAnalysis : public MachineFunctionPass {
class GISelValueTrackingAnalysisLegacy : public MachineFunctionPass {
std::unique_ptr<GISelValueTracking> Info;

public:
static char ID;
GISelValueTrackingAnalysis() : MachineFunctionPass(ID) {
initializeGISelValueTrackingAnalysisPass(*PassRegistry::getPassRegistry());
GISelValueTrackingAnalysisLegacy() : MachineFunctionPass(ID) {
initializeGISelValueTrackingAnalysisLegacyPass(
*PassRegistry::getPassRegistry());
}
GISelValueTracking &get(MachineFunction &MF);
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &MF) override;
void releaseMemory() override { Info.reset(); }
};

class GISelValueTrackingAnalysis
: public AnalysisInfoMixin<GISelValueTrackingAnalysis> {
friend AnalysisInfoMixin<GISelValueTrackingAnalysis>;
static AnalysisKey Key;

public:
using Result = GISelValueTracking;

Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM);
};

class GISelValueTrackingPrinterPass
: public PassInfoMixin<GISelValueTrackingPrinterPass> {
raw_ostream &OS;

public:
GISelValueTrackingPrinterPass(raw_ostream &OS) : OS(OS) {}

PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM);
};
} // namespace llvm

#endif // LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
2 changes: 1 addition & 1 deletion 2 llvm/include/llvm/InitializePasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void initializeLazyValueInfoWrapperPassPass(PassRegistry &);
void initializeLegacyLICMPassPass(PassRegistry &);
void initializeLegalizerPass(PassRegistry &);
void initializeGISelCSEAnalysisWrapperPassPass(PassRegistry &);
void initializeGISelValueTrackingAnalysisPass(PassRegistry &);
void initializeGISelValueTrackingAnalysisLegacyPass(PassRegistry &);
void initializeLiveDebugValuesLegacyPass(PassRegistry &);
void initializeLiveDebugVariablesWrapperLegacyPass(PassRegistry &);
void initializeLiveIntervalsWrapperPassPass(PassRegistry &);
Expand Down
2 changes: 2 additions & 0 deletions 2 llvm/include/llvm/Passes/MachinePassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ LOOP_PASS("loop-term-fold", LoopTermFoldPass())
// computed. (We still either need to regenerate kill flags after regalloc, or
// preferably fix the scavenger to not depend on them).
MACHINE_FUNCTION_ANALYSIS("edge-bundles", EdgeBundlesAnalysis())
MACHINE_FUNCTION_ANALYSIS("gisel-value-tracking", GISelValueTrackingAnalysis())
MACHINE_FUNCTION_ANALYSIS("livedebugvars", LiveDebugVariablesAnalysis())
MACHINE_FUNCTION_ANALYSIS("live-intervals", LiveIntervalsAnalysis())
MACHINE_FUNCTION_ANALYSIS("live-reg-matrix", LiveRegMatrixAnalysis())
Expand Down Expand Up @@ -165,6 +166,7 @@ MACHINE_FUNCTION_PASS("post-RA-sched", PostRASchedulerPass(TM))
MACHINE_FUNCTION_PASS("postmisched", PostMachineSchedulerPass(TM))
MACHINE_FUNCTION_PASS("post-ra-pseudos", ExpandPostRAPseudosPass())
MACHINE_FUNCTION_PASS("print", PrintMIRPass())
MACHINE_FUNCTION_PASS("print<gisel-value-tracking>", GISelValueTrackingPrinterPass(errs()))
MACHINE_FUNCTION_PASS("print<livedebugvars>", LiveDebugVariablesPrinterPass(errs()))
MACHINE_FUNCTION_PASS("print<live-intervals>", LiveIntervalsPrinterPass(errs()))
MACHINE_FUNCTION_PASS("print<live-stacks>", LiveStacksPrinterPass(errs()))
Expand Down
47 changes: 42 additions & 5 deletions 47 llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@

using namespace llvm;

char llvm::GISelValueTrackingAnalysis::ID = 0;
char llvm::GISelValueTrackingAnalysisLegacy::ID = 0;

INITIALIZE_PASS(GISelValueTrackingAnalysis, DEBUG_TYPE,
INITIALIZE_PASS(GISelValueTrackingAnalysisLegacy, DEBUG_TYPE,
"Analysis for ComputingKnownBits", false, true)

GISelValueTracking::GISelValueTracking(MachineFunction &MF, unsigned MaxDepth)
Expand Down Expand Up @@ -893,20 +893,57 @@ unsigned GISelValueTracking::computeNumSignBits(Register R, unsigned Depth) {
return computeNumSignBits(R, DemandedElts, Depth);
}

void GISelValueTrackingAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
void GISelValueTrackingAnalysisLegacy::getAnalysisUsage(
AnalysisUsage &AU) const {
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}

bool GISelValueTrackingAnalysis::runOnMachineFunction(MachineFunction &MF) {
bool GISelValueTrackingAnalysisLegacy::runOnMachineFunction(
MachineFunction &MF) {
return false;
}

GISelValueTracking &GISelValueTrackingAnalysis::get(MachineFunction &MF) {
GISelValueTracking &GISelValueTrackingAnalysisLegacy::get(MachineFunction &MF) {
if (!Info) {
unsigned MaxDepth =
MF.getTarget().getOptLevel() == CodeGenOptLevel::None ? 2 : 6;
Info = std::make_unique<GISelValueTracking>(MF, MaxDepth);
}
return *Info;
}

AnalysisKey GISelValueTrackingAnalysis::Key;

GISelValueTracking
GISelValueTrackingAnalysis::run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM) {
return Result(MF);
}

PreservedAnalyses
GISelValueTrackingPrinterPass::run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM) {
auto &VTA = MFAM.getResult<GISelValueTrackingAnalysis>(MF);
const auto &MRI = MF.getRegInfo();
OS << "name: ";
MF.getFunction().printAsOperand(OS, /*PrintType=*/false);
OS << '\n';

for (MachineBasicBlock &BB : MF) {
for (MachineInstr &MI : BB) {
for (MachineOperand &MO : MI.defs()) {
if (!MO.isReg() || MO.getReg().isPhysical())
continue;
Register Reg = MO.getReg();
if (!MRI.getType(Reg).isValid())
continue;
KnownBits Known = VTA.getKnownBits(Reg);
unsigned SignedBits = VTA.computeNumSignBits(Reg);
OS << " " << MO << " KnownBits:" << Known << " SignBits:" << SignedBits
<< '\n';
};
}
}
return PreservedAnalyses::all();
}
8 changes: 4 additions & 4 deletions 8 llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,
"Select target instructions out of generic instructions",
false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyBlockFrequencyInfoPass)
INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
Expand Down Expand Up @@ -120,8 +120,8 @@ class InstructionSelect::MIIteratorMaintainer : public GISelChangeObserver {

void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetPassConfig>();
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();

if (OptLevel != CodeGenOptLevel::None) {
AU.addRequired<ProfileSummaryInfoWrapperPass>();
Expand All @@ -146,7 +146,7 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
OptLevel = MF.getFunction().hasOptNone() ? CodeGenOptLevel::None
: MF.getTarget().getOptLevel();

VT = &getAnalysis<GISelValueTrackingAnalysis>().get(MF);
VT = &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
if (OptLevel != CodeGenOptLevel::None) {
PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
if (PSI && PSI->hasProfileSummary())
Expand Down
9 changes: 5 additions & 4 deletions 9 llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
"Legalize the Machine IR a function's Machine IR", false,
false)
Expand All @@ -86,8 +86,8 @@ void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetPassConfig>();
AU.addRequired<GISelCSEAnalysisWrapperPass>();
AU.addPreserved<GISelCSEAnalysisWrapperPass>();
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
getSelectionDAGFallbackAnalysisUsage(AU);
MachineFunctionPass::getAnalysisUsage(AU);
}
Expand Down Expand Up @@ -341,7 +341,8 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
AuxObservers.push_back(&LocObserver);

// This allows Known Bits Analysis in the legalizer.
GISelValueTracking *VT = &getAnalysis<GISelValueTrackingAnalysis>().get(MF);
GISelValueTracking *VT =
&getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);

const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
MFResult Result = legalizeMachineFunction(MF, LI, AuxObservers, LocObserver,
Expand Down
1 change: 1 addition & 0 deletions 1 llvm/lib/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ add_llvm_component_library(LLVMPasses
Analysis
CFGuard
CodeGen
GlobalISel
Core
Coroutines
HipStdPar
Expand Down
1 change: 1 addition & 0 deletions 1 llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include "llvm/CodeGen/FinalizeISel.h"
#include "llvm/CodeGen/FixupStatepointCallerSaved.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
#include "llvm/CodeGen/GlobalMerge.h"
#include "llvm/CodeGen/GlobalMergeFunctions.h"
#include "llvm/CodeGen/HardwareLoops.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ void AArch64O0PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetPassConfig>();
AU.setPreservesCFG();
getSelectionDAGFallbackAnalysisUsage(AU);
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
MachineFunctionPass::getAnalysisUsage(AU);
}

Expand All @@ -153,7 +153,8 @@ bool AArch64O0PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
auto &TPC = getAnalysis<TargetPassConfig>();

const Function &F = MF.getFunction();
GISelValueTracking *VT = &getAnalysis<GISelValueTrackingAnalysis>().get(MF);
GISelValueTracking *VT =
&getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);

const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();

Expand All @@ -174,7 +175,7 @@ INITIALIZE_PASS_BEGIN(AArch64O0PreLegalizerCombiner, DEBUG_TYPE,
"Combine AArch64 machine instrs before legalization",
false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
INITIALIZE_PASS_END(AArch64O0PreLegalizerCombiner, DEBUG_TYPE,
"Combine AArch64 machine instrs before legalization", false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -636,8 +636,8 @@ void AArch64PostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetPassConfig>();
AU.setPreservesCFG();
getSelectionDAGFallbackAnalysisUsage(AU);
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
if (!IsOptNone) {
AU.addRequired<MachineDominatorTreeWrapperPass>();
AU.addPreserved<MachineDominatorTreeWrapperPass>();
Expand Down Expand Up @@ -668,7 +668,8 @@ bool AArch64PostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
const auto *LI = ST.getLegalizerInfo();

GISelValueTracking *VT = &getAnalysis<GISelValueTrackingAnalysis>().get(MF);
GISelValueTracking *VT =
&getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
MachineDominatorTree *MDT =
IsOptNone ? nullptr
: &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
Expand Down Expand Up @@ -883,7 +884,7 @@ INITIALIZE_PASS_BEGIN(AArch64PostLegalizerCombiner, DEBUG_TYPE,
"Combine AArch64 MachineInstrs after legalization", false,
false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_END(AArch64PostLegalizerCombiner, DEBUG_TYPE,
"Combine AArch64 MachineInstrs after legalization", false,
false)
Expand Down
9 changes: 5 additions & 4 deletions 9 llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,8 +820,8 @@ void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetPassConfig>();
AU.setPreservesCFG();
getSelectionDAGFallbackAnalysisUsage(AU);
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
AU.addRequired<MachineDominatorTreeWrapperPass>();
AU.addPreserved<MachineDominatorTreeWrapperPass>();
AU.addRequired<GISelCSEAnalysisWrapperPass>();
Expand Down Expand Up @@ -852,7 +852,8 @@ bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
const Function &F = MF.getFunction();
bool EnableOpt =
MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
GISelValueTracking *VT = &getAnalysis<GISelValueTrackingAnalysis>().get(MF);
GISelValueTracking *VT =
&getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
MachineDominatorTree *MDT =
&getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
Expand All @@ -874,7 +875,7 @@ INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner, DEBUG_TYPE,
"Combine AArch64 machine instrs before legalization",
false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
INITIALIZE_PASS_END(AArch64PreLegalizerCombiner, DEBUG_TYPE,
"Combine AArch64 machine instrs before legalization", false,
Expand Down
9 changes: 5 additions & 4 deletions 9 llvm/lib/Target/AMDGPU/AMDGPUPostLegalizerCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,8 @@ void AMDGPUPostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetPassConfig>();
AU.setPreservesCFG();
getSelectionDAGFallbackAnalysisUsage(AU);
AU.addRequired<GISelValueTrackingAnalysis>();
AU.addPreserved<GISelValueTrackingAnalysis>();
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
if (!IsOptNone) {
AU.addRequired<MachineDominatorTreeWrapperPass>();
AU.addPreserved<MachineDominatorTreeWrapperPass>();
Expand All @@ -490,7 +490,8 @@ bool AMDGPUPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
const AMDGPULegalizerInfo *LI =
static_cast<const AMDGPULegalizerInfo *>(ST.getLegalizerInfo());

GISelValueTracking *VT = &getAnalysis<GISelValueTrackingAnalysis>().get(MF);
GISelValueTracking *VT =
&getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
MachineDominatorTree *MDT =
IsOptNone ? nullptr
: &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
Expand All @@ -512,7 +513,7 @@ INITIALIZE_PASS_BEGIN(AMDGPUPostLegalizerCombiner, DEBUG_TYPE,
"Combine AMDGPU machine instrs after legalization", false,
false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysis)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
INITIALIZE_PASS_END(AMDGPUPostLegalizerCombiner, DEBUG_TYPE,
"Combine AMDGPU machine instrs after legalization", false,
false)
Expand Down
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.