| Index: src/IceOperand.cpp
|
| diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
|
| index 9e523be249aedfaa714ea9381c1fdb297fb7efb9..d1854f4f0f0a6d4e48306b87acef22f227f2b84b 100644
|
| --- a/src/IceOperand.cpp
|
| +++ b/src/IceOperand.cpp
|
| @@ -165,13 +165,13 @@ void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node,
|
| // of the block that actually uses a Variable.
|
| assert(Node);
|
| bool MakeMulti = false;
|
| + if (IsImplicit)
|
| + MakeMulti = true;
|
| // A phi source variable conservatively needs to be marked as
|
| // multi-block, even if its definition is in the same block. This
|
| // is because there can be additional control flow before branching
|
| // back to this node, and the variable is live throughout those
|
| // nodes.
|
| - if (IsImplicit)
|
| - MakeMulti = true;
|
| if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr))
|
| MakeMulti = true;
|
|
|
| @@ -201,23 +201,63 @@ void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) {
|
| // of the block, consider not marking this as a separate use. But
|
| // be careful not to omit all uses of the variable if markDef() and
|
| // markUse() both use this optimization.
|
| + assert(Node);
|
| + Definitions.push_back(Instr);
|
| const bool IsFromDef = true;
|
| const bool IsImplicit = false;
|
| markUse(Instr, Node, IsFromDef, IsImplicit);
|
| switch (MultiDef) {
|
| case MDS_Unknown:
|
| + assert(SingleDefNode == NULL);
|
| MultiDef = MDS_SingleDef;
|
| - SingleDefInst = Instr;
|
| + SingleDefNode = Node;
|
| break;
|
| case MDS_SingleDef:
|
| - MultiDef = MDS_MultiDef;
|
| - SingleDefInst = NULL;
|
| + assert(SingleDefNode);
|
| + if (Node == SingleDefNode) {
|
| + MultiDef = MDS_MultiDefSingleBlock;
|
| + } else {
|
| + MultiDef = MDS_MultiDefMultiBlock;
|
| + SingleDefNode = NULL;
|
| + }
|
| + break;
|
| + case MDS_MultiDefSingleBlock:
|
| + assert(SingleDefNode);
|
| + if (Node != SingleDefNode) {
|
| + MultiDef = MDS_MultiDefMultiBlock;
|
| + SingleDefNode = NULL;
|
| + }
|
| break;
|
| - case MDS_MultiDef:
|
| + case MDS_MultiDefMultiBlock:
|
| + assert(SingleDefNode == NULL);
|
| break;
|
| }
|
| }
|
|
|
| +const Inst *VariableTracking::getFirstDefinition() const {
|
| + switch (MultiDef) {
|
| + case MDS_Unknown:
|
| + case MDS_MultiDefMultiBlock:
|
| + return NULL;
|
| + case MDS_SingleDef:
|
| + case MDS_MultiDefSingleBlock:
|
| + assert(!Definitions.empty());
|
| + return Definitions[0];
|
| + }
|
| +}
|
| +
|
| +const Inst *VariableTracking::getSingleDefinition() const {
|
| + switch (MultiDef) {
|
| + case MDS_Unknown:
|
| + case MDS_MultiDefMultiBlock:
|
| + case MDS_MultiDefSingleBlock:
|
| + return NULL;
|
| + case MDS_SingleDef:
|
| + assert(!Definitions.empty());
|
| + return Definitions[0];
|
| + }
|
| +}
|
| +
|
| void VariablesMetadata::init() {
|
| Metadata.clear();
|
| Metadata.resize(Func->getNumVariables());
|
| @@ -243,6 +283,18 @@ void VariablesMetadata::init() {
|
| ++I) {
|
| if ((*I)->isDeleted())
|
| continue;
|
| + if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(*I)) {
|
| + // A FakeKill instruction indicates certain Variables (usually
|
| + // physical scratch registers) are redefined, so we register
|
| + // them as defs.
|
| + for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) {
|
| + Variable *Var = llvm::cast<Variable>((*I)->getSrc(SrcNum));
|
| + SizeT VarNum = Var->getIndex();
|
| + assert(VarNum < Metadata.size());
|
| + Metadata[VarNum].markDef(Kill, Node);
|
| + }
|
| + continue; // no point in executing the rest
|
| + }
|
| if (Variable *Dest = (*I)->getDest()) {
|
| SizeT DestNum = Dest->getIndex();
|
| assert(DestNum < Metadata.size());
|
| @@ -275,18 +327,35 @@ bool VariablesMetadata::isMultiDef(const Variable *Var) const {
|
| }
|
|
|
| bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
|
| - if (getDefinition(Var) == NULL)
|
| + if (Var->getIsArg())
|
| return true;
|
| + if (!isTracked(Var))
|
| + return true; // conservative answer
|
| SizeT VarNum = Var->getIndex();
|
| // Conservatively return true if the state is unknown.
|
| return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
|
| }
|
|
|
| -const Inst *VariablesMetadata::getDefinition(const Variable *Var) const {
|
| +const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
|
| + if (!isTracked(Var))
|
| + return NULL; // conservative answer
|
| + SizeT VarNum = Var->getIndex();
|
| + return Metadata[VarNum].getFirstDefinition();
|
| +}
|
| +
|
| +const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
|
| if (!isTracked(Var))
|
| return NULL; // conservative answer
|
| SizeT VarNum = Var->getIndex();
|
| - return Metadata[VarNum].getDefinition();
|
| + return Metadata[VarNum].getSingleDefinition();
|
| +}
|
| +
|
| +const InstDefList &
|
| +VariablesMetadata::getDefinitions(const Variable *Var) const {
|
| + if (!isTracked(Var))
|
| + return NoDefinitions;
|
| + SizeT VarNum = Var->getIndex();
|
| + return Metadata[VarNum].getDefinitions();
|
| }
|
|
|
| const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
|
| @@ -296,6 +365,8 @@ const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
|
| return Metadata[VarNum].getNode();
|
| }
|
|
|
| +const InstDefList VariablesMetadata::NoDefinitions;
|
| +
|
| // ======================== dump routines ======================== //
|
|
|
| void Variable::emit(const Cfg *Func) const {
|
|
|