Skip to content

Commit

Permalink
JIT: Use ucvtf for unsigned right shift
Browse files Browse the repository at this point in the history
Summary:
Unsigned right shift is supposed to convert back from an unsigned
32-bit integer, not a 2s complement int.

Reviewed By: lavenzg

Differential Revision: D68923851

fbshipit-source-id: cffe3746c850d7cb603a3670ea435ff564c84345
  • Loading branch information
avp authored and facebook-github-bot committed Jan 31, 2025
1 parent 3b43c57 commit fa8a149
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 20 deletions.
6 changes: 5 additions & 1 deletion lib/VM/JIT/arm64/JitEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5192,6 +5192,7 @@ void Emitter::bitBinOp(
FR frRes,
FR frLeft,
FR frRight,
bool unsignedRes,
const char *name,
SHLegacyValue (*slowCall)(
SHRuntime *shr,
Expand Down Expand Up @@ -5253,7 +5254,10 @@ void Emitter::bitBinOp(

// Invoke the fast path, and move the result back as a 32 bit integer.
fast(a, hwTempLGpX.a64GpX(), hwTempLGpX.a64GpX(), hwTempRGpX.a64GpX());
a.scvtf(hwRes.a64VecD(), hwTempLGpX.a64GpX().w());
if (unsignedRes)
a.ucvtf(hwRes.a64VecD(), hwTempLGpX.a64GpX().w());
else
a.scvtf(hwRes.a64VecD(), hwTempLGpX.a64GpX().w());

a.bind(contLab);

Expand Down
42 changes: 23 additions & 19 deletions lib/VM/JIT/arm64/JitEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -492,35 +492,38 @@ class Emitter {
DECL_BINOP(divN, true, "divN", _sh_ljs_div_rjs, { as.fdiv(res, dl, dr); })
#undef DECL_BINOP

#define DECL_BIT_BINOP(methodName, commentStr, slowCall, a64body) \
void methodName(FR rRes, FR rLeft, FR rRight) { \
bitBinOp( \
rRes, \
rLeft, \
rRight, \
commentStr, \
slowCall, \
#slowCall, \
[](a64::Assembler & a, \
const a64::GpX &res, \
const a64::GpX &dl, \
const a64::GpX &dr) a64body); \
#define DECL_BIT_BINOP(methodName, unsignedRes, commentStr, slowCall, a64body) \
void methodName(FR rRes, FR rLeft, FR rRight) { \
bitBinOp( \
rRes, \
rLeft, \
rRight, \
unsignedRes, \
commentStr, \
slowCall, \
#slowCall, \
[](a64::Assembler & a, \
const a64::GpX &res, \
const a64::GpX &dl, \
const a64::GpX &dr) a64body); \
}

DECL_BIT_BINOP(bitAnd, "bit_and", _sh_ljs_bit_and_rjs, {
DECL_BIT_BINOP(bitAnd, false, "bit_and", _sh_ljs_bit_and_rjs, {
a.and_(res, dl, dr);
})
DECL_BIT_BINOP(bitOr, "bit_or", _sh_ljs_bit_or_rjs, { a.orr(res, dl, dr); })
DECL_BIT_BINOP(bitXor, "bit_xor", _sh_ljs_bit_xor_rjs, {
DECL_BIT_BINOP(bitOr, false, "bit_or", _sh_ljs_bit_or_rjs, {
a.orr(res, dl, dr);
})
DECL_BIT_BINOP(bitXor, false, "bit_xor", _sh_ljs_bit_xor_rjs, {
a.eor(res, dl, dr);
})
DECL_BIT_BINOP(lShift, "lshift", _sh_ljs_left_shift_rjs, {
DECL_BIT_BINOP(lShift, false, "lshift", _sh_ljs_left_shift_rjs, {
a.lsl(res.w(), dl.w(), dr.w());
})
DECL_BIT_BINOP(rShift, "rshift", _sh_ljs_right_shift_rjs, {
DECL_BIT_BINOP(rShift, false, "rshift", _sh_ljs_right_shift_rjs, {
a.asr(res.w(), dl.w(), dr.w());
})
DECL_BIT_BINOP(urShift, "rshiftu", _sh_ljs_unsigned_right_shift_rjs, {
DECL_BIT_BINOP(urShift, true, "rshiftu", _sh_ljs_unsigned_right_shift_rjs, {
a.lsr(res.w(), dl.w(), dr.w());
})

Expand Down Expand Up @@ -1116,6 +1119,7 @@ class Emitter {
FR frRes,
FR frLeft,
FR frRight,
bool unsignedRes,
const char *name,
SHLegacyValue (*slowCall)(
SHRuntime *shr,
Expand Down
8 changes: 8 additions & 0 deletions test/jit/binops.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ function addS(b) {

print("addS", addS("B"));
// CHECK-NEXT: addS aBc

function ushr0(a) {
return a >>> 0;
}
print(ushr0(-2000000000));
// CHECK-NEXT: 2294967296
print(ushr0(3000000000));
// CHECK-NEXT: 3000000000

0 comments on commit fa8a149

Please sign in to comment.