Jit/hir/optimization.h (139 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #pragma once #include "Jit/hir/hir.h" #include "Jit/hir/type.h" #include "Jit/ref.h" #include "Jit/util.h" #include <functional> #include <memory> #include <string> #include <unordered_map> namespace jit { namespace hir { class BasicBlock; class Environment; class Function; class Instr; class LoadAttr; class Register; class Pass { public: explicit Pass(const char* name) : name_(name) {} virtual ~Pass() {} virtual void Run(Function& irfunc) = 0; const char* name() const { return name_; } protected: const char* name_; }; using PassFactory = std::function<std::unique_ptr<Pass>()>; // Inserts incref/decref instructions. class RefcountInsertion : public Pass { public: RefcountInsertion() : Pass("RefcountInsertion") {} void Run(Function& irfunc) override; static std::unique_ptr<RefcountInsertion> Factory() { return std::make_unique<RefcountInsertion>(); } private: DISALLOW_COPY_AND_ASSIGN(RefcountInsertion); }; // Perform a mixed bag of strength-reduction optimizations: remove redundant // null checks, conversions, loads from compile-time constant containers, etc. // // If your optimization requires no global analysis or state and operates on // one instruction at a time by inspecting its inputs (and anything reachable // from them), it may be a good fit for Simplify. class Simplify : public Pass { public: Simplify() : Pass("Simplify") {} void Run(Function& func) override; static std::unique_ptr<Simplify> Factory() { return std::make_unique<Simplify>(); } private: DISALLOW_COPY_AND_ASSIGN(Simplify); }; class DynamicComparisonElimination : public Pass { public: DynamicComparisonElimination() : Pass("DynamicComparisonElimination") {} void Run(Function& irfunc) override; static std::unique_ptr<DynamicComparisonElimination> Factory() { return std::make_unique<DynamicComparisonElimination>(); } private: Instr* ReplaceCompare(Compare* compare, IsTruthy* truthy); Instr* ReplaceTypeCheck( Function& irfunc, CondBranch& cond_branch, BasicBlock& block, Register* obj_op, Register* type_op, Instr* isinstance, IsTruthy* truthy, bool is_subtype, bool is_optional); Instr* ReplaceVectorCall( Function& irfunc, CondBranch& cond_branch, BasicBlock& block, VectorCall* vectorcall, IsTruthy* truthy); void InitBuiltins(); DISALLOW_COPY_AND_ASSIGN(DynamicComparisonElimination); bool inited_builtins_{false}; PyCFunction isinstance_func_{nullptr}; }; // Eliminate Assign instructions by propagating copies. class CopyPropagation : public Pass { public: CopyPropagation() : Pass("CopyPropagation") {} void Run(Function& irfunc) override; static std::unique_ptr<CopyPropagation> Factory() { return std::make_unique<CopyPropagation>(); } }; // Eliminate instructions whose outputs are not used in a return or by // other instructions with side-effects class DeadCodeElimination : public Pass { public: DeadCodeElimination() : Pass("DeadCodeElimination") {} void Run(Function& irfunc) override; static std::unique_ptr<DeadCodeElimination> Factory() { return std::make_unique<DeadCodeElimination>(); } }; class GuardTypeRemoval : public Pass { public: GuardTypeRemoval() : Pass("GuardTypeRemoval") {} void Run(Function& irfunc) override; static std::unique_ptr<GuardTypeRemoval> Factory() { return std::make_unique<GuardTypeRemoval>(); } }; // Remove Phis that only have one unique input value (other than their output). class PhiElimination : public Pass { public: PhiElimination() : Pass("PhiElimination") {} void Run(Function& irfunc) override; static std::unique_ptr<PhiElimination> Factory() { return std::make_unique<PhiElimination>(); } }; class CleanCFG : public Pass { public: CleanCFG() : Pass("CleanCFG") {} void Run(Function& irfunc) override; // Remove blocks that aren't reachable from the entry, whether or not they're // empty. Avoid using this alone; use CleanCFG instead. Returns true if it // changed the graph and false otherwise. static bool RemoveUnreachableBlocks(CFG* cfg); // Remove any blocks that consist of a single jump to another block. Avoid // using this alone; use CleanCFG instead. static bool RemoveTrampolineBlocks(CFG* cfg); static std::unique_ptr<CleanCFG> Factory() { return std::make_unique<CleanCFG>(); } }; class InlineFunctionCalls : public Pass { public: InlineFunctionCalls() : Pass("InlineFunctionCalls") {} void Run(Function& irfunc) override; static std::unique_ptr<InlineFunctionCalls> Factory() { return std::make_unique<InlineFunctionCalls>(); } }; class PassRegistry { public: PassRegistry(); std::unique_ptr<Pass> MakePass(const std::string& name); private: DISALLOW_COPY_AND_ASSIGN(PassRegistry); std::unordered_map<std::string, PassFactory> factories_; }; } // namespace hir } // namespace jit