Commit 2ddfe43a authored by ahaas's avatar ahaas Committed by Commit bot

[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}
parent 3088979d
......@@ -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) {
......
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