Bug 1027359 - Fix incorrect codegen in ma_mod_mask. (r=mjrosenb)

This commit is contained in:
Shu-yu Guo 2014-06-30 14:01:24 -07:00
parent 1fd6574e68
commit e5d1fe8bee
5 changed files with 22 additions and 13 deletions

View File

@ -826,9 +826,10 @@ CodeGeneratorARM::visitModMaskI(LModMaskI *ins)
{
Register src = ToRegister(ins->getOperand(0));
Register dest = ToRegister(ins->getDef(0));
Register tmp = ToRegister(ins->getTemp(0));
Register tmp1 = ToRegister(ins->getTemp(0));
Register tmp2 = ToRegister(ins->getTemp(1));
MMod *mir = ins->mir();
masm.ma_mod_mask(src, dest, tmp, ins->shift());
masm.ma_mod_mask(src, dest, tmp1, tmp2, ins->shift());
if (mir->canBeNegativeDividend()) {
if (!mir->isTruncated()) {
JS_ASSERT(mir->fallible());

View File

@ -263,18 +263,20 @@ class LModPowTwoI : public LInstructionHelper<1, 1, 0>
}
};
class LModMaskI : public LInstructionHelper<1, 1, 1>
class LModMaskI : public LInstructionHelper<1, 1, 2>
{
const int32_t shift_;
public:
LIR_HEADER(ModMaskI);
LModMaskI(const LAllocation &lhs, const LDefinition &temp1, int32_t shift)
LModMaskI(const LAllocation &lhs, const LDefinition &temp1, const LDefinition &temp2,
int32_t shift)
: shift_(shift)
{
setOperand(0, lhs);
setTemp(0, temp1);
setTemp(1, temp2);
}
int32_t shift() const {

View File

@ -321,7 +321,7 @@ LIRGeneratorARM::lowerModI(MMod *mod)
return false;
return define(lir, mod);
} else if (shift < 31 && (1 << (shift+1)) - 1 == rhs) {
LModMaskI *lir = new(alloc()) LModMaskI(useRegister(mod->lhs()), temp(LDefinition::GENERAL), shift+1);
LModMaskI *lir = new(alloc()) LModMaskI(useRegister(mod->lhs()), temp(), temp(), shift+1);
if (mod->fallible() && !assignSnapshot(lir, Bailout_DoubleOutput))
return false;
return define(lir, mod);

View File

@ -922,7 +922,8 @@ MacroAssemblerARM::ma_check_mul(Register src1, Imm32 imm, Register dest, Conditi
}
void
MacroAssemblerARM::ma_mod_mask(Register src, Register dest, Register hold, int32_t shift)
MacroAssemblerARM::ma_mod_mask(Register src, Register dest, Register hold, Register tmp,
int32_t shift)
{
// MATH:
// We wish to compute x % (1<<y) - 1 for a known constant, y.
@ -945,20 +946,24 @@ MacroAssemblerARM::ma_mod_mask(Register src, Register dest, Register hold, int32
// as holding the trial subtraction as a temp value
// dest is the accumulator (and holds the final result)
// move the whole value into the scratch register, setting the codition codes so
// we can muck with them later
as_mov(ScratchRegister, O2Reg(src), SetCond);
// move the whole value into tmp, setting the codition codes so we can
// muck with them later.
//
// Note that we cannot use ScratchRegister in place of tmp here, as ma_and
// below on certain architectures move the mask into ScratchRegister
// before performing the bitwise and.
as_mov(tmp, O2Reg(src), SetCond);
// Zero out the dest.
ma_mov(Imm32(0), dest);
// Set the hold appropriately.
ma_mov(Imm32(1), hold);
ma_mov(Imm32(-1), hold, NoSetCond, Signed);
ma_rsb(Imm32(0), ScratchRegister, SetCond, Signed);
ma_rsb(Imm32(0), tmp, SetCond, Signed);
// Begin the main loop.
bind(&head);
// Extract the bottom bits into lr.
ma_and(Imm32(mask), ScratchRegister, secondScratchReg_);
ma_and(Imm32(mask), tmp, secondScratchReg_);
// Add those bits to the accumulator.
ma_add(secondScratchReg_, dest, dest);
// Do a trial subtraction, this is the same operation as cmp, but we store the dest
@ -966,7 +971,7 @@ MacroAssemblerARM::ma_mod_mask(Register src, Register dest, Register hold, int32
// If (sum - C) > 0, store sum - C back into sum, thus performing a modulus.
ma_mov(secondScratchReg_, dest, NoSetCond, NotSigned);
// Get rid of the bits that we extracted before, and set the condition codes
as_mov(ScratchRegister, lsr(ScratchRegister, shift), SetCond);
as_mov(tmp, lsr(tmp, shift), SetCond);
// If the shift produced zero, finish, otherwise, continue in the loop.
ma_b(&head, NonZero);
// Check the hold to see if we need to negate the result. Hold can only be 1 or -1,

View File

@ -263,7 +263,8 @@ class MacroAssemblerARM : public Assembler
// fast mod, uses scratch registers, and thus needs to be in the assembler
// implicitly assumes that we can overwrite dest at the beginning of the sequence
void ma_mod_mask(Register src, Register dest, Register hold, int32_t shift);
void ma_mod_mask(Register src, Register dest, Register hold, Register tmp,
int32_t shift);
// mod, depends on integer divide instructions being supported
void ma_smod(Register num, Register div, Register dest);