compiler: generate appropriate landingpad IR

When used together with modified personality function, we got ~20%
performance improvement in exception unwinding with zynq.
This commit is contained in:
pca006132 2022-01-06 13:36:19 +08:00 committed by Sébastien Bourdeauducq
parent 5e1847e7c1
commit 9f90088fa6
3 changed files with 32 additions and 14 deletions

View File

@ -1347,6 +1347,7 @@ class LandingPad(Terminator):
def __init__(self, cleanup, name=""): def __init__(self, cleanup, name=""):
super().__init__([cleanup], builtins.TException(), name) super().__init__([cleanup], builtins.TException(), name)
self.types = [] self.types = []
self.has_cleanup = True
def copy(self, mapper): def copy(self, mapper):
self_copy = super().copy(mapper) self_copy = super().copy(mapper)

View File

@ -718,6 +718,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
cleanup = self.add_block('handler.cleanup') cleanup = self.add_block('handler.cleanup')
landingpad = dispatcher.append(ir.LandingPad(cleanup)) landingpad = dispatcher.append(ir.LandingPad(cleanup))
if not any(node.finalbody):
landingpad.has_cleanup = False
handlers = [] handlers = []
for handler_node in node.handlers: for handler_node in node.handlers:

View File

@ -1722,7 +1722,8 @@ class LLVMIRGenerator:
def process_LandingPad(self, insn): def process_LandingPad(self, insn):
# Layout on return from landing pad: {%_Unwind_Exception*, %Exception*} # Layout on return from landing pad: {%_Unwind_Exception*, %Exception*}
lllandingpadty = ll.LiteralStructType([llptr, llptr]) lllandingpadty = ll.LiteralStructType([llptr, llptr])
lllandingpad = self.llbuilder.landingpad(lllandingpadty, cleanup=True) lllandingpad = self.llbuilder.landingpad(lllandingpadty,
cleanup=insn.has_cleanup)
llrawexn = self.llbuilder.extract_value(lllandingpad, 1) llrawexn = self.llbuilder.extract_value(lllandingpad, 1)
llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type)) llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type))
llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)], llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)],
@ -1731,23 +1732,34 @@ class LLVMIRGenerator:
for target, typ in insn.clauses(): for target, typ in insn.clauses():
if typ is None: if typ is None:
exnname = "" # see the comment in ksupport/eh.rs # we use a null pointer here, similar to how cpp does it
# https://llvm.org/docs/ExceptionHandling.html#try-catch
# > If @ExcType is null, any exception matches, so the
# landingpad should always be entered. This is used for C++
# catch-all blocks (“catch (...)”).
lllandingpad.add_clause(
ll.CatchClause(
ll.Constant(lli32, 0).inttoptr(llptr)
)
)
else: else:
exnname = "{}:{}".format(typ.id, typ.name) exnname = "{}:{}".format(typ.id, typ.name)
llclauseexnname = self.llconst_of_const( llclauseexnname = self.llconst_of_const(
ir.Constant(exnname, builtins.TStr())) ir.Constant(exnname, builtins.TStr()))
llclauseexnnameptr = self.llmodule.globals.get("exn.{}".format(exnname)) llclauseexnnameptr = self.llmodule.globals.get("exn.{}".format(exnname))
if llclauseexnnameptr is None: if llclauseexnnameptr is None:
llclauseexnnameptr = ll.GlobalVariable(self.llmodule, llclauseexnname.type, llclauseexnnameptr = ll.GlobalVariable(self.llmodule, llclauseexnname.type,
name="exn.{}".format(exnname)) name="exn.{}".format(exnname))
llclauseexnnameptr.global_constant = True llclauseexnnameptr.global_constant = True
llclauseexnnameptr.initializer = llclauseexnname llclauseexnnameptr.initializer = llclauseexnname
llclauseexnnameptr.linkage = "private" llclauseexnnameptr.linkage = "private"
llclauseexnnameptr.unnamed_addr = True llclauseexnnameptr.unnamed_addr = True
lllandingpad.add_clause(ll.CatchClause(llclauseexnnameptr)) lllandingpad.add_clause(ll.CatchClause(llclauseexnnameptr))
if typ is None: if typ is None:
# typ is None means that we match all exceptions, so no need to
# compare
self.llbuilder.branch(self.map(target)) self.llbuilder.branch(self.map(target))
else: else:
llexnlen = self.llbuilder.extract_value(llexnname, 1) llexnlen = self.llbuilder.extract_value(llexnname, 1)
@ -1764,6 +1776,9 @@ class LLVMIRGenerator:
self.llbuilder.branch(self.map(target)) self.llbuilder.branch(self.map(target))
if self.llbuilder.basic_block.terminator is None: if self.llbuilder.basic_block.terminator is None:
self.llbuilder.branch(self.map(insn.cleanup())) if insn.has_cleanup:
self.llbuilder.branch(self.map(insn.cleanup()))
else:
self.llbuilder.resume(lllandingpad)
return llexn return llexn