From 1b80746f4892efa768b55004018249af85edfe7a Mon Sep 17 00:00:00 2001 From: Michael Birtwell Date: Tue, 22 Feb 2022 16:49:11 +0000 Subject: [PATCH] Remove `outer_final` We don't need to know whether there's a outer finally block that's already implicit in the current break and continue target. Signed-off-by: Michael Birtwell --- .../compiler/transforms/artiq_ir_generator.py | 24 +---------- .../try_finally_while_try_finally_break.py | 42 +++++++++++++++++++ .../try_loop/try_finally_while_try_reraise.py | 42 +++++++++++++++++++ .../try_loop/try_finally_while_try_return.py | 29 +++++++++++++ 4 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 artiq/test/lit/try_loop/try_finally_while_try_finally_break.py create mode 100644 artiq/test/lit/try_loop/try_finally_while_try_reraise.py create mode 100644 artiq/test/lit/try_loop/try_finally_while_try_return.py diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index 8b9355894..4a3d9fbbc 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -113,7 +113,6 @@ class ARTIQIRGenerator(algorithm.Visitor): self.return_target = None self.unwind_target = None self.catch_clauses = [] - self.outer_final = None self.final_branch = None self.function_map = dict() self.variable_map = dict() @@ -468,7 +467,6 @@ class ARTIQIRGenerator(algorithm.Visitor): self.append(ir.BranchIf(cond, if_true, tail), block=head) def visit_While(self, node): - old_outer_final, self.outer_final = self.outer_final, None try: head = self.add_block("while.head") self.append(ir.Branch(head)) @@ -488,7 +486,6 @@ class ARTIQIRGenerator(algorithm.Visitor): finally: self.break_target = old_break self.continue_target = old_continue - self.outer_final = old_outer_final if any(node.orelse): else_tail = self.add_block("while.else") @@ -563,7 +560,6 @@ class ARTIQIRGenerator(algorithm.Visitor): assert False def visit_ForT(self, node): - old_outer_final, self.outer_final = self.outer_final, None try: iterable = self.visit(node.iter) length = self.iterable_len(iterable) @@ -601,7 +597,6 @@ class ARTIQIRGenerator(algorithm.Visitor): finally: self.break_target = old_break self.continue_target = old_continue - self.outer_final = old_outer_final if any(node.orelse): else_tail = self.add_block("for.else") @@ -710,9 +705,7 @@ class ARTIQIRGenerator(algorithm.Visitor): value = return_action.append(ir.GetLocal(self.current_private_env, "$return")) return_action.append(ir.Return(value)) final_branch(return_action, return_proxy) - - old_outer_final, self.outer_final = self.outer_final, final_branch - elif self.outer_final is None: + else: landingpad.has_cleanup = False # we should propagate the clauses to nested try catch blocks @@ -777,7 +770,7 @@ class ARTIQIRGenerator(algorithm.Visitor): self.continue_target = old_continue self.return_target = old_return - if any(node.finalbody) or self.outer_final is not None: + if any(node.finalbody): # create new unwind target for cleanup final_dispatcher = self.add_block("try.final.dispatch") final_landingpad = ir.LandingPad(cleanup) @@ -790,16 +783,6 @@ class ARTIQIRGenerator(algorithm.Visitor): # if we have a while:try/finally continue must execute finally # before continuing the while redirect = final_branch - elif self.outer_final is not None: - # If we have while:try/finally:try then we need to execute that finally - # before the continuing the while - # If we have try/finally:while:try then we should just continue the - # while without having to execute the finally until later - # If we have try/finally:while:try/finally:try we should execute - # one but not the other - # This is achieved by reseting self.outer_final in while and for - # loops - redirect = self.outer_final else: redirect = lambda dest, proxy: proxy.append(ir.Branch(dest)) @@ -860,7 +843,6 @@ class ARTIQIRGenerator(algorithm.Visitor): if any(node.finalbody): # Finalize and continue after try statement. - self.outer_final = old_outer_final self.unwind_target = old_unwind # Exception path finalizer_reraise = self.add_block("finally.resume") @@ -910,8 +892,6 @@ class ARTIQIRGenerator(algorithm.Visitor): block.append(ir.SetLocal(final_state, "$cont", tail)) block.append(ir.Branch(finalizer)) else: - if self.outer_final is not None: - self.unwind_target = old_unwind self.current_block = tail = self.add_block("try.tail") if not body.is_terminated(): body.append(ir.Branch(tail)) diff --git a/artiq/test/lit/try_loop/try_finally_while_try_finally_break.py b/artiq/test/lit/try_loop/try_finally_while_try_finally_break.py new file mode 100644 index 000000000..c66d88ceb --- /dev/null +++ b/artiq/test/lit/try_loop/try_finally_while_try_finally_break.py @@ -0,0 +1,42 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def run(): + loop = 0 + print("start") + try: + while True: + print("loop") + try: + if loop == 0: + loop += 1 + continue + func() + break + except RuntimeError: + print("except") + return False + finally: + print("finally2") + print("after-while") + finally: + print("finally1") + print("exit") + return True + + +def func(): + print("func") + +# CHECK-L: start +# CHECK-NEXT-L: loop +# CHECK-NEXT-L: finally2 +# CHECK-NEXT-L: loop +# CHECK-NEXT-L: func +# CHECK-NEXT-L: finally2 +# CHECK-NEXT-L: after-while +# CHECK-NEXT-L: finally1 +# CHECK-NEXT-L: exit + +run() diff --git a/artiq/test/lit/try_loop/try_finally_while_try_reraise.py b/artiq/test/lit/try_loop/try_finally_while_try_reraise.py new file mode 100644 index 000000000..f7c6db84f --- /dev/null +++ b/artiq/test/lit/try_loop/try_finally_while_try_reraise.py @@ -0,0 +1,42 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def run(): + print("start") + try: + try: + while True: + print("loop") + try: + print("try") + func() + print("unreachable") + return True + except RuntimeError: + print("except1") + raise + print("unreachable") + finally: + print("finally1") + print("unreachable") + return False + except RuntimeError: + print("except2") + raise + finally: + print("finally2") + return True + + +def func(): + raise RuntimeError("Test") + +# CHECK-L: start +# CHECK-NEXT-L: loop +# CHECK-NEXT-L: try +# CHECK-NEXT-L: except1 +# CHECK-NEXT-L: finally1 +# CHECK-NEXT-L: except2 +# CHECK-NEXT-L: finally2 +run() diff --git a/artiq/test/lit/try_loop/try_finally_while_try_return.py b/artiq/test/lit/try_loop/try_finally_while_try_return.py new file mode 100644 index 000000000..92a547f02 --- /dev/null +++ b/artiq/test/lit/try_loop/try_finally_while_try_return.py @@ -0,0 +1,29 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def run(): + try: + while True: + try: + print("try") + func() + return True + except RuntimeError: + print("except") + return False + print("unreachable") + finally: + print("finally") + print("unreachable") + return False + + +def func(): + pass + +# CHECK-L: try +# CHECK-NOT-L: except +# CHECK-NOT-L: unreachable +# CHECK-L: finally +run()