summaryrefslogtreecommitdiffstats
path: root/compiler/utils
diff options
context:
space:
mode:
authorMark Mendell <mark.p.mendell@intel.com>2015-03-26 21:07:46 -0400
committerMark Mendell <mark.p.mendell@intel.com>2015-04-09 10:47:11 -0400
commitf55c3e0825cdfc4c5a27730031177d1a0198ec5a (patch)
tree500a596838d0ec2bfb3f84ea3c4d87b35d5ca22f /compiler/utils
parent96159860fc6c4bf68a51a8a57941971f122685d6 (diff)
downloadandroid_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.cc54
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h112
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);
};