Add Om1 lowering with no optimizations.
This adds infrastructure for low-level x86-32 instructions, and the target lowering patterns.
Practically no optimizations are performed. Optimizations to be introduced later include liveness analysis, dead-code elimination, global linear-scan register allocation, linear-scan based stack slot coalescing, and compare/branch fusing. One optimization that is present is simple coalescing of stack slots for variables that are only live within a single basic block.
There are also some fairly comprehensive cross tests. This testing infrastructure translates bitcode using both Subzero and llc, and a testing harness calls both versions with a variety of "interesting" inputs and compares the results. Specifically, Arithmetic, Icmp, Fcmp, and Cast instructions are tested this way, across all PNaCl primitive types.
BUG=
R=jvoung@chromium.org
Review URL: https://codereview.chromium.org/265703002
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index 1009a33..56520d3 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -16,6 +16,7 @@
#include "IceCfg.h"
#include "IceInst.h"
#include "IceOperand.h"
+#include "IceTargetLowering.h" // dumping stack/frame pointer register
namespace Ice {
@@ -27,6 +28,14 @@
return A.Name < B.Name;
}
+bool operator<(const RegWeight &A, const RegWeight &B) {
+ return A.getWeight() < B.getWeight();
+}
+bool operator<=(const RegWeight &A, const RegWeight &B) { return !(B < A); }
+bool operator==(const RegWeight &A, const RegWeight &B) {
+ return !(B < A) && !(A < B);
+}
+
void Variable::setUse(const Inst *Inst, const CfgNode *Node) {
if (DefNode == NULL)
return;
@@ -66,19 +75,57 @@
return buf;
}
+Variable Variable::asType(Type Ty) {
+ Variable V(Ty, DefNode, Number, Name);
+ V.RegNum = RegNum;
+ V.StackOffset = StackOffset;
+ return V;
+}
+
// ======================== dump routines ======================== //
+void Variable::emit(const Cfg *Func) const {
+ Func->getTarget()->emitVariable(this, Func);
+}
+
void Variable::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
const CfgNode *CurrentNode = Func->getCurrentNode();
(void)CurrentNode; // used only in assert()
assert(CurrentNode == NULL || DefNode == NULL || DefNode == CurrentNode);
- Str << "%" << getName();
+ if (Func->getContext()->isVerbose(IceV_RegOrigins) ||
+ (!hasReg() && !Func->getTarget()->hasComputedFrame()))
+ Str << "%" << getName();
+ if (hasReg()) {
+ if (Func->getContext()->isVerbose(IceV_RegOrigins))
+ Str << ":";
+ Str << Func->getTarget()->getRegName(RegNum, getType());
+ } else if (Func->getTarget()->hasComputedFrame()) {
+ if (Func->getContext()->isVerbose(IceV_RegOrigins))
+ Str << ":";
+ Str << "[" << Func->getTarget()->getRegName(
+ Func->getTarget()->getFrameOrStackReg(), IceType_i32);
+ int32_t Offset = getStackOffset();
+ if (Offset) {
+ if (Offset > 0)
+ Str << "+";
+ Str << Offset;
+ }
+ Str << "]";
+ }
}
-void Operand::dump(const Cfg *Func) const {
- Ostream &Str = Func->getContext()->getStrDump();
- Str << "Operand<?>";
+void ConstantRelocatable::emit(const Cfg *Func) const {
+ Ostream &Str = Func->getContext()->getStrEmit();
+ if (SuppressMangling)
+ Str << Name;
+ else
+ Str << Func->getContext()->mangleName(Name);
+ if (Offset) {
+ if (Offset > 0)
+ Str << "+";
+ Str << Offset;
+ }
}
void ConstantRelocatable::dump(const Cfg *Func) const {
@@ -88,4 +135,12 @@
Str << "+" << Offset;
}
+Ostream &operator<<(Ostream &Str, const RegWeight &W) {
+ if (W.getWeight() == RegWeight::Inf)
+ Str << "Inf";
+ else
+ Str << W.getWeight();
+ return Str;
+}
+
} // end of namespace Ice