[loong64][mips64] Fix a Int64Mul error in instruction selection.

The second parameter of Int64Mul may be a 64-bit immediate value,
treating it as a 32-bit value will lose the upper 32 bits.
Besides, add a test for this error.

Bug: v8:12373
Change-Id: I92e95f7906051c91f9076730e5490b0956416d68
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3272195
Auto-Submit: Liu yu <liuyu@loongson.cn>
Commit-Queue: Liu yu <liuyu@loongson.cn>
Reviewed-by: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77833}
This commit is contained in:
Liu Yu 2021-11-10 14:00:34 +08:00 committed by V8 LUCI CQ
parent 27f0d28f65
commit 9a900169f8
5 changed files with 24 additions and 10 deletions

View File

@ -865,7 +865,7 @@ void TurboAssembler::Alsl_w(Register rd, Register rj, Register rk, uint8_t sa,
void TurboAssembler::Alsl_d(Register rd, Register rj, Register rk, uint8_t sa,
Register scratch) {
DCHECK(sa >= 1 && sa <= 31);
DCHECK(sa >= 1 && sa <= 63);
if (sa <= 4) {
alsl_d(rd, rj, rk, sa);
} else {

View File

@ -1097,13 +1097,16 @@ void TurboAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
void TurboAssembler::Dlsa(Register rd, Register rt, Register rs, uint8_t sa,
Register scratch) {
DCHECK(sa >= 1 && sa <= 31);
DCHECK(sa >= 1 && sa <= 63);
if (kArchVariant == kMips64r6 && sa <= 4) {
dlsa(rd, rt, rs, sa - 1);
} else {
Register tmp = rd == rt ? scratch : rd;
DCHECK(tmp != rt);
dsll(tmp, rs, sa);
if (sa <= 31)
dsll(tmp, rs, sa);
else
dsll32(tmp, rs, sa - 32);
Daddu(rd, rt, tmp);
}
}

View File

@ -1086,15 +1086,14 @@ void InstructionSelector::VisitInt64Mul(Node* node) {
Loong64OperandGenerator g(this);
Int64BinopMatcher m(node);
if (m.right().HasResolvedValue() && m.right().ResolvedValue() > 0) {
uint32_t value = static_cast<uint32_t>(m.right().ResolvedValue());
uint64_t value = static_cast<uint64_t>(m.right().ResolvedValue());
if (base::bits::IsPowerOfTwo(value)) {
Emit(kLoong64Sll_d | AddressingModeField::encode(kMode_None),
g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.TempImmediate(base::bits::WhichPowerOfTwo(value)));
return;
}
if (base::bits::IsPowerOfTwo(value - 1) && value - 1 > 0 &&
value - 1 <= 31) {
if (base::bits::IsPowerOfTwo(value - 1) && value - 1 > 0) {
// Alsl_d macro will handle the shifting value out of bound cases.
Emit(kLoong64Alsl_d, g.DefineAsRegister(node),
g.UseRegister(m.left().node()), g.UseRegister(m.left().node()),

View File

@ -1125,17 +1125,15 @@ void InstructionSelector::VisitUint32MulHigh(Node* node) {
void InstructionSelector::VisitInt64Mul(Node* node) {
Mips64OperandGenerator g(this);
Int64BinopMatcher m(node);
// TODO(dusmil): Add optimization for shifts larger than 32.
if (m.right().HasResolvedValue() && m.right().ResolvedValue() > 0) {
uint32_t value = static_cast<uint32_t>(m.right().ResolvedValue());
uint64_t value = static_cast<uint64_t>(m.right().ResolvedValue());
if (base::bits::IsPowerOfTwo(value)) {
Emit(kMips64Dshl | AddressingModeField::encode(kMode_None),
g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.TempImmediate(base::bits::WhichPowerOfTwo(value)));
return;
}
if (base::bits::IsPowerOfTwo(value - 1) && kArchVariant == kMips64r6 &&
value - 1 > 0 && value - 1 <= 31) {
if (base::bits::IsPowerOfTwo(value - 1) && value - 1 > 0) {
// Dlsa macro will handle the shifting value out of bound cases.
Emit(kMips64Dlsa, g.DefineAsRegister(node),
g.UseRegister(m.left().node()), g.UseRegister(m.left().node()),

View File

@ -7308,6 +7308,20 @@ TEST(Regression12330) {
m.Return(ovf);
m.GenerateCode();
}
TEST(Regression12373) {
FOR_INT64_INPUTS(i) {
RawMachineAssemblerTester<int64_t> m(MachineType::Int64(),
MachineType::Int64());
RawMachineAssemblerTester<int64_t> n(MachineType::Int64());
Node* mul_rr = m.Int64Mul(m.Parameter(0), m.Parameter(1));
Node* mul_ri = n.Int64Mul(n.Parameter(0), n.Int64Constant(i));
m.Return(mul_rr);
n.Return(mul_ri);
FOR_INT64_INPUTS(j) { CHECK_EQ(m.Call(j, i), n.Call(j)); }
}
}
#endif // V8_TARGET_ARCH_64_BIT
} // namespace compiler