@@ -2592,126 +2592,6 @@ LIRGenerator::TranslatedBlock LIRGenerator::translateOneBasicBlock(
25922592 }
25932593 case Opcode::kPrimitiveCompare : {
25942594 auto instr = static_cast <const PrimitiveCompare*>(&i);
2595- // Float comparisons need NaN-correct condition codes, and the choice is
2596- // architecture-specific because comisd (x86-64) and fcmp (ARM64) expose
2597- // different flags for unordered (NaN) operands. Pick the LIR opcode
2598- // (and operand order) so the opcode's standard condition, used both by
2599- // the standalone setcc/cset and by a compare fused into a branch
2600- // through compareToBranchCC, yields Python's result: every ordering
2601- // comparison involving a NaN is false, `NaN == NaN` is False, `Nan !=
2602- // NaN` is True.
2603- if (instr->left ()->type () <= TCDouble) {
2604- Register* lhs = instr->left ();
2605- Register* rhs = instr->right ();
2606- #if defined(CINDER_X86_64)
2607- // comisd sets unsigned-sense flags and reports unordered as CF=1, so
2608- // only the above / above-equal conditions are false for NaN. Express
2609- // every ordering as > / >=, swapping operands for < / <=. == / !=
2610- // have no NaN-correct single-instruction form (comisd folds unordered
2611- // into ZF), so build them from ordering comparisons:
2612- // a == b == (a <= b) && (a >= b); a != b == !(a == b)
2613- // Floats are neither signed nor unsigned, so the signed and unsigned
2614- // PrimitiveCompareOp variants denote the same ordering (Static Python
2615- // `double` emits the unsigned variants; the Python-float path emits
2616- // the natural ones).
2617- switch (instr->op ()) {
2618- case PrimitiveCompareOp::kGreaterThan :
2619- case PrimitiveCompareOp::kGreaterThanUnsigned :
2620- bbb.appendInstr (
2621- instr->output (), Instruction::kGreaterThanUnsigned , lhs, rhs);
2622- break ;
2623- case PrimitiveCompareOp::kGreaterThanEqual :
2624- case PrimitiveCompareOp::kGreaterThanEqualUnsigned :
2625- bbb.appendInstr (
2626- instr->output (),
2627- Instruction::kGreaterThanEqualUnsigned ,
2628- lhs,
2629- rhs);
2630- break ;
2631- case PrimitiveCompareOp::kLessThan : // a < b == b > a
2632- case PrimitiveCompareOp::kLessThanUnsigned :
2633- bbb.appendInstr (
2634- instr->output (), Instruction::kGreaterThanUnsigned , rhs, lhs);
2635- break ;
2636- case PrimitiveCompareOp::kLessThanEqual : // a <= b == b >= a
2637- case PrimitiveCompareOp::kLessThanEqualUnsigned :
2638- bbb.appendInstr (
2639- instr->output (),
2640- Instruction::kGreaterThanEqualUnsigned ,
2641- rhs,
2642- lhs);
2643- break ;
2644- case PrimitiveCompareOp::kEqual :
2645- case PrimitiveCompareOp::kNotEqual : {
2646- Instruction* le = bbb.appendInstr (
2647- OutVReg{Operand::k8bit},
2648- Instruction::kGreaterThanEqualUnsigned ,
2649- rhs,
2650- lhs); // a <= b
2651- Instruction* ge = bbb.appendInstr (
2652- OutVReg{Operand::k8bit},
2653- Instruction::kGreaterThanEqualUnsigned ,
2654- lhs,
2655- rhs); // a >= b
2656- if (instr->op () == PrimitiveCompareOp::kEqual ) {
2657- bbb.appendInstr (instr->output (), Instruction::kAnd , le, ge);
2658- } else {
2659- Instruction* eq = bbb.appendInstr (
2660- OutVReg{Operand::k8bit}, Instruction::kAnd , le, ge);
2661- bbb.appendInstr (
2662- instr->output (),
2663- Instruction::kXor ,
2664- eq,
2665- Imm{1 , DataType::k8bit});
2666- }
2667- break ;
2668- }
2669- default :
2670- JIT_ABORT (
2671- " Not a float comparison {}" , static_cast <int >(instr->op ()));
2672- }
2673- #elif defined(CINDER_AARCH64)
2674- // fcmp leaves Z=0 for unordered operands and sets C=1, V=1. Pick the
2675- // condition that is false for NaN on each ordering: GT/GE for > / >=
2676- // (signed opcodes), LO/LS for < / <= (unsigned opcodes). EQ/NE key
2677- // off Z alone and are already NaN-correct. Floats are neither signed
2678- // nor unsigned, so the signed and unsigned PrimitiveCompareOp
2679- // variants denote the same ordering (Static Python `double` emits the
2680- // unsigned variants; the Python-float path emits the natural ones).
2681- Instruction::Opcode op;
2682- switch (instr->op ()) {
2683- case PrimitiveCompareOp::kEqual :
2684- op = Instruction::kEqual ;
2685- break ;
2686- case PrimitiveCompareOp::kNotEqual :
2687- op = Instruction::kNotEqual ;
2688- break ;
2689- case PrimitiveCompareOp::kGreaterThan :
2690- case PrimitiveCompareOp::kGreaterThanUnsigned :
2691- op = Instruction::kGreaterThanSigned ;
2692- break ;
2693- case PrimitiveCompareOp::kGreaterThanEqual :
2694- case PrimitiveCompareOp::kGreaterThanEqualUnsigned :
2695- op = Instruction::kGreaterThanEqualSigned ;
2696- break ;
2697- case PrimitiveCompareOp::kLessThan :
2698- case PrimitiveCompareOp::kLessThanUnsigned :
2699- op = Instruction::kLessThanUnsigned ;
2700- break ;
2701- case PrimitiveCompareOp::kLessThanEqual :
2702- case PrimitiveCompareOp::kLessThanEqualUnsigned :
2703- op = Instruction::kLessThanEqualUnsigned ;
2704- break ;
2705- default :
2706- JIT_ABORT (
2707- " Not a float comparison {}" , static_cast <int >(instr->op ()));
2708- }
2709- bbb.appendInstr (instr->output (), op, lhs, rhs);
2710- #else
2711- CINDER_UNSUPPORTED
2712- #endif
2713- break ;
2714- }
27152595 Instruction::Opcode op;
27162596 switch (instr->op ()) {
27172597 case PrimitiveCompareOp::kEqual :
@@ -3488,6 +3368,17 @@ LIRGenerator::TranslatedBlock LIRGenerator::translateOneBasicBlock(
34883368 op);
34893369 break ;
34903370 }
3371+ case Opcode::kFloatCompare : {
3372+ auto instr = static_cast <const FloatCompare*>(&i);
3373+
3374+ bbb.appendCallInstruction (
3375+ instr->output (),
3376+ PyFloat_Type.tp_richcompare ,
3377+ instr->left (),
3378+ instr->right (),
3379+ static_cast <int >(instr->op ()));
3380+ break ;
3381+ }
34913382 case Opcode::kLongCompare : {
34923383 auto instr = static_cast <const LongCompare*>(&i);
34933384
0 commit comments