MIPS64: small improvements in code generation
Specifically:
- More efficient load/store of constant 0 (and +0.0)
- Improved swapping of floats/doubles in registers
- Use kNoOutputOverlap wherever possible
- More efficient 64-bit integer comparison with 0
- More efficient load of integer constants of the form (2**n)-1
Change-Id: Ic2914d8865aa6616b9a0b21b3cc173d4477eb8c7
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index 00e8995..cedbedb 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -892,45 +892,58 @@
} else if ((value & 0xFFFF) == 0 && ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) {
Lui(rd, value >> 16);
Dati(rd, (value >> 48) + bit31);
+ } else if (IsPowerOfTwo(value + UINT64_C(1))) {
+ int shift_cnt = 64 - CTZ(value + UINT64_C(1));
+ Daddiu(rd, ZERO, -1);
+ if (shift_cnt < 32) {
+ Dsrl(rd, rd, shift_cnt);
+ } else {
+ Dsrl32(rd, rd, shift_cnt & 31);
+ }
} else {
int shift_cnt = CTZ(value);
int64_t tmp = value >> shift_cnt;
if (IsUint<16>(tmp)) {
Ori(rd, ZERO, tmp);
- if (shift_cnt < 32)
+ if (shift_cnt < 32) {
Dsll(rd, rd, shift_cnt);
- else
+ } else {
Dsll32(rd, rd, shift_cnt & 31);
+ }
} else if (IsInt<16>(tmp)) {
Daddiu(rd, ZERO, tmp);
- if (shift_cnt < 32)
+ if (shift_cnt < 32) {
Dsll(rd, rd, shift_cnt);
- else
+ } else {
Dsll32(rd, rd, shift_cnt & 31);
+ }
} else if (IsInt<32>(tmp)) {
// Loads with 3 instructions.
Lui(rd, tmp >> 16);
Ori(rd, rd, tmp);
- if (shift_cnt < 32)
+ if (shift_cnt < 32) {
Dsll(rd, rd, shift_cnt);
- else
+ } else {
Dsll32(rd, rd, shift_cnt & 31);
+ }
} else {
shift_cnt = 16 + CTZ(value >> 16);
tmp = value >> shift_cnt;
if (IsUint<16>(tmp)) {
Ori(rd, ZERO, tmp);
- if (shift_cnt < 32)
+ if (shift_cnt < 32) {
Dsll(rd, rd, shift_cnt);
- else
+ } else {
Dsll32(rd, rd, shift_cnt & 31);
+ }
Ori(rd, rd, value);
} else if (IsInt<16>(tmp)) {
Daddiu(rd, ZERO, tmp);
- if (shift_cnt < 32)
+ if (shift_cnt < 32) {
Dsll(rd, rd, shift_cnt);
- else
+ } else {
Dsll32(rd, rd, shift_cnt & 31);
+ }
Ori(rd, rd, value);
} else {
// Loads with 3-4 instructions.
@@ -941,10 +954,11 @@
used_lui = true;
}
if ((tmp2 & 0xFFFF) != 0) {
- if (used_lui)
+ if (used_lui) {
Ori(rd, rd, tmp2);
- else
+ } else {
Ori(rd, ZERO, tmp2);
+ }
}
if (bit31) {
tmp2 += UINT64_C(0x100000000);