diff options
author | Mark Mendell <mark.p.mendell@intel.com> | 2015-03-26 21:07:46 -0400 |
---|---|---|
committer | Mark Mendell <mark.p.mendell@intel.com> | 2015-04-09 10:47:11 -0400 |
commit | f55c3e0825cdfc4c5a27730031177d1a0198ec5a (patch) | |
tree | 500a596838d0ec2bfb3f84ea3c4d87b35d5ca22f /compiler/utils | |
parent | 96159860fc6c4bf68a51a8a57941971f122685d6 (diff) | |
download | android_art-f55c3e0825cdfc4c5a27730031177d1a0198ec5a.tar.gz android_art-f55c3e0825cdfc4c5a27730031177d1a0198ec5a.tar.bz2 android_art-f55c3e0825cdfc4c5a27730031177d1a0198ec5a.zip |
[optimizing] Add RIP support for x86_64
Support a constant area addressed using RIP on x86_64. Use it for FP
operations to avoid loading constants into a CPU register and moving
to a XMM register.
Change-Id: I58421759ef2a8475538876c20e696ec787015a72
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
Diffstat (limited to 'compiler/utils')
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 54 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 112 |
2 files changed, 164 insertions, 2 deletions
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index 30e821860c..a9e8c501ea 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -1975,6 +1975,10 @@ void X86_64Assembler::EmitOperand(uint8_t reg_or_opcode, const Operand& operand) for (int i = 1; i < length; i++) { EmitUint8(operand.encoding_[i]); } + AssemblerFixup* fixup = operand.GetFixup(); + if (fixup != nullptr) { + EmitFixup(fixup); + } } @@ -2702,5 +2706,55 @@ void X86_64ExceptionSlowPath::Emit(Assembler *sasm) { #undef __ } +void X86_64Assembler::AddConstantArea() { + const std::vector<int32_t>& area = constant_area_.GetBuffer(); + for (size_t i = 0, u = area.size(); i < u; i++) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitInt32(area[i]); + } +} + +int ConstantArea::AddInt32(int32_t v) { + for (size_t i = 0, u = buffer_.size(); i < u; i++) { + if (v == buffer_[i]) { + return i * elem_size_; + } + } + + // Didn't match anything. + int result = buffer_.size() * elem_size_; + buffer_.push_back(v); + return result; +} + +int ConstantArea::AddInt64(int64_t v) { + int32_t v_low = v; + int32_t v_high = v >> 32; + if (buffer_.size() > 1) { + // Ensure we don't pass the end of the buffer. + for (size_t i = 0, u = buffer_.size() - 1; i < u; i++) { + if (v_low == buffer_[i] && v_high == buffer_[i+1]) { + return i * elem_size_; + } + } + } + + // Didn't match anything. + int result = buffer_.size() * elem_size_; + buffer_.push_back(v_low); + buffer_.push_back(v_high); + return result; +} + +int ConstantArea::AddDouble(double v) { + // Treat the value as a 64-bit integer value. + return AddInt64(bit_cast<int64_t, double>(v)); +} + +int ConstantArea::AddFloat(float v) { + // Treat the value as a 32-bit integer value. + return AddInt32(bit_cast<int32_t, float>(v)); +} + } // namespace x86_64 } // namespace art diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index d357a813e8..ef6205c870 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -97,9 +97,13 @@ class Operand : public ValueObject { && (reg.NeedsRex() == ((rex_ & 1) != 0)); // REX.000B bits match. } + AssemblerFixup* GetFixup() const { + return fixup_; + } + protected: // Operand can be sub classed (e.g: Address). - Operand() : rex_(0), length_(0) { } + Operand() : rex_(0), length_(0), fixup_(nullptr) { } void SetModRM(uint8_t mod_in, CpuRegister rm_in) { CHECK_EQ(mod_in & ~3, 0); @@ -136,12 +140,17 @@ class Operand : public ValueObject { length_ += disp_size; } + void SetFixup(AssemblerFixup* fixup) { + fixup_ = fixup; + } + private: uint8_t rex_; uint8_t length_; uint8_t encoding_[6]; + AssemblerFixup* fixup_; - explicit Operand(CpuRegister reg) : rex_(0), length_(0) { SetModRM(3, reg); } + explicit Operand(CpuRegister reg) : rex_(0), length_(0), fixup_(nullptr) { SetModRM(3, reg); } // Get the operand encoding byte at the given index. uint8_t encoding_at(int index_in) const { @@ -232,6 +241,15 @@ class Address : public Operand { return result; } + // An RIP relative address that will be fixed up later. + static Address RIP(AssemblerFixup* fixup) { + Address result; + result.SetModRM(0, CpuRegister(RBP)); + result.SetDisp32(0); + result.SetFixup(fixup); + return result; + } + // If no_rip is true then the Absolute address isn't RIP relative. static Address Absolute(ThreadOffset<8> addr, bool no_rip = false) { return Absolute(addr.Int32Value(), no_rip); @@ -242,6 +260,55 @@ class Address : public Operand { }; +/** + * Class to handle constant area values. + */ +class ConstantArea { + public: + ConstantArea() {} + + /** + * Add a double to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddDouble(double v); + + /** + * Add a float to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddFloat(float v); + + /** + * Add an int32_t to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddInt32(int32_t v); + + /** + * Add an int64_t to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddInt64(int64_t v); + + int GetSize() const { + return buffer_.size() * elem_size_; + } + + const std::vector<int32_t>& GetBuffer() const { + return buffer_; + } + + private: + static constexpr size_t elem_size_ = sizeof(int32_t); + std::vector<int32_t> buffer_; +}; + + class X86_64Assembler FINAL : public Assembler { public: X86_64Assembler() {} @@ -669,6 +736,45 @@ class X86_64Assembler FINAL : public Assembler { // and branch to a ExceptionSlowPath if it is. void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; + /** + * Add a double to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddDouble(double v) { return constant_area_.AddDouble(v); } + + /** + * Add a float to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddFloat(float v) { return constant_area_.AddFloat(v); } + + /** + * Add an int32_t to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddInt32(int32_t v) { return constant_area_.AddInt32(v); } + + /** + * Add an int64_t to the constant area. + * @param v literal to be added to the constant area. + * @returns the offset in the constant area where the literal resides. + */ + int AddInt64(int64_t v) { return constant_area_.AddInt64(v); } + + /** + * Add the contents of the constant area to the assembler buffer. + */ + void AddConstantArea(); + + /** + * Is the constant area empty? + * @returns 'true' if there are no literals in the constant area. + */ + bool IsConstantAreaEmpty() const { return constant_area_.GetSize() == 0; } + private: void EmitUint8(uint8_t value); void EmitInt32(int32_t value); @@ -714,6 +820,8 @@ class X86_64Assembler FINAL : public Assembler { void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src); void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand); + ConstantArea constant_area_; + DISALLOW_COPY_AND_ASSIGN(X86_64Assembler); }; |