[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>
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index d357a81..ef6205c 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -97,9 +97,13 @@
&& (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 @@
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 @@
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 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 @@
// 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 @@
void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src);
void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand);
+ ConstantArea constant_area_;
+
DISALLOW_COPY_AND_ASSIGN(X86_64Assembler);
};