blob: c322c10b483a7b22ce666919d89ab5b9e18f3717 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_LICM_h
#define jit_LICM_h
#include "jit/IonAllocPolicy.h"
#include "jit/IonAnalysis.h"
#include "jit/MIR.h"
#include "jit/MIRGraph.h"
// This file represents the Loop Invariant Code Motion optimization pass
namespace js {
namespace jit {
class MIRGraph;
class MBasicBlock;
typedef Vector<MBasicBlock*, 1, IonAllocPolicy> BlockQueue;
typedef Vector<MInstruction*, 1, IonAllocPolicy> InstructionQueue;
class LICM
{
MIRGenerator *mir;
MIRGraph &graph;
public:
LICM(MIRGenerator *mir, MIRGraph &graph);
bool analyze();
};
class Loop
{
MIRGenerator *mir;
public:
// Loop code may return three values:
enum LoopReturn {
LoopReturn_Success,
LoopReturn_Error, // Compilation failure.
LoopReturn_Skip // The loop is not suitable for LICM, but there is no error.
};
public:
// A loop is constructed on a backedge found in the control flow graph.
Loop(MIRGenerator *mir, MBasicBlock *footer);
// Initializes the loop, finds all blocks and instructions contained in the loop.
LoopReturn init();
// Identifies hoistable loop invariant instructions and moves them out of the loop.
bool optimize();
private:
// These blocks define the loop. header_ points to the loop header
MBasicBlock *header_;
// The pre-loop block is the first predecessor of the loop header. It is where
// the loop is first entered and where hoisted instructions will be placed.
MBasicBlock* preLoop_;
bool hoistInstructions(InstructionQueue &toHoist);
// Utility methods for invariance testing and instruction hoisting.
bool isInLoop(MDefinition *ins);
bool isBeforeLoop(MDefinition *ins);
bool isLoopInvariant(MInstruction *ins);
bool isLoopInvariant(MDefinition *ins);
// This method determines if this block hot within a loop. That is, if it's
// always or usually run when the loop executes
bool checkHotness(MBasicBlock *block);
// Worklist and worklist usage methods
InstructionQueue worklist_;
bool insertInWorklist(MInstruction *ins);
MInstruction* popFromWorklist();
inline bool isHoistable(const MDefinition *ins) const {
return ins->isMovable() && !ins->isEffectful() && !ins->neverHoist();
}
};
} // namespace jit
} // namespace js
#endif /* jit_LICM_h */