Commit 144cdcea by Jim Stichnoth

Subzero: Refactor tracking of Defs and block-local Variables.

This affects tracking of two kinds of Variable metadata: whether a Variable is block-local (i.e., all uses are in a single block) and if so, which CfgNode that is; and whether a Variable has a single defining instruction, and if so, which Inst that is. Originally, this metadata was constructed incrementally, which was quite fragile and most likely inaccurate under many circumstances. In the new approach, this metadata is reconstructed in a separate pass as needed. As a side benefit, the metadata fields are removed from each Variable and pulled into a separate structure, shrinking the size of Variable. There should be no functional changes, except that simple stack slot coalescing is turned off under Om1, since it takes a separate pass to calculate block-local variables, and passes are minimized under Om1. As a result, a couple of the lit tests needed to be changed. There are a few non-mechanical changes, generally to tighten up Variable tracking for liveness analysis. This is being done mainly to get precise Variable definition information so that register allocation can infer the best register preferences as well as when overlapping live ranges are allowable. BUG=none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/589003002
parent cff9dae7
...@@ -28,7 +28,7 @@ Cfg::Cfg(GlobalContext *Ctx) ...@@ -28,7 +28,7 @@ Cfg::Cfg(GlobalContext *Ctx)
IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL), IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL),
NextInstNumber(1), Live(NULL), NextInstNumber(1), Live(NULL),
Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)), Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
CurrentNode(NULL) {} VMetadata(new VariablesMetadata(this)), CurrentNode(NULL) {}
Cfg::~Cfg() {} Cfg::~Cfg() {}
...@@ -45,16 +45,20 @@ CfgNode *Cfg::makeNode(const IceString &Name) { ...@@ -45,16 +45,20 @@ CfgNode *Cfg::makeNode(const IceString &Name) {
return Node; return Node;
} }
Variable *Cfg::makeVariable(Type Ty, const CfgNode *Node, Variable *Cfg::makeVariable(Type Ty, const IceString &Name) {
const IceString &Name) { return makeVariable<Variable>(Ty, Name);
return makeVariable<Variable>(Ty, Node, Name);
} }
void Cfg::addArg(Variable *Arg) { void Cfg::addArg(Variable *Arg) {
Arg->setIsArg(this); Arg->setIsArg();
Args.push_back(Arg); Args.push_back(Arg);
} }
void Cfg::addImplicitArg(Variable *Arg) {
Arg->setIsImplicitArg();
ImplicitArgs.push_back(Arg);
}
// Returns whether the stack frame layout has been computed yet. This // Returns whether the stack frame layout has been computed yet. This
// is used for dumping the stack frame location of Variables. // is used for dumping the stack frame location of Variables.
bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
...@@ -147,6 +151,7 @@ void Cfg::genFrame() { ...@@ -147,6 +151,7 @@ void Cfg::genFrame() {
// completely with a single block. It is a quick single pass and // completely with a single block. It is a quick single pass and
// doesn't need to iterate until convergence. // doesn't need to iterate until convergence.
void Cfg::livenessLightweight() { void Cfg::livenessLightweight() {
getVMetadata()->init();
for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
(*I)->livenessLightweight(); (*I)->livenessLightweight();
} }
...@@ -154,6 +159,7 @@ void Cfg::livenessLightweight() { ...@@ -154,6 +159,7 @@ void Cfg::livenessLightweight() {
void Cfg::liveness(LivenessMode Mode) { void Cfg::liveness(LivenessMode Mode) {
Live.reset(new Liveness(this, Mode)); Live.reset(new Liveness(this, Mode));
getVMetadata()->init();
Live->init(); Live->init();
// Initialize with all nodes needing to be processed. // Initialize with all nodes needing to be processed.
llvm::BitVector NeedToProcess(Nodes.size(), true); llvm::BitVector NeedToProcess(Nodes.size(), true);
...@@ -361,9 +367,12 @@ void Cfg::dump(const IceString &Message) { ...@@ -361,9 +367,12 @@ void Cfg::dump(const IceString &Message) {
for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
I != E; ++I) { I != E; ++I) {
Variable *Var = *I; Variable *Var = *I;
Str << "//" Str << "// multiblock=";
<< " multiblock=" << Var->isMultiblockLife() << " " if (getVMetadata()->isTracked(Var))
<< " weight=" << Var->getWeight() << " "; Str << getVMetadata()->isMultiBlock(Var);
else
Str << "?";
Str << " weight=" << Var->getWeight() << " ";
Var->dump(this); Var->dump(this);
if (Variable *Pref = Var->getPreferredRegister()) { if (Variable *Pref = Var->getPreferredRegister()) {
Str << " pref="; Str << " pref=";
......
...@@ -63,17 +63,15 @@ public: ...@@ -63,17 +63,15 @@ public:
// Manage Variables. // Manage Variables.
// Create a new Variable with a particular type and an optional // Create a new Variable with a particular type and an optional
// name. The Node argument is the node where the variable is defined. // name. The Node argument is the node where the variable is defined.
template <typename T> template <typename T> T *makeVariable(Type Ty, const IceString &Name = "") {
T *makeVariable(Type Ty, const CfgNode *Node, const IceString &Name = "") {
SizeT Index = Variables.size(); SizeT Index = Variables.size();
T *Var = T::create(this, Ty, Node, Index, Name); T *Var = T::create(this, Ty, Index, Name);
Variables.push_back(Var); Variables.push_back(Var);
return Var; return Var;
} }
// TODO(stichnot): Remove this function with C++11, and use default // TODO(stichnot): Remove this function with C++11, and use default
// argument <typename T=Variable> above. // argument <typename T=Variable> above.
Variable *makeVariable(Type Ty, const CfgNode *Node, Variable *makeVariable(Type Ty, const IceString &Name = "");
const IceString &Name = "");
SizeT getNumVariables() const { return Variables.size(); } SizeT getNumVariables() const { return Variables.size(); }
const VarList &getVariables() const { return Variables; } const VarList &getVariables() const { return Variables; }
...@@ -81,9 +79,12 @@ public: ...@@ -81,9 +79,12 @@ public:
void addArg(Variable *Arg); void addArg(Variable *Arg);
const VarList &getArgs() const { return Args; } const VarList &getArgs() const { return Args; }
VarList &getArgs() { return Args; } VarList &getArgs() { return Args; }
void addImplicitArg(Variable *Arg);
const VarList &getImplicitArgs() const { return ImplicitArgs; }
// Miscellaneous accessors. // Miscellaneous accessors.
TargetLowering *getTarget() const { return Target.get(); } TargetLowering *getTarget() const { return Target.get(); }
VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
Liveness *getLiveness() const { return Live.get(); } Liveness *getLiveness() const { return Live.get(); }
bool hasComputedFrame() const; bool hasComputedFrame() const;
...@@ -161,8 +162,10 @@ private: ...@@ -161,8 +162,10 @@ private:
InstNumberT NextInstNumber; InstNumberT NextInstNumber;
VarList Variables; VarList Variables;
VarList Args; // subset of Variables, in argument order VarList Args; // subset of Variables, in argument order
VarList ImplicitArgs; // subset of Variables
llvm::OwningPtr<Liveness> Live; llvm::OwningPtr<Liveness> Live;
llvm::OwningPtr<TargetLowering> Target; llvm::OwningPtr<TargetLowering> Target;
llvm::OwningPtr<VariablesMetadata> VMetadata;
// CurrentNode is maintained during dumping/emitting just for // CurrentNode is maintained during dumping/emitting just for
// validating Variable::DefNode. Normally, a traversal over // validating Variable::DefNode. Normally, a traversal over
......
...@@ -47,7 +47,6 @@ void CfgNode::appendInst(Inst *Inst) { ...@@ -47,7 +47,6 @@ void CfgNode::appendInst(Inst *Inst) {
} else { } else {
Insts.push_back(Inst); Insts.push_back(Inst);
} }
Inst->updateVars(this);
} }
// Renumbers the non-deleted instructions in the node. This needs to // Renumbers the non-deleted instructions in the node. This needs to
...@@ -92,9 +91,8 @@ void CfgNode::computePredecessors() { ...@@ -92,9 +91,8 @@ void CfgNode::computePredecessors() {
// blocks. Note that this transformation preserves SSA form. // blocks. Note that this transformation preserves SSA form.
void CfgNode::placePhiLoads() { void CfgNode::placePhiLoads() {
for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
Inst *Inst = (*I)->lower(Func, this); Inst *Inst = (*I)->lower(Func);
Insts.insert(Insts.begin(), Inst); Insts.insert(Insts.begin(), Inst);
Inst->updateVars(this);
} }
} }
...@@ -213,7 +211,6 @@ void CfgNode::placePhiStores() { ...@@ -213,7 +211,6 @@ void CfgNode::placePhiStores() {
Insts.insert(SafeInsertionPoint, NewInst); Insts.insert(SafeInsertionPoint, NewInst);
else else
Insts.insert(InsertionPoint, NewInst); Insts.insert(InsertionPoint, NewInst);
NewInst->updateVars(this);
} }
} }
} }
...@@ -281,12 +278,12 @@ void CfgNode::livenessLightweight() { ...@@ -281,12 +278,12 @@ void CfgNode::livenessLightweight() {
I != E; ++I) { I != E; ++I) {
if ((*I)->isDeleted()) if ((*I)->isDeleted())
continue; continue;
(*I)->livenessLightweight(Live); (*I)->livenessLightweight(Func, Live);
} }
for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
if ((*I)->isDeleted()) if ((*I)->isDeleted())
continue; continue;
(*I)->livenessLightweight(Live); (*I)->livenessLightweight(Func, Live);
} }
} }
......
...@@ -56,7 +56,7 @@ template <typename T> static std::string LLVMObjectAsString(const T *O) { ...@@ -56,7 +56,7 @@ template <typename T> static std::string LLVMObjectAsString(const T *O) {
class LLVM2ICEConverter { class LLVM2ICEConverter {
public: public:
LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext)
: Ctx(Ctx), Func(NULL), CurrentNode(NULL), TypeConverter(LLVMContext) {} : Ctx(Ctx), Func(NULL), TypeConverter(LLVMContext) {}
// Caller is expected to delete the returned Ice::Cfg object. // Caller is expected to delete the returned Ice::Cfg object.
Ice::Cfg *convertFunction(const Function *F) { Ice::Cfg *convertFunction(const Function *F) {
...@@ -68,7 +68,6 @@ public: ...@@ -68,7 +68,6 @@ public:
Func->setInternal(F->hasInternalLinkage()); Func->setInternal(F->hasInternalLinkage());
// The initial definition/use of each arg is the entry node. // The initial definition/use of each arg is the entry node.
CurrentNode = mapBasicBlockToNode(&F->getEntryBlock());
for (Function::const_arg_iterator ArgI = F->arg_begin(), for (Function::const_arg_iterator ArgI = F->arg_begin(),
ArgE = F->arg_end(); ArgE = F->arg_end();
ArgI != ArgE; ++ArgI) { ArgI != ArgE; ++ArgI) {
...@@ -85,7 +84,6 @@ public: ...@@ -85,7 +84,6 @@ public:
} }
for (Function::const_iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; for (Function::const_iterator BBI = F->begin(), BBE = F->end(); BBI != BBE;
++BBI) { ++BBI) {
CurrentNode = mapBasicBlockToNode(BBI);
convertBasicBlock(BBI); convertBasicBlock(BBI);
} }
Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock())); Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock()));
...@@ -132,8 +130,7 @@ private: ...@@ -132,8 +130,7 @@ private:
if (IceTy == Ice::IceType_void) if (IceTy == Ice::IceType_void)
return NULL; return NULL;
if (VarMap.find(V) == VarMap.end()) { if (VarMap.find(V) == VarMap.end()) {
assert(CurrentNode); VarMap[V] = Func->makeVariable(IceTy, V->getName());
VarMap[V] = Func->makeVariable(IceTy, CurrentNode, V->getName());
} }
return VarMap[V]; return VarMap[V];
} }
...@@ -614,7 +611,6 @@ private: ...@@ -614,7 +611,6 @@ private:
// Data // Data
Ice::GlobalContext *Ctx; Ice::GlobalContext *Ctx;
Ice::Cfg *Func; Ice::Cfg *Func;
Ice::CfgNode *CurrentNode;
std::map<const Value *, Ice::Variable *> VarMap; std::map<const Value *, Ice::Variable *> VarMap;
std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; std::map<const BasicBlock *, Ice::CfgNode *> NodeMap;
Ice::TypeConverter TypeConverter; Ice::TypeConverter TypeConverter;
......
...@@ -57,6 +57,7 @@ class Liveness; ...@@ -57,6 +57,7 @@ class Liveness;
class Operand; class Operand;
class TargetLowering; class TargetLowering;
class Variable; class Variable;
class VariablesMetadata;
// TODO: Switch over to LLVM's ADT container classes. // TODO: Switch over to LLVM's ADT container classes.
// http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task // http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task
......
...@@ -111,21 +111,7 @@ bool Inst::isLastUse(const Operand *TestSrc) const { ...@@ -111,21 +111,7 @@ bool Inst::isLastUse(const Operand *TestSrc) const {
return false; return false;
} }
void Inst::updateVars(CfgNode *Node) { void Inst::livenessLightweight(Cfg *Func, llvm::BitVector &Live) {
if (Dest)
Dest->setDefinition(this, Node);
for (SizeT I = 0; I < getSrcSize(); ++I) {
Operand *Src = getSrc(I);
SizeT NumVars = Src->getNumVars();
for (SizeT J = 0; J < NumVars; ++J) {
Variable *Var = Src->getVar(J);
Var->setUse(this, Node);
}
}
}
void Inst::livenessLightweight(llvm::BitVector &Live) {
assert(!isDeleted()); assert(!isDeleted());
if (llvm::isa<InstFakeKill>(this)) if (llvm::isa<InstFakeKill>(this))
return; return;
...@@ -136,7 +122,7 @@ void Inst::livenessLightweight(llvm::BitVector &Live) { ...@@ -136,7 +122,7 @@ void Inst::livenessLightweight(llvm::BitVector &Live) {
SizeT NumVars = Src->getNumVars(); SizeT NumVars = Src->getNumVars();
for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) { for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
const Variable *Var = Src->getVar(J); const Variable *Var = Src->getVar(J);
if (Var->isMultiblockLife()) if (Func->getVMetadata()->isMultiBlock(Var))
continue; continue;
SizeT Index = Var->getIndex(); SizeT Index = Var->getIndex();
if (Live[Index]) if (Live[Index])
...@@ -354,19 +340,17 @@ void InstPhi::livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target, ...@@ -354,19 +340,17 @@ void InstPhi::livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target,
// Change "a=phi(...)" to "a_phi=phi(...)" and return a new // Change "a=phi(...)" to "a_phi=phi(...)" and return a new
// instruction "a=a_phi". // instruction "a=a_phi".
Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) { Inst *InstPhi::lower(Cfg *Func) {
Variable *Dest = getDest(); Variable *Dest = getDest();
assert(Dest); assert(Dest);
IceString PhiName = Dest->getName() + "_phi"; IceString PhiName = Dest->getName() + "_phi";
Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName); Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName);
NewSrc->setIsMultidef();
this->Dest = NewSrc; this->Dest = NewSrc;
InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc); InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc);
// Set Dest and NewSrc to have affinity with each other, as a hint // Set Dest and NewSrc to have affinity with each other, as a hint
// for register allocation. // for register allocation.
Dest->setPreferredRegister(NewSrc, false); Dest->setPreferredRegister(NewSrc, false);
NewSrc->setPreferredRegister(Dest, false); NewSrc->setPreferredRegister(Dest, false);
Dest->replaceDefinition(NewInst, Node);
return NewInst; return NewInst;
} }
......
...@@ -92,13 +92,7 @@ public: ...@@ -92,13 +92,7 @@ public:
return NodeList(); return NodeList();
} }
// Updates the status of the Variables contained within the void livenessLightweight(Cfg *Func, llvm::BitVector &Live);
// instruction. In particular, it marks where the Dest variable is
// first assigned, and it tracks whether variables are live across
// basic blocks, i.e. used in a different block from their definition.
void updateVars(CfgNode *Node);
void livenessLightweight(llvm::BitVector &Live);
void liveness(InstNumberT InstNumber, llvm::BitVector &Live, void liveness(InstNumberT InstNumber, llvm::BitVector &Live,
Liveness *Liveness, const CfgNode *Node); Liveness *Liveness, const CfgNode *Node);
...@@ -520,7 +514,7 @@ public: ...@@ -520,7 +514,7 @@ public:
Operand *getOperandForTarget(CfgNode *Target) const; Operand *getOperandForTarget(CfgNode *Target) const;
void livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target, void livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target,
Liveness *Liveness); Liveness *Liveness);
Inst *lower(Cfg *Func, CfgNode *Node); Inst *lower(Cfg *Func);
virtual void dump(const Cfg *Func) const; virtual void dump(const Cfg *Func) const;
static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
......
...@@ -95,8 +95,11 @@ OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, ...@@ -95,8 +95,11 @@ OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base,
} }
} }
InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount) InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount,
: InstX8632(Func, InstX8632::Adjuststack, 0, NULL), Amount(Amount) {} Variable *Esp)
: InstX8632(Func, InstX8632::Adjuststack, 1, Esp), Amount(Amount) {
addSource(Esp);
}
InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1,
Operand *Source2) Operand *Source2)
...@@ -1497,8 +1500,6 @@ void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { ...@@ -1497,8 +1500,6 @@ void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const {
void VariableSplit::emit(const Cfg *Func) const { void VariableSplit::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(Var->getLocalUseNode() == NULL ||
Var->getLocalUseNode() == Func->getCurrentNode());
assert(!Var->hasReg()); assert(!Var->hasReg());
// The following is copied/adapted from TargetX8632::emitVariable(). // The following is copied/adapted from TargetX8632::emitVariable().
const TargetLowering *Target = Func->getTarget(); const TargetLowering *Target = Func->getTarget();
......
...@@ -142,10 +142,9 @@ private: ...@@ -142,10 +142,9 @@ private:
// Variable and SpillVariable share that slot. // Variable and SpillVariable share that slot.
class SpillVariable : public Variable { class SpillVariable : public Variable {
public: public:
static SpillVariable *create(Cfg *Func, Type Ty, const CfgNode *Node, static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index,
SizeT Index, const IceString &Name) { const IceString &Name) {
return new (Func->allocate<SpillVariable>()) return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index, Name);
SpillVariable(Ty, Node, Index, Name);
} }
const static OperandKind SpillVariableKind = const static OperandKind SpillVariableKind =
static_cast<OperandKind>(kVariable_Target); static_cast<OperandKind>(kVariable_Target);
...@@ -156,9 +155,8 @@ public: ...@@ -156,9 +155,8 @@ public:
Variable *getLinkedTo() const { return LinkedTo; } Variable *getLinkedTo() const { return LinkedTo; }
// Inherit dump() and emit() from Variable. // Inherit dump() and emit() from Variable.
private: private:
SpillVariable(Type Ty, const CfgNode *Node, SizeT Index, SpillVariable(Type Ty, SizeT Index, const IceString &Name)
const IceString &Name) : Variable(SpillVariableKind, Ty, Index, Name), LinkedTo(NULL) {}
: Variable(SpillVariableKind, Ty, Node, Index, Name), LinkedTo(NULL) {}
Variable *LinkedTo; Variable *LinkedTo;
}; };
...@@ -393,16 +391,16 @@ private: ...@@ -393,16 +391,16 @@ private:
// updates the stack offset during code emission. // updates the stack offset during code emission.
class InstX8632AdjustStack : public InstX8632 { class InstX8632AdjustStack : public InstX8632 {
public: public:
static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount) { static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) {
return new (Func->allocate<InstX8632AdjustStack>()) return new (Func->allocate<InstX8632AdjustStack>())
InstX8632AdjustStack(Func, Amount); InstX8632AdjustStack(Func, Amount, Esp);
} }
virtual void emit(const Cfg *Func) const; virtual void emit(const Cfg *Func) const;
virtual void dump(const Cfg *Func) const; virtual void dump(const Cfg *Func) const;
static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
private: private:
InstX8632AdjustStack(Cfg *Func, SizeT Amount); InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp);
InstX8632AdjustStack(const InstX8632AdjustStack &) LLVM_DELETED_FUNCTION; InstX8632AdjustStack(const InstX8632AdjustStack &) LLVM_DELETED_FUNCTION;
InstX8632AdjustStack &operator=(const InstX8632AdjustStack &) InstX8632AdjustStack &operator=(const InstX8632AdjustStack &)
LLVM_DELETED_FUNCTION; LLVM_DELETED_FUNCTION;
......
...@@ -41,10 +41,10 @@ void Liveness::init() { ...@@ -41,10 +41,10 @@ void Liveness::init() {
// block. // block.
for (SizeT i = 0; i < NumVars; ++i) { for (SizeT i = 0; i < NumVars; ++i) {
Variable *Var = Func->getVariables()[i]; Variable *Var = Func->getVariables()[i];
if (Var->isMultiblockLife()) { if (Func->getVMetadata()->isMultiBlock(Var)) {
++NumGlobals; ++NumGlobals;
} else { } else {
SizeT Index = Var->getLocalUseNode()->getIndex(); SizeT Index = Func->getVMetadata()->getLocalUseNode(Var)->getIndex();
++Nodes[Index].NumLocals; ++Nodes[Index].NumLocals;
} }
} }
...@@ -64,11 +64,11 @@ void Liveness::init() { ...@@ -64,11 +64,11 @@ void Liveness::init() {
Variable *Var = Func->getVariables()[i]; Variable *Var = Func->getVariables()[i];
SizeT VarIndex = Var->getIndex(); SizeT VarIndex = Var->getIndex();
SizeT LiveIndex; SizeT LiveIndex;
if (Var->isMultiblockLife()) { if (Func->getVMetadata()->isMultiBlock(Var)) {
LiveIndex = TmpNumGlobals++; LiveIndex = TmpNumGlobals++;
LiveToVarMap[LiveIndex] = Var; LiveToVarMap[LiveIndex] = Var;
} else { } else {
SizeT NodeIndex = Var->getLocalUseNode()->getIndex(); SizeT NodeIndex = Func->getVMetadata()->getLocalUseNode(Var)->getIndex();
LiveIndex = Nodes[NodeIndex].NumLocals++; LiveIndex = Nodes[NodeIndex].NumLocals++;
Nodes[NodeIndex].LiveToVarMap[LiveIndex] = Var; Nodes[NodeIndex].LiveToVarMap[LiveIndex] = Var;
LiveIndex += NumGlobals; LiveIndex += NumGlobals;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "IceCfg.h" #include "IceCfg.h"
#include "IceCfgNode.h"
#include "IceInst.h" #include "IceInst.h"
#include "IceOperand.h" #include "IceOperand.h"
#include "IceTargetLowering.h" // dumping stack/frame pointer register #include "IceTargetLowering.h" // dumping stack/frame pointer register
...@@ -138,48 +139,6 @@ bool LiveRange::containsValue(InstNumberT Value) const { ...@@ -138,48 +139,6 @@ bool LiveRange::containsValue(InstNumberT Value) const {
return false; return false;
} }
void Variable::setUse(const Inst *Inst, const CfgNode *Node) {
if (DefNode == NULL)
return;
if (llvm::isa<InstPhi>(Inst) || Node != DefNode)
DefNode = NULL;
}
void Variable::setDefinition(Inst *Inst, const CfgNode *Node) {
if (DefInst && !DefInst->isDeleted() && DefInst != Inst) {
// Detect when a variable is being defined multiple times,
// particularly for Phi instruction lowering. If this happens, we
// need to lock DefInst to NULL.
DefInst = NULL;
DefNode = NULL;
return;
}
if (DefNode == NULL)
return;
DefInst = Inst;
if (Node != DefNode)
DefNode = NULL;
}
void Variable::replaceDefinition(Inst *Inst, const CfgNode *Node) {
DefInst = NULL;
setDefinition(Inst, Node);
}
void Variable::setIsArg(Cfg *Func, bool IsArg) {
if (IsArg) {
IsArgument = true;
if (DefNode == NULL)
return;
CfgNode *Entry = Func->getEntryNode();
if (DefNode == Entry)
return;
DefNode = NULL;
} else {
IsArgument = false;
}
}
IceString Variable::getName() const { IceString Variable::getName() const {
if (!Name.empty()) if (!Name.empty())
return Name; return Name;
...@@ -191,16 +150,156 @@ IceString Variable::getName() const { ...@@ -191,16 +150,156 @@ IceString Variable::getName() const {
Variable Variable::asType(Type Ty) { Variable Variable::asType(Type Ty) {
// Note: This returns a Variable, even if the "this" object is a // Note: This returns a Variable, even if the "this" object is a
// subclass of Variable. // subclass of Variable.
Variable V(kVariable, Ty, DefNode, Number, Name); Variable V(kVariable, Ty, Number, Name);
V.RegNum = RegNum; V.RegNum = RegNum;
V.StackOffset = StackOffset; V.StackOffset = StackOffset;
return V; return V;
} }
void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node,
bool IsFromDef, bool IsImplicit) {
// TODO(stichnot): If the use occurs as a source operand in the
// first instruction of the block, and its definition is in this
// block's only predecessor, we might consider not marking this as a
// separate use. This may also apply if it's the first instruction
// of the block that actually uses a Variable.
assert(Node);
bool MakeMulti = false;
// 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;
if (!MakeMulti) {
switch (MultiBlock) {
case MBS_Unknown:
MultiBlock = MBS_SingleBlock;
SingleUseNode = Node;
break;
case MBS_SingleBlock:
if (SingleUseNode != Node)
MakeMulti = true;
break;
case MBS_MultiBlock:
break;
}
}
if (MakeMulti) {
MultiBlock = MBS_MultiBlock;
SingleUseNode = NULL;
}
}
void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) {
// TODO(stichnot): If the definition occurs in the last instruction
// 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.
const bool IsFromDef = true;
const bool IsImplicit = false;
markUse(Instr, Node, IsFromDef, IsImplicit);
switch (MultiDef) {
case MDS_Unknown:
MultiDef = MDS_SingleDef;
SingleDefInst = Instr;
break;
case MDS_SingleDef:
MultiDef = MDS_MultiDef;
SingleDefInst = NULL;
break;
case MDS_MultiDef:
break;
}
}
void VariablesMetadata::init() {
Metadata.clear();
Metadata.resize(Func->getNumVariables());
// Mark implicit args as being used in the entry node.
const VarList &ImplicitArgList = Func->getImplicitArgs();
for (VarList::const_iterator I = ImplicitArgList.begin(),
E = ImplicitArgList.end();
I != E; ++I) {
const Variable *Var = *I;
const Inst *NoInst = NULL;
const CfgNode *EntryNode = Func->getEntryNode();
const bool IsFromDef = false;
const bool IsImplicit = true;
Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit);
}
SizeT NumNodes = Func->getNumNodes();
for (SizeT N = 0; N < NumNodes; ++N) {
CfgNode *Node = Func->getNodes()[N];
const InstList &Insts = Node->getInsts();
for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E;
++I) {
if ((*I)->isDeleted())
continue;
if (Variable *Dest = (*I)->getDest()) {
SizeT DestNum = Dest->getIndex();
assert(DestNum < Metadata.size());
Metadata[DestNum].markDef(*I, Node);
}
for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) {
Operand *Src = (*I)->getSrc(SrcNum);
SizeT NumVars = Src->getNumVars();
for (SizeT J = 0; J < NumVars; ++J) {
const Variable *Var = Src->getVar(J);
SizeT VarNum = Var->getIndex();
assert(VarNum < Metadata.size());
const bool IsFromDef = false;
const bool IsImplicit = false;
Metadata[VarNum].markUse(*I, Node, IsFromDef, IsImplicit);
}
}
}
}
}
bool VariablesMetadata::isMultiDef(const Variable *Var) const {
if (Var->getIsArg())
return false;
if (!isTracked(Var))
return true; // conservative answer
SizeT VarNum = Var->getIndex();
// Conservatively return true if the state is unknown.
return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
}
bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
if (getDefinition(Var) == NULL)
return true;
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 {
if (!isTracked(Var))
return NULL; // conservative answer
SizeT VarNum = Var->getIndex();
return Metadata[VarNum].getDefinition();
}
const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
if (!isTracked(Var))
return NULL; // conservative answer
SizeT VarNum = Var->getIndex();
return Metadata[VarNum].getNode();
}
// ======================== dump routines ======================== // // ======================== dump routines ======================== //
void Variable::emit(const Cfg *Func) const { void Variable::emit(const Cfg *Func) const {
Func->getTarget()->emitVariable(this, Func); Func->getTarget()->emitVariable(this);
} }
void Variable::dump(const Cfg *Func, Ostream &Str) const { void Variable::dump(const Cfg *Func, Ostream &Str) const {
...@@ -208,9 +307,6 @@ void Variable::dump(const Cfg *Func, Ostream &Str) const { ...@@ -208,9 +307,6 @@ void Variable::dump(const Cfg *Func, Ostream &Str) const {
Str << "%" << getName(); Str << "%" << getName();
return; return;
} }
const CfgNode *CurrentNode = Func->getCurrentNode();
(void)CurrentNode; // used only in assert()
assert(CurrentNode == NULL || DefNode == NULL || DefNode == CurrentNode);
if (Func->getContext()->isVerbose(IceV_RegOrigins) || if (Func->getContext()->isVerbose(IceV_RegOrigins) ||
(!hasReg() && !Func->getTarget()->hasComputedFrame())) (!hasReg() && !Func->getTarget()->hasComputedFrame()))
Str << "%" << getName(); Str << "%" << getName();
......
...@@ -347,10 +347,10 @@ class Variable : public Operand { ...@@ -347,10 +347,10 @@ class Variable : public Operand {
Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
public: public:
static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, static Variable *create(Cfg *Func, Type Ty, SizeT Index,
const IceString &Name) { const IceString &Name) {
return new (Func->allocate<Variable>()) return new (Func->allocate<Variable>())
Variable(kVariable, Ty, Node, Index, Name); Variable(kVariable, Ty, Index, Name);
} }
SizeT getIndex() const { return Number; } SizeT getIndex() const { return Number; }
...@@ -361,24 +361,10 @@ public: ...@@ -361,24 +361,10 @@ public:
Name = NewName; Name = NewName;
} }
Inst *getDefinition() const { return DefInst; }
void setDefinition(Inst *Inst, const CfgNode *Node);
void replaceDefinition(Inst *Inst, const CfgNode *Node);
const CfgNode *getLocalUseNode() const { return DefNode; }
bool isMultiblockLife() const { return (DefNode == NULL); }
void setUse(const Inst *Inst, const CfgNode *Node);
// Multidef means a variable is non-SSA and has multiple defining
// instructions. Currently this classification is limited to SSA
// lowering temporaries where the definitions are in different basic
// blocks, and it is not maintained during target lowering when the
// same temporary may be updated in consecutive instructions.
bool getIsMultidef() const { return IsMultidef; }
void setIsMultidef() { IsMultidef = true; }
bool getIsArg() const { return IsArgument; } bool getIsArg() const { return IsArgument; }
void setIsArg(Cfg *Func, bool IsArg = true); void setIsArg(bool Val = true) { IsArgument = Val; }
bool getIsImplicitArg() const { return IsImplicitArgument; }
void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
int32_t getStackOffset() const { return StackOffset; } int32_t getStackOffset() const { return StackOffset; }
void setStackOffset(int32_t Offset) { StackOffset = Offset; } void setStackOffset(int32_t Offset) { StackOffset = Offset; }
...@@ -447,13 +433,11 @@ public: ...@@ -447,13 +433,11 @@ public:
virtual ~Variable() {} virtual ~Variable() {}
protected: protected:
Variable(OperandKind K, Type Ty, const CfgNode *Node, SizeT Index, Variable(OperandKind K, Type Ty, SizeT Index, const IceString &Name)
const IceString &Name) : Operand(K, Ty), Number(Index), Name(Name), IsArgument(false),
: Operand(K, Ty), Number(Index), Name(Name), DefInst(NULL), DefNode(Node), IsImplicitArgument(false), StackOffset(0), RegNum(NoRegister),
IsMultidef(false), IsArgument(false), StackOffset(0), RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL),
RegNum(NoRegister), RegNumTmp(NoRegister), Weight(1), AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
RegisterPreference(NULL), AllowRegisterOverlap(false), LoVar(NULL),
HiVar(NULL) {
Vars = VarsReal; Vars = VarsReal;
Vars[0] = this; Vars[0] = this;
NumVars = 1; NumVars = 1;
...@@ -463,18 +447,8 @@ protected: ...@@ -463,18 +447,8 @@ protected:
const SizeT Number; const SizeT Number;
// Name is optional. // Name is optional.
IceString Name; IceString Name;
// DefInst is the instruction that produces this variable as its
// dest.
Inst *DefInst;
// DefNode is the node where this variable was produced, and is
// reset to NULL if it is used outside that node. This is used for
// detecting isMultiblockLife(). TODO: Collapse this to a single
// bit and use a separate pass to calculate the values across the
// Cfg. This saves space in the Variable, and removes the fragility
// of incrementally computing and maintaining the information.
const CfgNode *DefNode;
bool IsMultidef;
bool IsArgument; bool IsArgument;
bool IsImplicitArgument;
// StackOffset is the canonical location on stack (only if // StackOffset is the canonical location on stack (only if
// RegNum<0 || IsArgument). // RegNum<0 || IsArgument).
int32_t StackOffset; int32_t StackOffset;
...@@ -509,6 +483,60 @@ protected: ...@@ -509,6 +483,60 @@ protected:
Variable *VarsReal[1]; Variable *VarsReal[1];
}; };
// VariableTracking tracks the metadata for a single variable.
class VariableTracking {
public:
enum MultiDefState {
// TODO(stichnot): Consider using just a simple counter.
MDS_Unknown,
MDS_SingleDef,
MDS_MultiDef
};
enum MultiBlockState {
MBS_Unknown,
MBS_SingleBlock,
MBS_MultiBlock
};
VariableTracking()
: MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL),
SingleDefInst(NULL) {}
MultiDefState getMultiDef() const { return MultiDef; }
MultiBlockState getMultiBlock() const { return MultiBlock; }
const Inst *getDefinition() const { return SingleDefInst; }
const CfgNode *getNode() const { return SingleUseNode; }
void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef,
bool IsImplicit);
void markDef(const Inst *Instr, const CfgNode *Node);
private:
VariableTracking &operator=(const VariableTracking &) LLVM_DELETED_FUNCTION;
MultiDefState MultiDef;
MultiBlockState MultiBlock;
const CfgNode *SingleUseNode;
const Inst *SingleDefInst;
};
// VariablesMetadata analyzes and summarizes the metadata for the
// complete set of Variables.
class VariablesMetadata {
public:
VariablesMetadata(const Cfg *Func) : Func(Func) {}
void init();
bool isTracked(const Variable *Var) const {
return Var->getIndex() < Metadata.size();
}
bool isMultiDef(const Variable *Var) const;
const Inst *getDefinition(const Variable *Var) const;
bool isMultiBlock(const Variable *Var) const;
const CfgNode *getLocalUseNode(const Variable *Var) const;
private:
const Cfg *Func;
std::vector<VariableTracking> Metadata;
VariablesMetadata(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
VariablesMetadata &operator=(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
};
} // end of namespace Ice } // end of namespace Ice
#endif // SUBZERO_SRC_ICEOPERAND_H #endif // SUBZERO_SRC_ICEOPERAND_H
...@@ -53,7 +53,6 @@ void LoweringContext::init(CfgNode *N) { ...@@ -53,7 +53,6 @@ void LoweringContext::init(CfgNode *N) {
void LoweringContext::insert(Inst *Inst) { void LoweringContext::insert(Inst *Inst) {
getNode()->getInsts().insert(Next, Inst); getNode()->getInsts().insert(Next, Inst);
Inst->updateVars(getNode());
} }
void LoweringContext::skipDeleted(InstList::iterator &I) const { void LoweringContext::skipDeleted(InstList::iterator &I) const {
......
...@@ -172,7 +172,7 @@ public: ...@@ -172,7 +172,7 @@ public:
virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0; virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0;
void regAlloc(); void regAlloc();
virtual void emitVariable(const Variable *Var, const Cfg *Func) const = 0; virtual void emitVariable(const Variable *Var) const = 0;
// Performs target-specific argument lowering. // Performs target-specific argument lowering.
virtual void lowerArguments() = 0; virtual void lowerArguments() = 0;
......
...@@ -322,6 +322,7 @@ void TargetX8632::translateO2() { ...@@ -322,6 +322,7 @@ void TargetX8632::translateO2() {
// Address mode optimization. // Address mode optimization.
Timer T_doAddressOpt; Timer T_doAddressOpt;
Func->getVMetadata()->init();
Func->doAddressOpt(); Func->doAddressOpt();
T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()"); T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()");
...@@ -470,10 +471,13 @@ Variable *TargetX8632::getPhysicalRegister(SizeT RegNum) { ...@@ -470,10 +471,13 @@ Variable *TargetX8632::getPhysicalRegister(SizeT RegNum) {
assert(RegNum < PhysicalRegisters.size()); assert(RegNum < PhysicalRegisters.size());
Variable *Reg = PhysicalRegisters[RegNum]; Variable *Reg = PhysicalRegisters[RegNum];
if (Reg == NULL) { if (Reg == NULL) {
CfgNode *Node = NULL; // NULL means multi-block lifetime Reg = Func->makeVariable(IceType_i32);
Reg = Func->makeVariable(IceType_i32, Node);
Reg->setRegNum(RegNum); Reg->setRegNum(RegNum);
PhysicalRegisters[RegNum] = Reg; PhysicalRegisters[RegNum] = Reg;
// Specially mark esp as an "argument" so that it is considered
// live upon function entry.
if (RegNum == RegX8632::Reg_esp)
Func->addImplicitArg(Reg);
} }
return Reg; return Reg;
} }
...@@ -505,10 +509,8 @@ IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const { ...@@ -505,10 +509,8 @@ IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const {
} }
} }
void TargetX8632::emitVariable(const Variable *Var, const Cfg *Func) const { void TargetX8632::emitVariable(const Variable *Var) const {
Ostream &Str = Ctx->getStrEmit(); Ostream &Str = Ctx->getStrEmit();
assert(Var->getLocalUseNode() == NULL ||
Var->getLocalUseNode() == Func->getCurrentNode());
if (Var->hasReg()) { if (Var->hasReg()) {
Str << getRegName(Var->getRegNum(), Var->getType()); Str << getRegName(Var->getRegNum(), Var->getType());
return; return;
...@@ -548,11 +550,10 @@ void TargetX8632::lowerArguments() { ...@@ -548,11 +550,10 @@ void TargetX8632::lowerArguments() {
int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs; int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs;
++NumXmmArgs; ++NumXmmArgs;
IceString Name = "home_reg:" + Arg->getName(); IceString Name = "home_reg:" + Arg->getName();
const CfgNode *DefNode = NULL; Variable *RegisterArg = Func->makeVariable(Ty, Name);
Variable *RegisterArg = Func->makeVariable(Ty, DefNode, Name);
RegisterArg->setRegNum(RegNum); RegisterArg->setRegNum(RegNum);
RegisterArg->setIsArg(Func); RegisterArg->setIsArg();
Arg->setIsArg(Func, false); Arg->setIsArg(false);
Args[I] = RegisterArg; Args[I] = RegisterArg;
Context.insert(InstAssign::create(Func, Arg, RegisterArg)); Context.insert(InstAssign::create(Func, Arg, RegisterArg));
...@@ -675,6 +676,7 @@ void TargetX8632::addProlog(CfgNode *Node) { ...@@ -675,6 +676,7 @@ void TargetX8632::addProlog(CfgNode *Node) {
size_t InArgsSizeBytes = 0; size_t InArgsSizeBytes = 0;
size_t PreservedRegsSizeBytes = 0; size_t PreservedRegsSizeBytes = 0;
SpillAreaSizeBytes = 0; SpillAreaSizeBytes = 0;
const VariablesMetadata *VMetadata = Func->getVMetadata();
Context.init(Node); Context.init(Node);
Context.setInsertPoint(Context.getCur()); Context.setInsertPoint(Context.getCur());
...@@ -743,11 +745,11 @@ void TargetX8632::addProlog(CfgNode *Node) { ...@@ -743,11 +745,11 @@ void TargetX8632::addProlog(CfgNode *Node) {
size_t Increment = typeWidthInBytesOnStack(Var->getType()); size_t Increment = typeWidthInBytesOnStack(Var->getType());
if (!SpillAreaAlignmentBytes) if (!SpillAreaAlignmentBytes)
SpillAreaAlignmentBytes = Increment; SpillAreaAlignmentBytes = Increment;
if (SimpleCoalescing) { if (SimpleCoalescing && VMetadata->isTracked(Var)) {
if (Var->isMultiblockLife()) { if (VMetadata->isMultiBlock(Var)) {
GlobalsSize += Increment; GlobalsSize += Increment;
} else { } else {
SizeT NodeIndex = Var->getLocalUseNode()->getIndex(); SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
LocalsSize[NodeIndex] += Increment; LocalsSize[NodeIndex] += Increment;
if (LocalsSize[NodeIndex] > SpillAreaSizeBytes) if (LocalsSize[NodeIndex] > SpillAreaSizeBytes)
SpillAreaSizeBytes = LocalsSize[NodeIndex]; SpillAreaSizeBytes = LocalsSize[NodeIndex];
...@@ -852,12 +854,12 @@ void TargetX8632::addProlog(CfgNode *Node) { ...@@ -852,12 +854,12 @@ void TargetX8632::addProlog(CfgNode *Node) {
I != E; ++I) { I != E; ++I) {
Variable *Var = *I; Variable *Var = *I;
size_t Increment = typeWidthInBytesOnStack(Var->getType()); size_t Increment = typeWidthInBytesOnStack(Var->getType());
if (SimpleCoalescing) { if (SimpleCoalescing && VMetadata->isTracked(Var)) {
if (Var->isMultiblockLife()) { if (VMetadata->isMultiBlock(Var)) {
GlobalsSpaceUsed += Increment; GlobalsSpaceUsed += Increment;
NextStackOffset = GlobalsSpaceUsed; NextStackOffset = GlobalsSpaceUsed;
} else { } else {
SizeT NodeIndex = Var->getLocalUseNode()->getIndex(); SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
LocalsSize[NodeIndex] += Increment; LocalsSize[NodeIndex] += Increment;
NextStackOffset = SpillAreaPaddingBytes + NextStackOffset = SpillAreaPaddingBytes +
GlobalsAndSubsequentPaddingSize + GlobalsAndSubsequentPaddingSize +
...@@ -1035,14 +1037,12 @@ void TargetX8632::split64(Variable *Var) { ...@@ -1035,14 +1037,12 @@ void TargetX8632::split64(Variable *Var) {
return; return;
} }
assert(Hi == NULL); assert(Hi == NULL);
Lo = Func->makeVariable(IceType_i32, Context.getNode(), Lo = Func->makeVariable(IceType_i32, Var->getName() + "__lo");
Var->getName() + "__lo"); Hi = Func->makeVariable(IceType_i32, Var->getName() + "__hi");
Hi = Func->makeVariable(IceType_i32, Context.getNode(),
Var->getName() + "__hi");
Var->setLoHi(Lo, Hi); Var->setLoHi(Lo, Hi);
if (Var->getIsArg()) { if (Var->getIsArg()) {
Lo->setIsArg(Func); Lo->setIsArg();
Hi->setIsArg(Func); Hi->setIsArg();
} }
} }
...@@ -2276,8 +2276,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) { ...@@ -2276,8 +2276,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
Variable *T = NULL; Variable *T = NULL;
// TODO: Should be able to force a spill setup by calling legalize() with // TODO: Should be able to force a spill setup by calling legalize() with
// Legal_Mem and not Legal_Reg or Legal_Imm. // Legal_Mem and not Legal_Reg or Legal_Imm.
SpillVariable *SpillVar = SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(SrcType);
Func->makeVariable<SpillVariable>(SrcType, Context.getNode());
SpillVar->setLinkedTo(Dest); SpillVar->setLinkedTo(Dest);
Variable *Spill = SpillVar; Variable *Spill = SpillVar;
Spill->setWeight(RegWeight::Zero); Spill->setWeight(RegWeight::Zero);
...@@ -2294,8 +2293,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) { ...@@ -2294,8 +2293,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
// a_lo.i32 = t_lo.i32 // a_lo.i32 = t_lo.i32
// t_hi.i32 = hi(s.f64) // t_hi.i32 = hi(s.f64)
// a_hi.i32 = t_hi.i32 // a_hi.i32 = t_hi.i32
SpillVariable *SpillVar = SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64);
Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode());
SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM)); SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM));
Variable *Spill = SpillVar; Variable *Spill = SpillVar;
Spill->setWeight(RegWeight::Zero); Spill->setWeight(RegWeight::Zero);
...@@ -2325,8 +2323,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) { ...@@ -2325,8 +2323,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
// t_hi.i32 = b_hi.i32 // t_hi.i32 = b_hi.i32
// hi(s.f64) = t_hi.i32 // hi(s.f64) = t_hi.i32
// a.f64 = s.f64 // a.f64 = s.f64
SpillVariable *SpillVar = SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64);
Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode());
SpillVar->setLinkedTo(Dest); SpillVar->setLinkedTo(Dest);
Variable *Spill = SpillVar; Variable *Spill = SpillVar;
Spill->setWeight(RegWeight::Zero); Spill->setWeight(RegWeight::Zero);
...@@ -2349,8 +2346,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) { ...@@ -2349,8 +2346,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
case IceType_v8i1: { case IceType_v8i1: {
assert(Src0->getType() == IceType_i8); assert(Src0->getType() == IceType_i8);
InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1); InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1);
Variable *Src0AsI32 = Func->makeVariable(stackSlotType(), Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
Context.getNode());
// Arguments to functions are required to be at least 32 bits wide. // Arguments to functions are required to be at least 32 bits wide.
lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0));
Call->addArg(Src0AsI32); Call->addArg(Src0AsI32);
...@@ -2359,8 +2355,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) { ...@@ -2359,8 +2355,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
case IceType_v16i1: { case IceType_v16i1: {
assert(Src0->getType() == IceType_i16); assert(Src0->getType() == IceType_i16);
InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1); InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1);
Variable *Src0AsI32 = Func->makeVariable(stackSlotType(), Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
Context.getNode());
// Arguments to functions are required to be at least 32 bits wide. // Arguments to functions are required to be at least 32 bits wide.
lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0));
Call->addArg(Src0AsI32); Call->addArg(Src0AsI32);
...@@ -2429,7 +2424,7 @@ void TargetX8632::lowerExtractElement(const InstExtractElement *Inst) { ...@@ -2429,7 +2424,7 @@ void TargetX8632::lowerExtractElement(const InstExtractElement *Inst) {
// //
// TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when
// support for legalizing to mem is implemented. // support for legalizing to mem is implemented.
Variable *Slot = Func->makeVariable(Ty, Context.getNode()); Variable *Slot = Func->makeVariable(Ty);
Slot->setWeight(RegWeight::Zero); Slot->setWeight(RegWeight::Zero);
_movp(Slot, legalizeToVar(SourceVectNotLegalized)); _movp(Slot, legalizeToVar(SourceVectNotLegalized));
...@@ -2584,8 +2579,8 @@ void TargetX8632::lowerIcmp(const InstIcmp *Inst) { ...@@ -2584,8 +2579,8 @@ void TargetX8632::lowerIcmp(const InstIcmp *Inst) {
NewTy = IceType_v16i8; NewTy = IceType_v16i8;
break; break;
} }
Variable *NewSrc0 = Func->makeVariable(NewTy, Context.getNode()); Variable *NewSrc0 = Func->makeVariable(NewTy);
Variable *NewSrc1 = Func->makeVariable(NewTy, Context.getNode()); Variable *NewSrc1 = Func->makeVariable(NewTy);
lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0));
lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1));
Src0 = NewSrc0; Src0 = NewSrc0;
...@@ -2760,8 +2755,7 @@ void TargetX8632::lowerInsertElement(const InstInsertElement *Inst) { ...@@ -2760,8 +2755,7 @@ void TargetX8632::lowerInsertElement(const InstInsertElement *Inst) {
if (ElementTy == IceType_i1) { if (ElementTy == IceType_i1) {
// Expand the element to the appropriate size for it to be inserted // Expand the element to the appropriate size for it to be inserted
// in the vector. // in the vector.
Variable *Expanded = Variable *Expanded = Func->makeVariable(InVectorElementTy);
Func->makeVariable(InVectorElementTy, Context.getNode());
InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded,
ElementToInsertNotLegalized); ElementToInsertNotLegalized);
lowerCast(Cast); lowerCast(Cast);
...@@ -2853,7 +2847,7 @@ void TargetX8632::lowerInsertElement(const InstInsertElement *Inst) { ...@@ -2853,7 +2847,7 @@ void TargetX8632::lowerInsertElement(const InstInsertElement *Inst) {
// //
// TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when
// support for legalizing to mem is implemented. // support for legalizing to mem is implemented.
Variable *Slot = Func->makeVariable(Ty, Context.getNode()); Variable *Slot = Func->makeVariable(Ty);
Slot->setWeight(RegWeight::Zero); Slot->setWeight(RegWeight::Zero);
_movp(Slot, legalizeToVar(SourceVectNotLegalized)); _movp(Slot, legalizeToVar(SourceVectNotLegalized));
...@@ -3123,7 +3117,7 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { ...@@ -3123,7 +3117,7 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
// wide. // wide.
Operand *ValOp = Instr->getArg(1); Operand *ValOp = Instr->getArg(1);
assert(ValOp->getType() == IceType_i8); assert(ValOp->getType() == IceType_i8);
Variable *ValExt = Func->makeVariable(stackSlotType(), Context.getNode()); Variable *ValExt = Func->makeVariable(stackSlotType());
lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp));
InstCall *Call = makeHelperCall("memset", NULL, 3); InstCall *Call = makeHelperCall("memset", NULL, 3);
Call->addArg(Instr->getArg(0)); Call->addArg(Instr->getArg(0));
...@@ -3579,17 +3573,18 @@ void dumpAddressOpt(const Cfg *Func, const Variable *Base, ...@@ -3579,17 +3573,18 @@ void dumpAddressOpt(const Cfg *Func, const Variable *Base,
Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n";
} }
bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) { bool matchTransitiveAssign(const VariablesMetadata *VMetadata, Variable *&Var,
const Inst *&Reason) {
// Var originates from Var=SrcVar ==> // Var originates from Var=SrcVar ==>
// set Var:=SrcVar // set Var:=SrcVar
if (Var == NULL) if (Var == NULL)
return false; return false;
if (const Inst *VarAssign = Var->getDefinition()) { if (const Inst *VarAssign = VMetadata->getDefinition(Var)) {
if (llvm::isa<InstAssign>(VarAssign)) { if (llvm::isa<InstAssign>(VarAssign)) {
Operand *SrcOp = VarAssign->getSrc(0); Operand *SrcOp = VarAssign->getSrc(0);
assert(SrcOp); assert(SrcOp);
if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
if (!SrcVar->getIsMultidef() && if (!VMetadata->isMultiDef(SrcVar) &&
// TODO: ensure SrcVar stays single-BB // TODO: ensure SrcVar stays single-BB
true) { true) {
Var = SrcVar; Var = SrcVar;
...@@ -3602,7 +3597,8 @@ bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) { ...@@ -3602,7 +3597,8 @@ bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) {
return false; return false;
} }
bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift, bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable *&Base,
Variable *&Index, uint16_t &Shift,
const Inst *&Reason) { const Inst *&Reason) {
// Index==NULL && Base is Base=Var1+Var2 ==> // Index==NULL && Base is Base=Var1+Var2 ==>
// set Base=Var1, Index=Var2, Shift=0 // set Base=Var1, Index=Var2, Shift=0
...@@ -3610,16 +3606,16 @@ bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift, ...@@ -3610,16 +3606,16 @@ bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift,
return false; return false;
if (Index != NULL) if (Index != NULL)
return false; return false;
const Inst *BaseInst = Base->getDefinition(); const Inst *BaseInst = VMetadata->getDefinition(Base);
if (BaseInst == NULL) if (BaseInst == NULL)
return false; return false;
if (BaseInst->getSrcSize() < 2) if (BaseInst->getSrcSize() < 2)
return false; return false;
if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
if (Var1->getIsMultidef()) if (VMetadata->isMultiDef(Var1))
return false; return false;
if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
if (Var2->getIsMultidef()) if (VMetadata->isMultiDef(Var2))
return false; return false;
if (isAdd(BaseInst) && if (isAdd(BaseInst) &&
// TODO: ensure Var1 and Var2 stay single-BB // TODO: ensure Var1 and Var2 stay single-BB
...@@ -3635,12 +3631,13 @@ bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift, ...@@ -3635,12 +3631,13 @@ bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift,
return false; return false;
} }
bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) { bool matchShiftedIndex(const VariablesMetadata *VMetadata, Variable *&Index,
uint16_t &Shift, const Inst *&Reason) {
// Index is Index=Var*Const && log2(Const)+Shift<=3 ==> // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
// Index=Var, Shift+=log2(Const) // Index=Var, Shift+=log2(Const)
if (Index == NULL) if (Index == NULL)
return false; return false;
const Inst *IndexInst = Index->getDefinition(); const Inst *IndexInst = VMetadata->getDefinition(Index);
if (IndexInst == NULL) if (IndexInst == NULL)
return false; return false;
if (IndexInst->getSrcSize() < 2) if (IndexInst->getSrcSize() < 2)
...@@ -3651,7 +3648,7 @@ bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) { ...@@ -3651,7 +3648,7 @@ bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) {
if (ConstantInteger32 *Const = if (ConstantInteger32 *Const =
llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) { llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) {
if (ArithInst->getOp() == InstArithmetic::Mul && if (ArithInst->getOp() == InstArithmetic::Mul &&
!Var->getIsMultidef() && Const->getType() == IceType_i32) { !VMetadata->isMultiDef(Var) && Const->getType() == IceType_i32) {
uint64_t Mult = Const->getValue(); uint64_t Mult = Const->getValue();
uint32_t LogMult; uint32_t LogMult;
switch (Mult) { switch (Mult) {
...@@ -3683,14 +3680,15 @@ bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) { ...@@ -3683,14 +3680,15 @@ bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) {
return false; return false;
} }
bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) { bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base,
int32_t &Offset, const Inst *&Reason) {
// Base is Base=Var+Const || Base is Base=Const+Var ==> // Base is Base=Var+Const || Base is Base=Const+Var ==>
// set Base=Var, Offset+=Const // set Base=Var, Offset+=Const
// Base is Base=Var-Const ==> // Base is Base=Var-Const ==>
// set Base=Var, Offset-=Const // set Base=Var, Offset-=Const
if (Base == NULL) if (Base == NULL)
return false; return false;
const Inst *BaseInst = Base->getDefinition(); const Inst *BaseInst = VMetadata->getDefinition(Base);
if (BaseInst == NULL) if (BaseInst == NULL)
return false; return false;
if (const InstArithmetic *ArithInst = if (const InstArithmetic *ArithInst =
...@@ -3709,7 +3707,7 @@ bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) { ...@@ -3709,7 +3707,7 @@ bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) {
Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0)); Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0));
Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1));
} }
if (Var == NULL || Const == NULL || Var->getIsMultidef()) if (Var == NULL || Const == NULL || VMetadata->isMultiDef(Var))
return false; return false;
int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue(); int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue();
if (WouldOverflowAdd(Offset, MoreOffset)) if (WouldOverflowAdd(Offset, MoreOffset))
...@@ -3737,17 +3735,18 @@ void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, ...@@ -3737,17 +3735,18 @@ void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
// blocks, then don't go further. Alternatively (?), never consider // blocks, then don't go further. Alternatively (?), never consider
// a transformation that would change a variable that is currently // a transformation that would change a variable that is currently
// *not* live across basic block boundaries into one that *is*. // *not* live across basic block boundaries into one that *is*.
if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/)
return; return;
const VariablesMetadata *VMetadata = Func->getVMetadata();
bool Continue = true; bool Continue = true;
while (Continue) { while (Continue) {
const Inst *Reason = NULL; const Inst *Reason = NULL;
if (matchTransitiveAssign(Base, Reason) || if (matchTransitiveAssign(VMetadata, Base, Reason) ||
matchTransitiveAssign(Index, Reason) || matchTransitiveAssign(VMetadata, Index, Reason) ||
matchCombinedBaseIndex(Base, Index, Shift, Reason) || matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason) ||
matchShiftedIndex(Index, Shift, Reason) || matchShiftedIndex(VMetadata, Index, Shift, Reason) ||
matchOffsetBase(Base, Offset, Reason)) { matchOffsetBase(VMetadata, Base, Offset, Reason)) {
dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason); dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason);
} else { } else {
Continue = false; Continue = false;
...@@ -3939,7 +3938,7 @@ void TargetX8632::lowerSelect(const InstSelect *Inst) { ...@@ -3939,7 +3938,7 @@ void TargetX8632::lowerSelect(const InstSelect *Inst) {
// Sign extend the condition operand if applicable. // Sign extend the condition operand if applicable.
if (SrcTy == IceType_v4f32) { if (SrcTy == IceType_v4f32) {
// The sext operation takes only integer arguments. // The sext operation takes only integer arguments.
Variable *T3 = Func->makeVariable(IceType_v4i32, Context.getNode()); Variable *T3 = Func->makeVariable(IceType_v4i32);
lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition));
_movp(T, T3); _movp(T, T3);
} else if (typeElementType(SrcTy) != IceType_i1) { } else if (typeElementType(SrcTy) != IceType_i1) {
...@@ -4070,17 +4069,17 @@ void TargetX8632::scalarizeArithmetic(InstArithmetic::OpKind Kind, ...@@ -4070,17 +4069,17 @@ void TargetX8632::scalarizeArithmetic(InstArithmetic::OpKind Kind,
Constant *Index = Ctx->getConstantInt32(IceType_i32, I); Constant *Index = Ctx->getConstantInt32(IceType_i32, I);
// Extract the next two inputs. // Extract the next two inputs.
Variable *Op0 = Func->makeVariable(ElementTy, Context.getNode()); Variable *Op0 = Func->makeVariable(ElementTy);
lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index));
Variable *Op1 = Func->makeVariable(ElementTy, Context.getNode()); Variable *Op1 = Func->makeVariable(ElementTy);
lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index));
// Perform the arithmetic as a scalar operation. // Perform the arithmetic as a scalar operation.
Variable *Res = Func->makeVariable(ElementTy, Context.getNode()); Variable *Res = Func->makeVariable(ElementTy);
lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1));
// Insert the result into position. // Insert the result into position.
Variable *DestT = Func->makeVariable(Ty, Context.getNode()); Variable *DestT = Func->makeVariable(Ty);
lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index));
T = DestT; T = DestT;
// TODO(stichnot): Use postLower() in -Om1 mode to avoid buildup of // TODO(stichnot): Use postLower() in -Om1 mode to avoid buildup of
...@@ -4324,7 +4323,7 @@ OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) { ...@@ -4324,7 +4323,7 @@ OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) {
Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) {
// There aren't any 64-bit integer registers for x86-32. // There aren't any 64-bit integer registers for x86-32.
assert(Type != IceType_i64); assert(Type != IceType_i64);
Variable *Reg = Func->makeVariable(Type, Context.getNode()); Variable *Reg = Func->makeVariable(Type);
if (RegNum == Variable::NoRegister) if (RegNum == Variable::NoRegister)
Reg->setWeightInfinite(); Reg->setWeightInfinite();
else else
......
...@@ -52,7 +52,7 @@ public: ...@@ -52,7 +52,7 @@ public:
static const uint8_t Padding[] = { 0xF4 }; static const uint8_t Padding[] = { 0xF4 };
return llvm::ArrayRef<uint8_t>(Padding, 1); return llvm::ArrayRef<uint8_t>(Padding, 1);
} }
virtual void emitVariable(const Variable *Var, const Cfg *Func) const; virtual void emitVariable(const Variable *Var) const;
virtual void lowerArguments(); virtual void lowerArguments();
virtual void addProlog(CfgNode *Node); virtual void addProlog(CfgNode *Node);
virtual void addEpilog(CfgNode *Node); virtual void addEpilog(CfgNode *Node);
...@@ -190,7 +190,8 @@ protected: ...@@ -190,7 +190,8 @@ protected:
Context.insert(InstX8632Add::create(Func, Dest, Src0)); Context.insert(InstX8632Add::create(Func, Dest, Src0));
} }
void _adjust_stack(int32_t Amount) { void _adjust_stack(int32_t Amount) {
Context.insert(InstX8632AdjustStack::create(Func, Amount)); Context.insert(InstX8632AdjustStack::create(
Func, Amount, getPhysicalRegister(RegX8632::Reg_esp)));
} }
void _addps(Variable *Dest, Operand *Src0) { void _addps(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Addps::create(Func, Dest, Src0)); Context.insert(InstX8632Addps::create(Func, Dest, Src0));
......
...@@ -948,7 +948,7 @@ private: ...@@ -948,7 +948,7 @@ private:
// Recover since we can't throw an exception. // Recover since we can't throw an exception.
Ty = Ice::IceType_i32; Ty = Ice::IceType_i32;
} }
return Func->makeVariable(Ty, CurrentNode); return Func->makeVariable(Ty);
} }
// Generates the next available local variable using the given type. // Generates the next available local variable using the given type.
......
...@@ -78,8 +78,8 @@ block: ...@@ -78,8 +78,8 @@ block:
ret <4 x i32> %vec.local ret <4 x i32> %vec.local
; CHECK-LABEL: align_local_vector_and_global_float: ; CHECK-LABEL: align_local_vector_and_global_float:
; CHECK: cvtsi2ss xmm0, eax ; CHECK: cvtsi2ss xmm0, eax
; CHECK-NEXT: movss dword ptr [esp+28], xmm0 ; CHECK-NEXT: movss dword ptr [esp+{{12|28}}], xmm0
; CHECK: movups xmm0, xmmword ptr [esp] ; CHECK: movups xmm0, xmmword ptr [{{esp|esp\+16}}]
; CHECK-NEXT: add esp, 44 ; CHECK-NEXT: add esp, 44
; CHECK-NEXT: ret ; CHECK-NEXT: ret
} }
......
...@@ -55,6 +55,9 @@ NonZero: ...@@ -55,6 +55,9 @@ NonZero:
; CHECK: mov dword ptr [esp + [[OFF:.*]]], [[REG1]] ; CHECK: mov dword ptr [esp + [[OFF:.*]]], [[REG1]]
; CHECK: add [[REG2:.*]], 54321 ; CHECK: add [[REG2:.*]], 54321
; Now there should be sharing of the stack slot (OFF is the same). ; Now there should be sharing of the stack slot (OFF is the same).
; CHECK: mov dword ptr [esp + [[OFF]]], [[REG2]] ; Commenting out after disabling simple coalescing for -Om1.
; TODO(stichnot): Add it back if/when we add a flag to enable simple
; coalescing.
; xCHECK: mov dword ptr [esp + [[OFF]]], [[REG2]]
; ERRORS-NOT: ICE translation error ; ERRORS-NOT: ICE translation error
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment