[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