Index: src/IceInst.cpp |
diff --git a/src/IceInst.cpp b/src/IceInst.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e90e0d2056fb159b6d784ee1f031a31f172de304 |
--- /dev/null |
+++ b/src/IceInst.cpp |
@@ -0,0 +1,469 @@ |
+//===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// |
+// |
+// The Subzero Code Generator |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// This file implements the Inst class, primarily the various |
+// subclass constructors and dump routines. |
+// |
+//===----------------------------------------------------------------------===// |
+ |
+#include "IceCfg.h" |
+#include "IceCfgNode.h" |
+#include "IceInst.h" |
+#include "IceOperand.h" |
+ |
+namespace Ice { |
+ |
+Inst::Inst(IceCfg *Cfg, InstKind Kind, IceSize_t MaxSrcs, Variable *Dest) |
+ : Kind(Kind), Number(Cfg->newInstNumber()), Deleted(false), |
+ HasSideEffects(false), Dest(Dest), MaxSrcs(MaxSrcs), NumSrcs(0), |
+ Srcs(Cfg->allocateArrayOf<Operand *>(MaxSrcs)) {} |
+ |
+Inst::~Inst() { |
+#ifdef ICE_NO_ARENAS |
+ for (IceSize_t i = 0; i < getSrcSize(); ++i) { |
+ Operand *Src = getSrc(i); |
+ if (Src && !Src->isPooled()) { |
+ delete Src; |
+ } |
+ } |
+ delete[] Srcs; |
+ if (getDest() && !getDest()->isPooled()) { |
+ delete getDest(); |
+ } |
JF
2014/04/23 03:51:28
Same thing on deletion, though it kind of seems li
Jim Stichnoth
2014/04/26 15:02:11
Done. And you're right, it was just wrong for the
|
+#endif // ICE_NO_ARENAS |
+} |
+ |
+void Inst::updateVars(CfgNode *Node) { |
+ if (Dest) |
+ Dest->setDefinition(this, Node); |
+ |
+ IceSize_t VarIndex = 0; |
+ for (IceSize_t I = 0; I < getSrcSize(); ++I) { |
+ Operand *Src = getSrc(I); |
+ IceSize_t NumVars = Src->getNumVars(); |
+ for (IceSize_t J = 0; J < NumVars; ++J, ++VarIndex) { |
+ Variable *Var = Src->getVar(J); |
+ Var->setUse(this, Node); |
+ } |
+ } |
+} |
+ |
+InstAlloca::InstAlloca(IceCfg *Cfg, Operand *ByteCount, uint32_t Align, |
+ Variable *Dest) |
+ : Inst(Cfg, Inst::Alloca, 1, Dest), Align(Align) { |
+ addSource(ByteCount); |
+} |
+ |
+InstArithmetic::InstArithmetic(IceCfg *Cfg, OpKind Op, Variable *Dest, |
+ Operand *Source1, Operand *Source2) |
+ : Inst(Cfg, Inst::Arithmetic, 2, Dest), Op(Op) { |
+ addSource(Source1); |
+ addSource(Source2); |
+} |
+ |
+bool InstArithmetic::isCommutative() const { |
+#define X(tag, str, commutative) \ |
+ case tag: \ |
+ return commutative; |
+ |
+ switch (getOp()) { ICEINSTARITHMETIC_TABLE } |
JF
2014/04/23 03:51:28
Load from a static const bool table instead: show
Jim Stichnoth
2014/04/26 15:02:11
Done.
|
+#undef X |
+ |
+ assert(0); // should be unreachable |
JF
2014/04/23 03:51:28
llvm_unreachable
Jim Stichnoth
2014/04/26 15:02:11
Done.
|
+ return false; |
+} |
+ |
+InstAssign::InstAssign(IceCfg *Cfg, Variable *Dest, Operand *Source) |
+ : Inst(Cfg, Inst::Assign, 1, Dest) { |
+ addSource(Source); |
+} |
+ |
+// If TargetTrue==TargetFalse, we turn it into an unconditional |
+// branch. This ensures that, along with the 'switch' instruction |
+// semantics, there is at most one edge from one node to another. |
+InstBr::InstBr(IceCfg *Cfg, Operand *Source, CfgNode *TargetTrue, |
+ CfgNode *TargetFalse) |
+ : Inst(Cfg, Inst::Br, 1, NULL), TargetFalse(TargetFalse), |
+ TargetTrue(TargetTrue) { |
+ if (TargetTrue == TargetFalse) { |
+ TargetTrue = NULL; // turn into unconditional version |
+ } else { |
+ addSource(Source); |
+ } |
+} |
+ |
+InstBr::InstBr(IceCfg *Cfg, CfgNode *Target) |
+ : Inst(Cfg, Inst::Br, 0, NULL), TargetFalse(Target), TargetTrue(NULL) {} |
+ |
+NodeList InstBr::getTerminatorEdges() const { |
+ NodeList OutEdges; |
+ OutEdges.push_back(TargetFalse); |
+ if (TargetTrue) |
+ OutEdges.push_back(TargetTrue); |
+ return OutEdges; |
+} |
+ |
+InstCast::InstCast(IceCfg *Cfg, OpKind CastKind, Variable *Dest, |
+ Operand *Source) |
+ : Inst(Cfg, Inst::Cast, 1, Dest), CastKind(CastKind) { |
+ addSource(Source); |
+} |
+ |
+InstFcmp::InstFcmp(IceCfg *Cfg, FCond Condition, Variable *Dest, |
+ Operand *Source1, Operand *Source2) |
+ : Inst(Cfg, Inst::Fcmp, 2, Dest), Condition(Condition) { |
+ addSource(Source1); |
+ addSource(Source2); |
+} |
+ |
+InstIcmp::InstIcmp(IceCfg *Cfg, ICond Condition, Variable *Dest, |
+ Operand *Source1, Operand *Source2) |
+ : Inst(Cfg, Inst::Icmp, 2, Dest), Condition(Condition) { |
+ addSource(Source1); |
+ addSource(Source2); |
+} |
+ |
+InstLoad::InstLoad(IceCfg *Cfg, Variable *Dest, Operand *SourceAddr) |
+ : Inst(Cfg, Inst::Load, 1, Dest) { |
+ addSource(SourceAddr); |
+} |
+ |
+InstPhi::InstPhi(IceCfg *Cfg, IceSize_t MaxSrcs, Variable *Dest) |
+ : Inst(Cfg, Phi, MaxSrcs, Dest) { |
+ Labels = Cfg->allocateArrayOf<CfgNode *>(MaxSrcs); |
+} |
+ |
+// TODO: A Switch instruction (and maybe others) can add duplicate |
+// edges. We may want to de-dup Phis and validate consistency (i.e., |
+// the source operands are the same for duplicate edges), though it |
+// seems the current lowering code is OK with this situation. |
+void InstPhi::addArgument(Operand *Source, CfgNode *Label) { |
+ Labels[getSrcSize()] = Label; |
+ addSource(Source); |
+} |
+ |
+InstRet::InstRet(IceCfg *Cfg, Operand *RetValue) |
+ : Inst(Cfg, Ret, RetValue ? 1 : 0, NULL) { |
+ if (RetValue) |
+ addSource(RetValue); |
+} |
+ |
+InstSelect::InstSelect(IceCfg *Cfg, Variable *Dest, Operand *Condition, |
+ Operand *SourceTrue, Operand *SourceFalse) |
+ : Inst(Cfg, Inst::Select, 3, Dest) { |
+ assert(Condition->getType() == IceType_i1); |
+ addSource(Condition); |
+ addSource(SourceTrue); |
+ addSource(SourceFalse); |
+} |
+ |
+InstStore::InstStore(IceCfg *Cfg, Operand *Data, Operand *Addr) |
+ : Inst(Cfg, Inst::Store, 2, NULL) { |
+ addSource(Data); |
+ addSource(Addr); |
+} |
+ |
+InstSwitch::InstSwitch(IceCfg *Cfg, IceSize_t NumCases, Operand *Source, |
+ CfgNode *LabelDefault) |
+ : Inst(Cfg, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), |
+ NumCases(NumCases) { |
+ addSource(Source); |
+ Values = Cfg->allocateArrayOf<uint64_t>(NumCases); |
+ Labels = Cfg->allocateArrayOf<CfgNode *>(NumCases); |
+ // Initialize in case buggy code doesn't set all entries |
+ for (IceSize_t I = 0; I < NumCases; ++I) { |
+ Values[I] = 0; |
+ Labels[I] = NULL; |
+ } |
+} |
+ |
+void InstSwitch::addBranch(IceSize_t CaseIndex, uint64_t Value, |
+ CfgNode *Label) { |
+ assert(CaseIndex < NumCases); |
+ Values[CaseIndex] = Value; |
+ Labels[CaseIndex] = Label; |
+} |
+ |
+NodeList InstSwitch::getTerminatorEdges() const { |
+ NodeList OutEdges; |
+ OutEdges.push_back(LabelDefault); |
+ for (IceSize_t I = 0; I < NumCases; ++I) { |
+ OutEdges.push_back(Labels[I]); |
+ } |
+ return OutEdges; |
+} |
+ |
+InstUnreachable::InstUnreachable(IceCfg *Cfg) |
+ : Inst(Cfg, Inst::Unreachable, 0, NULL) {} |
+ |
+// ======================== Dump routines ======================== // |
+ |
+void Inst::dumpDecorated(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ if (!Cfg->getContext()->isVerbose(IceV_Deleted) && isDeleted()) |
+ return; |
+ if (Cfg->getContext()->isVerbose(IceV_InstNumbers)) { |
+ const static size_t BufLen = 30; |
+ char buf[BufLen]; |
+ int32_t Number = getNumber(); |
+ if (Number < 0) |
+ snprintf(buf, BufLen, "[XXX]"); |
+ else |
+ snprintf(buf, BufLen, "[%3d]", Number); |
+ Str << buf; |
+ } |
+ Str << " "; |
+ if (isDeleted()) |
+ Str << " //"; |
+ dump(Cfg); |
+ Str << "\n"; |
+} |
+ |
+void Inst::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " =~ "; |
+ dumpSources(Cfg); |
+} |
+ |
+void Inst::dumpSources(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ for (IceSize_t I = 0; I < getSrcSize(); ++I) { |
+ if (I > 0) |
+ Str << ", "; |
+ getSrc(I)->dump(Cfg); |
+ } |
+} |
+ |
+void Inst::dumpDest(const IceCfg *Cfg) const { |
+ if (getDest()) |
+ getDest()->dump(Cfg); |
+} |
+ |
+void InstAlloca::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = alloca i8, i32 "; |
+ getSizeInBytes()->dump(Cfg); |
+ Str << ", align " << Align; |
+} |
+ |
+void InstArithmetic::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = "; |
+ |
+#define X(tag, str, commutative) \ |
+ case tag: \ |
+ Str << str; \ |
+ break; |
+ |
+ switch (getOp()) { ICEINSTARITHMETIC_TABLE } |
JF
2014/04/23 03:51:28
Same thing on table lookup from static const char
Jim Stichnoth
2014/04/26 15:02:11
Done.
|
+#undef X |
+ |
+ Str << " " << getDest()->getType() << " "; |
+ dumpSources(Cfg); |
+} |
+ |
+void InstAssign::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = " << getDest()->getType() << " "; |
+ dumpSources(Cfg); |
+} |
+ |
+void InstBr::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << "br "; |
+ if (!isUnconditional()) { |
+ Str << "i1 "; |
+ getCondition()->dump(Cfg); |
+ Str << ", label %" << getTargetTrue()->getName() << ", "; |
+ } |
+ Str << "label %" << getTargetFalse()->getName(); |
+} |
+ |
+void InstCall::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ if (getDest()) { |
+ dumpDest(Cfg); |
+ Str << " = "; |
+ } |
+ if (Tail) |
+ Str << "tail "; |
+ Str << "call "; |
+ if (getDest()) |
+ Str << getDest()->getType(); |
+ else |
+ Str << "void"; |
+ Str << " "; |
+ getCallTarget()->dump(Cfg); |
+ Str << "("; |
+ for (IceSize_t I = 0; I < getNumArgs(); ++I) { |
+ if (I > 0) |
+ Str << ", "; |
+ Str << getArg(I)->getType() << " "; |
+ getArg(I)->dump(Cfg); |
+ } |
+ Str << ")"; |
+} |
+ |
+void InstCast::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = "; |
+ |
+#define X(tag, str) \ |
+ case tag: \ |
+ Str << str; \ |
+ break; |
+ |
+ switch (getCastKind()) { |
+ ICEINSTCAST_TABLE |
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
|
+ default: |
+ Str << "UNKNOWN"; |
+ assert(0); |
+ break; |
+ } |
+#undef X |
+ |
+ Str << " " << getSrc(0)->getType() << " "; |
+ dumpSources(Cfg); |
+ Str << " to " << getDest()->getType(); |
+} |
+ |
+void InstIcmp::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = icmp "; |
+ |
+#define X(tag, str) \ |
+ case tag: \ |
+ Str << str; \ |
+ break; |
+ |
+ switch (getCondition()) { ICEINSTICMP_TABLE } |
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
|
+#undef X |
+ Str << " " << getSrc(0)->getType() << " "; |
+ dumpSources(Cfg); |
+} |
+ |
+void InstFcmp::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = fcmp "; |
+ |
+#define X(tag, str) \ |
+ case tag: \ |
+ Str << str; \ |
+ break; |
+ |
+ switch (getCondition()) { ICEINSTFCMP_TABLE } |
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
|
+#undef X |
+ Str << " " << getSrc(0)->getType() << " "; |
+ dumpSources(Cfg); |
+} |
+ |
+void InstLoad::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ IceType Type = getDest()->getType(); |
+ Str << " = load " << Type << "* "; |
+ dumpSources(Cfg); |
+ switch (Type) { |
+ case IceType_f32: |
+ Str << ", align 4"; |
+ break; |
+ case IceType_f64: |
+ Str << ", align 8"; |
+ break; |
+ default: |
+ Str << ", align 1"; |
+ break; |
+ } |
+} |
+ |
+void InstStore::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ IceType Type = getData()->getType(); |
+ Str << "store " << Type << " "; |
+ getData()->dump(Cfg); |
+ Str << ", " << Type << "* "; |
+ getAddr()->dump(Cfg); |
+ Str << ", align "; |
+ switch (Type) { |
+ case IceType_f32: |
+ Str << "4"; |
+ break; |
+ case IceType_f64: |
+ Str << "8"; |
+ break; |
+ default: |
+ Str << "1"; |
+ break; |
+ } |
+} |
+ |
+void InstSwitch::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ IceType Type = getComparison()->getType(); |
+ Str << "switch " << Type << " "; |
+ getSrc(0)->dump(Cfg); |
+ Str << ", label %" << getLabelDefault()->getName() << " [\n"; |
+ for (IceSize_t I = 0; I < getNumCases(); ++I) { |
+ Str << " " << Type << " " << getValue(I) << ", label %" |
+ << getLabel(I)->getName() << "\n"; |
+ } |
+ Str << " ]"; |
+} |
+ |
+void InstPhi::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Str << " = phi " << getDest()->getType() << " "; |
+ for (IceSize_t I = 0; I < getSrcSize(); ++I) { |
+ if (I > 0) |
+ Str << ", "; |
+ Str << "[ "; |
+ getSrc(I)->dump(Cfg); |
+ Str << ", %" << Labels[I]->getName() << " ]"; |
+ } |
+} |
+ |
+void InstRet::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ IceType Type = hasRetValue() ? getSrc(0)->getType() : IceType_void; |
+ Str << "ret " << Type; |
+ if (hasRetValue()) { |
+ Str << " "; |
+ dumpSources(Cfg); |
+ } |
+} |
+ |
+void InstSelect::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ dumpDest(Cfg); |
+ Operand *Condition = getCondition(); |
+ Operand *TrueOp = getTrueOperand(); |
+ Operand *FalseOp = getFalseOperand(); |
+ Str << " = select " << Condition->getType() << " "; |
+ Condition->dump(Cfg); |
+ Str << ", " << TrueOp->getType() << " "; |
+ TrueOp->dump(Cfg); |
+ Str << ", " << FalseOp->getType() << " "; |
+ FalseOp->dump(Cfg); |
+} |
+ |
+void InstUnreachable::dump(const IceCfg *Cfg) const { |
+ IceOstream &Str = Cfg->getContext()->getStrDump(); |
+ Str << "unreachable"; |
+} |
+ |
+} // end of namespace Ice |