blob: 2a3de981921f78793a7ca4e8f752bf7bfafe2aae [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 _MEMORY_OPT_REP_H
#define _MEMORY_OPT_REP_H
#include "./ssa/SSA.h"
namespace Jitrino {
class Type;
class AliasAnalyzer;
// each AliasRep represents a set of memory locations
// note that we don't distinguish singletons, that's a separate issue
// overlap between sets is tested by using AliasManager::mayAlias()
class AliasRep {
public:
enum Kind {
NullKind, // empty set
GlobalKind, // overlaps all globals
LocalKind, // overlaps all non-globals
AnyKind, // full set: everything
UnknownKind, // other opnd, should not be vtable, methodptr, arraylen, field
ObjectFieldKind, // parameterized by object and field desc
UnresolvedObjectFieldKind, // field of unresolved type
ArrayElementKind, // offset into array, parameterized by array object and offset opnd
StaticFieldKind, // just field, type is pulled out too
UnresolvedStaticFieldKind, // just field, type is pulled out too
ObjectVtableKind, // opnd
MethodPtrKind, // opnd, desc
FunPtrKind, // opnd
TypeVtableKind, // type
ArrayLenKind, // opnd
NewObjectKind, // opnd (all fields initialized by NewObject or NewArray)
NewTypeKind, // type (all fields initialized by <clinit>
FinishObjectKind, // all final fields of an object
FinishTypeKind, // all final fields of a type
LockKind, // opnd
TypeLockKind // type
} kind;
Opnd *opnd;
Opnd *idx;
Opnd *enclClass;
Type *type;
TypeMemberDesc *desc;
int id;
AliasRep(int) : kind(NullKind), opnd(0), idx(0), enclClass(0), type(0), desc(0), id(0) {};
AliasRep(Kind k=NullKind) : kind(k), opnd(0), idx(0), enclClass(0),type(0), desc(0), id(0) {};
AliasRep(Kind k, Opnd *op) : kind(k), opnd(op), idx(0), enclClass(0),type(0), desc(0), id(0) {
};
AliasRep(Kind k, Opnd *op, Opnd *idx0) : kind(k), opnd(op), idx(idx0), enclClass(0), type(0), desc(0), id(0) {
};
AliasRep(Kind k, Opnd *op, TypeMemberDesc *md) : kind(k), opnd(op), idx(0), enclClass(0), type(0), desc(md), id(0) {
};
AliasRep(Kind k, Type *t) : kind(k), opnd(0), idx(0), enclClass(0), type(t), desc(0), id(0) {
};
AliasRep(Kind k, TypeMemberDesc *md) : kind(k), opnd(0), idx(0), enclClass(0), type(0), desc(md), id(0) {
};
AliasRep(Kind k, Opnd* op, Opnd* enc, Opnd* idx0) : kind(k), opnd(op), idx(idx0), enclClass(enc), type(0), desc(0), id(0) {
};
void dump(::std::ostream &os) const;
void print(::std::ostream &os) const;
bool isObjectFinal() const; // all pointed to locations are final for one object
Opnd *getFinalObject() const; // get a representation for that object
bool isTypeFinal() const; // all pointed to locations are final for one type
NamedType *getFinalType() const; // get a representation for that type
bool isEmpty() const { return (kind == NullKind); };
bool operator < (const AliasRep &other) const {
return ((kind < other.kind) ||
((kind == other.kind) &&
((opnd < other.opnd) ||
((opnd == other.opnd) &&
((enclClass < other.enclClass) ||
((enclClass== other.enclClass) &&
((type < other.type) ||
((type == other.type) &&
((desc < other.desc) ||
((desc == other.desc) &&
(idx < other.idx)))))))))));
}
bool operator == (const AliasRep &other) const {
return ((kind == other.kind) &&
(opnd == other.opnd) &&
(enclClass == other.enclClass) &&
(type == other.type) &&
(desc == other.desc) &&
(idx == other.idx));
}
operator size_t() const {
return (((size_t) kind) ^
((size_t) opnd) ^
((size_t) type) ^
((size_t) desc) ^
((size_t) enclClass));
}
};
class AliasManager {
friend class MemoryOpt;
public:
typedef StlVector<AliasRep> AliasList;
private:
U_32 numAliasReps;
AliasList allAliasReps;
typedef StlHashMap<AliasRep, StlVectorSet<AliasRep> *> AliasRep2AliasReps;
AliasRep2AliasReps canon2others;
typedef StlHashMap<AliasRep, AliasRep> Alias2Alias;
Alias2Alias other2canon;
typedef StlHashMap<AliasRep, AliasList *> Ancestors;
Ancestors ancestors;
AliasRep findOrInsertAlias(AliasRep rep);
// use only during initial alias set construction
bool isDuplicate(const AliasRep &a, const AliasRep &b);
void sawDuplicate(const AliasRep &ar, const AliasRep &canon);
public:
AliasRep getReference(Opnd *addr); // examine for an indirect addr
AliasRep getObjectField(Opnd *obj, TypeMemberDesc *field);
AliasRep getUnresolvedObjectField(Opnd *obj, Opnd* enclClass, Opnd* cpIdx);
AliasRep getStaticField(TypeMemberDesc *field);
AliasRep getUnresolvedStaticField(Opnd* enclClass, Opnd* cpIdx);
AliasRep getArrayElementByType(Type *elementType);
AliasRep getLock(Opnd *obj);
AliasRep getLock(Type *type);
AliasRep getAny();
AliasRep getAnyGlobal();
AliasRep getVtableOf(Opnd *opnd);
AliasRep getMethodPtr(Opnd *opnd, MethodDesc *desc);
AliasRep getFunPtr(Opnd *opnd);
AliasRep getNoMemory();
AliasRep getAnyEscaping();
AliasRep getAnyLocal();
AliasRep getVtableOf(NamedType *type);
AliasRep getArrayLen(Opnd *opnd);
AliasRep getArrayElements(Opnd *array, Opnd *offset, Opnd *length);
AliasRep getObjectNew(Opnd *opnd); // fields initialized by NewObject or NewArray
AliasRep getTypeNew(NamedType *type); // (final static) fields initialized by type initialization
AliasRep getFinishObject(Opnd *obj); // final fields of object
AliasRep getFinishType(NamedType *type); // final fields of type
MemoryManager &mm;
AliasAnalyzer *analyzer;
TypeManager* typeManager;
void dumpAliasReps(::std::ostream &os) const;
AliasManager(MemoryManager &mm0, AliasAnalyzer *aa, TypeManager* tm) :
numAliasReps(0), allAliasReps(mm0), canon2others(mm0), other2canon(mm0), ancestors(mm0), mm(mm0), analyzer(aa), typeManager(tm) {};
bool mayAlias(const AliasRep &a, const AliasRep &b);
// yields a list of ancestors in any order
const AliasList *getAncestors(const AliasRep &a);
private:
// adds parents to result, returning true if nonempty
// yields a list of ancestors in any order
void computeAncestors(const AliasRep &a, AliasList *result);
};
class InstMemBehavior {
public:
bool acquire, release;
StlVectorSet<AliasRep> defs;
StlVectorSet<AliasRep> uses;
InstMemBehavior(MemoryManager &mm)
: acquire(false), release(false), defs(mm), uses(mm)
{};
InstMemBehavior(const StlVectorSet<AliasRep> &defs0,
const StlVectorSet<AliasRep> &uses0)
: acquire(false), release(false), defs(defs0), uses(uses0) {};
};
class AliasDefSites : public StlHashMap<AliasRep, VarDefSites *> {
MemoryManager &mm;
U_32 numNodes;
public:
typedef StlHashMap<AliasRep, VarDefSites *> BaseType;
AliasDefSites(MemoryManager &m, U_32 n): BaseType(m), mm(m), numNodes(n) {};
void addAliasDefSite(const AliasRep &rep, Node* node) {
VarDefSites* aliasSites = (*this)[rep];
if (!aliasSites) {
aliasSites = new (mm) VarDefSites(mm, numNodes);
(*this)[rep] = aliasSites;
}
aliasSites->addDefSite(node);
};
bool hasAliasDefSite(const AliasRep &rep, Node* node) {
iterator aliasSitesIter = this->find(rep);
if (aliasSitesIter == end()) {
return false;
}
VarDefSites* aliasSites = (*aliasSitesIter).second;
return aliasSites->isDefSite(node);
};
};
class MemPhiSites {
public:
MemoryManager &mm;
size_t numNodes;
StlVector<AliasRep> **nodeArray;
MemPhiSites(MemoryManager &mm0, size_t numNodes) : mm(mm0), nodeArray() {
nodeArray = new (mm0) StlVector<AliasRep> *[numNodes];
for (size_t i = 0; i < numNodes; i++) {
nodeArray[i] = 0;
}
}
void addMemPhi(Node *n, const AliasRep &rep) {
size_t i = n->getDfNum();
StlVector<AliasRep> *a = nodeArray[i];
if (!a) {
a = new (mm) StlVector<AliasRep>(mm);
nodeArray[i] = a;
}
a->push_back(rep);
}
const StlVector<AliasRep> *getMemPhis(Node *n) const {
size_t i = n->getDfNum();
return nodeArray[i];
}
};
struct AliasBinding {
Inst *inst;
U_32 when;
AliasBinding(Inst *inst0=0, U_32 when0=0) : inst(inst0), when(when0) {};
};
bool operator !=(const AliasBinding &a, const AliasBinding &b) {
return ((a.inst != b.inst) || (a.when != b.when));
}
class DescendentSet : public StlVectorSet<AliasRep> {
public:
DescendentSet(MemoryManager &m, U_32 depth0) : StlVectorSet<AliasRep>(m), depth(depth0) {};
DescendentSet(MemoryManager &m, DescendentSet *other, U_32 depth0)
: StlVectorSet<AliasRep>(m), depth(depth0)
{
insert(other->begin(), other->end());
}
U_32 depth;
};
class AliasRenameMap {
typedef SparseScopedMap<AliasRep, AliasBinding> DefMap;
typedef SparseScopedMap<AliasRep, DescendentSet *> DescendentMap;
DefMap defMap;
DescendentMap activeDescendents;
U_32 depth;
U_32 timeCount;
AliasManager *aliasManager;
MemoryManager &mm;
public:
AliasRenameMap(MemoryManager &m, AliasManager *am0,
size_t sizeEstimate1,
size_t sizeEstimate2) :
defMap(sizeEstimate1, m),
activeDescendents(sizeEstimate2, m),
depth(0), timeCount(0),
aliasManager(am0), mm(m) {};
void enter_scope();
void exit_scope();
void insert(const AliasRep &rep, Inst *defInst);
// finds most recent relevant defs
typedef StlVectorSet<Inst *> DefsSet;
void lookup(const AliasRep &rep, DefsSet &defs);
};
} //namespace Jitrino
#endif // _MEMORY_OPT_REP_H