diff --git a/include/avian/codegen/architecture.h b/include/avian/codegen/architecture.h index 5500311446..47687aefaf 100644 --- a/include/avian/codegen/architecture.h +++ b/include/avian/codegen/architecture.h @@ -45,7 +45,7 @@ class OperandMask { { } - OperandMask() : typeMask(~0), lowRegisterMask(RegisterMask::Any), highRegisterMask(RegisterMask::Any) + OperandMask() : typeMask(~0), lowRegisterMask(AnyRegisterMask), highRegisterMask(AnyRegisterMask) { } diff --git a/include/avian/codegen/assembler.h b/include/avian/codegen/assembler.h index d7be61c326..e1d451a8a9 100644 --- a/include/avian/codegen/assembler.h +++ b/include/avian/codegen/assembler.h @@ -53,7 +53,7 @@ class Assembler { public: class Client { public: - virtual Register acquireTemporary(RegisterMask mask = RegisterMask::Any) = 0; + virtual Register acquireTemporary(RegisterMask mask = AnyRegisterMask) = 0; virtual void releaseTemporary(Register r) = 0; virtual void save(Register r) = 0; diff --git a/include/avian/codegen/registers.h b/include/avian/codegen/registers.h index cc91b458a5..5cafcc724c 100644 --- a/include/avian/codegen/registers.h +++ b/include/avian/codegen/registers.h @@ -61,11 +61,27 @@ constexpr Register NoRegister; class RegisterMask { private: uint64_t mask; + + static constexpr unsigned maskStart(uint64_t mask, unsigned offset = 64) { + return mask == 0 ? (offset & 63) : maskStart(mask << 1, offset - 1); + } + + static constexpr unsigned maskLimit(uint64_t mask, unsigned offset = 0) { + return mask == 0 ? offset : maskLimit(mask >> 1, offset + 1); + } public: constexpr RegisterMask(uint64_t mask) : mask(mask) {} constexpr RegisterMask() : mask(0) {} constexpr RegisterMask(Register reg) : mask(static_cast(1) << reg.index()) {} + constexpr unsigned begin() const { + return maskStart(mask); + } + + constexpr unsigned end() const { + return maskLimit(mask); + } + constexpr RegisterMask operator &(RegisterMask o) const { return RegisterMask(mask & o.mask); } @@ -102,36 +118,79 @@ public: constexpr explicit operator bool() const { return mask != 0; } - - static RegisterMask Any; - static RegisterMask None; }; +constexpr RegisterMask AnyRegisterMask(~static_cast(0)); +constexpr RegisterMask NoneRegisterMask(0); + constexpr RegisterMask Register::operator | (Register o) const { return RegisterMask(*this) | o; } +class RegisterIterator; + class BoundedRegisterMask : public RegisterMask { public: uint8_t start; uint8_t limit; - static unsigned maskStart(RegisterMask mask); - static unsigned maskLimit(RegisterMask mask); - - inline BoundedRegisterMask(RegisterMask mask) - : RegisterMask(mask), start(maskStart(mask)), limit(maskLimit(mask)) + BoundedRegisterMask(RegisterMask mask) + : RegisterMask(mask), start(mask.begin()), limit(mask.end()) { } + + RegisterIterator begin() const; + + RegisterIterator end() const; }; +class RegisterIterator { + public: + int index; + int direction; + int limit; + const RegisterMask mask; + + RegisterIterator(int index, int direction, int limit, RegisterMask mask) + : index(index), direction(direction), limit(limit), mask(mask) + { + } + + bool operator !=(const RegisterIterator& o) const { + return index != o.index; + } + + Register operator *() { + return Register(index); + } + + void operator ++ () { + if(index != limit) { + index += direction; + } + while(index != limit && !mask.contains(Register(index))) { + index += direction; + } + } +}; + +inline RegisterIterator BoundedRegisterMask::begin() const { + // We use reverse iteration... for some reason. + return RegisterIterator(limit - 1, -1, start - 1, *this); +} + +inline RegisterIterator BoundedRegisterMask::end() const { + // We use reverse iteration... for some reason. + return RegisterIterator(start - 1, -1, start - 1, *this); +} + class RegisterFile { public: BoundedRegisterMask allRegisters; BoundedRegisterMask generalRegisters; BoundedRegisterMask floatRegisters; - inline RegisterFile(RegisterMask generalRegisterMask, RegisterMask floatRegisterMask) + RegisterFile(RegisterMask generalRegisterMask, RegisterMask floatRegisterMask) : allRegisters(generalRegisterMask | floatRegisterMask), generalRegisters(generalRegisterMask), floatRegisters(floatRegisterMask) @@ -139,31 +198,6 @@ class RegisterFile { } }; -class RegisterIterator { - public: - int index; - const BoundedRegisterMask& mask; - - inline RegisterIterator(const BoundedRegisterMask& mask) - : index(mask.start), mask(mask) - { - } - - inline bool hasNext() - { - return index < mask.limit; - } - - inline Register next() - { - int r = index; - do { - index++; - } while (index < mask.limit && !(mask.contains(Register(index)))); - return Register(r); - } -}; - } // namespace codegen } // namespace avian diff --git a/makefile b/makefile index cbaa4ec42a..73efef11ca 100755 --- a/makefile +++ b/makefile @@ -1223,7 +1223,6 @@ compiler-sources = \ $(src)/codegen/compiler.cpp \ $(wildcard $(src)/codegen/compiler/*.cpp) \ $(src)/debug-util.cpp \ - $(src)/codegen/registers.cpp \ $(src)/codegen/runtime.cpp \ $(src)/codegen/targets.cpp \ $(src)/util/fixed-allocator.cpp diff --git a/src/codegen/CMakeLists.txt b/src/codegen/CMakeLists.txt index 8a0b4baaf2..001a8681d3 100644 --- a/src/codegen/CMakeLists.txt +++ b/src/codegen/CMakeLists.txt @@ -1,6 +1,5 @@ add_library (avian_codegen compiler.cpp - registers.cpp runtime.cpp targets.cpp diff --git a/src/codegen/compiler/context.cpp b/src/codegen/compiler/context.cpp index 17f50856ae..d285f0c77f 100644 --- a/src/codegen/compiler/context.cpp +++ b/src/codegen/compiler/context.cpp @@ -53,19 +53,15 @@ Context::Context(vm::System* system, - regFile->generalRegisters.start), targetInfo(arch->targetInfo()) { - for (unsigned i = regFile->generalRegisters.start; - i < regFile->generalRegisters.limit; - ++i) { - new (registerResources + i) RegisterResource(arch->reserved(Register(i))); + for (Register i : regFile->generalRegisters) { + new (registerResources + i.index()) RegisterResource(arch->reserved(i)); - if (registerResources[i].reserved) { + if (registerResources[i.index()].reserved) { --availableGeneralRegisterCount; } } - for (unsigned i = regFile->floatRegisters.start; - i < regFile->floatRegisters.limit; - ++i) { - new (registerResources + i) RegisterResource(arch->reserved(Register(i))); + for (Register i : regFile->floatRegisters) { + new (registerResources + i.index()) RegisterResource(arch->reserved(i)); } } diff --git a/src/codegen/compiler/regalloc.cpp b/src/codegen/compiler/regalloc.cpp index 13197c6b50..1aed5fda70 100644 --- a/src/codegen/compiler/regalloc.cpp +++ b/src/codegen/compiler/regalloc.cpp @@ -95,9 +95,7 @@ Register pickRegisterTarget(Context* c, *cost = Target::Impossible; if (mask & c->regFile->generalRegisters) { - for (Register i = Register(c->regFile->generalRegisters.limit - 1); - i.index() >= c->regFile->generalRegisters.start; - i = Register(i.index() - 1)) { + for (Register i : c->regFile->generalRegisters) { if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { return i; } @@ -105,9 +103,7 @@ Register pickRegisterTarget(Context* c, } if (mask & c->regFile->floatRegisters) { - for (Register i = Register(c->regFile->floatRegisters.start); - i.index() < c->regFile->floatRegisters.limit; - i = Register(i.index() + 1)) { + for (Register i : c->regFile->floatRegisters) { if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { return i; } @@ -235,7 +231,7 @@ Target pickTarget(Context* c, Value* value = read->value; RegisterMask registerMask - = (isFloatValue(value) ? RegisterMask::Any : (RegisterMask)c->regFile->generalRegisters); + = (isFloatValue(value) ? AnyRegisterMask : (RegisterMask)c->regFile->generalRegisters); SiteMask mask(~0, registerMask, AnyFrameIndex); read->intersect(&mask); diff --git a/src/codegen/registers.cpp b/src/codegen/registers.cpp deleted file mode 100644 index 001de19df7..0000000000 --- a/src/codegen/registers.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2008-2014, Avian Contributors - - Permission to use, copy, modify, and/or distribute this software - for any purpose with or without fee is hereby granted, provided - that the above copyright notice and this permission notice appear - in all copies. - - There is NO WARRANTY for this software. See license.txt for - details. */ - -#include - -namespace avian { -namespace codegen { - -unsigned BoundedRegisterMask::maskStart(RegisterMask mask) -{ - for (int i = 0; i <= 31; ++i) { - if (mask.contains(Register(i))) - return i; - } - return 32; -} - -unsigned BoundedRegisterMask::maskLimit(RegisterMask mask) -{ - for (int i = 31; i >= 0; --i) { - if (mask.contains(Register(i))) - return i + 1; - } - return 0; -} - -RegisterMask RegisterMask::Any(~static_cast(0)); - -} // namespace codegen -} // namespace avian diff --git a/src/codegen/target/arm/assembler.cpp b/src/codegen/target/arm/assembler.cpp index 2fd89a86db..a6c7491279 100644 --- a/src/codegen/target/arm/assembler.cpp +++ b/src/codegen/target/arm/assembler.cpp @@ -397,7 +397,7 @@ class MyArchitecture : public Architecture { bool* thunk) { aMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::ConstantMask; - aMask.setLowHighRegisterMasks(~static_cast(0), ~static_cast(0)); + aMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); *thunk = false; } @@ -506,7 +506,7 @@ class MyArchitecture : public Architecture { const OperandMask& dstMask) { srcMask.typeMask = ~0; - srcMask.setLowHighRegisterMasks(~static_cast(0), ~static_cast(0)); + srcMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); tmpMask.typeMask = 0; tmpMask.setLowHighRegisterMasks(0, 0); @@ -520,7 +520,7 @@ class MyArchitecture : public Architecture { && dstMask.lowRegisterMask & FPR_MASK) { srcMask.typeMask = tmpMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::MemoryMask; - tmpMask.setLowHighRegisterMasks(~static_cast(0), ~static_cast(0)); + tmpMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); } } diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index e78300f709..86736faa99 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -596,7 +596,7 @@ class MyArchitecture : public Architecture { case lir::Move: aMask.typeMask = ~0; - aMask.setLowHighRegisterMasks(~static_cast(0), ~static_cast(0)); + aMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); if (TargetBytesPerWord == 4) { if (aSize == 4 and bSize == 8) { @@ -697,7 +697,7 @@ class MyArchitecture : public Architecture { const OperandMask& dstMask) { srcMask.typeMask = ~0; - srcMask.setLowHighRegisterMasks(~static_cast(0), ~static_cast(0)); + srcMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); tmpMask.typeMask = 0; tmpMask.setLowHighRegisterMasks(0, 0); diff --git a/unittest/codegen/registers-test.cpp b/unittest/codegen/registers-test.cpp index b648ef6e13..861a1e76c3 100644 --- a/unittest/codegen/registers-test.cpp +++ b/unittest/codegen/registers-test.cpp @@ -23,14 +23,25 @@ TEST(RegisterIterator) assertEqual(0, regs.start); assertEqual(7, regs.limit); - RegisterIterator it(regs); - assertTrue(it.hasNext()); - assertEqual(0, it.next().index()); - assertTrue(it.hasNext()); - assertEqual(2, it.next().index()); - assertTrue(it.hasNext()); - assertEqual(4, it.next().index()); - assertTrue(it.hasNext()); - assertEqual(6, it.next().index()); - assertFalse(it.hasNext()); + for(int i = 0; i < 64; i++) { + assertEqual(i, BoundedRegisterMask(static_cast(1) << i).start); + assertEqual(i + 1, BoundedRegisterMask(static_cast(1) << i).limit); + } + + auto it = regs.begin(); + auto end = regs.end(); + + assertTrue(it != end); + assertEqual(6, (*it).index()); + ++it; + assertTrue(it != end); + assertEqual(4, (*it).index()); + ++it; + assertTrue(it != end); + assertEqual(2, (*it).index()); + ++it; + assertTrue(it != end); + assertEqual(0, (*it).index()); + ++it; + assertFalse(it != end); }