[aarch64-port-dev ] Use LDR (literal) for loads from constant pool

Andrew Haley aph at redhat.com
Tue Dec 10 08:56:52 PST 2013


The LDR (literal) instruction has a range of 2^20 bytes.  I think this
is probably enough, given that the amount of code in a method is
limited to 2^16 bytes.  I suppose we could (should?) check for all of
the cases in our code generation where we're using a PC-relative load
and convert them to ADRP if they don't reach, but I think that HotSpot
doesn't try to compile such huge methods anyway.

Andrew.



# HG changeset patch
# User aph
# Date 1386693415 0
# Node ID 0ddd83538c3354e2d6fffe49db65ab814ae7d751
# Parent  93b2e2d86bbd1e550697dfb099cd2eb38ca69b19
Use LDR (literal) for loads from constant pool

diff -r 93b2e2d86bbd -r 0ddd83538c33 src/cpu/aarch64/vm/aarch64.ad
--- a/src/cpu/aarch64/vm/aarch64.ad	Tue Dec 10 14:28:28 2013 +0000
+++ b/src/cpu/aarch64/vm/aarch64.ad	Tue Dec 10 16:36:55 2013 +0000
@@ -5114,13 +5114,11 @@
   ins_cost(DEFAULT_COST * 2);

   format %{
-    "lea rscratch1, [$constantaddress]\t# load from constant table: float=$con\n\t"
-    "ldrs $dst, rscratch1"
-  %}
-
-  ins_encode %{
-    __ lea(rscratch1, $constantaddress($con));
-    __ ldrs(as_FloatRegister($dst$$reg), rscratch1);
+    "ldrs $dst, [$constantaddress]\t# load from constant table: float=$con\n\t"
+  %}
+
+  ins_encode %{
+    __ ldrs(as_FloatRegister($dst$$reg), $constantaddress($con));
   %}

   ins_pipe(pipe_class_default);
@@ -5146,13 +5144,11 @@

   ins_cost(DEFAULT_COST * 2);
   format %{
-    "lea rscratch1, [$constantaddress]\t# load from constant table: float=$con\n\t"
-    "ldrd $dst, rscratch1"
-  %}
-
-  ins_encode %{
-    __ lea(rscratch1, $constantaddress($con));
-    __ ldrd(as_FloatRegister($dst$$reg), rscratch1);
+    "ldrd $dst, [$constantaddress]\t# load from constant table: float=$con\n\t"
+  %}
+
+  ins_encode %{
+    __ ldrd(as_FloatRegister($dst$$reg), $constantaddress($con));
   %}

   ins_pipe(pipe_class_default);
diff -r 93b2e2d86bbd -r 0ddd83538c33 src/cpu/aarch64/vm/assembler_aarch64.hpp
--- a/src/cpu/aarch64/vm/assembler_aarch64.hpp	Tue Dec 10 14:28:28 2013 +0000
+++ b/src/cpu/aarch64/vm/assembler_aarch64.hpp	Tue Dec 10 16:36:55 2013 +0000
@@ -428,6 +428,9 @@
   Register index() {
     return _index;
   }
+  mode getMode() const {
+    return _mode;
+  }
   bool uses(Register reg) const { return _base == reg || _index == reg; }
   address target() const { return _target; }
   const RelocationHolder& rspec() const { return _rspec; }
@@ -483,10 +486,6 @@
       i->sf(_offset, 20, 12);
       break;

-    case literal:
-      ShouldNotReachHere();
-      break;
-
     default:
       ShouldNotReachHere();
     }
@@ -1226,10 +1225,32 @@
   // Load/store register (all modes)
   void ld_st2(Register Rt, const Address &adr, int size, int op, int V = 0) {
     starti;
+
+    f(V, 26); // general reg?
+    zrf(Rt, 0);
+
+    // Encoding for literal loads is done here (rather than pushed
+    // down into Address::encode) because the encoding of this
+    // instruction is too different from all of the other forms to
+    // make it worth sharing.
+    if (adr.getMode() == Address::literal) {
+      assert(size == 0b10 || size == 0b11, "bad operand size in ldr");
+      assert(op == 0b01, "literal form can only be used with loads");
+      f(size & 0b01, 31, 30), f(0b011, 29, 27), f(0b00, 25, 24);
+      long offset = (adr.target() - pc()) >> 2;
+      sf(offset, 23, 5);
+#ifdef ASSERT
+      Relocation* reloc = adr.rspec().reloc();
+      relocInfo::relocType rtype = (relocInfo::relocType) reloc->type();
+      assert(rtype == relocInfo::internal_word_type,
+	     "only internal_word_type relocs make sense here");
+#endif
+      code_section()->relocate(pc(), adr.rspec());
+      return;
+    }
+
     f(size, 31, 30);
     f(op, 23, 22); // str
-    f(V, 26); // general reg?
-    zrf(Rt, 0);
     adr.encode(current);
   }




More information about the aarch64-port-dev mailing list