ir/function.hpp
ir/value.cpp
ir/value.hpp
+ ir/lowering.cpp
+ ir/lowering.hpp
backend/context.cpp
backend/context.hpp
backend/program.cpp
*/
#include "ir/context.hpp"
#include "ir/unit.hpp"
+#include "ir/lowering.hpp"
namespace gbe {
namespace ir {
// Check first that all branch instructions point to valid labels
for (auto it = usedLabels->begin(); it != usedLabels->end(); ++it)
GBE_ASSERTM(*it != LABEL_IS_POINTED, "A label is used and not defined");
+ GBE_DELETE(usedLabels);
+
+ // Remove all returns and insert one unique return block at the end of the
+ // function
+ lowerReturn(unit, fn->getName());
+
+ // Properly order labels and compute the CFG
fn->sortLabels();
fn->computeCFG();
- GBE_DELETE(usedLabels);
const StackElem elem = fnStack.back();
fnStack.pop_back();
fn = elem.fn;
return fn->file.appendArrayTuple(reg, regNum);
}
/*! We just use variadic templates to forward instruction functions */
-#define DECL_INSN(NAME, FAMILY) \
+#define DECL_INSN(NAME, FAMILY) \
template <typename... Args> INLINE void NAME(Args...args);
#include "ir/instruction.hxx"
#undef DECL_INSN
return unit.getPointerSize();
}
-#define DECL_THREE_SRC_INSN(NAME) \
- INLINE void NAME(Type type, \
- Register dst, \
- Register src0, \
- Register src1, \
- Register src2) \
- { \
- const Tuple index = this->tuple(src0, src1, src2); \
- return this->NAME(type, dst, index); \
+#define DECL_THREE_SRC_INSN(NAME) \
+ INLINE void NAME(Type type, \
+ Register dst, \
+ Register src0, \
+ Register src1, \
+ Register src2) \
+ { \
+ const Tuple index = this->tuple(src0, src1, src2); \
+ return this->NAME(type, dst, index); \
}
DECL_THREE_SRC_INSN(MAD);
DECL_THREE_SRC_INSN(SEL);
this->STORE(type, index, offset, space, valueNum, dwAligned);
}
- private:
+ protected:
/*! A block must be started with a label */
void startBlock(void);
/*! A block must be ended with a branch */
};
// Use argument checker to assert argument value correctness
-#define DECL_INSN(NAME, FAMILY) \
- template <typename... Args> \
- INLINE void Context::NAME(Args...args) { \
- GBE_ASSERTM(fn != NULL, "No function currently defined"); \
- const Instruction insn = gbe::ir::NAME(args...); \
- this->append(insn); \
+#define DECL_INSN(NAME, FAMILY) \
+ template <typename... Args> \
+ INLINE void Context::NAME(Args...args) { \
+ GBE_ASSERTM(fn != NULL, "No function currently defined"); \
+ const Instruction insn = gbe::ir::NAME(args...); \
+ this->append(insn); \
}
#include "ir/instruction.hxx"
#undef DECL_INSN
if (insn.getOpcode() != OP_LABEL) return;
// Create the new label
+#if 0
Instruction *newLabel = newInstruction();
*newLabel = LABEL(LabelIndex(last));
-
+#else
+ const Instruction newLabel = LABEL(LabelIndex(last));
+#endif
// Replace the previous label instruction
LabelInstruction &label = cast<LabelInstruction>(insn);
const LabelIndex index = label.getLabelIndex();
labelMap.insert(std::make_pair(index, LabelIndex(last++)));
- newLabel->replace(&insn);
+ newLabel.replace(&insn);
});
// Patch all branch instructions with the new labels
const LabelIndex newIndex = labelMap.find(index)->second;
// Insert the patched branch instruction
- Instruction *newBra = newInstruction();
- if (bra.isPredicated() == true)
- *newBra = BRA(newIndex, bra.getPredicateIndex());
- else
- *newBra = BRA(newIndex);
- newBra->replace(&insn);
+ if (bra.isPredicated() == true) {
+ const Instruction newBra = BRA(newIndex, bra.getPredicateIndex());
+ newBra.replace(&insn);
+ } else {
+ const Instruction newBra = BRA(newIndex);
+ newBra.replace(&insn);
+ }
});
// Reset the label to block mapping
}
/*! Get function the entry point block */
INLINE const BasicBlock &getTopBlock(void) const {
- GBE_ASSERT(blockNum() > 0);
+ GBE_ASSERT(blockNum() > 0 && blocks[0] != NULL);
return *blocks[0];
}
+ /*! Get the last block */
+ INLINE const BasicBlock &getBottomBlock(void) const {
+ const uint32_t n = blockNum();
+ GBE_ASSERT(n > 0 && blocks[n-1] != NULL);
+ return *blocks[n-1];
+ }
+ /*! Get the last block */
+ INLINE BasicBlock &getBottomBlock(void) {
+ const uint32_t n = blockNum();
+ GBE_ASSERT(n > 0 && blocks[n-1] != NULL);
+ return *blocks[n-1];
+ }
/*! Get block from its label */
INLINE const BasicBlock &getBlock(LabelIndex label) const {
GBE_ASSERT(label < labelNum() && labels[label] != NULL);
out << "." << type << "." << addrSpace << (dwAligned ? "." : ".un") << "aligned";
out << " {";
for (uint32_t i = 0; i < valueNum; ++i)
- out << "%" << this->getDst(fn, i) << (i != (valueNum-1) ? " " : "");
+ out << "%" << this->getDst(fn, i) << (i != (valueNum-1u) ? " " : "");
out << "}";
out << " %" << this->getSrc(fn, 0);
}
out << "." << type << "." << addrSpace << (dwAligned ? "." : ".un") << "aligned";
out << " %" << this->getSrc(fn, 0) << " {";
for (uint32_t i = 0; i < valueNum; ++i)
- out << "%" << this->getSrc(fn, i+1) << (i != (valueNum-1) ? " " : "");
+ out << "%" << this->getSrc(fn, i+1) << (i != (valueNum-1u) ? " " : "");
out << "}";
}
return bb->getParent();
}
- void Instruction::replace(Instruction *other) {
+ void Instruction::replace(Instruction *other) const {
Function &fn = other->getFunction();
BasicBlock *bb = other->getParent();
- if (bb->getFirstInstruction() == other) bb->setFirstInstruction(this);
- if (bb->getLastInstruction() == other) bb->setLastInstruction(this);
- if (other->predecessor) other->predecessor->successor = this;
- if (other->successor) other->successor->predecessor = this;
- this->parent = other->parent;
- this->predecessor = other->predecessor;
- this->successor = other->successor;
+ Instruction *insn = fn.newInstruction();
+ *insn = *this;
+ if (bb->getFirstInstruction() == other) bb->setFirstInstruction(insn);
+ if (bb->getLastInstruction() == other) bb->setLastInstruction(insn);
+ if (other->predecessor) other->predecessor->successor = insn;
+ if (other->successor) other->successor->predecessor = insn;
+ insn->parent = other->parent;
+ insn->predecessor = other->predecessor;
+ insn->successor = other->successor;
fn.deleteInstruction(other);
}
*/
bool wellFormed(std::string &why) const;
/*! Replace other by this instruction */
- void replace(Instruction *other);
+ void replace(Instruction *other) const;
/*! Indicates if the instruction belongs to instruction type T. Typically, T
* can be BinaryInstruction, UnaryInstruction, LoadInstruction and so on
*/