Commit 2751ca49 authored by Miran.Karic's avatar Miran.Karic Committed by Commit Bot

MIPS64: Fix optimizations to li macro.

An optimization in li checks if a value has all their "n" LSBs set to
one, and their "64-n" MSBs set to zero. This is done by checking
base::bits::IsPowerOfTwo(value + 1), but this doesn't cover the case
when only MSB is zero, and other bits are one. Added another check that
covers the missing case, this also fixes Dsubu test.

BUG=
TEST=cctest/test-assembler-mips/Dsubu

Change-Id: I97b8fb4984af3b7f974ba901e3a1a9c89e925805
Reviewed-on: https://chromium-review.googlesource.com/598228Reviewed-by: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Commit-Queue: Miran Karić <Miran.Karic@imgtec.com>
Cr-Commit-Position: refs/heads/master@{#47134}
parent 439f1f6f
......@@ -1582,7 +1582,8 @@ int TurboAssembler::InstrCountForLi64Bit(int64_t value) {
((value >> 31) & 0x1ffff) == ((0x20000 - bit31) & 0x1ffff) &&
kArchVariant == kMips64r6) {
return 2;
} else if (base::bits::IsPowerOfTwo(value + 1)) {
} else if (base::bits::IsPowerOfTwo(value + 1) ||
value == std::numeric_limits<int64_t>::max()) {
return 2;
} else {
int shift_cnt = base::bits::CountTrailingZeros64(value);
......@@ -1649,6 +1650,8 @@ int TurboAssembler::InstrCountForLi64Bit(int64_t value) {
return INT_MAX;
}
// All changes to if...else conditions here must be added to
// InstrCountForLi64Bit as well.
void TurboAssembler::li_optimized(Register rd, Operand j, LiFlags mode) {
DCHECK(!j.is_reg());
DCHECK(!MustUseReg(j.rmode()));
......@@ -1704,9 +1707,10 @@ void TurboAssembler::li_optimized(Register rd, Operand j, LiFlags mode) {
// 16 MSBs contain a signed 16-bit number.
daddiu(rd, zero_reg, j.immediate() & kImm16Mask);
dati(rd, ((j.immediate() >> 48) + bit31) & kImm16Mask);
} else if (base::bits::IsPowerOfTwo(j.immediate() + 1)) {
// 64-bit values which have their "n" MSBs set to one, and their
// "64-n" LSBs set to zero. "n" must meet the restrictions 0 < n < 64.
} else if (base::bits::IsPowerOfTwo(j.immediate() + 1) ||
j.immediate() == std::numeric_limits<int64_t>::max()) {
// 64-bit values which have their "n" LSBs set to one, and their
// "64-n" MSBs set to zero. "n" must meet the restrictions 0 < n < 64.
int shift_cnt = 64 - base::bits::CountTrailingZeros64(j.immediate() + 1);
daddiu(rd, zero_reg, -1);
if (shift_cnt < 32) {
......
......@@ -6329,11 +6329,10 @@ TEST(Dsubu) {
struct TestCaseDsubu tc[] = {
// imm, expected_res, num_instr
{0xffffffffffff8000, 0x8000, 2}, // min_int16
// The test case above generates ori + daddu instruction sequence.
// The test case above generates daddiu + dsubu instruction sequence.
// We can't have just daddiu because -min_int16 > max_int16 so use
// register. We can load min_int16 to at register with daddiu and then
// subtract at with dsubu, but now we use ori + daddu because -min_int16
// can be loaded using ori.
// register, but we can load min_int16 to at register with daddiu and then
// subtract at with dsubu.
{0x8000, 0xffffffffffff8000, 1}, // max_int16 + 1
// Generates daddiu
// max_int16 + 1 is not int16 but -(max_int16 + 1) is, just use daddiu.
......@@ -6363,13 +6362,13 @@ TEST(Dsubu) {
// r6 - Generates daddiu + dati + dsubu
{0x8000000000000000, 0x8000000000000000, 3}, // min_int64
// The test case above generates:
// r2 - daddiu + dsrl32 + dsubu instruction sequence,
// r2 - daddiu + dsll32 + dsubu instruction sequence,
// r6 - ori + dati + dsubu.
// The result of 0 - min_int64 eqauls max_int64 + 1, which wraps around to
// min_int64 again.
{0xffff0000ffffffff, 0x0000ffff00000001, 4},
// The test case above generates:
// r2 - ori + dsrl32 + ori + daddu instruction sequence,
// r2 - ori + dsll32 + ori + daddu instruction sequence,
// r6 - daddiu + dahi + dati + dsubu.
// For r2 loading imm would take more instructions than loading -imm so we
// can load -imm and add with daddu.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment