[wasm] Fixed register allocation for Word32PairShl on arm.
The previous register allocation allowed invalid register aliasing in cases where in the TF graph the node was used for multiple inputs of the Word32PairShl node. Additionally I renamed PairLsl to LslPair in the code generation for consistency. R=titzer@chromium.org, v8-arm-ports@googlegroups.com Review URL: https://codereview.chromium.org/1776393004 Cr-Commit-Position: refs/heads/master@{#34755}
This commit is contained in:
parent
3088979d5c
commit
2ddfe43a44
@ -1101,15 +1101,16 @@ void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) {
|
||||
vmov(dst, VmovIndexLo, src);
|
||||
}
|
||||
}
|
||||
void MacroAssembler::PairLsl(Register dst_low, Register dst_high,
|
||||
void MacroAssembler::LslPair(Register dst_low, Register dst_high,
|
||||
Register src_low, Register src_high,
|
||||
Register scratch, Register shift) {
|
||||
DCHECK(!AreAliased(dst_low, src_high, shift));
|
||||
DCHECK(!AreAliased(dst_high, src_low, shift));
|
||||
DCHECK(!AreAliased(dst_high, src_low));
|
||||
DCHECK(!AreAliased(dst_high, shift));
|
||||
|
||||
Label less_than_32;
|
||||
Label done;
|
||||
cmp_raw_immediate(shift, 32);
|
||||
b(lt, &less_than_32);
|
||||
rsb(scratch, shift, Operand(32), SetCC);
|
||||
b(gt, &less_than_32);
|
||||
// If shift >= 32
|
||||
and_(scratch, shift, Operand(0x1f));
|
||||
lsl(dst_high, src_low, Operand(scratch));
|
||||
@ -1117,27 +1118,28 @@ void MacroAssembler::PairLsl(Register dst_low, Register dst_high,
|
||||
jmp(&done);
|
||||
bind(&less_than_32);
|
||||
// If shift < 32
|
||||
rsb(scratch, shift, Operand(32));
|
||||
lsl(dst_high, src_high, Operand(shift));
|
||||
orr(dst_high, dst_high, Operand(src_low, LSR, scratch));
|
||||
lsl(dst_low, src_low, Operand(shift));
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::PairLsl(Register dst_low, Register dst_high,
|
||||
void MacroAssembler::LslPair(Register dst_low, Register dst_high,
|
||||
Register src_low, Register src_high,
|
||||
uint32_t shift) {
|
||||
DCHECK(!AreAliased(dst_low, src_high));
|
||||
DCHECK(!AreAliased(dst_high, src_low));
|
||||
Label less_than_32;
|
||||
Label done;
|
||||
if (shift >= 32) {
|
||||
if (shift == 0) {
|
||||
Move(dst_high, src_high);
|
||||
Move(dst_low, src_low);
|
||||
} else if (shift == 32) {
|
||||
Move(dst_high, src_low);
|
||||
Move(dst_low, Operand(0));
|
||||
} else if (shift >= 32) {
|
||||
shift &= 0x1f;
|
||||
lsl(dst_high, src_low, Operand(shift));
|
||||
mov(dst_low, Operand(0));
|
||||
} else if (shift == 0) {
|
||||
Move(dst_low, src_low);
|
||||
Move(dst_high, src_high);
|
||||
} else {
|
||||
lsl(dst_high, src_high, Operand(shift));
|
||||
orr(dst_high, dst_high, Operand(src_low, LSR, 32 - shift));
|
||||
|
@ -549,9 +549,9 @@ class MacroAssembler: public Assembler {
|
||||
void VmovLow(Register dst, DwVfpRegister src);
|
||||
void VmovLow(DwVfpRegister dst, Register src);
|
||||
|
||||
void PairLsl(Register dst_low, Register dst_high, Register src_low,
|
||||
void LslPair(Register dst_low, Register dst_high, Register src_low,
|
||||
Register src_high, Register scratch, Register shift);
|
||||
void PairLsl(Register dst_low, Register dst_high, Register src_low,
|
||||
void LslPair(Register dst_low, Register dst_high, Register src_low,
|
||||
Register src_high, uint32_t shift);
|
||||
|
||||
// Loads the number from object into dst register.
|
||||
|
@ -798,12 +798,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
Operand(i.InputRegister(3)));
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
case kArmPairLsl:
|
||||
case kArmLslPair:
|
||||
if (instr->InputAt(2)->IsImmediate()) {
|
||||
__ PairLsl(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
|
||||
__ LslPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
|
||||
i.InputRegister(1), i.InputInt32(2));
|
||||
} else {
|
||||
__ PairLsl(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
|
||||
__ LslPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
|
||||
i.InputRegister(1), kScratchReg, i.InputRegister(2));
|
||||
}
|
||||
break;
|
||||
|
@ -47,7 +47,7 @@ namespace compiler {
|
||||
V(ArmRbit) \
|
||||
V(ArmUxtah) \
|
||||
V(ArmAddPair) \
|
||||
V(ArmPairLsl) \
|
||||
V(ArmLslPair) \
|
||||
V(ArmVcmpF32) \
|
||||
V(ArmVaddF32) \
|
||||
V(ArmVsubF32) \
|
||||
|
@ -49,7 +49,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArmUxtah:
|
||||
case kArmRbit:
|
||||
case kArmAddPair:
|
||||
case kArmPairLsl:
|
||||
case kArmLslPair:
|
||||
case kArmVcmpF32:
|
||||
case kArmVaddF32:
|
||||
case kArmVsubF32:
|
||||
|
@ -785,6 +785,8 @@ void InstructionSelector::VisitInt32PairAdd(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitWord32PairShl(Node* node) {
|
||||
ArmOperandGenerator g(this);
|
||||
// We use g.UseUniqueRegister here for InputAt(0) to guarantee that there is
|
||||
// no register aliasing with output registers.
|
||||
Int32Matcher m(node->InputAt(2));
|
||||
InstructionOperand shift_operand;
|
||||
if (m.HasValue()) {
|
||||
@ -793,15 +795,15 @@ void InstructionSelector::VisitWord32PairShl(Node* node) {
|
||||
shift_operand = g.UseUniqueRegister(m.node());
|
||||
}
|
||||
|
||||
InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)),
|
||||
InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
|
||||
g.UseRegister(node->InputAt(1)),
|
||||
shift_operand};
|
||||
|
||||
InstructionOperand outputs[] = {
|
||||
g.DefineSameAsFirst(node),
|
||||
g.DefineAsRegister(node),
|
||||
g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
|
||||
|
||||
Emit(kArmPairLsl, 2, outputs, 3, inputs);
|
||||
Emit(kArmLslPair, 2, outputs, 3, inputs);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
|
||||
|
@ -4264,6 +4264,64 @@ TEST(RunInt32PairAddWithSharedInput) {
|
||||
TestInt32PairAddWithSharedInput(0, 0, 0, 1);
|
||||
TestInt32PairAddWithSharedInput(1, 1, 0, 0);
|
||||
}
|
||||
|
||||
TEST(RunWord32PairShl) {
|
||||
BufferedRawMachineAssemblerTester<int32_t> m(
|
||||
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
||||
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
|
||||
Node* PairAdd =
|
||||
m.Word32PairShl(m.Parameter(0), m.Parameter(1), m.Parameter(2));
|
||||
|
||||
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
||||
m.Projection(0, PairAdd));
|
||||
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
||||
m.Projection(1, PairAdd));
|
||||
m.Return(m.Int32Constant(74));
|
||||
|
||||
FOR_INT64_INPUTS(i) {
|
||||
for (uint32_t j = 0; j < 64; j++) {
|
||||
m.Call(static_cast<uint32_t>(*i & 0xffffffff),
|
||||
static_cast<uint32_t>(*i >> 32), j);
|
||||
CHECK_EQ(*i << j, ToInt64(low, high));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestWord32PairShlWithSharedInput(int a, int b) {
|
||||
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
|
||||
MachineType::Uint32());
|
||||
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
|
||||
Node* PairAdd =
|
||||
m.Word32PairShl(m.Parameter(a), m.Parameter(b), m.Parameter(1));
|
||||
|
||||
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
||||
m.Projection(0, PairAdd));
|
||||
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
||||
m.Projection(1, PairAdd));
|
||||
m.Return(m.Int32Constant(74));
|
||||
|
||||
FOR_UINT32_INPUTS(i) {
|
||||
for (uint32_t j = 0; j < 64; j++) {
|
||||
m.Call(*i, j);
|
||||
uint32_t inputs[] = {*i, j};
|
||||
CHECK_EQ(ToInt64(inputs[a], inputs[b]) << j, ToInt64(low, high));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RunWord32PairShlWithSharedInput) {
|
||||
TestWord32PairShlWithSharedInput(0, 0);
|
||||
TestWord32PairShlWithSharedInput(0, 1);
|
||||
TestWord32PairShlWithSharedInput(1, 0);
|
||||
TestWord32PairShlWithSharedInput(1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(RunDeadChangeFloat64ToInt32) {
|
||||
|
Loading…
Reference in New Issue
Block a user