forked from M-Labs/artiq
1
0
Fork 0

LLVMIRGenerator: allocate less.

This commit is contained in:
whitequark 2015-08-10 09:12:34 +03:00
parent b99eae6b3f
commit 22570afbda
1 changed files with 51 additions and 41 deletions

View File

@ -7,6 +7,16 @@ from pythonparser import ast, diagnostic
from llvmlite_artiq import ir as ll from llvmlite_artiq import ir as ll
from .. import types, builtins, ir from .. import types, builtins, ir
llvoid = ll.VoidType()
lli1 = ll.IntType(1)
lli8 = ll.IntType(8)
lli32 = ll.IntType(32)
lldouble = ll.DoubleType()
llptr = ll.IntType(8).as_pointer()
llemptyptr = ll.LiteralStructType( []).as_pointer()
class LLVMIRGenerator: class LLVMIRGenerator:
def __init__(self, engine, module_name, target): def __init__(self, engine, module_name, target):
self.engine = engine self.engine = engine
@ -26,11 +36,11 @@ class LLVMIRGenerator:
return ll.LiteralStructType([self.llty_of_type(eltty) for eltty in typ.elts]) return ll.LiteralStructType([self.llty_of_type(eltty) for eltty in typ.elts])
elif types.is_rpc_function(typ): elif types.is_rpc_function(typ):
if for_return: if for_return:
return ll.VoidType() return llvoid
else: else:
return ll.LiteralStructType([]) return ll.LiteralStructType([])
elif types.is_function(typ): elif types.is_function(typ):
envarg = ll.IntType(8).as_pointer() envarg = llptr
llty = ll.FunctionType(args=[envarg] + llty = ll.FunctionType(args=[envarg] +
[self.llty_of_type(typ.args[arg]) [self.llty_of_type(typ.args[arg])
for arg in typ.args] + for arg in typ.args] +
@ -43,27 +53,27 @@ class LLVMIRGenerator:
return ll.LiteralStructType([envarg, llty.as_pointer()]) return ll.LiteralStructType([envarg, llty.as_pointer()])
elif builtins.is_none(typ): elif builtins.is_none(typ):
if for_return: if for_return:
return ll.VoidType() return llvoid
else: else:
return ll.LiteralStructType([]) return ll.LiteralStructType([])
elif builtins.is_bool(typ): elif builtins.is_bool(typ):
return ll.IntType(1) return lli1
elif builtins.is_int(typ): elif builtins.is_int(typ):
return ll.IntType(builtins.get_int_width(typ)) return ll.IntType(builtins.get_int_width(typ))
elif builtins.is_float(typ): elif builtins.is_float(typ):
return ll.DoubleType() return lldouble
elif builtins.is_str(typ) or ir.is_exn_typeinfo(typ): elif builtins.is_str(typ) or ir.is_exn_typeinfo(typ):
return ll.IntType(8).as_pointer() return llptr
elif builtins.is_list(typ): elif builtins.is_list(typ):
lleltty = self.llty_of_type(builtins.get_iterable_elt(typ)) lleltty = self.llty_of_type(builtins.get_iterable_elt(typ))
return ll.LiteralStructType([ll.IntType(32), lleltty.as_pointer()]) return ll.LiteralStructType([lli32, lleltty.as_pointer()])
elif builtins.is_range(typ): elif builtins.is_range(typ):
lleltty = self.llty_of_type(builtins.get_iterable_elt(typ)) lleltty = self.llty_of_type(builtins.get_iterable_elt(typ))
return ll.LiteralStructType([lleltty, lleltty, lleltty]) return ll.LiteralStructType([lleltty, lleltty, lleltty])
elif ir.is_basic_block(typ): elif ir.is_basic_block(typ):
return ll.IntType(8).as_pointer() return llptr
elif ir.is_option(typ): elif ir.is_option(typ):
return ll.LiteralStructType([ll.IntType(1), self.llty_of_type(typ.params["inner"])]) return ll.LiteralStructType([lli1, self.llty_of_type(typ.params["inner"])])
elif ir.is_environment(typ): elif ir.is_environment(typ):
llty = ll.LiteralStructType([self.llty_of_type(typ.params[name]) llty = ll.LiteralStructType([self.llty_of_type(typ.params[name])
for name in typ.params]) for name in typ.params])
@ -117,14 +127,14 @@ class LLVMIRGenerator:
llconst = self.llmodule.get_global(name) llconst = self.llmodule.get_global(name)
if llconst is None: if llconst is None:
llstrty = ll.ArrayType(ll.IntType(8), len(as_bytes)) llstrty = ll.ArrayType(lli8, len(as_bytes))
llconst = ll.GlobalVariable(self.llmodule, llstrty, name) llconst = ll.GlobalVariable(self.llmodule, llstrty, name)
llconst.global_constant = True llconst.global_constant = True
llconst.initializer = ll.Constant(llstrty, bytearray(as_bytes)) llconst.initializer = ll.Constant(llstrty, bytearray(as_bytes))
llconst.linkage = linkage llconst.linkage = linkage
llconst.unnamed_addr = unnamed_addr llconst.unnamed_addr = unnamed_addr
return llconst.bitcast(ll.IntType(8).as_pointer()) return llconst.bitcast(llptr)
else: else:
assert False assert False
@ -134,36 +144,36 @@ class LLVMIRGenerator:
return llfun return llfun
if name in "llvm.donothing": if name in "llvm.donothing":
llty = ll.FunctionType(ll.VoidType(), []) llty = ll.FunctionType(llvoid, [])
elif name in "llvm.trap": elif name in "llvm.trap":
llty = ll.FunctionType(ll.VoidType(), []) llty = ll.FunctionType(llvoid, [])
elif name == "llvm.floor.f64": elif name == "llvm.floor.f64":
llty = ll.FunctionType(ll.DoubleType(), [ll.DoubleType()]) llty = ll.FunctionType(lldouble, [lldouble])
elif name == "llvm.round.f64": elif name == "llvm.round.f64":
llty = ll.FunctionType(ll.DoubleType(), [ll.DoubleType()]) llty = ll.FunctionType(lldouble, [lldouble])
elif name == "llvm.pow.f64": elif name == "llvm.pow.f64":
llty = ll.FunctionType(ll.DoubleType(), [ll.DoubleType(), ll.DoubleType()]) llty = ll.FunctionType(lldouble, [lldouble, lldouble])
elif name == "llvm.powi.f64": elif name == "llvm.powi.f64":
llty = ll.FunctionType(ll.DoubleType(), [ll.DoubleType(), ll.IntType(32)]) llty = ll.FunctionType(lldouble, [lldouble, lli32])
elif name == "llvm.copysign.f64": elif name == "llvm.copysign.f64":
llty = ll.FunctionType(ll.DoubleType(), [ll.DoubleType(), ll.DoubleType()]) llty = ll.FunctionType(lldouble, [lldouble, lldouble])
elif name == "llvm.stacksave": elif name == "llvm.stacksave":
llty = ll.FunctionType(ll.IntType(8).as_pointer(), []) llty = ll.FunctionType(llptr, [])
elif name == "llvm.stackrestore": elif name == "llvm.stackrestore":
llty = ll.FunctionType(ll.VoidType(), [ll.IntType(8).as_pointer()]) llty = ll.FunctionType(llvoid, [llptr])
elif name == self.target.print_function: elif name == self.target.print_function:
llty = ll.FunctionType(ll.VoidType(), [ll.IntType(8).as_pointer()], var_arg=True) llty = ll.FunctionType(llvoid, [llptr], var_arg=True)
elif name == "__artiq_personality": elif name == "__artiq_personality":
llty = ll.FunctionType(ll.IntType(32), [], var_arg=True) llty = ll.FunctionType(lli32, [], var_arg=True)
elif name == "__artiq_raise": elif name == "__artiq_raise":
llty = ll.FunctionType(ll.VoidType(), [self.llty_of_type(builtins.TException())]) llty = ll.FunctionType(llvoid, [self.llty_of_type(builtins.TException())])
elif name == "__artiq_reraise": elif name == "__artiq_reraise":
llty = ll.FunctionType(ll.VoidType(), []) llty = ll.FunctionType(llvoid, [])
elif name == "send_rpc": elif name == "send_rpc":
llty = ll.FunctionType(ll.VoidType(), [ll.IntType(32), ll.IntType(8).as_pointer()], llty = ll.FunctionType(llvoid, [lli32, llptr],
var_arg=True) var_arg=True)
elif name == "recv_rpc": elif name == "recv_rpc":
llty = ll.FunctionType(ll.IntType(32), [ll.IntType(8).as_pointer()]) llty = ll.FunctionType(lli32, [llptr])
else: else:
assert False assert False
@ -254,7 +264,7 @@ class LLVMIRGenerator:
return llinsn return llinsn
def llindex(self, index): def llindex(self, index):
return ll.Constant(ll.IntType(32), index) return ll.Constant(lli32, index)
def process_Alloc(self, insn): def process_Alloc(self, insn):
if ir.is_environment(insn.type): if ir.is_environment(insn.type):
@ -263,11 +273,11 @@ class LLVMIRGenerator:
elif ir.is_option(insn.type): elif ir.is_option(insn.type):
if len(insn.operands) == 0: # empty if len(insn.operands) == 0: # empty
llvalue = ll.Constant(self.llty_of_type(insn.type), ll.Undefined) llvalue = ll.Constant(self.llty_of_type(insn.type), ll.Undefined)
return self.llbuilder.insert_value(llvalue, ll.Constant(ll.IntType(1), False), 0, return self.llbuilder.insert_value(llvalue, ll.Constant(lli1, False), 0,
name=insn.name) name=insn.name)
elif len(insn.operands) == 1: # full elif len(insn.operands) == 1: # full
llvalue = ll.Constant(self.llty_of_type(insn.type), ll.Undefined) llvalue = ll.Constant(self.llty_of_type(insn.type), ll.Undefined)
llvalue = self.llbuilder.insert_value(llvalue, ll.Constant(ll.IntType(1), True), 0) llvalue = self.llbuilder.insert_value(llvalue, ll.Constant(lli1, True), 0)
return self.llbuilder.insert_value(llvalue, self.map(insn.operands[0]), 1, return self.llbuilder.insert_value(llvalue, self.map(insn.operands[0]), 1,
name=insn.name) name=insn.name)
else: else:
@ -439,8 +449,8 @@ class LLVMIRGenerator:
[self.map(insn.lhs()), self.map(insn.rhs())], [self.map(insn.lhs()), self.map(insn.rhs())],
name=insn.name) name=insn.name)
else: else:
lllhs = self.llbuilder.sitofp(self.map(insn.lhs()), ll.DoubleType()) lllhs = self.llbuilder.sitofp(self.map(insn.lhs()), lldouble)
llrhs = self.llbuilder.trunc(self.map(insn.rhs()), ll.IntType(32)) llrhs = self.llbuilder.trunc(self.map(insn.rhs()), lli32)
llvalue = self.llbuilder.call(self.llbuiltin("llvm.powi.f64"), [lllhs, llrhs]) llvalue = self.llbuilder.call(self.llbuiltin("llvm.powi.f64"), [lllhs, llrhs])
return self.llbuilder.fptosi(llvalue, self.llty_of_type(insn.type), return self.llbuilder.fptosi(llvalue, self.llty_of_type(insn.type),
name=insn.name) name=insn.name)
@ -497,19 +507,19 @@ class LLVMIRGenerator:
elif isinstance(lllhs.type, ll.PointerType): elif isinstance(lllhs.type, ll.PointerType):
return self.llbuilder.icmp_unsigned(op, lllhs, llrhs, return self.llbuilder.icmp_unsigned(op, lllhs, llrhs,
name=insn.name) name=insn.name)
elif isinstance(lllhs.type, (ll.FloatType, ll.DoubleType)): elif isinstance(lllhs.type, ll.DoubleType):
return self.llbuilder.fcmp_ordered(op, lllhs, llrhs, return self.llbuilder.fcmp_ordered(op, lllhs, llrhs,
name=insn.name) name=insn.name)
elif isinstance(lllhs.type, ll.LiteralStructType): elif isinstance(lllhs.type, ll.LiteralStructType):
# Compare aggregates (such as lists or ranges) element-by-element. # Compare aggregates (such as lists or ranges) element-by-element.
llvalue = ll.Constant(ll.IntType(1), True) llvalue = ll.Constant(lli1, True)
for index in range(len(lllhs.type.elements)): for index in range(len(lllhs.type.elements)):
lllhselt = self.llbuilder.extract_value(lllhs, index) lllhselt = self.llbuilder.extract_value(lllhs, index)
llrhselt = self.llbuilder.extract_value(llrhs, index) llrhselt = self.llbuilder.extract_value(llrhs, index)
llresult = self.llbuilder.icmp_unsigned('==', lllhselt, llrhselt) llresult = self.llbuilder.icmp_unsigned('==', lllhselt, llrhselt)
llvalue = self.llbuilder.select(llresult, llvalue, llvalue = self.llbuilder.select(llresult, llvalue,
ll.Constant(ll.IntType(1), False)) ll.Constant(lli1, False))
return self.llbuilder.icmp_unsigned(op, llvalue, ll.Constant(ll.IntType(1), True), return self.llbuilder.icmp_unsigned(op, llvalue, ll.Constant(lli1, True),
name=insn.name) name=insn.name)
else: else:
print(lllhs, llrhs) print(lllhs, llrhs)
@ -567,7 +577,7 @@ class LLVMIRGenerator:
def process_Closure(self, insn): def process_Closure(self, insn):
llvalue = ll.Constant(self.llty_of_type(insn.target_function.type), ll.Undefined) llvalue = ll.Constant(self.llty_of_type(insn.target_function.type), ll.Undefined)
llenv = self.llbuilder.bitcast(self.map(insn.environment()), ll.IntType(8).as_pointer()) llenv = self.llbuilder.bitcast(self.map(insn.environment()), llptr)
llvalue = self.llbuilder.insert_value(llvalue, llenv, 0) llvalue = self.llbuilder.insert_value(llvalue, llenv, 0)
llvalue = self.llbuilder.insert_value(llvalue, self.map(insn.target_function), 1, llvalue = self.llbuilder.insert_value(llvalue, self.map(insn.target_function), 1,
name=insn.name) name=insn.name)
@ -611,7 +621,7 @@ class LLVMIRGenerator:
error_handler(typ) error_handler(typ)
def _build_rpc(self, fun_loc, fun_type, args, llnormalblock, llunwindblock): def _build_rpc(self, fun_loc, fun_type, args, llnormalblock, llunwindblock):
llservice = ll.Constant(ll.IntType(32), fun_type.service) llservice = ll.Constant(lli32, fun_type.service)
tag = b"" tag = b""
@ -676,7 +686,7 @@ class LLVMIRGenerator:
llretty = self.llty_of_type(fun_type.ret) llretty = self.llty_of_type(fun_type.ret)
llslot = self.llbuilder.alloca(llretty) llslot = self.llbuilder.alloca(llretty)
llslotgen = self.llbuilder.bitcast(llslot, ll.IntType(8).as_pointer()) llslotgen = self.llbuilder.bitcast(llslot, llptr)
self.llbuilder.branch(llhead) self.llbuilder.branch(llhead)
self.llbuilder.position_at_end(llhead) self.llbuilder.position_at_end(llhead)
@ -692,7 +702,7 @@ class LLVMIRGenerator:
self.llbuilder.cbranch(lldone, lltail, llalloc) self.llbuilder.cbranch(lldone, lltail, llalloc)
self.llbuilder.position_at_end(llalloc) self.llbuilder.position_at_end(llalloc)
llalloca = self.llbuilder.alloca(ll.IntType(8), llsize) llalloca = self.llbuilder.alloca(lli8, llsize)
llphi.add_incoming(llalloca, llalloc) llphi.add_incoming(llalloca, llalloc)
self.llbuilder.branch(llhead) self.llbuilder.branch(llhead)
@ -783,8 +793,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([ll.IntType(8).as_pointer(), lllandingpadty = ll.LiteralStructType([llptr,
ll.IntType(8).as_pointer()]) llptr])
lllandingpad = self.llbuilder.landingpad(lllandingpadty, lllandingpad = self.llbuilder.landingpad(lllandingpadty,
self.llbuiltin("__artiq_personality"), self.llbuiltin("__artiq_personality"),
cleanup=True) cleanup=True)