[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:
ahaas 2016-03-14 10:22:27 -07:00 committed by Commit bot
parent 3088979d5c
commit 2ddfe43a44
7 changed files with 84 additions and 22 deletions

View File

@ -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));

View File

@ -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.

View File

@ -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;

View File

@ -47,7 +47,7 @@ namespace compiler {
V(ArmRbit) \
V(ArmUxtah) \
V(ArmAddPair) \
V(ArmPairLsl) \
V(ArmLslPair) \
V(ArmVcmpF32) \
V(ArmVaddF32) \
V(ArmVsubF32) \

View File

@ -49,7 +49,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArmUxtah:
case kArmRbit:
case kArmAddPair:
case kArmPairLsl:
case kArmLslPair:
case kArmVcmpF32:
case kArmVaddF32:
case kArmVsubF32:

View File

@ -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(); }

View File

@ -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) {