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)
|
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)
|
if (imm == 1)
|
||||||
m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
|
m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
|
||||||
else {
|
else {
|
||||||
@ -983,6 +985,8 @@ public:
|
|||||||
|
|
||||||
void shrl_CLr(RegisterID dst)
|
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);
|
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
|
// Shift operation, taking two 32-bit integers as inputs and returning
|
||||||
// a 32-bit integer result as an output.
|
// a 32-bit integer result as an output.
|
||||||
class LShiftI : public LInstructionHelper<1, 2, 0>
|
class LShiftI : public LBinaryMath<0>
|
||||||
{
|
{
|
||||||
JSOp op_;
|
JSOp op_;
|
||||||
|
|
||||||
|
@ -680,67 +680,66 @@ CodeGeneratorARM::visitBitOpI(LBitOpI *ins)
|
|||||||
bool
|
bool
|
||||||
CodeGeneratorARM::visitShiftI(LShiftI *ins)
|
CodeGeneratorARM::visitShiftI(LShiftI *ins)
|
||||||
{
|
{
|
||||||
const LAllocation *lhs = ins->getOperand(0);
|
Register lhs = ToRegister(ins->lhs());
|
||||||
const LAllocation *rhs = ins->getOperand(1);
|
const LAllocation *rhs = ins->rhs();
|
||||||
const LDefinition *dest = ins->getDef(0);
|
Register dest = ToRegister(ins->output());
|
||||||
|
|
||||||
// The shift amounts should be AND'ed into the 0-31 range since arm shifts
|
if (rhs->isConstant()) {
|
||||||
// by the lower byte of the register (it will attempt to shift by 250 if you
|
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||||
// ask it to, and the result will probably not be what you want.
|
switch (ins->bitop()) {
|
||||||
if (!rhs->isConstant()) {
|
case JSOP_LSH:
|
||||||
masm.ma_and(Imm32(0x1f), ToRegister(rhs), ToRegister(dest));
|
if (shift)
|
||||||
rhs = dest->output();
|
masm.ma_lsl(Imm32(shift), lhs, dest);
|
||||||
|
else
|
||||||
|
masm.ma_mov(lhs, dest);
|
||||||
|
break;
|
||||||
|
case JSOP_RSH:
|
||||||
|
if (shift)
|
||||||
|
masm.ma_asr(Imm32(shift), lhs, dest);
|
||||||
|
else
|
||||||
|
masm.ma_mov(lhs, dest);
|
||||||
|
break;
|
||||||
|
case JSOP_URSH:
|
||||||
|
if (shift) {
|
||||||
|
masm.ma_lsr(Imm32(shift), lhs, dest);
|
||||||
|
} else {
|
||||||
|
// 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()) {
|
switch (ins->bitop()) {
|
||||||
case JSOP_LSH:
|
case JSOP_LSH:
|
||||||
if (rhs->isConstant()) {
|
masm.ma_lsl(dest, lhs, dest);
|
||||||
masm.ma_lsl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
|
|
||||||
} else {
|
|
||||||
masm.ma_lsl(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JSOP_RSH:
|
case JSOP_RSH:
|
||||||
if (rhs->isConstant()) {
|
masm.ma_asr(dest, lhs, dest);
|
||||||
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));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JSOP_URSH: {
|
case JSOP_URSH:
|
||||||
MUrsh *ursh = ins->mir()->toUrsh();
|
masm.ma_lsr(dest, lhs, dest);
|
||||||
if (rhs->isConstant()) {
|
if (ins->mir()->toUrsh()->canOverflow()) {
|
||||||
if ((ToInt32(rhs) & 0x1f) != 0) {
|
// x >>> 0 can overflow.
|
||||||
masm.ma_lsr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
|
masm.ma_cmp(dest, Imm32(0));
|
||||||
} else {
|
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
|
||||||
masm.ma_mov(ToRegister(lhs), ToRegister(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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
JS_NOT_REACHED("unexpected shift opcode");
|
JS_NOT_REACHED("Unexpected shift op");
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -756,12 +755,13 @@ CodeGeneratorARM::visitUrshD(LUrshD *ins)
|
|||||||
FloatRegister out = ToFloatRegister(ins->output());
|
FloatRegister out = ToFloatRegister(ins->output());
|
||||||
|
|
||||||
if (rhs->isConstant()) {
|
if (rhs->isConstant()) {
|
||||||
if ((ToInt32(rhs) & 0x1f) != 0)
|
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||||
masm.ma_lsr(Imm32(ToInt32(rhs) & 0x1F), lhs, temp);
|
if (shift)
|
||||||
|
masm.ma_lsr(Imm32(shift), lhs, temp);
|
||||||
else
|
else
|
||||||
masm.ma_mov(lhs, temp);
|
masm.ma_mov(lhs, temp);
|
||||||
} else {
|
} else {
|
||||||
masm.ma_and(Imm32(0x1f), ToRegister(rhs), temp);
|
masm.ma_and(Imm32(0x1F), ToRegister(rhs), temp);
|
||||||
masm.ma_lsr(temp, lhs, 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(0, useRegister(lhs));
|
||||||
ins->setOperand(1, useRegisterOrConstant(rhs));
|
ins->setOperand(1, useRegisterOrConstant(rhs));
|
||||||
return define(ins, mir,
|
return define(ins, mir);
|
||||||
LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -808,45 +808,54 @@ CodeGeneratorX86Shared::visitBitOpI(LBitOpI *ins)
|
|||||||
bool
|
bool
|
||||||
CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
|
CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
|
||||||
{
|
{
|
||||||
const LAllocation *lhs = ins->getOperand(0);
|
Register lhs = ToRegister(ins->lhs());
|
||||||
const LAllocation *rhs = ins->getOperand(1);
|
const LAllocation *rhs = ins->rhs();
|
||||||
|
|
||||||
|
if (rhs->isConstant()) {
|
||||||
|
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||||
switch (ins->bitop()) {
|
switch (ins->bitop()) {
|
||||||
case JSOP_LSH:
|
case JSOP_LSH:
|
||||||
if (rhs->isConstant())
|
if (shift)
|
||||||
masm.shll(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs));
|
masm.shll(Imm32(shift), lhs);
|
||||||
else
|
|
||||||
masm.shll_cl(ToRegister(lhs));
|
|
||||||
break;
|
break;
|
||||||
case JSOP_RSH:
|
case JSOP_RSH:
|
||||||
if (rhs->isConstant())
|
if (shift)
|
||||||
masm.sarl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs));
|
masm.sarl(Imm32(shift), lhs);
|
||||||
else
|
|
||||||
masm.sarl_cl(ToRegister(lhs));
|
|
||||||
break;
|
break;
|
||||||
case JSOP_URSH: {
|
case JSOP_URSH:
|
||||||
MUrsh *ursh = ins->mir()->toUrsh();
|
if (shift) {
|
||||||
if (rhs->isConstant())
|
masm.shrl(Imm32(shift), lhs);
|
||||||
masm.shrl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs));
|
} else if (ins->mir()->toUrsh()->canOverflow()) {
|
||||||
else
|
// x >>> 0 can overflow.
|
||||||
masm.shrl_cl(ToRegister(lhs));
|
masm.testl(lhs, lhs);
|
||||||
|
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
|
||||||
// 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()))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
JS_NOT_REACHED("unexpected shift opcode");
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -862,7 +871,9 @@ CodeGeneratorX86Shared::visitUrshD(LUrshD *ins)
|
|||||||
FloatRegister out = ToFloatRegister(ins->output());
|
FloatRegister out = ToFloatRegister(ins->output());
|
||||||
|
|
||||||
if (rhs->isConstant()) {
|
if (rhs->isConstant()) {
|
||||||
masm.shrl(Imm32(ToInt32(rhs) & 0x1F), lhs);
|
int32_t shift = ToInt32(rhs) & 0x1F;
|
||||||
|
if (shift)
|
||||||
|
masm.shrl(Imm32(shift), lhs);
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(ToRegister(rhs) == ecx);
|
JS_ASSERT(ToRegister(rhs) == ecx);
|
||||||
masm.shrl_cl(lhs);
|
masm.shrl_cl(lhs);
|
||||||
|
Loading…
Reference in New Issue
Block a user