@@ -215,6 +215,7 @@ bool isSupportedOpcode(int opcode) {
215215 case STORE_SLICE :
216216 case STORE_SUBSCR :
217217 case SWAP :
218+ case TO_BOOL :
218219 case TP_ALLOC :
219220 case UNARY_INVERT :
220221 case UNARY_NEGATIVE :
@@ -876,6 +877,10 @@ void HIRBuilder::translate(
876877 break ;
877878 }
878879 case UNARY_NOT :
880+ #if PY_VERSION_HEX >= 0x030E0000
881+ emitUnaryNot (tc);
882+ break ;
883+ #endif
879884 case UNARY_NEGATIVE :
880885 case UNARY_POSITIVE :
881886 case UNARY_INVERT : {
@@ -958,6 +963,10 @@ void HIRBuilder::translate(
958963 emitCompareOp (tc, bc_instr);
959964 break ;
960965 }
966+ case TO_BOOL : {
967+ emitToBool (tc);
968+ break ;
969+ }
961970 case COPY_DICT_WITHOUT_KEYS : {
962971 emitCopyDictWithoutKeys (tc);
963972 break ;
@@ -2106,6 +2115,34 @@ static inline UnaryOpKind get_unary_op_kind(
21062115 }
21072116}
21082117
2118+ void HIRBuilder::emitUnaryNot (TranslationContext& tc) {
2119+ Register* operand = tc.frame .stack .pop ();
2120+ Register* is_false = temps_.AllocateNonStack ();
2121+ Register* const_false = temps_.AllocateNonStack ();
2122+ tc.emit <LoadConst>(const_false, Type::fromObject (Py_False));
2123+ tc.emit <PrimitiveCompare>(
2124+ is_false, PrimitiveCompareOp::kEqual , const_false, operand);
2125+
2126+ BasicBlock* is_true_block = tc.block ->cfg ->AllocateBlock ();
2127+ BasicBlock* is_false_block = tc.block ->cfg ->AllocateBlock ();
2128+ BasicBlock* done_block = tc.block ->cfg ->AllocateBlock ();
2129+
2130+ tc.emit <CondBranch>(is_false, is_false_block, is_true_block);
2131+
2132+ Register* result = temps_.AllocateStack ();
2133+
2134+ tc.block = is_true_block;
2135+ tc.emit <LoadConst>(result, Type::fromObject (Py_False));
2136+ tc.emit <Branch>(done_block);
2137+
2138+ tc.block = is_false_block;
2139+ tc.emit <LoadConst>(result, Type::fromObject (Py_True));
2140+ tc.emit <Branch>(done_block);
2141+
2142+ tc.block = done_block;
2143+ tc.frame .stack .push (result);
2144+ }
2145+
21092146void HIRBuilder::emitUnaryOp (
21102147 TranslationContext& tc,
21112148 const jit::BytecodeInstruction& bc_instr) {
@@ -2611,6 +2648,34 @@ void HIRBuilder::emitCompareOp(
26112648
26122649 tc.emit <Compare>(result, op, left, right, tc.frame );
26132650 stack.push (result);
2651+ if (PY_VERSION_HEX >= 0x030E0000 && bc_instr.oparg () & 0x10 ) {
2652+ emitToBool (tc);
2653+ }
2654+ }
2655+
2656+ void HIRBuilder::emitToBool (TranslationContext& tc) {
2657+ Register* operand = tc.frame .stack .pop ();
2658+ Register* truthy_result = temps_.AllocateStack ();
2659+ tc.emit <IsTruthy>(truthy_result, operand, tc.frame );
2660+
2661+ BasicBlock* true_block = tc.block ->cfg ->AllocateBlock ();
2662+ BasicBlock* false_block = tc.block ->cfg ->AllocateBlock ();
2663+ BasicBlock* done_block = tc.block ->cfg ->AllocateBlock ();
2664+
2665+ tc.emit <CondBranch>(truthy_result, true_block, false_block);
2666+
2667+ Register* coerced_result = temps_.AllocateStack ();
2668+
2669+ tc.block = true_block;
2670+ tc.emit <LoadConst>(coerced_result, Type::fromObject (Py_True));
2671+ tc.emit <Branch>(done_block);
2672+
2673+ tc.block = false_block;
2674+ tc.emit <LoadConst>(coerced_result, Type::fromObject (Py_False));
2675+ tc.emit <Branch>(done_block);
2676+
2677+ tc.block = done_block;
2678+ tc.frame .stack .push (coerced_result);
26142679}
26152680
26162681void HIRBuilder::emitCopyDictWithoutKeys (TranslationContext& tc) {
@@ -3688,9 +3753,18 @@ void HIRBuilder::emitPopJumpIf(
36883753
36893754 if (bc_instr.opcode () == POP_JUMP_IF_FALSE ||
36903755 bc_instr.opcode () == POP_JUMP_IF_TRUE ) {
3691- Register* tval = temps_.AllocateNonStack ();
3692- tc.emit <IsTruthy>(tval, var, tc.frame );
3693- tc.emit <CondBranch>(tval, true_block, false_block);
3756+ Register* is_true = temps_.AllocateNonStack ();
3757+ // In 3.14+ coercion to exactly Py_True or Py_False is performed by earlier
3758+ // instructions. See GH-106008.
3759+ if constexpr (PY_VERSION_HEX >= 0x030E0000 ) {
3760+ Register* const_true = temps_.AllocateNonStack ();
3761+ tc.emit <LoadConst>(const_true, Type::fromObject (Py_True));
3762+ tc.emit <PrimitiveCompare>(
3763+ is_true, PrimitiveCompareOp::kEqual , var, const_true);
3764+ } else {
3765+ tc.emit <IsTruthy>(is_true, var, tc.frame );
3766+ }
3767+ tc.emit <CondBranch>(is_true, true_block, false_block);
36943768 } else {
36953769 tc.emit <CondBranch>(var, true_block, false_block);
36963770 }
0 commit comments