blob: c3c2ab9427f604bb805d93596e891c4e541906fd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Pavel A. Ozhdikhin
*
*/
#ifndef _SSA_H_
#define _SSA_H_
#include "MemoryManager.h"
#include "Stack.h"
#include "FlowGraph.h"
#include "HashTable.h"
#include "Dominator.h"
#include "optpass.h"
namespace Jitrino {
class DomFrontier;
class SparseOpndMap;
struct OptimizerFlags;
//
// There is a VarDefSites for each var that records all CFG nodes in which
// the var is defined. Phi node also defines var. The two bit vectors are
// used to avoid adding/recording CFG nodes twice.
//
class VarDefSites {
public:
VarDefSites(MemoryManager& m, U_32 max)
: stack(m), alreadyRecorded(m, max), insertedPhi(m, max) {}
void addDefSite(Node* node) {
// avoid pushing the same node twice onto the stack
if (alreadyRecorded.getBit(node->getDfNum()))
return;
alreadyRecorded.setBit(node->getDfNum(),true);
stack.push(node);
}
Node* removeDefSite() {return stack.pop();}
void insertPhiSite(Node* node) {
insertedPhi.setBit(node->getDfNum(), true);
addDefSite(node);
}
bool beenInsertedPhi(Node* node) {
return insertedPhi.getBit(node->getDfNum());
}
bool isDefSite(Node* node) {
return alreadyRecorded.getBit(node->getDfNum());
}
private:
Stack<Node> stack;
BitSet alreadyRecorded; // def sites (blocks) been recorded
BitSet insertedPhi; // blocks that have been inserted phi
};
//
// A hash table that keeps the mapping: var --> VarDefSites
//
class DefSites {
public:
DefSites(MemoryManager& m, U_32 n) : table(m,32), mm(m), numNodes(n) {}
void addVarDefSite(VarOpnd* var, Node* node) {
if (var == NULL) return;
VarDefSites* varSites = table.lookup(var);
if (varSites == NULL) {
varSites = new (mm) VarDefSites(mm, numNodes);
table.insert(var,varSites);
}
varSites->addDefSite(node);
}
PtrHashTable<VarDefSites>* getVarDefSites() {return &table;}
private:
PtrHashTable<VarDefSites> table;
MemoryManager& mm;
U_32 numNodes;
};
class RenameStack;
class SSABuilder {
public:
SSABuilder(OpndManager& om, InstFactory& factory, DomFrontier& df, ControlFlowGraph* f, const OptimizerFlags& optFlags)
: instFactory(factory), frontier(df), opndManager(om), fg(f), createPhi(false), optimizerFlags(optFlags) {}
bool convertSSA(MethodDesc& methodDesc);
bool fixupSSA(MethodDesc& methodDesc, bool useBetterAlg);
bool fixupVars(ControlFlowGraph* fg, MethodDesc& methodDesc);
static void deconvertSSA(ControlFlowGraph* fg,OpndManager& opndManager);
static void splitSsaWebs(ControlFlowGraph* fg,OpndManager& opndManager);
static bool phiInstsOnRightPositionsInBB(Node* node);
private:
void findDefSites(DefSites& allDefSites);
void insertPhi(DefSites& allDefSites);
void createPhiInst(VarOpnd* var, Node* insertedLoc);
void addPhiSrc(PhiInst* i, SsaVarOpnd* src);
void renameNode(RenameStack *rs, DominatorNode* dt,
const StlVectorSet<VarOpnd *> *whatVars);
void clearPhiSrcs(Node *, const StlVectorSet<VarOpnd *> *whatVars);
void clearPhiSrcs2(Node *,
const StlVectorSet<VarOpnd *> *whatVars,
StlVector<VarOpnd *> *changedVars,
const StlVectorSet<Opnd *> *removedVars,
StlVector<Node *> &scratchNodeList);
bool checkForTrivialPhis(Node *,
StlVector<VarOpnd *> &changedVars);
void checkForTrivialPhis2(Node *node,
const StlVectorSet<VarOpnd *> *lookatVars,
StlVector<VarOpnd *> *changedVars,
StlVector<Opnd *> *removedVars);
InstFactory& instFactory;
DomFrontier& frontier;
OpndManager& opndManager;
ControlFlowGraph* fg;
bool createPhi;
const OptimizerFlags& optimizerFlags;
friend class ClearPhiSrcsWalker;
friend class CheckForTrivialPhisWalker;
friend class ClearPhiSrcsWalker2;
friend class CheckForTrivialPhisWalker2;
friend class SsaRenameWalker;
};
} //namespace Jitrino
#endif // _SSA_H_