Minor compiler update - unreachable code remover will not remove labels.

This commit is contained in:
kobalicek
2016-03-29 01:01:28 +02:00
parent 95aacf9fd1
commit 6ef5878eca
2 changed files with 47 additions and 17 deletions

View File

@@ -296,12 +296,26 @@ Error Context::removeUnreachableCode() {
if (node != first) { if (node != first) {
HLNode* end = node; HLNode* end = node;
node = first; node = first;
// NOTE: The strategy is as follows:
// 1. The algorithm removes everything until it finds a first label.
// 2. After the first label is found it removes only removable nodes.
bool removeEverything = true;
do { do {
HLNode* next = node->getNext(); HLNode* next = node->getNext();
if (!node->isInformative() && node->getType() != HLNode::kTypeAlign) { bool remove = node->isRemovable();
ASMJIT_TLOG("[%05d] Unreachable\n", node->getFlowId());
if (!remove) {
if (node->isLabel())
removeEverything = false;
remove = removeEverything;
}
if (remove) {
ASMJIT_TLOG("[%05d] Removing unreachable node\n", node->getFlowId());
compiler->removeNode(node); compiler->removeNode(node);
} }
node = next; node = next;
} while (node != end); } while (node != end);
} }

View File

@@ -105,28 +105,32 @@ struct HLNode {
//! is a mark that is set by scheduler after the node has been visited. //! is a mark that is set by scheduler after the node has been visited.
kFlagIsScheduled = 0x0002, kFlagIsScheduled = 0x0002,
//! Whether the node can be safely removed by the `Compiler` in case it's
//! unreachable.
kFlagIsRemovable = 0x0004,
//! Whether the node is informative only and can be safely removed. //! Whether the node is informative only and can be safely removed.
kFlagIsInformative = 0x0004, kFlagIsInformative = 0x0008,
//! Whether the `HLInst` is a jump. //! Whether the `HLInst` is a jump.
kFlagIsJmp = 0x0008, kFlagIsJmp = 0x0010,
//! Whether the `HLInst` is a conditional jump. //! Whether the `HLInst` is a conditional jump.
kFlagIsJcc = 0x0010, kFlagIsJcc = 0x0020,
//! Whether the `HLInst` is an unconditinal jump or conditional jump that is //! Whether the `HLInst` is an unconditinal jump or conditional jump that is
//! likely to be taken. //! likely to be taken.
kFlagIsTaken = 0x0020, kFlagIsTaken = 0x0040,
//! Whether the `HLNode` will return from a function. //! Whether the `HLNode` will return from a function.
//! //!
//! This flag is used by both `HLSentinel` and `HLRet`. //! This flag is used by both `HLSentinel` and `HLRet`.
kFlagIsRet = 0x0040, kFlagIsRet = 0x0080,
//! Whether the instruction is special. //! Whether the instruction is special.
kFlagIsSpecial = 0x0080, kFlagIsSpecial = 0x0100,
//! Whether the instruction is an FPU instruction. //! Whether the instruction is an FPU instruction.
kFlagIsFp = 0x0100 kFlagIsFp = 0x0200
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -187,9 +191,14 @@ struct HLNode {
ASMJIT_INLINE bool isTranslated() const noexcept { return hasFlag(kFlagIsTranslated); } ASMJIT_INLINE bool isTranslated() const noexcept { return hasFlag(kFlagIsTranslated); }
//! Get whether the node has been translated. //! Get whether the node has been translated.
ASMJIT_INLINE bool isScheduled() const noexcept { return hasFlag(kFlagIsScheduled); } ASMJIT_INLINE bool isScheduled() const noexcept { return hasFlag(kFlagIsScheduled); }
//! Get whether the node is removable if it's in unreachable code block.
ASMJIT_INLINE bool isRemovable() const noexcept { return hasFlag(kFlagIsRemovable); }
//! Get whether the node is informative only (comment, hint). //! Get whether the node is informative only (comment, hint).
ASMJIT_INLINE bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); } ASMJIT_INLINE bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); }
//! Whether the node is `HLLabel`.
ASMJIT_INLINE bool isLabel() const noexcept { return _type == kTypeLabel; }
//! Whether the `HLInst` node is an unconditional jump. //! Whether the `HLInst` node is an unconditional jump.
ASMJIT_INLINE bool isJmp() const noexcept { return hasFlag(kFlagIsJmp); } ASMJIT_INLINE bool isJmp() const noexcept { return hasFlag(kFlagIsJmp); }
//! Whether the `HLInst` node is a conditional jump. //! Whether the `HLInst` node is a conditional jump.
@@ -326,6 +335,7 @@ struct HLInst : public HLNode {
ASMJIT_INLINE HLInst(Compiler* compiler, uint32_t instId, uint32_t instOptions, Operand* opList, uint32_t opCount) noexcept ASMJIT_INLINE HLInst(Compiler* compiler, uint32_t instId, uint32_t instOptions, Operand* opList, uint32_t opCount) noexcept
: HLNode(compiler, kTypeInst) { : HLNode(compiler, kTypeInst) {
orFlags(kFlagIsRemovable);
_instId = static_cast<uint16_t>(instId); _instId = static_cast<uint16_t>(instId);
_reserved = 0; _reserved = 0;
_instOptions = instOptions; _instOptions = instOptions;
@@ -446,8 +456,10 @@ struct HLJump : public HLInst {
// [Construction / Destruction] // [Construction / Destruction]
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
ASMJIT_INLINE HLJump(Compiler* compiler, uint32_t code, uint32_t options, Operand* opList, uint32_t opCount) noexcept : ASMJIT_INLINE HLJump(Compiler* compiler, uint32_t code, uint32_t options, Operand* opList, uint32_t opCount) noexcept
HLInst(compiler, code, options, opList, opCount) {} : HLInst(compiler, code, options, opList, opCount),
_target(nullptr),
_jumpNext(nullptr) {}
ASMJIT_INLINE ~HLJump() noexcept {} ASMJIT_INLINE ~HLJump() noexcept {}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -657,7 +669,7 @@ struct HLComment : public HLNode {
ASMJIT_INLINE HLComment(Compiler* compiler, const char* comment) noexcept ASMJIT_INLINE HLComment(Compiler* compiler, const char* comment) noexcept
: HLNode(compiler, kTypeComment) { : HLNode(compiler, kTypeComment) {
orFlags(kFlagIsInformative); orFlags(kFlagIsRemovable | kFlagIsInformative);
_comment = comment; _comment = comment;
} }
@@ -680,7 +692,7 @@ struct HLSentinel : public HLNode {
//! Create a new `HLSentinel` instance. //! Create a new `HLSentinel` instance.
ASMJIT_INLINE HLSentinel(Compiler* compiler) noexcept ASMJIT_INLINE HLSentinel(Compiler* compiler) noexcept
: HLNode(compiler, kTypeSentinel) { : HLNode(compiler, kTypeSentinel) {
_flags |= kFlagIsRet; orFlags(kFlagIsRet);
} }
//! Destroy the `HLSentinel` instance. //! Destroy the `HLSentinel` instance.
@@ -703,7 +715,7 @@ struct HLHint : public HLNode {
ASMJIT_INLINE HLHint(Compiler* compiler, VarData* vd, uint32_t hint, uint32_t value) noexcept ASMJIT_INLINE HLHint(Compiler* compiler, VarData* vd, uint32_t hint, uint32_t value) noexcept
: HLNode(compiler, kTypeHint) { : HLNode(compiler, kTypeHint) {
orFlags(kFlagIsInformative); orFlags(kFlagIsRemovable | kFlagIsInformative);
_vd = vd; _vd = vd;
_hint = hint; _hint = hint;
_value = value; _value = value;
@@ -977,7 +989,7 @@ struct HLRet : public HLNode {
ASMJIT_INLINE HLRet(Compiler* compiler, const Operand& o0, const Operand& o1) noexcept ASMJIT_INLINE HLRet(Compiler* compiler, const Operand& o0, const Operand& o1) noexcept
: HLNode(compiler, kTypeRet) { : HLNode(compiler, kTypeRet) {
_flags |= kFlagIsRet; orFlags(kFlagIsRet);
_ret[0] = o0; _ret[0] = o0;
_ret[1] = o1; _ret[1] = o1;
} }
@@ -1024,7 +1036,9 @@ struct HLCall : public HLNode {
: HLNode(compiler, kTypeCall), : HLNode(compiler, kTypeCall),
_decl(nullptr), _decl(nullptr),
_target(target), _target(target),
_args(nullptr) {} _args(nullptr) {
orFlags(kFlagIsRemovable);
}
//! Destroy the `HLCall` instance. //! Destroy the `HLCall` instance.
ASMJIT_INLINE ~HLCall() noexcept {} ASMJIT_INLINE ~HLCall() noexcept {}
@@ -1096,7 +1110,9 @@ struct HLCallArg : public HLNode {
_call(call), _call(call),
_sVd(sVd), _sVd(sVd),
_cVd(cVd), _cVd(cVd),
_args(0) {} _args(0) {
orFlags(kFlagIsRemovable);
}
//! Destroy the `HLCallArg` instance. //! Destroy the `HLCallArg` instance.
ASMJIT_INLINE ~HLCallArg() noexcept {} ASMJIT_INLINE ~HLCallArg() noexcept {}