Add rotate-right instruction to hydrogen and use it instead of bitwise operations
of the form ((x >>> i) | (x << (32 - i))). This CL is based on https://chromiumcodereview.appspot.com/10984057/ by Jay Conrod <dconrod@codeaurora.org>. R=danno@chromium.org,mstarzinger@chromium.org,dconrod@codeaurora.org Review URL: https://chromiumcodereview.appspot.com/11033005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12855 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
b77e629f1a
commit
f106c9c9f7
@ -177,6 +177,7 @@ const char* LArithmeticT::Mnemonic() const {
|
||||
case Token::BIT_AND: return "bit-and-t";
|
||||
case Token::BIT_OR: return "bit-or-t";
|
||||
case Token::BIT_XOR: return "bit-xor-t";
|
||||
case Token::ROR: return "ror-t";
|
||||
case Token::SHL: return "shl-t";
|
||||
case Token::SAR: return "sar-t";
|
||||
case Token::SHR: return "shr-t";
|
||||
@ -1099,6 +1100,11 @@ LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoRor(HRor* instr) {
|
||||
return DoShift(Token::ROR, instr);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoShr(HShr* instr) {
|
||||
return DoShift(Token::SHR, instr);
|
||||
}
|
||||
|
@ -1489,6 +1489,9 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||
// Mask the right_op operand.
|
||||
__ and_(scratch, ToRegister(right_op), Operand(0x1F));
|
||||
switch (instr->op()) {
|
||||
case Token::ROR:
|
||||
__ mov(result, Operand(left, ROR, scratch));
|
||||
break;
|
||||
case Token::SAR:
|
||||
__ mov(result, Operand(left, ASR, scratch));
|
||||
break;
|
||||
@ -1512,6 +1515,13 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||
int value = ToInteger32(LConstantOperand::cast(right_op));
|
||||
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
|
||||
switch (instr->op()) {
|
||||
case Token::ROR:
|
||||
if (shift_count != 0) {
|
||||
__ mov(result, Operand(left, ROR, shift_count));
|
||||
} else {
|
||||
__ Move(result, left);
|
||||
}
|
||||
break;
|
||||
case Token::SAR:
|
||||
if (shift_count != 0) {
|
||||
__ mov(result, Operand(left, ASR, shift_count));
|
||||
|
@ -1459,7 +1459,14 @@ int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
|
||||
}
|
||||
|
||||
case ROR: {
|
||||
UNIMPLEMENTED();
|
||||
if (shift_amount == 0) {
|
||||
*carry_out = c_flag_;
|
||||
} else {
|
||||
uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
|
||||
uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
|
||||
result = right | left;
|
||||
*carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,7 @@ class LChunkBuilder;
|
||||
V(Random) \
|
||||
V(RegExpLiteral) \
|
||||
V(Return) \
|
||||
V(Ror) \
|
||||
V(Sar) \
|
||||
V(Shl) \
|
||||
V(Shr) \
|
||||
@ -3729,6 +3730,25 @@ class HSar: public HBitwiseBinaryOperation {
|
||||
};
|
||||
|
||||
|
||||
class HRor: public HBitwiseBinaryOperation {
|
||||
public:
|
||||
HRor(HValue* context, HValue* left, HValue* right)
|
||||
: HBitwiseBinaryOperation(context, left, right) {
|
||||
ChangeRepresentation(Representation::Integer32());
|
||||
}
|
||||
|
||||
static HInstruction* NewHRor(Zone* zone,
|
||||
HValue* context,
|
||||
HValue* left,
|
||||
HValue* right);
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Ror)
|
||||
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) { return true; }
|
||||
};
|
||||
|
||||
|
||||
class HOsrEntry: public HTemplateInstruction<0> {
|
||||
public:
|
||||
explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
|
||||
|
@ -8226,6 +8226,61 @@ HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
|
||||
return new(zone()) HStringCharCodeAt(context, string, checked_index);
|
||||
}
|
||||
|
||||
// Checks if the given shift amounts have form: (sa) and (32 - sa).
|
||||
static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
|
||||
HValue* const32_minus_sa) {
|
||||
if (!const32_minus_sa->IsSub()) return false;
|
||||
HSub* sub = HSub::cast(const32_minus_sa);
|
||||
HValue* const32 = sub->left();
|
||||
if (!const32->IsConstant() ||
|
||||
HConstant::cast(const32)->Integer32Value() != 32) {
|
||||
return false;
|
||||
}
|
||||
return (sub->right() == sa);
|
||||
}
|
||||
|
||||
|
||||
// Checks if the left and the right are shift instructions with the oposite
|
||||
// directions that can be replaced by one rotate right instruction or not.
|
||||
// Returns the operand and the shift amount for the rotate instruction in the
|
||||
// former case.
|
||||
bool HGraphBuilder::MatchRotateRight(HValue* left,
|
||||
HValue* right,
|
||||
HValue** operand,
|
||||
HValue** shift_amount) {
|
||||
HShl* shl;
|
||||
HShr* shr;
|
||||
if (left->IsShl() && right->IsShr()) {
|
||||
shl = HShl::cast(left);
|
||||
shr = HShr::cast(right);
|
||||
} else if (left->IsShr() && right->IsShl()) {
|
||||
shl = HShl::cast(right);
|
||||
shr = HShr::cast(left);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
|
||||
!ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
|
||||
return false;
|
||||
}
|
||||
*operand= shr->left();
|
||||
*shift_amount = shr->right();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CanBeZero(HValue *right) {
|
||||
if (right->IsConstant()) {
|
||||
HConstant* right_const = HConstant::cast(right);
|
||||
if (right_const->HasInteger32Value() &&
|
||||
(right_const->Integer32Value() & 0x1f) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
|
||||
HValue* left,
|
||||
@ -8264,25 +8319,26 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
|
||||
break;
|
||||
case Token::BIT_XOR:
|
||||
case Token::BIT_AND:
|
||||
case Token::BIT_OR:
|
||||
instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
|
||||
break;
|
||||
case Token::BIT_OR: {
|
||||
HValue* operand, *shift_amount;
|
||||
if (info.IsInteger32() &&
|
||||
MatchRotateRight(left, right, &operand, &shift_amount)) {
|
||||
instr = new(zone()) HRor(context, operand, shift_amount);
|
||||
} else {
|
||||
instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Token::SAR:
|
||||
instr = HSar::NewHSar(zone(), context, left, right);
|
||||
break;
|
||||
case Token::SHR:
|
||||
instr = HShr::NewHShr(zone(), context, left, right);
|
||||
if (FLAG_opt_safe_uint32_operations && instr->IsShr()) {
|
||||
bool can_be_shift_by_zero = true;
|
||||
if (right->IsConstant()) {
|
||||
HConstant* right_const = HConstant::cast(right);
|
||||
if (right_const->HasInteger32Value() &&
|
||||
(right_const->Integer32Value() & 0x1f) != 0) {
|
||||
can_be_shift_by_zero = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_be_shift_by_zero) graph()->RecordUint32Instruction(instr);
|
||||
if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
|
||||
CanBeZero(right)) {
|
||||
graph()->RecordUint32Instruction(instr);
|
||||
}
|
||||
break;
|
||||
case Token::SHL:
|
||||
|
@ -270,6 +270,7 @@ class HGraph: public ZoneObject {
|
||||
void DehoistSimpleArrayIndexComputations();
|
||||
void DeadCodeElimination();
|
||||
void PropagateDeoptimizingMark();
|
||||
void EliminateUnusedInstructions();
|
||||
|
||||
// Returns false if there are phi-uses of the arguments-object
|
||||
// which are not supported by the optimizing compiler.
|
||||
@ -1220,6 +1221,11 @@ class HGraphBuilder: public AstVisitor {
|
||||
HValue* receiver,
|
||||
Handle<Map> receiver_map);
|
||||
|
||||
bool MatchRotateRight(HValue* left,
|
||||
HValue* right,
|
||||
HValue** operand,
|
||||
HValue** shift_amount);
|
||||
|
||||
Zone* zone() const { return zone_; }
|
||||
|
||||
// The translation state of the currently-being-translated function.
|
||||
|
@ -1064,6 +1064,25 @@ void Assembler::rcr(Register dst, uint8_t imm8) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::ror(Register dst, uint8_t imm8) {
|
||||
EnsureSpace ensure_space(this);
|
||||
ASSERT(is_uint5(imm8)); // illegal shift count
|
||||
if (imm8 == 1) {
|
||||
EMIT(0xD1);
|
||||
EMIT(0xC8 | dst.code());
|
||||
} else {
|
||||
EMIT(0xC1);
|
||||
EMIT(0xC8 | dst.code());
|
||||
EMIT(imm8);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::ror_cl(Register dst) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0xD3);
|
||||
EMIT(0xC8 | dst.code());
|
||||
}
|
||||
|
||||
|
||||
void Assembler::sar(Register dst, uint8_t imm8) {
|
||||
EnsureSpace ensure_space(this);
|
||||
|
@ -817,6 +817,8 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
void rcl(Register dst, uint8_t imm8);
|
||||
void rcr(Register dst, uint8_t imm8);
|
||||
void ror(Register dst, uint8_t imm8);
|
||||
void ror_cl(Register dst);
|
||||
|
||||
void sar(Register dst, uint8_t imm8);
|
||||
void sar_cl(Register dst);
|
||||
|
@ -1300,6 +1300,13 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||
ASSERT(ToRegister(right).is(ecx));
|
||||
|
||||
switch (instr->op()) {
|
||||
case Token::ROR:
|
||||
__ ror_cl(ToRegister(left));
|
||||
if (instr->can_deopt()) {
|
||||
__ test(ToRegister(left), Immediate(0x80000000));
|
||||
DeoptimizeIf(not_zero, instr->environment());
|
||||
}
|
||||
break;
|
||||
case Token::SAR:
|
||||
__ sar_cl(ToRegister(left));
|
||||
break;
|
||||
@ -1321,6 +1328,14 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||
int value = ToInteger32(LConstantOperand::cast(right));
|
||||
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
|
||||
switch (instr->op()) {
|
||||
case Token::ROR:
|
||||
if (shift_count == 0 && instr->can_deopt()) {
|
||||
__ test(ToRegister(left), Immediate(0x80000000));
|
||||
DeoptimizeIf(not_zero, instr->environment());
|
||||
} else {
|
||||
__ ror(ToRegister(left), shift_count);
|
||||
}
|
||||
break;
|
||||
case Token::SAR:
|
||||
if (shift_count != 0) {
|
||||
__ sar(ToRegister(left), shift_count);
|
||||
|
@ -179,6 +179,7 @@ const char* LArithmeticT::Mnemonic() const {
|
||||
case Token::BIT_AND: return "bit-and-t";
|
||||
case Token::BIT_OR: return "bit-or-t";
|
||||
case Token::BIT_XOR: return "bit-xor-t";
|
||||
case Token::ROR: return "ror-t";
|
||||
case Token::SHL: return "sal-t";
|
||||
case Token::SAR: return "sar-t";
|
||||
case Token::SHR: return "shr-t";
|
||||
@ -1160,6 +1161,11 @@ LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoRor(HRor* instr) {
|
||||
return DoShift(Token::ROR, instr);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoShr(HShr* instr) {
|
||||
return DoShift(Token::SHR, instr);
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ namespace internal {
|
||||
T(SHL, "<<", 11) \
|
||||
T(SAR, ">>", 11) \
|
||||
T(SHR, ">>>", 11) \
|
||||
T(ROR, "rotate right", 11) /* only used by Crankshaft */ \
|
||||
T(ADD, "+", 12) \
|
||||
T(SUB, "-", 12) \
|
||||
T(MUL, "*", 13) \
|
||||
|
@ -1021,6 +1021,14 @@ class Assembler : public AssemblerBase {
|
||||
shift(dst, imm8, 0x1);
|
||||
}
|
||||
|
||||
void rorl(Register dst, Immediate imm8) {
|
||||
shift_32(dst, imm8, 0x1);
|
||||
}
|
||||
|
||||
void rorl_cl(Register dst) {
|
||||
shift_32(dst, 0x1);
|
||||
}
|
||||
|
||||
// Shifts dst:src left by cl bits, affecting only dst.
|
||||
void shld(Register dst, Register src);
|
||||
|
||||
|
@ -1210,6 +1210,9 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||
ASSERT(ToRegister(right).is(rcx));
|
||||
|
||||
switch (instr->op()) {
|
||||
case Token::ROR:
|
||||
__ rorl_cl(ToRegister(left));
|
||||
break;
|
||||
case Token::SAR:
|
||||
__ sarl_cl(ToRegister(left));
|
||||
break;
|
||||
@ -1231,6 +1234,11 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
||||
int value = ToInteger32(LConstantOperand::cast(right));
|
||||
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
|
||||
switch (instr->op()) {
|
||||
case Token::ROR:
|
||||
if (shift_count != 0) {
|
||||
__ rorl(ToRegister(left), Immediate(shift_count));
|
||||
}
|
||||
break;
|
||||
case Token::SAR:
|
||||
if (shift_count != 0) {
|
||||
__ sarl(ToRegister(left), Immediate(shift_count));
|
||||
|
@ -179,6 +179,7 @@ const char* LArithmeticT::Mnemonic() const {
|
||||
case Token::BIT_AND: return "bit-and-t";
|
||||
case Token::BIT_OR: return "bit-or-t";
|
||||
case Token::BIT_XOR: return "bit-xor-t";
|
||||
case Token::ROR: return "ror-t";
|
||||
case Token::SHL: return "sal-t";
|
||||
case Token::SAR: return "sar-t";
|
||||
case Token::SHR: return "shr-t";
|
||||
@ -1100,6 +1101,11 @@ LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoRor(HRor* instr) {
|
||||
return DoShift(Token::ROR, instr);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoShr(HShr* instr) {
|
||||
return DoShift(Token::SHR, instr);
|
||||
}
|
||||
|
224
test/mjsunit/compiler/rotate.js
Normal file
224
test/mjsunit/compiler/rotate.js
Normal file
@ -0,0 +1,224 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax --expose-gc
|
||||
|
||||
// Test shift operations that can be replaced by rotate operation.
|
||||
|
||||
function SideEffect() {
|
||||
with ({}) { } // not inlinable
|
||||
}
|
||||
|
||||
function Twenty() {
|
||||
SideEffect();
|
||||
return 20;
|
||||
}
|
||||
|
||||
function Twelve() {
|
||||
SideEffect();
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
function ROR(x, sa) {
|
||||
return (x >>> sa) | (x << (32 - sa));
|
||||
}
|
||||
|
||||
function ROR1(x, sa) {
|
||||
return (x >>> sa) | (x << (32 - sa));
|
||||
}
|
||||
|
||||
function ROR2(x, sa) {
|
||||
return (x >>> (32 - sa)) | (x << (sa));
|
||||
}
|
||||
|
||||
function ROR3(x, sa) {
|
||||
return (x << (32 - sa)) | (x >>> sa);
|
||||
}
|
||||
|
||||
function ROR4(x, sa) {
|
||||
return (x << (sa)) | (x >>> (32 - sa));
|
||||
}
|
||||
|
||||
assertEquals(1 << ((2 % 32)), ROR(1, 30));
|
||||
assertEquals(1 << ((2 % 32)), ROR(1, 30));
|
||||
%OptimizeFunctionOnNextCall(ROR);
|
||||
assertEquals(1 << ((2 % 32)), ROR(1, 30));
|
||||
|
||||
assertEquals(0xF0000FFF | 0, ROR1(0x0000FFFF, 4));
|
||||
assertEquals(0xF0000FFF | 0, ROR1(0x0000FFFF, 4));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(0xF0000FFF | 0, ROR1(0x0000FFFF, 4));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR1(0x0000FFFF, 20));
|
||||
assertEquals(0x0FFFF000 | 0, ROR1(0x0000FFFF, 20));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(0x0FFFF000 | 0, ROR1(0x0000FFFF, 20));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR1(0x0000FFFF, Twenty()));
|
||||
assertEquals(0x0FFFF000 | 0, ROR1(0x0000FFFF, Twenty()));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(0x0FFFF000 | 0, ROR1(0x0000FFFF, Twenty()));
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(0xFFFFFFFF | 0, ROR1(0xFFFFFFFF, i));
|
||||
assertEquals(0xFFFFFFFF | 0, ROR1(0xFFFFFFFF, i));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(0xFFFFFFFF | 0, ROR1(0xFFFFFFFF, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(-1, ROR1(-1, i));
|
||||
assertEquals(-1, ROR1(-1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(-1, ROR1(-1, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(1 << (32 - (i % 32)), ROR1(1, i));
|
||||
assertEquals(1 << (32 - (i % 32)), ROR1(1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(1 << (32 - (i % 32)), ROR1(1, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(1 << (32 - (i % 32)), ROR1(1.4, i));
|
||||
assertEquals(1 << (32 - (i % 32)), ROR1(1.4, i));
|
||||
%OptimizeFunctionOnNextCall(ROR1);
|
||||
assertEquals(1 << (32 - (i % 32)), ROR1(1.4, i));
|
||||
}
|
||||
|
||||
|
||||
|
||||
assertEquals(0xF0000FFF | 0, ROR2(0x0000FFFF, 28));
|
||||
assertEquals(0xF0000FFF | 0, ROR2(0x0000FFFF, 28));
|
||||
%OptimizeFunctionOnNextCall(ROR2);
|
||||
assertEquals(0xF0000FFF | 0, ROR2(0x0000FFFF, 28));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR2(0x0000FFFF, 12));
|
||||
assertEquals(0x0FFFF000 | 0, ROR2(0x0000FFFF, 12));
|
||||
%OptimizeFunctionOnNextCall(ROR2);
|
||||
assertEquals(0x0FFFF000 | 0, ROR2(0x0000FFFF, 12));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR2(0x0000FFFF, Twelve()));
|
||||
assertEquals(0x0FFFF000 | 0, ROR2(0x0000FFFF, Twelve()));
|
||||
%OptimizeFunctionOnNextCall(ROR2);
|
||||
assertEquals(0x0FFFF000 | 0, ROR2(0x0000FFFF, Twelve()));
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(0xFFFFFFFF | 0, ROR2(0xFFFFFFFF, i));
|
||||
assertEquals(0xFFFFFFFF | 0, ROR2(0xFFFFFFFF, i));
|
||||
%OptimizeFunctionOnNextCall(ROR2);
|
||||
assertEquals(0xFFFFFFFF | 0, ROR2(0xFFFFFFFF, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(-1, ROR2(-1, i));
|
||||
assertEquals(-1, ROR2(-1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR2);
|
||||
assertEquals(-1, ROR2(-1, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(1 << ((i % 32)), ROR2(1, i));
|
||||
assertEquals(1 << ((i % 32)), ROR2(1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR2);
|
||||
assertEquals(1 << ((i % 32)), ROR2(1, i));
|
||||
}
|
||||
|
||||
assertEquals(0xF0000FFF | 0, ROR3(0x0000FFFF, 4));
|
||||
assertEquals(0xF0000FFF | 0, ROR3(0x0000FFFF, 4));
|
||||
%OptimizeFunctionOnNextCall(ROR3);
|
||||
assertEquals(0xF0000FFF | 0, ROR3(0x0000FFFF, 4));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR3(0x0000FFFF, 20));
|
||||
assertEquals(0x0FFFF000 | 0, ROR3(0x0000FFFF, 20));
|
||||
%OptimizeFunctionOnNextCall(ROR3);
|
||||
assertEquals(0x0FFFF000 | 0, ROR3(0x0000FFFF, 20));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR3(0x0000FFFF, Twenty()));
|
||||
assertEquals(0x0FFFF000 | 0, ROR3(0x0000FFFF, Twenty()));
|
||||
%OptimizeFunctionOnNextCall(ROR3);
|
||||
assertEquals(0x0FFFF000 | 0, ROR3(0x0000FFFF, Twenty()));
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(0xFFFFFFFF | 0, ROR3(0xFFFFFFFF, i));
|
||||
assertEquals(0xFFFFFFFF | 0, ROR3(0xFFFFFFFF, i));
|
||||
%OptimizeFunctionOnNextCall(ROR3);
|
||||
assertEquals(0xFFFFFFFF | 0, ROR3(0xFFFFFFFF, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(-1, ROR3(-1, i));
|
||||
assertEquals(-1, ROR3(-1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR3);
|
||||
assertEquals(-1, ROR3(-1, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(1 << (32 - (i % 32)), ROR3(1, i));
|
||||
assertEquals(1 << (32 - (i % 32)), ROR3(1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR3);
|
||||
assertEquals(1 << (32 - (i % 32)), ROR3(1, i));
|
||||
}
|
||||
|
||||
assertEquals(0xF0000FFF | 0, ROR4(0x0000FFFF, 28));
|
||||
assertEquals(0xF0000FFF | 0, ROR4(0x0000FFFF, 28));
|
||||
%OptimizeFunctionOnNextCall(ROR4);
|
||||
assertEquals(0xF0000FFF | 0, ROR4(0x0000FFFF, 28));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR4(0x0000FFFF, 12));
|
||||
assertEquals(0x0FFFF000 | 0, ROR4(0x0000FFFF, 12));
|
||||
%OptimizeFunctionOnNextCall(ROR4);
|
||||
assertEquals(0x0FFFF000 | 0, ROR4(0x0000FFFF, 12));
|
||||
|
||||
assertEquals(0x0FFFF000 | 0, ROR4(0x0000FFFF, Twelve()));
|
||||
assertEquals(0x0FFFF000 | 0, ROR4(0x0000FFFF, Twelve()));
|
||||
%OptimizeFunctionOnNextCall(ROR4);
|
||||
assertEquals(0x0FFFF000 | 0, ROR4(0x0000FFFF, Twelve()));
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(0xFFFFFFFF | 0, ROR4(0xFFFFFFFF, i));
|
||||
assertEquals(0xFFFFFFFF | 0, ROR4(0xFFFFFFFF, i));
|
||||
%OptimizeFunctionOnNextCall(ROR4);
|
||||
assertEquals(0xFFFFFFFF | 0, ROR4(0xFFFFFFFF, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(-1, ROR4(-1, i));
|
||||
assertEquals(-1, ROR4(-1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR4);
|
||||
assertEquals(-1, ROR4(-1, i));
|
||||
}
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
assertEquals(1 << ((i % 32)), ROR4(1, i));
|
||||
assertEquals(1 << ((i % 32)), ROR4(1, i));
|
||||
%OptimizeFunctionOnNextCall(ROR4);
|
||||
assertEquals(1 << ((i % 32)), ROR4(1, i));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user