Skip to content

Commit

Permalink
Constant fold LongBinaryOp with known operands
Browse files Browse the repository at this point in the history
Reviewed By: ATalaba

Differential Revision: D35425492

fbshipit-source-id: 4546010
  • Loading branch information
tekknolagi authored and facebook-github-bot committed Apr 18, 2022
1 parent 4e96d32 commit 6ee3e6a
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 69 deletions.
29 changes: 29 additions & 0 deletions Jit/hir/hir.h
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,26 @@ class INSTR_CLASS(
CompareOp op_;
};

// NB: This needs to be in the order that the values appear in the
// BinaryOpKind enum
static const binaryfunc kLongBinaryOpSlotMethods[] = {
PyLong_Type.tp_as_number->nb_add,
PyLong_Type.tp_as_number->nb_and,

PyLong_Type.tp_as_number->nb_floor_divide,
PyLong_Type.tp_as_number->nb_lshift,
0, // unsupported: matrix multiply
PyLong_Type.tp_as_number->nb_remainder,
PyLong_Type.tp_as_number->nb_multiply,
PyLong_Type.tp_as_number->nb_or,
0, // power is ternary and handled specially
PyLong_Type.tp_as_number->nb_rshift,
0, // unsupported: getitem
PyLong_Type.tp_as_number->nb_subtract,
PyLong_Type.tp_as_number->nb_true_divide,
PyLong_Type.tp_as_number->nb_xor,
};

// Perform the operation indicated by op
class INSTR_CLASS(
LongBinaryOp,
Expand All @@ -2243,6 +2263,15 @@ class INSTR_CLASS(
return op_;
}

binaryfunc slotMethod() const {
auto op_kind = static_cast<unsigned long>(op());
JIT_CHECK(
op_kind < ARRAYSIZE(kLongBinaryOpSlotMethods), "unsupported binop");
binaryfunc helper = kLongBinaryOpSlotMethods[op_kind];
JIT_DCHECK(helper != nullptr, "unsupported slot method");
return helper;
}

Register* left() const {
return GetOperand(0);
}
Expand Down
27 changes: 27 additions & 0 deletions Jit/hir/simplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,31 @@ Register* simplifyBinaryOp(Env& env, const BinaryOp* instr) {
return nullptr;
}

Register* simplifyLongBinaryOp(Env& env, const LongBinaryOp* instr) {
Type left_type = instr->left()->type();
Type right_type = instr->right()->type();
if (left_type.hasObjectSpec() && right_type.hasObjectSpec()) {
ThreadedCompileSerialize guard;
PyObject* result;
if (instr->op() == BinaryOpKind::kPower) {
Ref<> none(Py_None);
result =
PyNumber_Power(left_type.objectSpec(), right_type.objectSpec(), none);
} else {
binaryfunc helper = instr->slotMethod();
result = (*helper)(left_type.objectSpec(), right_type.objectSpec());
}
if (result == nullptr) {
PyErr_Clear();
return nullptr;
}
env.emit<UseType>(instr->left(), left_type);
env.emit<UseType>(instr->right(), right_type);
return env.emit<LoadConst>(Type::fromObject(result));
}
return nullptr;
}

Register* simplifyPrimitiveUnbox(Env& env, const PrimitiveUnbox* instr) {
Register* unboxed_value = instr->GetOperand(0);
Type unbox_output_type = instr->GetOutput()->type();
Expand Down Expand Up @@ -589,6 +614,8 @@ Register* simplifyInstr(Env& env, const Instr* instr) {

case Opcode::kBinaryOp:
return simplifyBinaryOp(env, static_cast<const BinaryOp*>(instr));
case Opcode::kLongBinaryOp:
return simplifyLongBinaryOp(env, static_cast<const LongBinaryOp*>(instr));

case Opcode::kPrimitiveUnbox:
return simplifyPrimitiveUnbox(
Expand Down
26 changes: 1 addition & 25 deletions Jit/lir/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1545,31 +1545,7 @@ LIRGenerator::TranslatedBlock LIRGenerator::TranslateOneBasicBlock(
}
case Opcode::kLongBinaryOp: {
auto instr = static_cast<const LongBinaryOp*>(&i);

// NB: This needs to be in the order that the values appear in the
// BinaryOpKind enum
static const uint64_t helpers[] = {
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_add),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_and),
reinterpret_cast<uint64_t>(
PyLong_Type.tp_as_number->nb_floor_divide),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_lshift),
0, // unsupported: matrix multiply
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_remainder),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_multiply),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_or),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_power),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_rshift),
0, // unsupported: getitem
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_subtract),
reinterpret_cast<uint64_t>(
PyLong_Type.tp_as_number->nb_true_divide),
reinterpret_cast<uint64_t>(PyLong_Type.tp_as_number->nb_xor),
};
auto op_kind = static_cast<unsigned long>(instr->op());
JIT_CHECK(op_kind < sizeof(helpers), "unsupported binop");
uint64_t helper = helpers[op_kind];
JIT_CHECK(helper != 0, "unsupported binop");
uint64_t helper = reinterpret_cast<uint64_t>(instr->slotMethod());
if (instr->op() == BinaryOpKind::kPower) {
bbb.AppendCode(
"Call {}, {:#x}, {}, {}, {:#x}",
Expand Down
20 changes: 8 additions & 12 deletions RuntimeTests/hir_tests/inliner_elimination_static_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,10 @@ fun jittestmodule:test {
v14:MortalLongExact[4] = LoadConst<MortalLongExact[4]>
UseType<LongExact> v10
UseType<LongExact> v14
v16:LongExact = LongBinaryOp<Add> v10 v14 {
FrameState {
NextInstrOffset 12
}
}
Return v16
UseType<MortalLongExact[3]> v10
UseType<MortalLongExact[4]> v14
v17:MortalLongExact[7] = LoadConst<MortalLongExact[7]>
Return v17
}
}
---
Expand All @@ -52,25 +50,23 @@ def add(x, y):
return x + y

def test():
return add(3, 4)
return add(3, "x")
---
fun jittestmodule:test {
bb 0 {
v4:MortalLongExact[3] = LoadConst<MortalLongExact[3]>
v5:MortalLongExact[4] = LoadConst<MortalLongExact[4]>
v5:MortalUnicodeExact["x"] = LoadConst<MortalUnicodeExact["x"]>
BeginInlinedFunction<jittestmodule:add> {
NextInstrOffset 10
}
UseType<LongExact> v4
UseType<LongExact> v5
v17:LongExact = LongBinaryOp<Add> v4 v5 {
v15:Object = BinaryOp<Add> v4 v5 {
FrameState {
NextInstrOffset 8
Locals<2> v4 v5
}
}
EndInlinedFunction
Return v17
Return v15
}
}
---
Expand Down
20 changes: 8 additions & 12 deletions RuntimeTests/hir_tests/inliner_elimination_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,10 @@ fun jittestmodule:test {
v20:MortalLongExact[4] = LoadConst<MortalLongExact[4]>
UseType<LongExact> v14
UseType<LongExact> v20
v24:LongExact = LongBinaryOp<Add> v14 v20 {
FrameState {
NextInstrOffset 10
}
}
Return v24
UseType<MortalLongExact[3]> v14
UseType<MortalLongExact[4]> v20
v25:MortalLongExact[7] = LoadConst<MortalLongExact[7]>
Return v25
}
}
---
Expand All @@ -73,7 +71,7 @@ def add(x, y):
return x + y

def test():
return add(3, 4)
return add(3, "x")
---
fun jittestmodule:test {
bb 0 {
Expand All @@ -82,23 +80,21 @@ fun jittestmodule:test {
Descr 'LOAD_GLOBAL: add'
}
v6:MortalLongExact[3] = LoadConst<MortalLongExact[3]>
v7:MortalLongExact[4] = LoadConst<MortalLongExact[4]>
v7:MortalUnicodeExact["x"] = LoadConst<MortalUnicodeExact["x"]>
v19:Object = LoadField<func_code@16, Object, borrowed> v5
v20:MortalCode["add"] = GuardIs<0xdeadbeef> v19 {
}
BeginInlinedFunction<jittestmodule:add> {
NextInstrOffset 8
}
UseType<LongExact> v6
UseType<LongExact> v7
v21:LongExact = LongBinaryOp<Add> v6 v7 {
v17:Object = BinaryOp<Add> v6 v7 {
FrameState {
NextInstrOffset 6
Locals<2> v6 v7
}
}
EndInlinedFunction
Return v21
Return v17
}
}
---
11 changes: 4 additions & 7 deletions RuntimeTests/hir_tests/inliner_static_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,11 @@ fun jittestmodule:test {
}
UseType<LongExact> v4
UseType<LongExact> v5
v19:LongExact = LongBinaryOp<Add> v4 v5 {
FrameState {
NextInstrOffset 8
Locals<2> v4 v5
}
}
UseType<MortalLongExact[1]> v4
UseType<MortalLongExact[2]> v5
v20:MortalLongExact[3] = LoadConst<MortalLongExact[3]>
EndInlinedFunction
Return v19
Return v20
}
}
---
Expand Down
21 changes: 8 additions & 13 deletions RuntimeTests/hir_tests/inliner_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ fun jittestmodule:test {
EndInlinedFunction
UseType<LongExact> v14
UseType<LongExact> v20
v24:LongExact = LongBinaryOp<Add> v14 v20 {
FrameState {
NextInstrOffset 10
}
}
Return v24
UseType<MortalLongExact[3]> v14
UseType<MortalLongExact[4]> v20
v25:MortalLongExact[7] = LoadConst<MortalLongExact[7]>
Return v25
}
}
---
Expand Down Expand Up @@ -154,14 +152,11 @@ fun jittestmodule:test {
}
UseType<LongExact> v6
UseType<LongExact> v7
v21:LongExact = LongBinaryOp<Add> v6 v7 {
FrameState {
NextInstrOffset 6
Locals<2> v6 v7
}
}
UseType<MortalLongExact[2]> v6
UseType<MortalLongExact[3]> v7
v22:MortalLongExact[5] = LoadConst<MortalLongExact[5]>
EndInlinedFunction
Return v21
Return v22
}
}
---
Expand Down
29 changes: 29 additions & 0 deletions RuntimeTests/hir_tests/simplify_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,35 @@ fun test {
}
}
---
BinaryOpWithObjSpecLeftAndRightLongExactTurnsIntoLoadConst
---
# HIR
fun test {
bb 0 {
v1 = LoadArg<0>
v2 = LoadArg<1>
v3 = RefineType<LongExact[2]> v1
v4 = RefineType<LongExact[3]> v2
v5 = BinaryOp<Power> v3 v4
Return v5
}
}
---
fun test {
bb 0 {
v1:Object = LoadArg<0>
v2:Object = LoadArg<1>
v3:MortalLongExact[2] = RefineType<MortalLongExact[2]> v1
v4:MortalLongExact[3] = RefineType<MortalLongExact[3]> v2
UseType<LongExact> v3
UseType<LongExact> v4
UseType<MortalLongExact[2]> v3
UseType<MortalLongExact[3]> v4
v7:MortalLongExact[8] = LoadConst<MortalLongExact[8]>
Return v7
}
}
---
BinaryOpTrueDivideWithLeftAndRightLongExactTurnsIntoLongBinaryOpFloat
---
# HIR
Expand Down

0 comments on commit 6ee3e6a

Please sign in to comment.