diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 3b94c56487694..b2dbab3d911bc 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -122,10 +122,12 @@ def visit_goto(self, op: Goto) -> None: def visit_branch(self, op: Branch) -> None: true, false = op.true, op.false negated = op.negated + negated_rare = False if true is self.next_block and op.traceback_entry is None: # Switch true/false since it avoids an else block. true, false = false, true negated = not negated + negated_rare = True neg = '!' if negated else '' cond = '' @@ -150,7 +152,10 @@ def visit_branch(self, op: Branch) -> None: # For error checks, tell the compiler the branch is unlikely if op.traceback_entry is not None or op.rare: - cond = 'unlikely({})'.format(cond) + if not negated_rare: + cond = 'unlikely({})'.format(cond) + else: + cond = 'likely({})'.format(cond) if false is self.next_block: if op.traceback_entry is None: diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index a3f55a7facf2f..60c62d2b4b4c5 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -187,6 +187,29 @@ def test_branch_is_error_next_block(self) -> None: """if (cpy_r_b == 2) goto CPyL9;""", next_block=next_block) + def test_branch_rare(self) -> None: + self.assert_emit(Branch(self.b, BasicBlock(8), BasicBlock(9), Branch.BOOL, rare=True), + """if (unlikely(cpy_r_b)) { + goto CPyL8; + } else + goto CPyL9; + """) + next_block = BasicBlock(9) + self.assert_emit(Branch(self.b, BasicBlock(8), next_block, Branch.BOOL, rare=True), + """if (unlikely(cpy_r_b)) goto CPyL8;""", + next_block=next_block) + next_block = BasicBlock(8) + b = Branch(self.b, next_block, BasicBlock(9), Branch.BOOL, rare=True) + self.assert_emit(b, + """if (likely(!cpy_r_b)) goto CPyL9;""", + next_block=next_block) + next_block = BasicBlock(8) + b = Branch(self.b, next_block, BasicBlock(9), Branch.BOOL, rare=True) + b.negated = True + self.assert_emit(b, + """if (likely(cpy_r_b)) goto CPyL9;""", + next_block=next_block) + def test_call(self) -> None: decl = FuncDecl('myfn', None, 'mod', FuncSignature([RuntimeArg('m', int_rprimitive)], int_rprimitive))