mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 787906 - Don't emit a shift instruction for x >>> 0. r=dvander
This commit is contained in:
parent
22abc28b96
commit
84b7b334fb
@ -973,6 +973,8 @@ public:
|
||||
|
||||
void shrl_i8r(int imm, RegisterID dst)
|
||||
{
|
||||
js::JaegerSpew(js::JSpew_Insns,
|
||||
IPFX "shrl $%d, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
|
||||
if (imm == 1)
|
||||
m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
|
||||
else {
|
||||
@ -983,6 +985,8 @@ public:
|
||||
|
||||
void shrl_CLr(RegisterID dst)
|
||||
{
|
||||
js::JaegerSpew(js::JSpew_Insns,
|
||||
IPFX "shrl %%cl, %s\n", MAYBE_PAD, nameIReg(4, dst));
|
||||
m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst);
|
||||
}
|
||||
|
||||
|
@ -1198,7 +1198,7 @@ class LBitOpV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
|
||||
|
||||
// Shift operation, taking two 32-bit integers as inputs and returning
|
||||
// a 32-bit integer result as an output.
|
||||
class LShiftI : public LInstructionHelper<1, 2, 0>
|
||||
class LShiftI : public LBinaryMath<0>
|
||||
{
|
||||
JSOp op_;
|
||||
|
||||
|
@ -680,67 +680,66 @@ CodeGeneratorARM::visitBitOpI(LBitOpI *ins)
|
||||
bool
|
||||
CodeGeneratorARM::visitShiftI(LShiftI *ins)
|
||||
{
|
||||
const LAllocation *lhs = ins->getOperand(0);
|
||||
const LAllocation *rhs = ins->getOperand(1);
|
||||
const LDefinition *dest = ins->getDef(0);
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
const LAllocation *rhs = ins->rhs();
|
||||
Register dest = ToRegister(ins->output());
|
||||
|
||||
// The shift amounts should be AND'ed into the 0-31 range since arm shifts
|
||||
// by the lower byte of the register (it will attempt to shift by 250 if you
|
||||
// ask it to, and the result will probably not be what you want.
|
||||
if (!rhs->isConstant()) {
|
||||
masm.ma_and(Imm32(0x1f), ToRegister(rhs), ToRegister(dest));
|
||||
rhs = dest->output();
|
||||
}
|
||||
|
||||
switch (ins->bitop()) {
|
||||
case JSOP_LSH:
|
||||
if (rhs->isConstant()) {
|
||||
masm.ma_lsl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
|
||||
} else {
|
||||
masm.ma_lsl(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
|
||||
}
|
||||
if (rhs->isConstant()) {
|
||||
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||
switch (ins->bitop()) {
|
||||
case JSOP_LSH:
|
||||
if (shift)
|
||||
masm.ma_lsl(Imm32(shift), lhs, dest);
|
||||
else
|
||||
masm.ma_mov(lhs, dest);
|
||||
break;
|
||||
case JSOP_RSH:
|
||||
if (rhs->isConstant()) {
|
||||
if ((ToInt32(rhs) & 0x1f) != 0) {
|
||||
masm.ma_asr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
|
||||
} else {
|
||||
masm.ma_mov(ToRegister(lhs), ToRegister(dest));
|
||||
}
|
||||
} else {
|
||||
masm.ma_asr(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
|
||||
}
|
||||
case JSOP_RSH:
|
||||
if (shift)
|
||||
masm.ma_asr(Imm32(shift), lhs, dest);
|
||||
else
|
||||
masm.ma_mov(lhs, dest);
|
||||
break;
|
||||
case JSOP_URSH: {
|
||||
MUrsh *ursh = ins->mir()->toUrsh();
|
||||
if (rhs->isConstant()) {
|
||||
if ((ToInt32(rhs) & 0x1f) != 0) {
|
||||
masm.ma_lsr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
|
||||
} else {
|
||||
masm.ma_mov(ToRegister(lhs), ToRegister(dest));
|
||||
}
|
||||
case JSOP_URSH:
|
||||
if (shift) {
|
||||
masm.ma_lsr(Imm32(shift), lhs, dest);
|
||||
} else {
|
||||
masm.ma_lsr(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
|
||||
}
|
||||
|
||||
// Note: this is an unsigned operation.
|
||||
// We don't have a UINT32 type, so we will emulate this with INT32
|
||||
// The bit representation of an integer from ToInt32 and ToUint32 are the same.
|
||||
// So the inputs are ok.
|
||||
// But we need to bring the output back again from UINT32 to INT32.
|
||||
// Both representation overlap each other in the positive numbers. (in INT32)
|
||||
// So there is only a problem when solution (in INT32) is negative.
|
||||
if (ursh->canOverflow()) {
|
||||
masm.ma_cmp(ToRegister(dest), Imm32(0));
|
||||
if (!bailoutIf(Assembler::LessThan, ins->snapshot())) {
|
||||
return false;
|
||||
// x >>> 0 can overflow.
|
||||
masm.ma_mov(lhs, dest);
|
||||
if (ins->mir()->toUrsh()->canOverflow()) {
|
||||
masm.ma_cmp(dest, Imm32(0));
|
||||
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Unexpected shift op");
|
||||
}
|
||||
} else {
|
||||
// The shift amounts should be AND'ed into the 0-31 range since arm
|
||||
// shifts by the lower byte of the register (it will attempt to shift
|
||||
// by 250 if you ask it to).
|
||||
masm.ma_and(Imm32(0x1F), ToRegister(rhs), dest);
|
||||
|
||||
switch (ins->bitop()) {
|
||||
case JSOP_LSH:
|
||||
masm.ma_lsl(dest, lhs, dest);
|
||||
break;
|
||||
case JSOP_RSH:
|
||||
masm.ma_asr(dest, lhs, dest);
|
||||
break;
|
||||
case JSOP_URSH:
|
||||
masm.ma_lsr(dest, lhs, dest);
|
||||
if (ins->mir()->toUrsh()->canOverflow()) {
|
||||
// x >>> 0 can overflow.
|
||||
masm.ma_cmp(dest, Imm32(0));
|
||||
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Unexpected shift op");
|
||||
}
|
||||
default:
|
||||
JS_NOT_REACHED("unexpected shift opcode");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -756,12 +755,13 @@ CodeGeneratorARM::visitUrshD(LUrshD *ins)
|
||||
FloatRegister out = ToFloatRegister(ins->output());
|
||||
|
||||
if (rhs->isConstant()) {
|
||||
if ((ToInt32(rhs) & 0x1f) != 0)
|
||||
masm.ma_lsr(Imm32(ToInt32(rhs) & 0x1F), lhs, temp);
|
||||
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||
if (shift)
|
||||
masm.ma_lsr(Imm32(shift), lhs, temp);
|
||||
else
|
||||
masm.ma_mov(lhs, temp);
|
||||
} else {
|
||||
masm.ma_and(Imm32(0x1f), ToRegister(rhs), temp);
|
||||
masm.ma_and(Imm32(0x1F), ToRegister(rhs), temp);
|
||||
masm.ma_lsr(temp, lhs, temp);
|
||||
}
|
||||
|
||||
|
@ -217,8 +217,7 @@ LIRGeneratorARM::lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mi
|
||||
|
||||
ins->setOperand(0, useRegister(lhs));
|
||||
ins->setOperand(1, useRegisterOrConstant(rhs));
|
||||
return define(ins, mir,
|
||||
LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
|
||||
return define(ins, mir);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -808,45 +808,54 @@ CodeGeneratorX86Shared::visitBitOpI(LBitOpI *ins)
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
|
||||
{
|
||||
const LAllocation *lhs = ins->getOperand(0);
|
||||
const LAllocation *rhs = ins->getOperand(1);
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
const LAllocation *rhs = ins->rhs();
|
||||
|
||||
switch (ins->bitop()) {
|
||||
case JSOP_LSH:
|
||||
if (rhs->isConstant())
|
||||
masm.shll(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs));
|
||||
else
|
||||
masm.shll_cl(ToRegister(lhs));
|
||||
if (rhs->isConstant()) {
|
||||
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||
switch (ins->bitop()) {
|
||||
case JSOP_LSH:
|
||||
if (shift)
|
||||
masm.shll(Imm32(shift), lhs);
|
||||
break;
|
||||
case JSOP_RSH:
|
||||
if (rhs->isConstant())
|
||||
masm.sarl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs));
|
||||
else
|
||||
masm.sarl_cl(ToRegister(lhs));
|
||||
case JSOP_RSH:
|
||||
if (shift)
|
||||
masm.sarl(Imm32(shift), lhs);
|
||||
break;
|
||||
case JSOP_URSH: {
|
||||
MUrsh *ursh = ins->mir()->toUrsh();
|
||||
if (rhs->isConstant())
|
||||
masm.shrl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs));
|
||||
else
|
||||
masm.shrl_cl(ToRegister(lhs));
|
||||
|
||||
// Note: this is an unsigned operation.
|
||||
// We don't have a UINT32 type, so we will emulate this with INT32
|
||||
// The bit representation of an integer from ToInt32 and ToUint32 are the same.
|
||||
// So the inputs are ok.
|
||||
// But we need to bring the output back again from UINT32 to INT32.
|
||||
// Both representation overlap each other in the positive numbers. (in INT32)
|
||||
// So there is only a problem when solution (in INT32) is negative.
|
||||
if (ursh->canOverflow()) {
|
||||
masm.cmpl(ToOperand(lhs), Imm32(0));
|
||||
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
|
||||
case JSOP_URSH:
|
||||
if (shift) {
|
||||
masm.shrl(Imm32(shift), lhs);
|
||||
} else if (ins->mir()->toUrsh()->canOverflow()) {
|
||||
// x >>> 0 can overflow.
|
||||
masm.testl(lhs, lhs);
|
||||
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Unexpected shift op");
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(ToRegister(rhs) == ecx);
|
||||
switch (ins->bitop()) {
|
||||
case JSOP_LSH:
|
||||
masm.shll_cl(lhs);
|
||||
break;
|
||||
case JSOP_RSH:
|
||||
masm.sarl_cl(lhs);
|
||||
break;
|
||||
case JSOP_URSH:
|
||||
masm.shrl_cl(lhs);
|
||||
if (ins->mir()->toUrsh()->canOverflow()) {
|
||||
// x >>> 0 can overflow.
|
||||
masm.testl(lhs, lhs);
|
||||
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Unexpected shift op");
|
||||
}
|
||||
default:
|
||||
JS_NOT_REACHED("unexpected shift opcode");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -862,7 +871,9 @@ CodeGeneratorX86Shared::visitUrshD(LUrshD *ins)
|
||||
FloatRegister out = ToFloatRegister(ins->output());
|
||||
|
||||
if (rhs->isConstant()) {
|
||||
masm.shrl(Imm32(ToInt32(rhs) & 0x1F), lhs);
|
||||
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||
if (shift)
|
||||
masm.shrl(Imm32(shift), lhs);
|
||||
} else {
|
||||
JS_ASSERT(ToRegister(rhs) == ecx);
|
||||
masm.shrl_cl(lhs);
|
||||
|
Loading…
Reference in New Issue
Block a user